Skip to content

Commit 8649a46

Browse files
authored
Merge pull request #2828 from devtron-labs/chore-data-test-is
feat: Integration of API token flag && Data test id in API Token
2 parents 5fb78da + 775df0d commit 8649a46

File tree

14 files changed

+181
-51
lines changed

14 files changed

+181
-51
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"private": true,
55
"homepage": "/dashboard",
66
"dependencies": {
7-
"@devtron-labs/devtron-fe-common-lib": "1.17.0-pre-12",
7+
"@devtron-labs/devtron-fe-common-lib": "1.17.0-pre-13",
88
"@esbuild-plugins/node-globals-polyfill": "0.2.3",
99
"@rjsf/core": "^5.13.3",
1010
"@rjsf/utils": "^5.13.3",

src/Pages/GlobalConfigurations/Authorization/APITokens/ApiTokens.component.tsx

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import {
2828
import emptyGeneratToken from '@Images/ic-empty-generate-token.png'
2929
import { EMPTY_STATE_STATUS } from '@Config/constantMessaging'
3030

31-
import { TokenListType, TokenResponseType } from './apiToken.type'
31+
import { TokenListType } from './apiToken.type'
3232
import APITokenList from './APITokenList'
3333
import CreateAPIToken from './CreateAPIToken'
3434
import EditAPIToken from './EditAPIToken'
@@ -90,13 +90,6 @@ const ApiTokens = () => {
9090
handleFilterChanges(_searchText)
9191
}
9292

93-
const [tokenResponse, setTokenResponse] = useState<TokenResponseType>({
94-
success: false,
95-
token: '',
96-
userId: 0,
97-
userIdentifier: 'API-TOKEN:test',
98-
})
99-
10093
const renderSearchToken = () => (
10194
<SearchBar
10295
initialSearchText={searchText}
@@ -131,8 +124,6 @@ const ApiTokens = () => {
131124
handleGenerateTokenActionButton={handleActionButton}
132125
setSelectedExpirationDate={setSelectedExpirationDate}
133126
selectedExpirationDate={selectedExpirationDate}
134-
tokenResponse={tokenResponse}
135-
setTokenResponse={setTokenResponse}
136127
reload={getData}
137128
/>
138129
</Route>

src/Pages/GlobalConfigurations/Authorization/APITokens/CreateAPIToken.tsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ import {
4343
usePermissionConfiguration,
4444
} from '../Shared/components/PermissionConfigurationForm'
4545
import { createUserPermissionPayload, validateDirectPermissionForm } from '../utils'
46-
import { FormType, GenerateTokenType } from './apiToken.type'
46+
import { FormType, GenerateTokenType, TokenResponseType } from './apiToken.type'
4747
import { getDateInMilliseconds } from './apiToken.utils'
4848
import ExpirationDate from './ExpirationDate'
4949
import GenerateActionButton from './GenerateActionButton'
@@ -69,8 +69,6 @@ const CreateAPIToken = ({
6969
handleGenerateTokenActionButton,
7070
setSelectedExpirationDate,
7171
selectedExpirationDate,
72-
tokenResponse,
73-
setTokenResponse,
7472
reload,
7573
}: GenerateTokenType) => {
7674
const history = useHistory()
@@ -106,6 +104,13 @@ const CreateAPIToken = ({
106104
allowManageAllAccess,
107105
} = usePermissionConfiguration()
108106
const [customDate, setCustomDate] = useState<Moment>(null)
107+
const [tokenResponse, setTokenResponse] = useState<TokenResponseType>({
108+
success: false,
109+
token: '',
110+
userId: 0,
111+
userIdentifier: 'API-TOKEN:test',
112+
hideApiToken: false,
113+
})
109114
const validationRules = new ValidationRules()
110115

111116
// Reset selected expiration date to 30 days on unmount
@@ -210,6 +215,7 @@ const CreateAPIToken = ({
210215
const userPermissionPayload = createUserPermissionPayload({
211216
id: result.userId,
212217
userIdentifier: result.userIdentifier,
218+
hideApiToken: result.hideApiToken,
213219
userRoleGroups,
214220
serverMode,
215221
directPermission,
@@ -308,13 +314,13 @@ const CreateAPIToken = ({
308314
buttonText="Generate token"
309315
disabled={isSaveDisabled}
310316
/>
311-
312317
<GenerateModal
313318
close={handleGenerateTokenActionButton}
314319
token={tokenResponse.token}
315320
reload={reload}
316321
redirectToTokenList={redirectToTokenList}
317322
open={showGenerateModal}
323+
hideApiToken={tokenResponse.hideApiToken}
318324
/>
319325
</div>
320326
)

src/Pages/GlobalConfigurations/Authorization/APITokens/EditAPIToken.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
Button,
2424
ButtonStyleType,
2525
ButtonVariantType,
26+
ClipboardButton,
2627
CustomInput,
2728
Icon,
2829
InfoBlock,
@@ -243,6 +244,19 @@ const EditAPIToken = ({
243244
placeholder="Enter a description to remember where you have used this token"
244245
error={invalidDescription ? 'Max 350 characters allowed.' : null}
245246
/>
247+
{!!editData?.token?.length && (
248+
<label className="form__row">
249+
<span className="form__label">Token</span>
250+
<div className="flex dc__content-space top cn-9">
251+
<span data-testid="api-token-string" className="mono fs-14 dc__word-break">
252+
{editData.token}
253+
</span>
254+
<div className="icon-dim-16 ml-8">
255+
<ClipboardButton content={editData.token} />
256+
</div>
257+
</div>
258+
</label>
259+
)}
246260
<div className="dc__border-top" />
247261
<PermissionConfigurationForm showUserPermissionGroupSelector isAddMode={false} />
248262
</div>

src/Pages/GlobalConfigurations/Authorization/APITokens/GenerateModal.tsx

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,16 @@ import {
2626
} from '@devtron-labs/devtron-fe-common-lib'
2727

2828
import { GenerateTokenModalType } from './apiToken.type'
29+
import { getApiTokenHeader } from './apiToken.utils'
2930

3031
const GenerateModal = ({
3132
close,
32-
token,
33+
token = '',
3334
reload,
3435
redirectToTokenList,
3536
isRegenerationModal,
3637
open,
38+
hideApiToken = false,
3739
}: GenerateTokenModalType) => {
3840
const [copyToClipboardPromise, setCopyToClipboardPromise] = useState<ReturnType<typeof copyToClipboard>>(null)
3941
const modelType = isRegenerationModal ? 'Regenerated' : 'Generated'
@@ -60,9 +62,7 @@ const GenerateModal = ({
6062
<GenericModal.Body>
6163
<div className="flexbox-col dc__gap-20 p-20">
6264
<div className="flexbox-col dc__gap-4">
63-
<h5 className="m-0 cn-9 lh-1-5 fw-6">
64-
Copy and store this token safely, you won’t be able to view it again.
65-
</h5>
65+
<h5 className="m-0 cn-9 lh-1-5 fw-6">{getApiTokenHeader(hideApiToken)}</h5>
6666
<p className="cn-7 fs-12 lh-1-5 m-0">
6767
You can regenerate a token anytime. If you do, remember to update any scripts or
6868
applications using the old token.
@@ -71,7 +71,11 @@ const GenerateModal = ({
7171

7272
<InfoBlock
7373
heading="API Token"
74-
description={token}
74+
description={
75+
<div className="fs-13 font-roboto flexbox dc__word-break" data-testid="generated-token">
76+
{token}
77+
</div>
78+
}
7579
variant="success"
7680
customIcon={<Icon name="ic-key" color="G500" />}
7781
/>

src/Pages/GlobalConfigurations/Authorization/APITokens/RegenerateModal.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ const RegeneratedModal = ({
117117
redirectToTokenList={redirectToTokenList}
118118
isRegenerationModal
119119
open={showGenerateModal}
120+
hideApiToken={tokenResponse.hideApiToken}
120121
/>
121122
) : (
122123
<VisibleModal className="regenerate-token-modal">

src/Pages/GlobalConfigurations/Authorization/APITokens/apiToken.type.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,10 @@ export interface FormType {
2626
}
2727
export interface TokenResponseType {
2828
success: boolean
29-
token: string
3029
userId: number
3130
userIdentifier: string
31+
hideApiToken: boolean
32+
token?: string
3233
}
3334

3435
export interface GenerateTokenType {
@@ -37,25 +38,24 @@ export interface GenerateTokenType {
3738
handleGenerateTokenActionButton: () => void
3839
setSelectedExpirationDate
3940
selectedExpirationDate
40-
tokenResponse: TokenResponseType
41-
setTokenResponse: React.Dispatch<React.SetStateAction<TokenResponseType>>
4241
reload: () => void
4342
}
4443

45-
export interface TokenListType {
44+
export interface TokenListType extends Pick<TokenResponseType, 'token' | 'userIdentifier' | 'userId' | 'hideApiToken'> {
4645
expireAtInMs: number
4746
id: number
4847
name: string
49-
userId: number
50-
userIdentifier: string
5148
description: string
5249
lastUsedByIp?: string
5350
lastUsedAt?: string
5451
updatedAt?: string
5552
}
5653

5754
export interface EditDataType
58-
extends Pick<TokenListType, 'name' | 'description' | 'expireAtInMs' | 'id' | 'userId' | 'userIdentifier'> {}
55+
extends Pick<
56+
TokenListType,
57+
'name' | 'description' | 'expireAtInMs' | 'token' | 'id' | 'userId' | 'userIdentifier' | 'hideApiToken'
58+
> {}
5959
export interface EditTokenType {
6060
setShowRegeneratedModal: React.Dispatch<React.SetStateAction<boolean>>
6161
showRegeneratedModal: boolean
@@ -77,11 +77,12 @@ export interface GenerateActionButtonType {
7777

7878
export interface GenerateTokenModalType {
7979
close: () => void
80-
token: string
80+
token: TokenListType['token']
8181
reload: () => void
8282
redirectToTokenList: () => void
8383
isRegenerationModal?: boolean
8484
open: GenericModalProps['open']
85+
hideApiToken: TokenListType['hideApiToken']
8586
}
8687

8788
export interface APITokenListType {

src/Pages/GlobalConfigurations/Authorization/APITokens/apiToken.utils.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
* limitations under the License.
1515
*/
1616

17+
import { TokenListType } from './apiToken.type'
18+
1719
export function getOptions(customDate) {
1820
return [
1921
{ value: 7, label: '7 days' },
@@ -36,3 +38,6 @@ export const isTokenExpired = (expiredDate: number): boolean => {
3638

3739
return getDateInMilliseconds(new Date().valueOf()) > getDateInMilliseconds(expiredDate)
3840
}
41+
42+
export const getApiTokenHeader = (hideApiToken: TokenListType['hideApiToken']) =>
43+
`Copy and store this token safely ${hideApiToken ? ', you won’t be able to view it again.' : ''}`

src/Pages/GlobalConfigurations/Authorization/types.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import {
3737
} from '@devtron-labs/devtron-fe-common-lib'
3838

3939
import { SERVER_MODE } from '../../../config'
40+
import { TokenResponseType } from './APITokens/apiToken.type'
4041
import { PermissionType, UserRoleType } from './constants'
4142

4243
export interface UserAndGroupPermissionsWrapProps {
@@ -311,7 +312,8 @@ export interface CreateUserPermissionPayloadParams
311312
extends Pick<User, 'userStatus' | 'timeToLive' | 'userRoleGroups' | 'canManageAllAccess'> {
312313
id: number
313314
userGroups: Pick<UserGroupType, 'name' | 'userGroupId'>[]
314-
userIdentifier: string
315+
hideApiToken?: TokenResponseType['hideApiToken']
316+
userIdentifier: TokenResponseType['userIdentifier']
315317
serverMode: SERVER_MODE
316318
directPermission: DirectPermissionsRoleFilter[]
317319
chartPermission: ChartGroupPermissionsFilter

0 commit comments

Comments
 (0)