mirror of
https://gitlab2.federez.net/re2o/re2o
synced 2024-11-21 19:03:11 +00:00
Fix #261
This commit is contained in:
parent
e7795a775c
commit
f6b2225eb8
13 changed files with 380 additions and 36 deletions
|
@ -48,6 +48,7 @@ from .models import (
|
|||
LdapServiceUser,
|
||||
LdapServiceUserGroup,
|
||||
LdapUserGroup,
|
||||
SSHKey,
|
||||
)
|
||||
from .forms import (
|
||||
UserChangeForm,
|
||||
|
@ -130,6 +131,12 @@ class WhitelistAdmin(VersionAdmin):
|
|||
pass
|
||||
|
||||
|
||||
class SSHKeyAdmin(VersionAdmin):
|
||||
"""SSHKey model for admin."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class UserAdmin(VersionAdmin, BaseUserAdmin):
|
||||
"""Gestion d'un user : modification des champs perso, mot de passe, etc"""
|
||||
|
||||
|
@ -224,6 +231,7 @@ admin.site.register(Ban, BanAdmin)
|
|||
admin.site.register(EMailAddress, EMailAddressAdmin)
|
||||
admin.site.register(Whitelist, WhitelistAdmin)
|
||||
admin.site.register(Request, RequestAdmin)
|
||||
admin.site.register(SSHKey, SSHKeyAdmin)
|
||||
# Now register the new UserAdmin...
|
||||
admin.site.unregister(User)
|
||||
admin.site.unregister(ServiceUser)
|
||||
|
|
|
@ -24,6 +24,7 @@ from rest_framework import serializers
|
|||
import users.models as users
|
||||
from api.serializers import NamespacedHRField, NamespacedHIField, NamespacedHMSerializer
|
||||
|
||||
|
||||
class UserSerializer(NamespacedHMSerializer):
|
||||
"""Serialize `users.models.User` objects.
|
||||
"""
|
||||
|
@ -210,7 +211,7 @@ class EMailAddressSerializer(NamespacedHMSerializer):
|
|||
class Meta:
|
||||
model = users.EMailAddress
|
||||
fields = ("user", "local_part", "complete_email_address", "api_url")
|
||||
|
||||
|
||||
|
||||
class LocalEmailUsersSerializer(NamespacedHMSerializer):
|
||||
email_address = EMailAddressSerializer(read_only=True, many=True)
|
||||
|
@ -241,4 +242,12 @@ class MailingSerializer(ClubSerializer):
|
|||
admins = MailingMemberSerializer(source="administrators", many=True)
|
||||
|
||||
class Meta(ClubSerializer.Meta):
|
||||
fields = ("name", "members", "admins")
|
||||
fields = ("name", "members", "admins")
|
||||
|
||||
|
||||
class SSHKeySerializer(NamespacedHMSerializer):
|
||||
"""Serialize an SSHKey."""
|
||||
|
||||
class Meta:
|
||||
model = users.SSHKey
|
||||
fields = "__all__"
|
||||
|
|
|
@ -34,16 +34,16 @@ urls_viewset = [
|
|||
(r"users/shell", views.ShellViewSet, "shell"),
|
||||
(r"users/ban", views.BanViewSet, None),
|
||||
(r"users/whitelist", views.WhitelistViewSet, None),
|
||||
(r"users/emailaddress", views.EMailAddressViewSet, None)
|
||||
(r"users/emailaddress", views.EMailAddressViewSet, None),
|
||||
(r"users/sshkey", views.SSHKeyViewSet, None),
|
||||
]
|
||||
|
||||
urls_view = [
|
||||
(r"users/localemail", views.LocalEmailUsersView),
|
||||
(r"users/mailing-standard", views.StandardMailingView),
|
||||
(r"users/mailing-club", views.ClubMailingView),
|
||||
|
||||
# Deprecated
|
||||
(r"localemail/users", views.LocalEmailUsersView),
|
||||
(r"mailing/standard", views.StandardMailingView),
|
||||
(r"mailing/club", views.ClubMailingView),
|
||||
]
|
||||
]
|
||||
|
|
|
@ -169,7 +169,7 @@ class StandardMailingView(views.APIView):
|
|||
adherents_data = serializers.MailingMemberSerializer(
|
||||
all_has_access(), many=True
|
||||
).data
|
||||
|
||||
|
||||
data = [{"name": "adherents", "members": adherents_data}]
|
||||
groups = Group.objects.all()
|
||||
for group in groups:
|
||||
|
@ -189,4 +189,12 @@ class ClubMailingView(generics.ListAPIView):
|
|||
"""
|
||||
|
||||
queryset = users.Club.objects.all()
|
||||
serializer_class = serializers.MailingSerializer
|
||||
serializer_class = serializers.MailingSerializer
|
||||
|
||||
|
||||
class SSHKeyViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Exposes list and details of `users.models.SSHKey` objects.
|
||||
"""
|
||||
|
||||
queryset = users.SSHKey.objects.all()
|
||||
serializer_class = serializers.SSHKeySerializer
|
||||
|
|
|
@ -38,7 +38,10 @@ from __future__ import unicode_literals
|
|||
from django import forms
|
||||
from django.forms import ModelForm, Form
|
||||
from django.contrib.auth.forms import ReadOnlyPasswordHashField
|
||||
from django.contrib.auth.password_validation import validate_password, password_validators_help_text_html
|
||||
from django.contrib.auth.password_validation import (
|
||||
validate_password,
|
||||
password_validators_help_text_html,
|
||||
)
|
||||
from django.core.validators import MinLengthValidator
|
||||
from django.utils import timezone
|
||||
from django.utils.functional import lazy
|
||||
|
@ -69,6 +72,7 @@ from .models import (
|
|||
Ban,
|
||||
Adherent,
|
||||
Club,
|
||||
SSHKey,
|
||||
)
|
||||
|
||||
|
||||
|
@ -84,7 +88,7 @@ class PassForm(FormRevMixin, FieldPermissionFormMixin, forms.ModelForm):
|
|||
label=_("New password"),
|
||||
max_length=255,
|
||||
widget=forms.PasswordInput,
|
||||
help_text=password_validators_help_text_html()
|
||||
help_text=password_validators_help_text_html(),
|
||||
)
|
||||
passwd2 = forms.CharField(
|
||||
label=_("New password confirmation"),
|
||||
|
@ -133,12 +137,10 @@ class UserCreationForm(FormRevMixin, forms.ModelForm):
|
|||
label=_("Password"),
|
||||
widget=forms.PasswordInput,
|
||||
max_length=255,
|
||||
help_text=password_validators_help_text_html()
|
||||
help_text=password_validators_help_text_html(),
|
||||
)
|
||||
password2 = forms.CharField(
|
||||
label=_("Password confirmation"),
|
||||
widget=forms.PasswordInput,
|
||||
max_length=255,
|
||||
label=_("Password confirmation"), widget=forms.PasswordInput, max_length=255,
|
||||
)
|
||||
is_admin = forms.BooleanField(label=_("Is admin"))
|
||||
|
||||
|
@ -287,9 +289,7 @@ class MassArchiveForm(forms.Form):
|
|||
|
||||
date = forms.DateTimeField(help_text="%d/%m/%y")
|
||||
full_archive = forms.BooleanField(
|
||||
label=_(
|
||||
"Fully archive users? WARNING: CRITICAL OPERATION IF TRUE"
|
||||
),
|
||||
label=_("Fully archive users? WARNING: CRITICAL OPERATION IF TRUE"),
|
||||
initial=False,
|
||||
required=False,
|
||||
)
|
||||
|
@ -380,6 +380,7 @@ class AdherentCreationForm(AdherentForm):
|
|||
AdherentForm auquel on ajoute une checkbox afin d'éviter les
|
||||
doublons d'utilisateurs et, optionnellement,
|
||||
un champ mot de passe"""
|
||||
|
||||
# Champ pour choisir si un lien est envoyé par mail pour le mot de passe
|
||||
init_password_by_mail_info = _(
|
||||
"If this options is set, you will receive a link to set"
|
||||
|
@ -392,9 +393,7 @@ class AdherentCreationForm(AdherentForm):
|
|||
)
|
||||
|
||||
init_password_by_mail = forms.BooleanField(
|
||||
help_text=init_password_by_mail_info,
|
||||
required=False,
|
||||
initial=True
|
||||
help_text=init_password_by_mail_info, required=False, initial=True
|
||||
)
|
||||
init_password_by_mail.label = _("Send password reset link by email.")
|
||||
|
||||
|
@ -405,7 +404,7 @@ class AdherentCreationForm(AdherentForm):
|
|||
label=_("Password"),
|
||||
widget=forms.PasswordInput,
|
||||
max_length=255,
|
||||
help_text=password_validators_help_text_html()
|
||||
help_text=password_validators_help_text_html(),
|
||||
)
|
||||
password2 = forms.CharField(
|
||||
required=False,
|
||||
|
@ -482,8 +481,12 @@ class AdherentCreationForm(AdherentForm):
|
|||
# Save the provided password in hashed format
|
||||
user = super(AdherentForm, self).save(commit=False)
|
||||
|
||||
is_set_password_allowed = OptionalUser.get_cached_value("allow_set_password_during_user_creation")
|
||||
set_passwd = is_set_password_allowed and not self.cleaned_data.get("init_password_by_mail")
|
||||
is_set_password_allowed = OptionalUser.get_cached_value(
|
||||
"allow_set_password_during_user_creation"
|
||||
)
|
||||
set_passwd = is_set_password_allowed and not self.cleaned_data.get(
|
||||
"init_password_by_mail"
|
||||
)
|
||||
if set_passwd:
|
||||
user.set_password(self.cleaned_data["password1"])
|
||||
|
||||
|
@ -886,3 +889,15 @@ class InitialRegisterForm(forms.Form):
|
|||
if self.cleaned_data["register_machine"]:
|
||||
if self.mac_address and self.nas_type:
|
||||
self.user.autoregister_machine(self.mac_address, self.nas_type)
|
||||
|
||||
|
||||
class SSHKeyForm(FormRevMixin, ModelForm):
|
||||
"""Create or edit an SSHKey"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
|
||||
super(SSHKeyForm, self).__init__(*args, prefix=prefix, **kwargs)
|
||||
|
||||
class Meta:
|
||||
model = SSHKey
|
||||
exclude = ["user"]
|
||||
|
|
54
users/migrations/0092_auto_20200423_1804.py
Normal file
54
users/migrations/0092_auto_20200423_1804.py
Normal file
|
@ -0,0 +1,54 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.28 on 2020-04-23 16:04
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import ldapdb.models.fields
|
||||
import re2o.mixins
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("users", "0091_auto_20200423_1256"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="SSHKey",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("key", models.TextField(blank=True, verbose_name="Public ssh key")),
|
||||
(
|
||||
"user",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "SSH key",
|
||||
"verbose_name_plural": "SSH keys",
|
||||
"permissions": (("view_sshkey", "Can view an SSHKey object"),),
|
||||
},
|
||||
bases=(re2o.mixins.RevMixin, re2o.mixins.AclMixin, models.Model),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="ldapuser",
|
||||
name="ssh_keys",
|
||||
field=ldapdb.models.fields.ListField(
|
||||
blank=True, db_column="sshkeys", null=True
|
||||
),
|
||||
),
|
||||
]
|
18
users/migrations/0093_auto_20200423_2028.py
Normal file
18
users/migrations/0093_auto_20200423_2028.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.28 on 2020-04-23 18:28
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("users", "0092_auto_20200423_1804"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name="ldapuser", old_name="ssh_keys", new_name="sshkeys",
|
||||
),
|
||||
]
|
23
users/migrations/0094_auto_20200423_2030.py
Normal file
23
users/migrations/0094_auto_20200423_2030.py
Normal file
|
@ -0,0 +1,23 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.28 on 2020-04-23 18:30
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations
|
||||
import ldapdb.models.fields
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("users", "0093_auto_20200423_2028"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="ldapuser",
|
||||
name="sshkeys",
|
||||
field=ldapdb.models.fields.ListField(
|
||||
blank=True, db_column="sshkeys", max_length=200, null=True
|
||||
),
|
||||
),
|
||||
]
|
|
@ -105,7 +105,7 @@ def linux_user_validator(login):
|
|||
pas les contraintes unix (maj, min, chiffres ou tiret)"""
|
||||
if not linux_user_check(login):
|
||||
raise forms.ValidationError(
|
||||
_("The username \"%(label)s\" contains forbidden characters."),
|
||||
_('The username "%(label)s" contains forbidden characters.'),
|
||||
params={"label": login},
|
||||
)
|
||||
|
||||
|
@ -405,7 +405,10 @@ class User(
|
|||
@cached_property
|
||||
def get_shadow_expire(self):
|
||||
"""Return the shadow_expire value for the user"""
|
||||
if self.state == self.STATE_DISABLED or self.email_state == self.EMAIL_STATE_UNVERIFIED:
|
||||
if (
|
||||
self.state == self.STATE_DISABLED
|
||||
or self.email_state == self.EMAIL_STATE_UNVERIFIED
|
||||
):
|
||||
return str(0)
|
||||
else:
|
||||
return None
|
||||
|
@ -670,7 +673,12 @@ class User(
|
|||
self.full_archive()
|
||||
|
||||
def ldap_sync(
|
||||
self, base=True, access_refresh=True, mac_refresh=True, group_refresh=False
|
||||
self,
|
||||
base=True,
|
||||
access_refresh=True,
|
||||
mac_refresh=True,
|
||||
group_refresh=False,
|
||||
sshkeys_refresh=False,
|
||||
):
|
||||
""" Synchronisation du ldap. Synchronise dans le ldap les attributs de
|
||||
self
|
||||
|
@ -734,6 +742,10 @@ class User(
|
|||
for group in Group.objects.all():
|
||||
if hasattr(group, "listright"):
|
||||
group.listright.ldap_sync()
|
||||
if sshkeys_refresh:
|
||||
user_ldap.sshkeys = [
|
||||
str(key.key) for key in SSHKey.objects.filter(user=self)
|
||||
]
|
||||
user_ldap.save()
|
||||
|
||||
def ldap_del(self):
|
||||
|
@ -1051,7 +1063,7 @@ class User(
|
|||
False,
|
||||
_(
|
||||
"Impossible to edit the organisation's"
|
||||
" user without the \"change_all_users\" right."
|
||||
' user without the "change_all_users" right.'
|
||||
),
|
||||
("users.change_all_users",),
|
||||
)
|
||||
|
@ -1120,7 +1132,8 @@ class User(
|
|||
if not (
|
||||
(
|
||||
self.pk == user_request.pk
|
||||
and OptionalUser.get_cached_value("self_room_policy") != OptionalUser.DISABLED
|
||||
and OptionalUser.get_cached_value("self_room_policy")
|
||||
!= OptionalUser.DISABLED
|
||||
)
|
||||
or user_request.has_perm("users.change_user")
|
||||
):
|
||||
|
@ -1263,7 +1276,7 @@ class User(
|
|||
can = user_request.is_superuser
|
||||
return (
|
||||
can,
|
||||
_("\"superuser\" right required to edit the superuser flag.")
|
||||
_('"superuser" right required to edit the superuser flag.')
|
||||
if not can
|
||||
else None,
|
||||
[],
|
||||
|
@ -1357,9 +1370,7 @@ class User(
|
|||
# Allow empty emails only if the user had an empty email before
|
||||
is_created = not self.pk
|
||||
if not self.email and (self.__original_email or is_created):
|
||||
raise forms.ValidationError(
|
||||
_("Email field cannot be empty.")
|
||||
)
|
||||
raise forms.ValidationError(_("Email field cannot be empty."))
|
||||
|
||||
self.email = self.email.lower()
|
||||
|
||||
|
@ -1432,14 +1443,12 @@ class Adherent(User):
|
|||
a user or if the `options.all_can_create` is set.
|
||||
"""
|
||||
if not user_request.is_authenticated:
|
||||
if not OptionalUser.get_cached_value(
|
||||
"self_adhesion"
|
||||
):
|
||||
if not OptionalUser.get_cached_value("self_adhesion"):
|
||||
return False, _("Self registration is disabled."), None
|
||||
else:
|
||||
return True, None, None
|
||||
else:
|
||||
if OptionalUser.get_cached_value("all_can_create_adherent"):
|
||||
if OptionalUser.get_cached_value("all_can_create_adherent"):
|
||||
return True, None, None
|
||||
else:
|
||||
can = user_request.has_perm("users.add_user")
|
||||
|
@ -2000,6 +2009,9 @@ class LdapUser(ldapdb.models.Model):
|
|||
shadowexpire = ldapdb.models.fields.CharField(
|
||||
db_column="shadowExpire", blank=True, null=True
|
||||
)
|
||||
sshkeys = ldapdb.models.fields.ListField(
|
||||
db_column="sshkeys", max_length=200, blank=True, null=True
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
@ -2248,3 +2260,53 @@ class EMailAddress(RevMixin, AclMixin, models.Model):
|
|||
if result:
|
||||
raise ValidationError(reason)
|
||||
super(EMailAddress, self).clean(*args, **kwargs)
|
||||
|
||||
|
||||
class SSHKey(RevMixin, AclMixin, models.Model):
|
||||
"""Represents an SSH public key belonging to a user."""
|
||||
|
||||
key = models.TextField(blank=True, verbose_name=_("Public ssh key"))
|
||||
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
|
||||
class Meta:
|
||||
permissions = (("view_sshkey", _("Can view an SSHKey object")),)
|
||||
verbose_name = _("SSH key")
|
||||
verbose_name_plural = _("SSH keys")
|
||||
|
||||
def can_edit(self, user_request, *_args, **_kwargs):
|
||||
"""Check if a user can edit the SSH key
|
||||
|
||||
Args:
|
||||
user_request: The user who wants to edit the object.
|
||||
|
||||
Returns:
|
||||
a message and a boolean which is True if the user can edit
|
||||
the local email account.
|
||||
"""
|
||||
if self.user == user_request or user_request.has_perm("users.edit_sshkey"):
|
||||
return True, None, None
|
||||
return (
|
||||
False,
|
||||
_("You don't have the right to edit another user's SSHKey."),
|
||||
("users.edit_sshkey",),
|
||||
)
|
||||
|
||||
|
||||
@receiver(post_save, sender=SSHKey)
|
||||
def sshkey_post_save(**kwargs):
|
||||
"""Sync LDAP record for user when SSHKey is saved."""
|
||||
key = kwargs["instance"]
|
||||
is_created = kwargs["created"]
|
||||
user = key.user
|
||||
user.ldap_sync(
|
||||
base=False, access_refresh=False, mac_refresh=False, sshkeys_refresh=True
|
||||
)
|
||||
|
||||
|
||||
@receiver(post_delete, sender=SSHKey)
|
||||
def sshkey_post_delete(**kwargs):
|
||||
"""Sync LDAP record for user when SSHKey is deleted"""
|
||||
user = kwargs["instance"].user
|
||||
user.ldap_sync(
|
||||
base=False, access_refresh=False, mac_refresh=False, sshkeys_refresh=True
|
||||
)
|
||||
|
|
60
users/templates/users/aff_sshkeys.html
Normal file
60
users/templates/users/aff_sshkeys.html
Normal file
|
@ -0,0 +1,60 @@
|
|||
{% comment %}
|
||||
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
se veut agnostique au réseau considéré, de manière à être installable en
|
||||
quelques clics.
|
||||
|
||||
Copyright © 2017 Gabriel Détraz
|
||||
Copyright © 2017 Lara Kermarec
|
||||
Copyright © 2017 Augustin Lemesle
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
{% endcomment %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% load acl %}
|
||||
{% load logs_extra %}
|
||||
|
||||
|
||||
{% if sshkeys.paginator %}
|
||||
{% include 'pagination.html' with list=sshkeys %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans "SSH key" %}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
{% for sshkey in sshkeys %}
|
||||
<td>{{ sshkey.key }}</td>
|
||||
<td class="text-right">
|
||||
{% can_delete sshkey %}
|
||||
{% include 'buttons/suppr.html' with href='users:del-sshkey' id=sshkey.id %}
|
||||
{% acl_end %}
|
||||
{% history_button sshkey %}
|
||||
{% can_edit sshkey %}
|
||||
{% include 'buttons/edit.html' with href='users:edit-sshkey' id=sshkey.id %}
|
||||
{% acl_end %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
{% if sshkey.paginator %}
|
||||
{% include 'pagination.html' with list=sshkey %}
|
||||
{% endif %}
|
|
@ -562,6 +562,34 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading clearfix profil" data-parent="#accordion" data-toggle="collapse" data-target="#sshkeys">
|
||||
<h3 class="panel-title pull-left">
|
||||
<i class="fa fa-key"></i>
|
||||
{% trans "SSH keys" %}
|
||||
</h3>
|
||||
</div>
|
||||
<div id="sshkeys" class="panel-collapse collapse">
|
||||
<div class="panel-body">
|
||||
{% can_edit users %}
|
||||
{% can_create SSHKey %}
|
||||
<a class="btn btn-primary btn-sm" role="button" href="{% url 'users:add-sshkey' users.id %}">
|
||||
<i class="fa fa-key"></i>
|
||||
{% trans "Add an SSH key" %}
|
||||
</a>
|
||||
{% acl_end %}
|
||||
{% acl_end %}
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
{% if sshkeys %}
|
||||
{% include 'users/aff_sshkeys.html' with sshkeys=sshkeys %}
|
||||
{% else %}
|
||||
<p>{% trans "No SSH key" %}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% for template in optionnal_templates_list %}
|
||||
{{ template }}
|
||||
{% endfor %}
|
||||
|
|
|
@ -44,7 +44,11 @@ urlpatterns = [
|
|||
url(r"^state/(?P<userid>[0-9]+)$", views.state, name="state"),
|
||||
url(r"^groups/(?P<userid>[0-9]+)$", views.groups, name="groups"),
|
||||
url(r"^password/(?P<userid>[0-9]+)$", views.password, name="password"),
|
||||
url(r"^confirm_email/(?P<userid>[0-9]+)$", views.resend_confirmation_email, name="resend-confirmation-email"),
|
||||
url(
|
||||
r"^confirm_email/(?P<userid>[0-9]+)$",
|
||||
views.resend_confirmation_email,
|
||||
name="resend-confirmation-email",
|
||||
),
|
||||
url(
|
||||
r"^del_group/(?P<userid>[0-9]+)/(?P<listrightid>[0-9]+)$",
|
||||
views.del_group,
|
||||
|
@ -127,4 +131,7 @@ urlpatterns = [
|
|||
url(r"^$", views.index, name="index"),
|
||||
url(r"^index_clubs/$", views.index_clubs, name="index-clubs"),
|
||||
url(r"^initial_register/$", views.initial_register, name="initial-register"),
|
||||
url(r"^add_sshkey/(?P<userid>[0-9]+)$", views.add_sshkey, name="add-sshkey",),
|
||||
url(r"^edit_sshkey/(?P<sshkeyid>[0-9]+)$", views.edit_sshkey, name="edit-sshkey",),
|
||||
url(r"^del_sshkey/(?P<sshkeyid>[0-9]+)$", views.del_sshkey, name="del-sshkey",),
|
||||
]
|
||||
|
|
|
@ -86,6 +86,7 @@ from .models import (
|
|||
Club,
|
||||
ListShell,
|
||||
EMailAddress,
|
||||
SSHKey,
|
||||
)
|
||||
from .forms import (
|
||||
BanForm,
|
||||
|
@ -110,6 +111,7 @@ from .forms import (
|
|||
ClubAdminandMembersForm,
|
||||
GroupForm,
|
||||
InitialRegisterForm,
|
||||
SSHKeyForm,
|
||||
)
|
||||
|
||||
|
||||
|
@ -932,6 +934,7 @@ def profil(request, users, **_kwargs):
|
|||
request.GET.get("order"),
|
||||
SortTable.USERS_INDEX_WHITE,
|
||||
)
|
||||
sshkeys = users.sshkey_set.all()
|
||||
try:
|
||||
balance = find_payment_method(Paiement.objects.get(is_balance=True))
|
||||
except Paiement.DoesNotExist:
|
||||
|
@ -956,6 +959,7 @@ def profil(request, users, **_kwargs):
|
|||
"local_email_accounts_enabled": (
|
||||
OptionalUser.objects.first().local_email_accounts_enabled
|
||||
),
|
||||
"sshkeys": sshkeys,
|
||||
},
|
||||
)
|
||||
|
||||
|
@ -1101,3 +1105,51 @@ def initial_register(request):
|
|||
request,
|
||||
)
|
||||
|
||||
|
||||
@login_required
|
||||
@can_create(SSHKey)
|
||||
@can_edit(User)
|
||||
def add_sshkey(request, user, userid):
|
||||
"""Create an SSHKey for the given user."""
|
||||
sshkey_instance = SSHKey(user=user)
|
||||
sshkey = SSHKeyForm(request.POST or None, instance=sshkey_instance)
|
||||
|
||||
if sshkey.is_valid():
|
||||
sshkey.save()
|
||||
messages.success(request, _("The SSH key was added."))
|
||||
return redirect(reverse("users:profil", kwargs={"userid": str(userid)}))
|
||||
|
||||
return form(
|
||||
{"userform": sshkey, "action_name": _("Add")}, "users/user.html", request
|
||||
)
|
||||
|
||||
|
||||
@login_required
|
||||
@can_edit(SSHKey)
|
||||
def edit_sshkey(request, sshkey_instance, **_kwargs):
|
||||
"""Edit an SSHKey for the given user."""
|
||||
sshkey = SSHKeyForm(request.POST or None, instance=sshkey_instance)
|
||||
sshkey.request = request
|
||||
|
||||
if sshkey.is_valid():
|
||||
if sshkey.changed_data:
|
||||
sshkey.save()
|
||||
messages.success(request, _("The SSH Key was edited."))
|
||||
return redirect(reverse("users:profil", kwargs={"userid": str(userid)}))
|
||||
|
||||
return form(
|
||||
{"userform": sshkey, "action_name": _("Edit")}, "users/user.html", request
|
||||
)
|
||||
|
||||
|
||||
@login_required
|
||||
@can_delete(SSHKey)
|
||||
def del_sshkey(request, sshkey, **_kwargs):
|
||||
"""Delete SSH key."""
|
||||
if request.method == "POST":
|
||||
sshkey.delete()
|
||||
messages.success(request, _("The SSH key was deleted."))
|
||||
return redirect(reverse("users:profil", kwargs={"userid": str(sshkey.user.id)}))
|
||||
return form(
|
||||
{"objet": sshkey, "objet_name": _("SSH key")}, "users/delete.html", request
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue