Various fixes about Reseller mode in frontend.

see #3268
This commit is contained in:
Antoine Nguyen
2025-07-14 16:03:57 +02:00
parent c28e42ec77
commit e306b0799a
24 changed files with 237 additions and 120 deletions
@@ -80,6 +80,7 @@
<script setup>
import accountApi from '@/api/accounts'
import domainApi from '@/api/domains'
import constants from '@/constants.json'
import { useBusStore } from '@/stores'
import { useGettext } from 'vue3-gettext'
import { ref, onMounted } from 'vue'
@@ -128,13 +129,15 @@ function fetchAdministrators(domain) {
}
function fetchAccounts() {
accountApi.getAll({ role: 'DomainAdmins' }).then((resp) => {
accounts.value = resp.data.filter(
(account) =>
administrators.value.find((admin) => admin.id === account.pk) ===
undefined
)
})
accountApi
.getAll({ role: [constants.RESELLER, constants.DOMAIN_ADMIN] })
.then((resp) => {
accounts.value = resp.data.filter(
(account) =>
administrators.value.find((admin) => admin.id === account.pk) ===
undefined
)
})
}
function addAdministrator() {
domainApi
@@ -138,7 +138,8 @@
v-if="
limitsConfig.params &&
limitsConfig.params.enable_domain_limits &&
(authUser.role === 'SuperAdmins' || authUser.role === 'Resellers')
(authUser.role === constants.SUPER_ADMIN ||
authUser.role === constants.RESELLER)
"
value="resourcesForm"
eager
@@ -184,6 +185,7 @@ import { useGettext } from 'vue3-gettext'
import { useAuthStore } from '@/stores'
import { useRouter } from 'vue-router'
import domainsApi from '@/api/domains'
import constants from '@/constants.json'
const router = useRouter()
const { $gettext } = useGettext()
@@ -219,8 +221,8 @@ const formMap = computed(() => {
if (
limitsConfig.value.params &&
limitsConfig.value.params.enable_domain_limits &&
(authUser.value.role === 'SuperAdmins' ||
authUser.value.role === 'Resellers')
(authUser.value.role === constants.SUPER_ADMIN ||
authUser.value.role === constants.RESELLER)
) {
map.resourcesForm = resourcesForm
}
@@ -68,6 +68,7 @@ import AccountRoleForm from './form_steps/AccountRoleForm.vue'
import AccountGeneralForm from './form_steps/AccountGeneralForm.vue'
import AccountMailboxForm from './form_steps/AccountMailboxForm.vue'
import AccountAliasForm from './form_steps/AccountAliasForm.vue'
import constants from '@/constants.json'
import { useGettext } from 'vue3-gettext'
import { ref, computed } from 'vue'
@@ -81,10 +82,7 @@ const domainsStore = useDomainsStore()
const emit = defineEmits(['close', 'created'])
const needsMailbox = computed(
() =>
account.value.role !== 'SuperAdmins' &&
account.value.username &&
account.value.username.indexOf('@') !== -1
() => account.value.username && account.value.username.indexOf('@') !== -1
)
const summarySections = computed(() => {
@@ -187,7 +185,7 @@ const steps = computed(() => {
const account = ref({
aliases: [],
is_active: true,
role: 'SimpleUsers',
role: constants.USER,
mailbox: {
use_domain_quota: true,
},
@@ -234,19 +232,33 @@ function setFormErrors(step, errors) {
function preparePayload(payload) {
const cleaned_payload = { ...payload }
if (
cleaned_payload.role === 'SuperAdmins' &&
[constants.RESELLER, constants.SUPER_ADMIN].includes(
cleaned_payload.role
) &&
cleaned_payload.username &&
cleaned_payload.username.indexOf('@') === -1
) {
delete cleaned_payload.mailbox
}
if (cleaned_payload.mailbox && cleaned_payload.mailbox.message_limit === '') {
cleaned_payload.mailbox.message_limit = null
if (cleaned_payload.mailbox) {
if (cleaned_payload.mailbox.message_limit === '') {
cleaned_payload.mailbox.message_limit = null
}
if (
cleaned_payload.mailbox.quota === undefined ||
cleaned_payload.mailbox.quota === null
) {
cleaned_payload.mailbox.quota = 0
}
}
return cleaned_payload
}
function validateAccount() {
function validateAccount(step) {
if (step === 1) {
// No validation after role selection
return true
}
const payload = preparePayload({ ...account.value })
return accountsApi.validate(payload)
}
@@ -209,6 +209,7 @@ import { ref, computed, onMounted, watch } from 'vue'
import { useGettext } from 'vue3-gettext'
import { useRoute, useRouter } from 'vue-router'
import { usePermissions } from '@/composables/permissions'
import constants from '@/constants.json'
const { $gettext } = useGettext()
const authStore = useAuthStore()
@@ -229,8 +230,8 @@ const needsResources = computed(() => {
const isNeeded =
limitsConfig.value.params &&
limitsConfig.value.params.enable_admin_limits &&
editedAccount.value.role !== 'SimpleUsers' &&
editedAccount.value.role !== 'SuperAdmins'
editedAccount.value.role !== constants.USER &&
editedAccount.value.role !== constants.SUPER_ADMIN
if (isNeeded === undefined) {
return false
}
@@ -285,7 +286,7 @@ async function save() {
const data = { ...editedAccount.value }
if (usernameIsEmail.value) {
data.mailbox.full_address = data.username
} else {
} else if (data.mailbox) {
delete data.mailbox.full_address
}
if (data.new_password) {
@@ -303,7 +304,7 @@ async function save() {
if (editedAccount.value.pk === authStore.authUser.pk) {
data.role = authStore.authUser.role
} else {
data.role = 'SimpleUsers'
data.role = constants.USER
}
}
await accountsApi.patch(editedAccount.value.pk, data)
@@ -50,7 +50,7 @@
<v-col v-else cols="6">
<v-progress-linear
:color="account.mailbox.quota_usage < 80 ? 'primary' : 'warning'"
:value="account.mailbox.quota_usage"
:model-value="account.mailbox.quota_usage"
height="25"
class="white--text"
>
@@ -57,6 +57,7 @@ import { ref, computed } from 'vue'
import { useGettext } from 'vue3-gettext'
import { useAuthStore } from '@/stores'
import rules from '@/plugins/rules'
import constants from '@/constants.json'
const { $gettext } = useGettext()
const authStore = useAuthStore()
@@ -72,21 +73,18 @@ const formErrors = ref({})
const account = computed(() => props.modelValue)
const usernamePlaceholder = computed(() => {
if (account.value.role === 'SimpleUsers') {
if (account.value.role === constants.USER) {
return $gettext('Enter an email address')
}
return $gettext('Enter a simple username or an email address')
})
const usernameInputType = computed(() => {
return account.value.role === 'SimpleUsers' ? 'email' : 'text'
return account.value.role === constants.USER ? 'email' : 'text'
})
function updateUsername() {
if (
account.value.role != 'SuperAdmins' &&
account.value.username.indexOf('@') !== -1
) {
if (account.value.username.indexOf('@') !== -1) {
account.value.mailbox.full_address = account.value.username
account.value.mailbox.message_limit = null
}
@@ -44,11 +44,12 @@
</v-form>
</template>
<script setup lang="js">
<script setup>
import { ref, computed, watch } from 'vue'
import { useGettext } from 'vue3-gettext'
import { useDomainsStore } from '@/stores'
import rules from '@/plugins/rules'
import constants from '@/constants.json'
const { $gettext } = useGettext()
const emit = defineEmits(['update:modelValue'])
@@ -68,7 +69,7 @@ watch(
(value) => {
if (value) {
form.value = { ...value }
if (form.value.role === 'SimpleUsers') {
if (form.value.role === constants.USER) {
if (!form.value.mailbox) {
form.value.mailbox = {}
}
@@ -25,11 +25,12 @@
</v-form>
</template>
<script setup lang="js">
<script setup>
import ChoiceField from '@/components/tools/ChoiceField'
import { computed, ref } from 'vue'
import { useAuthStore } from '@/stores'
import { useGettext } from 'vue3-gettext'
import constants from '@/constants.json'
const authStore = useAuthStore()
const { $gettext } = useGettext()
@@ -59,16 +60,16 @@ const roleHelp = computed(() => {
})
const accountRoles = computed(() => {
if (authUser.value.role === 'SuperAdmins') {
if (authUser.value.role === constants.SUPER_ADMIN) {
return [
...simpleUserRole,
...domainAdminsRole,
...resellerRole,
...simpleUserRole,
...superAdminsRole,
]
} else if (authUser.value.role === 'DomainAdmins') {
} else if (authUser.value.role === constants.DOMAIN_ADMIN) {
return [...simpleUserRole]
} else if (authUser.value.role === 'Resellers') {
} else if (authUser.value.role === constants.RESELLER) {
return [...domainAdminsRole, ...simpleUserRole]
} else {
return []
@@ -78,7 +79,7 @@ const accountRoles = computed(() => {
const simpleUserRole = [
{
label: $gettext('Simple user'),
value: 'SimpleUsers',
value: constants.USER,
help: $gettext(
'A user with no privileges but with a mailbox. He will be allowed to use all end-user features: webmail, calendar, contacts, filters.'
),
@@ -88,7 +89,7 @@ const simpleUserRole = [
const domainAdminsRole = [
{
label: $gettext('Domain administrator'),
value: 'DomainAdmins',
value: constants.DOMAIN_ADMIN,
help: $gettext(
'A user with privileges on one or more domain. He will be allowed to administer mailboxes and he can also have a mailbox.'
),
@@ -97,14 +98,16 @@ const domainAdminsRole = [
const resellerRole = [
{
label: $gettext('Reseller'),
value: 'Resellers',
help: $gettext('help'),
value: constants.RESELLER,
help: $gettext(
'An intermediate user who has the same privileges than a Domain administrator, plus the possibility to create domains and to assign resources.'
),
},
]
const superAdminsRole = [
{
label: $gettext('Super administrator'),
value: 'SuperAdmins',
value: constants.SUPER_ADMIN,
help: $gettext(
"A user with all privileges, can do anything. By default, such a user does not have a mailbox so he can't access end-user features."
),