-
Notifications
You must be signed in to change notification settings - Fork 39
feat (SDK): add sessions page #1081
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
52 commits
Select commit
Hold shift + click to select a range
f849c33
feat: add init code
paanSinghCoder e1eb6b5
Merge branch 'main' into feat/sessions-page-sdk
paanSinghCoder cc2d024
feat: add list items
paanSinghCoder 61d081f
style: add list styling
paanSinghCoder 7a01885
chore: minor changes
paanSinghCoder 25d8e05
chore: add data-test-id
paanSinghCoder adc7f41
chore: use IconButton instead of Image
paanSinghCoder 542ae9c
chore: import sort
paanSinghCoder bd71f02
chore: props
paanSinghCoder 6522eb3
Merge branch 'main' into feat/sessions-page-sdk
paanSinghCoder af26d99
Merge branch 'main' into feat/sessions-page-sdk
paanSinghCoder 6a6b6e4
Merge branch 'main' into feat/sessions-page-sdk
paanSinghCoder 71b8edf
Merge branch 'main' into feat/sessions-page-sdk
paanSinghCoder 1dd998f
feat: add api
paanSinghCoder ecd3cb9
fix: container scrollable
paanSinghCoder 6df4fe9
Merge branch 'main' into feat/sessions-page-sdk
paanSinghCoder 86b7fcb
chore: revert swagger files
paanSinghCoder 81bc445
feat: add ping user session api
paanSinghCoder 6023313
Merge branch 'main' into feat/sessions-page-sdk
paanSinghCoder 95c292f
Merge branch 'main' into feat/sessions-page-sdk
paanSinghCoder 03aae9a
Merge branch 'main' into feat/sessions-page-sdk
paanSinghCoder fabc34e
Merge branch 'main' into feat/sessions-page-sdk
paanSinghCoder 254fdf0
Merge branch 'main' into feat/sessions-page-sdk
paanSinghCoder fc9c19b
Merge branch 'main' into feat/sessions-page-sdk
paanSinghCoder 8e4f4ce
Merge branch 'main' into feat/sessions-page-sdk
paanSinghCoder 2474528
feat: handle time and formatting
paanSinghCoder 5f6da69
style: fix styling
paanSinghCoder e468c59
fix: refetch and css
paanSinghCoder 474013a
chore: keep current session first
paanSinghCoder 0996b64
chore: rename Revoke for current session
paanSinghCoder 494b277
chore: rename copy
paanSinghCoder e4286a5
style: title
paanSinghCoder 17357dd
chore: conditional show error message
paanSinghCoder 9929b93
chore: remove console
paanSinghCoder 89cbea0
fix: comments on PR
paanSinghCoder 08f0bc2
fix: remove comment
paanSinghCoder 9b1036b
fix: change useLastActivityTracker invoke strategy
paanSinghCoder bdbcb17
Apply suggestion from @paanSinghCoder
paanSinghCoder 6922fd8
Apply suggestion from @paanSinghCoder
paanSinghCoder cf79c95
Apply suggestion from @paanSinghCoder
paanSinghCoder 833dffb
Merge branch 'main' into feat/sessions-page-sdk
paanSinghCoder 4bb8372
Merge branch 'main' into feat/sessions-page-sdk
paanSinghCoder 3e9b5a7
Apply suggestion from @rsbh
paanSinghCoder 8fde07e
Apply suggestion from @rsbh
paanSinghCoder 197a5b8
Apply suggestion from @rsbh
paanSinghCoder f4b472e
fix: use unknown as type for error
paanSinghCoder bf73534
chore: use useQuery
paanSinghCoder 1c1a715
fix: use dayjs
paanSinghCoder 47e90e4
fix: pass onLogout via props from client
paanSinghCoder f809533
Update sdks/js/packages/core/react/components/organization/sessions/s…
paanSinghCoder bf96584
Update ui/src/pages/users/details/security/sessions/revoke-session-co…
paanSinghCoder fe0a439
Merge branch 'main' into feat/sessions-page-sdk
paanSinghCoder File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 3 additions & 0 deletions
3
sdks/js/packages/core/react/components/organization/sessions/index.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export { SessionsPage } from './sessions-page'; | ||
export { RevokeSessionConfirm } from './revoke-session-confirm'; | ||
export { RevokeSessionFinalConfirm } from './revoke-session-final-confirm'; |
152 changes: 152 additions & 0 deletions
152
sdks/js/packages/core/react/components/organization/sessions/revoke-session-confirm.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
import { useState, useMemo } from 'react'; | ||
import { useNavigate, useSearch, useRouteContext } from '@tanstack/react-router'; | ||
import { | ||
Button, | ||
Text, | ||
Dialog, | ||
Flex, | ||
List, | ||
Skeleton | ||
} from '@raystack/apsara/v1'; | ||
import { useSessions } from '../../../hooks/useSessions'; | ||
import { useMutation } from '@connectrpc/connect-query'; | ||
import { FrontierServiceQueries } from '@raystack/proton/frontier'; | ||
import { RevokeSessionFinalConfirm } from './revoke-session-final-confirm'; | ||
import styles from './sessions.module.css'; | ||
|
||
export const RevokeSessionConfirm = () => { | ||
const navigate = useNavigate({ from: '/sessions/revoke' }); | ||
const search = useSearch({ from: '/sessions/revoke' }) as { sessionId?: string }; | ||
const { sessions, revokeSession, isRevokingSession } = useSessions(); | ||
const { onLogout } = useRouteContext({ from: '__root__' }) as { onLogout?: () => void }; | ||
const [isFinalConfirmOpen, setIsFinalConfirmOpen] = useState(false); | ||
|
||
const { mutate: logout } = useMutation(FrontierServiceQueries.authLogout, { | ||
onSuccess: () => { | ||
if (onLogout) { | ||
onLogout(); | ||
} | ||
}, | ||
onError: (error) => { | ||
console.error('Failed to logout:', error); | ||
// Fallback to regular session revocation | ||
if (search.sessionId) { | ||
revokeSession(search.sessionId); | ||
navigate({ to: '/sessions' }); | ||
} | ||
}, | ||
}); | ||
|
||
// Find the session data based on sessionId from URL params | ||
const sessionData = useMemo(() => { | ||
if (!search.sessionId || sessions.length === 0) { | ||
return null; | ||
} | ||
|
||
const session = sessions.find(s => s.id === search.sessionId); | ||
if (!session) { | ||
console.error('Not found'); | ||
return null; | ||
} | ||
|
||
return session; | ||
}, [search.sessionId, sessions]); | ||
paanSinghCoder marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
const handleRevokeClick = () => { | ||
setIsFinalConfirmOpen(true); | ||
}; | ||
|
||
const handleFinalConfirm = () => { | ||
paanSinghCoder marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (!search.sessionId) return; | ||
|
||
if (sessionData?.isCurrent) { | ||
logout({}); | ||
return; | ||
} | ||
|
||
revokeSession(search.sessionId); | ||
navigate({ to: '/sessions' }); | ||
}; | ||
|
||
|
||
return ( | ||
<> | ||
{sessionData ? ( | ||
<Dialog open={true} onOpenChange={() => navigate({ to: '/sessions' })}> | ||
<Dialog.Content | ||
style={{ padding: 0, maxWidth: '400px', width: '100%' }} | ||
> | ||
<Dialog.Header className={styles.revokeSessionConfirmHeader}> | ||
<Flex justify="between" align="center" width="full"> | ||
<Text size="regular"> | ||
{sessionData.browser} on {sessionData.operatingSystem} | ||
</Text> | ||
<Dialog.CloseButton data-test-id="frontier-sdk-close-revoke-session-dialog" /> | ||
</Flex> | ||
</Dialog.Header> | ||
|
||
<Dialog.Body className={styles.revokeSessionConfirmBody}> | ||
<List className={styles.listRoot}> | ||
<List.Item className={styles.listItem}> | ||
<List.Label minWidth="120px">Device</List.Label> | ||
<List.Value>{sessionData.browser} on {sessionData.operatingSystem}</List.Value> | ||
</List.Item> | ||
<List.Item className={styles.listItem}> | ||
<List.Label minWidth="120px">IP Address</List.Label> | ||
<List.Value>{sessionData.ipAddress}</List.Value> | ||
</List.Item> | ||
<List.Item className={styles.listItem}> | ||
<List.Label minWidth="120px">Last Location</List.Label> | ||
<List.Value>{sessionData.location}</List.Value> | ||
</List.Item> | ||
<List.Item className={styles.listItem}> | ||
<List.Label minWidth="120px">Last Active</List.Label> | ||
<List.Value>{sessionData.lastActive}</List.Value> | ||
</List.Item> | ||
</List> | ||
</Dialog.Body> | ||
|
||
<Dialog.Footer> | ||
<Flex justify="end" gap={5}> | ||
<Button | ||
variant="outline" | ||
color="neutral" | ||
onClick={() => navigate({ to: '/sessions' })} | ||
data-test-id="frontier-sdk-cancel-revoke-session-dialog" | ||
> | ||
Cancel | ||
</Button> | ||
<Button | ||
variant="solid" | ||
color="danger" | ||
onClick={handleRevokeClick} | ||
data-test-id="frontier-sdk-confirm-revoke-session-dialog" | ||
> | ||
{sessionData?.isCurrent ? 'Logout' : 'Revoke'} | ||
</Button> | ||
</Flex> | ||
</Dialog.Footer> | ||
</Dialog.Content> | ||
</Dialog> | ||
) : ( | ||
<Dialog open={true} onOpenChange={() => navigate({ to: '/sessions' })}> | ||
<Dialog.Content style={{ padding: 0, maxWidth: '400px', width: '100%' }}> | ||
<Skeleton | ||
height="20px" | ||
containerStyle={{ padding: '2rem' }} | ||
count={4} | ||
/> | ||
</Dialog.Content> | ||
</Dialog> | ||
)} | ||
|
||
<RevokeSessionFinalConfirm | ||
isOpen={isFinalConfirmOpen} | ||
onOpenChange={setIsFinalConfirmOpen} | ||
onConfirm={handleFinalConfirm} | ||
isLoading={isRevokingSession} | ||
isCurrentSession={sessionData?.isCurrent} | ||
/> | ||
</> | ||
); | ||
}; |
88 changes: 88 additions & 0 deletions
88
.../js/packages/core/react/components/organization/sessions/revoke-session-final-confirm.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import { | ||
Button, | ||
toast, | ||
Dialog, | ||
Flex, | ||
Text | ||
} from '@raystack/apsara/v1'; | ||
import styles from './sessions.module.css'; | ||
|
||
const getErrorMessage = (error: unknown): string => { | ||
if (error && typeof error === 'object' && 'status' in error && error.status === 500) { | ||
return 'Something went wrong'; | ||
} | ||
return error instanceof Error ? error.message : 'Something went wrong'; | ||
}; | ||
|
||
interface RevokeSessionFinalConfirmProps { | ||
isOpen: boolean; | ||
onOpenChange: (isOpen: boolean) => void; | ||
onConfirm: () => void; | ||
isLoading?: boolean; | ||
isCurrentSession?: boolean; | ||
} | ||
|
||
export const RevokeSessionFinalConfirm = ({ | ||
isOpen, | ||
onOpenChange, | ||
onConfirm, | ||
isLoading = false, | ||
isCurrentSession = false | ||
}: RevokeSessionFinalConfirmProps) => { | ||
const handleConfirm = async () => { | ||
try { | ||
onConfirm(); | ||
onOpenChange(false); | ||
} catch (error: any) { | ||
toast.error('Failed to revoke session', { | ||
description: getErrorMessage(error) | ||
}); | ||
} | ||
}; | ||
|
||
return ( | ||
<Dialog open={isOpen} onOpenChange={onOpenChange}> | ||
<Dialog.Content | ||
style={{ padding: 0, maxWidth: '400px', width: '100%' }} | ||
> | ||
<Dialog.Header className={styles.revokeSessionConfirmHeader}> | ||
<Dialog.Title>Revoke</Dialog.Title> | ||
<Dialog.CloseButton data-test-id="frontier-sdk-close-final-revoke-dialog" /> | ||
</Dialog.Header> | ||
|
||
<Dialog.Body className={styles.revokeSessionFinalConfirmBody}> | ||
<Flex direction="column" gap={4}> | ||
<Text size="small" variant="secondary"> | ||
Are you sure you want to revoke this session? This action cannot be undone. | ||
</Text> | ||
</Flex> | ||
</Dialog.Body> | ||
|
||
<Dialog.Footer> | ||
<Flex justify="end" gap={5}> | ||
<Button | ||
variant="outline" | ||
color="neutral" | ||
onClick={() => onOpenChange(false)} | ||
data-test-id="frontier-sdk-cancel-final-revoke-dialog" | ||
disabled={isLoading} | ||
> | ||
Cancel | ||
</Button> | ||
<Button | ||
variant="solid" | ||
color="danger" | ||
onClick={handleConfirm} | ||
data-test-id="frontier-sdk-confirm-final-revoke-dialog" | ||
disabled={isLoading} | ||
loading={isLoading} | ||
loaderText={isCurrentSession ? "Signing out..." : "Revoking..."} | ||
> | ||
{isCurrentSession ? 'Logout' : 'Revoke'} | ||
</Button> | ||
</Flex> | ||
</Dialog.Footer> | ||
</Dialog.Content> | ||
</Dialog> | ||
); | ||
}; |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.