Skip to content
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

Add "Log back as previous user" feature #193

Merged
merged 4 commits into from
Mar 31, 2022
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
20 changes: 15 additions & 5 deletions www/src/components/accounts/ServiceAccounts.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useCallback, useState } from 'react'
import React, { useCallback, useState, useContext } from 'react'
import { Box, Layer, TextInput } from 'grommet'
import { useMutation } from 'react-apollo'
import { Edit } from 'grommet-icons'
Expand All @@ -9,13 +9,14 @@ import { UserRow } from './User'
import { extendConnection, removeConnection, updateCache } from '../../utils/graphql'
import { useQuery } from 'react-apollo'
import { GqlError } from '../utils/Alert'
import { setToken } from '../../helpers/authentication'
import { setToken, setPreviousUserData, fetchToken } from '../../helpers/authentication'
import { SearchIcon } from './utils'
import { SectionContentContainer, SectionPortal } from '../Explore'
import { INPUT_WIDTH } from './constants'
import { LoopingLogo } from '../utils/AnimatedLogo'
import { Icon } from './Group'
import { DeleteUser } from '../users/DeleteUser'
import { CurrentUserContext } from '../login/CurrentUser'

function ServiceAccount({user, next, update}) {
const [open, setOpen] = useState(false)
Expand All @@ -27,12 +28,21 @@ function ServiceAccount({user, next, update}) {
window.location = '/'
}
})
const me = useContext(CurrentUserContext)

function handleImpersonateClick() {
setPreviousUserData({
me,
jwt: fetchToken(),
})
mutation()
}

return (
<>
<Box fill='horizontal' gap='small' direction='row' align='center' border={{side: 'bottom', color: 'light-6'}} pad={{right: 'small'}}>
<UserRow user={user} next={next.node} noborder notoggle />
<SecondaryButton label='impersonate' onClick={mutation} loading={loading} />
<SecondaryButton label='impersonate' onClick={handleImpersonateClick} loading={loading} />
<Icon icon={Edit} tooltip='edit' onClick={() => setOpen(true)} />
<DeleteUser id={user.id} update={update} />
</Box>
Expand All @@ -59,7 +69,7 @@ function ServiceAccount({user, next, update}) {
export function ServiceAccounts() {
const [q, setQ] = useState(null)
const {data, fetchMore} = useQuery(USERS_Q, {
variables: {q, serviceAccount: true},
variables: {q, serviceAccount: true},
fetchPolicy: 'cache-and-network'
})
const update = useCallback((cache, {data: {deleteUser}}) => updateCache(cache, {
Expand Down Expand Up @@ -99,4 +109,4 @@ export function ServiceAccounts() {
</SectionPortal>
</SectionContentContainer>
)
}
}
43 changes: 30 additions & 13 deletions www/src/components/users/EditUser.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import React, { useContext, useState, useEffect, useCallback } from 'react'
import { Box, Text } from 'grommet'
import { useFilePicker } from 'react-sage'
import { Button, InputCollection, ResponsiveInput, Select, User, Installed,
import { Button, InputCollection, ResponsiveInput, Select, User, Installed,
PublicKeys, Credentials, Password, Logout, Fingerprint } from 'forge-core'
import { useMutation, useQuery } from 'react-apollo'
import { Transaction } from 'grommet-icons'
import { OAUTH_URLS, UPDATE_USER } from './queries'
import Avatar from './Avatar'
import { StatusCritical, Checkmark } from 'grommet-icons'
Expand All @@ -16,7 +17,7 @@ import { SIDEBAR_WIDTH } from '../constants'
import { Keys } from './Keys'
import { SectionContentContainer, SectionPortal } from '../Explore'
import { LoginMethod } from './types'
import { wipeToken } from '../../helpers/authentication'
import { wipeToken, getPreviousUserData, setPreviousUserData, setToken } from '../../helpers/authentication'
import { EabCredentials } from './EabCredentials'
import { SectionChoice } from '../utils/SectionChoice'
import { Provider } from '../repos/misc'
Expand All @@ -26,7 +27,7 @@ import { host } from '../../helpers/hostname'

export const EditContext = React.createContext({})

function EditAvatar({me}) {
function EditAvatar({me, noClick=false}) {
const {files, onClick, HiddenFileInput} = useFilePicker({})
const [mutation] = useMutation(UPDATE_USER)
useEffect(() => {
Expand All @@ -37,7 +38,7 @@ function EditAvatar({me}) {

return (
<>
<Avatar user={me} size='50px' onClick={onClick} />
<Avatar user={me} size='50px' onClick={noClick ? null : onClick} />
<HiddenFileInput accept='.jpg, .jpeg, .png' multiple={false} />
</>
)
Expand Down Expand Up @@ -105,10 +106,18 @@ export default function EditUser() {
window.location = '/'
}, [])

const previousUserData = getPreviousUserData()

function handlePreviousUserClick() {
setToken(previousUserData.jwt)
setPreviousUserData(null)
window.location.reload()
}

return (
<Box fill>
<Box fill direction='row'>
<Box flex={false} background='backgroundColor' gap='xsmall' width={SIDEBAR_WIDTH}
<Box flex={false} background='backgroundColor' gap='xsmall' width={SIDEBAR_WIDTH}
pad='small'>
<Box flex={false} direction='row' gap='small' align='center' margin={{bottom: 'xsmall'}}>
<EditAvatar me={me} />
Expand All @@ -123,10 +132,18 @@ export default function EditUser() {
<EditSelect edit='tokens' name='Access Tokens' icon={<Fingerprint size='14px' />} />
<EditSelect edit='keys' name='Public Keys' icon={<PublicKeys size='14px' />} />
<EditSelect edit='credentials' name='Eab Credentials' icon={<Credentials size='14px' />} />
<SectionChoice
label='Logout'
<SectionChoice
label='Logout'
icon={<Logout size='14px' />}
onClick={logout} />
onClick={logout}
/>
{previousUserData && previousUserData.me.id !== me.id && (
<SectionChoice
label={`Log back as ${previousUserData.me.name}`}
icon={<Transaction size='14px' />}
onClick={handlePreviousUserClick}
/>
)}
</Box>
<Box fill>
<EditContent edit='user' name='User Attributes'>
Expand All @@ -147,19 +164,19 @@ export default function EditUser() {
<Provider provider={me.provider} width={40} />
</Attribute>
)}

<Attribute name='Login Method'>
<Select
name='login-method'
value={{value: attributes.loginMethod, label: attributes.loginMethod.toLocaleLowerCase()}}
onChange={({value}) => setAttributes({...attributes, loginMethod: value})}
options={Object.values(LoginMethod).map((m) => ({
label: m.toLocaleLowerCase(),
label: m.toLocaleLowerCase(),
value: m
}))} />
</Attribute>
{data && data.oauthUrls.map((url) => (
<OauthEnabler url={url} me={me} />
{data && data.oauthUrls.map((url, i) => (
<OauthEnabler url={url} me={me} key={url + i} />
))}
</Attributes>
<SectionPortal>
Expand Down Expand Up @@ -218,4 +235,4 @@ export default function EditUser() {
</Box>
</Box>
)
}
}
8 changes: 4 additions & 4 deletions www/src/components/utils/SectionChoice.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ export function SectionChoice({label, selected, icon, onClick}) {
return (
<Box background={selected ? 'sidebarHover' : null} focusIndicator={false}
hoverIndicator='sidebarHover' direction='row' align='center' gap='small'
round='3px' pad={{horizontal: 'small'}} height={SIDEBAR_ICON_HEIGHT}
round='3px' pad={{horizontal: 'small'}} height={SIDEBAR_ICON_HEIGHT}
onClick={onClick}>
{icon}
<Box fill='horizontal'>
<Text size='small'>{label}</Text>
<Box fill='horizontal' overflow="hidden">
<Text size='small' truncate>{label}</Text>
</Box>
</Box>
)
}
}
3 changes: 2 additions & 1 deletion www/src/constants.js
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export const AUTH_TOKEN = 'auth-token'
export const AUTH_TOKEN = 'auth-token'
export const AUTH_PREVIOUS_USER_DATA = 'auth-previous-user-data'
17 changes: 15 additions & 2 deletions www/src/helpers/authentication.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {AUTH_TOKEN} from '../constants'
import {AUTH_TOKEN, AUTH_PREVIOUS_USER_DATA} from '../constants'

export function wipeToken() {
localStorage.removeItem(AUTH_TOKEN)
Expand All @@ -10,4 +10,17 @@ export function fetchToken() {

export function setToken(token) {
localStorage.setItem(AUTH_TOKEN, token)
}
}

export function setPreviousUserData(userData) {
localStorage.setItem(AUTH_PREVIOUS_USER_DATA, JSON.stringify(userData))
michaeljguarino marked this conversation as resolved.
Show resolved Hide resolved
}

export function getPreviousUserData() {
try {
michaeljguarino marked this conversation as resolved.
Show resolved Hide resolved
return JSON.parse(localStorage.getItem(AUTH_PREVIOUS_USER_DATA)) || null
}
catch {
return null
}
}