From 7218c457dde5724a874a34539388b9d8c8173f7a Mon Sep 17 00:00:00 2001 From: Lera24 Date: Wed, 15 May 2024 17:14:27 +0300 Subject: [PATCH] feature: add 2fa[WTEL-3405] --- package-lock.json | 9 ++ package.json | 1 + src/app/locale/en/en.js | 3 + src/app/locale/ru/ru.js | 3 + src/app/locale/ua/ua.js | 3 + .../directory/modules/users/api/users-2fa.js | 21 +++ .../components/_internals/user-qrcode.vue | 123 ++++++++++++++++++ .../users/components/opened-user-general.vue | 32 +++-- .../directory/modules/users/store/users.js | 10 ++ 9 files changed, 193 insertions(+), 12 deletions(-) create mode 100644 src/modules/directory/modules/users/api/users-2fa.js create mode 100644 src/modules/directory/modules/users/components/_internals/user-qrcode.vue diff --git a/package-lock.json b/package-lock.json index 3b4a6b9d2..b3eea8906 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,6 +26,7 @@ "jszip-utils": "^0.1.0", "monaco-editor": "^0.44.0", "path": "^0.12.7", + "qrcode.vue": "^3.4.1", "query-string": "^7.1.1", "sortablejs": "^1.10.2", "vue": "^3.2.47", @@ -6426,6 +6427,14 @@ "node": ">=6" } }, + "node_modules/qrcode.vue": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/qrcode.vue/-/qrcode.vue-3.4.1.tgz", + "integrity": "sha512-wq/zHsifH4FJ1GXQi8/wNxD1KfQkckIpjK1KPTc/qwYU5/Bkd4me0w4xZSg6EXk6xLBkVDE0zxVagewv5EMAVA==", + "peerDependencies": { + "vue": "^3.0.0" + } + }, "node_modules/qs": { "version": "6.12.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.0.tgz", diff --git a/package.json b/package.json index 7d89a7392..e7752236b 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "jszip-utils": "^0.1.0", "monaco-editor": "^0.44.0", "path": "^0.12.7", + "qrcode.vue": "^3.4.1", "query-string": "^7.1.1", "sortablejs": "^1.10.2", "vue": "^3.2.47", diff --git a/src/app/locale/en/en.js b/src/app/locale/en/en.js index 319df6647..07e03d681 100644 --- a/src/app/locale/en/en.js +++ b/src/app/locale/en/en.js @@ -207,6 +207,9 @@ export default { tokenPopupSave: 'Save as TXT', userIp: 'User IP', userId: 'User ID', + download: 'Download', + regenerate: 'Regenerate', + askingAlert: 'Are you sure you want to regenerate the code? The user won’t be able to log in', }, license: { customers: 'Customers', diff --git a/src/app/locale/ru/ru.js b/src/app/locale/ru/ru.js index 3f95ea5ca..beaf0e6b2 100644 --- a/src/app/locale/ru/ru.js +++ b/src/app/locale/ru/ru.js @@ -207,6 +207,9 @@ export default { tokenPopupSave: 'Сохранить в формате TXT', userIp: 'IP пользователя', userId: 'ID пользователя', + download: 'Скачать', + regenerate: 'Перегенерировать', + askingAlert: 'Вы уверены, что хотите перегенерировать QR-код? Пользователь потеряет возможность войти в систему', }, license: { customers: 'Пользователи', diff --git a/src/app/locale/ua/ua.js b/src/app/locale/ua/ua.js index 57953279d..157c0a054 100644 --- a/src/app/locale/ua/ua.js +++ b/src/app/locale/ua/ua.js @@ -207,6 +207,9 @@ export default { tokenPopupSave: 'Зберегти у форматі TXT', userIp: 'IP користувача', userId: 'ID користувача', + download: 'Завантажити', + regenerate: 'Перегенерувати', + askingAlert: 'Ви впевнені, що хочете перегенерувати QR-код? Користувач втратить можливість зайти в систему', }, license: { customers: 'Користувачі', diff --git a/src/modules/directory/modules/users/api/users-2fa.js b/src/modules/directory/modules/users/api/users-2fa.js new file mode 100644 index 000000000..f5c3c8e45 --- /dev/null +++ b/src/modules/directory/modules/users/api/users-2fa.js @@ -0,0 +1,21 @@ +import applyTransform, { notify } from '@webitel/ui-sdk/src/api/transformers/index.js'; +import instance from '../../../../../app/api/instance'; + +const generateUrl = async ({ id }) => { + const url = `users/${id}/2fa`; + + try { + const response = await instance.post(url,{}); + return applyTransform(response.data, []); + } catch (err) { + throw applyTransform(err, [ + notify, + ]); + } +}; + +const Users2faAPI = { + generate: generateUrl, +}; + +export default Users2faAPI; diff --git a/src/modules/directory/modules/users/components/_internals/user-qrcode.vue b/src/modules/directory/modules/users/components/_internals/user-qrcode.vue new file mode 100644 index 000000000..e0bce6af3 --- /dev/null +++ b/src/modules/directory/modules/users/components/_internals/user-qrcode.vue @@ -0,0 +1,123 @@ + + + + + diff --git a/src/modules/directory/modules/users/components/opened-user-general.vue b/src/modules/directory/modules/users/components/opened-user-general.vue index ec5516d48..5138b841b 100644 --- a/src/modules/directory/modules/users/components/opened-user-general.vue +++ b/src/modules/directory/modules/users/components/opened-user-general.vue @@ -15,11 +15,9 @@ + + + @@ -51,10 +58,11 @@ import PasswordInput from '../../../../../app/components/utils/generate-password-input.vue'; import openedTabComponentMixin from '../../../../../app/mixins/objectPagesMixins/openedObjectTabMixin/openedTabComponentMixin'; +import UserQrcode from './_internals/user-qrcode.vue'; export default { name: 'OpenedUserGeneral', - components: { PasswordInput }, + components: { PasswordInput, UserQrcode }, mixins: [openedTabComponentMixin], }; diff --git a/src/modules/directory/modules/users/store/users.js b/src/modules/directory/modules/users/store/users.js index ab3d112c1..74a5ef238 100644 --- a/src/modules/directory/modules/users/store/users.js +++ b/src/modules/directory/modules/users/store/users.js @@ -3,6 +3,7 @@ import ObjectStoreModule import PermissionsStoreModule from '../../../../../app/store/BaseStoreModules/StoreModules/PermissionsStoreModule/PermissionsStoreModule'; import UsersAPI from '../api/users'; +import Users2faAPI from '../api/users-2fa.js'; import logs from '../modules/logs/store/logs'; import tokens from '../modules/tokens/store/usersTokens'; import headers from './_internals/headers'; @@ -23,6 +24,7 @@ const resettableState = { note: '', }, variables: [], + totpUrl: '', }, }; @@ -55,6 +57,14 @@ const actions = { context.commit('RESET_ITEM_STATE'); context.dispatch('directory/users/tokens/RESET_STATE', {}, { root: true }); }, + REGENERATE_2FA_URL: async (context) => { + try { + await Users2faAPI.generate({id: context.state.itemId}); + await context.dispatch('LOAD_ITEM'); + } catch (err) { + throw err; + } + } }; const mutations = {