119 lines
4.0 KiB
Vue
119 lines
4.0 KiB
Vue
<script setup>
|
|
|
|
import { ref, useTemplateRef } from 'vue';
|
|
import { Dialog, TextInput, FormGroup, MultiSelect } from '@cloudron/pankow';
|
|
import UsersModel from '../models/UsersModel.js';
|
|
import GroupsModel from '../models/GroupsModel.js';
|
|
import AppsModel from '../models/AppsModel.js';
|
|
|
|
const usersModel = UsersModel.create();
|
|
const groupsModel = GroupsModel.create();
|
|
const appsModel = AppsModel.create();
|
|
|
|
const emit = defineEmits([ 'success' ]);
|
|
|
|
const dialog = useTemplateRef('dialog');
|
|
|
|
// also determines if new or edit mode
|
|
const group = ref(null);
|
|
const busy = ref(false);
|
|
const formError = ref({});
|
|
const name = ref('');
|
|
const userIds = ref([]);
|
|
const allUsers = ref([]);
|
|
const appIds = ref([]);
|
|
const allApps = ref([]);
|
|
|
|
async function onSubmit() {
|
|
busy.value = true;
|
|
formError.value = {};
|
|
|
|
if (group.value) {
|
|
const [error] = await groupsModel.update(group.value.id, name.value, userIds.value, appIds.value);
|
|
if (error) {
|
|
if (error.body && error.body.message.indexOf('name') === 0) formError.value.name = error.body.message;
|
|
else formError.value.generic = error.body ? error.body.message : 'Internal error';
|
|
busy.value = false;
|
|
return console.error(error);
|
|
}
|
|
} else {
|
|
const [error] = await groupsModel.add(name.value, userIds.value, appIds.value);
|
|
if (error) {
|
|
if (error.body && error.body.message.indexOf('name') === 0) formError.value.name = error.body.message;
|
|
else formError.value.generic = error.body ? error.body.message : 'Internal error';
|
|
busy.value = false;
|
|
return console.error(error);
|
|
}
|
|
}
|
|
|
|
emit('success');
|
|
dialog.value.close();
|
|
busy.value = false;
|
|
}
|
|
|
|
defineExpose({
|
|
async open(g = null) {
|
|
g = g ? JSON.parse(JSON.stringify(g)) : null; // make a copy
|
|
group.value = g;
|
|
name.value = g ? g.name : '';
|
|
formError.value = {};
|
|
busy.value = false;
|
|
|
|
let [error, result] = await usersModel.list();
|
|
if (error) return console.error(error);
|
|
result.forEach(u => u.label = (u.username || u.email));
|
|
allUsers.value = result;
|
|
userIds.value = g ? g.userIds : [];
|
|
|
|
[error, result] = await appsModel.list();
|
|
if (error) return console.error(error);
|
|
result.forEach(a => a.label = (a.label || a.fqdn));
|
|
allApps.value = result;
|
|
appIds.value = g ? g.appIds : [];
|
|
|
|
dialog.value.open();
|
|
}
|
|
});
|
|
|
|
</script>
|
|
|
|
<template>
|
|
<Dialog ref="dialog"
|
|
:title="group ? $t('users.editGroupDialog.title') : $t('users.addGroupDialog.title')"
|
|
:confirm-label="group ? $t('main.dialog.save') : $t('users.group.addGroupAction')"
|
|
:confirm-busy="busy"
|
|
:confirm-active="!busy && name !== ''"
|
|
reject-style="secondary"
|
|
:reject-label="$t('main.dialog.cancel')"
|
|
:reject-active="!busy"
|
|
@confirm="onSubmit()"
|
|
>
|
|
<p class="text-warning" v-if="group?.source">{{ $t('users.editGroupDialog.externalLdapWarning') }}</p>
|
|
<form @submit.prevent="onSubmit()" autocomplete="off">
|
|
<fieldset :disabled="busy">
|
|
<input type="submit" style="display: none;" />
|
|
|
|
<div class="error-label" v-if="formError.generic">{{ formError.generic }}</div>
|
|
|
|
<FormGroup>
|
|
<label for="nameInput">{{ $t('users.group.name') }}</label>
|
|
<TextInput id="nameInput" v-model="name" required/>
|
|
<div class="error-label" v-if="formError.name">{{ formError.name }}</div>
|
|
</FormGroup>
|
|
|
|
<FormGroup>
|
|
<label for="usersInput">{{ $t('users.group.users') }}</label>
|
|
<!-- membership of external groups cannot be edited -->
|
|
<div v-if="group?.source"><span v-for="user of groupEdit.selectedUsers" :key="user.id"> {{ (user.username || user.email) }}</span></div>
|
|
<MultiSelect v-else v-model="userIds" :options="allUsers" option-key="id" :search-threshold="20"/>
|
|
</FormGroup>
|
|
|
|
<FormGroup>
|
|
<label for="appsInput">{{ $t('users.group.allowedApps') }}</label>
|
|
<MultiSelect v-model="appIds" :options="allApps" option-key="id" :search-threshold="20"/>
|
|
</FormGroup>
|
|
</fieldset>
|
|
</form>
|
|
</Dialog>
|
|
</template>
|