mirror of
https://github.com/logto-io/logto.git
synced 2024-12-30 20:33:54 -05:00
feat(core): modify and delete PATs (#6390)
This commit is contained in:
parent
22d0a06fc6
commit
fe054d5af5
5 changed files with 133 additions and 2 deletions
|
@ -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) {}
|
||||
|
||||
|
@ -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',
|
||||
});
|
||||
}
|
||||
|
||||
async getTokensByUserId(userId: string) {
|
||||
return this.pool.any<PersonalAccessToken>(sql`
|
||||
select ${sql.join(Object.values(fields), sql`, `)}
|
||||
|
|
|
@ -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."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
);
|
||||
|
||||
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();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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>();
|
||||
|
|
|
@ -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';
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue