mirror of
https://gitlab2.federez.net/re2o/re2o
synced 2024-12-23 15:33:45 +00:00
Fix #98
This commit is contained in:
parent
5d5c6bd17c
commit
a3b352b29d
4 changed files with 200 additions and 70 deletions
|
@ -213,3 +213,17 @@ def remove_user_room(room, force=True):
|
||||||
if force or not user.has_access():
|
if force or not user.has_access():
|
||||||
user.room = None
|
user.room = None
|
||||||
user.save()
|
user.save()
|
||||||
|
|
||||||
|
|
||||||
|
def permission_tree(queryset=None):
|
||||||
|
r = {}
|
||||||
|
permissions = queryset or Permission.objects.all()
|
||||||
|
for p in permissions:
|
||||||
|
key, app, model = p.natural_key()
|
||||||
|
name = p.name
|
||||||
|
if app not in r:
|
||||||
|
r[app] = {}
|
||||||
|
if model not in r[app]:
|
||||||
|
r[app][model] = {}
|
||||||
|
r[app][model][key] = p
|
||||||
|
return r
|
||||||
|
|
|
@ -48,6 +48,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
<script src="/static/js/bootstrap-tokenfield/bootstrap-tokenfield.js"></script>
|
<script src="/static/js/bootstrap-tokenfield/bootstrap-tokenfield.js"></script>
|
||||||
<script src="{% static 'js/collapse-from-url.js' %}"></script>
|
<script src="{% static 'js/collapse-from-url.js' %}"></script>
|
||||||
|
|
||||||
|
{% block custom_js %}{% endblock %}
|
||||||
|
|
||||||
{# Load CSS #}
|
{# Load CSS #}
|
||||||
{% bootstrap_css %}
|
{% bootstrap_css %}
|
||||||
<link href="{% static 'css/typeaheadjs.css' %}" rel="stylesheet">
|
<link href="{% static 'css/typeaheadjs.css' %}" rel="stylesheet">
|
||||||
|
|
141
users/templates/users/edit_listright.html
Normal file
141
users/templates/users/edit_listright.html
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
{% extends 'users/sidebar.html' %}
|
||||||
|
{% 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 bootstrap3 %}
|
||||||
|
{% load static %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% block title %}{% trans "Users" %}{% endblock %}
|
||||||
|
|
||||||
|
{% block custom_js %}
|
||||||
|
<!-- first import Vue -->
|
||||||
|
<script src="https://unpkg.com/vue/dist/vue.js"></script>
|
||||||
|
<!-- import JavaScript -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/liquor-tree/dist/liquor-tree.umd.js"></script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
{% bootstrap_form_errors form %}
|
||||||
|
|
||||||
|
<form class="form" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
{% bootstrap_field form.name %}
|
||||||
|
{% bootstrap_field form.unix_name %}
|
||||||
|
{% if form.gid %}
|
||||||
|
{% bootstrap_field form.gid %}
|
||||||
|
{% endif %}
|
||||||
|
{% bootstrap_field form.critical %}
|
||||||
|
{% bootstrap_field form.details %}
|
||||||
|
<div id="treeapp" style="display: none;">
|
||||||
|
<label class="control-label">Permissions</label>
|
||||||
|
<tree
|
||||||
|
:data="treeData"
|
||||||
|
:options="treeOptions"
|
||||||
|
@node:checked="onNodeChecked"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div id="legacy_form">
|
||||||
|
{% bootstrap_field form.permissions %}
|
||||||
|
</div>
|
||||||
|
{% bootstrap_button action_name button_type="submit" icon='ok' button_class='btn-success' %}
|
||||||
|
</form>
|
||||||
|
{% if load_js_file %}
|
||||||
|
<script src="{{ load_js_file }}"></script>
|
||||||
|
{% endif %}
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
new Vue({
|
||||||
|
el: '#treeapp',
|
||||||
|
data: function() {
|
||||||
|
return {
|
||||||
|
treeData: this.getData(),
|
||||||
|
treeOptions: {
|
||||||
|
checkbox: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted(){
|
||||||
|
document.getElementById('legacy_form').style.display='none';
|
||||||
|
document.getElementById('treeapp').style.display='block';
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getData() {
|
||||||
|
return [
|
||||||
|
{% for app,models in permissions.items %}
|
||||||
|
{
|
||||||
|
text: '{{ app }}',
|
||||||
|
state: { expanded: false },
|
||||||
|
children: [
|
||||||
|
{% for model,keys in models.items %}
|
||||||
|
{
|
||||||
|
text:'{{model}}',
|
||||||
|
children:[
|
||||||
|
{% for key,permission in keys.items %}
|
||||||
|
{
|
||||||
|
text: '{{ key }} : {{ permission.name }}',
|
||||||
|
{% if permission in instance.permissions.all %}
|
||||||
|
state: { checked: true },
|
||||||
|
{% else %}
|
||||||
|
state: { checked: false },
|
||||||
|
{% endif %}
|
||||||
|
data: {
|
||||||
|
checkbox_value: '{{permission.id}}'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{% endfor %}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{% endfor %}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{% endfor %}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
onNodeChecked(node) {
|
||||||
|
if ("checkbox_value" in node.data) {
|
||||||
|
var selector = '#id_ListRight-permissions input[value="'.concat(node.data.checkbox_value, '"]');
|
||||||
|
console.log(selector);
|
||||||
|
document.querySelector(selector).checked=true;
|
||||||
|
// document.getElementById(node.data.checkbox_id).checked=true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onNodeUnchecked(node) {
|
||||||
|
if ("checkbox_value" in node.data) {
|
||||||
|
var selector = '#id_ListRight-permissions input[value="'.concat(node.data.checkbox_value, '"]');
|
||||||
|
console.log(selector);
|
||||||
|
document.querySelector(selector).checked=false;
|
||||||
|
// document.getElementById(node.data.checkbox_id).checked=false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
113
users/views.py
113
users/views.py
|
@ -61,7 +61,7 @@ from preferences.models import OptionalUser, GeneralOption, AssoOption
|
||||||
from importlib import import_module
|
from importlib import import_module
|
||||||
from re2o.settings_local import OPTIONNAL_APPS_RE2O
|
from re2o.settings_local import OPTIONNAL_APPS_RE2O
|
||||||
from re2o.views import form
|
from re2o.views import form
|
||||||
from re2o.utils import all_has_access
|
from re2o.utils import all_has_access, permission_tree
|
||||||
from re2o.base import re2o_paginator, SortTable
|
from re2o.base import re2o_paginator, SortTable
|
||||||
from re2o.acl import (
|
from re2o.acl import (
|
||||||
can_create,
|
can_create,
|
||||||
|
@ -123,7 +123,9 @@ def new_user(request):
|
||||||
|
|
||||||
GTU_sum_up = GeneralOption.get_cached_value("GTU_sum_up")
|
GTU_sum_up = GeneralOption.get_cached_value("GTU_sum_up")
|
||||||
GTU = GeneralOption.get_cached_value("GTU")
|
GTU = GeneralOption.get_cached_value("GTU")
|
||||||
is_set_password_allowed = OptionalUser.get_cached_value("allow_set_password_during_user_creation")
|
is_set_password_allowed = OptionalUser.get_cached_value(
|
||||||
|
"allow_set_password_during_user_creation"
|
||||||
|
)
|
||||||
|
|
||||||
if user.is_valid():
|
if user.is_valid():
|
||||||
user = user.save()
|
user = user.save()
|
||||||
|
@ -200,11 +202,7 @@ def edit_club_admin_members(request, club_instance, **_kwargs):
|
||||||
reverse("users:profil", kwargs={"userid": str(club_instance.id)})
|
reverse("users:profil", kwargs={"userid": str(club_instance.id)})
|
||||||
)
|
)
|
||||||
return form(
|
return form(
|
||||||
{
|
{"userform": club, "showCGU": False, "action_name": _("Edit"),},
|
||||||
"userform": club,
|
|
||||||
"showCGU": False,
|
|
||||||
"action_name": _("Edit"),
|
|
||||||
},
|
|
||||||
"users/user.html",
|
"users/user.html",
|
||||||
request,
|
request,
|
||||||
)
|
)
|
||||||
|
@ -234,9 +232,7 @@ def edit_info(request, user, userid):
|
||||||
|
|
||||||
return redirect(reverse("users:profil", kwargs={"userid": str(userid)}))
|
return redirect(reverse("users:profil", kwargs={"userid": str(userid)}))
|
||||||
return form(
|
return form(
|
||||||
{"userform": user_form, "action_name": _("Edit")},
|
{"userform": user_form, "action_name": _("Edit")}, "users/user.html", request,
|
||||||
"users/user.html",
|
|
||||||
request,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -250,12 +246,12 @@ def state(request, user, userid):
|
||||||
user_instance = state_form.save()
|
user_instance = state_form.save()
|
||||||
messages.success(request, _("The states were edited."))
|
messages.success(request, _("The states were edited."))
|
||||||
if user_instance.trigger_email_changed_state(request):
|
if user_instance.trigger_email_changed_state(request):
|
||||||
messages.success(request, _("An email to confirm the address was sent."))
|
messages.success(
|
||||||
|
request, _("An email to confirm the address was sent.")
|
||||||
|
)
|
||||||
return redirect(reverse("users:profil", kwargs={"userid": str(userid)}))
|
return redirect(reverse("users:profil", kwargs={"userid": str(userid)}))
|
||||||
return form(
|
return form(
|
||||||
{"userform": state_form, "action_name": _("Edit")},
|
{"userform": state_form, "action_name": _("Edit")}, "users/user.html", request,
|
||||||
"users/user.html",
|
|
||||||
request,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -270,9 +266,7 @@ def groups(request, user, userid):
|
||||||
messages.success(request, _("The groups were edited."))
|
messages.success(request, _("The groups were edited."))
|
||||||
return redirect(reverse("users:profil", kwargs={"userid": str(userid)}))
|
return redirect(reverse("users:profil", kwargs={"userid": str(userid)}))
|
||||||
return form(
|
return form(
|
||||||
{"userform": group_form, "action_name": _("Edit")},
|
{"userform": group_form, "action_name": _("Edit")}, "users/user.html", request,
|
||||||
"users/user.html",
|
|
||||||
request,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -325,9 +319,7 @@ def new_serviceuser(request):
|
||||||
messages.success(request, _("The service user was created."))
|
messages.success(request, _("The service user was created."))
|
||||||
return redirect(reverse("users:index-serviceusers"))
|
return redirect(reverse("users:index-serviceusers"))
|
||||||
return form(
|
return form(
|
||||||
{"userform": user, "action_name": _("Add")},
|
{"userform": user, "action_name": _("Add")}, "users/user.html", request,
|
||||||
"users/user.html",
|
|
||||||
request,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -342,9 +334,7 @@ def edit_serviceuser(request, serviceuser, **_kwargs):
|
||||||
messages.success(request, _("The service user was edited."))
|
messages.success(request, _("The service user was edited."))
|
||||||
return redirect(reverse("users:index-serviceusers"))
|
return redirect(reverse("users:index-serviceusers"))
|
||||||
return form(
|
return form(
|
||||||
{"userform": serviceuser, "action_name": _("Edit")},
|
{"userform": serviceuser, "action_name": _("Edit")}, "users/user.html", request,
|
||||||
"users/user.html",
|
|
||||||
request,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -380,9 +370,7 @@ def add_ban(request, user, userid):
|
||||||
return redirect(reverse("users:profil", kwargs={"userid": str(userid)}))
|
return redirect(reverse("users:profil", kwargs={"userid": str(userid)}))
|
||||||
if user.is_ban():
|
if user.is_ban():
|
||||||
messages.error(request, _("Warning: this user already has an active ban."))
|
messages.error(request, _("Warning: this user already has an active ban."))
|
||||||
return form(
|
return form({"userform": ban, "action_name": _("Add")}, "users/user.html", request)
|
||||||
{"userform": ban, "action_name": _("Add")}, "users/user.html", request
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
|
@ -399,9 +387,7 @@ def edit_ban(request, ban_instance, **_kwargs):
|
||||||
ban.save()
|
ban.save()
|
||||||
messages.success(request, _("The ban was edited."))
|
messages.success(request, _("The ban was edited."))
|
||||||
return redirect(reverse("users:index"))
|
return redirect(reverse("users:index"))
|
||||||
return form(
|
return form({"userform": ban, "action_name": _("Edit")}, "users/user.html", request)
|
||||||
{"userform": ban, "action_name": _("Edit")}, "users/user.html", request
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
|
@ -434,9 +420,7 @@ def add_whitelist(request, user, userid):
|
||||||
request, _("Warning: this user already has an active whitelist.")
|
request, _("Warning: this user already has an active whitelist.")
|
||||||
)
|
)
|
||||||
return form(
|
return form(
|
||||||
{"userform": whitelist, "action_name": _("Add")},
|
{"userform": whitelist, "action_name": _("Add")}, "users/user.html", request,
|
||||||
"users/user.html",
|
|
||||||
request,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -454,9 +438,7 @@ def edit_whitelist(request, whitelist_instance, **_kwargs):
|
||||||
messages.success(request, _("The whitelist was edited."))
|
messages.success(request, _("The whitelist was edited."))
|
||||||
return redirect(reverse("users:index"))
|
return redirect(reverse("users:index"))
|
||||||
return form(
|
return form(
|
||||||
{"userform": whitelist, "action_name": _("Edit")},
|
{"userform": whitelist, "action_name": _("Edit")}, "users/user.html", request,
|
||||||
"users/user.html",
|
|
||||||
request,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -489,11 +471,7 @@ def add_emailaddress(request, user, userid):
|
||||||
messages.success(request, _("The local email account was created."))
|
messages.success(request, _("The local email account was created."))
|
||||||
return redirect(reverse("users:profil", kwargs={"userid": str(userid)}))
|
return redirect(reverse("users:profil", kwargs={"userid": str(userid)}))
|
||||||
return form(
|
return form(
|
||||||
{
|
{"userform": emailaddress, "showCGU": False, "action_name": _("Add"),},
|
||||||
"userform": emailaddress,
|
|
||||||
"showCGU": False,
|
|
||||||
"action_name": _("Add"),
|
|
||||||
},
|
|
||||||
"users/user.html",
|
"users/user.html",
|
||||||
request,
|
request,
|
||||||
)
|
)
|
||||||
|
@ -516,11 +494,7 @@ def edit_emailaddress(request, emailaddress_instance, **_kwargs):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return form(
|
return form(
|
||||||
{
|
{"userform": emailaddress, "showCGU": False, "action_name": _("Edit"),},
|
||||||
"userform": emailaddress,
|
|
||||||
"showCGU": False,
|
|
||||||
"action_name": _("Edit"),
|
|
||||||
},
|
|
||||||
"users/user.html",
|
"users/user.html",
|
||||||
request,
|
request,
|
||||||
)
|
)
|
||||||
|
@ -556,7 +530,9 @@ def edit_email_settings(request, user_instance, **_kwargs):
|
||||||
messages.success(request, _("The email settings were edited."))
|
messages.success(request, _("The email settings were edited."))
|
||||||
|
|
||||||
if user_instance.send_confirm_email_if_necessary(request):
|
if user_instance.send_confirm_email_if_necessary(request):
|
||||||
messages.success(request, _("An email to confirm your address was sent."))
|
messages.success(
|
||||||
|
request, _("An email to confirm your address was sent.")
|
||||||
|
)
|
||||||
|
|
||||||
return redirect(
|
return redirect(
|
||||||
reverse("users:profil", kwargs={"userid": str(user_instance.id)})
|
reverse("users:profil", kwargs={"userid": str(user_instance.id)})
|
||||||
|
@ -584,9 +560,7 @@ def add_school(request):
|
||||||
messages.success(request, _("The school was added."))
|
messages.success(request, _("The school was added."))
|
||||||
return redirect(reverse("users:index-school"))
|
return redirect(reverse("users:index-school"))
|
||||||
return form(
|
return form(
|
||||||
{"userform": school, "action_name": _("Add")},
|
{"userform": school, "action_name": _("Add")}, "users/user.html", request,
|
||||||
"users/user.html",
|
|
||||||
request,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -602,9 +576,7 @@ def edit_school(request, school_instance, **_kwargs):
|
||||||
messages.success(request, _("The school was edited."))
|
messages.success(request, _("The school was edited."))
|
||||||
return redirect(reverse("users:index-school"))
|
return redirect(reverse("users:index-school"))
|
||||||
return form(
|
return form(
|
||||||
{"userform": school, "action_name": _("Edit")},
|
{"userform": school, "action_name": _("Edit")}, "users/user.html", request,
|
||||||
"users/user.html",
|
|
||||||
request,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -662,9 +634,7 @@ def edit_shell(request, shell_instance, **_kwargs):
|
||||||
messages.success(request, _("The shell was edited."))
|
messages.success(request, _("The shell was edited."))
|
||||||
return redirect(reverse("users:index-shell"))
|
return redirect(reverse("users:index-shell"))
|
||||||
return form(
|
return form(
|
||||||
{"userform": shell, "action_name": _("Edit")},
|
{"userform": shell, "action_name": _("Edit")}, "users/user.html", request,
|
||||||
"users/user.html",
|
|
||||||
request,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -676,7 +646,9 @@ def del_shell(request, shell, **_kwargs):
|
||||||
shell.delete()
|
shell.delete()
|
||||||
messages.success(request, _("The shell was deleted."))
|
messages.success(request, _("The shell was deleted."))
|
||||||
return redirect(reverse("users:index-shell"))
|
return redirect(reverse("users:index-shell"))
|
||||||
return form({"objet": shell, "objet_name": _("shell")}, "users/delete.html", request)
|
return form(
|
||||||
|
{"objet": shell, "objet_name": _("shell")}, "users/delete.html", request
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
|
@ -690,8 +662,8 @@ def add_listright(request):
|
||||||
messages.success(request, _("The group of rights was added."))
|
messages.success(request, _("The group of rights was added."))
|
||||||
return redirect(reverse("users:index-listright"))
|
return redirect(reverse("users:index-listright"))
|
||||||
return form(
|
return form(
|
||||||
{"userform": listright, "action_name": _("Add")},
|
{"form": listright, "action_name": _("Add"), "permissions": permission_tree()},
|
||||||
"users/user.html",
|
"users/edit_listright.html",
|
||||||
request,
|
request,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -701,15 +673,20 @@ def add_listright(request):
|
||||||
def edit_listright(request, listright_instance, **_kwargs):
|
def edit_listright(request, listright_instance, **_kwargs):
|
||||||
""" Editer un groupe/droit, necessite droit bureau,
|
""" Editer un groupe/droit, necessite droit bureau,
|
||||||
à partir du listright id """
|
à partir du listright id """
|
||||||
listright = ListRightForm(request.POST or None, instance=listright_instance)
|
listright_form = ListRightForm(request.POST or None, instance=listright_instance)
|
||||||
if listright.is_valid():
|
if listright_form.is_valid():
|
||||||
if listright.changed_data:
|
if listright_form.changed_data:
|
||||||
listright.save()
|
listright_form.save()
|
||||||
messages.success(request, _("The group of rights was edited."))
|
messages.success(request, _("The group of rights was edited."))
|
||||||
return redirect(reverse("users:index-listright"))
|
return redirect(reverse("users:index-listright"))
|
||||||
return form(
|
return form(
|
||||||
{"userform": listright, "action_name": _("Edit")},
|
{
|
||||||
"users/user.html",
|
"form": listright_form,
|
||||||
|
"action_name": _("Edit"),
|
||||||
|
"permissions": permission_tree(),
|
||||||
|
"instance": listright_instance,
|
||||||
|
},
|
||||||
|
"users/edit_listright.html",
|
||||||
request,
|
request,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1064,7 +1041,7 @@ def process_email(request, req):
|
||||||
return form(
|
return form(
|
||||||
{"email": user.email, "name": user.get_full_name()},
|
{"email": user.email, "name": user.get_full_name()},
|
||||||
"users/confirm_email.html",
|
"users/confirm_email.html",
|
||||||
request
|
request,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1085,11 +1062,7 @@ def resend_confirmation_email(request, logged_user, userid):
|
||||||
messages.success(request, _("An email to confirm your address was sent."))
|
messages.success(request, _("An email to confirm your address was sent."))
|
||||||
return redirect(reverse("users:profil", kwargs={"userid": userid}))
|
return redirect(reverse("users:profil", kwargs={"userid": userid}))
|
||||||
|
|
||||||
return form(
|
return form({"email": user.email}, "users/resend_confirmation_email.html", request)
|
||||||
{"email": user.email},
|
|
||||||
"users/resend_confirmation_email.html",
|
|
||||||
request
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
|
|
Loading…
Reference in a new issue