style: 修改了代码格式,删掉了一些无用的代码,添加了一些注释

This commit is contained in:
zerlei 2024-10-12 14:30:56 +08:00
parent 1e033e2ca3
commit ca6795d31f
14 changed files with 815 additions and 1206 deletions

View file

@ -3,7 +3,7 @@ namespace Common;
public class DirFileConfig
{
/// <summary>
/// 相对路径
/// 相对路径,与根路径拼成一个完整的路径,注意 "/" 不要缺少
/// </summary>
public required string DirPath { get; set; }
@ -17,9 +17,17 @@ public class DirFileConfig
/// </summary>
public List<string>? CherryPicks { get; set; }
///
/// <summary>
/// 本地文件信息,也是即将发布的文件信息,通常是最新的版本
/// </summary>
public Dir? LocalDirInfo { get; set; }
/// <summary>
/// 差异文件信息
/// </summary>
public Dir? DiffDirInfo { get; set; }
/// <summary>
/// 远程文件信息,通常是较旧的版本
/// </summary>
public Dir? RemoteDirInfo { get; set; }
}
@ -63,6 +71,9 @@ public class Config
/// </summary>
public required string Name { get; set; }
/// <summary>
/// 本次发布的唯一id
/// </summary>
public Guid Id { get; set; } = Guid.NewGuid();
/// <summary>

View file

@ -6,28 +6,52 @@ namespace Common;
public abstract class AbsPipeLine(bool isAES)
{
/// <summary>
/// pipeLine工作函数生效期间永久阻塞
/// </summary>
/// <param name="receiveCb">回调函数从pipeline接收到的消息</param>
/// <param name="addr">连接的远程地址</param>
/// <returns>第一次返回连接信息第二次当pipeline 被断开时返回,此时可能是正常完成断开,或异常发生断开</returns>
public abstract IAsyncEnumerable<int> Work(Func<byte[], bool> receiveCb, string addr = "");
protected Func<byte[], bool> ReceiveMsg = (byte[] a) =>
{
return true;
};
/// <summary>
/// 监听pipeline 消息由Work 函数调用
/// </summary>
/// <param name="receiveCb">消息回调</param>
/// <returns></returns>
protected abstract Task Listen(Func<byte[], bool> receiveCb);
/// <summary>
/// 关闭连接
/// </summary>
/// <param name="CloseReason"></param>
/// <param name="CloseReason">关闭原因</param>
/// <returns></returns>
public abstract Task Close(string? CloseReason);
/// <summary>
/// 发送消息
/// 向管道中发送消息
/// </summary>
/// <param name="msg"></param>
/// <returns></returns>
public abstract Task SendMsg(SyncMsg msg);
/// <summary>
/// 打包文件上传
/// </summary>
/// <param name="url">上传地址</param>
/// <param name="filePath">上传的文件路径</param>
/// <param name="progressCb">上传进度回调(现在没有回调)</param>
/// <returns>上传完成时返回</returns>/
public abstract Task UploadFile(string url, string filePath, Func<double, bool> progressCb);
/// <summary>
/// 管道消息是否使用AES加密
/// </summary>
protected readonly bool IsAES = isAES;
}
@ -42,16 +66,16 @@ public class WebSocPipeLine<TSocket>(TSocket socket, bool isAES) : AbsPipeLine(i
Func<double, bool> progressCb
)
{
//throw new Exception("sdfsdf");
using var client = new HttpClient();
using var content = new MultipartFormDataContent();
using var fileStream = new FileStream(filePath, FileMode.Open);
var progress = new Progress<double>(
(current) =>
{
progressCb(current);
}
);
// TODO 上传进度回调
// var progress = new Progress<double>(
// (current) =>
// {
// progressCb(current);
// }
// );
//var fileContent = new ProgressStreamContent(fileStream, progress);
content.Add(new StreamContent(fileStream), "file", Path.GetFileName(filePath));
var it = await client.PostAsync("http://" + url + "/UploadFile", content);
@ -80,7 +104,7 @@ public class WebSocPipeLine<TSocket>(TSocket socket, bool isAES) : AbsPipeLine(i
protected override async Task Listen(Func<byte[], bool> receiveCb)
{
//最大1MB!=
//warning 最大支持1MB这由需要同步的文件数量大小决定 UTF-8 每个字符汉字视为4个字节数字1个 英文字母2个。1MB=256KB*425万个字符能描述就行
var buffer = new byte[1024 * 1024];
while (Socket.State == WebSocketState.Open)
@ -100,8 +124,6 @@ public class WebSocPipeLine<TSocket>(TSocket socket, bool isAES) : AbsPipeLine(i
System.Buffer.BlockCopy(buffer, 0, nbuffer, 0, receiveResult.Count);
if (IsAES)
{
//var msg1 = Encoding.UTF8.GetString(nbuffer);
//var n1Buffler = Encoding.UTF8.GetBytes(msg1);
var nnbuffer = AESHelper.DecryptStringFromBytes_Aes(nbuffer);
receiveCb(Encoding.UTF8.GetBytes(nnbuffer));
}
@ -117,14 +139,8 @@ public class WebSocPipeLine<TSocket>(TSocket socket, bool isAES) : AbsPipeLine(i
{
if (Socket.State == WebSocketState.Open)
{
//await SendMsg(
// new SyncMsg
// {
// Type = SyncMsgType.Error,
// Step = SyncProcessStep.Finally,
// Body = CloseReason ?? ""
// }
//);
//CloseReason 最大不能超过123bytes.https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close
//若传递超过这个限制此处表现WebSocket将会卡住无法关闭。
if (Encoding.UTF8.GetBytes(CloseReason ?? "").Length > 120)
{
await SendMsg(
@ -156,9 +172,9 @@ public class WebSocPipeLine<TSocket>(TSocket socket, bool isAES) : AbsPipeLine(i
{
string msgStr = JsonSerializer.Serialize(msg);
var it = AESHelper.EncryptStringToBytes_Aes(msgStr);
//var xx = new ArraySegment<byte>(it);
if (IsAES)
{
// 加密后的字符使用Binary 发送,加密通常不会发送到最前端,通常是 js 写的websocket
await Socket.SendAsync(
new ArraySegment<byte>(it),
WebSocketMessageType.Binary,

View file

@ -1,5 +1,8 @@
namespace Common;
/// <summary>
/// Dir比较方法
/// </summary>
public static class DirExtension
{
/// <summary>
@ -248,6 +251,13 @@ public static class DirExtension
return cDir;
}
/// <summary>
/// 根据Dirobject记录的信息写入磁盘
/// </summary>
/// <param name="thisDir"></param>
/// <param name="fileDirOp"> 文件操作类,它是如何写入文件的方法</param>
/// <exception cref="ArgumentException"></exception>
public static void WriteByThisInfo(this Dir thisDir, FileDirOpStra fileDirOp)
{
static void f(Dir dir, FileDirOpStra fileDirOp)
@ -285,6 +295,13 @@ public static class DirExtension
f(thisDir, fileDirOp);
}
/// <summary>
/// 从文件夹中提取文件信息
/// </summary>
/// <param name="thisDir"></param>
/// <param name="cherryPicks">只提取这些信息,最高级别</param>
/// <param name="exculdes">忽略这些文件信息</param>
/// <exception cref="NotSupportedException"></exception>
public static void ExtractInfo(
this Dir thisDir,
List<string>? cherryPicks = null,
@ -334,7 +351,12 @@ public static class DirExtension
}
}
}
/// <summary>
/// 添加一个子对象,这个不包含文件或文件夹的创建
/// </summary>
/// <param name="thisDir"></param>
/// <param name="child"></param>
/// <exception cref="ArgumentException"></exception>
public static void AddChild(this Dir thisDir, AFileOrDir child)
{
if (child.FormatedPath[..thisDir.FormatedPath.Length] != thisDir.FormatedPath)
@ -371,6 +393,16 @@ public static class DirExtension
}
}
/// <summary>
/// 合并diffdir中的内容
/// </summary>
/// <param name="thisDir"></param>
/// <param name="diffdir"></param>
/// <param name="IsUpdateObject">是否更新对象</param>
/// <param name="IsUpdateDirFile">是否更新文件夹和文件</param>
/// <exception cref="ArgumentException"></exception>
/// <exception cref="NotImplementedException"></exception>
public static void Combine(
this Dir thisDir,
FileDirOpStra? fileDirOp,
@ -495,6 +527,14 @@ public static class DirExtension
}
}
/// <summary>
/// clone一个新的对象
/// </summary>
/// <param name="thisDir"></param>
/// <param name="optype">重设的操作类型</param>
/// <param name="IsResetNextOpType">是否重设操作类型</param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public static Dir Clone(
this Dir thisDir,
NextOpType? optype = null,
@ -536,6 +576,13 @@ public static class DirExtension
return ndir;
}
/// <summary>
/// 改变根路径位置
/// </summary>
/// <param name="thisDir"></param>
/// <param name="oldPath"></param>
/// <param name="newPath"></param>
/// <returns></returns>
public static Dir ResetRootPath(this Dir thisDir, string oldPath, string newPath)
{
thisDir.FormatedPath = thisDir.FormatedPath.Replace(oldPath, newPath);
@ -553,6 +600,10 @@ public static class DirExtension
return thisDir;
}
/// <summary>
/// 文件操作权限检查(废弃)
/// </summary>
/// <param name="thisDir"></param>
public static void AccessCheck(this Dir thisDir)
{
//不是核心关注点下面实现有bug。不校验所有文件夹权限创建时会抛出错误此时手动处理吧。
@ -639,247 +690,3 @@ public static class DirExtension
//});
}
}
/// <summary>
/// 文件夹结构,它包含文件和文件夹
/// </summary>
/// <param name="path">绝对路径</param>
/// <param name="children">子文件或文件夹</param>
// public class Dirxx(string path, List<AFileOrDir>? children = null, NextOpType? nextOp = null)
// : AFileOrDir(path, DirOrFile.Dir, nextOp)
// {
// public List<AFileOrDir> Children { get; set; } = children ?? [];
/* public override bool IsEqual(AFileOrDir other)
{
if (other is not Dir otherDir)
{
return false;
}
else
{
if (this.FormatedPath != otherDir.FormatedPath || this.NextOp != otherDir.NextOp)
{
return false;
}
if (this.Children.Count != otherDir.Children.Count)
{
return false;
}
this.Children.Sort(AFileOrDir.Compare);
otherDir.Children.Sort(AFileOrDir.Compare);
for (int i = 0; i < this.Children.Count; i++)
{
if (!this.Children[i].IsEqual(otherDir.Children[i]))
{
return false;
}
}
return true;
}
} */
/// <summary>
/// clone, 但是更改根目录
/// </summary>
/// <param name="optype">操作步骤</param>
/// <param name="oldRootPath">旧根路径</param>
/// <param name="newRootPath">新根路径</param>
/// <param name="IsResetNextOpType">是否重置下步操作</param>
/// <returns></returns>
// public Dir Clone(
// NextOpType? optype,
// string oldRootPath,
// string newRootPath,
// bool IsResetNextOpType = false
// )
// {
// var ndir = this.Clone(optype, IsResetNextOpType);
// ndir.ResetRootPath(oldRootPath, newRootPath);
// return ndir;
// }
/// <summary>
/// clone,不克隆文件
/// </summary>
/// <param name="optype"></param>
/// <param name="IsResetNextOpType"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
// public Dir Clone(NextOpType? optype = null, bool IsResetNextOpType = false) { }
/// <summary>
/// 重设置根目录
/// </summary>
/// <param name="oldPath"></param>
/// <param name="newPath"></param>
// public void ResetRootPath(string oldPath, string newPath)
// {
// this.FormatedPath = this.FormatedPath.Replace(oldPath, newPath);
// this.Children.ForEach(e =>
// {
// if (e is File file)
// {
// file.FormatedPath = file.FormatedPath.Replace(oldPath, newPath);
// }
// else if (e is Dir dir)
// {
// dir.ResetRootPath(oldPath, newPath);
// }
// });
// }
/// <summary>
/// 文件夹合并
/// </summary>
/// <param name="fileDirOp">具体操作步骤</param>
/// <param name="diffdir">将要更新的内容</param>
/// <param name="IsUpdateObject"> 是否更新Object对象</param>
/// <param name="IsUpdateDirFile">是否更新文件目录树</param>
/// <returns></returns>
// public void Combine(
// FileDirOpStra? fileDirOp,
// Dir diffdir,
// bool IsUpdateObject = true,
// bool IsUpdateDirFile = false
// ) { }
// /// <summary>
// /// 合并两个文件夹,other不会发生改变this将合并一个副本这不会改变文件结构
// /// </summary>
// /// <param name="other">它的一个clone将被合并的dir,它的NextOp 不应该是空,否则什么都不会发生</param>
// /// <returns></returns>
// public void CombineJustObject(Dir other)
// {
// Combine(null, other, true, false);
// }
// /// <summary>
// /// 合并两个文件夹,other不会发生改变this将不会改变而文件结构会改变
// /// </summary>
// /// <param name="other">它的一个clone将被合并的dir,它的NextOp 不应该是空,否则什么都不会发生</param>
// /// <returns></returns>
// public void CombineJustDirFile(FileDirOpStra fileDirOp, Dir diffDir)
// {
// Combine(fileDirOp, diffDir, false, true);
// }
// /// <summary>
// /// 添加子节点,根目录相同,才会被添加进去
// /// </summary>
// /// <param name="child"></param>
// /// <returns></returns>/
// protected void AddChild(AFileOrDir child) { }
// /// <summary>
// /// 从文件夹中提取信息
// /// </summary>
// /// <param name="cherryPicks">绝对路径,只包含的文件或者目录</param>
// /// <param name="exculdes">绝对路径,排除的文件或目录</param>
// /// <exception cref="NotSupportedException"></exception>
// /// <summary>
// /// 写入目录文件树,首先必须定义写入文件的策略,此目录结构不包含文件内容,但有一个
// /// 文件的修改时间,是否修改文件的修改时间,需要定义文件的写入策略 WriteFileStrageFunc
// /// </summary>
// /// <returns></returns>
// /// <summary>
// /// 校验文件夹和文件权限
// /// </summary>
// // private void AccessCheck()j
// // {
// //不是核心关注点下面实现有bug。不校验所有文件夹权限创建时会抛出错误此时手动处理吧。
// // return;
// //this.Children.ForEach(e =>
// //{
// // if (e is File file)
// // {
// // if (file.NextOp == null) { }
// // else if (file.NextOp == NextOpType.Add)
// // {
// // if (
// // !AccessWrapper.CheckDirAccess(
// // Path.GetDirectoryName(file.FormatedPath)
// // ?? throw new DirectoryNotFoundException(
// // $"{file.FormatedPath} 此父路径不存在"
// // ),
// // [DirAcess.CreateFiles]
// // )
// // )
// // {
// // throw new UnauthorizedAccessException($"{file.FormatedPath} 无权限创建文件");
// // }
// // }
// // else if (file.NextOp == NextOpType.Modify)
// // {
// // if (
// // !(
// // AccessWrapper.CheckFileAccess(file.FormatedPath, [FileAccess.Delete])
// // && AccessWrapper.CheckDirAccess(
// // Path.GetDirectoryName(file.FormatedPath)
// // ?? throw new DirectoryNotFoundException(
// // $"{file.FormatedPath} 此父路径不存在"
// // ),
// // [DirAcess.CreateFiles]
// // )
// // )
// // )
// // {
// // throw new UnauthorizedAccessException(
// // $"{file.FormatedPath} 无权限删除源文件或者创建新文件"
// // );
// // }
// // }
// // else if (file.NextOp == NextOpType.Del)
// // {
// // if (!AccessWrapper.CheckFileAccess(file.FormatedPath, [FileAccess.Delete]))
// // {
// // throw new UnauthorizedAccessException($"{file.FormatedPath} 无权限删除源文件");
// // }
// // }
// // }
// // else if (e is Dir dir)
// // {
// // if (dir.NextOp == null) { }
// // else if (dir.NextOp == NextOpType.Add)
// // {
// // if (
// // !AccessWrapper.CheckDirAccess(
// // Path.GetDirectoryName(dir.FormatedPath)
// // ?? throw new DirectoryNotFoundException(
// // $"{dir.FormatedPath} 此父路径不存在"
// // ),
// // [DirAcess.CreateDirectories, DirAcess.CreateFiles]
// // )
// // )
// // {
// // throw new UnauthorizedAccessException($"{dir.FormatedPath} 无权限创建文件夹或者文件");
// // }
// // }
// // else if (dir.NextOp == NextOpType.Del)
// // {
// // if (!AccessWrapper.CheckDirAccess(dir.FormatedPath, [DirAcess.Delete]))
// // {
// // throw new UnauthorizedAccessException($"{dir.FormatedPath} 无权限删除文件夹");
// // }
// // else
// // {
// // //校验是否拥有子文件或者文件夹的删除权限,
// // dir.AccessCheck();
// // }
// // }
// // }
// //});
// // }
// /// <summary>
// /// 比较两个目录文件树是否相同,不相同返回差异部分,左侧是右侧的下一个版本,任何一个节点的nextop != null即所有
// /// 节点都会打上标记
// /// 文件夹的 NextOp 只有新增和删除
// /// </summary>
// /// <param name="otherRootDir"></param>
// /// <returns></returns>
// }

View file

@ -39,10 +39,10 @@ public class AFileOrDir
set { Path = value; }
}
public bool IsEqual(AFileOrDir other)
{
return false;
}
// public bool IsEqual(AFileOrDir other)
// {
// return false;
// }
public static int Compare(AFileOrDir l, AFileOrDir r)
{
@ -69,7 +69,7 @@ public class File : AFileOrDir
public required DateTime MTime { get; set; }
public new bool IsEqual(AFileOrDir other)
public bool IsEqual(AFileOrDir other)
{
if (other is not File otherFile)
{
@ -96,7 +96,7 @@ public class Dir : AFileOrDir
public required List<AFileOrDir> Children { get; set; }
public new bool IsEqual(AFileOrDir other)
public bool IsEqual(AFileOrDir other)
{
if (other is not Dir otherDir)
{
@ -116,7 +116,23 @@ public class Dir : AFileOrDir
otherDir.Children.Sort(AFileOrDir.Compare);
for (int i = 0; i < this.Children.Count; i++)
{
if (!this.Children[i].IsEqual(otherDir.Children[i]))
var l = this.Children[i];
var r = otherDir.Children[i];
if (l is Dir ld && r is Dir rd)
{
if (!ld.IsEqual(rd))
{
return false;
}
}
else if (l is File lf && r is File rf)
{
if (!lf.IsEqual(rf))
{
return false;
}
}
else
{
return false;
}

View file

@ -321,391 +321,391 @@ public class FileDirOpForUnpack(string srcRootPath, string dstRootPath) : FileDi
}
}
/// <summary>
/// 文件目录权限校验
/// </summary>
public class FileDirOpForAccessCheck : FileDirOpStra
{
public override void FileCreate(string absolutePath, DateTime mtime)
{
throw new NotImplementedException();
}
// /// <summary>
// /// 文件目录权限校验
// /// </summary>
// public class FileDirOpForAccessCheck : FileDirOpStra
// {
// public override void FileCreate(string absolutePath, DateTime mtime)
// {
// throw new NotImplementedException();
// }
public override void DirCreate(Dir dir, bool IsRecursion = true)
{
throw new NotImplementedException();
}
// public override void DirCreate(Dir dir, bool IsRecursion = true)
// {
// throw new NotImplementedException();
// }
public override void FileModify(string absolutePath, DateTime mtime)
{
throw new NotImplementedException();
}
// public override void FileModify(string absolutePath, DateTime mtime)
// {
// throw new NotImplementedException();
// }
public override void FileDel(string absolutePath)
{
throw new NotImplementedException();
}
// public override void FileDel(string absolutePath)
// {
// throw new NotImplementedException();
// }
public override void DirDel(Dir dir, bool IsRecursion = true)
{
throw new NotImplementedException();
}
}
// public override void DirDel(Dir dir, bool IsRecursion = true)
// {
// throw new NotImplementedException();
// }
// }
public enum FileAccess
{
Read,
Write,
Delete,
Execute
}
// public enum FileAccess
// {
// Read,
// Write,
// Delete,
// Execute
// }
public enum DirAcess
{
/// <summary>
/// 读取权限
/// </summary>
Read,
// public enum DirAcess
// {
// /// <summary>
// /// 读取权限
// /// </summary>
// Read,
/// <summary>
/// 写入权限
/// </summary>
Write,
// /// <summary>
// /// 写入权限
// /// </summary>
// Write,
/// <summary>
/// 列出文件夹权限
/// </summary>
ListDirectory,
// /// <summary>
// /// 列出文件夹权限
// /// </summary>
// ListDirectory,
/// <summary>
/// 创建文件权限
/// </summary>
CreateFiles,
// /// <summary>
// /// 创建文件权限
// /// </summary>
// CreateFiles,
/// <summary>
/// 创建文件夹权限
/// </summary>
CreateDirectories,
// /// <summary>
// /// 创建文件夹权限
// /// </summary>
// CreateDirectories,
/// <summary>
/// 删除文件权限
/// </summary>
Delete,
// /// <summary>
// /// 删除文件权限
// /// </summary>
// Delete,
/// <summary>
/// 删除文件夹及其子文件
/// </summary>
DeleteSubdirectoriesAndFiles,
}
// /// <summary>
// /// 删除文件夹及其子文件
// /// </summary>
// DeleteSubdirectoriesAndFiles,
// }
/// <summary>
/// 运行此软件的用户与目标软件的用户最好是 一个用户,一个用户组,或者运行此软件的用户具备最高权限。
/// </summary>
public class AccessWrapper
{
/// <summary>
///
/// </summary>
/// <param name="absolutePath"></param>
public static void FreeThisDirAccess(string absolutePath)
{
if (
CheckDirAccess(
absolutePath,
[
DirAcess.Read,
DirAcess.Write,
DirAcess.Delete,
DirAcess.ListDirectory,
DirAcess.CreateFiles,
DirAcess.CreateDirectories,
DirAcess.DeleteSubdirectoriesAndFiles
]
)
) { }
else
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
DirectoryInfo dirInfo = new(absolutePath);
//获得该文件的访问权限
var dirSecurity = dirInfo.GetAccessControl();
//设定文件ACL继承
InheritanceFlags inherits =
InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit;
// /// <summary>
// /// 运行此软件的用户与目标软件的用户最好是 一个用户,一个用户组,或者运行此软件的用户具备最高权限。
// /// </summary>
// public class AccessWrapper
// {
// /// <summary>
// ///
// /// </summary>
// /// <param name="absolutePath"></param>
// public static void FreeThisDirAccess(string absolutePath)
// {
// if (
// CheckDirAccess(
// absolutePath,
// [
// DirAcess.Read,
// DirAcess.Write,
// DirAcess.Delete,
// DirAcess.ListDirectory,
// DirAcess.CreateFiles,
// DirAcess.CreateDirectories,
// DirAcess.DeleteSubdirectoriesAndFiles
// ]
// )
// ) { }
// else
// {
// if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
// {
// DirectoryInfo dirInfo = new(absolutePath);
// //获得该文件的访问权限
// var dirSecurity = dirInfo.GetAccessControl();
// //设定文件ACL继承
// InheritanceFlags inherits =
// InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit;
var cUser =
(
WindowsIdentity.GetCurrent().Groups
?? throw new Exception("GetWindowsIdentity failed. 你需要手动处理发布内容!--检查权限!")
).FirstOrDefault() ?? throw new NullReferenceException("can't be null");
FileSystemAccessRule MdfRule =
new(
cUser,
FileSystemRights.Modify,
inherits,
PropagationFlags.InheritOnly,
AccessControlType.Allow
);
if (dirSecurity.ModifyAccessRule(AccessControlModification.Set, MdfRule, out _)) { }
else
{
throw new Exception("AddAccessRule failed. 你需要手动处理发布内容!--检查权限!");
}
//设置访问权限
dirInfo.SetAccessControl(dirSecurity);
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
//TODO Linux文件权限
}
else
{
throw new NotSupportedException(
$"{RuntimeInformation.OSDescription} is not supported."
);
}
}
}
// var cUser =
// (
// WindowsIdentity.GetCurrent().Groups
// ?? throw new Exception("GetWindowsIdentity failed. 你需要手动处理发布内容!--检查权限!")
// ).FirstOrDefault() ?? throw new NullReferenceException("can't be null");
// FileSystemAccessRule MdfRule =
// new(
// cUser,
// FileSystemRights.Modify,
// inherits,
// PropagationFlags.InheritOnly,
// AccessControlType.Allow
// );
// if (dirSecurity.ModifyAccessRule(AccessControlModification.Set, MdfRule, out _)) { }
// else
// {
// throw new Exception("AddAccessRule failed. 你需要手动处理发布内容!--检查权限!");
// }
// //设置访问权限
// dirInfo.SetAccessControl(dirSecurity);
// }
// else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
// {
// //TODO Linux文件权限
// }
// else
// {
// throw new NotSupportedException(
// $"{RuntimeInformation.OSDescription} is not supported."
// );
// }
// }
// }
public static void FreeThisFileAccess(string absolutePath)
{
if (
CheckFileAccess(
absolutePath,
[FileAccess.Read, FileAccess.Write, FileAccess.Delete, FileAccess.Execute]
)
) { }
else
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
FileInfo fileInfo = new(absolutePath);
//获得该文件的访问权限
FileSecurity fileSecurity = fileInfo.GetAccessControl();
// public static void FreeThisFileAccess(string absolutePath)
// {
// if (
// CheckFileAccess(
// absolutePath,
// [FileAccess.Read, FileAccess.Write, FileAccess.Delete, FileAccess.Execute]
// )
// ) { }
// else
// {
// if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
// {
// FileInfo fileInfo = new(absolutePath);
// //获得该文件的访问权限
// FileSecurity fileSecurity = fileInfo.GetAccessControl();
var cUser =
(
WindowsIdentity.GetCurrent().Groups
?? throw new NullReferenceException(
"GetWindowsIdentity failed. 你需要手动处理发布内容!-- 检查权限"
)
).FirstOrDefault() ?? throw new NullReferenceException("can't be null");
FileSystemAccessRule MdfRule =
new(cUser, FileSystemRights.Modify, AccessControlType.Allow);
if (fileSecurity.ModifyAccessRule(AccessControlModification.Set, MdfRule, out _))
{ }
else
{
throw new Exception("AddAccessRule failed. 你需要手动处理发布内容!--检查权限");
}
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
//TODO Linux文件权限
}
else
{
throw new NotSupportedException(
$"{RuntimeInformation.OSDescription} is not supported."
);
}
}
}
// var cUser =
// (
// WindowsIdentity.GetCurrent().Groups
// ?? throw new NullReferenceException(
// "GetWindowsIdentity failed. 你需要手动处理发布内容!-- 检查权限"
// )
// ).FirstOrDefault() ?? throw new NullReferenceException("can't be null");
// FileSystemAccessRule MdfRule =
// new(cUser, FileSystemRights.Modify, AccessControlType.Allow);
// if (fileSecurity.ModifyAccessRule(AccessControlModification.Set, MdfRule, out _))
// { }
// else
// {
// throw new Exception("AddAccessRule failed. 你需要手动处理发布内容!--检查权限");
// }
// }
// else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
// {
// //TODO Linux文件权限
// }
// else
// {
// throw new NotSupportedException(
// $"{RuntimeInformation.OSDescription} is not supported."
// );
// }
// }
// }
public static bool CheckDirAccess(string absolutePath, DirAcess[] access)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
DirectoryInfo dirInfo = new(absolutePath);
//获得该文件的访问权限
var dirSecurity = dirInfo.GetAccessControl();
var ac = dirSecurity
.GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier))
.Cast<FileSystemAccessRule>();
#pragma warning disable CA1416 // Validate platform compatibility
var it =
from i in ac
where
(
WindowsIdentity.GetCurrent().Groups
?? throw new NullReferenceException("未能获取当前用户组!")
).Contains(i.IdentityReference)
select i;
#pragma warning restore CA1416 // Validate platform compatibility
List<DirAcess> caccess = [];
foreach (var i in it)
{
if (i.FileSystemRights.HasFlag(FileSystemRights.FullControl))
{
return true;
}
if (
i.FileSystemRights.HasFlag(
FileSystemRights.Read
| FileSystemRights.Modify
| FileSystemRights.ReadAndExecute
)
)
{
caccess.Add(DirAcess.Read);
}
if (i.FileSystemRights.HasFlag(FileSystemRights.Write | FileSystemRights.Modify))
{
caccess.Add(DirAcess.Write);
}
if (i.FileSystemRights.HasFlag(FileSystemRights.Modify | FileSystemRights.Delete))
{
caccess.Add(DirAcess.Delete);
}
if (
i.FileSystemRights.HasFlag(
FileSystemRights.ListDirectory | FileSystemRights.Modify
)
)
{
caccess.Add(DirAcess.ListDirectory);
}
if (
i.FileSystemRights.HasFlag(
FileSystemRights.CreateFiles | FileSystemRights.Modify
)
)
{
caccess.Add(DirAcess.CreateFiles);
}
if (
i.FileSystemRights.HasFlag(
FileSystemRights.CreateDirectories | FileSystemRights.Modify
)
)
{
caccess.Add(DirAcess.CreateDirectories);
}
if (
i.FileSystemRights.HasFlag(
FileSystemRights.DeleteSubdirectoriesAndFiles | FileSystemRights.Modify
)
)
{
caccess.Add(DirAcess.DeleteSubdirectoriesAndFiles);
}
}
foreach (var i in access)
{
if (!caccess.Contains(i))
{
return false;
}
}
return true;
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
//TODO Linux文件权限
return true;
}
else
{
throw new NotSupportedException(
$"{RuntimeInformation.OSDescription} is not supported."
);
}
}
// public static bool CheckDirAccess(string absolutePath, DirAcess[] access)
// {
// if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
// {
// DirectoryInfo dirInfo = new(absolutePath);
// //获得该文件的访问权限
// var dirSecurity = dirInfo.GetAccessControl();
// var ac = dirSecurity
// .GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier))
// .Cast<FileSystemAccessRule>();
// #pragma warning disable CA1416 // Validate platform compatibility
// var it =
// from i in ac
// where
// (
// WindowsIdentity.GetCurrent().Groups
// ?? throw new NullReferenceException("未能获取当前用户组!")
// ).Contains(i.IdentityReference)
// select i;
// #pragma warning restore CA1416 // Validate platform compatibility
// List<DirAcess> caccess = [];
// foreach (var i in it)
// {
// if (i.FileSystemRights.HasFlag(FileSystemRights.FullControl))
// {
// return true;
// }
// if (
// i.FileSystemRights.HasFlag(
// FileSystemRights.Read
// | FileSystemRights.Modify
// | FileSystemRights.ReadAndExecute
// )
// )
// {
// caccess.Add(DirAcess.Read);
// }
// if (i.FileSystemRights.HasFlag(FileSystemRights.Write | FileSystemRights.Modify))
// {
// caccess.Add(DirAcess.Write);
// }
// if (i.FileSystemRights.HasFlag(FileSystemRights.Modify | FileSystemRights.Delete))
// {
// caccess.Add(DirAcess.Delete);
// }
// if (
// i.FileSystemRights.HasFlag(
// FileSystemRights.ListDirectory | FileSystemRights.Modify
// )
// )
// {
// caccess.Add(DirAcess.ListDirectory);
// }
// if (
// i.FileSystemRights.HasFlag(
// FileSystemRights.CreateFiles | FileSystemRights.Modify
// )
// )
// {
// caccess.Add(DirAcess.CreateFiles);
// }
// if (
// i.FileSystemRights.HasFlag(
// FileSystemRights.CreateDirectories | FileSystemRights.Modify
// )
// )
// {
// caccess.Add(DirAcess.CreateDirectories);
// }
// if (
// i.FileSystemRights.HasFlag(
// FileSystemRights.DeleteSubdirectoriesAndFiles | FileSystemRights.Modify
// )
// )
// {
// caccess.Add(DirAcess.DeleteSubdirectoriesAndFiles);
// }
// }
// foreach (var i in access)
// {
// if (!caccess.Contains(i))
// {
// return false;
// }
// }
// return true;
// }
// else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
// {
// //TODO Linux文件权限
// return true;
// }
// else
// {
// throw new NotSupportedException(
// $"{RuntimeInformation.OSDescription} is not supported."
// );
// }
// }
public static bool CheckFileAccess(string absolutePath, FileAccess[] access)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
FileInfo fileInfo = new(absolutePath);
//获得该文件的访问权限
FileSecurity fileSecurity = fileInfo.GetAccessControl();
// public static bool CheckFileAccess(string absolutePath, FileAccess[] access)
// {
// if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
// {
// FileInfo fileInfo = new(absolutePath);
// //获得该文件的访问权限
// FileSecurity fileSecurity = fileInfo.GetAccessControl();
var ac = fileSecurity
.GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier))
.Cast<FileSystemAccessRule>();
#pragma warning disable CA1416 // 验证平台兼容性
var it =
from i in ac
where
(
WindowsIdentity.GetCurrent().Groups
?? throw new NullReferenceException("未能获取当前用户组!")
).Contains(i.IdentityReference)
select i;
#pragma warning restore CA1416 // 验证平台兼容性
// var ac = fileSecurity
// .GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier))
// .Cast<FileSystemAccessRule>();
// #pragma warning disable CA1416 // 验证平台兼容性
// var it =
// from i in ac
// where
// (
// WindowsIdentity.GetCurrent().Groups
// ?? throw new NullReferenceException("未能获取当前用户组!")
// ).Contains(i.IdentityReference)
// select i;
// #pragma warning restore CA1416 // 验证平台兼容性
List<FileAccess> caccess = [];
foreach (var i in it)
{
if (i.FileSystemRights.HasFlag(FileSystemRights.FullControl))
{
return true;
}
if (i.FileSystemRights.HasFlag(FileSystemRights.Read | FileSystemRights.Modify))
{
caccess.Add(FileAccess.Read);
}
if (i.FileSystemRights.HasFlag(FileSystemRights.Write | FileSystemRights.Modify))
{
caccess.Add(FileAccess.Write);
}
if (i.FileSystemRights.HasFlag(FileSystemRights.Write | FileSystemRights.Modify))
{
caccess.Add(FileAccess.Delete);
}
if (
i.FileSystemRights.HasFlag(
FileSystemRights.ExecuteFile | FileSystemRights.Modify
)
)
{
caccess.Add(FileAccess.Execute);
}
}
foreach (var i in access)
{
if (!caccess.Contains(i))
{
return false;
}
}
return true;
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
//TODO Linux文件夹权限
return true;
}
else
{
throw new NotSupportedException(
$"{RuntimeInformation.OSDescription} is not supported."
);
}
}
// List<FileAccess> caccess = [];
// foreach (var i in it)
// {
// if (i.FileSystemRights.HasFlag(FileSystemRights.FullControl))
// {
// return true;
// }
// if (i.FileSystemRights.HasFlag(FileSystemRights.Read | FileSystemRights.Modify))
// {
// caccess.Add(FileAccess.Read);
// }
// if (i.FileSystemRights.HasFlag(FileSystemRights.Write | FileSystemRights.Modify))
// {
// caccess.Add(FileAccess.Write);
// }
// if (i.FileSystemRights.HasFlag(FileSystemRights.Write | FileSystemRights.Modify))
// {
// caccess.Add(FileAccess.Delete);
// }
// if (
// i.FileSystemRights.HasFlag(
// FileSystemRights.ExecuteFile | FileSystemRights.Modify
// )
// )
// {
// caccess.Add(FileAccess.Execute);
// }
// }
// foreach (var i in access)
// {
// if (!caccess.Contains(i))
// {
// return false;
// }
// }
// return true;
// }
// else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
// {
// //TODO Linux文件夹权限
// return true;
// }
// else
// {
// throw new NotSupportedException(
// $"{RuntimeInformation.OSDescription} is not supported."
// );
// }
// }
/// <summary>
/// 获取当前用户
/// </summary>
/// <returns></returns>
/// <exception cref="NotSupportedException"></exception>
// /// <summary>
// /// 获取当前用户
// /// </summary>
// /// <returns></returns>
// /// <exception cref="NotSupportedException"></exception>
public static string GetCurrentUser()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return System.Security.Principal.WindowsIdentity.GetCurrent().Name;
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
return Environment.UserName;
}
else
{
throw new NotSupportedException(
$"{RuntimeInformation.OSDescription} is not supported."
);
}
}
}
// public static string GetCurrentUser()
// {
// if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
// {
// return System.Security.Principal.WindowsIdentity.GetCurrent().Name;
// }
// else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
// {
// return Environment.UserName;
// }
// else
// {
// throw new NotSupportedException(
// $"{RuntimeInformation.OSDescription} is not supported."
// );
// }
// }
// }

View file

@ -10,36 +10,11 @@ namespace LocalServer.Controllers
{
private readonly LocalSyncServerFactory Factory = factory;
private static async Task Echo(WebSocket webSocket)
{
var buffer = new byte[1024 * 4];
var receiveResult = await webSocket.ReceiveAsync(
new ArraySegment<byte>(buffer),
CancellationToken.None
);
while (!receiveResult.CloseStatus.HasValue)
{
await webSocket.SendAsync(
new ArraySegment<byte>(buffer, 0, receiveResult.Count),
receiveResult.MessageType,
receiveResult.EndOfMessage,
CancellationToken.None
);
receiveResult = await webSocket.ReceiveAsync(
new ArraySegment<byte>(buffer),
CancellationToken.None
);
}
await webSocket.CloseAsync(
receiveResult.CloseStatus.Value,
receiveResult.CloseStatusDescription,
CancellationToken.None
);
}
/// <summary>
/// websoc 连接入口
/// </summary>
/// <param name="Name"></param>
/// <returns></returns>
[Route("/websoc")]
public async Task WebsocketConnection(string Name)
{
@ -50,8 +25,8 @@ namespace LocalServer.Controllers
if (Factory.GetServerByName(Name) == null)
{
var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync();
//await Echo(webSocket);
var pipeLine = new WebSocPipeLine<WebSocket>(webSocket, false);
//必须在此保留连接的上下文,否则 websocket 就直接断了。。。微软 这个设计措不及防
await Factory.CreateLocalSyncServer(
pipeLine,
Name,
@ -75,18 +50,18 @@ namespace LocalServer.Controllers
}
}
[Route("/macaddr")]
public string GetMacAddress()
{
NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
string macaddrs = "";
foreach (NetworkInterface nic in nics)
{
PhysicalAddress physicalAddress = nic.GetPhysicalAddress();
macaddrs += physicalAddress.ToString() + ";";
}
return macaddrs;
}
//TODO 是否在本地记载同步日志?
// [Route("/macaddr")]
// public string GetMacAddress()
// {
// NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
// string macaddrs = "";
// foreach (NetworkInterface nic in nics)
// {
// PhysicalAddress physicalAddress = nic.GetPhysicalAddress();
// macaddrs += physicalAddress.ToString() + ";";
// }
// return macaddrs;
// }
// //TODO 是否在本地记载同步日志?
}
}

View file

@ -8,63 +8,76 @@ public class LocalSyncServer
#pragma warning disable CA2211 // Non-constant fields should not be visible
public static string TempRootFile = "C:/TempPack";
public static string SqlPackageAbPath = "sqlpackage";
// 使用msdeploy 将会打包当前可运行的内容,它很有可能不包含最新的构建
//public static string MsdeployAbPath = "msdeploy";
//与visual studio 匹配的Msbuild 路径。在vs 中打开power shell 命令行,使用 `(get-Command -Name msbuild).Source `
//使用msbuild 会缺少.net frame的运行环境 bin\roslyn 里面的内容,第一次需要人为复制一下,后面就就好了。
public static string MSBuildAbPath = "MSBuild";
#pragma warning restore CA2211 // Non-constant fields should not be visible
/// <summary>
/// 连接状态流程管理LocalPipe 和 remotePipe 也在此处交换信息
/// </summary>
private StateHelpBase StateHelper;
public void SetStateHelper(StateHelpBase helper)
{
StateHelper = helper;
}
public static string GetProjectOutPath(string project)
{
try
{
XDocument xdoc = XDocument.Load(project);
// 获取根元素
XElement rootElement = xdoc.Root ?? throw new NullReferenceException("Root");
Console.WriteLine("根元素: " + rootElement.Name);
/// <summary>
/// 查找构建xml文件获取构建信息那这个不用了
/// </summary>
/// <returns></returns>
// public static string GetProjectOutPath(string project)
// {
// try
// {
// XDocument xdoc = XDocument.Load(project);
// // 获取根元素
// XElement rootElement = xdoc.Root ?? throw new NullReferenceException("Root");
// Console.WriteLine("根元素: " + rootElement.Name);
// 遍历子节点
foreach (XElement element in rootElement.Elements())
{
if (element.Name.LocalName.Contains("PropertyGroup"))
{
var Conditon = element.Attribute("Condition");
// // 遍历子节点
// foreach (XElement element in rootElement.Elements())
// {
// if (element.Name.LocalName.Contains("PropertyGroup"))
// {
// var Conditon = element.Attribute("Condition");
if (Conditon != null)
{
if (Conditon.Value.Contains("Release"))
{
foreach (XElement element2 in element.Elements())
{
if (element2.Name.LocalName == "OutputPath")
{
return element2.Value;
}
}
}
}
}
}
return "bin/";
}
catch (Exception)
{
return "bin/";
}
}
// if (Conditon != null)
// {
// if (Conditon.Value.Contains("Release"))
// {
// foreach (XElement element2 in element.Elements())
// {
// if (element2.Name.LocalName == "OutputPath")
// {
// return element2.Value;
// }
// }
// }
// }
// }
// }
// return "bin/";
// }
// catch (Exception)
// {
// return "bin/";
// }
// }
public StateHelpBase GetStateHelper()
{
return StateHelper;
}
/// <summary>
/// 此次发布的配置
/// </summary>
public Config? SyncConfig;
public Config NotNullSyncConfig
@ -79,13 +92,19 @@ public class LocalSyncServer
}
}
/// <summary>
/// 发布的名称
/// </summary>
public string Name;
/// <summary>
/// 发布源连接
/// jswebsocket 和 local server 的连接,它没有加密
/// </summary>
public readonly AbsPipeLine LocalPipe;
/// <summary>
/// local server 和 remote server 的连接,它有加密
/// </summary>
public readonly AbsPipeLine RemotePipe;
/// <summary>
@ -107,6 +126,10 @@ public class LocalSyncServer
RemotePipe = remotePipe;
}
/// <summary>
/// 这个阻塞在接口中有http上下文处
/// </summary>
/// <returns></returns>
public async Task Connect()
{
try
@ -125,6 +148,10 @@ public class LocalSyncServer
}
}
/// <summary>
/// 关闭连接
/// </summary>
/// <param name="CloseReason"></param>
public void Close(string? CloseReason)
{
try

View file

@ -2,19 +2,10 @@ using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using Common;
namespace LocalServer;
// enum StateWhenMsg
// {
// Authority = 0,
// ConfigInfo = 1,
// LocalPackAndUpload = 2,
// RemoteUnPackAndRelease = 3,
// }
public abstract class StateHelpBase(
LocalSyncServer context,
SyncProcessStep step = SyncProcessStep.Connect
@ -147,18 +138,11 @@ public class DeployHelper(LocalSyncServer context)
h.DiffProcess();
}
else
{
{ // msbuild 只在windows 才有
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
//构建
//var OutputPath = LocalSyncServer.GetProjectOutPath(
// Context.NotNullSyncConfig.LocalProjectAbsolutePath
//);
//var AbOutPath = Path.Combine(
// Context.NotNullSyncConfig.LocalProjectAbsolutePath,
// OutputPath
//);
ProcessStartInfo startbuildInfo =
new()
{
@ -333,8 +317,6 @@ public class DeployMSSqlHelper(LocalSyncServer context)
PackAndSwitchNext();
}
else
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
var arguments =
$" /Action:Extract /TargetFile:{LocalSyncServer.TempRootFile}/{Context.NotNullSyncConfig.Id.ToString()}/{Context.NotNullSyncConfig.Id.ToString()}.dacpac"
@ -384,11 +366,6 @@ public class DeployMSSqlHelper(LocalSyncServer context)
throw new Exception("执行发布错误,错误信息参考上一条消息!");
}
}
else
{
throw new NotSupportedException("只支持windows!");
}
}
}
protected override void HandleLocalMsg(SyncMsg msg) { }
@ -410,6 +387,7 @@ public class UploadPackedHelper(LocalSyncServer context)
$"{LocalSyncServer.TempRootFile}/{Context.NotNullSyncConfig.Id}.zip",
(double current) =>
{
//这里可能需要降低获取上传进度的频率
Context
.LocalPipe.SendMsg(CreateMsg(current.ToString(), SyncMsgType.Process))
.Wait();
@ -450,222 +428,3 @@ public class FinallyPublishHelper(LocalSyncServer context)
Context.LocalPipe.SendMsg(msg).Wait();
}
}
// /// <summary>
// /// 0. 发布源验证密码
// /// </summary>
// /// <param name="context"></param>
// public class LocalAuthorityState(LocalSyncServer context) : StateHelpBase(context)
// {
// public override void HandleRemoteMsg(SyncMsg? msg)
// {
// throw new NotImplementedException("error usage!");
// }
// public override void HandleLocalMsg(SyncMsg? msg)
// {
// if (msg == null)
// {
// return;
// }
// else
// {
// string Pwd = msg.Body;
// if (Pwd == "Xfs1%$@_fdYU.>>")
// {
// Context.LocalSocketSendMsg(new SyncMsg(SyncMsgType.Success, "源服务密码校验成功!"));
// Context.StateHelper = new WaitingConfigInfoState(Context);
// }
// else
// {
// throw new UnauthorizedAccessException("pwd error!");
// }
// }
// }
// }
// /// <summary>
// /// 1. 获取配置信息,它包含目标的服务器的配置信息
// /// </summary>
// /// <param name="context"></param>
// public class WaitingConfigInfoState(LocalSyncServer context) : StateHelpBase(context)
// {
// public override void HandleRemoteMsg(SyncMsg? msg) { }
// public override void HandleLocalMsg(SyncMsg? msg)
// {
// if (msg == null)
// {
// return;
// }
// else
// {
// string ConfigInfo = msg.Body;
// Context.SyncConfig =
// JsonSerializer.Deserialize<Config>(ConfigInfo)
// ?? throw new NullReferenceException("ConfigInfo is null");
// var task = Context.RemoteSocket.ConnectAsync(
// new Uri(Context.SyncConfig.RemoteUrl),
// CancellationToken.None
// );
// if (task.Wait(10000))
// {
// if (Context.RemoteSocket.State == WebSocketState.Open)
// {
// var state = new RemoteAuthorityState(Context);
// state.SendPwdToRemoteServer();
// Context.StateHelper = state;
// }
// else
// {
// throw new Exception("connect remote server failed!");
// }
// }
// else
// {
// throw new TimeoutException("connect remote server timeout");
// }
// }
// }
// }
// /// <summary>
// /// 2. 目标服务器权限校验
// /// </summary>
// /// <param name="context"></param>
// public class RemoteAuthorityState(LocalSyncServer context) : StateHelpBase(context)
// {
// public override void HandleRemoteMsg(SyncMsg? msg)
// {
// if (msg == null)
// {
// return;
// }
// else
// {
// if (msg.Type == SyncMsgType.Success)
// {
// Context.LocalSocketSendMsg(new SyncMsg(SyncMsgType.Success, "远程服务器校验成功!"));
// var diffState = new DirFilesDiffState(Context);
// diffState.SendSyncConfigToRemote();
// Context.StateHelper = diffState;
// }
// else
// {
// throw new Exception("远程服务器权限校验失败请检查Local Server 的Mac地址是否在 Remote Server 的允许列表内!");
// }
// }
// }
// public override void HandleLocalMsg(SyncMsg? msg) { }
// public void SendPwdToRemoteServer()
// {
// var authorityInfo = new
// {
// Pwd = "xfs@#123hd??1>>|12#4",
// MacAdr = new LocalServer.Controllers.LocalServerController(
// Context.Factory
// ).GetMacAddress()
// };
// Context.RemoteSocketSendMsg(authorityInfo);
// }
// }
// /// <summary>
// /// 3. 文件比较
// /// </summary>
// /// <param name="context"></param>
// public class DirFilesDiffState(LocalSyncServer context) : StateHelpBase(context)
// {
// public override void HandleRemoteMsg(SyncMsg? msg)
// {
// if (msg == null)
// {
// return;
// }
// else
// {
// if (msg.IsSuccess)
// {
// var state = new LocalPackAndUploadState(Context);
// state.PackDiffDir(msg);
// Context.StateHelper = state;
// }
// else
// {
// throw new Exception(msg.Body);
// }
// }
// }
// public override void HandleLocalMsg(SyncMsg? msg) { }
// public void SendSyncConfigToRemote()
// {
// Context.RemoteSocketSendMsg(
// Context.SyncConfig
// ?? throw new NullReferenceException("SyncConfig should't be null here!")
// );
// }
// }
// /// <summary>
// /// 4. 本地打包并上传
// /// </summary>
// /// <param name="context"></param>
// public class LocalPackAndUploadState(LocalSyncServer context) : StateHelpBase(context)
// {
// public override void HandleRemoteMsg(SyncMsg? msg)
// {
// if (msg == null)
// {
// return;
// }
// else { }
// }
// public override void HandleLocalMsg(SyncMsg? msg) { }
// /// <summary>
// /// 打包文件
// /// </summary>
// /// <param name="msg"></param>
// /// <exception cref="Exception"></exception>
// public void PackDiffDir(SyncMsg msg)
// {
// if (msg.IsSuccess)
// {
// var diff = JsonSerializer.Deserialize<Dir>(msg.Body);
// Context.LocalSocketSendMsg(new SyncMsg(SyncMsgType.Success, "文件打包完成!"));
// Context.LocalSocketSendMsg(new SyncMsg(SyncMsgType.Success, "文件上传完成!"));
// }
// else
// {
// throw new Exception(msg.Body);
// }
// }
// private void UploadPackedFiles(string absolutePath)
// {
// //TODO 传递上传进度到前端。
// }
// }
// /// <summary>
// /// 5. 目标服务器解包并发布
// /// </summary>
// /// <param name="context"></param>
// public class RemoteUnPackAndReleaseState(LocalSyncServer context) : StateHelpBase(context)
// {
// public override void HandleRemoteMsg(SyncMsg? msg)
// {
// if (msg == null)
// {
// return;
// }
// else { }
// }
// public override void HandleLocalMsg(SyncMsg? msg) { }
// }

View file

@ -24,8 +24,6 @@ public class SyncFilesController(RemoteSyncServerFactory factory, SqliteDbContex
var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync();
var pipeLine = new WebSocPipeLine<WebSocket>(webSocket, true);
await Factory.CreateRemoteSyncServer(pipeLine, Name);
var x = 11;
}
else
{
@ -43,127 +41,11 @@ public class SyncFilesController(RemoteSyncServerFactory factory, SqliteDbContex
HttpContext.Response.StatusCode = StatusCodes.Status400BadRequest;
}
}
[HttpGet("/GetSyncFilesLogs")]
public IActionResult GetSyncFilesLogs(
string? ClientName,
int? Status,
DateTime? SyncTimeStart,
DateTime? SyncTimeEnd,
int page,
int rows
)
{
var item =
from i in _db.SyncLogHeads
where
(
string.IsNullOrEmpty(ClientName)
|| (i.ClientName != null && i.ClientName.Contains(ClientName))
)
&& (Status == null || i.Status == Status)
&& (SyncTimeStart == null || i.SyncTime >= SyncTimeStart)
&& (SyncTimeEnd == null || i.SyncTime <= SyncTimeEnd)
orderby i.Id descending
select new
{
Head = i,
Files = (from j in _db.SyncLogFiles where j.HeadId == i.Id select j).ToList()
};
return Ok(item.Skip((page - 1) * rows).Take(rows).ToList());
}
public class InputFileInfo
{
public required string RelativePath { get; set; }
public DateTime MTime { get; set; }
}
public class OutputFileInfo : InputFileInfo
{
/// <summary>
/// 0 新增 1 修改 2 删除
/// 上传文件
/// </summary>
public int ServerOpType { get; set; }
}
public class ServerOpFileInfo : OutputFileInfo
{
public required string ServerRootDirPath { get; set; }
public required string ClientRootDirPath { get; set; }
}
public class InputFiles
{
public required string ServerRootDirPath { get; set; }
/// <summary>
/// 0 special 1 exclude
/// </summary>
public int Type { get; set; }
public List<FileInfo>? Files { get; set; }
}
public class ServerOpFiles
{
public required string ServerRootDirPath { get; set; }
public string? ClientRootDirPath { get; set; }
public List<OutputFileInfo>? Files { get; set; }
}
[HttpPost("/GetFilesInfoByDir")]
public IActionResult GetFilesInfoByDir([FromBody] InputFiles inputFiles)
{
return Ok(new { IsSuccess = true });
}
[HttpPost("/InitASync")]
public IActionResult InitASync([FromBody] SyncLogHead head)
{
try
{
var CurrentSyncTaskCount = (
from i in _db.SyncLogHeads
where i.Status == 0
select i
).Count();
if (CurrentSyncTaskCount > 0)
{
throw new Exception("存在未完成的任务,请等待完成!");
}
head.Id = Guid.NewGuid();
head.SyncTime = DateTime.Now;
head.Status = 0;
_db.SyncLogHeads.Add(head);
_db.SaveChanges();
return Ok(new { IsSuccess = true, head.Id });
}
catch (Exception e)
{
return Ok(new { IsSuccess = false, e.Message });
}
}
[HttpGet("/CloseASync")]
public IActionResult CloseASync(Guid Id, string Message, int Status)
{
try
{
var current =
(from i in _db.SyncLogHeads where i.Id == Id select i).FirstOrDefault()
?? throw new Exception("任务不存在!");
current.Status = Status;
current.Message = Message;
_db.SaveChanges();
return Ok(new { IsSuccess = true });
}
catch (Exception e)
{
return Ok(new { IsSuccess = false, e.Message });
}
}
/// <param name="file"></param>
/// <returns></returns>
[HttpPost("/UploadFile")]
public async Task<IActionResult> UploadFile(IFormFile file)
{
@ -199,4 +81,124 @@ public class SyncFilesController(RemoteSyncServerFactory factory, SqliteDbContex
return StatusCode(500, new { IsSuccess = false, Message = $"上传文件失败: {ex.Message}" });
}
}
// [HttpGet("/GetSyncFilesLogs")]
// public IActionResult GetSyncFilesLogs(
// string? ClientName,
// int? Status,
// DateTime? SyncTimeStart,
// DateTime? SyncTimeEnd,
// int page,
// int rows
// )
// {
// var item =
// from i in _db.SyncLogHeads
// where
// (
// string.IsNullOrEmpty(ClientName)
// || (i.ClientName != null && i.ClientName.Contains(ClientName))
// )
// && (Status == null || i.Status == Status)
// && (SyncTimeStart == null || i.SyncTime >= SyncTimeStart)
// && (SyncTimeEnd == null || i.SyncTime <= SyncTimeEnd)
// orderby i.Id descending
// select new
// {
// Head = i,
// Files = (from j in _db.SyncLogFiles where j.HeadId == i.Id select j).ToList()
// };
// return Ok(item.Skip((page - 1) * rows).Take(rows).ToList());
// }
// public class InputFileInfo
// {
// public required string RelativePath { get; set; }
// public DateTime MTime { get; set; }
// }
// public class OutputFileInfo : InputFileInfo
// {
// /// <summary>
// /// 0 新增 1 修改 2 删除
// /// </summary>
// public int ServerOpType { get; set; }
// }
// public class ServerOpFileInfo : OutputFileInfo
// {
// public required string ServerRootDirPath { get; set; }
// public required string ClientRootDirPath { get; set; }
// }
// public class InputFiles
// {
// public required string ServerRootDirPath { get; set; }
// /// <summary>
// /// 0 special 1 exclude
// /// </summary>
// public int Type { get; set; }
// public List<FileInfo>? Files { get; set; }
// }
// public class ServerOpFiles
// {
// public required string ServerRootDirPath { get; set; }
// public string? ClientRootDirPath { get; set; }
// public List<OutputFileInfo>? Files { get; set; }
// }
// [HttpPost("/GetFilesInfoByDir")]
// public IActionResult GetFilesInfoByDir([FromBody] InputFiles inputFiles)
// {
// return Ok(new { IsSuccess = true });
// }
// [HttpPost("/InitASync")]
// public IActionResult InitASync([FromBody] SyncLogHead head)
// {
// try
// {
// var CurrentSyncTaskCount = (
// from i in _db.SyncLogHeads
// where i.Status == 0
// select i
// ).Count();
// if (CurrentSyncTaskCount > 0)
// {
// throw new Exception("存在未完成的任务,请等待完成!");
// }
// head.Id = Guid.NewGuid();
// head.SyncTime = DateTime.Now;
// head.Status = 0;
// _db.SyncLogHeads.Add(head);
// _db.SaveChanges();
// return Ok(new { IsSuccess = true, head.Id });
// }
// catch (Exception e)
// {
// return Ok(new { IsSuccess = false, e.Message });
// }
// }
// [HttpGet("/CloseASync")]
// public IActionResult CloseASync(Guid Id, string Message, int Status)
// {
// try
// {
// var current =
// (from i in _db.SyncLogHeads where i.Id == Id select i).FirstOrDefault()
// ?? throw new Exception("任务不存在!");
// current.Status = Status;
// current.Message = Message;
// _db.SaveChanges();
// return Ok(new { IsSuccess = true });
// }
// catch (Exception e)
// {
// return Ok(new { IsSuccess = false, e.Message });
// }
// }
}

View file

@ -10,10 +10,6 @@ ConfigurationBuilder configurationBuilder = new();
// Add services to the container.
//添加配置文件路径
RemoteSyncServerFactory.NamePwd =
[
.. (builder.Configuration.GetSection("NamePwds").Get<Tuple<string, string>[]>() ?? [])
];
foreach (var x in builder.Configuration.GetSection("NamePwds").GetChildren())
{
var it = x.GetChildren();

View file

@ -7,6 +7,10 @@ public class RemoteSyncServerFactory
private readonly object Lock = new();
#pragma warning disable CA2211 // Non-constant fields should not be visible
/// <summary>
/// 发布的名称和密码
/// </summary>
public static List<Tuple<string, string>> NamePwd = [];
#pragma warning restore CA2211 // Non-constant fields should not be visible

View file

@ -6,13 +6,6 @@ using Common;
namespace RemoteServer;
// enum StateWhenMsg
// {
// Authority = 0,
// ConfigInfo = 1,
// LocalPackAndUpload = 2,
// RemoteUnPackAndRelease = 3,
// }
public abstract class StateHelpBase(
RemoteSyncServer context,
@ -151,8 +144,6 @@ public class FinallyPublishHelper(RemoteSyncServer context)
public void FinallyPublish()
{
// 发布数据库
if (Context.NotNullSyncConfig.IsDeployDb)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
var arguments =
@ -191,11 +182,6 @@ public class FinallyPublishHelper(RemoteSyncServer context)
}
}
else
{
throw new NotSupportedException("只支持windows!");
}
}
else
{
Context.Pipe.SendMsg(CreateMsg("跳过数据库发布!")).Wait();
}

View file

@ -1,3 +1,4 @@
using System.Runtime.InteropServices;
using System.Text.Json;
using Common;
using LocalServer;
@ -12,6 +13,9 @@ public class PipeTest
{
[Fact]
public async void TestCase()
{
//msbuild 只能在windows上跑
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
var p1 = new TestPipe(false, "1");
var x = Task.Run(async () =>
@ -20,10 +24,12 @@ public class PipeTest
(byte[] b) =>
{
var msg = JsonSerializer.Deserialize<SyncMsg>(b);
#pragma warning disable CS8602 // Dereference of a possibly null reference.
if (msg.Body == "·¢²¼Íê³É£¡")
{
p1.Close("正常退出!");
_ = p1.Close("正常退出!");
}
#pragma warning restore CS8602 // Dereference of a possibly null reference.
Console.WriteLine(b);
return true;
}
@ -43,7 +49,8 @@ public class PipeTest
p3.Other = p4;
p4.Other = p3;
LocalSyncServer.TempRootFile = "D:/FileSyncTest/stemp";
RemoteSyncServer.SqlPackageAbPath = "C:\\Users\\ZHAOLEI\\.dotnet\\tools\\sqlpackage.exe";
RemoteSyncServer.SqlPackageAbPath =
"C:\\Users\\ZHAOLEI\\.dotnet\\tools\\sqlpackage.exe";
//LocalSyncServer.MsdeployAbPath =
// "C:\\Program Files\\IIS\\Microsoft Web Deploy V3\\msdeploy.exe";
LocalSyncServer.SqlPackageAbPath = "C:\\Users\\ZHAOLEI\\.dotnet\\tools\\sqlpackage.exe";
@ -77,4 +84,5 @@ public class PipeTest
Assert.Fail(p1.ErrResult);
}
}
}
}

View file

@ -15,7 +15,9 @@ namespace ServerTest
public TestPipe? Other;
public string? ErrResult;
public string Id = id;
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
public static RemoteSyncServerFactory syncServerFactory;
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
public override async IAsyncEnumerable<int> Work(
Func<byte[], bool> receiveCb,
@ -44,7 +46,7 @@ namespace ServerTest
//}
Task.Run(() =>
{
var it = syncServerFactory.GetServerByName("Test");
var it = syncServerFactory.GetServerByName("Test")?? throw new NullReferenceException("找不到服务名称!");
var h = new UnPackAndReleaseHelper(it);
it.SetStateHelpBase(h);
h.UnPack();