oak-general-business/lib/features/token.js

372 lines
13 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Token = void 0;
const Feature_1 = require("oak-frontend-base/es/types/Feature");
const Exception_1 = require("oak-domain/lib/types/Exception");
const Projection_1 = require("../types/Projection");
const Exception_2 = require("../types/Exception");
const constants_1 = require("../config/constants");
const lodash_1 = require("oak-domain/lib/utils/lodash");
class Token extends Feature_1.Feature {
tokenValue;
environment;
cache;
storage;
application;
async loadSavedToken() {
this.tokenValue = await this.storage.load(constants_1.LOCAL_STORAGE_KEYS.token);
await this.refreshTokenData(this.tokenValue);
this.publish();
}
constructor(cache, storage, environment, application) {
super();
this.cache = cache;
this.storage = storage;
this.environment = environment;
this.application = application;
this.tokenValue = ''; // 置个空字符串代表还在load storage缓存的数据
// this.loadSavedToken();
application.subscribe(() => this.loadSavedToken());
if (process.env.OAK_PLATFORM === 'web' && (process.env.NODE_ENV !== 'development' || process.env.OAK_DEV_MODE === 'server')) {
// 纯前台模式 多窗口时不监听storage
// 在web下可能多窗口一个窗口更新了token其它窗口应跟着变
window.addEventListener('storage', async (e) => {
if (e.key === constants_1.LOCAL_STORAGE_KEYS.token) {
this.tokenValue = e.newValue
? JSON.parse(e.newValue)
: undefined;
await this.refreshTokenData(this.tokenValue);
this.publish();
}
});
}
}
checkNeedSetPassword() {
const user = this.getUserInfo();
const { system } = this.application.getApplication();
const { Security } = system.config;
if (Security?.level === 'strong' && user && !user.hasPassword) {
return Promise.reject(new Exception_2.OakPasswordUnset());
}
}
async refreshTokenData(tokenValue) {
if (!tokenValue) {
this.tokenValue = undefined;
return;
}
const env = await this.environment.getEnv();
try {
const applicationId = this.application.getApplicationId();
const { result } = await this.cache.exec('refreshToken', {
tokenValue,
env,
applicationId,
}, undefined, true, true);
if (tokenValue !== result) {
// 如果返回空字符串token被disabledtokenValue置为undefined
if (result) {
this.tokenValue = result;
await this.storage.save(constants_1.LOCAL_STORAGE_KEYS.token, result);
this.checkNeedSetPassword();
}
else {
this.removeToken(true);
}
}
else {
this.checkNeedSetPassword();
}
}
catch (err) {
// refresh出了任何错都无视(排除网络异常)直接放弃此token
console.warn(err);
if (err instanceof Exception_1.OakNetworkException ||
err instanceof Exception_1.OakServerProxyException ||
err instanceof Exception_1.OakRequestTimeoutException ||
err instanceof Exception_1.OakClockDriftException) {
return;
}
this.removeToken(true);
}
}
async loginByMobile(mobile, captcha, disableRegister) {
const env = await this.environment.getEnv();
const { result } = await this.cache.exec('loginByMobile', {
mobile,
captcha,
disableRegister,
env,
}, undefined, true);
this.tokenValue = result;
await this.storage.save(constants_1.LOCAL_STORAGE_KEYS.token, result);
this.publish();
this.checkNeedSetPassword();
}
async loginByEmail(email, captcha, disableRegister) {
const env = await this.environment.getEnv();
const { result } = await this.cache.exec('loginByEmail', {
email,
captcha,
disableRegister,
env,
}, undefined, true);
this.tokenValue = result;
await this.storage.save(constants_1.LOCAL_STORAGE_KEYS.token, result);
this.publish();
this.checkNeedSetPassword();
}
async loginByAccount(account, password) {
const env = await this.environment.getEnv();
const { result } = await this.cache.exec('loginByAccount', {
account,
password,
env,
}, undefined, true);
this.tokenValue = result;
await this.storage.save(constants_1.LOCAL_STORAGE_KEYS.token, result);
this.publish();
this.checkNeedSetPassword();
}
async bindByMobile(mobile, captcha) {
const env = await this.environment.getEnv();
await this.cache.exec('bindByMobile', {
mobile,
captcha,
env,
}, undefined, true);
this.publish();
}
async bindByEmail(email, captcha) {
const env = await this.environment.getEnv();
await this.cache.exec('bindByEmail', {
email,
captcha,
env,
}, undefined, true);
this.publish();
}
async loginWebByMpToken(mpToken) {
const env = await this.environment.getEnv();
const { result } = await this.cache.exec('loginWebByMpToken', {
mpToken,
env,
}, undefined, true);
this.tokenValue = result;
await this.storage.save(constants_1.LOCAL_STORAGE_KEYS.token, result);
this.publish();
this.checkNeedSetPassword();
}
async loginByWechatInWebEnv(wechatLoginId) {
const env = await this.environment.getEnv();
const { result } = await this.cache.exec('loginByWechat', {
env: env,
wechatLoginId,
});
this.tokenValue = result;
await this.storage.save(constants_1.LOCAL_STORAGE_KEYS.token, result);
this.publish();
this.checkNeedSetPassword();
}
async loginByOAuth(code, state) {
const env = await this.environment.getEnv();
const { result } = await this.cache.exec('loginByOauth', {
env: env,
code,
state,
});
this.tokenValue = result;
await this.storage.save(constants_1.LOCAL_STORAGE_KEYS.token, result);
this.publish();
this.checkNeedSetPassword();
}
async loginWechat(code, params) {
const env = await this.environment.getEnv();
const { result } = await this.cache.exec('loginWechat', {
code,
env: env,
wechatLoginId: params?.wechatLoginId,
});
this.tokenValue = result;
await this.storage.save(constants_1.LOCAL_STORAGE_KEYS.token, result);
this.publish();
this.checkNeedSetPassword();
}
async loginWechatMp() {
const { code } = await wx.login();
const env = await this.environment.getEnv();
const { result } = await this.cache.exec('loginWechatMp', {
code,
env: env,
});
this.tokenValue = result;
await this.storage.save(constants_1.LOCAL_STORAGE_KEYS.token, result);
this.publish();
this.checkNeedSetPassword();
}
async loginWechatNative(code) {
const env = await this.environment.getEnv();
const { result } = await this.cache.exec('loginWechatNative', {
code,
env: env,
});
this.tokenValue = result;
await this.storage.save(constants_1.LOCAL_STORAGE_KEYS.token, result);
this.publish();
this.checkNeedSetPassword();
}
async syncUserInfoWechatMp() {
// 2.27.1及以上版本不再支持getUserProfile(返回头像为【灰色头像】,昵称为【微信用户】)
const info = await wx.getUserProfile({
desc: '同步微信昵称和头像信息',
});
const { userInfo: { nickName: nickname, avatarUrl }, encryptedData, signature, iv, } = info;
await this.cache.exec('syncUserInfoWechatMp', {
nickname,
avatarUrl,
encryptedData,
signature,
iv,
});
this.publish();
}
async logout(dontPublish) {
await this.cache.exec('logout', {
tokenValue: this.tokenValue,
}, undefined, undefined, true);
this.removeToken(dontPublish);
}
removeToken(dontPublish) {
this.tokenValue = undefined;
this.storage.remove(constants_1.LOCAL_STORAGE_KEYS.token);
if (!dontPublish) {
this.publish();
}
}
getTokenValue() {
if (this.tokenValue === '') {
throw new Exception_2.OakUserInfoLoadingException();
}
return this.tokenValue;
}
getToken(allowUnloggedIn) {
if (this.tokenValue === '') {
throw new Exception_2.OakUserInfoLoadingException();
}
if (this.tokenValue) {
const token = this.cache.get('token', {
data: (0, lodash_1.cloneDeep)(Projection_1.tokenProjection),
filter: {
value: this.tokenValue,
},
})[0];
if (!token) {
if (allowUnloggedIn) {
return undefined;
}
throw new Exception_2.OakUserInfoLoadingException();
}
return token;
}
if (allowUnloggedIn) {
return undefined;
}
throw new Exception_1.OakUnloggedInException();
}
getUserId(allowUnloggedIn) {
const token = this.getToken(allowUnloggedIn);
if (token?.userId) {
return token.userId;
}
}
// getUserInfo 不要求登录
getUserInfo() {
const token = this.getToken(true);
if (token?.user) {
return token.user;
}
}
isRoot() {
const token = this.getToken(true);
return !!token?.user?.isRoot;
}
/**
* 这个是指token的player到底是不是root
* @returns
*/
isReallyRoot() {
const token = this.getToken(true);
return !!token?.player?.isRoot;
}
isSelf() {
const token = this.getToken();
return token?.playerId === token?.userId;
}
async sendCaptcha(origin, content, type) {
const env = await this.environment.getEnv();
if (origin === 'mobile') {
const { result } = await this.cache.exec('sendCaptchaByMobile', {
mobile: content,
env: env,
type,
});
return result;
}
else {
const { result } = await this.cache.exec('sendCaptchaByEmail', {
email: content,
env: env,
type,
});
return result;
}
}
async switchTo(userId) {
const currentUserId = this.getUserId();
if (currentUserId === userId) {
throw new Exception_1.OakPreConditionUnsetException('您已经是当前用户');
}
await this.cache.exec('switchTo', {
userId,
});
this.publish();
}
async refreshWechatPublicUserInfo() {
await this.cache.exec('refreshWechatPublicUserInfo', {});
}
async getWechatMpUserPhoneNumber(code) {
const env = await this.environment.getEnv();
await this.cache.exec('getWechatMpUserPhoneNumber', {
code,
env: env,
});
}
async wakeupParasite(id) {
const env = await this.environment.getEnv();
const { result } = await this.cache.exec('wakeupParasite', {
id,
env: env,
});
this.tokenValue = result;
await this.storage.save(constants_1.LOCAL_STORAGE_KEYS.token, result);
this.publish();
}
needVerifyPassword() {
const user = this.getUserInfo();
const { system } = this.application.getApplication();
const { Security } = system.config;
if (Security && ['strong', 'medium'].includes(Security.level)) {
// 对于安全要求中高的系统,需要检查其验证密码时间
const stamp = Date.now() - Security.passwordVerifyGap;
return user?.hasPassword && user.verifyPasswordAt < stamp;
}
}
async verifyPassword(password) {
const env = this.environment.getEnv();
await this.cache.exec('verifyPassword', {
password,
env,
});
}
}
exports.Token = Token;