- {{ item.key }}
- {{ item.value|yesno }}
-
- {{ displayList(item.value) }}
-
- {{ item.value }}
+
+ {{ item.key }}
+ {{ item.value|yesno }}
+
+ {{ displayList(item.value) }}
+
+ {{ item.value }}
+
diff --git a/frontend/src/main.js b/frontend/src/main.js
index bbdb84000..68416868c 100644
--- a/frontend/src/main.js
+++ b/frontend/src/main.js
@@ -7,6 +7,7 @@ import App from './App.vue'
import router from './router'
import store from './store'
import vuetify from './plugins/vuetify'
+import sassStyles from './styles/global.scss' // eslint-disable-line no-unused-vars
Vue.config.productionTip = false
diff --git a/frontend/src/plugins/vuetify.js b/frontend/src/plugins/vuetify.js
index 4e62dfec3..406f9b7fa 100644
--- a/frontend/src/plugins/vuetify.js
+++ b/frontend/src/plugins/vuetify.js
@@ -5,10 +5,14 @@ Vue.use(Vuetify)
export default new Vuetify({
theme: {
+ options: {
+ customProperties: true
+ },
themes: {
light: {
primary: '#046BF8',
- secondary: '#F18429'
+ secondary: '#F18429',
+ label: '#616161'
}
}
}
diff --git a/frontend/src/styles/global.scss b/frontend/src/styles/global.scss
new file mode 100644
index 000000000..4127ef24f
--- /dev/null
+++ b/frontend/src/styles/global.scss
@@ -0,0 +1,5 @@
+.m-label {
+ display: block;
+ margin-bottom: 4px;
+ color: var(--v-label-base);
+}
diff --git a/modoboa/admin/api/v1/serializers.py b/modoboa/admin/api/v1/serializers.py
index 6e2042af5..33497285f 100644
--- a/modoboa/admin/api/v1/serializers.py
+++ b/modoboa/admin/api/v1/serializers.py
@@ -305,7 +305,13 @@ class WritableAccountSerializer(AccountSerializer):
raise serializers.ValidationError({
"username": _("Must be equal to mailbox full_address")
})
- if not self.partial and not data.get("random_password"):
+ condition = (
+ not data.get("random_password") and (
+ data.get("password") or
+ not self.partial
+ )
+ )
+ if condition:
password = data.get("password")
if password:
try:
diff --git a/modoboa/admin/api/v2/serializers.py b/modoboa/admin/api/v2/serializers.py
index 058d2b091..ee21bc0ef 100644
--- a/modoboa/admin/api/v2/serializers.py
+++ b/modoboa/admin/api/v2/serializers.py
@@ -160,9 +160,11 @@ class WritableAccountSerializer(v1_serializers.WritableAccountSerializer):
)
class Meta(v1_serializers.WritableAccountSerializer.Meta):
- fields = v1_serializers.WritableAccountSerializer.Meta.fields + (
- "aliases",
- )
+ fields = tuple(
+ field
+ for field in v1_serializers.WritableAccountSerializer.Meta.fields
+ if field != "random_password"
+ ) + ("aliases", )
def validate_aliases(self, value):
"""Check if required domains are locals and user can access them."""
diff --git a/modoboa/admin/api/v2/viewsets.py b/modoboa/admin/api/v2/viewsets.py
index 43ca7b5a9..c50fd1e07 100644
--- a/modoboa/admin/api/v2/viewsets.py
+++ b/modoboa/admin/api/v2/viewsets.py
@@ -161,6 +161,12 @@ class AccountViewSet(v1_viewsets.AccountViewSet):
serializer.is_valid(raise_exception=True)
return response.Response(status=204)
+ @action(methods=["get"], detail=False)
+ def random_password(self, request, **kwargs):
+ """Generate a random password."""
+ password = lib.make_password()
+ return response.Response({"password": password})
+
class IdentityViewSet(viewsets.ViewSet):
"""Viewset for identities."""