musician add webappusers and systemusers
This commit is contained in:
parent
ee7cf07294
commit
5c0c82d50b
|
@ -3,8 +3,11 @@ from django.contrib.auth.forms import AuthenticationForm
|
|||
from django.core.exceptions import ValidationError
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from django.contrib.auth.hashers import make_password
|
||||
|
||||
from orchestra.contrib.domains.models import Domain, Record
|
||||
from orchestra.contrib.mailboxes.models import Address, Mailbox
|
||||
from orchestra.contrib.systemusers.models import WebappUsers, SystemUser
|
||||
from orchestra.contrib.musician.validators import ValidateZoneMixin
|
||||
|
||||
from . import api
|
||||
|
@ -27,6 +30,42 @@ class LoginForm(AuthenticationForm):
|
|||
|
||||
return self.cleaned_data
|
||||
|
||||
class ChangePasswordForm(forms.ModelForm):
|
||||
error_messages = {
|
||||
'password_mismatch': _('The two password fields didn’t match.'),
|
||||
}
|
||||
password = forms.CharField(
|
||||
label=_("Password"),
|
||||
strip=False,
|
||||
widget=forms.PasswordInput(attrs={'autocomplete': 'new-password'}),
|
||||
)
|
||||
password2 = forms.CharField(
|
||||
label=_("Password confirmation"),
|
||||
widget=forms.PasswordInput(attrs={'autocomplete': 'new-password'}),
|
||||
strip=False,
|
||||
help_text=_("Enter the same password as before, for verification."),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
fields = ("password",)
|
||||
model = WebappUsers
|
||||
|
||||
def clean_password2(self):
|
||||
password = self.cleaned_data.get("password")
|
||||
password2 = self.cleaned_data.get("password2")
|
||||
if password and password2 and password != password2:
|
||||
raise ValidationError(
|
||||
self.error_messages['password_mismatch'],
|
||||
code='password_mismatch',
|
||||
)
|
||||
return password2
|
||||
|
||||
def clean(self):
|
||||
cleaned_data = super().clean()
|
||||
password = cleaned_data.get("password")
|
||||
cleaned_data['password'] = make_password(password)
|
||||
return cleaned_data
|
||||
|
||||
|
||||
class MailForm(forms.ModelForm):
|
||||
class Meta:
|
||||
|
@ -53,36 +92,12 @@ class MailForm(forms.ModelForm):
|
|||
return instance
|
||||
|
||||
|
||||
class MailboxChangePasswordForm(forms.ModelForm):
|
||||
error_messages = {
|
||||
'password_mismatch': _('The two password fields didn’t match.'),
|
||||
}
|
||||
password = forms.CharField(
|
||||
label=_("Password"),
|
||||
strip=False,
|
||||
widget=forms.PasswordInput(attrs={'autocomplete': 'new-password'}),
|
||||
)
|
||||
password2 = forms.CharField(
|
||||
label=_("Password confirmation"),
|
||||
widget=forms.PasswordInput(attrs={'autocomplete': 'new-password'}),
|
||||
strip=False,
|
||||
help_text=_("Enter the same password as before, for verification."),
|
||||
)
|
||||
class MailboxChangePasswordForm(ChangePasswordForm):
|
||||
|
||||
class Meta:
|
||||
fields = ("password",)
|
||||
model = Mailbox
|
||||
|
||||
def clean_password2(self):
|
||||
password = self.cleaned_data.get("password")
|
||||
password2 = self.cleaned_data.get("password2")
|
||||
if password and password2 and password != password2:
|
||||
raise ValidationError(
|
||||
self.error_messages['password_mismatch'],
|
||||
code='password_mismatch',
|
||||
)
|
||||
return password2
|
||||
|
||||
|
||||
class MailboxCreateForm(forms.ModelForm):
|
||||
error_messages = {
|
||||
|
@ -120,7 +135,7 @@ class MailboxCreateForm(forms.ModelForm):
|
|||
self.error_messages['password_mismatch'],
|
||||
code='password_mismatch',
|
||||
)
|
||||
return password2
|
||||
return password
|
||||
|
||||
def save(self, commit=True):
|
||||
instance = super().save(commit=False)
|
||||
|
@ -169,3 +184,14 @@ class RecordUpdateForm(ValidateZoneMixin, forms.ModelForm):
|
|||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.domain = self.instance.domain
|
||||
|
||||
|
||||
class WebappUsersChangePasswordForm(ChangePasswordForm):
|
||||
class Meta:
|
||||
fields = ("password",)
|
||||
model = WebappUsers
|
||||
|
||||
class SystemUsersChangePasswordForm(ChangePasswordForm):
|
||||
class Meta:
|
||||
fields = ("password",)
|
||||
model = SystemUser
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
{% extends "musician/base.html" %}
|
||||
{% load bootstrap4 i18n %}
|
||||
|
||||
{% block content %}
|
||||
<h1 class="service-name">{% trans "Change password" %}: <span class="font-weight-light">{{ object.name }}</span></h1>
|
||||
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form form %}
|
||||
{% buttons %}
|
||||
<a class="btn btn-light mr-2" href="{% url 'musician:systemuser-list' %}">{% trans "Cancel" %}</a>
|
||||
<button type="submit" class="btn btn-secondary">{% trans "Save" %}</button>
|
||||
{% endbuttons %}
|
||||
</form>
|
||||
{% endblock %}
|
|
@ -0,0 +1,41 @@
|
|||
{% extends "musician/users_base.html" %}
|
||||
{% load bootstrap4 i18n %}
|
||||
|
||||
{% block tabcontent %}
|
||||
<p></p>
|
||||
<p>{% trans "The main user is your system's main user on each server. You'll be able to view the logs of your websites at (/home/account/logs) and all web content, but you'll never be able to edit content on a website." %}</p>
|
||||
<p>{% trans "This user only has write permissions in their own directory." %}</p>
|
||||
|
||||
|
||||
<table class="table service-list">
|
||||
<colgroup>
|
||||
<col span="1" style="width: 15%;">
|
||||
<col span="1" style="width: 25%;">
|
||||
<col span="1" style="width: 60%;">
|
||||
</colgroup>
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th scope="col">{% trans "Username" %}</th>
|
||||
<th scope="col">{% trans "Path" %}</th>
|
||||
<th scope="col"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for systemuser in object_list %}
|
||||
{% if systemuser.is_main %}
|
||||
<tr>
|
||||
<td>{{ systemuser.username }}</td>
|
||||
<td>{{ systemuser.home }}/{{ systemuser.username }}</td>
|
||||
<td>
|
||||
<div class="d-flex justify-content-end">
|
||||
<a class="btn btn-outline-warning" href="{% url 'musician:systemuser-password' systemuser.id %}">
|
||||
<i class="fas fa-key"></i> {% trans "Update password" %}</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{% endblock %}
|
|
@ -0,0 +1,31 @@
|
|||
{% extends "musician/base.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block content %}
|
||||
{% if active_domain %}
|
||||
<a class="btn-arrow-left" href="{% url 'musician:systemuser-list' %}">{% trans "Go to global" %}</a>
|
||||
{% endif %}
|
||||
|
||||
<h1 class="service-name">{{ service.verbose_name }}
|
||||
{% if active_domain %}<span class="font-weight-light">{% trans "for" %} {{ active_domain.name }}</span>{% endif %}
|
||||
</h1>
|
||||
<p class="service-description">{{ service.description }}</p>
|
||||
|
||||
{% with request.resolver_match.url_name as url_name %}
|
||||
<ul class="nav nav-tabs" id="myTab" role="tablist">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {% if url_name == 'systemuser-list' %}active{% endif %}" href="{% url 'musician:systemuser-list' %}" role="tab"
|
||||
aria-selected="{% if url_name == 'systemuser-list' %}true{% else %}false{% endif %}">{% trans "Main User" %}</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {% if url_name == 'webappuser-list' %}active{% endif %}" href="{% url 'musician:webappuser-list' %}" role="tab"
|
||||
aria-selected="{% if url_name == 'webappuser-list' %}true{% else %}false{% endif %}">{% trans "SFTP Users" %}</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endwith %}
|
||||
|
||||
<div class="tab-content" id="myTabContent">
|
||||
{% block tabcontent %}
|
||||
{% endblock %}
|
||||
|
||||
{% endblock %}
|
|
@ -0,0 +1,15 @@
|
|||
{% extends "musician/base.html" %}
|
||||
{% load bootstrap4 i18n %}
|
||||
|
||||
{% block content %}
|
||||
<h1 class="service-name">{% trans "Change password" %}: <span class="font-weight-light">{{ object.name }}</span></h1>
|
||||
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form form %}
|
||||
{% buttons %}
|
||||
<a class="btn btn-light mr-2" href="{% url 'musician:webappuser-list' %}">{% trans "Cancel" %}</a>
|
||||
<button type="submit" class="btn btn-secondary">{% trans "Save" %}</button>
|
||||
{% endbuttons %}
|
||||
</form>
|
||||
{% endblock %}
|
|
@ -0,0 +1,37 @@
|
|||
{% extends "musician/users_base.html" %}
|
||||
{% load bootstrap4 i18n %}
|
||||
|
||||
{% block tabcontent %}
|
||||
|
||||
<table class="table service-list">
|
||||
<colgroup>
|
||||
<col span="1" style="width: 15%;">
|
||||
<col span="1" style="width: 25%;">
|
||||
<col span="1" style="width: 40%;">
|
||||
<col span="1" style="width: 20%;">
|
||||
</colgroup>
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th scope="col">{% trans "Username" %}</th>
|
||||
<th scope="col">{% trans "Path" %}</th>
|
||||
<th scope="col">{% trans "Server" %}</th>
|
||||
<th scope="col"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for webappuser in object_list %}
|
||||
<tr>
|
||||
<td>{{ webappuser.username }}</td>
|
||||
<td>/home/{{ webappuser.account }}/webapps/{{ webappuser.home }}</td>
|
||||
<td>{{ webappuser.target_server }}</td>
|
||||
<td>
|
||||
<a class="btn btn-outline-warning" href="{% url 'musician:webappuser-password' webappuser.id %}">
|
||||
<i class="fas fa-key"></i> {% trans "Update password" %}</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
{% include "musician/components/table_paginator.html" %}
|
||||
</table>
|
||||
|
||||
{% endblock %}
|
|
@ -39,4 +39,9 @@ urlpatterns = [
|
|||
path('mailing-lists/', views.MailingListsView.as_view(), name='mailing-lists'),
|
||||
path('databases/', views.DatabaseListView.as_view(), name='database-list'),
|
||||
path('saas/', views.SaasListView.as_view(), name='saas-list'),
|
||||
|
||||
path('webappusers/', views.WebappUserListView.as_view(), name='webappuser-list'),
|
||||
path('webappuser/<int:pk>/change-password/', views.WebappUserChangePasswordView.as_view(), name='webappuser-password'),
|
||||
path('systemusers/', views.SystemUserListView.as_view(), name='systemuser-list'),
|
||||
path('systemuser/<int:pk>/change-password/', views.SystemUserChangePasswordView.as_view(), name='systemuser-password'),
|
||||
]
|
||||
|
|
|
@ -32,12 +32,14 @@ from orchestra.contrib.lists.models import List
|
|||
from orchestra.contrib.mailboxes.models import Address, Mailbox
|
||||
from orchestra.contrib.resources.models import Resource, ResourceData
|
||||
from orchestra.contrib.saas.models import SaaS
|
||||
from orchestra.contrib.systemusers.models import WebappUsers, SystemUser
|
||||
from orchestra.utils.html import html_to_pdf
|
||||
|
||||
from .auth import logout as auth_logout
|
||||
from .forms import (LoginForm, MailboxChangePasswordForm, MailboxCreateForm,
|
||||
MailboxSearchForm, MailboxUpdateForm, MailForm,
|
||||
RecordCreateForm, RecordUpdateForm)
|
||||
RecordCreateForm, RecordUpdateForm, WebappUsersChangePasswordForm,
|
||||
SystemUsersChangePasswordForm)
|
||||
from .mixins import (CustomContextMixin, ExtendedPaginationMixin,
|
||||
UserTokenRequiredMixin)
|
||||
from .models import Address as AddressService
|
||||
|
@ -612,3 +614,39 @@ class LogoutView(RedirectView):
|
|||
def post(self, request, *args, **kwargs):
|
||||
"""Logout may be done via POST."""
|
||||
return self.get(request, *args, **kwargs)
|
||||
|
||||
|
||||
class WebappUserListView(ServiceListView):
|
||||
model = WebappUsers
|
||||
template_name = "musician/webappuser_list.html"
|
||||
extra_context = {
|
||||
# Translators: This message appears on the page title
|
||||
'title': _('Webapp users'),
|
||||
}
|
||||
|
||||
class WebappUserChangePasswordView(CustomContextMixin, UserTokenRequiredMixin, UpdateView):
|
||||
template_name = "musician/webappuser_change_password.html"
|
||||
model = WebappUsers
|
||||
form_class = WebappUsersChangePasswordForm
|
||||
success_url = reverse_lazy("musician:webappuser-list")
|
||||
|
||||
def get_queryset(self):
|
||||
return self.model.objects.filter(account=self.request.user)
|
||||
|
||||
|
||||
class SystemUserListView(ServiceListView):
|
||||
model = SystemUser
|
||||
template_name = "musician/systemuser_list.html"
|
||||
extra_context = {
|
||||
# Translators: This message appears on the page title
|
||||
'title': _('Main users'),
|
||||
}
|
||||
|
||||
class SystemUserChangePasswordView(CustomContextMixin, UserTokenRequiredMixin, UpdateView):
|
||||
template_name = "musician/systemuser_change_password.html"
|
||||
model = SystemUser
|
||||
form_class = SystemUsersChangePasswordForm
|
||||
success_url = reverse_lazy("musician:systemuser-list")
|
||||
|
||||
def get_queryset(self):
|
||||
return self.model.objects.filter(account=self.request.user)
|
Loading…
Reference in a new issue