appPassword: add expiry
This commit is contained in:
@@ -4,9 +4,8 @@ import { useI18n } from 'vue-i18n';
|
||||
const i18n = useI18n();
|
||||
const t = i18n.t;
|
||||
|
||||
import moment from 'moment-timezone';
|
||||
import { ref, onMounted, useTemplateRef } from 'vue';
|
||||
import { Button, ClipboardButton, Dialog, SingleSelect, FormGroup, TextInput, TableView, InputDialog, InputGroup } from '@cloudron/pankow';
|
||||
import { Button, ClipboardButton, DateTimeInput, Dialog, SingleSelect, FormGroup, TextInput, TableView, InputDialog, InputGroup } from '@cloudron/pankow';
|
||||
import { prettyLongDate } from '@cloudron/pankow/utils';
|
||||
import ActionBar from './ActionBar.vue';
|
||||
import Section from './Section.vue';
|
||||
@@ -35,7 +34,16 @@ const columns = {
|
||||
sort(a, b) {
|
||||
if (!a) return 1;
|
||||
if (!b) return -1;
|
||||
return moment(a).isBefore(b) ? 1 : -1;
|
||||
return new Date(a) - new Date(b);
|
||||
}
|
||||
},
|
||||
expiresAt: {
|
||||
label: t('profile.appPasswords.expires'),
|
||||
hideMobile: true,
|
||||
sort(a, b) {
|
||||
if (!a) return 1;
|
||||
if (!b) return -1;
|
||||
return new Date(a) - new Date(b);
|
||||
}
|
||||
},
|
||||
actions: {}
|
||||
@@ -54,6 +62,8 @@ const addedPassword = ref('');
|
||||
const passwordName = ref('');
|
||||
const identifiers = ref([]);
|
||||
const identifier = ref('');
|
||||
const expiresAtDate = ref('');
|
||||
const minExpiresAt = new Date().toISOString().slice(0, 16);
|
||||
const addError = ref('');
|
||||
const busy = ref(false);
|
||||
|
||||
@@ -62,16 +72,20 @@ async function refresh() {
|
||||
const [error, result] = await appPasswordsModel.list();
|
||||
if (error) return console.error(error);
|
||||
|
||||
// setup label for the table UI
|
||||
result.forEach(function (password) {
|
||||
if (password.identifier === 'mail') return password.label = password.identifier;
|
||||
const app = appsById[password.identifier];
|
||||
if (!app) return password.label = password.identifier + ' (App not found)';
|
||||
for (const password of result) {
|
||||
if (password.identifier === 'mail') {
|
||||
password.label = password.identifier;
|
||||
} else {
|
||||
const app = appsById[password.identifier];
|
||||
if (!app) return password.label = password.identifier + ' (App not found)';
|
||||
|
||||
const ftp = app.manifest.addons && app.manifest.addons.localstorage && app.manifest.addons.localstorage.ftp;
|
||||
const labelSuffix = ftp ? ' - SFTP' : '';
|
||||
password.label = app.label ? app.label + ' (' + app.fqdn + ')' + labelSuffix : app.fqdn + labelSuffix;
|
||||
});
|
||||
const ftp = app.manifest.addons && app.manifest.addons.localstorage && app.manifest.addons.localstorage.ftp;
|
||||
const labelSuffix = ftp ? ' - SFTP' : '';
|
||||
password.label = app.label ? app.label + ' (' + app.fqdn + ')' + labelSuffix : app.fqdn + labelSuffix;
|
||||
}
|
||||
|
||||
password.expired = password.expiresAt && new Date(password.expiresAt) < new Date();
|
||||
}
|
||||
|
||||
passwords.value = result;
|
||||
}
|
||||
@@ -86,6 +100,7 @@ function onReset() {
|
||||
setTimeout(() => {
|
||||
passwordName.value = '';
|
||||
identifier.value = '';
|
||||
expiresAtDate.value = '';
|
||||
addedPassword.value = '';
|
||||
addError.value = '';
|
||||
busy.value = false;
|
||||
@@ -100,7 +115,8 @@ async function onSubmit() {
|
||||
addError.value = '';
|
||||
addedPassword.value = '';
|
||||
|
||||
const [error, result] = await appPasswordsModel.add(identifier.value, passwordName.value);
|
||||
const expiresAt = expiresAtDate.value ? new Date(expiresAtDate.value).toISOString() : null;
|
||||
const [error, result] = await appPasswordsModel.add(identifier.value, passwordName.value, expiresAt);
|
||||
if (error) {
|
||||
busy.value = false;
|
||||
addError.value = error.body ? error.body.message : 'Internal error';
|
||||
@@ -110,6 +126,7 @@ async function onSubmit() {
|
||||
addedPassword.value = result.password;
|
||||
passwordName.value = '';
|
||||
identifier.value = '';
|
||||
expiresAtDate.value = '';
|
||||
|
||||
await refresh();
|
||||
|
||||
@@ -197,6 +214,11 @@ onMounted(async () => {
|
||||
<label>{{ $t('profile.createAppPassword.app') }}</label>
|
||||
<SingleSelect outline v-model="identifier" :options="identifiers" option-label="label" option-key="id" required/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<label for="expiresAt">{{ $t('profile.createAppPassword.expiresAt') }} (optional)</label>
|
||||
<DateTimeInput id="expiresAt" v-model="expiresAtDate" :min="minExpiresAt"/>
|
||||
</FormGroup>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
@@ -221,7 +243,13 @@ onMounted(async () => {
|
||||
<br/>
|
||||
|
||||
<TableView :columns="columns" :model="passwords" :placeholder="$t('profile.appPasswords.noPasswordsPlaceholder')">
|
||||
<template #creationTime="password">{{ prettyLongDate(password.creationTime) }}</template>
|
||||
<template #name="password"><span :class="{ 'text-muted': password.expired }">{{ password.name }}</span></template>
|
||||
<template #label="password"><span :class="{ 'text-muted': password.expired }">{{ password.label }}</span></template>
|
||||
<template #creationTime="password"><span :class="{ 'text-muted': password.expired }">{{ prettyLongDate(password.creationTime) }}</span></template>
|
||||
<template #expiresAt="password">
|
||||
<span :class="{ 'text-muted': password.expired }" v-if="!password.expiresAt">-</span>
|
||||
<span :class="{ 'text-muted': password.expired }" v-else>{{ prettyLongDate(password.expiresAt) }}</span>
|
||||
</template>
|
||||
<template #actions="password">
|
||||
<ActionBar :actions="createActionMenu(password)" />
|
||||
</template>
|
||||
|
||||
@@ -18,10 +18,10 @@ function create() {
|
||||
if (error || result.status !== 200) return [error || result];
|
||||
return [null, result.body.appPasswords];
|
||||
},
|
||||
async add(identifier, name) {
|
||||
async add(identifier, name, expiresAt) {
|
||||
let error, result;
|
||||
try {
|
||||
result = await fetcher.post(`${API_ORIGIN}/api/v1/app_passwords`, { identifier, name }, { access_token: accessToken });
|
||||
result = await fetcher.post(`${API_ORIGIN}/api/v1/app_passwords`, { identifier, name, expiresAt }, { access_token: accessToken });
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user