yavsc/src/Yavsc/Services/FileSystemAuthManager.cs

120 lines
3.8 KiB
C#

6 years ago
using System;
using System.Linq;
using System.Security.Principal;
using System.Security.Claims;
using Yavsc.Models;
using Microsoft.Extensions.Logging;
5 years ago
using Microsoft.Extensions.OptionsModel;
using System.IO;
using rules;
using Microsoft.Data.Entity;
using Microsoft.AspNet.FileProviders;
6 years ago
namespace Yavsc.Services
{
public class FileSystemAuthManager : IFileSystemAuthManager
{
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();
readonly ApplicationDbContext _dbContext;
readonly ILogger _logger;
6 years ago
5 years ago
readonly SiteSettings SiteSettings;
readonly string aclfileName;
readonly RuleSetParser ruleSetParser;
public FileSystemAuthManager(ApplicationDbContext dbContext, ILoggerFactory loggerFactory,
IOptions<SiteSettings> sitesOptions)
6 years ago
{
_dbContext = dbContext;
_logger = loggerFactory.CreateLogger<FileSystemAuthManager>();
5 years ago
SiteSettings = sitesOptions.Value;
aclfileName = SiteSettings.AccessListFileName;
ruleSetParser = new RuleSetParser(false);
6 years ago
}
public FileAccessRight GetFilePathAccess(ClaimsPrincipal user, IFileInfo file)
6 years ago
{
var parts = file.PhysicalPath.Split(Path.DirectorySeparatorChar);
var cwd = Environment.CurrentDirectory.Split(Path.DirectorySeparatorChar).Length;
// below 3 parts behind cwd, no file name.
if (parts.Length < cwd + 3) return FileAccessRight.None;
5 years ago
var fileDir = string.Join("/", parts.Take(parts.Length - 1));
var fileName = parts[parts.Length - 1];
var cusername = user.GetUserName();
var funame = parts[cwd+1];
if (funame == cusername)
5 years ago
{
return FileAccessRight.Read | FileAccessRight.Write;
}
if (aclfileName == fileName)
return FileAccessRight.None;
5 years ago
ruleSetParser.Reset();
var cuserid = user.GetUserId();
var fuserid = _dbContext.Users.SingleOrDefault(u => u.UserName == funame).Id;
if (string.IsNullOrEmpty(fuserid)) return FileAccessRight.None;
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);
}
for (int dirlevel = parts.Length - 1; dirlevel > cwd + 1; dirlevel--)
{
fileDir = string.Join(Path.DirectorySeparatorChar.ToString(), parts.Take(dirlevel));
var aclfin = Path.Combine(fileDir, aclfileName);
var aclfi = new FileInfo(aclfin);
if (!aclfi.Exists) continue;
ruleSetParser.ParseFile(aclfi.FullName);
}
5 years ago
if (ruleSetParser.Rules.Allow(cusername))
5 years ago
{
return FileAccessRight.Read;
}
return FileAccessRight.None;
// TODO default user scoped file access policy
5 years ago
6 years ago
}
public string NormalizePath(string path)
{
throw new NotImplementedException();
}
public void SetAccess(long circleId, string normalizedFullPath, FileAccessRight access)
{
throw new NotImplementedException();
}
}
}