From 4e4fb630b46cf18984501dd426eebb688a356bb1 Mon Sep 17 00:00:00 2001 From: Valentino K Date: Fri, 15 Apr 2022 14:30:27 +0200 Subject: [PATCH] Added user roles functionality --- src/components/Form/Select/Select.tsx | 10 ++--- .../CurrentUserModal/CurrentUserModal.tsx | 43 ++++++++----------- .../components/CurrentUserModal/types.ts | 4 +- .../users/components/UserModal/UserModal.tsx | 39 ++++++++--------- src/services/auth/redux/actions.ts | 1 + src/services/auth/redux/reducers.ts | 25 ++++++++--- src/services/auth/transformations.ts | 18 ++++++++ src/services/auth/types.ts | 11 ++--- src/services/users/redux/actions.ts | 16 ++++--- src/services/users/transformations.ts | 33 +++++++------- src/services/users/types.ts | 9 ++-- 11 files changed, 117 insertions(+), 92 deletions(-) create mode 100644 src/services/auth/transformations.ts diff --git a/src/components/Form/Select/Select.tsx b/src/components/Form/Select/Select.tsx index ab9b238..b5416d2 100644 --- a/src/components/Form/Select/Select.tsx +++ b/src/components/Form/Select/Select.tsx @@ -10,8 +10,6 @@ export const Select = ({ control, name, label, options }: SelectProps) => { } = useController({ name, control, - rules: { required: true }, - defaultValue: '', }); return ( @@ -25,14 +23,14 @@ export const Select = ({ control, name, label, options }: SelectProps) => { id={name} onChange={field.onChange} // send value to hook form onBlur={field.onBlur} // notify when input is touched/blur - value={field.value ? field.value.toString() : ''} // input value + value={field.value ? field.value : ''} // input value name={name} // send down the input name ref={field.ref} // send input ref, so we can focus on input when error appear className="shadow-sm focus:ring-primary-500 focus:border-primary-500 block w-full sm:text-sm border-gray-300 rounded-md" > - {options?.map((value) => ( - ))} diff --git a/src/components/Header/components/CurrentUserModal/CurrentUserModal.tsx b/src/components/Header/components/CurrentUserModal/CurrentUserModal.tsx index be7f18f..cf578cb 100644 --- a/src/components/Header/components/CurrentUserModal/CurrentUserModal.tsx +++ b/src/components/Header/components/CurrentUserModal/CurrentUserModal.tsx @@ -1,21 +1,21 @@ import React, { useEffect } from 'react'; import { useForm } from 'react-hook-form'; import { Modal, Banner } from 'src/components'; -import { Input } from 'src/components/Form'; -import { useUsers } from 'src/services/users'; -import { CurrentUser } from 'src/services/auth'; +import { Input, Select } from 'src/components/Form'; +import { User, UserRole, useUsers } from 'src/services/users'; import { appAccessList } from './consts'; import { UserModalProps } from './types'; export const CurrentUserModal = ({ open, onClose, user }: UserModalProps) => { const { editUserById, userModalLoading } = useUsers(); - const { control, reset, handleSubmit } = useForm({ + const { control, reset, handleSubmit } = useForm({ defaultValues: { name: null, email: null, id: null, - preferredUsername: null, + role_id: null, + status: null, }, }); @@ -70,11 +70,23 @@ export const CurrentUserModal = ({ open, onClose, user }: UserModalProps) => {
- + */} + {/*
- -
- -
- -
-
diff --git a/src/components/Header/components/CurrentUserModal/types.ts b/src/components/Header/components/CurrentUserModal/types.ts index 31814e0..00bc7d6 100644 --- a/src/components/Header/components/CurrentUserModal/types.ts +++ b/src/components/Header/components/CurrentUserModal/types.ts @@ -1,7 +1,7 @@ -import { CurrentUser } from 'src/services/auth'; +import { User } from 'src/services/users'; export type UserModalProps = { open: boolean; onClose: () => void; - user: CurrentUser; + user: User; }; diff --git a/src/modules/users/components/UserModal/UserModal.tsx b/src/modules/users/components/UserModal/UserModal.tsx index f00b098..5b3814b 100644 --- a/src/modules/users/components/UserModal/UserModal.tsx +++ b/src/modules/users/components/UserModal/UserModal.tsx @@ -2,9 +2,8 @@ import React, { useEffect, useState } from 'react'; import { TrashIcon } from '@heroicons/react/outline'; import { useForm } from 'react-hook-form'; import { Modal, Banner, ConfirmationModal } from 'src/components'; -import { Input } from 'src/components/Form'; -import { useUsers } from 'src/services/users'; -import { CurrentUserState } from 'src/services/users/redux'; +import { Input, Select } from 'src/components/Form'; +import { User, UserRole, useUsers } from 'src/services/users'; import { useAuth } from 'src/services/auth'; import { appAccessList } from './consts'; import { UserModalProps } from './types'; @@ -14,11 +13,12 @@ export const UserModal = ({ open, onClose, userId }: UserModalProps) => { const { user, loadUser, editUserById, createNewUser, userModalLoading, deleteUserById } = useUsers(); const { currentUser } = useAuth(); - const { control, reset, handleSubmit } = useForm({ + const { control, reset, handleSubmit } = useForm({ defaultValues: { name: null, email: null, id: null, + role_id: null, status: null, }, }); @@ -117,7 +117,19 @@ export const UserModal = ({ open, onClose, userId }: UserModalProps) => {
- +
- -
- -
- -
-
diff --git a/src/services/auth/redux/actions.ts b/src/services/auth/redux/actions.ts index 9fb3bca..cde2b8e 100644 --- a/src/services/auth/redux/actions.ts +++ b/src/services/auth/redux/actions.ts @@ -6,6 +6,7 @@ export enum AuthActionTypes { SIGN_IN_SUCCESS = 'auth/sign_in_success', SIGN_IN_FAILURE = 'auth/sign_in_failure', SIGN_OUT = 'auth/SIGN_OUT', + UPDATE_AUTH_USER = 'auth/update_auth_user', REGISTRATION_START = 'auth/registration_start', REGISTRATION_FAILURE = 'auth/registration_failure', } diff --git a/src/services/auth/redux/reducers.ts b/src/services/auth/redux/reducers.ts index d2d05f2..8deb265 100644 --- a/src/services/auth/redux/reducers.ts +++ b/src/services/auth/redux/reducers.ts @@ -1,14 +1,17 @@ import { createApiReducer, chainReducers, INITIAL_API_STATUS } from 'src/services/api'; +import { User } from 'src/services/users'; import { AuthState } from './types'; import { AuthActionTypes } from './actions'; -import { CurrentUser } from '../types'; +import { transformAuthUser } from '../transformations'; -const initialCurrentUserState: CurrentUser = { +const initialCurrentUserState: User = { email: null, name: null, - preferredUsername: null, id: null, + role_id: null, + status: null, + preferredUsername: null, }; const initialState: AuthState = { @@ -17,9 +20,21 @@ const initialState: AuthState = { _status: INITIAL_API_STATUS, }; +const authLocalReducer = (state: any = initialState, action: any) => { + switch (action.type) { + case AuthActionTypes.UPDATE_AUTH_USER: + return { + ...state, + userInfo: action.payload, + }; + default: + return state; + } +}; + const auth = createApiReducer( [AuthActionTypes.SIGN_IN_START, AuthActionTypes.SIGN_IN_SUCCESS, AuthActionTypes.SIGN_IN_FAILURE], - (data) => ({ token: data.accessToken, userInfo: data.userInfo }), + (data) => transformAuthUser(data), (data) => data.error.message, ); @@ -29,4 +44,4 @@ const signOut = createApiReducer( () => initialState, ); -export default chainReducers(initialState, auth, signOut); +export default chainReducers(initialState, auth, signOut, authLocalReducer); diff --git a/src/services/auth/transformations.ts b/src/services/auth/transformations.ts new file mode 100644 index 0000000..2cfebaf --- /dev/null +++ b/src/services/auth/transformations.ts @@ -0,0 +1,18 @@ +import { UserRole } from '../users'; +import { Auth } from './types'; + +export const transformAuthUser = (response: any): Auth => { + const resolvedUserRole = !response.userInfo.role_id ? UserRole.User : response.userInfo.role_id; + + return { + token: response.accessToken, + userInfo: { + id: response.userInfo.id, + role_id: resolvedUserRole, + email: response.userInfo.email ?? null, + name: response.userInfo.name ?? null, + preferredUsername: response.userInfo.preferredUsername, + status: response.userInfo.state ?? null, + }, + }; +}; diff --git a/src/services/auth/types.ts b/src/services/auth/types.ts index c7ac644..f196385 100644 --- a/src/services/auth/types.ts +++ b/src/services/auth/types.ts @@ -1,11 +1,6 @@ +import { User } from '../users'; + export interface Auth { token: string | null; - userInfo: CurrentUser; -} - -export interface CurrentUser { - email: string | null; - name: string | null; - preferredUsername: string | null; - id: string | null; + userInfo: User; } diff --git a/src/services/users/redux/actions.ts b/src/services/users/redux/actions.ts index dbcabe8..67be7ee 100644 --- a/src/services/users/redux/actions.ts +++ b/src/services/users/redux/actions.ts @@ -1,7 +1,8 @@ import { Dispatch } from 'redux'; import { showToast, ToastType } from 'src/common/util/show-toast'; import { performApiCall } from 'src/services/api'; -import { transformRequestUser, transformResponseUser } from '../transformations'; +import { AuthActionTypes } from 'src/services/auth'; +import { transformRequestUser, transformUser } from '../transformations'; export enum UserActionTypes { FETCH_USERS = 'users/fetch_users', @@ -38,7 +39,7 @@ export const fetchUsers = () => async (dispatch: Dispatch) => { dispatch({ type: UserActionTypes.FETCH_USERS, - payload: data.map(transformResponseUser), + payload: data.map(transformUser), }); } catch (err) { console.error(err); @@ -58,7 +59,7 @@ export const fetchUserById = (id: string) => async (dispatch: Dispatch) => dispatch({ type: UserActionTypes.FETCH_USER, - payload: transformResponseUser(data), + payload: transformUser(data), }); } catch (err) { console.error(err); @@ -79,7 +80,12 @@ export const updateUserById = (user: any) => async (dispatch: Dispatch) => dispatch({ type: UserActionTypes.UPDATE_USER, - payload: transformResponseUser(data), + payload: transformUser(data), + }); + + dispatch({ + type: AuthActionTypes.UPDATE_AUTH_USER, + payload: transformUser(data), }); showToast('User updated successfully.', ToastType.Success); @@ -104,7 +110,7 @@ export const createUser = (user: any) => async (dispatch: Dispatch) => { dispatch({ type: UserActionTypes.CREATE_USER, - payload: transformResponseUser(data), + payload: transformUser(data), }); showToast('User created successfully.', ToastType.Success); diff --git a/src/services/users/transformations.ts b/src/services/users/transformations.ts index db77f9a..5bef470 100644 --- a/src/services/users/transformations.ts +++ b/src/services/users/transformations.ts @@ -1,31 +1,32 @@ import _ from 'lodash'; -import { User } from './types'; - -export const transformResponseUser = (response: any): User => { - const userResponse = _.get(response, 'user', response); - - return { - id: userResponse.id, - email: userResponse.traits.email, - name: userResponse.traits.name ?? null, - status: userResponse.state, - }; -}; +import { User, UserRole } from './types'; export const transformUser = (response: any): User => { const userResponse = _.get(response, 'user', response); + const resolvedUserRole = !userResponse.traits.role_id ? UserRole.User : userResponse.traits.role_id; + return { id: userResponse.id, - email: userResponse.email, - name: userResponse.name, - status: userResponse.status, + role_id: resolvedUserRole, + email: userResponse.traits.email, + name: userResponse.traits.name ?? null, + preferredUsername: userResponse.preferredUsername, + status: userResponse.state, }; }; -export const transformRequestUser = (data: any) => { +export const transformRequestUser = (data: Pick) => { + if (data.role_id === UserRole.User) { + return { + email: data.email, + name: data.name, + }; + } + return { + role_id: Number(data.role_id), email: data.email, name: data.name, }; diff --git a/src/services/users/types.ts b/src/services/users/types.ts index 1e50992..2ab4e1b 100644 --- a/src/services/users/types.ts +++ b/src/services/users/types.ts @@ -1,7 +1,9 @@ export interface User { id: number | null; + role_id: UserRole | null; email: string | null; name: string | null; + preferredUsername: string | null; status: string | null; } @@ -10,10 +12,9 @@ export interface FormUser extends User { confirmPassword?: string; } -export interface UserRole { - id?: number; - name: string; - isAdministrator: boolean; +export enum UserRole { + Admin = '1', + User = '2', } export interface UserApiRequest {