feat: windows权限修改。

- windows 上权限是用用户的组实现
- 面向对象带来的一个冗余后果是,当用基类表示时,难以简单的确定它的实际类是什么
- 多态表达了复杂,但没有解决这种复杂性,软件开发的目的是:制造复杂的假象
This commit is contained in:
zerlei 2024-07-30 13:24:47 +08:00
parent c254cb190a
commit fc6c7bf8d2
3 changed files with 124 additions and 161 deletions

View file

@ -133,6 +133,11 @@ public class Dir(string path, List<AFileOrDir>? children = null, NextOpType? nex
bool IsUpdateDirFile = false bool IsUpdateDirFile = false
) )
{ {
///验证 target 文件或者文件夹是否具备相关文件权限。
if (IsUpdateDirFile)
{
diffdir.AccessCheck();
}
if (this.FormatedPath != diffdir.FormatedPath) if (this.FormatedPath != diffdir.FormatedPath)
{ {
throw new ArgumentException("their path is not same"); throw new ArgumentException("their path is not same");
@ -365,7 +370,7 @@ public class Dir(string path, List<AFileOrDir>? children = null, NextOpType? nex
/// <summary> /// <summary>
/// 校验文件夹和文件权限 /// 校验文件夹和文件权限
/// </summary> /// </summary>
public void AccessCheck() private void AccessCheck()
{ {
this.Children.ForEach(e => this.Children.ForEach(e =>
{ {
@ -438,7 +443,9 @@ public class Dir(string path, List<AFileOrDir>? children = null, NextOpType? nex
if (!AccessWrapper.CheckDirAccess(dir.FormatedPath, [DirAcess.Delete])) if (!AccessWrapper.CheckDirAccess(dir.FormatedPath, [DirAcess.Delete]))
{ {
throw new UnauthorizedAccessException($"{dir.FormatedPath} 无权限删除文件夹"); throw new UnauthorizedAccessException($"{dir.FormatedPath} 无权限删除文件夹");
} else { }
else
{
//校验是否拥有子文件或者文件夹的删除权限, //校验是否拥有子文件或者文件夹的删除权限,
dir.AccessCheck(); dir.AccessCheck();
} }

View file

@ -1,4 +1,5 @@
using System.Linq; using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Security.AccessControl; using System.Security.AccessControl;
@ -45,19 +46,55 @@ public class FileDirOpForPack(string srcRootPath, string dstRootPath) : FileDirO
var x = DstRootPath; var x = DstRootPath;
} }
public override void FileCreate(string absolutePath, DateTime mtime) /// <summary>
///
/// </summary>
/// <param name="absolutePath"></param>
/// <param name="mtime"></param>
/// <exception cref="NotImplementedException"></exception>
public override void FileCreate(string srcPath, DateTime mtime)
{ {
throw new NotImplementedException(); var dstPath = srcPath.Replace(SrcRootPath, DstRootPath);
var dstDirPath =
Path.GetDirectoryName(dstPath) ?? throw new NullReferenceException("父路径不存在!");
if (!Directory.Exists(dstDirPath))
{
Directory.CreateDirectory(dstDirPath);
}
System.IO.File.Copy(srcPath, dstPath, true);
} }
public override void DirCreate(Dir dir, bool IsRecursion = true) public override void DirCreate(Dir dir, bool IsRecursion = true)
{ {
throw new NotImplementedException(); var srcPath = dir.FormatedPath;
var dstPath = srcPath.Replace(SrcRootPath, DstRootPath);
var dstDirPath =
Path.GetDirectoryName(dstPath) ?? throw new NullReferenceException("父路径不存在!");
if (!Directory.Exists(dstDirPath))
{
Directory.CreateDirectory(dstDirPath);
}
if (IsRecursion)
{
foreach (var c in dir.Children)
{
if (c is Dir d)
{
this.DirCreate(d, true);
}
else if (c is File f)
{
this.FileCreate(f.FormatedPath, f.MTime);
}
}
}
} }
public override void FileModify(string absolutePath, DateTime mtime) public override void FileModify(string absolutePath, DateTime mtime)
{ {
throw new NotImplementedException(); this.FileCreate(absolutePath, mtime);
} }
public override void FileDel(string absolutePath) public override void FileDel(string absolutePath)
@ -171,11 +208,6 @@ public enum DirAcess
/// </summary> /// </summary>
Write, Write,
/// <summary>
/// 修改权限
/// </summary>
Modify,
/// <summary> /// <summary>
/// 列出文件夹权限 /// 列出文件夹权限
/// </summary> /// </summary>
@ -219,7 +251,6 @@ public class AccessWrapper
[ [
DirAcess.Read, DirAcess.Read,
DirAcess.Write, DirAcess.Write,
DirAcess.Modify,
DirAcess.Delete, DirAcess.Delete,
DirAcess.ListDirectory, DirAcess.ListDirectory,
DirAcess.CreateFiles, DirAcess.CreateFiles,
@ -240,109 +271,22 @@ public class AccessWrapper
InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit; InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit;
var cUser = var cUser =
WindowsIdentity.GetCurrent().User (
?? throw new Exception("GetWindowsIdentity failed. 你需要手动处理发布内容!"); WindowsIdentity.GetCurrent().Groups
FileSystemAccessRule ReadRule = ?? throw new Exception("GetWindowsIdentity failed. 你需要手动处理发布内容!--检查权限!")
new( ).FirstOrDefault() ?? throw new NullReferenceException("can't be null");
cUser, FileSystemAccessRule MdfRule =
FileSystemRights.Read,
inherits,
PropagationFlags.None,
AccessControlType.Allow
);
FileSystemAccessRule WriteRule =
new(
cUser,
FileSystemRights.Write,
inherits,
PropagationFlags.None,
AccessControlType.Allow
);
FileSystemAccessRule ModifyRule =
new( new(
cUser, cUser,
FileSystemRights.Modify, FileSystemRights.Modify,
inherits, inherits,
PropagationFlags.None, PropagationFlags.InheritOnly,
AccessControlType.Allow AccessControlType.Allow
); );
FileSystemAccessRule DeleteRule = if (dirSecurity.ModifyAccessRule(AccessControlModification.Set, MdfRule, out _)) { }
new(
cUser,
FileSystemRights.Delete,
inherits,
PropagationFlags.None,
AccessControlType.Allow
);
FileSystemAccessRule ListDirectoryRule =
new(
cUser,
FileSystemRights.ListDirectory,
inherits,
PropagationFlags.None,
AccessControlType.Allow
);
FileSystemAccessRule CreateFilesRule =
new(
cUser,
FileSystemRights.CreateFiles,
inherits,
PropagationFlags.None,
AccessControlType.Allow
);
FileSystemAccessRule CreateDirsRule =
new(
cUser,
FileSystemRights.CreateDirectories,
inherits,
PropagationFlags.None,
AccessControlType.Allow
);
FileSystemAccessRule DeleteSubdirectoriesAndFilesRule =
new(
cUser,
FileSystemRights.DeleteSubdirectoriesAndFiles,
inherits,
PropagationFlags.None,
AccessControlType.Allow
);
if (
dirSecurity.ModifyAccessRule(AccessControlModification.Add, ReadRule, out _)
&& dirSecurity.ModifyAccessRule(AccessControlModification.Add, WriteRule, out _)
&& dirSecurity.ModifyAccessRule(
AccessControlModification.Add,
ModifyRule,
out _
)
&& dirSecurity.ModifyAccessRule(
AccessControlModification.Add,
ListDirectoryRule,
out _
)
&& dirSecurity.ModifyAccessRule(
AccessControlModification.Add,
CreateFilesRule,
out _
)
&& dirSecurity.ModifyAccessRule(
AccessControlModification.Add,
CreateDirsRule,
out _
)
&& dirSecurity.ModifyAccessRule(
AccessControlModification.Add,
DeleteRule,
out _
)
&& dirSecurity.ModifyAccessRule(
AccessControlModification.Add,
DeleteSubdirectoriesAndFilesRule,
out _
)
) { }
else else
{ {
throw new Exception("AddAccessRule failed. 你需要手动处理发布内容!"); throw new Exception("AddAccessRule failed. 你需要手动处理发布内容!--检查权限!");
} }
//设置访问权限 //设置访问权限
dirInfo.SetAccessControl(dirSecurity); dirInfo.SetAccessControl(dirSecurity);
@ -377,37 +321,19 @@ public class AccessWrapper
FileSecurity fileSecurity = fileInfo.GetAccessControl(); FileSecurity fileSecurity = fileInfo.GetAccessControl();
var cUser = var cUser =
WindowsIdentity.GetCurrent().User (
?? throw new Exception("GetWindowsIdentity failed. 你需要手动处理发布内容!"); WindowsIdentity.GetCurrent().Groups
FileSystemAccessRule ReadRule = ?? throw new NullReferenceException(
new(cUser, FileSystemRights.Read, AccessControlType.Allow); "GetWindowsIdentity failed. 你需要手动处理发布内容!-- 检查权限"
FileSystemAccessRule WriteRule = )
new(cUser, FileSystemRights.Write, AccessControlType.Allow); ).FirstOrDefault() ?? throw new NullReferenceException("can't be null");
FileSystemAccessRule DeleteRule = FileSystemAccessRule MdfRule =
new(cUser, FileSystemRights.Delete, AccessControlType.Allow); new(cUser, FileSystemRights.Modify, AccessControlType.Allow);
FileSystemAccessRule ExecuteRule = if (fileSecurity.ModifyAccessRule(AccessControlModification.Set, MdfRule, out _))
new(cUser, FileSystemRights.ExecuteFile, AccessControlType.Allow); { }
if (
fileSecurity.ModifyAccessRule(AccessControlModification.Add, ReadRule, out _)
&& fileSecurity.ModifyAccessRule(
AccessControlModification.Add,
WriteRule,
out _
)
&& fileSecurity.ModifyAccessRule(
AccessControlModification.Add,
DeleteRule,
out _
)
&& fileSecurity.ModifyAccessRule(
AccessControlModification.Add,
ExecuteRule,
out _
)
) { }
else else
{ {
throw new Exception("AddAccessRule failed. 你需要手动处理发布内容!"); throw new Exception("AddAccessRule failed. 你需要手动处理发布内容!--检查权限");
} }
} }
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
@ -431,50 +357,72 @@ public class AccessWrapper
//获得该文件的访问权限 //获得该文件的访问权限
var dirSecurity = dirInfo.GetAccessControl(); var dirSecurity = dirInfo.GetAccessControl();
var ac = dirSecurity var ac = dirSecurity
.GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount)) .GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier))
.Cast<FileSystemAccessRule>(); .Cast<FileSystemAccessRule>();
#pragma warning disable CA1416 // Validate platform compatibility #pragma warning disable CA1416 // Validate platform compatibility
var it = var it =
from i in ac from i in ac
where i.IdentityReference == WindowsIdentity.GetCurrent().User where
(
WindowsIdentity.GetCurrent().Groups
?? throw new NullReferenceException("未能获取当前用户组!")
).Contains(i.IdentityReference)
select i; select i;
#pragma warning restore CA1416 // Validate platform compatibility #pragma warning restore CA1416 // Validate platform compatibility
List<DirAcess> caccess = []; List<DirAcess> caccess = [];
foreach (var i in it) foreach (var i in it)
{ {
if (i.FileSystemRights == FileSystemRights.FullControl) if (i.FileSystemRights.HasFlag(FileSystemRights.FullControl))
{ {
return true; return true;
} }
else if (i.FileSystemRights == FileSystemRights.Read) if (
i.FileSystemRights.HasFlag(
FileSystemRights.Read
| FileSystemRights.Modify
| FileSystemRights.ReadAndExecute
)
)
{ {
caccess.Add(DirAcess.Read); caccess.Add(DirAcess.Read);
} }
else if (i.FileSystemRights == FileSystemRights.Write) if (i.FileSystemRights.HasFlag(FileSystemRights.Write | FileSystemRights.Modify))
{ {
caccess.Add(DirAcess.Write); caccess.Add(DirAcess.Write);
} }
else if (i.FileSystemRights == FileSystemRights.Delete) if (i.FileSystemRights.HasFlag(FileSystemRights.Modify | FileSystemRights.Delete))
{ {
caccess.Add(DirAcess.Delete); caccess.Add(DirAcess.Delete);
} }
else if (i.FileSystemRights == FileSystemRights.Modify) if (
{ i.FileSystemRights.HasFlag(
caccess.Add(DirAcess.Modify); FileSystemRights.ListDirectory | FileSystemRights.Modify
} )
else if (i.FileSystemRights == FileSystemRights.ListDirectory) )
{ {
caccess.Add(DirAcess.ListDirectory); caccess.Add(DirAcess.ListDirectory);
} }
else if (i.FileSystemRights == FileSystemRights.CreateFiles) if (
i.FileSystemRights.HasFlag(
FileSystemRights.CreateFiles | FileSystemRights.Modify
)
)
{ {
caccess.Add(DirAcess.CreateFiles); caccess.Add(DirAcess.CreateFiles);
} }
else if (i.FileSystemRights == FileSystemRights.CreateDirectories) if (
i.FileSystemRights.HasFlag(
FileSystemRights.CreateDirectories | FileSystemRights.Modify
)
)
{ {
caccess.Add(DirAcess.CreateDirectories); caccess.Add(DirAcess.CreateDirectories);
} }
else if (i.FileSystemRights == FileSystemRights.DeleteSubdirectoriesAndFiles) if (
i.FileSystemRights.HasFlag(
FileSystemRights.DeleteSubdirectoriesAndFiles | FileSystemRights.Modify
)
)
{ {
caccess.Add(DirAcess.DeleteSubdirectoriesAndFiles); caccess.Add(DirAcess.DeleteSubdirectoriesAndFiles);
} }
@ -508,37 +456,45 @@ public class AccessWrapper
FileInfo fileInfo = new(absolutePath); FileInfo fileInfo = new(absolutePath);
//获得该文件的访问权限 //获得该文件的访问权限
FileSecurity fileSecurity = fileInfo.GetAccessControl(); FileSecurity fileSecurity = fileInfo.GetAccessControl();
var ac = fileSecurity var ac = fileSecurity
.GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount)) .GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier))
.Cast<FileSystemAccessRule>(); .Cast<FileSystemAccessRule>();
#pragma warning disable CA1416 // Validate platform compatibility #pragma warning disable CA1416 // 验证平台兼容性
var it = var it =
from i in ac from i in ac
where i.IdentityReference == WindowsIdentity.GetCurrent().User where
(
WindowsIdentity.GetCurrent().Groups
?? throw new NullReferenceException("未能获取当前用户组!")
).Contains(i.IdentityReference)
select i; select i;
#pragma warning restore CA1416 // Validate platform compatibility #pragma warning restore CA1416 // 验证平台兼容性
List<FileAccess> caccess = []; List<FileAccess> caccess = [];
foreach (var i in it) foreach (var i in it)
{ {
if (i.FileSystemRights == FileSystemRights.FullControl) if (i.FileSystemRights.HasFlag(FileSystemRights.FullControl))
{ {
return true; return true;
} }
else if (i.FileSystemRights == FileSystemRights.Read) if (i.FileSystemRights.HasFlag(FileSystemRights.Read | FileSystemRights.Modify))
{ {
caccess.Add(FileAccess.Read); caccess.Add(FileAccess.Read);
} }
else if (i.FileSystemRights == FileSystemRights.Write) if (i.FileSystemRights.HasFlag(FileSystemRights.Write | FileSystemRights.Modify))
{ {
caccess.Add(FileAccess.Write); caccess.Add(FileAccess.Write);
} }
else if (i.FileSystemRights == FileSystemRights.Delete) if (i.FileSystemRights.HasFlag(FileSystemRights.Write | FileSystemRights.Modify))
{ {
caccess.Add(FileAccess.Delete); caccess.Add(FileAccess.Delete);
} }
else if (i.FileSystemRights == FileSystemRights.ExecuteFile) if (
i.FileSystemRights.HasFlag(
FileSystemRights.ExecuteFile | FileSystemRights.Modify
)
)
{ {
caccess.Add(FileAccess.Execute); caccess.Add(FileAccess.Execute);
} }

View file

@ -60,7 +60,7 @@ public class DirFileOpTest(FilesSeed filesSeed) : IClassFixture<FilesSeed>
[Fact, TestPriority(2)] [Fact, TestPriority(2)]
public void SyncFileDir() public void SyncFileDir()
{ {
filesSeed.OldDir.CombineJustDirFile(filesSeed.fileDirOp,filesSeed.DiffDir); filesSeed.OldDir.CombineJustDirFile(filesSeed.fileDirOp, filesSeed.DiffDir);
Dir oldSync = new(filesSeed.OldDir.FormatedPath); Dir oldSync = new(filesSeed.OldDir.FormatedPath);
oldSync.ExtractInfo(); oldSync.ExtractInfo();
oldSync.ResetRootPath(filesSeed.OldDir.FormatedPath, filesSeed.NewDir.FormatedPath); oldSync.ResetRootPath(filesSeed.OldDir.FormatedPath, filesSeed.NewDir.FormatedPath);