Skip to content

Commit

Permalink
feat(core): modify and delete PATs
Browse files Browse the repository at this point in the history
  • Loading branch information
wangsijie committed Aug 13, 2024
1 parent c74bc3a commit e60f84a
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 2 deletions.
10 changes: 9 additions & 1 deletion packages/core/src/queries/personal-access-tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export class PersonalAccessTokensQueries {
returning: true,
});

public readonly update = buildUpdateWhereWithPool(this.pool)(PersonalAccessTokens, true);
private readonly update = buildUpdateWhereWithPool(this.pool)(PersonalAccessTokens, true);

constructor(public readonly pool: CommonQueryMethods) {}

Expand All @@ -26,6 +26,14 @@ export class PersonalAccessTokensQueries {
`);
}

async updateName(userId: string, name: string, newName: string) {
return this.update({
where: { userId, name },
set: { name: newName },
jsonbMode: 'replace',
});
}

Check warning on line 35 in packages/core/src/queries/personal-access-tokens.ts

View check run for this annotation

Codecov / codecov/patch

packages/core/src/queries/personal-access-tokens.ts#L30-L35

Added lines #L30 - L35 were not covered by tests

async getTokensByUserId(userId: string) {
return this.pool.any<PersonalAccessToken>(sql`
select ${sql.join(Object.values(fields), sql`, `)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,53 @@
}
}
}
},
"/api/users/{userId}/personal-access-tokens/{name}": {
"delete": {
"summary": "Delete personal access token",
"description": "Delete a token for the user by name.",
"parameters": [
{
"name": "name",
"in": "path",
"description": "The name of the token."
}
],
"responses": {
"204": {
"description": "The token was deleted successfully."
}
}
},
"patch": {
"summary": "Update personal access token",
"description": "Update a token for the user by name.",
"parameters": [
{
"name": "name",
"in": "path",
"description": "The name of the token."
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"properties": {
"name": {
"description": "The token name to update. Must be unique within the user."
}
}
}
}
}
},
"responses": {
"204": {
"description": "The token was updated successfully."
}
}
}
}
}
}
37 changes: 37 additions & 0 deletions packages/core/src/routes/admin-user/personal-access-token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,41 @@ export default function adminUserPersonalAccessTokenRoutes<T extends ManagementA
return next();
}
);

router.delete(
'/users/:userId/personal-access-tokens/:name',
koaGuard({
params: z.object({ userId: z.string(), name: z.string() }),
status: [204, 404],
}),
async (ctx, next) => {
const {
params: { userId, name },
} = ctx.guard;

await queries.personalAccessTokens.deleteByName(userId, name);
ctx.status = 204;

return next();
}

Check warning on line 78 in packages/core/src/routes/admin-user/personal-access-token.ts

View check run for this annotation

Codecov / codecov/patch

packages/core/src/routes/admin-user/personal-access-token.ts#L70-L78

Added lines #L70 - L78 were not covered by tests
);

router.patch(
'/users/:userId/personal-access-tokens/:name',
koaGuard({
params: z.object({ userId: z.string(), name: z.string() }),
body: PersonalAccessTokens.updateGuard.pick({ name: true }).required(),
response: PersonalAccessTokens.guard,
status: [200, 400, 404],
}),
async (ctx, next) => {
const {
params: { userId, name },
body,
} = ctx.guard;

ctx.body = await queries.personalAccessTokens.updateName(userId, name, body.name);
return next();
}

Check warning on line 97 in packages/core/src/routes/admin-user/personal-access-token.ts

View check run for this annotation

Codecov / codecov/patch

packages/core/src/routes/admin-user/personal-access-token.ts#L90-L97

Added lines #L90 - L97 were not covered by tests
);
}
14 changes: 14 additions & 0 deletions packages/integration-tests/src/api/admin-user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,3 +143,17 @@ export const createPersonalAccessToken = async ({

export const getUserPersonalAccessTokens = async (userId: string) =>
authedAdminApi.get(`users/${userId}/personal-access-tokens`).json<PersonalAccessToken[]>();

export const deletePersonalAccessToken = async (userId: string, name: string) =>
authedAdminApi.delete(`users/${userId}/personal-access-tokens/${name}`);

export const updatePersonalAccessToken = async (
userId: string,
name: string,
body: Record<string, unknown>
) =>
authedAdminApi
.patch(`users/${userId}/personal-access-tokens/${name}`, {
json: body,
})
.json<PersonalAccessToken>();
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import { HTTPError } from 'ky';

import {
createPersonalAccessToken,
deletePersonalAccessToken,
deleteUser,
getUserPersonalAccessTokens,
updatePersonalAccessToken,
} from '#src/api/admin-user.js';
import { createUserByAdmin } from '#src/helpers/index.js';
import { devFeatureTest, randomString } from '#src/utils.js';
Expand Down Expand Up @@ -67,7 +69,7 @@ devFeatureTest.describe('personal access tokens', () => {
await deleteUser(user.id);
});

it('should be able to create, get multiple PATs', async () => {
it('should be able to create, get, and delete multiple PATs', async () => {
const user = await createUserByAdmin();
const name1 = randomString();
const name2 = randomString();
Expand All @@ -85,6 +87,29 @@ devFeatureTest.describe('personal access tokens', () => {
expect.arrayContaining([pat1, pat2])
);

await Promise.all([
deletePersonalAccessToken(user.id, name1),
deletePersonalAccessToken(user.id, name2),
]);
expect(await getUserPersonalAccessTokens(user.id)).toEqual([]);

await deleteUser(user.id);
});

it('should be able to update PAT', async () => {
const user = await createUserByAdmin();
const name = randomString();
await createPersonalAccessToken({
userId: user.id,
name,
});

const newName = randomString();
const updatedPat = await updatePersonalAccessToken(user.id, name, {
name: newName,
});
expect(updatedPat).toEqual(expect.objectContaining({ userId: user.id, name: newName }));

await deleteUser(user.id);
});
});

0 comments on commit e60f84a

Please sign in to comment.