diff --git a/src/i18n/lang/en.json b/src/i18n/lang/en.json index 9afb29e84..e94eff8f5 100644 --- a/src/i18n/lang/en.json +++ b/src/i18n/lang/en.json @@ -150,8 +150,10 @@ "60d": "60 Days", "90d": "90 Days", "permissionExplanation": "Permissions allow you to scope what an api token is allowed to do.", + "titleRequired": "The title is required", "attributes": { "title": "Title", + "titlePlaceholder": "Enter a title you will recognize later", "expiresAt": "Expires at", "permissions": "Permissions" } diff --git a/src/modelTypes/IApiToken.ts b/src/modelTypes/IApiToken.ts index ce2627b63..189549c4d 100644 --- a/src/modelTypes/IApiToken.ts +++ b/src/modelTypes/IApiToken.ts @@ -6,6 +6,7 @@ export interface IApiPermission { export interface IApiToken extends IAbstract { id: number + title: string token: string permissions: IApiPermission expiresAt: Date diff --git a/src/models/apiTokenModel.ts b/src/models/apiTokenModel.ts index 8bcc277ca..20d21c1eb 100644 --- a/src/models/apiTokenModel.ts +++ b/src/models/apiTokenModel.ts @@ -3,6 +3,7 @@ import type {IApiToken} from '@/modelTypes/IApiToken' export default class ApiTokenModel extends AbstractModel { id = 0 + title = '' token = '' permissions = null expiresAt: Date = null diff --git a/src/views/user/settings/ApiTokens.vue b/src/views/user/settings/ApiTokens.vue index 685ed5d72..4e35092c1 100644 --- a/src/views/user/settings/ApiTokens.vue +++ b/src/views/user/settings/ApiTokens.vue @@ -16,6 +16,8 @@ const availableRoutes = ref(null) const newToken = ref(new ApiTokenModel()) const newTokenExpiry = ref(30) const newTokenPermissions = ref({}) +const newTokenTitleValid = ref(true) +const apiTokenTitle = ref() onMounted(async () => { tokens.value = await service.getAll() @@ -38,12 +40,17 @@ function deleteToken() { } async function createToken() { + if (!newTokenTitleValid.value) { + apiTokenTitle.value.focus() + return + } + const expiry = Number(newTokenExpiry.value) - if(!isNaN(expiry)) { + if (!isNaN(expiry)) { // if it's a number, we assume it's the number of days in the future newToken.value.expiresAt = new Date((new Date()) + expiry * MILLISECONDS_A_DAY) } - + newToken.value.permissions = {} Object.entries(newTokenPermissions.value).forEach(([key, ps]) => { const all = Object.entries(ps) @@ -54,7 +61,7 @@ async function createToken() { newToken.value.permissions[key] = all } }) - + const token = await service.create(newToken.value) newToken.value = new ApiTokenModel() newTokenExpiry.value = 30 @@ -113,19 +120,27 @@ async function createToken() { + :placeholder="$t('user.settings.apiTokens.attributes.titlePlaceholder')" + v-model="newToken.title" + @keyup="() => newTokenTitleValid = newToken.title !== ''" + @focusout="() => newTokenTitleValid = newToken.title !== ''" + /> +

+ {{ $t('user.settings.apiTokens.titleRequired') }} +

- +
- @@ -140,9 +155,9 @@ async function createToken() {

{{ $t('user.settings.apiTokens.permissionExplanation') }}

{{ group }}
-