diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml
index 70caf3aaf..79b387f4a 100644
--- a/.github/workflows/checks.yml
+++ b/.github/workflows/checks.yml
@@ -99,6 +99,7 @@ jobs:
spec:
- login
- users
+ - apiKeys
- roles
- profiles
- resetpassword
diff --git a/CLAUDE.md b/CLAUDE.md
index 74bbe819d..e1722a5ba 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -46,7 +46,7 @@ proposer de migrer Vue en premier : `bootstrap-vue` 2 ne tourne pas sous
## Garde-fou
-Les 17 specs Cypress (`test/e2e/cypress/integration/single-backend/`) sont le
+Les 18 specs Cypress (`test/e2e/cypress/integration/single-backend/`) sont le
seul filet de sécurité du chantier — il n'y a pas de tests unitaires. Toute PR de
migration doit passer les specs du domaine touché. Ne jamais désactiver une spec
pour faire passer une migration : c'est le signal que la migration est fausse.
diff --git a/src/components/ApiKeys/MyApiKeys.vue b/src/components/ApiKeys/MyApiKeys.vue
new file mode 100644
index 000000000..54397b940
--- /dev/null
+++ b/src/components/ApiKeys/MyApiKeys.vue
@@ -0,0 +1,29 @@
+
+
+ My API keys
+
+
+
+
+
+
diff --git a/src/components/Common/Breadcrumb.vue b/src/components/Common/Breadcrumb.vue
index 0500aaae2..95513b5ca 100644
--- a/src/components/Common/Breadcrumb.vue
+++ b/src/components/Common/Breadcrumb.vue
@@ -15,6 +15,7 @@
'SecurityUsersCreate',
'SecurityUsersUpdate',
'SecurityUsersEditCustomMapping',
+ 'SecurityUsersApiKeys',
])
"
>
diff --git a/src/components/Common/SessionBar.vue b/src/components/Common/SessionBar.vue
index 0a5a8dc05..7d9d68dd5 100644
--- a/src/components/Common/SessionBar.vue
+++ b/src/components/Common/SessionBar.vue
@@ -66,6 +66,16 @@
+
+
+
+ My API keys
+
+
+
Log out
@@ -93,9 +103,10 @@ import {
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import { type ThemePreference, useTheme } from '@/composables/useTheme';
-import { useAuthStore } from '@/stores';
+import { useAuthStore, useKuzzleStore } from '@/stores';
const authStore = useAuthStore();
+const kuzzleStore = useKuzzleStore();
const router = useRouter();
const { preference, setPreference } = useTheme();
@@ -133,6 +144,12 @@ const profiles = computed((): string[] => {
return Array.isArray(profileIds) ? profileIds.filter((id) => typeof id === 'string') : [];
});
+// Une session anonyme n'a pas de clés à elle, ni un backend v1 (ADR-0070).
+const showMyApiKeys = computed(
+ () =>
+ authStore.canSearchOwnApiKeys && (kuzzleStore.currentEnvironment?.backendMajorVersion ?? 0) > 1,
+);
+
async function logout(): Promise {
try {
await authStore.doLogout();
diff --git a/src/components/Security/ApiKeys/ApiKeyList.vue b/src/components/Security/ApiKeys/ApiKeyList.vue
new file mode 100644
index 000000000..f9902547b
--- /dev/null
+++ b/src/components/Security/ApiKeys/ApiKeyList.vue
@@ -0,0 +1,252 @@
+
+
+
+
+ API keys require Kuzzle 2
+
+ This connection targets a Kuzzle 1 backend, which has no API keys.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ No API key
+
+
+ An API key lets an application or a script call Kuzzle as
+ {{ ownerLabel }}, without a password.
+
+
+
+
+
+
Create a new user
@@ -82,7 +94,7 @@
import { computed, onMounted, reactive, ref } from 'vue';
import { useVuelidate } from '@vuelidate/core';
import { helpers, not } from '@vuelidate/validators';
-import { useRoute, useRouter } from 'vue-router';
+import { RouterLink, useRoute, useRouter } from 'vue-router';
import MainSpinner from '../../Common/MainSpinner.vue';
import Headline from '../../Materialize/Headline.vue';
@@ -128,6 +140,11 @@ const strategies = ref([]);
const credentialsMapping = ref>({});
const customContent = ref('{}');
const customContentMapping = ref>({});
+// Les clés d'API n'existent qu'à partir de Kuzzle 2 (ADR-0070).
+const showApiKeys = computed(
+ () =>
+ authStore.canSearchApiKeys && (kuzzleStore.currentEnvironment?.backendMajorVersion ?? 0) > 1,
+);
// Les identifiants ne sont pas validés ici : leur forme dépend de la stratégie
// d'authentification, et c'est Kuzzle qui les refuse à l'enregistrement.
diff --git a/src/components/Security/Users/UserItem.vue b/src/components/Security/Users/UserItem.vue
index 0cbb38119..7fb7c1840 100644
--- a/src/components/Security/Users/UserItem.vue
+++ b/src/components/Security/Users/UserItem.vue
@@ -44,6 +44,18 @@