case 4688 - agent User flag and agent tokens on the user form
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -102,6 +102,102 @@
|
||||
@change="fieldValueChanged('allowLogin')"
|
||||
></v-checkbox>
|
||||
</v-col>
|
||||
<!-- case 4688: AI agent: no login page sign-in, connects to /mcp with an agent token -->
|
||||
<v-col cols="12" sm="6" lg="4" xl="3">
|
||||
<v-checkbox
|
||||
ref="agent"
|
||||
v-model="obj.agent"
|
||||
dense
|
||||
:readonly="formState.readOnly"
|
||||
:disabled="obj.id === 1"
|
||||
:label="$sock.t('UserAgent')"
|
||||
:hint="$sock.t('UserAgentHint')"
|
||||
persistent-hint
|
||||
data-cy="agent"
|
||||
:error-messages="form().serverErrors(this, 'agent')"
|
||||
@change="fieldValueChanged('agent')"
|
||||
></v-checkbox>
|
||||
</v-col>
|
||||
<v-col v-if="obj.agent && obj.id != 0" cols="12">
|
||||
<v-card outlined class="pa-3" data-cy="agentTokens">
|
||||
<div class="text-subtitle-1">
|
||||
{{ $sock.t("AgentTokens") }}
|
||||
</div>
|
||||
<v-alert
|
||||
v-if="newAgentToken"
|
||||
type="warning"
|
||||
dense
|
||||
class="mt-2"
|
||||
>
|
||||
{{ $sock.t("AgentTokenShowOnce") }}
|
||||
<div
|
||||
class="text-body-2 mt-2"
|
||||
style="word-break: break-all"
|
||||
>
|
||||
<code>{{ newAgentToken }}</code>
|
||||
</div>
|
||||
</v-alert>
|
||||
<v-simple-table v-if="agentTokens.length > 0" dense>
|
||||
<tbody>
|
||||
<tr v-for="t in agentTokens" :key="t.id">
|
||||
<td>{{ t.name }}</td>
|
||||
<td class="text-caption">
|
||||
{{ $sock.t("AgentTokenExpires") }}:
|
||||
{{
|
||||
t.expires
|
||||
? tokenDate(t.expires)
|
||||
: $sock.t("AgentTokenNever")
|
||||
}}
|
||||
<br />
|
||||
{{ $sock.t("AgentTokenLastUsed") }}:
|
||||
{{ tokenDate(t.lastUsed) }}
|
||||
</td>
|
||||
<td>
|
||||
<span v-if="t.revoked" class="text-caption">
|
||||
{{ $sock.t("AgentTokenRevoked") }}
|
||||
{{ tokenDate(t.revoked) }}
|
||||
</span>
|
||||
<v-btn
|
||||
v-else-if="rights.change"
|
||||
small
|
||||
@click="revokeAgentToken(t)"
|
||||
>{{ $sock.t("AgentTokenRevoke") }}</v-btn
|
||||
>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</v-simple-table>
|
||||
<div v-else class="text-caption my-2">
|
||||
{{ $sock.t("AgentTokenNone") }}
|
||||
</div>
|
||||
<v-row v-if="rights.change" dense align="center">
|
||||
<v-col cols="12" sm="6">
|
||||
<v-text-field
|
||||
v-model="newAgentTokenName"
|
||||
dense
|
||||
:label="$sock.t('AgentTokenName')"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
<v-col cols="6" sm="3">
|
||||
<v-text-field
|
||||
v-model.number="newAgentTokenDays"
|
||||
dense
|
||||
type="number"
|
||||
min="0"
|
||||
:label="$sock.t('AgentTokenExpiresDays')"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
<v-col cols="6" sm="3">
|
||||
<v-btn
|
||||
small
|
||||
color="primary"
|
||||
@click="createAgentToken()"
|
||||
>{{ $sock.t("AgentTokenCreate") }}</v-btn
|
||||
>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card>
|
||||
</v-col>
|
||||
<v-col v-if="obj.allowLogin" cols="12" sm="6" lg="4" xl="3">
|
||||
<v-text-field
|
||||
id="username"
|
||||
@@ -446,6 +542,7 @@ export default {
|
||||
concurrency: 0,
|
||||
active: true,
|
||||
allowLogin: true,
|
||||
agent: false,
|
||||
name: null,
|
||||
roles: null,
|
||||
userType: 2,
|
||||
@@ -460,6 +557,10 @@ export default {
|
||||
lastLogin: null
|
||||
},
|
||||
|
||||
agentTokens: [],
|
||||
newAgentToken: null,
|
||||
newAgentTokenName: null,
|
||||
newAgentTokenDays: 90,
|
||||
optionsObj: {
|
||||
id: 0,
|
||||
concurrency: 0,
|
||||
@@ -641,6 +742,7 @@ export default {
|
||||
vm.formState.loading = false;
|
||||
} else {
|
||||
vm.obj = res.data;
|
||||
await vm.getAgentTokens();
|
||||
generateMenu(vm);
|
||||
window.$gz.form.setFormState({
|
||||
vm: vm,
|
||||
@@ -848,6 +950,66 @@ export default {
|
||||
window.$gz.errorHandler.handleFormError(error, vm);
|
||||
}
|
||||
},
|
||||
//case 4688: agent tokens
|
||||
tokenDate(d) {
|
||||
if (!d) {
|
||||
return "-";
|
||||
}
|
||||
return window.$gz.locale.utcDateToShortDateAndTimeLocalized(
|
||||
d,
|
||||
window.$gz.locale.getResolvedTimeZoneName(),
|
||||
window.$gz.locale.getResolvedLanguage(),
|
||||
window.$gz.locale.getHour12()
|
||||
);
|
||||
},
|
||||
async getAgentTokens() {
|
||||
const vm = this;
|
||||
vm.newAgentToken = null;
|
||||
if (!vm.obj.agent || !vm.obj.id) {
|
||||
vm.agentTokens = [];
|
||||
return;
|
||||
}
|
||||
const res = await window.$gz.api.get(`agent-token/${vm.obj.id}`);
|
||||
if (!res.error) {
|
||||
vm.agentTokens = res.data;
|
||||
}
|
||||
},
|
||||
async createAgentToken() {
|
||||
const vm = this;
|
||||
window.$gz.form.deleteAllErrorBoxErrors(vm);
|
||||
const days =
|
||||
vm.newAgentTokenDays === "" || vm.newAgentTokenDays == null
|
||||
? null
|
||||
: vm.newAgentTokenDays;
|
||||
const res = await window.$gz.api.post("agent-token", {
|
||||
userId: vm.obj.id,
|
||||
name: vm.newAgentTokenName,
|
||||
expiresDays: days
|
||||
});
|
||||
if (res.error) {
|
||||
vm.formState.serverError = res.error;
|
||||
window.$gz.form.setErrorBoxErrors(vm);
|
||||
return;
|
||||
}
|
||||
await vm.getAgentTokens();
|
||||
vm.newAgentToken = res.data.token;
|
||||
vm.newAgentTokenName = null;
|
||||
},
|
||||
async revokeAgentToken(t) {
|
||||
const vm = this;
|
||||
if (
|
||||
(await window.$gz.dialog.confirmGeneric("AgentTokenRevoke")) != true
|
||||
) {
|
||||
return;
|
||||
}
|
||||
const res = await window.$gz.api.remove(`agent-token/${t.id}`);
|
||||
if (res.error) {
|
||||
vm.formState.serverError = res.error;
|
||||
window.$gz.form.setErrorBoxErrors(vm);
|
||||
} else {
|
||||
await vm.getAgentTokens();
|
||||
}
|
||||
},
|
||||
async disableTfa() {
|
||||
const vm = this;
|
||||
|
||||
@@ -1101,6 +1263,19 @@ async function initForm(vm) {
|
||||
async function fetchTranslatedText() {
|
||||
await window.$gz.translation.cacheTranslations([
|
||||
"PasskeyRemoveAll",
|
||||
"UserAgent",
|
||||
"UserAgentHint",
|
||||
"AgentTokens",
|
||||
"AgentTokenCreate",
|
||||
"AgentTokenName",
|
||||
"AgentTokenExpiresDays",
|
||||
"AgentTokenShowOnce",
|
||||
"AgentTokenExpires",
|
||||
"AgentTokenNever",
|
||||
"AgentTokenLastUsed",
|
||||
"AgentTokenRevoke",
|
||||
"AgentTokenRevoked",
|
||||
"AgentTokenNone",
|
||||
"Vendor",
|
||||
"User",
|
||||
"UserSettings",
|
||||
|
||||
Reference in New Issue
Block a user