Skip to content

Commit 81dacc6

Browse files
authored
DG26-10: API key creation inconsistency (#2845)
1 parent b5d26cd commit 81dacc6

4 files changed

Lines changed: 49 additions & 11 deletions

File tree

crates/defguard_core/src/enterprise/handlers/api_tokens.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,16 @@ pub async fn add_api_token(
4949
));
5050
}
5151

52+
if !user.is_active {
53+
error!(
54+
"User {} attempted to create API token for inactive user {username}",
55+
session.user.username
56+
);
57+
return Err(WebError::Forbidden(
58+
"Cannot create API token for inactive user",
59+
));
60+
}
61+
5262
// TODO: check if the name is already used
5363

5464
// generate token string

crates/defguard_core/tests/integration/api/api_tokens.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,11 +363,33 @@ async fn dg25_3_test_token_invalidation(_: PgPoolOptions, options: PgConnectOpti
363363
let user_details = fetch_user_details(&client, "hpotter").await;
364364
assert!(!user_details.user.is_active);
365365

366+
// cannot create a new token for an inactive user
367+
let response = client
368+
.post("/api/v1/user/hpotter/api_token")
369+
.json(&AddApiTokenData {
370+
name: "inactive user token".into(),
371+
})
372+
.send()
373+
.await;
374+
assert_eq!(response.status(), StatusCode::FORBIDDEN);
375+
376+
// re-enable the user
377+
let mut user_details = fetch_user_details(&client, "hpotter").await;
378+
user_details.user.is_active = true;
379+
let response = client
380+
.put("/api/v1/user/hpotter")
381+
.json(&user_details.user)
382+
.send()
383+
.await;
384+
assert_eq!(response.status(), StatusCode::OK);
385+
let user_details = fetch_user_details(&client, "hpotter").await;
386+
assert!(user_details.user.is_active);
387+
366388
// log out
367389
let response = client.post("/api/v1/auth/logout").send().await;
368390
assert_eq!(response.status(), StatusCode::OK);
369391

370-
// cannot use token for authentication anymore
392+
// cannot use token for authentication anymore after reactivation
371393
let response = client
372394
.get("/api/v1/me")
373395
.header(

web/messages/en/modal.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@
116116
"modal_add_api_title": "Add API token",
117117
"modal_add_api_token_copy_copy_label": "API Token",
118118
"modal_add_api_token_copy_warning": "Please copy and save the API token below now. You won't be able to see it again.",
119+
"modal_add_api_token_disabled_user_error": "Can't create API token for disabled user",
119120
"modal_rename_api_title": "Rename API token",
120121
"modal_add_user_title": "Add new user",
121122
"modal_add_new_device_title": "Add new device",

web/src/pages/user-profile/UserProfilePage/tabs/ProfileApiTokensTab/ProfileApiTokensTab.tsx

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { LayoutGrid } from '../../../../../shared/components/LayoutGrid/LayoutGr
33
import { Button } from '../../../../../shared/defguard-ui/components/Button/Button';
44
import { EmptyStateFlexible } from '../../../../../shared/defguard-ui/components/EmptyStateFlexible/EmptyStateFlexible';
55
import { SizedBox } from '../../../../../shared/defguard-ui/components/SizedBox/SizedBox';
6+
import { Snackbar } from '../../../../../shared/defguard-ui/providers/snackbar/snackbar';
67
import { ThemeSpacing } from '../../../../../shared/defguard-ui/types';
78
import { openModal } from '../../../../../shared/hooks/modalControls/modalsSubjects';
89
import { ModalName } from '../../../../../shared/hooks/modalControls/modalTypes';
@@ -44,8 +45,20 @@ export const ProfileApiTokensTab = ({ availability, isLoading }: Props) => {
4445

4546
const AvailableProfileApiTokensTab = () => {
4647
const username = useUserProfile((s) => s.user.username);
48+
const isUserActive = useUserProfile((s) => s.user.is_active);
4749
const apiTokens = useUserProfile((s) => s.apiTokens);
4850

51+
const handleAddApiToken = () => {
52+
if (!isUserActive) {
53+
Snackbar.error(m.modal_add_api_token_disabled_user_error());
54+
return;
55+
}
56+
57+
openModal(ModalName.AddApiToken, {
58+
username,
59+
});
60+
};
61+
4962
return (
5063
<>
5164
{apiTokens.length === 0 && (
@@ -57,11 +70,7 @@ const AvailableProfileApiTokensTab = () => {
5770
iconLeft: 'add-token',
5871
testId: 'add-token',
5972
text: m.profile_api_tokens_add(),
60-
onClick: () => {
61-
openModal(ModalName.AddApiToken, {
62-
username,
63-
});
64-
},
73+
onClick: handleAddApiToken,
6574
}}
6675
/>
6776
)}
@@ -72,11 +81,7 @@ const AvailableProfileApiTokensTab = () => {
7281
<Button
7382
text={m.profile_api_tokens_add()}
7483
iconLeft="add-token"
75-
onClick={() => {
76-
openModal(ModalName.AddApiToken, {
77-
username,
78-
});
79-
}}
84+
onClick={handleAddApiToken}
8085
/>
8186
</ProfileTabHeader>
8287
<ProfileApiTokensTable />

0 commit comments

Comments
 (0)