yavsc/src/Yavsc/Services/FileSystemAuthManager.cs

133 lines
4.5 KiB
C#
Raw Normal View History

2019-08-04 11:45:00 +02:00
using System;
using System.Linq;
using System.Security.Principal;
using System.Security.Claims;
using Yavsc.Models;
2019-08-14 14:11:27 +01:00
using Microsoft.Extensions.Logging;
2020-10-09 19:35:39 +01:00
using Microsoft.Extensions.OptionsModel;
using System.IO;
using rules;
2020-10-17 11:35:15 +01:00
using Microsoft.Data.Entity;
2019-08-04 11:45:00 +02:00
namespace Yavsc.Services
{
public class FileSystemAuthManager : IFileSystemAuthManager
{
2020-10-17 11:35:15 +01:00
class BelongsToCircle : UserMatch
{
public override bool Match(string userId)
{
return true;
}
}
class OutOfCircle : UserMatch
{
public override bool Match(string userId)
{
return false;
}
}
UserMatch Out = new OutOfCircle();
UserMatch In = new BelongsToCircle();
2020-09-12 01:11:30 +01:00
readonly ApplicationDbContext _dbContext;
readonly ILogger _logger;
2019-08-04 11:45:00 +02:00
2020-10-09 19:35:39 +01:00
readonly SiteSettings SiteSettings;
readonly string aclfileName;
readonly RuleSetParser ruleSetParser;
public FileSystemAuthManager(ApplicationDbContext dbContext, ILoggerFactory loggerFactory,
IOptions<SiteSettings> sitesOptions)
2019-08-04 11:45:00 +02:00
{
_dbContext = dbContext;
2019-08-14 14:11:27 +01:00
_logger = loggerFactory.CreateLogger<FileSystemAuthManager>();
2020-10-09 19:35:39 +01:00
SiteSettings = sitesOptions.Value;
aclfileName = SiteSettings.AccessListFileName;
ruleSetParser = new RuleSetParser(true);
2019-08-04 11:45:00 +02:00
}
public FileAccessRight GetFilePathAccess(ClaimsPrincipal user, string normalizedFullPath)
{
2019-08-14 14:11:27 +01:00
2019-08-04 11:45:00 +02:00
// Assert (normalizedFullPath!=null)
var parts = normalizedFullPath.Split('/');
// below 4 parts, no file name.
2020-10-09 19:35:39 +01:00
if (parts.Length < 4) return FileAccessRight.None;
var fileDir = string.Join("/", parts.Take(parts.Length - 1));
2020-10-17 11:35:15 +01:00
var fileName = parts[parts.Length - 1];
2019-08-14 14:11:27 +01:00
var firstFileNamePart = parts[3];
2020-10-17 11:35:15 +01:00
if (firstFileNamePart == "pub" && aclfileName != fileName)
2020-10-09 19:35:39 +01:00
{
_logger.LogInformation("Serving public file.");
return FileAccessRight.Read;
}
2020-10-17 11:35:15 +01:00
if (user == null) return FileAccessRight.None;
var funame = parts[2];
2020-10-17 11:35:15 +01:00
var cusername = user.GetUserName();
if (funame == cusername)
2020-10-09 19:35:39 +01:00
{
_logger.LogInformation("Serving file to owner.");
return FileAccessRight.Read | FileAccessRight.Write;
}
2020-10-17 11:35:15 +01:00
if (aclfileName == fileName)
return FileAccessRight.None;
_logger.LogInformation($"Access to {normalizedFullPath} for {cusername}");
2020-10-09 19:35:39 +01:00
ruleSetParser.Reset();
2020-10-17 11:35:15 +01:00
var cuserid = user.GetUserId();
var fuserid = _dbContext.Users.Single(u => u.UserName == funame).Id;
var circles = _dbContext.Circle.Include(mb => mb.Members).Where(c => c.OwnerId == fuserid).ToArray();
foreach (var circle in circles)
{
if (circle.Members.Any(m => m.MemberId == cuserid))
ruleSetParser.Definitions.Add(circle.Name, In);
else ruleSetParser.Definitions.Add(circle.Name, Out);
}
// _dbContext.Circle.Select(c => c.OwnerId == )
for (int dirlevel = parts.Length - 1; dirlevel>0; dirlevel--)
{
var aclfi = new FileInfo(Path.Combine(Environment.CurrentDirectory, fileDir, aclfileName));
if (!aclfi.Exists) continue;
ruleSetParser.ParseFile(aclfi.FullName);
}
// TODO default user scoped file access policy
2020-10-09 19:35:39 +01:00
if (ruleSetParser.Rules.Allow(user.GetUserName()))
return FileAccessRight.Read;
2019-08-04 11:45:00 +02:00
2019-08-14 14:11:27 +01:00
var ucl = user.Claims.Where(c => c.Type == YavscClaimTypes.CircleMembership).Select(c => long.Parse(c.Value)).Distinct().ToArray();
2020-10-09 19:35:39 +01:00
2019-08-14 14:11:27 +01:00
var uclString = string.Join(",", ucl);
_logger.LogInformation($"{uclString} ");
foreach (
var cid in ucl
2020-10-09 19:35:39 +01:00
)
{
var ok = _dbContext.CircleAuthorizationToFile.Any(a => a.CircleId == cid && a.FullPath == fileDir);
2019-08-14 14:11:27 +01:00
if (ok) return FileAccessRight.Read;
}
2020-10-09 19:35:39 +01:00
2019-08-04 11:45:00 +02:00
return FileAccessRight.None;
}
public string NormalizePath(string path)
{
throw new NotImplementedException();
}
public void SetAccess(long circleId, string normalizedFullPath, FileAccessRight access)
{
throw new NotImplementedException();
}
}
2020-09-12 01:11:30 +01:00
}