123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299 |
- // https://docs.authing.co/v2/reference/sdk-for-node/management/UsersManagementClient.html
- const { ManagementClient } = require('authing-node-sdk')
- const managementClient = new ManagementClient({
- accessKeyId: '669b25e1731d50c59f5494d1',
- accessKeySecret: "4cfc095a72a67e22065c97e90054315c",
- host: 'https://textbook.u2-dev.hep.com.cn', // 应用的认证地址
- })
- /**
- * 用户创建前,创建用户至Authing
- * @desc 仅同步注册信息及密码,资料在afterSave中同步
- * @example
- * 注册:
- curl -X POST -H "Content-Type: application/json" -H "X-Parse-Application-Id: edu-textbook" -d '{
- "username": "333",
- "password": "333"
- }' http://127.0.0.1:61337/parse/users
- * 删除:
- */
- export function defineUserBeforeSave(){
- Parse.Cloud.beforeSave("_User", async (request) => {
- // console.log("UserBeforeSave")
- request.object = appendUserACL(request.object)
- let user = request.object;
- // 仅首次注册/创建用户/修改密码有password属性,同步Authing账号
- let password = user?.get("password");
- // console.log(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)
- // console.log(authingUserExists)
- if(authingUserExists?.statusCode==404){ // 创建用户
- let newuser = {
- status:"Activated",
- password:password,
- }
- if(mobile){newuser.phone = mobile}
- if(email){newuser.email = email}
- if(username){newuser.username = username}
- if(externalId){newuser.externalId = externalId}
- // console.log(newuser)
- 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.setRoleWriteAccess("superadmin", true);
- acl.setRoleReadAccess("superadmin", true);
- // 添加admin用户的可读可写权限
- acl.setRoleWriteAccess("admin", true);
- acl.setRoleReadAccess("admin", true);
- // 添加manager用户的可读可写权限
- acl.setRoleWriteAccess("manager", true);
- acl.setRoleReadAccess("manager", true);
-
- // 添加公共可读权限
- acl.setPublicReadAccess(true);
- user.setACL(acl);
- return user
- }
- /**
- * 用户删除前,删除用户从Authing
- */
- export function defineUserAfterDelete(){
- Parse.Cloud.afterDelete("_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){}
- // 直接给予删除权限
- // if(request?.master){
- // return await object.destroy({useMasterKey:true})
- // }
- // let requestUser = request.user;
- // if(!requestUser?.id){
- // throw new Parse.Error(206,"Insufficient auth.")
- // }
- // let query = new Parse.Query("_Role");
- // query.equalTo("users",requestUser)
- // let roles = await query.find({useMasterKey:true});
- // let acl = request.object.getACL();
- // if(!acl){
- // throw new Parse.Error(206,"Object has no ACL.")
- // }
- // if(acl.getWriteAccess(requestUser)){
- // return await request.object.destroy({useMasterKey:true})
- // }else{
- // let hasPermission = roles.some(role=>acl.getRoleWriteAccess(role.getName()))
- // if(hasPermission) {
- // return await request.object.destroy({useMasterKey:true})
- // }
- // throw new Parse.Error(206,"Insufficient auth.")
- // }
- });
- }
- /**
- * 用户保存后同步数据至Authing
- */
- export function defineUserAfterSave(){
- Parse.Cloud.afterSave("_User", async (request) => {
- // console.log("save _User",request?.object?.id)
- let query = new Parse.Query("Profile");
- query.equalTo("user",request?.object?.id)
- let profile = await query.first();
- syncUserProfileToAuthing(request?.object,profile)
- });
- Parse.Cloud.afterSave("Profile", async (request) => {
- // console.log("save Profile",request?.object?.id)
- let query = new Parse.Query("Profile");
- let userPointer = request?.object?.get("user")
- query.include("user");
- // console.log(userPointer)
- profile = await query.get(request?.object?.id,{useMasterKey:true});
- syncUserProfileToAuthing(profile.get("user"),profile)
- appandUserToRole(profile.get("user")?.toPointer() || userPointer,profile?.get("identity"))
- });
- }
- // 同步Profile角色身份
- var roleNameMap = {
- "国家级管理员":"superadmin",
- "工作联系人":"admin",
- "高校联系人":"manager",
- }
- async function appandUserToRole(user,roleName) {
- // console.log(user,roleName)
- roleName = roleNameMap[roleName] || roleName
- let id = user?.id || user?.objectId
- if(!id || !roleName) return
- let userObj = new Parse.User();
- userObj.id = id;
- let query = new Parse.Query(Parse.Role);
- query.equalTo("name", roleName);
- try{
- let role = await query.first({ useMasterKey: true });
- // console.log(role?.toJSON())
- if (role?.toJSON()?.name) {
- let usersRelation = role.relation("users");
- usersRelation.add(userObj);
- await role.save(null, { useMasterKey: true });
- let users = await usersRelation.query().find({ useMasterKey: true });
- // console.log('Users in role after addition:', users.map(u => u.toJSON()));
- }
- }catch(err){
- console.error(err)
- }
- }
- /**
- * 查询用户
- * @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
- let userInfo = user.toJSON();
- userInfo = fixJsonFileds(userInfo)
- if(profile?.id){
- let pjson = profile.toJSON();
- delete pjson.objectId;
- pjson= fixJsonFileds(pjson)
- Object.keys(pjson).forEach(key=>{
- userInfo[key] = pjson[key]
- })
- }
- // 映射对应字段
- userInfo.company = userInfo.companyName
- delete userInfo.companyName
- 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
- // 自定义数据全量同步
- userInfo.customData = JSON.parse(JSON.stringify(userInfo))
- // {
- // identifyStatus : userInfo.accountState
- // }
- // console.log(userInfo)
- // 同步数据至Authing用户池
- let result
- try{
- result = await managementClient.updateUser(userInfo)
- // console.log(result)
- }catch(err){console.log(err)}
- }
- function fixJsonFileds(json){
- // Parse独有关系数据
- delete json.ACL
- delete json.className
- delete json.sessionToken
- delete json.company
- delete json.user
- delete json.createdAt
- delete json.updatedAt
- // 来自Authing的数据
- delete json?.loginsCount
- delete json?.lastIP
- delete json?.lastLogin
- return json
- }
|