Merge pull request 'Account views: Accounts, Ldap, Samba' (!426) from hyervoni/salix-front-mindshore:feature/AccountFormsView into dev
gitea/salix-front/pipeline/head This commit looks good Details

Reviewed-on: #426
Reviewed-by: Alex Moreno <alexm@verdnatura.es>
Reviewed-by: Javier Segarra <jsegarra@verdnatura.es>
This commit is contained in:
Javier Segarra 2024-06-11 19:14:29 +00:00
commit e9051f1ee8
9 changed files with 529 additions and 14 deletions

View File

@ -0,0 +1,104 @@
<script setup>
import { useI18n } from 'vue-i18n';
import FormModel from 'components/FormModel.vue';
import VnRow from 'components/ui/VnRow.vue';
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
import VnInput from 'src/components/common/VnInput.vue';
import axios from 'axios';
import useNotify from 'src/composables/useNotify.js';
const { t } = useI18n();
const { notify } = useNotify();
const onSynchronizeAll = async () => {
try {
notify(t('Synchronizing in the background'), 'positive');
await axios.patch(`Accounts/syncAll`);
} catch (error) {
console.error('Error synchronizing all accounts', error);
}
};
const onSynchronizeRoles = async () => {
try {
await axios.patch(`RoleInherits/sync`);
notify(t('Roles synchronized!'), 'positive');
} catch (error) {
console.error('Error synchronizing roles', error);
}
};
</script>
<template>
<QPage>
<VnSubToolbar />
<FormModel
:url="`AccountConfigs/${1}`"
:url-update="`AccountConfigs/${1}`"
model="AccountAccounts"
auto-load
>
<template #moreActions>
<QBtn
class="q-ml-none"
color="primary"
:label="t('accounts.syncAll')"
@click="onSynchronizeAll()"
/>
<QBtn
color="primary"
:label="t('accounts.syncRoles')"
@click="onSynchronizeRoles()"
/>
</template>
<template #form="{ data }">
<div class="q-gutter-y-sm">
<VnInput :label="t('accounts.homedir')" v-model="data.homedir" />
<VnInput :label="t('accounts.shell')" v-model="data.shell" />
<VnInput
:label="t('accounts.idBase')"
v-model="data.idBase"
type="number"
min="0"
/>
<VnRow>
<VnInput
:label="t('accounts.min')"
v-model="data.min"
type="number"
min="0"
/>
<VnInput
:label="t('accounts.max')"
v-model="data.max"
type="number"
min="0"
/>
</VnRow>
<VnRow>
<VnInput
:label="t('accounts.warn')"
v-model="data.warn"
type="number"
min="0"
/>
<VnInput
:label="t('accounts.inact')"
v-model="data.inact"
type="number"
min="0"
/>
</VnRow>
</div>
</template>
</FormModel>
</QPage>
</template>
<i18n>
es:
Roles synchronized!: ¡Roles sincronizados!
Synchronizing in the background: Sincronizando en segundo plano
</i18n>

View File

@ -8,12 +8,12 @@ import VnSearchbar from 'components/ui/VnSearchbar.vue';
import CardList from 'src/components/ui/CardList.vue'; import CardList from 'src/components/ui/CardList.vue';
import VnLv from 'src/components/ui/VnLv.vue'; import VnLv from 'src/components/ui/VnLv.vue';
import AclFilter from './Acls/AclFilter.vue'; import AclFilter from './Acls/AclFilter.vue';
import AclFormView from './Acls/AclFormView.vue';
import { useVnConfirm } from 'composables/useVnConfirm'; import { useVnConfirm } from 'composables/useVnConfirm';
import { useStateStore } from 'stores/useStateStore'; import { useStateStore } from 'stores/useStateStore';
import axios from 'axios'; import axios from 'axios';
import useNotify from 'src/composables/useNotify.js'; import useNotify from 'src/composables/useNotify.js';
import AclFormView from './Acls/AclFormView.vue';
defineProps({ defineProps({
id: { id: {

View File

@ -0,0 +1,171 @@
<script setup>
import { ref, onMounted, computed } from 'vue';
import { useI18n } from 'vue-i18n';
import FormModel from 'components/FormModel.vue';
import VnRow from 'components/ui/VnRow.vue';
import VnInput from 'src/components/common/VnInput.vue';
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
import { useArrayData } from 'src/composables/useArrayData';
import useNotify from 'src/composables/useNotify.js';
import axios from 'axios';
const { t } = useI18n();
const { notify } = useNotify();
const arrayData = useArrayData('AccountLdap');
const URL_UPDATE = `LdapConfigs/${1}`;
const URL_CREATE = `LdapConfigs`;
const DEFAULT_DATA = {
id: 1,
hasData: false,
groupDn: null,
password: null,
rdn: null,
server: null,
userDn: null,
};
const initialData = ref({
...DEFAULT_DATA,
});
const hasData = computed({
get: () => initialData.value.hasData,
set: (val) => {
initialData.value.hasData = val;
if (!val) formCustomFn.value = deleteMailForward;
else formCustomFn.value = null;
},
});
const initialDataLoaded = ref(false);
const formUrlCreate = ref(null);
const formUrlUpdate = ref(null);
const formCustomFn = ref(null);
const onTestConection = async () => {
try {
await axios.get(`LdapConfigs/test`);
notify(t('LDAP connection established!'), 'positive');
} catch (error) {
console.error('Error testing connection', error);
}
};
const getInitialLdapConfig = async () => {
try {
initialDataLoaded.value = false;
const { data } = await axios.get(URL_UPDATE);
initialData.value = data;
hasData.value = true;
return data;
} catch (error) {
hasData.value = false;
arrayData.destroy();
console.error('Error fetching initial LDAP config', error);
return null;
} finally {
// Si asignamos un valor a urlUpdate, debemos asignar null a urlCreate y viceversa, ya puede causar problemas en formModel
if (hasData.value) {
formUrlUpdate.value = URL_UPDATE;
formUrlCreate.value = null;
} else {
formUrlUpdate.value = null;
formUrlCreate.value = URL_CREATE;
}
initialDataLoaded.value = true;
}
};
const deleteMailForward = async () => {
try {
await axios.delete(URL_UPDATE);
initialData.value = { ...DEFAULT_DATA };
hasData.value = false;
notify(t('globals.dataSaved'), 'positive');
} catch (err) {
console.error('Error deleting mail forward', err);
}
};
onMounted(async () => await getInitialLdapConfig());
</script>
<template>
<QPage>
<VnSubToolbar />
<FormModel
:key="initialDataLoaded"
model="AccountLdap"
:form-initial-data="initialData"
:url-create="formUrlCreate"
:url-update="formUrlUpdate"
:save-fn="formCustomFn"
auto-load
@on-data-saved="getInitialLdapConfig()"
>
<template #moreActions>
<QBtn
class="q-ml-none"
color="primary"
:label="t('ldap.testConnection')"
@click="onTestConection()"
>
<QTooltip>
{{ t('ldap.testConnection') }}
</QTooltip>
</QBtn>
</template>
<template #form="{ data, validate }">
<VnRow class="row q-gutter-md">
<div class="col">
<QCheckbox
:label="t('ldap.enableSync')"
v-model="data.hasData"
@update:model-value="($event) => (hasData = $event)"
:toggle-indeterminate="false"
/>
</div>
</VnRow>
<template v-if="hasData">
<VnInput
:label="t('ldap.server')"
clearable
v-model="data.server"
:required="true"
:rules="validate('LdapConfig.server')"
/>
<VnInput
:label="t('ldap.rdn')"
clearable
v-model="data.rdn"
:required="true"
:rules="validate('LdapConfig.rdn')"
/>
<VnInput
:label="t('ldap.password')"
clearable
type="password"
v-model="data.password"
:required="true"
:rules="validate('LdapConfig.password')"
/>
<VnInput :label="t('ldap.userDN')" clearable v-model="data.userDn" />
<VnInput
:label="t('ldap.groupDN')"
clearable
v-model="data.groupDn"
/>
</template>
</template>
</FormModel>
</QPage>
</template>
<i18n>
es:
LDAP connection established!: ¡Conexión con LDAP establecida!
</i18n>

View File

@ -0,0 +1,187 @@
<script setup>
import { ref, onMounted, computed } from 'vue';
import { useI18n } from 'vue-i18n';
import FormModel from 'components/FormModel.vue';
import VnRow from 'components/ui/VnRow.vue';
import VnInput from 'src/components/common/VnInput.vue';
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
import { useArrayData } from 'src/composables/useArrayData';
import useNotify from 'src/composables/useNotify.js';
import axios from 'axios';
const { t } = useI18n();
const { notify } = useNotify();
const arrayData = useArrayData('AccountSamba');
const formModel = ref(null);
const URL_UPDATE = `SambaConfigs/${1}`;
const URL_CREATE = `SambaConfigs`;
const DEFAULT_DATA = {
id: 1,
hasData: false,
adDomain: null,
adController: null,
adUser: null,
adPassword: null,
userDn: null,
verifyCert: false,
};
const initialData = ref({
...DEFAULT_DATA,
});
const hasData = computed({
get: () => initialData.value.hasData,
set: (val) => {
initialData.value.hasData = val;
if (!val) formCustomFn.value = deleteMailForward;
else formCustomFn.value = null;
},
});
const initialDataLoaded = ref(false);
const formUrlCreate = ref(null);
const formUrlUpdate = ref(null);
const formCustomFn = ref(null);
const onTestConection = async () => {
try {
await axios.get(`SambaConfigs/test`);
notify(t('Samba connection established!'), 'positive');
} catch (error) {
console.error('Error testing connection', error);
}
};
const getInitialSambaConfig = async () => {
try {
initialDataLoaded.value = false;
const { data } = await axios.get(URL_UPDATE);
initialData.value = data;
hasData.value = true;
return data;
} catch (error) {
hasData.value = false;
arrayData.destroy();
console.error('Error fetching initial Samba config', error);
return null;
} finally {
if (hasData.value) {
formUrlUpdate.value = URL_UPDATE;
formUrlCreate.value = null;
} else {
formUrlUpdate.value = null;
formUrlCreate.value = URL_CREATE;
}
initialDataLoaded.value = true;
}
};
const deleteMailForward = async () => {
try {
await axios.delete(URL_UPDATE);
initialData.value = { ...DEFAULT_DATA };
hasData.value = false;
notify(t('globals.dataSaved'), 'positive');
} catch (err) {
console.error('Error deleting mail forward', err);
}
};
onMounted(async () => await getInitialSambaConfig());
</script>
<template>
<QPage>
<VnSubToolbar />
<FormModel
ref="formModel"
:key="initialDataLoaded"
model="AccountSamba"
:form-initial-data="initialData"
:url-create="formUrlCreate"
:url-update="formUrlUpdate"
:save-fn="formCustomFn"
auto-load
@on-data-saved="getInitialSambaConfig()"
>
<template #moreActions>
<QBtn
class="q-ml-none"
color="primary"
:label="t('samba.testConnection')"
:disable="formModel.hasChanges"
@click="onTestConection()"
>
<QTooltip>
{{ t('samba.testConnection') }}
</QTooltip>
</QBtn>
</template>
<template #form="{ data, validate }">
<VnRow class="row q-gutter-md">
<div class="col">
<QCheckbox
:label="t('samba.enableSync')"
v-model="data.hasData"
@update:model-value="($event) => (hasData = $event)"
:toggle-indeterminate="false"
/>
</div>
</VnRow>
<template v-if="hasData">
<VnInput
:label="t('samba.domainAD')"
clearable
v-model="data.adDomain"
:required="true"
:rules="validate('SambaConfigs.server')"
/>
<VnInput
:label="t('samba.domainController')"
clearable
v-model="data.adController"
:required="true"
:rules="validate('SambaConfigs.adController')"
/>
<VnInput
:label="t('samba.userAD')"
clearable
v-model="data.adUser"
:rules="validate('SambaConfigs.adUser')"
/>
<VnInput
:label="t('samba.passwordAD')"
clearable
type="password"
v-model="data.adPassword"
/>
<VnInput
:label="t('samba.domainPart')"
clearable
v-model="data.userDn"
:required="true"
:rules="validate('SambaConfigs.userDn')"
/>
<QCheckbox
:label="t('samba.verifyCertificate')"
v-model="data.verifyCert"
:rules="validate('SambaConfigs.groupDn')"
:toggle-indeterminate="false"
/>
</template>
</template>
</FormModel>
</QPage>
</template>
<i18n>
es:
Samba connection established!: ¡Conexión con LDAP establecida!
</i18n>

View File

@ -1,11 +1,9 @@
<script setup> <script setup>
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import FormModel from 'components/FormModel.vue'; import FormModel from 'components/FormModel.vue';
import VnInput from 'src/components/common/VnInput.vue'; import VnInput from 'src/components/common/VnInput.vue';
const route = useRoute();
const { t } = useI18n(); const { t } = useI18n();
</script> </script>

View File

@ -67,6 +67,7 @@ ldap:
groupDN: Group DN groupDN: Group DN
testConnection: Test connection testConnection: Test connection
success: LDAP connection established! success: LDAP connection established!
password: Password
samba: samba:
enableSync: Enable synchronization enableSync: Enable synchronization
domainController: Domain controller domainController: Domain controller
@ -78,6 +79,16 @@ samba:
verifyCertificate: Verify certificate verifyCertificate: Verify certificate
testConnection: Test connection testConnection: Test connection
success: Samba connection established! success: Samba connection established!
accounts:
homedir: Homedir base
shell: Shell
idBase: User and role base id
min: Min
max: Max
warn: Warn
inact: Inact
syncAll: Synchronize all
syncRoles: Synchronize roles
connections: connections:
refresh: Refresh refresh: Refresh
username: Username username: Username

View File

@ -70,6 +70,7 @@ mailAlias:
name: Nombre name: Nombre
isPublic: Público isPublic: Público
ldap: ldap:
password: Contraseña
enableSync: Habilitar sincronización enableSync: Habilitar sincronización
server: Servidor server: Servidor
rdn: RDN rdn: RDN
@ -86,9 +87,19 @@ samba:
userAD: Usuario AD userAD: Usuario AD
passwordAD: Contraseña AD passwordAD: Contraseña AD
domainPart: DN usuarios (sin la parte del dominio) domainPart: DN usuarios (sin la parte del dominio)
Verify certificate: Verificar certificado verifyCertificate: Verificar certificado
testConnection: Probar conexión testConnection: Probar conexión
success: ¡Conexión con Samba establecida! success: ¡Conexión con Samba establecida!
accounts:
homedir: Directorio base para carpetas de usuario
shell: Intérprete de línea de comandos
idBase: Id base usuarios y roles
min: Min
max: Max
warn: Warn
inact: Inact
syncAll: Sincronizar todo
syncRoles: Sincronizar roles
connections: connections:
refresh: Actualizar refresh: Actualizar
username: Nombre de usuario username: Nombre de usuario

View File

@ -460,7 +460,7 @@ onMounted(async () => {
style="margin-left: 1px" style="margin-left: 1px"
/> />
</QBtnGroup> </QBtnGroup>
<QBtnGroup push class="q-gutter-x-sm" flat style="margin-left: 0px"> <QBtnGroup push class="q-gutter-x-sm q-ml-none" flat>
<QBtn <QBtn
v-if="reason && state && (isHimSelf || isHr)" v-if="reason && state && (isHimSelf || isHr)"
:label="t('Reason')" :label="t('Reason')"

View File

@ -15,6 +15,9 @@ export default {
'AccountList', 'AccountList',
'AccountAliasList', 'AccountAliasList',
'AccountRoles', 'AccountRoles',
'AccountAccounts',
'AccountLdap',
'AccountSamba',
'AccountAcls', 'AccountAcls',
'AccountConnections', 'AccountConnections',
], ],
@ -36,6 +39,15 @@ export default {
}, },
component: () => import('src/pages/Account/AccountList.vue'), component: () => import('src/pages/Account/AccountList.vue'),
}, },
{
path: 'role-list',
name: 'AccountRoles',
meta: {
title: 'roles',
icon: 'group',
},
component: () => import('src/pages/Account/Role/AccountRoles.vue'),
},
{ {
path: 'alias-list', path: 'alias-list',
name: 'AccountAliasList', name: 'AccountAliasList',
@ -54,6 +66,36 @@ export default {
}, },
component: () => import('src/pages/Account/AccountConnections.vue'), component: () => import('src/pages/Account/AccountConnections.vue'),
}, },
{
path: 'accounts',
name: 'AccountAccounts',
meta: {
title: 'accounts',
icon: 'accessibility',
roles: ['itManagement'],
},
component: () => import('src/pages/Account/AccountAccounts.vue'),
},
{
path: 'ldap',
name: 'AccountLdap',
meta: {
title: 'ldap',
icon: 'account_tree',
roles: ['itManagement'],
},
component: () => import('src/pages/Account/AccountLdap.vue'),
},
{
path: 'samba',
name: 'AccountSamba',
meta: {
title: 'samba',
icon: 'preview',
roles: ['itManagement'],
},
component: () => import('src/pages/Account/AccountSamba.vue'),
},
{ {
path: 'acls', path: 'acls',
name: 'AccountAcls', name: 'AccountAcls',
@ -68,15 +110,6 @@ export default {
name: 'AccountAclForm', name: 'AccountAclForm',
component: () => import('src/pages/Account/Acls/AclFormView.vue'), component: () => import('src/pages/Account/Acls/AclFormView.vue'),
}, },
{
path: 'role-list',
name: 'AccountRoles',
meta: {
title: 'roles',
icon: 'group',
},
component: () => import('src/pages/Account/Role/AccountRoles.vue'),
},
], ],
}, },
], ],