xref: /openbmc/webui-vue/src/store/modules/SecurityAndAccess/UserManagementStore.js (revision de23ea23d88451a2fa2774ec72053772603c23ae)
1 import api, { getResponseCount } from '@/store/api';
2 import i18n from '@/i18n';
3 
4 const getServerErrorMessages = function (error) {
5   let errorData = error.response.data.error
6     ? error.response.data.error
7     : error.response.data;
8   if (typeof errorData == 'string') {
9     return [];
10   }
11   return Object.values(errorData)
12     .reduce((a, b) => a.concat(b))
13     .filter((info) => info.Message)
14     .map((info) => info.Message);
15 };
16 
17 const UserManagementStore = {
18   namespaced: true,
19   state: {
20     allUsers: [],
21     accountRoles: [],
22     accountLockoutDuration: null,
23     accountLockoutThreshold: null,
24     accountMinPasswordLength: null,
25     accountMaxPasswordLength: null,
26   },
27   getters: {
28     allUsers(state) {
29       return state.allUsers;
30     },
31     accountRoles(state) {
32       return state.accountRoles;
33     },
34     accountSettings(state) {
35       return {
36         lockoutDuration: state.accountLockoutDuration,
37         lockoutThreshold: state.accountLockoutThreshold,
38       };
39     },
40     accountPasswordRequirements(state) {
41       return {
42         minLength: state.accountMinPasswordLength,
43         maxLength: state.accountMaxPasswordLength,
44       };
45     },
46   },
47   mutations: {
48     setUsers(state, allUsers) {
49       state.allUsers = allUsers;
50     },
51     setAccountRoles(state, accountRoles) {
52       state.accountRoles = accountRoles;
53     },
54     setLockoutDuration(state, lockoutDuration) {
55       state.accountLockoutDuration = lockoutDuration;
56     },
57     setLockoutThreshold(state, lockoutThreshold) {
58       state.accountLockoutThreshold = lockoutThreshold;
59     },
60     setAccountMinPasswordLength(state, minPasswordLength) {
61       state.accountMinPasswordLength = minPasswordLength;
62     },
63     setAccountMaxPasswordLength(state, maxPasswordLength) {
64       state.accountMaxPasswordLength = maxPasswordLength;
65     },
66   },
67   actions: {
68     async getUsers({ commit }) {
69       return await api
70         .get('/redfish/v1/AccountService/Accounts')
71         .then((response) =>
72           response.data.Members.map((user) => user['@odata.id']),
73         )
74         .then((userIds) => api.all(userIds.map((user) => api.get(user))))
75         .then((users) => {
76           const userData = users.map((user) => user.data);
77           commit('setUsers', userData);
78         })
79         .catch((error) => {
80           console.log(error);
81           const message = i18n.global.t(
82             'pageUserManagement.toast.errorLoadUsers',
83           );
84           throw new Error(message);
85         });
86     },
87     getAccountSettings({ commit }) {
88       api
89         .get('/redfish/v1/AccountService')
90         .then(({ data }) => {
91           commit('setLockoutDuration', data.AccountLockoutDuration);
92           commit('setLockoutThreshold', data.AccountLockoutThreshold);
93           commit('setAccountMinPasswordLength', data.MinPasswordLength);
94           commit('setAccountMaxPasswordLength', data.MaxPasswordLength);
95         })
96         .catch((error) => {
97           console.log(error);
98           const message = i18n.global.t(
99             'pageUserManagement.toast.errorLoadAccountSettings',
100           );
101           throw new Error(message);
102         });
103     },
104     getAccountRoles({ commit }) {
105       api
106         .get('/redfish/v1/AccountService/Roles')
107         .then(({ data: { Members = [] } = {} }) => {
108           const roles = Members.map((role) => {
109             return role['@odata.id'].split('/').pop();
110           });
111           commit('setAccountRoles', roles);
112         })
113         .catch((error) => console.log(error));
114     },
115     async createUser({ dispatch }, { username, password, privilege, status }) {
116       const data = {
117         UserName: username,
118         Password: password,
119         RoleId: privilege,
120         Enabled: status,
121       };
122       return await api
123         .post('/redfish/v1/AccountService/Accounts', data)
124         .then(() => dispatch('getUsers'))
125         .then(() =>
126           i18n.global.t('pageUserManagement.toast.successCreateUser', {
127             username,
128           }),
129         )
130         .catch((error) => {
131           let serverMessages = getServerErrorMessages(error);
132           let message =
133             serverMessages.length > 0
134               ? serverMessages.join(' ')
135               : i18n.global.t('pageUserManagement.toast.errorCreateUser', {
136                   username: username,
137                 });
138           throw new Error(message);
139         });
140     },
141     async updateUser(
142       { dispatch },
143       { originalUsername, username, password, privilege, status, locked },
144     ) {
145       const data = {};
146       if (username) data.UserName = username;
147       if (password) data.Password = password;
148       if (privilege) data.RoleId = privilege;
149       if (status !== undefined) data.Enabled = status;
150       if (locked !== undefined) data.Locked = locked;
151       return await api
152         .patch(`/redfish/v1/AccountService/Accounts/${originalUsername}`, data)
153         .then(() => dispatch('getUsers'))
154         .then(() =>
155           i18n.global.t('pageUserManagement.toast.successUpdateUser', {
156             username: originalUsername,
157           }),
158         )
159         .catch((error) => {
160           console.log(error);
161           const serverMessages = getServerErrorMessages(error);
162           const message =
163             serverMessages.length > 0
164               ? serverMessages.join(' ')
165               : i18n.global.t('pageUserManagement.toast.errorUpdateUser', {
166                   username: originalUsername,
167                 });
168           throw new Error(message);
169         });
170     },
171     async deleteUser({ dispatch }, username) {
172       return await api
173         .delete(`/redfish/v1/AccountService/Accounts/${username}`)
174         .then(() => dispatch('getUsers'))
175         .then(() =>
176           i18n.global.t('pageUserManagement.toast.successDeleteUser', {
177             username,
178           }),
179         )
180         .catch((error) => {
181           console.log(error);
182           const message = i18n.global.t(
183             'pageUserManagement.toast.errorDeleteUser',
184             {
185               username,
186             },
187           );
188           throw new Error(message);
189         });
190     },
191     async deleteUsers({ dispatch }, users) {
192       const promises = users.map(({ username }) => {
193         return api
194           .delete(`/redfish/v1/AccountService/Accounts/${username}`)
195           .catch((error) => {
196             console.log(error);
197             return error;
198           });
199       });
200       return await api
201         .all(promises)
202         .then((response) => {
203           dispatch('getUsers');
204           return response;
205         })
206         .then(
207           api.spread((...responses) => {
208             const { successCount, errorCount } = getResponseCount(responses);
209             let toastMessages = [];
210 
211             if (successCount) {
212               const message = i18n.global.t(
213                 'pageUserManagement.toast.successBatchDelete',
214                 successCount,
215               );
216               toastMessages.push({ type: 'success', message });
217             }
218 
219             if (errorCount) {
220               const message = i18n.global.t(
221                 'pageUserManagement.toast.errorBatchDelete',
222                 errorCount,
223               );
224               toastMessages.push({ type: 'error', message });
225             }
226 
227             return toastMessages;
228           }),
229         );
230     },
231     async enableUsers({ dispatch }, users) {
232       const data = {
233         Enabled: true,
234       };
235       const promises = users.map(({ username }) => {
236         return api
237           .patch(`/redfish/v1/AccountService/Accounts/${username}`, data)
238           .catch((error) => {
239             console.log(error);
240             return error;
241           });
242       });
243       return await api
244         .all(promises)
245         .then((response) => {
246           dispatch('getUsers');
247           return response;
248         })
249         .then(
250           api.spread((...responses) => {
251             const { successCount, errorCount } = getResponseCount(responses);
252             let toastMessages = [];
253 
254             if (successCount) {
255               const message = i18n.global.t(
256                 'pageUserManagement.toast.successBatchEnable',
257                 successCount,
258               );
259               toastMessages.push({ type: 'success', message });
260             }
261 
262             if (errorCount) {
263               const message = i18n.global.t(
264                 'pageUserManagement.toast.errorBatchEnable',
265                 errorCount,
266               );
267               toastMessages.push({ type: 'error', message });
268             }
269 
270             return toastMessages;
271           }),
272         );
273     },
274     async disableUsers({ dispatch }, users) {
275       const data = {
276         Enabled: false,
277       };
278       const promises = users.map(({ username }) => {
279         return api
280           .patch(`/redfish/v1/AccountService/Accounts/${username}`, data)
281           .catch((error) => {
282             console.log(error);
283             return error;
284           });
285       });
286       return await api
287         .all(promises)
288         .then((response) => {
289           dispatch('getUsers');
290           return response;
291         })
292         .then(
293           api.spread((...responses) => {
294             const { successCount, errorCount } = getResponseCount(responses);
295             let toastMessages = [];
296 
297             if (successCount) {
298               const message = i18n.global.t(
299                 'pageUserManagement.toast.successBatchDisable',
300                 successCount,
301               );
302               toastMessages.push({ type: 'success', message });
303             }
304 
305             if (errorCount) {
306               const message = i18n.global.t(
307                 'pageUserManagement.toast.errorBatchDisable',
308                 errorCount,
309               );
310               toastMessages.push({ type: 'error', message });
311             }
312 
313             return toastMessages;
314           }),
315         );
316     },
317     async saveAccountSettings(
318       { dispatch },
319       { lockoutThreshold, lockoutDuration },
320     ) {
321       const data = {};
322       if (lockoutThreshold !== undefined) {
323         data.AccountLockoutThreshold = lockoutThreshold;
324       }
325       if (lockoutDuration !== undefined) {
326         data.AccountLockoutDuration = lockoutDuration;
327       }
328 
329       return await api
330         .patch('/redfish/v1/AccountService', data)
331         //GET new settings to update view
332         .then(() => dispatch('getAccountSettings'))
333         .then(() =>
334           i18n.global.t('pageUserManagement.toast.successSaveSettings'),
335         )
336         .catch((error) => {
337           console.log(error);
338           const message = i18n.global.t(
339             'pageUserManagement.toast.errorSaveSettings',
340           );
341           throw new Error(message);
342         });
343     },
344   },
345 };
346 
347 export default UserManagementStore;
348