-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathSystemService.cs
More file actions
172 lines (153 loc) · 6.38 KB
/
Copy pathSystemService.cs
File metadata and controls
172 lines (153 loc) · 6.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
using AppBoxCore;
using AppBoxStore;
using AppBoxStore.Entities;
namespace AppBoxServer;
/// <summary>
/// 系统内置的一些服务,如初始化存储、密码Hash等
/// </summary>
internal sealed class SystemService : IService
{
private static readonly ModelId AdminPermissionId =
ModelId.Make(Consts.SYS_APP_ID, ModelType.Permission, 1, ModelLayer.SYS);
private static void EnsureIsAdmin()
{
if (!RuntimeContext.HasPermission(AdminPermissionId))
throw new Exception("Must login as Administrator");
}
/// <summary>
/// 用户登录时验证并返回组织单元的路径
/// </summary>
internal static async Task<TreePath> Login(string user, string password)
{
if (string.IsNullOrEmpty(user) || string.IsNullOrEmpty(password))
throw new Exception("用户名或密码为空");
//查找账号
var q = new SqlQuery<Employee>(Employee.MODELID);
q.Where(e => e.F(nameof(Employee.Account)) == user);
var emp = await q.ToSingleAsync();
if (emp == null)
throw new Exception("用户不存在");
if (emp.Password == null)
throw new Exception("用户密码不存在");
//验证密码
if (!RuntimeContext.PasswordHasher!.VerifyHashedPassword(emp.Password, password))
throw new Exception("密码错误");
//查找对应的组织单元
var q1 = new SqlQuery<OrgUnit>(OrgUnit.MODELID);
q1.Where(t => t.F(nameof(OrgUnit.Id)) == emp.Id);
var ous = await q1.ToListAsync();
if (ous.Count == 0)
throw new Exception("用户不在组织内");
var q2 = new SqlQuery<OrgUnit>(OrgUnit.MODELID);
q2.Where(t => t.F(nameof(OrgUnit.Id)) == ous[0].Id); //暂始终取第一个组织单元
var path = await q2.ToTreePathAsync(
t => t.R(nameof(OrgUnit.Parent), OrgUnit.MODELID),
t => t.F(nameof(OrgUnit.Name)));
return path!;
}
/// <summary>
/// 用于前端组织结构权限管理界面加载整个权限树
/// </summary>
private static async Task<IList<PermissionNode>> LoadPermissionTree()
{
var list = new List<PermissionNode>();
var apps = await MetaStore.LoadAllApplicationAsync();
//TODO:考虑排序
var folders = await MetaStore.LoadAllPermissionFolderAsync();
var permissions = await MetaStore.LoadAllPermissionAsync();
foreach (var app in apps)
{
var appNode = new PermissionNode
{ Name = app.Name, Children = new List<PermissionNode>() };
list.Add(appNode);
var folderIndex = new Dictionary<Guid, PermissionNode>();
//加载文件夹
var rootFolder = folders.SingleOrDefault(t => t.AppId == app.Id);
if (rootFolder != null)
LoopAddFolder(folderIndex, appNode, rootFolder);
//加载PermissionModels
var appPermissions = permissions.Where(t => t.AppId == app.Id);
foreach (var permission in appPermissions)
{
var node = new PermissionNode
{
Name = permission.Name,
ModelId = permission.Id.ToString(),
OrgUnits = permission.OrgUnits
};
if (permission.FolderId.HasValue &&
folderIndex.TryGetValue(permission.FolderId.Value, out var folderNode))
{
folderNode.Children!.Add(node);
}
else
{
appNode.Children.Add(node);
}
}
}
return list;
}
private static void LoopAddFolder(IDictionary<Guid, PermissionNode> dic, PermissionNode parent,
ModelFolder folder)
{
var parentNode = parent;
if (folder.Parent != null)
{
var node = new PermissionNode
{ Name = folder.Name!, Children = new List<PermissionNode>() };
dic.Add(folder.Id, node);
parent.Children!.Add(node);
parentNode = node;
}
if (folder.HasChildren)
{
for (var i = 0; i < folder.Children.Count; i++)
{
LoopAddFolder(dic, parentNode, folder.Children[i]);
}
}
}
/// <summary>
/// 保存单个PermissionModel的权限变更
/// </summary>
private static async Task<bool> SavePermission(string modelId, IList<Guid>? ouids)
{
EnsureIsAdmin();
var oldModel = (PermissionModel)await MetaStore.Provider.LoadModelAsync(modelId);
if (oldModel == null)
throw new Exception("Can't find PermissionModel");
//开始重置
oldModel.OrgUnits.Clear();
if (ouids != null)
{
foreach (var ouid in ouids)
{
oldModel.OrgUnits.Add(ouid);
}
}
//保存权限模型
await using var txn = await SqlStore.Default.BeginTransactionAsync();
await MetaStore.Provider.UpdateModelAsync(oldModel, txn);
await txn.CommitAsync();
//更新本地模型缓存
RuntimeContext.Current.InvalidModelsCache(null, [oldModel.Id], true);
//TODO: 激发事件通知集群更新缓存
return true;
}
public async ValueTask<AnyValue> InvokeAsync<T>(ReadOnlyMemory<char> method, T args)
where T : struct, IAnyArgs => method.Span switch
{
//@formatter:off
nameof(Login) => AnyValue.From(await Login(args.GetString()!, args.GetString()!)),
"GetViewAssemblies" => AnyValue.From(await MetaStore.Provider.LoadViewAssembliesAsync(args.GetString()!)),
"LoadAppAssembly" => AnyValue.From(await MetaStore.Provider.LoadAppAssemblyAsync(args.GetString()!)),
"LoadDynamicViewJson" => AnyValue.From( await MetaStore.Provider.LoadDynamicViewJsonAsync(args.GetLong()!.Value)),
"LoadDynamicWidgets" => AnyValue.From(await MetaStore.Provider.LoadDynamicWidgetsAsync()),
"HasPermission" => AnyValue.From(RuntimeContext.HasPermission(args.GetLong()!.Value)),
nameof(LoadPermissionTree) => AnyValue.From(await LoadPermissionTree()),
nameof(SavePermission) => AnyValue.From(await SavePermission(args.GetString()!, args.GetArray<Guid>())),
_ => throw new Exception($"Can't find method: {method}")
//@formatter:on
};
}