1// Copyright (C) 2019 Storj Labs, Inc.
2// See LICENSE for copying information.
3
4import { StoreModule } from '@/store';
5import { DisableMFARequest, UpdatedUser, User, UsersApi } from '@/types/users';
6import { MetaUtils } from '@/utils/meta';
7
8export const USER_ACTIONS = {
9    UPDATE: 'updateUser',
10    GET: 'getUser',
11    ENABLE_USER_MFA: 'enableUserMFA',
12    DISABLE_USER_MFA: 'disableUserMFA',
13    GENERATE_USER_MFA_SECRET: 'generateUserMFASecret',
14    GENERATE_USER_MFA_RECOVERY_CODES: 'generateUserMFARecoveryCodes',
15    CLEAR: 'clearUser',
16};
17
18export const USER_MUTATIONS = {
19    SET_USER: 'setUser',
20    SET_USER_MFA_SECRET: 'setUserMFASecret',
21    SET_USER_MFA_RECOVERY_CODES: 'setUserMFARecoveryCodes',
22    UPDATE_USER: 'updateUser',
23    CLEAR: 'clearUser',
24};
25
26export class UsersState {
27    public user: User = new User();
28    public userMFASecret = '';
29    public userMFARecoveryCodes: string[] = [];
30}
31
32const {
33    GET,
34    UPDATE,
35    ENABLE_USER_MFA,
36    DISABLE_USER_MFA,
37    GENERATE_USER_MFA_SECRET,
38    GENERATE_USER_MFA_RECOVERY_CODES,
39} = USER_ACTIONS;
40
41const {
42    SET_USER,
43    UPDATE_USER,
44    SET_USER_MFA_SECRET,
45    SET_USER_MFA_RECOVERY_CODES,
46    CLEAR,
47} = USER_MUTATIONS;
48
49interface UsersContext {
50    state: UsersState
51    commit: (string, ...unknown) => void
52}
53
54/**
55 * creates users module with all dependencies
56 *
57 * @param api - users api
58 */
59export function makeUsersModule(api: UsersApi): StoreModule<UsersState, UsersContext> {
60    return {
61        state: new UsersState(),
62
63        mutations: {
64            [SET_USER](state: UsersState, user: User): void {
65                state.user = user;
66
67                if (user.projectLimit === 0) {
68                    const limitFromConfig = MetaUtils.getMetaContent('default-project-limit');
69
70                    state.user.projectLimit = parseInt(limitFromConfig);
71
72                    return;
73                }
74
75                state.user.projectLimit = user.projectLimit;
76            },
77            [CLEAR](state: UsersState): void {
78                state.user = new User();
79                state.user.projectLimit = 1;
80            },
81            [UPDATE_USER](state: UsersState, user: UpdatedUser): void {
82                state.user.fullName = user.fullName;
83                state.user.shortName = user.shortName;
84            },
85            [SET_USER_MFA_SECRET](state: UsersState, secret: string): void {
86                state.userMFASecret = secret;
87            },
88            [SET_USER_MFA_RECOVERY_CODES](state: UsersState, codes: string[]): void {
89                state.userMFARecoveryCodes = codes;
90                state.user.mfaRecoveryCodeCount = codes.length;
91            },
92        },
93
94        actions: {
95            [UPDATE]: async function ({commit}: UsersContext, userInfo: UpdatedUser): Promise<void> {
96                await api.update(userInfo);
97
98                commit(UPDATE_USER, userInfo);
99            },
100            [GET]: async function ({commit}: UsersContext): Promise<User> {
101                const user = await api.get();
102
103                commit(SET_USER, user);
104
105                return user;
106            },
107            [DISABLE_USER_MFA]: async function (_, request: DisableMFARequest): Promise<void> {
108                await api.disableUserMFA(request.passcode, request.recoveryCode);
109            },
110            [ENABLE_USER_MFA]: async function (_, passcode: string): Promise<void> {
111                await api.enableUserMFA(passcode);
112            },
113            [GENERATE_USER_MFA_SECRET]: async function ({commit}: UsersContext): Promise<void> {
114                const secret = await api.generateUserMFASecret();
115
116                commit(SET_USER_MFA_SECRET, secret);
117            },
118            [GENERATE_USER_MFA_RECOVERY_CODES]: async function ({commit}: UsersContext): Promise<void> {
119                const codes = await api.generateUserMFARecoveryCodes();
120
121                commit(SET_USER_MFA_RECOVERY_CODES, codes);
122            },
123            [CLEAR]: function({commit}: UsersContext) {
124                commit(CLEAR);
125            },
126        },
127
128        getters: {
129            user: (state: UsersState): User => state.user,
130            userName: (state: UsersState): string => state.user.getFullName(),
131        },
132    };
133}
134