trigger-user-save.js 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. // https://docs.authing.co/v2/reference/sdk-for-node/management/UsersManagementClient.html
  2. const { ManagementClient } = require('authing-node-sdk')
  3. const managementClient = new ManagementClient({
  4. accessKeyId: '6686bffb373d06911e24a969',
  5. accessKeySecret: "4e978331675938d1bc81fb109e67d59a",
  6. host: 'https://textbook.u2-dev.hep.com.cn', // 应用的认证地址
  7. })
  8. /**
  9. * 用户创建前,创建用户至Authing
  10. * @desc 仅同步注册信息及密码,资料在afterSave中同步
  11. */
  12. export function defineUserBeforeSave(){
  13. Parse.Cloud.beforeSave("_User", async (request) => {
  14. request.object = appendUserACL(request.object)
  15. let user = request.object;
  16. // 仅首次注册/创建用户/修改密码有password属性,同步Authing账号
  17. let password = user?.get("password");
  18. if(password){
  19. let mobile = user?.get("mobile");
  20. let email = user?.get("email");
  21. let username = user?.get("username");
  22. let externalId = user?.id;
  23. let authingUserExists = await findUserByMobileEmailUserName(user)
  24. if(authingUserExists?.statusCode==404){ // 创建用户
  25. let newuser = {
  26. status:"Activated",
  27. }
  28. if(mobile){newuser.phone = mobile}
  29. if(email){newuser.email = email}
  30. if(username){newuser.username = username}
  31. if(externalId){newuser.externalId = externalId}
  32. result = await managementClient.createUser(newuser)
  33. }
  34. if(authingUserExists?.statusCode==200){
  35. let existsUser = authingUserExists?.data;
  36. try{
  37. let updateRes = await managementClient.updateUser({
  38. userId:existsUser?.userId,
  39. password:password,
  40. })
  41. // console.log(result)
  42. }catch(err){console.log(err)}
  43. }
  44. }
  45. });
  46. }
  47. function appendUserACL(user){
  48. let acl = user?.getACL();
  49. if(!acl) acl = new Parse.ACL();
  50. // 添加superadmin用户的可读可写权限
  51. acl.setRoleWriteAccess("superadmin", true);
  52. acl.setRoleReadAccess("superadmin", true);
  53. // 添加admin用户的可读可写权限
  54. acl.setRoleWriteAccess("admin", true);
  55. acl.setRoleReadAccess("admin", true);
  56. // 添加manager用户的可读可写权限
  57. acl.setRoleWriteAccess("manager", true);
  58. acl.setRoleReadAccess("manager", true);
  59. // 添加公共可读权限
  60. acl.setPublicReadAccess(true);
  61. user.setACL(acl);
  62. return user
  63. }
  64. /**
  65. * 用户删除前,删除用户从Authing
  66. */
  67. export function defineUserBeforeDelete(){
  68. Parse.Cloud.afterDelete("_User", async (request) => {
  69. let user = request.object;
  70. // console.log(user.toJSON());
  71. // console.log(user?.get("password"))
  72. try{
  73. let authingUserExists = await findUserByMobileEmailUserName(user)
  74. if(authingUserExists?.statusCode==200){
  75. let existsUser = authingUserExists?.data;
  76. let deleteRes = await managementClient.deleteUsersBatch({
  77. // 替换用户 ID 数组
  78. userIds: [existsUser.userId],
  79. options: {
  80. userIdType: "user_id"
  81. }
  82. });
  83. }
  84. }catch(deleteErr){}
  85. // 直接给予删除权限
  86. // if(request?.master){
  87. // return await object.destroy({useMasterKey:true})
  88. // }
  89. // let requestUser = request.user;
  90. // if(!requestUser?.id){
  91. // throw new Parse.Error(206,"Insufficient auth.")
  92. // }
  93. // let query = new Parse.Query("_Role");
  94. // query.equalTo("users",requestUser)
  95. // let roles = await query.find({useMasterKey:true});
  96. // let acl = request.object.getACL();
  97. // if(!acl){
  98. // throw new Parse.Error(206,"Object has no ACL.")
  99. // }
  100. // if(acl.getWriteAccess(requestUser)){
  101. // return await request.object.destroy({useMasterKey:true})
  102. // }else{
  103. // let hasPermission = roles.some(role=>acl.getRoleWriteAccess(role.getName()))
  104. // if(hasPermission) {
  105. // return await request.object.destroy({useMasterKey:true})
  106. // }
  107. // throw new Parse.Error(206,"Insufficient auth.")
  108. // }
  109. });
  110. }
  111. /**
  112. * 用户保存后同步数据至Authing
  113. */
  114. export function defineUserAfterSave(){
  115. Parse.Cloud.afterSave("_User", async (request) => {
  116. // console.log("save _User",request?.object?.id)
  117. let query = new Parse.Query("Profile");
  118. query.equalTo("user",request?.object?.id)
  119. let profile = await query.first();
  120. syncUserProfileToAuthing(request?.object,profile)
  121. });
  122. Parse.Cloud.afterSave("Profile", async (request) => {
  123. // console.log("save Profile",request?.object?.id)
  124. let query = new Parse.Query("Profile");
  125. let userPointer = request?.object?.get("user")
  126. query.include("user");
  127. console.log(userPointer)
  128. profile = await query.get(request?.object?.id,{useMasterKey:true});
  129. syncUserProfileToAuthing(profile.get("user"),profile)
  130. appandUserToRole(profile.get("user")?.toPointer() || userPointer,profile?.get("identity"))
  131. });
  132. }
  133. // 同步Profile角色身份
  134. var roleNameMap = {
  135. "国家级管理员":"superadmin",
  136. "工作联系人":"admin",
  137. "高校联系人":"manager",
  138. }
  139. async function appandUserToRole(user,roleName) {
  140. console.log(user,roleName)
  141. roleName = roleNameMap[roleName] || roleName
  142. let id = user?.id || user?.objectId
  143. if(!id || !roleName) return
  144. let userObj = new Parse.User();
  145. userObj.id = id;
  146. let query = new Parse.Query(Parse.Role);
  147. query.equalTo("name", roleName);
  148. try{
  149. let role = await query.first({ useMasterKey: true });
  150. console.log(role?.toJSON())
  151. if (role?.toJSON()?.name) {
  152. let usersRelation = role.relation("users");
  153. usersRelation.add(userObj);
  154. await role.save(null, { useMasterKey: true });
  155. let users = await usersRelation.query().find({ useMasterKey: true });
  156. console.log('Users in role after addition:', users.map(u => u.toJSON()));
  157. }
  158. }catch(err){
  159. console.error(err)
  160. }
  161. }
  162. /**
  163. * 查询用户
  164. * @param {*} user
  165. * @returns
  166. * 不存在:
  167. * {
  168. statusCode: 404,
  169. apiCode: 2004,
  170. message: '用户不存在',
  171. requestId: 'e59cb407-f2d9-4bd8-ac93-d2dbc8d6ab72'
  172. }
  173. {
  174. statusCode: 200,
  175. message: '',
  176. data: {
  177. userId: '669676e5a3a9ac870bfff2a3',
  178. createdAt: '2024-07-16T13:34:29.789Z',
  179. updatedAt: '2024-07-16T13:34:29.789Z',
  180. status: 'Activated'
  181. }
  182. }
  183. */
  184. async function findUserByMobileEmailUserName(user){
  185. let mobile = user?.get("mobile");
  186. let email = user?.get("email");
  187. let username = user?.get("username");
  188. let externalId = user?.id;
  189. let result;
  190. if(email){
  191. try{
  192. result = await managementClient.getUser({userIdType:`email`,userId:email})
  193. // console.log(email,result)
  194. }catch(err){}
  195. }
  196. if(mobile&&(!result || result?.statusCode==404)){
  197. try{
  198. result = await managementClient.getUser({userIdType:`phone`,userId:mobile})
  199. // console.log(mobile,result)
  200. }catch(err){}
  201. }
  202. if(username&&(!result || result?.statusCode==404)){
  203. try{
  204. result = await managementClient.getUser({userIdType:`username`,userId:username})
  205. // console.log("username",username,result)
  206. }catch(err){}
  207. }
  208. if(externalId&&(!result || result?.statusCode==404)){
  209. try{
  210. result = await managementClient.getUser({userIdType:`external_id`,userId:externalId})
  211. // console.log(externalId,result)
  212. }catch(err){}
  213. }
  214. return result
  215. }
  216. async function syncUserProfileToAuthing(user,profile){
  217. if(!user?.id) return
  218. let userInfo = user.toJSON();
  219. userInfo = fixJsonFileds(userInfo)
  220. if(profile?.id){
  221. let pjson = profile.toJSON();
  222. delete pjson.objectId;
  223. pjson= fixJsonFileds(pjson)
  224. Object.keys(pjson).forEach(key=>{
  225. userInfo[key] = pjson[key]
  226. })
  227. }
  228. // 映射对应字段
  229. userInfo.company = userInfo.companyName
  230. delete userInfo.companyName
  231. userInfo.userType = userInfo.identity
  232. delete userInfo.identity
  233. userInfo.userId = userInfo.objectId
  234. let authingUserExists = await findUserByMobileEmailUserName(user)
  235. if(authingUserExists?.statusCode==200){
  236. let existsUser = authingUserExists?.data;
  237. userInfo.userId = existsUser.userId
  238. }
  239. delete userInfo.objectId
  240. userInfo.identifyStatus = userInfo.accountState
  241. // 自定义数据全量同步
  242. userInfo.customData = JSON.parse(JSON.stringify(userInfo))
  243. // {
  244. // identifyStatus : userInfo.accountState
  245. // }
  246. // console.log(userInfo)
  247. // 同步数据至Authing用户池
  248. let result
  249. try{
  250. result = await managementClient.updateUser(userInfo)
  251. // console.log(result)
  252. }catch(err){console.log(err)}
  253. }
  254. function fixJsonFileds(json){
  255. // Parse独有关系数据
  256. delete json.ACL
  257. delete json.className
  258. delete json.sessionToken
  259. delete json.company
  260. delete json.user
  261. delete json.createdAt
  262. delete json.updatedAt
  263. // 来自Authing的数据
  264. delete json?.loginsCount
  265. delete json?.lastIP
  266. delete json?.lastLogin
  267. return json
  268. }