Просмотр исходного кода

Merge branch 'master' of http://git.fmode.cn:3000/bin/edu-textbook

warrior 8 месяцев назад
Родитель
Сommit
0ae04ca4f5
4 измененных файлов с 184 добавлено и 1 удалено
  1. 9 0
      README.md
  2. 150 0
      server/cloud/authing/trigger-user-save.js
  3. 22 0
      server/db/data/init-data.sql.js
  4. 3 1
      server/server.js

+ 9 - 0
README.md

@@ -15,6 +15,15 @@ npm run start
 ```
 
 
+## 本地开发调试
+/server
+
+``` bash
+npx vite build
+cp .\dist\server\server.js temp-server.js
+node temp-server.js --local
+```
+
 ## 线上开发环境
 - 服务器
     - root@8.140.98.43

+ 150 - 0
server/cloud/authing/trigger-user-save.js

@@ -1,3 +1,4 @@
+// https://docs.authing.co/v2/reference/sdk-for-node/management/UsersManagementClient.html
 const { ManagementClient } = require('authing-node-sdk')
 const managementClient  = new ManagementClient({
     accessKeyId: '6686bffb373d06911e24a969',
@@ -5,6 +6,95 @@ const managementClient  = new ManagementClient({
     host: 'https://textbook.u2-dev.hep.com.cn', // 应用的认证地址
 })
 
+
+/**
+ * 用户创建前,创建用户至Authing
+ * @desc 仅同步注册信息及密码,资料在afterSave中同步
+ */
+export function defineUserBeforeSave(){
+    Parse.Cloud.beforeSave("_User", async (request) => {
+        request.object = appendUserACL(request.object)
+        let user = request.object;
+        // 仅首次注册/创建用户/修改密码有password属性,同步Authing账号
+        let password = user?.get("password");
+        if(password){
+            let mobile = user?.get("mobile");
+            let email = user?.get("email");
+            let username = user?.get("username");
+            let externalId = user?.id;
+            let authingUserExists = await findUserByMobileEmailUserName(user)
+            if(authingUserExists?.statusCode==404){ // 创建用户
+                let newuser = {
+                    status:"Activated",
+                }
+                if(mobile){newuser.phone = mobile}
+                if(email){newuser.email = email}
+                if(username){newuser.username = username}
+                if(externalId){newuser.externalId = externalId}
+
+                result = await managementClient.createUser(newuser)
+            }
+            if(authingUserExists?.statusCode==200){
+                let existsUser = authingUserExists?.data;
+                try{
+                    let updateRes = await managementClient.updateUser({
+                        userId:existsUser?.userId,
+                        password:password,
+                    })
+                    // console.log(result)
+                }catch(err){console.log(err)}
+            }
+        }
+    });
+}
+function appendUserACL(user){
+    let acl = user?.getACL();
+    if(!acl) acl = new Parse.ACL();
+
+    // 添加superadmin用户的可读可写权限
+    acl.setWriteAccess("superadmin", true);
+    acl.setReadAccess("superadmin", true);
+
+    // 添加admin用户的可读可写权限
+    acl.setWriteAccess("admin", true);
+    acl.setReadAccess("admin", true);
+
+    // 添加manager用户的可读可写权限
+    acl.setWriteAccess("manager", true);
+    acl.setReadAccess("manager", true);
+    
+    // 添加公共可读权限
+    acl.setPublicReadAccess(true);
+
+    user.setACL(acl);
+    return user
+}
+/**
+ * 用户删除前,删除用户从Authing
+ */
+ export function defineUserBeforeDelete(){
+    Parse.Cloud.beforeDelete("_User", async (request) => {
+        let user = request.object;
+        // console.log(user.toJSON());
+        // console.log(user?.get("password"))
+            try{
+                let authingUserExists = await findUserByMobileEmailUserName(user)
+                if(authingUserExists?.statusCode==200){
+                    let existsUser = authingUserExists?.data;
+                        let deleteRes = await managementClient.deleteUsersBatch({
+                            // 替换用户 ID 数组
+                            userIds: [existsUser.userId],
+                            options: {
+                                userIdType: "user_id"
+                            }
+                        });
+                }
+            }catch(deleteErr){}
+        });
+}
+/**
+ * 用户保存后同步数据至Authing
+ */
 export function defineUserAfterSave(){
     Parse.Cloud.afterSave("_User", async (request) => {
         // console.log("save _User",request?.object?.id)
@@ -24,6 +114,61 @@ export function defineUserAfterSave(){
     });
 }
 
+/**
+ * 查询用户
+ * @param {*} user 
+ * @returns 
+ * 不存在:
+ *  {
+        statusCode: 404,
+        apiCode: 2004,
+        message: '用户不存在',
+        requestId: 'e59cb407-f2d9-4bd8-ac93-d2dbc8d6ab72'
+    }
+
+    {
+        statusCode: 200,
+        message: '',
+        data: {
+            userId: '669676e5a3a9ac870bfff2a3',
+            createdAt: '2024-07-16T13:34:29.789Z',
+            updatedAt: '2024-07-16T13:34:29.789Z',
+            status: 'Activated'
+        }
+    }
+ */
+async function findUserByMobileEmailUserName(user){
+    let mobile = user?.get("mobile");
+    let email = user?.get("email");
+    let username = user?.get("username");
+    let externalId = user?.id;
+    let result;
+    if(email){
+        try{
+            result = await managementClient.getUser({userIdType:`email`,userId:email})
+            // console.log(email,result)
+        }catch(err){}
+    } 
+    if(mobile&&(!result || result?.statusCode==404)){
+        try{
+            result = await managementClient.getUser({userIdType:`phone`,userId:mobile})
+            // console.log(mobile,result)
+        }catch(err){}
+    }
+    if(username&&(!result || result?.statusCode==404)){
+        try{
+            result = await managementClient.getUser({userIdType:`username`,userId:username})
+            // console.log("username",username,result)
+        }catch(err){}
+    }
+    if(externalId&&(!result || result?.statusCode==404)){
+        try{
+            result = await managementClient.getUser({userIdType:`external_id`,userId:externalId})
+            // console.log(externalId,result)
+        }catch(err){}
+    }
+    return result
+}
 
 async function syncUserProfileToAuthing(user,profile){
     if(!user?.id) return
@@ -43,6 +188,11 @@ async function syncUserProfileToAuthing(user,profile){
     userInfo.userType = userInfo.identity
     delete userInfo.identity
     userInfo.userId = userInfo.objectId
+    let authingUserExists = await findUserByMobileEmailUserName(user)
+    if(authingUserExists?.statusCode==200){
+        let existsUser = authingUserExists?.data;
+        userInfo.userId = existsUser.userId
+    }
     delete userInfo.objectId
     userInfo.identifyStatus = userInfo.accountState
     // 自定义数据全量同步

+ 22 - 0
server/db/data/init-data.sql.js

@@ -30,6 +30,28 @@ SET
 "company" = excluded."company",
 "createdAt"=excluded."createdAt";
 
+-- 初始化管理员角色
+INSERT INTO "_Role" ("objectId","title", "name", "_rperm", "_wperm", "company", "createdAt", "updatedAt")
+VALUES
+('ADMININITI','管理员', 'admin','{*,6684b5464b9206e48dbcf67c}','{6684b5464b9206e48dbcf67c}','RbIKpmuaMC','2024-06-16 12:00:00','2024-06-16 12:00:00')
+ON conflict("objectId") DO UPDATE
+SET 
+"title" = excluded."title",
+"name" = excluded."name",
+"company" = excluded."company",
+"createdAt"=excluded."createdAt";
+
+-- 初始化操作员角色
+INSERT INTO "_Role" ("objectId","title", "name", "_rperm", "_wperm", "company", "createdAt", "updatedAt")
+VALUES
+('MANAGERINT','操作员', 'manager','{*,6684b5464b9206e48dbcf67c}','{6684b5464b9206e48dbcf67c}','RbIKpmuaMC','2024-06-16 12:00:00','2024-06-16 12:00:00')
+ON conflict("objectId") DO UPDATE
+SET 
+"title" = excluded."title",
+"name" = excluded."name",
+"company" = excluded."company",
+"createdAt"=excluded."createdAt";
+
 -- 超级管理员帐号,添加至超管用户组
 INSERT INTO "_Join:users:_Role" ("relatedId", "owningId")
 VALUES

+ 3 - 1
server/server.js

@@ -44,7 +44,7 @@ global.config["LOCAL"] = argv.local || process.env["LOCAL"] || appConfig["LOCAL"
 
 import  {textbookRouter} from "./api/textbook/routes";
 import { defineAliOssSTS } from "./cloud/aliyun"
-import { defineAuthingLogin } from "./cloud/authing"
+import { defineAuthingLogin, defineUserBeforeDelete, defineUserBeforeSave } from "./cloud/authing"
 import { defineAuthingDepartSync } from "./cloud/authing"
 import { defineUserAfterSave } from "./cloud/authing"
 import { importData } from "./db/func/import-data"
@@ -182,6 +182,8 @@ async function initParseAndDatabase(){
       defineAuthingDepartSync();
       defineAliOssSTS();
       defineUserAfterSave();
+      defineUserBeforeSave();
+      defineUserBeforeDelete();
     });
  
     console.log("正在启动管理看板...")