Skip to content

Commit

Permalink
Add user management
Browse files Browse the repository at this point in the history
Update user model
  • Loading branch information
j-bernard committed Jun 28, 2022
1 parent 42a82fc commit 4b58cfe
Show file tree
Hide file tree
Showing 18 changed files with 276 additions and 77 deletions.
9 changes: 9 additions & 0 deletions src/lgr_auth/forms.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# -*- coding: utf-8 -*-
from django.contrib.auth import get_user_model
from django.contrib.auth.forms import PasswordResetForm
from django.forms import ModelForm

from lgr_auth.models import LgrUser


class LgrPasswordResetForm(PasswordResetForm):
Expand All @@ -10,3 +13,9 @@ class LgrPasswordResetForm(PasswordResetForm):

def get_users(self, email):
return get_user_model()._default_manager.filter(email__iexact=email)


class UserForm(ModelForm):
class Meta:
model = LgrUser
fields = ['first_name', 'last_name', 'email', 'role']
13 changes: 10 additions & 3 deletions src/lgr_auth/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Generated by Django 2.2.1 on 2021-02-09 00:52
# Generated by Django 3.1.7 on 2021-09-02 16:15

from django.db import migrations, models
import django.utils.timezone
import lgr_auth.models


Expand All @@ -19,10 +20,16 @@ class Migration(migrations.Migration):
('password', models.CharField(max_length=128, verbose_name='password')),
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
('email', lgr_auth.models.UAEmailField(error_messages={'unique': 'An user with that email already exists.'}, help_text='Required. Valid email address', max_length=254, unique=True)),
('role', models.PositiveSmallIntegerField(default=2)),
('role', models.CharField(choices=[('User', 'User'), ('ICANN', 'ICANN'), ('Admin', 'Admin')], default='User', max_length=16)),
('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')),
('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
('is_active', models.BooleanField(default=True, verbose_name='active')),
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
],
options={
'abstract': False,
'verbose_name': 'user',
'verbose_name_plural': 'users',
'ordering': ['email'],
},
),
]
26 changes: 0 additions & 26 deletions src/lgr_auth/migrations/0002_update_user_roles.py

This file was deleted.

30 changes: 29 additions & 1 deletion src/lgr_auth/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from django.contrib.auth.base_user import BaseUserManager, AbstractBaseUser
from django.core import validators
from django.db import models
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _


Expand Down Expand Up @@ -63,6 +64,15 @@ class LgrUser(AbstractBaseUser):
})
role = models.CharField(max_length=16, choices=((r.value, r.value) for r in LgrRole), null=False,
default=LgrRole.USER.value)
first_name = models.CharField(_('first name'), max_length=150, blank=True)
last_name = models.CharField(_('last name'), max_length=150, blank=True)
is_active = models.BooleanField(_('active'), default=True)
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)

class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
ordering = ['email']

# The username field will be the email address
USERNAME_FIELD = 'email'
Expand All @@ -74,4 +84,22 @@ def is_icann(self):
return self.role in (LgrRole.ICANN.value, LgrRole.ADMIN.value)

def is_admin(self):
return self.role == LgrRole.ADMIN.value
return self.role == LgrRole.ADMIN.value

def enable(self, enable):
self.is_active = enable
self.save(update_fields=['is_active'])

def enabled(self):
return self.is_active

def get_full_name(self):
"""
Return the first_name plus the last_name, with a space in between.
"""
full_name = '%s %s' % (self.first_name, self.last_name)
return full_name.strip()

def get_short_name(self):
"""Return the short name for the user."""
return self.first_name
24 changes: 24 additions & 0 deletions src/lgr_auth/templates/lgr_auth/user_update.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{% extends "_base.html" %}
{% load i18n %}

{% block html_title %}{% trans 'LGR Tools user edition' %}{% endblock %}

{% block navbar-right %}
<a class="header-link" href="{% url 'lgr_modes' %}">{% trans "Switch mode" %}</a>
{{ block.super }}
{% endblock %}

{% block content-title %}
{% blocktrans with email=user.email %}Edit user {{ email }}{% endblocktrans %}
{% endblock %}

{% block content %}
<form class="form-horizontal" method="post" enctype="multipart/form-data">
{% csrf_token %}
{% include "lgr_editor/_form_field.html" with field=form.first_name control_width=8 %}
{% include "lgr_editor/_form_field.html" with field=form.last_name control_width=8 %}
{% include "lgr_editor/_form_field.html" with field=form.email control_width=8 %}
{% include "lgr_editor/_form_field.html" with field=form.role control_width=8 %}
<button id="submit" type="submit" class="btn btn-primary">{% trans "Update" %}</button>
</form>
{% endblock content %}
3 changes: 3 additions & 0 deletions src/lgr_auth/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

# patterns from django.contrib.auth.urls
from lgr_auth.forms import LgrPasswordResetForm
from lgr_auth.views import LgrUserUpdateView

urlpatterns = [
path('login/', views.LoginView.as_view(template_name='lgr_auth/login.html', extra_context={'reset_mode': True}),
Expand All @@ -31,4 +32,6 @@
views.PasswordResetCompleteView.as_view(template_name='lgr_auth/password_reset_complete.html',
extra_context={'reset_mode': True}),
name='password_reset_complete'),
path('users/<int:user_pk>', LgrUserUpdateView.as_view(), name='lgr_update_user'),

]
39 changes: 39 additions & 0 deletions src/lgr_auth/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#! /bin/env python
# -*- coding: utf-8 -*-
"""
views.py
"""
import logging

from django.contrib import messages
from django.urls import reverse
from django.utils.translation import ugettext_lazy as _
from django.views.generic import UpdateView

from lgr_auth.forms import UserForm
from lgr_auth.models import LgrUser

logger = logging.getLogger(__name__)
from django.contrib.auth.mixins import LoginRequiredMixin


class LgrUserUpdateView(LoginRequiredMixin, UpdateView):
model = LgrUser
form_class = UserForm
pk_url_kwarg = 'user_pk'
template_name = 'lgr_auth/user_update.html'
success_url_name = 'lgr_update_user'

def get_queryset(self):
return LgrUser.objects.filter(pk=self.request.user.pk)

def get_success_url(self):
return reverse(self.success_url_name, kwargs={'user_pk': self.kwargs[self.pk_url_kwarg]})

def form_valid(self, form):
messages.add_message(self.request, messages.SUCCESS, _('User updated'))
return super().form_valid(form)

def form_invalid(self, form):
messages.add_message(self.request, messages.ERROR, _('Failed to update user'))
return super().form_invalid(form)
3 changes: 1 addition & 2 deletions src/lgr_idn_table_review/icann_tools/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
from lgr.core import LGR
from lgr.tools.utils import download_file
from lgr.utils import tag_to_language_script
from lgr_auth.models import LgrRole
from lgr_idn_table_review.icann_tools.models import IdnReviewIcannReport, IANAIdnTable
from lgr_models.models.lgr import RefLgr, RzLgrMember, RzLgr
from lgr_session.api import LGRStorage
Expand All @@ -40,7 +39,7 @@ def __init__(self, user):
super().__init__(user, filter_on_user=False)

def storage_can_read(self):
return self.user.role in [LgrRole.ICANN.value, LgrRole.ADMIN.value]
return self.user.is_icann()


def get_icann_idn_repository_tables():
Expand Down
4 changes: 4 additions & 0 deletions src/lgr_idn_table_review/icann_tools/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from lgr.core import LGR
from lgr.metadata import Metadata, Version
from lgr.parser.heuristic_parser import HeuristicParser
from lgr_auth.models import LgrUser
from lgr_models.models.lgr import LgrBaseModel
from lgr_models.models.report import LGRReport
from lgr_session.views import StorageType
Expand All @@ -29,12 +30,15 @@ class IANAIdnTable(LgrBaseModel):
"""
Model for a IANA IDN table, not meant to be saved in the database
"""

lgr_parser = HeuristicParser

url = models.URLField()
date = models.DateField()
lang_script = models.CharField(max_length=16)
version = models.DecimalField(max_digits=2, decimal_places=1)
# on delete user do nothing since this is unmanaged
owner = models.ForeignKey(to=LgrUser, on_delete=models.DO_NOTHING, related_name='+')

class Meta:
managed = False # do not manage this model, this is only used to create objects that won't be saved in the DB
Expand Down
3 changes: 1 addition & 2 deletions src/lgr_idn_table_review/icann_tools/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from django.utils.translation import ugettext_lazy as _
from django.views.generic import TemplateView

from lgr_auth.models import LgrRole
from lgr_idn_table_review.icann_tools.api import LGRIcannStorage
from lgr_web.views import INTERFACE_SESSION_MODE_KEY, Interfaces
from .tasks import idn_table_review_task
Expand All @@ -20,7 +19,7 @@ def setup(self, request, *args, **kwargs):
self.storage = LGRIcannStorage(request.user)

def test_func(self):
return self.request.user.role in [LgrRole.ICANN.value, LgrRole.ADMIN.value]
return self.request.user.is_icann()


class IdnTableIcannModeView(BaseIcannView, TemplateView):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,17 @@
{% for reports_grouped in report_ids %}
<li>
{% with report=reports_grouped.list|first %}
<form method="post" action="{% url "lgr_review_delete_report" report_id=report.report_id %}?next={{ request.path }}">
<a href="{% url 'lgr_review_report' report_id=report.report_id %}">{{ report.report_id }}</a>
<form id="form-delete-{{ report_id }}" method="post"
action="{% url "lgr_review_delete_report" report_id=report.report_id %}?next={{ request.path }}">
{% csrf_token %}
<button type="submit" class="delete_report confirm-prompt"
style="border: none; background: none;"
data-confirmation-prompt="{% blocktrans with report.report_id as report_id %}Are you sure you want to delete report {{ report_id }}?{% endblocktrans %}">
<span class="glyphicon glyphicon-trash" style="color :#333"></span>
</button>
</form>
<a href="{% url 'lgr_review_report' report_id=report.report_id %}">{{ report.report_id }}</a>
<a href="#"
class="delete_report confirm-prompt"
data-confirmation-prompt="{% blocktrans with report.report_id as report_id %}Are you sure you want to delete report {{ report_id }}?{% endblocktrans %}"
data-confirmation-action="$('#form-delete-{{ report_id }}').submit()">
<i class="glyphicon glyphicon-trash"></i>
</a>
{% endwith %}
</li>
{% empty %}
Expand Down
1 change: 0 additions & 1 deletion src/lgr_idn_table_review/idn_tool/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,6 @@ class IdnTableReviewDisplayIdnTable(IdnTableReviewViewMixin, SingleObjectMixin,

def get(self, request, *args, **kwargs):
idn_table = self.get_object(queryset=self.api.lgr_queryset())
# FIXME: should distinct txt and xml LGRs
content_type = 'text/plain'
if idn_table.filename.endswith('xml'):
content_type = 'text/xml'
Expand Down
6 changes: 0 additions & 6 deletions src/lgr_manage/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
from django.utils.translation import ugettext_lazy as _

from lgr_advanced.lgr_editor.forms import FILE_FIELD_ENCODING_HELP
from lgr_auth.models import LgrUser
from lgr_models.models.lgr import RzLgr, RzLgrMember, RefLgr, MSR
from lgr_web.utils import IANA_LANG_REGISTRY

Expand Down Expand Up @@ -56,8 +55,3 @@ class Meta:
'name': _('Name'),
}


class UserCreateForm(forms.ModelForm):
class Meta:
model = LgrUser
fields = ['email', 'role']
Loading

0 comments on commit 4b58cfe

Please sign in to comment.