account-security.js 2.5 KB

123456789101112131415161718192021222324252627282930313233
  1. function mayMigrateLegacyPassword(target) {
  2. return !!target && target.get('legacyPasswordMigrationAllowed') === true && target.get('passwordResetRequired') !== true && !target.get('isDisabled') && !target.get('isDeleted');
  3. }
  4. async function migrateLegacyLogin(username,password) {
  5. const original=await migratedLoginTarget(username);
  6. if(!mayMigrateLegacyPassword(original)) fail(401,'账号或密码错误;如首次登录旧账号,请联系管理员重置密码');
  7. const revision=Number(original.get('credentialRevision')||0);
  8. const legacyLoginName=String(original.get('username')||username);
  9. const verified=await verifyLegacyPassword(legacyLoginName,password),target=await migratedLoginTarget(username,verified);
  10. if(!target || target.id!==original.id || !mayMigrateLegacyPassword(target)) fail(401,'账号验证未通过');
  11. target.set('credentialExpectedRevision',revision);target.set('credentialMigrationAttempt',true);
  12. target.setPassword(password);await target.save(null,{useMasterKey:true});
  13. return Parse.User.logIn(String(target.get('username')),password);
  14. }
  15. async function changeAppPassword(input,current) {
  16. const oldPassword=String(input.currentPassword||''),password=String(input.newPassword||'');
  17. if(!oldPassword || password.length<8 || password.length>72)fail(400,'请输入当前密码及 8 至 72 位新密码');
  18. if(oldPassword===password)fail(400,'新密码不能与当前密码相同');
  19. const revision=Number(current.get('credentialRevision')||0);
  20. let verified;try{verified=await Parse.User.logIn(String(current.get('username')),oldPassword);}catch(error){if(Number(error.code)===101)fail(400,'当前密码不正确');throw error;}
  21. if(verified.id!==current.id)fail(403,'账号验证未通过');
  22. current.set('credentialExpectedRevision',revision);current.setPassword(password);current.set('passwordResetRequired',false);
  23. try{await current.save(null,{useMasterKey:true});await revokeUserSessions(current);}finally{
  24. // Reauthentication may have issued a temporary session even when saving failed.
  25. const q=new Parse.Query('_Session');q.equalTo('sessionToken',verified.getSessionToken());await Parse.Object.destroyAll(await q.find({useMasterKey:true}),{useMasterKey:true});
  26. }
  27. return {changed:true,loginRequired:true};
  28. }
  29. async function logoutAppSession(request,current) {
  30. const token=String(request.body?.token||'');
  31. if(token){const q=new Parse.Query('_Session');q.equalTo('user',current);q.equalTo('sessionToken',token);await Parse.Object.destroyAll(await q.find({useMasterKey:true}),{useMasterKey:true});}
  32. return {loggedOut:true};
  33. }