Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions admin-ui/app/components/Sidebar/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ export interface MenuIconMap {
// Sidebar state interface
export interface SidebarState {
health: Record<string, string>
isUserLogout: boolean
logoutAuditInFlight: boolean
logoutAuditSucceeded: boolean | null
}

// Root state interface for sidebar selectors
Expand All @@ -54,7 +55,8 @@ export interface SidebarRootState {
healthReducer: {
health: Record<string, string>
}
userReducer: {
isUserLogout: boolean
logoutAuditReducer: {
logoutAuditInFlight: boolean
logoutAuditSucceeded: boolean | null
}
}
2 changes: 1 addition & 1 deletion admin-ui/app/layout/components/SidebarMiddleNav.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react'
import { SidebarMenu, SidebarMenuItem } from 'Components'
import { auditLogoutLogs } from '../../../plugins/user-management/redux/features/userSlice'
import { auditLogoutLogs } from 'Redux/features/sessionSlice'
import { useDispatch } from 'react-redux'
import type { SidebarMiddleNavProps, LayoutDispatch } from './types'

Expand Down
9 changes: 7 additions & 2 deletions admin-ui/app/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -815,7 +815,13 @@
"add_ssa": "Add SSA",
"copied": "Copied",
"no_data_found": "No data found",
"role_already_exists": "Role already exists"
"no_sessions_found": "No sessions found",
"role_already_exists": "Role already exists",
"user_created_successfully": "User created successfully",
"user_updated_successfully": "User updated successfully",
"user_deleted_successfully": "User deleted successfully",
"password_changed_successfully": "Password changed successfully",
"device_deleted_successfully": "Device deleted successfully"
},
"tooltips": {
"add_attribute": "Add attribute",
Expand Down Expand Up @@ -1713,7 +1719,6 @@
"principalAttribute": "Name or Friendly Name of the attribute used to identify external",
"principalType": "Way to identify and track external users from the assertion."
},

"samlConfiguration": {
"enabled": "SAML functionality enabled.",
"selectedIdp": "Selected SAML server.",
Expand Down
8 changes: 7 additions & 1 deletion admin-ui/app/locales/es/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -815,7 +815,13 @@
"add_ssa": "Agregar SSA",
"copied": "Copiado",
"no_data_found": "No se encontraron datos",
"role_already_exists": "El rol ya existe"
"no_sessions_found": "No se encontraron sesiones",
"role_already_exists": "El rol ya existe",
"user_created_successfully": "Usuario creado exitosamente",
"user_updated_successfully": "Usuario actualizado exitosamente",
"user_deleted_successfully": "Usuario eliminado exitosamente",
"password_changed_successfully": "Contraseña cambiada exitosamente",
"device_deleted_successfully": "Dispositivo eliminado exitosamente"
},
"tooltips": {
"add_attribute": "Añadir atributo",
Expand Down
8 changes: 7 additions & 1 deletion admin-ui/app/locales/fr/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -752,7 +752,13 @@
"copied": "Copié",
"edit_acr": "Modifier ACR",
"no_data_found": "Aucune donnée trouvée",
"role_already_exists": "Le rôle existe déjà"
"no_sessions_found": "Aucune session trouvée",
"role_already_exists": "Le rôle existe déjà",
"user_created_successfully": "Utilisateur créé avec succès",
"user_updated_successfully": "Utilisateur mis à jour avec succès",
"user_deleted_successfully": "Utilisateur supprimé avec succès",
"password_changed_successfully": "Mot de passe modifié avec succès",
"device_deleted_successfully": "Appareil supprimé avec succès"
},
"tooltips": {
"add_attribute": "Ajouter un attribut",
Expand Down
8 changes: 7 additions & 1 deletion admin-ui/app/locales/pt/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -747,7 +747,13 @@
"copied": "Copiado",
"edit_acr": "Editar ACR",
"no_data_found": "Nenhum dado encontrado",
"role_already_exists": "Função já existe"
"no_sessions_found": "Nenhuma sessão encontrada",
"role_already_exists": "Função já existe",
"user_created_successfully": "Usuário criado com sucesso",
"user_updated_successfully": "Usuário atualizado com sucesso",
"user_deleted_successfully": "Usuário excluído com sucesso",
"password_changed_successfully": "Senha alterada com sucesso",
"device_deleted_successfully": "Dispositivo excluído com sucesso"
},
"tooltips": {
"add_attribute": "Adicionar atributo",
Expand Down
35 changes: 35 additions & 0 deletions admin-ui/app/redux/features/sessionSlice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import reducerRegistry from 'Redux/reducers/ReducerRegistry'

interface SessionState {
logoutAuditInFlight: boolean
logoutAuditSucceeded: boolean | null
}

const initialState: SessionState = {
logoutAuditInFlight: false,
logoutAuditSucceeded: null,
}

const sessionSlice = createSlice({
name: 'session',
initialState,
reducers: {
auditLogoutLogs: (state, _action: PayloadAction<{ message: string }>) => {
state.logoutAuditInFlight = true
state.logoutAuditSucceeded = null
},
auditLogoutLogsResponse: (state, action: PayloadAction<boolean>) => {
state.logoutAuditInFlight = false
state.logoutAuditSucceeded = action.payload
},
resetLogoutState: (state) => {
state.logoutAuditInFlight = false
state.logoutAuditSucceeded = null
},
},
})

export const { auditLogoutLogs, auditLogoutLogsResponse, resetLogoutState } = sessionSlice.actions
export default sessionSlice.reducer
reducerRegistry.register('logoutAuditReducer', sessionSlice.reducer)
2 changes: 2 additions & 0 deletions admin-ui/app/redux/reducers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import toastReducer from '../features/toastSlice'
import profileDetailsReducer from '../features/ProfileDetailsSlice'
import cedarPermissionsReducer from '../features/cedarPermissionsSlice'
import auditReducer from 'Plugins/admin/redux/features/auditSlice'
import sessionReducer from '../features/sessionSlice'

const appReducers = {
authReducer,
Expand All @@ -29,6 +30,7 @@ const appReducers = {
profileDetailsReducer,
cedarPermissions: cedarPermissionsReducer,
auditReducer,
sessionReducer,
}

export default appReducers
2 changes: 1 addition & 1 deletion admin-ui/app/redux/sagas/LicenseDetailsSaga.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { initAudit } from 'Redux/sagas/SagaUtils'
import { postUserAction } from 'Redux/api/backend-api'
import { addAdditionalData, isFourZeroOneError } from 'Utils/TokenController'
import { getAPIAccessToken } from 'Redux/features/authSlice'
import { API_LICENSE } from 'Plugins/user-management/redux/audit/Resources'
import { API_LICENSE } from '../../audit/Resources'
import { DELETION } from '@/audit/UserActionType'
const JansConfigApi = require('jans_config_api')

Expand Down
24 changes: 10 additions & 14 deletions admin-ui/app/redux/sagas/ProfileDetailsSaga.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,30 @@
// @ts-nocheck
// Note: This saga is kept for ProfileDetails functionality that hasn't been migrated yet
// The user management plugin itself has been fully migrated to React Query
import { all, call, fork, put, select, takeLatest } from 'redux-saga/effects'
import { isFourZeroOneError, addAdditionalData } from 'Utils/TokenController'
import { FETCH } from '../../audit/UserActionType'
import { getAPIAccessToken } from 'Redux/features/authSlice'
import { API_USERS } from 'Plugins/user-management/redux/audit/Resources'
import UserApi from 'Plugins/user-management/redux/api/UserApi'
import { API_USERS } from '../../audit/Resources'
import { initAudit } from 'Redux/sagas/SagaUtils'
import { postUserAction } from 'Redux/api/backend-api'
import { setUserProfileDetails } from 'Redux/features/ProfileDetailsSlice'
import { getProfileDetails, checkIsLoadingDetails } from '../features/ProfileDetailsSlice'
const JansConfigApi = require('jans_config_api')
import { getClient } from 'Redux/api/base'

function* newFunction() {
const token = yield select((state) => state.authReducer.token.access_token)
const issuer = yield select((state) => state.authReducer.issuer)
const api = new JansConfigApi.ConfigurationUserManagementApi(
getClient(JansConfigApi, token, issuer),
)
return new UserApi(api)
}

function* getProfileDetailsWorker({ payload }) {
const audit = yield* initAudit()
try {
yield put(checkIsLoadingDetails(true))
addAdditionalData(audit, FETCH, API_USERS, payload)
const userApi = yield* newFunction()
const data = yield call(userApi.getUsers, payload)
yield put(setUserProfileDetails(data?.entries?.[0]))
const token = yield select((state) => state.authReducer.token.access_token)
const issuer = yield select((state) => state.authReducer.issuer)
const api = new JansConfigApi.ConfigurationUserManagementApi(
getClient(JansConfigApi, token, issuer),
)
const data = yield call([api, api.getUserByInum], payload.pattern)
yield put(setUserProfileDetails(data))
yield call(postUserAction, audit)
} catch (e) {
yield put(setUserProfileDetails(null))
Expand Down
46 changes: 46 additions & 0 deletions admin-ui/app/redux/sagas/SessionSaga.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { all, call, fork, put, takeLatest } from 'redux-saga/effects'
import type { PayloadAction } from '@reduxjs/toolkit'
import { auditLogoutLogs, auditLogoutLogsResponse } from '../features/sessionSlice'
import { initAudit } from './SagaUtils'
import { addAdditionalData } from 'Utils/TokenController'
import { postUserAction } from 'Redux/api/backend-api'
import { CREATE } from '../../audit/UserActionType'

const API_USERS = '/api/v1/users'

interface ApiResponse {
status?: number
}

export function* auditLogoutLogsSaga({
payload,
}: PayloadAction<{ message: string }>): Generator<any, boolean, any> {
if (process.env.NODE_ENV === 'development') {
console.log('Logout audit:', payload.message)
}

const audit = yield call(initAudit)

try {
addAdditionalData(audit, CREATE, API_USERS, {})
audit.message = payload.message
const data: ApiResponse = yield call(postUserAction, audit)
const ok = !!data && typeof data.status === 'number' && data.status >= 200 && data.status < 300
yield put(auditLogoutLogsResponse(ok))
return ok
} catch (e: unknown) {
yield put(auditLogoutLogsResponse(false))
if (process.env.NODE_ENV === 'development') {
console.log('Error:', e)
}
return false
}
}

export function* watchAuditLogoutLogs(): Generator<any, void, any> {
yield takeLatest(auditLogoutLogs.type, auditLogoutLogsSaga)
}

export default function* sessionSaga(): Generator<any, void, any> {
yield all([fork(watchAuditLogoutLogs)])
}
3 changes: 3 additions & 0 deletions admin-ui/app/redux/sagas/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import process from 'Plugins/PluginSagasResolver'
import attributes from './AttributesSaga'
import profileDetails from './ProfileDetailsSaga'
import lockSaga from './LockSaga'
import sessionSaga from './SessionSaga'

export default function* rootSaga() {
const pluginSagaArr = process()
yield all(
Expand All @@ -31,6 +33,7 @@ export default function* rootSaga() {
attributes(),
profileDetails(),
lockSaga(),
sessionSaga(),
],
pluginSagaArr,
),
Expand Down
9 changes: 5 additions & 4 deletions admin-ui/app/routes/Apps/Gluu/GluuAppSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,12 @@ const MENU_ICON_MAP: MenuIconMap = {
interface RootState extends SidebarRootState {}

const selectHealth = (state: RootState): Record<string, string> => state.healthReducer.health
const selectIsUserLogout = (state: RootState): boolean => state.userReducer.isUserLogout
const selectLogoutAuditSucceeded = (state: RootState): boolean | null =>
state.logoutAuditReducer.logoutAuditSucceeded

function GluuAppSidebar(): JSX.Element {
const health = useSelector(selectHealth)
const isUserLogout = useSelector(selectIsUserLogout)
const logoutAuditSucceeded = useSelector(selectLogoutAuditSucceeded)
const [pluginMenus, setPluginMenus] = useState<PluginMenu[]>([])
const [loading, setLoading] = useState<boolean>(false)
const { t } = useTranslation()
Expand Down Expand Up @@ -162,10 +163,10 @@ function GluuAppSidebar(): JSX.Element {
}, [memoizedFilteredMenus, filterMenuItems])

useEffect(() => {
if (isUserLogout) {
if (logoutAuditSucceeded === true) {
navigate('/logout')
}
}, [isUserLogout, navigate])
}, [logoutAuditSucceeded, navigate])

return (
<ErrorBoundary FallbackComponent={GluuErrorFallBack}>
Expand Down
8 changes: 4 additions & 4 deletions admin-ui/app/routes/Apps/Gluu/GluuSessionTimeout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import SessionTimeoutDialog from './GluuSessionTimeoutDialog'
import { useNavigate } from 'react-router-dom'
import { withIdleTimer } from 'react-idle-timer'
import { useDispatch, useSelector } from 'react-redux'
import { auditLogoutLogs } from '../../../../plugins/user-management/redux/features/userSlice'
import { auditLogoutLogs } from 'Redux/features/sessionSlice'

let countdownInterval: any
let timeout: any
Expand All @@ -17,7 +17,7 @@ const SessionTimeout = ({ isAuthenticated }: any) => {
const idleTimer = useRef(null)
const sessionTimeout =
useSelector((state: any) => state.authReducer?.config?.sessionTimeoutInMins) || 5
const { isUserLogout } = useSelector((state: any) => state.userReducer)
const { logoutAuditSucceeded } = useSelector((state: any) => state.logoutAuditReducer)

const navigate = useNavigate()
const dispatch = useDispatch()
Expand Down Expand Up @@ -77,10 +77,10 @@ const SessionTimeout = ({ isAuthenticated }: any) => {
}

useEffect(() => {
if (isUserLogout) {
if (logoutAuditSucceeded === true) {
navigate('/logout')
}
}, [isUserLogout])
}, [logoutAuditSucceeded])

return (
<>
Expand Down
11 changes: 5 additions & 6 deletions admin-ui/app/routes/Apps/Profile/ProfilePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import { Box, Divider, Skeleton } from '@mui/material'
import { useNavigate } from 'react-router'
import { getProfileDetails } from 'Redux/features/ProfileDetailsSlice'
import { randomAvatar } from '../../../utilities'
import { setSelectedUserData } from 'Plugins/user-management/redux/features/userSlice'
import { USER_WRITE } from 'Utils/PermChecker'
import getThemeColor from '../../../context/theme/config'
import { useCedarling } from '@/cedarling'
Expand Down Expand Up @@ -116,11 +115,11 @@ const ProfileDetails: React.FC<ProfileDetailsProps> = () => {
useEffect(() => {}, [cedarPermissions])

const navigateToUserManagement = useCallback((): void => {
if (profileDetails) {
dispatch(setSelectedUserData(profileDetails))
navigate(`/user/usermanagement/edit/:${profileDetails.inum}`)
}
}, [profileDetails, dispatch, navigate])
if (!profileDetails?.inum) return
navigate(`/user/usermanagement/edit/${encodeURIComponent(profileDetails.inum)}`, {
state: { selectedUser: profileDetails },
})
}, [profileDetails, navigate])

const jansAdminUIRole = profileDetails?.customAttributes?.find(
(att: CustomAttribute): boolean => att?.name === 'jansAdminUIRole',
Expand Down
2 changes: 1 addition & 1 deletion admin-ui/app/routes/Dashboards/DashboardPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import JansLockUsers from 'components/SVG/menu/JansLockUsers'
import JansLockClients from 'components/SVG/menu/JansLockClients'
import { getHealthServerStatus } from '../../redux/features/healthSlice'
import GluuPermissionModal from 'Routes/Apps/Gluu/GluuPermissionModal'
import { auditLogoutLogs } from '../../../plugins/user-management/redux/features/userSlice'
import { auditLogoutLogs } from 'Redux/features/sessionSlice'
import { useNavigate } from 'react-router'
import { getLockStatus } from 'Redux/features/lockSlice'
import moment from 'moment'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,23 @@ import { useDispatch, useSelector } from 'react-redux'
import { Link, useNavigate } from 'react-router-dom'
import { DropdownMenu, DropdownItem } from 'Components'
import { useTranslation } from 'react-i18next'
import { auditLogoutLogs } from '../../../../plugins/user-management/redux/features/userSlice'
import { auditLogoutLogs } from 'Redux/features/sessionSlice'

const DropdownProfile = ({ position = '', end, userinfo }: any) => {
const { t } = useTranslation()
const dispatch = useDispatch()
const { isUserLogout } = useSelector((state: any) => state.userReducer)
const { logoutAuditSucceeded } = useSelector((state: any) => state.logoutAuditReducer)
const navigate = useNavigate()

const handleLogout = () => {
dispatch(auditLogoutLogs({ message: 'User logged out mannually' }))
}

useEffect(() => {
if (isUserLogout) {
if (logoutAuditSucceeded === true) {
navigate('/logout')
}
}, [isUserLogout])
}, [logoutAuditSucceeded])

return (
<DropdownMenu end={end}>
Expand Down
Loading
Loading