import $http from '@/utils/http-service';
import $sensitive, { reauthHandler } from '@/utils/sensitive';
import {
IUserInfo,
ILoginRule,
IError,
ISaveUser,
IResponseUserData,
ICustError,
IUsersInfo,
IAddUser,
IBackError,
IUserId
} from '../pages/User/models/type';
import { USER_ROLES, UnDeleteUsers, PasswordFailedProp } from '../pages/User/models/model';
import UserInfoService from '@/services/user-info.service';
import { traduction } from '@/utils/language';
const idList = [
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'10',
'11',
'12',
'13',
'14',
'15',
'16',
'17'
];
import { UI_REST_FIRMWAREINVENTORY } from '@/api/api';
import { importRsaPublicKey, rsaEncrypt, arrayBufferToHexStr } from '@/utils/crypto';
import { getStoreData } from '@/utils/composition';
export default class LocaluserService {
public static userInfo: UserInfoService = new UserInfoService();
public static setUserState(item: IResponseUserData, user: IUsersInfo, admins: any, resArr: any) {
* 设置可删除状态和禁用启动状态
* 1. 只有1个管理员,紧急用户无删除,其他场景由Oem.Huawei.Deleteable值决定
* 2. 只有1个管理员,紧急用户无法被禁用,其他场景可以被禁用
* 3. 禁用的鼠标提示默认不显示
* 4. 当只有1个管理员时,禁用鼠标提示显示
*/
if (admins.length <= 1 && item.RoleID === USER_ROLES.ADMINISTRATOR && item.Enabled) {
user.canDeleted = false;
user.canDisabled = false;
user.canDisbledTipSHow = true;
user.unDeletedReason = traduction('USER_UNDELETED_LAST');
user.unDisabledReason = traduction('USER_UNDELETED_LAST');
} else {
const delDisableReason = item.DelDisableReason;
if (delDisableReason) {
if (delDisableReason === UnDeleteUsers.SSHLOGIN) {
user.unDeletedReason = '';
} else if (delDisableReason === UnDeleteUsers.TRAPV3USER && !item.Deleteable) {
user.unDeletedReason = traduction('USER_UNDELETED_TRAPV3');
} else if (delDisableReason === UnDeleteUsers.EMERGENCYUSER) {
user.unDeletedReason = traduction('USER_UNDELETED_URGENT');
} else {
user.unDeletedReason = '';
}
}
const emergencyUser = resArr[1].emergencyLoginUser;
if (emergencyUser === item.UserName) {
user.canDeleted = false;
user.canDisabled = false;
user.deleteableTip = traduction('USER_UNDELETED_LAST');
} else {
user.canDeleted = item.Deleteable;
}
}
}
public static initUserItem(item: IResponseUserData) {
const rules: string[] = item.LoginRule.map((rule: string) => {
return rule.split('/').reverse().shift()?.[0] || '';
});
return {
id: item.ID,
userName: item.UserName,
roleId: item.RoleID,
loginInterface: item.LoginInterface,
loginRole: rules,
validate: item.PasswordValidityDays,
sshPublicKeyHash: item.SSHPublicKeyHash || '',
state: item.Enabled,
canDeleted: true,
canDisabled: true,
canDisbledTipSHow: false,
unDeletedReason: '',
unDisabledReason: '',
isTrapV3: item?.DelDisableReason === 'TrapV3User' && item?.Deleteable
};
}
public static getUserList(): Promise<IUsersInfo[]> {
return new Promise((resolve, reject) => {
Promise.all([this.getUsedIdList(), this.getPwdCheck()])
.then((resArr: any[]) => {
const members = resArr[0];
const resultArr: IUsersInfo[] = [];
const admins = members.filter((item: IResponseUserData) => {
return item.RoleID === USER_ROLES.ADMINISTRATOR && item.Enabled;
});
members.forEach((item: IResponseUserData) => {
const user: IUsersInfo = this.initUserItem(item);
this.setUserState(item, user, admins, resArr);
resultArr.push(user);
});
resolve(resultArr);
})
.catch(error => {
reject(error);
});
});
}
public static getUsedIdList(): Promise<IResponseUserData[]> {
return new Promise((resolve, reject) => {
$http
.get('/UI/Rest/AccessMgnt/Accounts')
.then((res: any) => {
resolve(res.data.Members);
})
.catch(error => {
reject(error);
});
});
}
public static getPwdCheck(): Promise<{
pwdCheck: boolean;
emergencyLoginUser: string;
minPwdLen: number;
firstLoginEnabled: boolean;
localNamePattern: any;
allowedLoginInterfaces: any;
}> {
return new Promise((resolve, reject) => {
$http
.get('/UI/Rest/AccessMgnt/AdvancedSecurity')
.then((res: any) => {
let escapedStr = '';
if (res.data?.LocalAccountNamePattern) {
escapedStr = res.data.LocalAccountNamePattern.replace(
/[\n\r\t\b\v\f\\]/g,
(match: string) => {
return {
'\n': '\\n',
'\r': '\\r',
'\t': '\\t',
'\b': '\\b',
'\v': '\\v',
'\f': '\\f',
'\\': '\\\\'
}[match];
}
);
}
resolve({
pwdCheck: res.data.PasswordComplexityCheckEnabled,
emergencyLoginUser: res.data.EmergencyLoginUser,
minPwdLen: res.data.MinimumPasswordLength,
firstLoginEnabled: res.data.InitialPasswordNeedModify,
allowedLoginInterfaces: res.data.AllowedLoginInterfaces || {},
localNamePattern: escapedStr || ''
});
})
.catch(error => {
reject(error);
});
});
}
public static getRules(): Promise<ILoginRule[]> {
return new Promise((resolve, reject) => {
$http
.get('/UI/Rest/AccessMgnt/LoginRule')
.then((res: any) => {
const ruleArr: ILoginRule[] = [];
res.data.Members.forEach((item: { [key: string]: any }, index: number) => {
const ruleItem: ILoginRule = {
id: item.ID + 1,
checked: false,
ruleEnabled: item.Status,
startTime: item.StartTime,
endTime: item.EndTime,
ip: item.IP,
mac: item.Mac,
active: index === 0 ? true : false
};
ruleArr.push(ruleItem);
});
resolve(ruleArr);
})
.catch(error => {
reject(error);
});
});
}
public static getUserInfo(id: number): Promise<IUserInfo> {
return new Promise((resolve, reject) => {
this.getUsedIdList()
.then((res: IResponseUserData[]) => {
const userMsg = res.filter((item: IResponseUserData) => {
return item.ID === id;
})[0];
const user: IUserInfo = {
RoleId: userMsg?.RoleID,
LoginInterface: userMsg?.LoginInterface,
LoginRule: userMsg?.LoginRule,
UserName: userMsg?.UserName,
AuthProtocol: userMsg?.SnmpV3AuthProtocol || 'SHA256',
EncryProtocol: userMsg?.SnmpV3PrivProtocol || 'AES',
SNMPEncryptPwdInit: userMsg?.SNMPEncryptPwdInit,
FirstLoginPolicy: userMsg?.FirstLoginPolicy
};
resolve(user);
})
.catch(error => reject(error));
});
}
public static getAddUserParams(): Promise<any> {
return new Promise((resolve, reject) => {
Promise.all([this.getUsedIdList(), this.getPwdCheck()])
.then((resArr: any[]) => {
const members = resArr[0] || [];
const tempArr: any[] = [];
let firstLoginResetSupport = false;
const idListCopy: string[] = [...idList];
members.forEach((item: any) => {
if (!firstLoginResetSupport && item.FirstLoginPolicy !== undefined) {
firstLoginResetSupport = true;
}
const position: number = idListCopy.indexOf(String(item.ID));
if (position > -1) {
idListCopy.splice(position, 1);
}
});
idListCopy.forEach(item => {
const tempId: IUserId = {
id: item,
label: item
};
tempArr.push(tempId);
});
const pwdCheck = resArr[1].pwdCheck;
const firstLoginEnabled = resArr[1].firstLoginEnabled;
const result = {
pwdCheck,
firstLoginEnabled,
userIdList: tempArr,
firstLoginResetSupport,
minPwdLen: resArr[1].minPwdLen,
localNamePattern: resArr[1].localNamePattern,
allowedLoginInterfaces: resArr[1].allowedLoginInterfaces
};
resolve(result);
})
.catch((error: any) => {
reject(error);
});
});
}
public static getEditUserParams(userId: number): Promise<any> {
return new Promise((resolve, reject) => {
Promise.all([this.getPwdCheck(), this.getUserInfo(userId)])
.then(resArr => {
if (resArr[1].FirstLoginPolicy === 0) {
resArr[1].FirstLoginPolicy = 1;
}
const pwdCheck = resArr[0].pwdCheck;
const firstLoginEnabled = resArr[0].firstLoginEnabled;
const userMsg = {
roleId: resArr[1].RoleId,
interfaceList: resArr[1].LoginInterface,
loginRule: resArr[1].LoginRule,
userName: resArr[1].UserName,
authProtocol: resArr[1].AuthProtocol,
encryProtocol: resArr[1].EncryProtocol,
firstLoginPolicy: resArr[1].FirstLoginPolicy
};
const snmpv3PwdInit = resArr[1].SNMPEncryptPwdInit;
const result = {
pwdCheck,
firstLoginEnabled,
userInfo: userMsg,
snmpv3PwdInit,
minPwdLen: resArr[0].minPwdLen,
localNamePattern: resArr[0].localNamePattern,
allowedLoginInterfaces: resArr[0].allowedLoginInterfaces
};
resolve(result);
})
.catch((error: any) => {
reject(error);
});
});
}
public static async addUserParamGen(
key: string,
param: IAddUser,
password: string
): Promise<any> {
const pubKey = await importRsaPublicKey(key, 'SHA-1');
const encUser = arrayBufferToHexStr(await rsaEncrypt(param.UserName, pubKey));
const encPwd = arrayBufferToHexStr(await rsaEncrypt(param.Password, pubKey));
const ret: Record<string, any> = {
ID: param.Id,
RoleID: param.RoleId,
UserName: encUser,
Password: encPwd,
FirstLoginPolicy: param.FirstLoginPolicy
};
if (password !== '') {
let base64Password = window.btoa(password);
ret.ReauthKey = arrayBufferToHexStr(await rsaEncrypt(base64Password, pubKey));
}
if ((param.LoginInterface || []).length > 0) {
ret.LoginInterface = param.LoginInterface;
}
if ((param.LoginRule || '').length > 0) {
ret.LoginRule = param.LoginRule;
}
return ret;
}
public static async addUserSensitive(param: IAddUser, password: string): Promise<any> {
const encryptedPaths = ['UserName', 'Password', 'ReauthKey'];
return await $sensitive(encryptedPaths, key =>
LocaluserService.addUserParamGen(key, param, password)
).post('/UI/Rest/AccessMgnt/Accounts');
}
public static addUser(param: IAddUser, password: string): Promise<ICustError> {
* 新增用户的逻辑如下
* 1.对ID为参数值的对象赋值密码,角色,用户名
* 2.对ID为参数值的用户设置规则和接口
* 3.2步骤必须等到1步骤操作成功后才执行
*/
return new Promise((resolve, reject) => {
LocaluserService.addUserSensitive(param, password)
.then(() => {
resolve({
type: 'success',
errors: null
});
})
.catch(error => {
const custError: IError[] = this.packingErrorMsg(error.data.error);
reject({
type: 'error',
errors: custError
});
});
});
}
public static async editUserParamGen(
key: string,
param: ISaveUser,
password: string
): Promise<any> {
const pubKey = await importRsaPublicKey(key, 'SHA-1');
const encUser = param.UserName
? arrayBufferToHexStr(await rsaEncrypt(param.UserName, pubKey))
: undefined;
const encPwd = param.Password
? arrayBufferToHexStr(await rsaEncrypt(param.Password, pubKey))
: undefined;
const params: { [key: string]: any } = {
Password: encPwd,
RoleID: param.RoleId,
UserName: encUser
};
this.changeParams(param, params);
const encSnmpV3PrivPasswd = param.SNMPV3Password
? arrayBufferToHexStr(await rsaEncrypt(param.SNMPV3Password, pubKey))
: undefined;
params.SNMPV3PrivPasswd = encSnmpV3PrivPasswd;
for (const k in params) {
if (Object.prototype.hasOwnProperty.call(params, k)) {
const value = params[k];
if (value === undefined) {
delete params[k];
}
}
}
if (password !== '') {
params.ReauthKey = arrayBufferToHexStr(await rsaEncrypt(window.btoa(password), pubKey));
}
return params;
}
public static async editUserSensitive(param: ISaveUser, password: string): Promise<any> {
const encryptedPaths = ['UserName', 'Password', 'ReauthKey', 'SNMPV3PrivPasswd'];
return await $sensitive(encryptedPaths, key =>
LocaluserService.editUserParamGen(key, param, password)
).patch(`/UI/Rest/AccessMgnt/Accounts/${param.Id}`);
}
public static editUser(param: ISaveUser, password: string): Promise<ICustError> {
return new Promise((resolve, reject) => {
LocaluserService.editUserSensitive(param, password)
.then(res => {
let result: ICustError | null = null;
if (res.data.error) {
const custError: IError[] = this.packingErrorMsg(res.data.error);
result = { type: 'someFailed', errors: custError };
} else {
result = { type: 'success', errors: null };
}
resolve(result);
})
.catch(error => {
const custError: IError[] = this.packingErrorMsg(error.data.error);
reject({ type: 'error', errors: custError });
});
});
}
public static changeParams(param: any, params: any) {
if (param.LoginInterface) {
params.LoginInterface = param.LoginInterface;
}
if (param.LoginRule) {
params.LoginRule = param.LoginRule;
}
if (param.SNMPV3Password) {
params.SNMPV3PrivPasswd = param.SNMPV3Password;
}
if (param.SnmpV3AuthProtocol) {
params.SnmpV3AuthProtocol = param.SnmpV3AuthProtocol;
}
if (param.SnmpV3PrivProtocol) {
params.SnmpV3PrivProtocol = param.SnmpV3PrivProtocol;
}
if (param.FirstLoginPolicy) {
params.FirstLoginPolicy = param.FirstLoginPolicy;
}
}
public static async deleteUserParamGen(
key: string,
password: string,
userId: string
): Promise<any> {
let params: any = {
RequestMethod: 'DELETE',
ID: userId
};
if (password !== '') {
const pubKey = await importRsaPublicKey(key, 'SHA-1');
params.ReauthKey = arrayBufferToHexStr(await rsaEncrypt(window.btoa(password), pubKey));
}
return params;
}
public static async deleteUserSensitive(userId: string, password: string): Promise<any> {
const allowHttpDelete = getStoreData('loct', 'allowHttpDelete');
const extraParams = {
RequestMethod: 'DELETE',
ID: userId
};
return (await allowHttpDelete)
? reauthHandler({ ReauthKey: btoa(password) }).delete(
`/UI/Rest/AccessMgnt/Accounts/${userId}`
)
: reauthHandler({ ReauthKey: btoa(password), ...extraParams }).post(
'/UI/Rest/AccessMgnt/Accounts',
{ ReauthKey: btoa(password), ...extraParams }
);
}
public static deleteUser(userId: string, password: string): Promise<ICustError> {
return new Promise((resolve, reject) => {
LocaluserService.deleteUserSensitive(userId, password)
.then(() => {
resolve({
type: 'success',
errors: null
});
})
.catch(error => {
const custError: IError[] = this.packingErrorMsg(error.data.error);
reject({ type: 'error', errors: custError });
});
});
}
public static async modifyUserParamGen(
key: string,
password: string,
state: boolean
): Promise<any> {
const params: { [key: string]: any } = {
Enabled: state
};
if (password !== '') {
const pubKey = await importRsaPublicKey(key, 'SHA-1');
params.ReauthKey = arrayBufferToHexStr(await rsaEncrypt(window.btoa(password), pubKey));
}
return params;
}
public static async modifyUserSensitive(
userId: string,
password: string,
state: boolean
): Promise<any> {
const encryptedPaths = ['ReauthKey'];
return await $sensitive(encryptedPaths, key =>
LocaluserService.modifyUserParamGen(key, password, state)
).patch(`/UI/Rest/AccessMgnt/Accounts/${userId}`);
}
public static modifyUserState(
userId: string,
password: string,
state: boolean
): Promise<ICustError> {
return new Promise((resolve, reject) => {
LocaluserService.modifyUserSensitive(userId, password, state)
.then(() => {
resolve({
type: 'success',
errors: null
});
})
.catch(error => {
const custError: IError[] = this.packingErrorMsg(error.data.error);
reject({ type: 'error', errors: custError });
});
});
}
public static uploadCerFile(formData: FormData) {
return $http.post(UI_REST_FIRMWAREINVENTORY, formData);
}
public static uploadFile(param: {
userId: number;
secPwd: string;
Content?: string;
type: string;
}): Promise<ICustError> {
return new Promise((resolve, reject) => {
const url = `/UI/Rest/AccessMgnt/Accounts/${param.userId}/ImportSSHPublicKey`;
$sensitive(['ReauthKey'], async key => {
const pubKey = await importRsaPublicKey(key, 'SHA-1');
const params = {
ReauthKey: arrayBufferToHexStr(await rsaEncrypt(param.secPwd, pubKey)),
Content: param.type === 'Text' ? param.Content : `/tmp/web/${param.Content}`,
Type: param.type
};
return params;
})
.post(url)
.then(() => {
resolve({
type: 'success',
errors: null
});
})
.catch(error => {
reject(error);
});
});
}
public static deleteSSHKey(userId: string, password: string): Promise<ICustError> {
const allowHttpDelete = getStoreData('loct', 'allowHttpDelete');
return new Promise((resolve, reject) => {
const url = `/UI/Rest/AccessMgnt/Accounts/${userId}/DeleteSSHPublicKey`;
const httpMethod = allowHttpDelete ? 'delete' : 'post';
$sensitive(['ReauthKey'], async key => {
let params = {};
if (password !== '') {
const pubKey = await importRsaPublicKey(key, 'SHA-1');
params = {
ReauthKey: arrayBufferToHexStr(await rsaEncrypt(window.btoa(password), pubKey))
};
}
return params;
})
[httpMethod](url)
.then(() => {
resolve({
type: 'success',
errors: null
});
})
.catch(error => {
const custError: IError[] = this.packingErrorMsg(error.data.error);
reject({ type: 'error', errors: custError });
});
});
}
private static packingErrorMsg(error: IBackError[]): IError[] {
const extendedInfo = error;
const errorData: IError[] = [];
extendedInfo.forEach(errorItem => {
const errorId = errorItem.code;
let relatedProp = '';
if (errorItem?.relatedProperties?.[0]) {
relatedProp = errorItem.relatedProperties[0].slice(2);
}
if (errorItem.message && errorItem.message.indexOf(PasswordFailedProp.PASSWORDPROP) > -1) {
relatedProp = PasswordFailedProp.PASSWORD;
}
if (
errorItem.message &&
errorItem.message.indexOf(PasswordFailedProp.SNMPV3PASSWORDPROP) > -1
) {
relatedProp = PasswordFailedProp.SNMPV3PASSWORD;
}
const temp: IError = {
errorId,
relatedProp
};
errorData.push(temp);
});
return errorData;
}
}