diff --git a/packages/backend/src/controllers/api/v1/access-tokens/revoke-access-token.js b/packages/backend/src/controllers/api/v1/access-tokens/revoke-access-token.js new file mode 100644 index 00000000..95c7ffbc --- /dev/null +++ b/packages/backend/src/controllers/api/v1/access-tokens/revoke-access-token.js @@ -0,0 +1,15 @@ +export default async (request, response) => { + const token = request.params.token; + + const accessToken = await request.currentUser + .$relatedQuery('accessTokens') + .findOne({ + token, + revoked_at: null, + }) + .throwIfNotFound(); + + await accessToken.revoke(); + + response.status(204).send(); +}; diff --git a/packages/backend/src/models/access-token.js b/packages/backend/src/models/access-token.js index 7afb4776..f40a185f 100644 --- a/packages/backend/src/models/access-token.js +++ b/packages/backend/src/models/access-token.js @@ -27,6 +27,10 @@ class AccessToken extends Base { }, }, }); + + async revoke() { + return await this.$query().patch({ revokedAt: new Date().toISOString() }); + } } export default AccessToken; diff --git a/packages/backend/src/routes/api/v1/access-tokens.js b/packages/backend/src/routes/api/v1/access-tokens.js index 8d7ed14c..b41c3e0f 100644 --- a/packages/backend/src/routes/api/v1/access-tokens.js +++ b/packages/backend/src/routes/api/v1/access-tokens.js @@ -1,9 +1,16 @@ import { Router } from 'express'; import asyncHandler from 'express-async-handler'; import createAccessTokenAction from '../../../controllers/api/v1/access-tokens/create-access-token.js'; - +import revokeAccessTokenAction from '../../../controllers/api/v1/access-tokens/revoke-access-token.js'; +import { authenticateUser } from '../../../helpers/authentication.js'; const router = Router(); router.post('/', asyncHandler(createAccessTokenAction)); +router.delete( + '/:token', + authenticateUser, + asyncHandler(revokeAccessTokenAction) +); + export default router;