diff --git a/frontend/src/i18n/lang/en.json b/frontend/src/i18n/lang/en.json index 3d4b43c12..91ec114d3 100644 --- a/frontend/src/i18n/lang/en.json +++ b/frontend/src/i18n/lang/en.json @@ -207,6 +207,13 @@ "tokenCreatedSuccess": "Here is your new api token: {token}", "tokenCreatedNotSeeAgain": "Store it in a secure location, you won't see it again!", "selectAll": "Select all", + "presets": { + "title": "Quick presets", + "readOnly": "Read only", + "tasks": "Task management", + "projects": "Project management", + "fullAccess": "Full access" + }, "delete": { "header": "Delete this token", "text1": "Are you sure you want to delete the token \"{token}\"?", diff --git a/frontend/src/views/user/settings/ApiTokens.vue b/frontend/src/views/user/settings/ApiTokens.vue index 6c7f81624..4399b729a 100644 --- a/frontend/src/views/user/settings/ApiTokens.vue +++ b/frontend/src/views/user/settings/ApiTokens.vue @@ -41,6 +41,86 @@ const route = useRoute() const now = new Date() +interface TokenPreset { + id: string + groups: Record +} + +const presets: TokenPreset[] = [ + { + id: 'readOnly', + groups: { + '*': ['read_one', 'read_all'], + }, + }, + { + id: 'tasks', + groups: { + 'tasks': '*', + 'tasks_attachments': '*', + 'tasks_assignees': '*', + 'tasks_labels': '*', + 'tasks_comments': '*', + 'tasks_relations': '*', + 'labels': ['read_one', 'read_all', 'create'], + 'projects': ['read_one', 'read_all'], + 'projects_views': ['read_one', 'read_all'], + 'projects_views_tasks': ['read_one', 'read_all'], + }, + }, + { + id: 'projects', + groups: { + 'projects': '*', + 'projects_views': '*', + 'projects_teams': '*', + 'projects_users': '*', + 'projects_shares': '*', + 'projects_webhooks': '*', + 'projects_buckets': '*', + 'projects_views_tasks': '*', + 'tasks': ['read_one', 'read_all'], + 'teams': ['read_one', 'read_all'], + }, + }, + { + id: 'fullAccess', + groups: { + '*': '*', + }, + }, +] + +function applyPreset(preset: TokenPreset) { + resetPermissions() + + for (const [groupKey, permissions] of Object.entries(preset.groups)) { + if (groupKey === '*') { + // Apply to all groups + for (const group of Object.keys(availableRoutes.value)) { + applyPermissionsToGroup(group, permissions) + } + } else if (availableRoutes.value[groupKey]) { + applyPermissionsToGroup(groupKey, permissions) + } + } +} + +function applyPermissionsToGroup(group: string, permissions: string[] | '*') { + if (permissions === '*') { + // Select all permissions in this group + selectPermissionGroup(group, true) + newTokenPermissionsGroup.value[group] = true + } else { + for (const perm of permissions) { + if (newTokenPermissions.value[group]?.[perm] !== undefined) { + newTokenPermissions.value[group][perm] = true + } + } + toggleGroupPermissionsFromChild(group, true) + } +} + const flatPickerConfig = computed(() => ({ altFormat: t('date.altFormatLong'), altInput: true, @@ -334,6 +414,26 @@ function toggleGroupPermissionsFromChild(group: string, checked: boolean) {

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

+ + +
+ +
+ + {{ $t(`user.settings.apiTokens.presets.${preset.id}`) }} + +
+
+