diff --git a/src/assets/views/auth-tokens.njk b/src/assets/views/auth-tokens.svelte similarity index 63% rename from src/assets/views/auth-tokens.njk rename to src/assets/views/auth-tokens.svelte index 7396754..503c883 100644 --- a/src/assets/views/auth-tokens.njk +++ b/src/assets/views/auth-tokens.svelte @@ -1,22 +1,31 @@ -{% extends 'layouts' %} + -{% set title = app.name + ' - Auth tokens' %} + +

Auth tokens

-{% block body %} -
-

Auth tokens

-
- {{ macros.csrf(getCsrfToken) }} +

+ + Auth tokens +

+ - -
+ - + @@ -24,40 +33,52 @@ - {% for token in auth_tokens %} + {#each $locals.auth_tokens as token} - + + + - - - {% endfor %} + {/each}
#SecretSecret Created at Last used at Actions
{{ token.id }}{token.id} -
-
{{ token.secret }}
- -
+ +
+ + + {#if token.used_at} + + {:else} + Never + {/if} {{ token.created_at.toISOString() }}{{ token.used_at.toISOString() }} -
- - {{ macros.csrf(getCsrfToken) }} -
+
+ +
-

Setup a desktop utility

+

+ + Setup a desktop utility +

There may be a desktop client at some point. For now, if you're an advanced user, you can setup scripts/macros.


First alternative: sh script (native on linux)

-

If you have the sh shell on your machine (i.e. you are on linux, git bash on windows...) and curl, you can - download and use these scripts:

+

If you have the sh shell on your machine (i.e. you are on linux, git bash on windows...) and curl, you + can download and use these scripts:

@@ -68,11 +89,11 @@ - + - +
upload_file.shDownloadDownload
shrink_url.shDownloadDownload
@@ -134,7 +155,7 @@ url_domain Choose domain name No - {{ allowed_domains.join('|') }} + {$locals.allowed_domains.join('|')} @@ -156,12 +177,11 @@ url_domain Choose domain name No - {{ allowed_domains.join('|') }} + {$locals.allowed_domains.join('|')}

For examples with curl, please download and review the scripts above.

-
-{% endblock %} +
diff --git a/src/controllers/AuthTokenController.ts b/src/controllers/AuthTokenController.ts index da6f62a..6166570 100644 --- a/src/controllers/AuthTokenController.ts +++ b/src/controllers/AuthTokenController.ts @@ -9,7 +9,7 @@ import AuthToken from "../models/AuthToken.js"; export default class AuthTokenController extends Controller { public routes(): void { - this.get('/auth-tokens', this.getAuthTokens, 'auth-tokens', RequireAuthMiddleware); + this.get('/auth-tokens/:page?', this.getAuthTokens, 'auth-tokens', RequireAuthMiddleware); this.post('/gen-auth-token', this.postGenAuthToken, 'generate-token', RequireAuthMiddleware); this.post('/revoke-auth-token/:id', this.postRevokeAuthToken, 'revoke-token', RequireAuthMiddleware); } @@ -17,10 +17,16 @@ export default class AuthTokenController extends Controller { public async getAuthTokens(req: Request, res: Response): Promise { const allowedDomains = config.get('allowed_url_domains'); const user = req.as(RequireAuthMiddleware).getUser(); + const authTokens = await AuthToken.paginateForUser(req, 2, user.getOrFail('id')); res.render('auth-tokens', { allowed_domains: allowedDomains, default_domain: allowedDomains[config.get('default_url_domain_for_files')], - auth_tokens: await AuthToken.select().where('user_id', user.id).get(), + auth_tokens: authTokens.map(token => ({ + ...token, + created_at: token.created_at?.toISOString(), + used_at: token.used_at?.toISOString(), + })), + pagination: authTokens.pagination?.serialize(), }); } diff --git a/src/models/AuthToken.ts b/src/models/AuthToken.ts index 329a85d..f0d78ca 100644 --- a/src/models/AuthToken.ts +++ b/src/models/AuthToken.ts @@ -1,14 +1,26 @@ +import {Request} from "express"; import {nanoid} from "nanoid"; import AuthProof from "swaf/auth/AuthProof"; import User from "swaf/auth/models/User"; import Model from "swaf/db/Model"; +import {ModelQueryResult} from "swaf/db/ModelQuery"; export default class AuthToken extends Model implements AuthProof { + public static async paginateForUser( + req: Request, + perPage: number, + user_id: number, + ): Promise> { + req.params.sortBy = 'created_at'; + req.params.sortDirection = 'DESC'; + return await this.paginate(req, perPage, this.select().where('user_id', user_id)); + } + public id?: number = undefined; protected readonly user_id?: number = undefined; private secret?: string = undefined; - protected created_at?: Date = undefined; - protected used_at?: Date = undefined; + public created_at?: Date = undefined; + public used_at?: Date = undefined; protected readonly ttl?: number = undefined; protected init(): void { @@ -23,6 +35,9 @@ export default class AuthToken extends Model implements AuthProof { } } + /** + * TODO promote this method to AuthProof interface in swaf and call it on successful authentication + */ public use(): void { this.used_at = new Date(); }