From ea83849cd3418a3aef5966355fe1c660541a7057 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20G=C3=B3is?= Date: Thu, 2 Mar 2023 13:49:50 +0000 Subject: [PATCH] refactor: rename sign-on log to login history (#3245) Renames `sign-on log` to `login history`. --- .../LoginHistory.tsx} | 6 +-- .../LoginHistoryActionsCell.tsx} | 6 +-- .../LoginHistoryDeleteAllDialog.tsx} | 14 +++--- .../LoginHistoryDeleteDialog.tsx} | 12 ++--- .../LoginHistorySuccessfulCell.tsx} | 13 +++-- .../LoginHistoryTable/LoginHistoryTable.tsx} | 48 +++++++++---------- .../__snapshots__/routes.test.tsx.snap | 4 +- frontend/src/component/menu/routes.ts | 14 +++--- .../useLoginHistoryApi.ts} | 8 ++-- .../useLoginHistory.ts} | 14 +++--- .../{signOnEvent.ts => loginEvent.ts} | 2 +- frontend/src/interfaces/uiConfig.ts | 2 +- .../__snapshots__/create-config.test.ts.snap | 4 +- src/lib/types/experimental.ts | 2 +- ...name-sign-on-log-table-to-login-history.js | 20 ++++++++ 15 files changed, 94 insertions(+), 75 deletions(-) rename frontend/src/component/{signOnLog/SignOnLog.tsx => loginHistory/LoginHistory.tsx} (78%) rename frontend/src/component/{signOnLog/SignOnLogTable/SignOnLogActionsCell/SignOnLogActionsCell.tsx => loginHistory/LoginHistoryTable/LoginHistoryActionsCell/LoginHistoryActionsCell.tsx} (86%) rename frontend/src/component/{signOnLog/SignOnLogTable/SignOnLogDeleteAllDialog/SignOnLogDeleteAllDialog.tsx => loginHistory/LoginHistoryTable/LoginHistoryDeleteAllDialog/LoginHistoryDeleteAllDialog.tsx} (56%) rename frontend/src/component/{signOnLog/SignOnLogTable/SignOnLogDeleteDialog/SignOnLogDeleteDialog.tsx => loginHistory/LoginHistoryTable/LoginHistoryDeleteDialog/LoginHistoryDeleteDialog.tsx} (67%) rename frontend/src/component/{signOnLog/SignOnLogTable/SignOnLogSuccessfulCell/SignOnLogSuccessfulCell.tsx => loginHistory/LoginHistoryTable/LoginHistorySuccessfulCell/LoginHistorySuccessfulCell.tsx} (82%) rename frontend/src/component/{signOnLog/SignOnLogTable/SignOnLogTable.tsx => loginHistory/LoginHistoryTable/LoginHistoryTable.tsx} (87%) rename frontend/src/hooks/api/actions/{useSignOnLogApi/useSignOnLogApi.ts => useLoginHistoryApi/useLoginHistoryApi.ts} (89%) rename frontend/src/hooks/api/getters/{useSignOnLog/useSignOnLog.ts => useLoginHistory/useLoginHistory.ts} (68%) rename frontend/src/interfaces/{signOnEvent.ts => loginEvent.ts} (82%) create mode 100644 src/migrations/20230302133740-rename-sign-on-log-table-to-login-history.js diff --git a/frontend/src/component/signOnLog/SignOnLog.tsx b/frontend/src/component/loginHistory/LoginHistory.tsx similarity index 78% rename from frontend/src/component/signOnLog/SignOnLog.tsx rename to frontend/src/component/loginHistory/LoginHistory.tsx index 98b3080e15..1f2de73458 100644 --- a/frontend/src/component/signOnLog/SignOnLog.tsx +++ b/frontend/src/component/loginHistory/LoginHistory.tsx @@ -3,16 +3,16 @@ import AccessContext from 'contexts/AccessContext'; import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; import { ADMIN } from 'component/providers/AccessProvider/permissions'; import { AdminAlert } from 'component/common/AdminAlert/AdminAlert'; -import { SignOnLogTable } from './SignOnLogTable/SignOnLogTable'; +import { LoginHistoryTable } from './LoginHistoryTable/LoginHistoryTable'; -export const SignOnLog = () => { +export const LoginHistory = () => { const { hasAccess } = useContext(AccessContext); return (
} + show={} elseShow={} />
diff --git a/frontend/src/component/signOnLog/SignOnLogTable/SignOnLogActionsCell/SignOnLogActionsCell.tsx b/frontend/src/component/loginHistory/LoginHistoryTable/LoginHistoryActionsCell/LoginHistoryActionsCell.tsx similarity index 86% rename from frontend/src/component/signOnLog/SignOnLogTable/SignOnLogActionsCell/SignOnLogActionsCell.tsx rename to frontend/src/component/loginHistory/LoginHistoryTable/LoginHistoryActionsCell/LoginHistoryActionsCell.tsx index 9d395670a7..52d2c9a411 100644 --- a/frontend/src/component/signOnLog/SignOnLogTable/SignOnLogActionsCell/SignOnLogActionsCell.tsx +++ b/frontend/src/component/loginHistory/LoginHistoryTable/LoginHistoryActionsCell/LoginHistoryActionsCell.tsx @@ -8,13 +8,13 @@ const StyledBox = styled(Box)(() => ({ justifyContent: 'center', })); -interface ISignOnLogActionsCellProps { +interface ILoginHistoryActionsCellProps { onDelete: (event: React.SyntheticEvent) => void; } -export const SignOnLogActionsCell = ({ +export const LoginHistoryActionsCell = ({ onDelete, -}: ISignOnLogActionsCellProps) => { +}: ILoginHistoryActionsCellProps) => { return ( >; onConfirm: () => void; } -export const SignOnLogDeleteAllDialog = ({ +export const LoginHistoryDeleteAllDialog = ({ open, setOpen, onConfirm, -}: IServiceAccountDeleteAllDialogProps) => ( +}: ILoginHistoryDeleteAllDialogProps) => ( { setOpen(false); }} > - You are about to clear the sign-on log. + You are about to clear the login history.
- This will delete all the sign-on events. + This will delete all the login events.
); diff --git a/frontend/src/component/signOnLog/SignOnLogTable/SignOnLogDeleteDialog/SignOnLogDeleteDialog.tsx b/frontend/src/component/loginHistory/LoginHistoryTable/LoginHistoryDeleteDialog/LoginHistoryDeleteDialog.tsx similarity index 67% rename from frontend/src/component/signOnLog/SignOnLogTable/SignOnLogDeleteDialog/SignOnLogDeleteDialog.tsx rename to frontend/src/component/loginHistory/LoginHistoryTable/LoginHistoryDeleteDialog/LoginHistoryDeleteDialog.tsx index b0e30da0aa..4fea356c97 100644 --- a/frontend/src/component/signOnLog/SignOnLogTable/SignOnLogDeleteDialog/SignOnLogDeleteDialog.tsx +++ b/frontend/src/component/loginHistory/LoginHistoryTable/LoginHistoryDeleteDialog/LoginHistoryDeleteDialog.tsx @@ -1,19 +1,19 @@ import { Dialogue } from 'component/common/Dialogue/Dialogue'; -import { ISignOnEvent } from 'interfaces/signOnEvent'; +import { ILoginEvent } from 'interfaces/loginEvent'; -interface IServiceAccountDeleteDialogProps { - event?: ISignOnEvent; +interface ILoginHistoryDeleteDialogProps { + event?: ILoginEvent; open: boolean; setOpen: React.Dispatch>; - onConfirm: (event: ISignOnEvent) => void; + onConfirm: (event: ILoginEvent) => void; } -export const SignOnLogDeleteDialog = ({ +export const LoginHistoryDeleteDialog = ({ event, open, setOpen, onConfirm, -}: IServiceAccountDeleteDialogProps) => ( +}: ILoginHistoryDeleteDialogProps) => ( ({ justifyContent: 'center', })); -interface ISignOnLogSuccessfulCellProps { +interface ILoginHistorySuccessfulCellProps { row: { - original: ISignOnEvent; + original: ILoginEvent; }; value: boolean; } -export const SignOnLogSuccessfulCell: VFC = ({ - row, - value, -}) => { +export const LoginHistorySuccessfulCell: VFC< + ILoginHistorySuccessfulCellProps +> = ({ row, value }) => { const { searchQuery } = useSearchHighlightContext(); if (value) diff --git a/frontend/src/component/signOnLog/SignOnLogTable/SignOnLogTable.tsx b/frontend/src/component/loginHistory/LoginHistoryTable/LoginHistoryTable.tsx similarity index 87% rename from frontend/src/component/signOnLog/SignOnLogTable/SignOnLogTable.tsx rename to frontend/src/component/loginHistory/LoginHistoryTable/LoginHistoryTable.tsx index f3ae723a26..17906b85a5 100644 --- a/frontend/src/component/signOnLog/SignOnLogTable/SignOnLogTable.tsx +++ b/frontend/src/component/loginHistory/LoginHistoryTable/LoginHistoryTable.tsx @@ -16,17 +16,17 @@ import { Search } from 'component/common/Search/Search'; import { useConditionallyHiddenColumns } from 'hooks/useConditionallyHiddenColumns'; import { useSearch } from 'hooks/useSearch'; import { TimeAgoCell } from 'component/common/Table/cells/TimeAgoCell/TimeAgoCell'; -import { useSignOnLog } from 'hooks/api/getters/useSignOnLog/useSignOnLog'; -import { SignOnLogSuccessfulCell } from './SignOnLogSuccessfulCell/SignOnLogSuccessfulCell'; -import { ISignOnEvent } from 'interfaces/signOnEvent'; -import { SignOnLogActionsCell } from './SignOnLogActionsCell/SignOnLogActionsCell'; -import { SignOnLogDeleteDialog } from './SignOnLogDeleteDialog/SignOnLogDeleteDialog'; -import { useSignOnLogApi } from 'hooks/api/actions/useSignOnLogApi/useSignOnLogApi'; +import { useLoginHistory } from 'hooks/api/getters/useLoginHistory/useLoginHistory'; +import { LoginHistorySuccessfulCell } from './LoginHistorySuccessfulCell/LoginHistorySuccessfulCell'; +import { ILoginEvent } from 'interfaces/loginEvent'; +import { LoginHistoryActionsCell } from './LoginHistoryActionsCell/LoginHistoryActionsCell'; +import { LoginHistoryDeleteDialog } from './LoginHistoryDeleteDialog/LoginHistoryDeleteDialog'; +import { useLoginHistoryApi } from 'hooks/api/actions/useLoginHistoryApi/useLoginHistoryApi'; import { formatDateYMDHMS } from 'utils/formatDate'; import { useSearchParams } from 'react-router-dom'; import { createLocalStorage } from 'utils/createLocalStorage'; import { Delete, Download } from '@mui/icons-material'; -import { SignOnLogDeleteAllDialog } from './SignOnLogDeleteAllDialog/SignOnLogDeleteAllDialog'; +import { LoginHistoryDeleteAllDialog } from './LoginHistoryDeleteAllDialog/LoginHistoryDeleteAllDialog'; export type PageQueryType = Partial< Record<'sort' | 'order' | 'search', string> @@ -35,7 +35,7 @@ export type PageQueryType = Partial< const defaultSort: SortingRule = { id: 'created_at' }; const { value: storedParams, setValue: setStoredParams } = createLocalStorage( - 'SignOnLogTable:v1', + 'LoginHistoryTable:v1', defaultSort ); @@ -46,11 +46,11 @@ const AUTH_TYPE_LABEL: { [key: string]: string } = { google: 'Google', }; -export const SignOnLogTable = () => { +export const LoginHistoryTable = () => { const { setToastData, setToastApiError } = useToast(); - const { events, loading, refetch } = useSignOnLog(); - const { removeEvent, removeAllEvents, downloadCSV } = useSignOnLogApi(); + const { events, loading, refetch } = useLoginHistory(); + const { removeEvent, removeAllEvents, downloadCSV } = useLoginHistoryApi(); const [searchParams, setSearchParams] = useSearchParams(); const [initialState] = useState(() => ({ @@ -67,11 +67,11 @@ export const SignOnLogTable = () => { })); const [searchValue, setSearchValue] = useState(initialState.globalFilter); - const [selectedEvent, setSelectedEvent] = useState(); + const [selectedEvent, setSelectedEvent] = useState(); const [deleteOpen, setDeleteOpen] = useState(false); const [deleteAllOpen, setDeleteAllOpen] = useState(false); - const onDeleteConfirm = async (event: ISignOnEvent) => { + const onDeleteConfirm = async (event: ILoginEvent) => { try { await removeEvent(event.id); setToastData({ @@ -89,7 +89,7 @@ export const SignOnLogTable = () => { try { await removeAllEvents(); setToastData({ - title: `Log has been cleared`, + title: `History has been cleared`, type: 'success', }); refetch(); @@ -122,7 +122,7 @@ export const SignOnLogTable = () => { }, { Header: 'Authentication', - accessor: (event: ISignOnEvent) => + accessor: (event: ILoginEvent) => AUTH_TYPE_LABEL[event.auth_type] || event.auth_type, width: 150, maxWidth: 150, @@ -140,7 +140,7 @@ export const SignOnLogTable = () => { Header: 'Success', accessor: 'successful', align: 'center', - Cell: SignOnLogSuccessfulCell, + Cell: LoginHistorySuccessfulCell, filterName: 'success', filterParsing: (value: boolean) => value.toString(), }, @@ -149,7 +149,7 @@ export const SignOnLogTable = () => { id: 'Actions', align: 'center', Cell: ({ row: { original: event } }: any) => ( - { setSelectedEvent(event); setDeleteOpen(true); @@ -238,7 +238,7 @@ export const SignOnLogTable = () => { isLoading={loading} header={ { show={} /> @@ -269,7 +269,7 @@ export const SignOnLogTable = () => { { condition={searchValue?.length > 0} show={ - No sign-on events found matching “ + No login events found matching “ {searchValue} ” } elseShow={ - No sign-on events available. + No login events available. } /> } /> - - { +export const useLoginHistoryApi = () => { const { loading, makeRequest, createRequest, errors } = useAPI({ propagateErrors: true, }); @@ -8,7 +8,7 @@ export const useSignOnLogApi = () => { const downloadCSV = async () => { const requestId = 'downloadCSV'; const req = createRequest( - 'api/admin/signons', + 'api/admin/logins', { method: 'GET', responseType: 'blob', @@ -25,7 +25,7 @@ export const useSignOnLogApi = () => { const removeEvent = async (eventId: number) => { const requestId = 'removeEvent'; const req = createRequest( - `api/admin/signons/${eventId}`, + `api/admin/logins/${eventId}`, { method: 'DELETE' }, requestId ); @@ -36,7 +36,7 @@ export const useSignOnLogApi = () => { const removeAllEvents = async () => { const requestId = 'removeAllEvents'; const req = createRequest( - 'api/admin/signons', + 'api/admin/logins', { method: 'DELETE' }, requestId ); diff --git a/frontend/src/hooks/api/getters/useSignOnLog/useSignOnLog.ts b/frontend/src/hooks/api/getters/useLoginHistory/useLoginHistory.ts similarity index 68% rename from frontend/src/hooks/api/getters/useSignOnLog/useSignOnLog.ts rename to frontend/src/hooks/api/getters/useLoginHistory/useLoginHistory.ts index 812f078bdd..ab66c8060e 100644 --- a/frontend/src/hooks/api/getters/useSignOnLog/useSignOnLog.ts +++ b/frontend/src/hooks/api/getters/useLoginHistory/useLoginHistory.ts @@ -1,25 +1,25 @@ -import { ISignOnEvent } from 'interfaces/signOnEvent'; +import { ILoginEvent } from 'interfaces/loginEvent'; import { useMemo } from 'react'; import { formatApiPath } from 'utils/formatPath'; import handleErrorResponses from '../httpErrorResponseHandler'; import { useConditionalSWR } from '../useConditionalSWR/useConditionalSWR'; import useUiConfig from '../useUiConfig/useUiConfig'; -export const useSignOnLog = () => { +export const useLoginHistory = () => { const { uiConfig, isEnterprise } = useUiConfig(); - const { signOnLog } = uiConfig.flags; + const { loginHistory } = uiConfig.flags; const { data, error, mutate } = useConditionalSWR( - signOnLog && isEnterprise(), + loginHistory && isEnterprise(), { events: [] }, - formatApiPath(`api/admin/signons`), + formatApiPath(`api/admin/logins`), fetcher ); return useMemo( () => ({ - events: (data?.events ?? []) as ISignOnEvent[], + events: (data?.events ?? []) as ILoginEvent[], loading: !error && !data, refetch: () => mutate(), error, @@ -30,6 +30,6 @@ export const useSignOnLog = () => { const fetcher = (path: string) => { return fetch(path) - .then(handleErrorResponses('Sign-On Log')) + .then(handleErrorResponses('Login History')) .then(res => res.json()); }; diff --git a/frontend/src/interfaces/signOnEvent.ts b/frontend/src/interfaces/loginEvent.ts similarity index 82% rename from frontend/src/interfaces/signOnEvent.ts rename to frontend/src/interfaces/loginEvent.ts index 285709ac5c..c543829b30 100644 --- a/frontend/src/interfaces/signOnEvent.ts +++ b/frontend/src/interfaces/loginEvent.ts @@ -1,4 +1,4 @@ -export interface ISignOnEvent { +export interface ILoginEvent { id: number; username: string; auth_type: string; diff --git a/frontend/src/interfaces/uiConfig.ts b/frontend/src/interfaces/uiConfig.ts index e9f32e352c..945d3addd5 100644 --- a/frontend/src/interfaces/uiConfig.ts +++ b/frontend/src/interfaces/uiConfig.ts @@ -47,7 +47,7 @@ export interface IFlags { showProjectApiAccess?: boolean; proPlanAutoCharge?: boolean; notifications?: boolean; - signOnLog?: boolean; + loginHistory?: boolean; } export interface IVersionInfo { diff --git a/src/lib/__snapshots__/create-config.test.ts.snap b/src/lib/__snapshots__/create-config.test.ts.snap index ccd38d593a..2c650e6b8a 100644 --- a/src/lib/__snapshots__/create-config.test.ts.snap +++ b/src/lib/__snapshots__/create-config.test.ts.snap @@ -74,6 +74,7 @@ exports[`should create default config 1`] = ` "embedProxy": true, "embedProxyFrontend": true, "featuresExportImport": false, + "loginHistory": false, "maintenanceMode": false, "messageBanner": false, "newProjectOverview": false, @@ -83,7 +84,6 @@ exports[`should create default config 1`] = ` "proxyReturnAllToggles": false, "responseTimeWithAppNameKillSwitch": false, "showProjectApiAccess": false, - "signOnLog": false, "strictSchemaValidation": false, }, }, @@ -96,6 +96,7 @@ exports[`should create default config 1`] = ` "embedProxy": true, "embedProxyFrontend": true, "featuresExportImport": false, + "loginHistory": false, "maintenanceMode": false, "messageBanner": false, "newProjectOverview": false, @@ -105,7 +106,6 @@ exports[`should create default config 1`] = ` "proxyReturnAllToggles": false, "responseTimeWithAppNameKillSwitch": false, "showProjectApiAccess": false, - "signOnLog": false, "strictSchemaValidation": false, }, "externalResolver": { diff --git a/src/lib/types/experimental.ts b/src/lib/types/experimental.ts index 87addfaa88..2bafbb3fc1 100644 --- a/src/lib/types/experimental.ts +++ b/src/lib/types/experimental.ts @@ -63,7 +63,7 @@ const flags = { false, ), notifications: parseEnvVarBoolean(process.env.NOTIFICATIONS, false), - signOnLog: parseEnvVarBoolean(process.env.UNLEASH_SIGN_ON_LOG, false), + loginHistory: parseEnvVarBoolean(process.env.UNLEASH_LOGIN_HISTORY, false), }; export const defaultExperimentalOptions: IExperimentalOptions = { diff --git a/src/migrations/20230302133740-rename-sign-on-log-table-to-login-history.js b/src/migrations/20230302133740-rename-sign-on-log-table-to-login-history.js new file mode 100644 index 0000000000..dc061955d9 --- /dev/null +++ b/src/migrations/20230302133740-rename-sign-on-log-table-to-login-history.js @@ -0,0 +1,20 @@ +exports.up = function (db, cb) { + db.runSql(`ALTER TABLE sign_on_log RENAME TO login_history`, cb); + db.runSql(`DELETE FROM settings WHERE name = 'sign_on_log_retention'`, cb); + db.runSql( + `INSERT INTO settings(name, content) VALUES ('login_history_retention', '{"hours": 336}')`, + cb, + ); +}; + +exports.down = function (db, cb) { + db.runSql(`ALTER TABLE login_history RENAME TO sign_on_log`, cb); + db.runSql( + `DELETE FROM settings WHERE name = 'login_history_retention'`, + cb, + ); + db.runSql( + `INSERT INTO settings(name, content) VALUES ('sign_on_log_retention', '{"hours": 336}')`, + cb, + ); +};