mirror of
https://gitlab.crans.org/bde/nk20
synced 2025-07-01 21:41:15 +02:00
Compare commits
1 Commits
08e50ffc22
...
v1.0.2
Author | SHA1 | Date | |
---|---|---|---|
1c5e951c2f |
@ -1,50 +0,0 @@
|
|||||||
import sys
|
|
||||||
|
|
||||||
from django.db import migrations
|
|
||||||
|
|
||||||
|
|
||||||
def give_note_account_permissions(apps, schema_editor):
|
|
||||||
"""
|
|
||||||
Automatically manage the membership of the Note account.
|
|
||||||
"""
|
|
||||||
User = apps.get_model("auth", "user")
|
|
||||||
Membership = apps.get_model("member", "membership")
|
|
||||||
Role = apps.get_model("permission", "role")
|
|
||||||
|
|
||||||
note = User.objects.filter(username="note")
|
|
||||||
if not note.exists():
|
|
||||||
# We are in a test environment, don't log error message
|
|
||||||
if len(sys.argv) > 1 and sys.argv[1] == 'test':
|
|
||||||
return
|
|
||||||
print("Warning: Note account was not found. The note account was not imported.")
|
|
||||||
print("Make sure you have imported the NK15 database. The new import script handles correctly the permissions.")
|
|
||||||
print("This migration will be ignored, you can re-run it if you forgot the note account or ignore it if you "
|
|
||||||
"don't want this account.")
|
|
||||||
return
|
|
||||||
|
|
||||||
note = note.get()
|
|
||||||
|
|
||||||
# Set for the two clubs a large expiration date and the correct role.
|
|
||||||
for m in Membership.objects.filter(user_id=note.id).all():
|
|
||||||
m.date_end = "3142-12-12"
|
|
||||||
m.roles.set(Role.objects.filter(name="PC Kfet").all())
|
|
||||||
m.save()
|
|
||||||
# By default, the note account is only authorized to be logged from localhost.
|
|
||||||
note.password = "ipbased$127.0.0.1"
|
|
||||||
note.is_active = True
|
|
||||||
note.save()
|
|
||||||
# Ensure that the note of the account is disabled
|
|
||||||
note.note.inactivity_reason = 'forced'
|
|
||||||
note.note.is_active = False
|
|
||||||
note.save()
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
dependencies = [
|
|
||||||
('member', '0005_remove_null_tag_on_charfields'),
|
|
||||||
('permission', '0001_initial'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.RunPython(give_note_account_permissions),
|
|
||||||
]
|
|
@ -5,7 +5,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||||||
{% load i18n perms %}
|
{% load i18n perms %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% if can_manage_registrations %}
|
{% if "member.change_profile_registration_valid"|has_perm:user %}
|
||||||
<a class="btn btn-block btn-secondary mb-3" href="{% url 'registration:future_user_list' %}">
|
<a class="btn btn-block btn-secondary mb-3" href="{% url 'registration:future_user_list' %}">
|
||||||
<i class="fa fa-user-plus"></i> {% trans "Registrations" %}
|
<i class="fa fa-user-plus"></i> {% trans "Registrations" %}
|
||||||
</a>
|
</a>
|
||||||
|
@ -234,13 +234,6 @@ class UserListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
|
|||||||
|
|
||||||
return qs
|
return qs
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
|
||||||
context = super().get_context_data(**kwargs)
|
|
||||||
pre_registered_users = User.objects.filter(PermissionBackend.filter_queryset(self.request.user, User, "view"))\
|
|
||||||
.filter(profile__registration_valid=False)
|
|
||||||
context["can_manage_registrations"] = pre_registered_users.exists()
|
|
||||||
return context
|
|
||||||
|
|
||||||
|
|
||||||
class ProfileAliasView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
|
class ProfileAliasView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
|
||||||
"""
|
"""
|
||||||
@ -254,8 +247,8 @@ class ProfileAliasView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
|
|||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
note = context['object'].note
|
note = context['object'].note
|
||||||
context["aliases"] = AliasTable(
|
context["aliases"] = AliasTable(note.alias_set.filter(PermissionBackend
|
||||||
note.alias_set.filter(PermissionBackend.filter_queryset(self.request.user, Alias, "view")).distinct().all())
|
.filter_queryset(self.request.user, Alias, "view")).all())
|
||||||
context["can_create"] = PermissionBackend.check_perm(self.request.user, "note.add_alias", Alias(
|
context["can_create"] = PermissionBackend.check_perm(self.request.user, "note.add_alias", Alias(
|
||||||
note=context["object"].note,
|
note=context["object"].note,
|
||||||
name="",
|
name="",
|
||||||
@ -457,8 +450,8 @@ class ClubAliasView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
|
|||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
note = context['object'].note
|
note = context['object'].note
|
||||||
context["aliases"] = AliasTable(note.alias_set.filter(
|
context["aliases"] = AliasTable(note.alias_set.filter(PermissionBackend
|
||||||
PermissionBackend.filter_queryset(self.request.user, Alias, "view")).distinct().all())
|
.filter_queryset(self.request.user, Alias, "view")).all())
|
||||||
context["can_create"] = PermissionBackend.check_perm(self.request.user, "note.add_alias", Alias(
|
context["can_create"] = PermissionBackend.check_perm(self.request.user, "note.add_alias", Alias(
|
||||||
note=context["object"].note,
|
note=context["object"].note,
|
||||||
name="",
|
name="",
|
||||||
@ -677,13 +670,11 @@ class ClubAddMemberView(ProtectQuerysetMixin, ProtectedCreateView):
|
|||||||
if not last_name or not first_name or (not bank and credit_type.special_type == "Chèque"):
|
if not last_name or not first_name or (not bank and credit_type.special_type == "Chèque"):
|
||||||
if not last_name:
|
if not last_name:
|
||||||
form.add_error('last_name', _("This field is required."))
|
form.add_error('last_name', _("This field is required."))
|
||||||
error = True
|
|
||||||
if not first_name:
|
if not first_name:
|
||||||
form.add_error('first_name', _("This field is required."))
|
form.add_error('first_name', _("This field is required."))
|
||||||
error = True
|
|
||||||
if not bank and credit_type.special_type == "Chèque":
|
if not bank and credit_type.special_type == "Chèque":
|
||||||
form.add_error('bank', _("This field is required."))
|
form.add_error('bank', _("This field is required."))
|
||||||
error = True
|
return self.form_invalid(form)
|
||||||
|
|
||||||
return not error
|
return not error
|
||||||
|
|
||||||
|
@ -799,12 +799,12 @@
|
|||||||
"member",
|
"member",
|
||||||
"membership"
|
"membership"
|
||||||
],
|
],
|
||||||
"query": "{}",
|
"query": "{\"club\": [\"club\"]}",
|
||||||
"type": "change",
|
"type": "change",
|
||||||
"mask": 3,
|
"mask": 3,
|
||||||
"field": "roles",
|
"field": "roles",
|
||||||
"permanent": false,
|
"permanent": false,
|
||||||
"description": "Modifier les rôles d'une adhésion"
|
"description": "Modifier les rôles d'un adhérent d'un club"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -2081,7 +2081,7 @@
|
|||||||
],
|
],
|
||||||
"query": "{}",
|
"query": "{}",
|
||||||
"type": "change",
|
"type": "change",
|
||||||
"mask": 2,
|
"mask": 1,
|
||||||
"field": "invalidity_reason",
|
"field": "invalidity_reason",
|
||||||
"permanent": false,
|
"permanent": false,
|
||||||
"description": "Modifier la raison d'invalidité d'une transaction"
|
"description": "Modifier la raison d'invalidité d'une transaction"
|
||||||
@ -2807,38 +2807,6 @@
|
|||||||
"description": "Voir ses propres alias, pour toujours"
|
"description": "Voir ses propres alias, pour toujours"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"model": "permission.permission",
|
|
||||||
"pk": 180,
|
|
||||||
"fields": {
|
|
||||||
"model": [
|
|
||||||
"auth",
|
|
||||||
"user"
|
|
||||||
],
|
|
||||||
"query": "{\"profile__registration_valid\": false}",
|
|
||||||
"type": "view",
|
|
||||||
"mask": 2,
|
|
||||||
"field": "",
|
|
||||||
"permanent": false,
|
|
||||||
"description": "Voir n'importe quel utilisateur non encore inscrit"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"model": "permission.permission",
|
|
||||||
"pk": 181,
|
|
||||||
"fields": {
|
|
||||||
"model": [
|
|
||||||
"member",
|
|
||||||
"profile"
|
|
||||||
],
|
|
||||||
"query": "{\"registration_valid\": false}",
|
|
||||||
"type": "view",
|
|
||||||
"mask": 2,
|
|
||||||
"field": "",
|
|
||||||
"permanent": false,
|
|
||||||
"description": "Voir n'importe quel profil non encore inscrit"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"model": "permission.role",
|
"model": "permission.role",
|
||||||
"pk": 1,
|
"pk": 1,
|
||||||
@ -3434,6 +3402,7 @@
|
|||||||
135,
|
135,
|
||||||
136,
|
136,
|
||||||
137,
|
137,
|
||||||
|
138,
|
||||||
139,
|
139,
|
||||||
140,
|
140,
|
||||||
143,
|
143,
|
||||||
@ -3446,38 +3415,6 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"model": "permission.role",
|
|
||||||
"pk": 20,
|
|
||||||
"fields": {
|
|
||||||
"for_club": 2,
|
|
||||||
"name": "PC Kfet",
|
|
||||||
"permissions": [
|
|
||||||
6,
|
|
||||||
22,
|
|
||||||
24,
|
|
||||||
25,
|
|
||||||
26,
|
|
||||||
27,
|
|
||||||
30,
|
|
||||||
49,
|
|
||||||
50,
|
|
||||||
55,
|
|
||||||
56,
|
|
||||||
57,
|
|
||||||
58,
|
|
||||||
143,
|
|
||||||
150,
|
|
||||||
166,
|
|
||||||
167,
|
|
||||||
168,
|
|
||||||
176,
|
|
||||||
177,
|
|
||||||
180,
|
|
||||||
181
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"model": "wei.weirole",
|
"model": "wei.weirole",
|
||||||
"pk": 12,
|
"pk": 12,
|
||||||
|
@ -4,8 +4,6 @@
|
|||||||
import django_tables2 as tables
|
import django_tables2 as tables
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
|
|
||||||
from treasury.models import SogeCredit
|
|
||||||
|
|
||||||
|
|
||||||
class FutureUserTable(tables.Table):
|
class FutureUserTable(tables.Table):
|
||||||
"""
|
"""
|
||||||
@ -23,7 +21,6 @@ class FutureUserTable(tables.Table):
|
|||||||
fields = ('last_name', 'first_name', 'username', 'email', )
|
fields = ('last_name', 'first_name', 'username', 'email', )
|
||||||
model = User
|
model = User
|
||||||
row_attrs = {
|
row_attrs = {
|
||||||
'class': lambda record: 'table-row'
|
'class': 'table-row',
|
||||||
+ (' bg-warning' if SogeCredit.objects.filter(user=record).exists() else ''),
|
|
||||||
'data-href': lambda record: record.pk
|
'data-href': lambda record: record.pk
|
||||||
}
|
}
|
||||||
|
@ -235,7 +235,7 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, FormMixin,
|
|||||||
fee += 8000
|
fee += 8000
|
||||||
ctx["total_fee"] = "{:.02f}".format(fee / 100, )
|
ctx["total_fee"] = "{:.02f}".format(fee / 100, )
|
||||||
|
|
||||||
ctx["declare_soge_account"] = SogeCredit.objects.filter(user=user).exists()
|
ctx["declare_soge_account"] = True
|
||||||
|
|
||||||
return ctx
|
return ctx
|
||||||
|
|
||||||
|
Submodule apps/scripts updated: 654492f9e9...7e27c3b71b
@ -28,8 +28,6 @@ class TreasuryConfig(AppConfig):
|
|||||||
source__in=NoteSpecial.objects.filter(~Q(remittancetype=None)),
|
source__in=NoteSpecial.objects.filter(~Q(remittancetype=None)),
|
||||||
specialtransactionproxy=None,
|
specialtransactionproxy=None,
|
||||||
):
|
):
|
||||||
proxy = SpecialTransactionProxy(transaction=transaction, remittance=None)
|
SpecialTransactionProxy.objects.create(transaction=transaction, remittance=None)
|
||||||
proxy._force_save = True
|
|
||||||
proxy.save()
|
|
||||||
|
|
||||||
post_migrate.connect(setup_specialtransactions_proxies, sender=SpecialTransactionProxy)
|
post_migrate.connect(setup_specialtransactions_proxies, sender=SpecialTransactionProxy)
|
||||||
|
@ -10,8 +10,9 @@ def save_special_transaction(instance, created, **kwargs):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
if not hasattr(instance, "_no_signal"):
|
if not hasattr(instance, "_no_signal"):
|
||||||
if created and RemittanceType.objects.filter(
|
if instance.is_credit():
|
||||||
note=instance.source if instance.is_credit() else instance.destination).exists():
|
if created and RemittanceType.objects.filter(note=instance.source).exists():
|
||||||
proxy = SpecialTransactionProxy(transaction=instance, remittance=None)
|
SpecialTransactionProxy.objects.create(transaction=instance, remittance=None).save()
|
||||||
proxy._force_save = True
|
else:
|
||||||
proxy.save()
|
if created and RemittanceType.objects.filter(note=instance.destination).exists():
|
||||||
|
SpecialTransactionProxy.objects.create(transaction=instance, remittance=None).save()
|
||||||
|
@ -147,4 +147,4 @@ class SogeCreditTable(tables.Table):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = SogeCredit
|
model = SogeCredit
|
||||||
fields = ('user', 'user__last_name', 'user__first_name', 'amount', 'valid', )
|
fields = ('user', 'amount', 'valid', )
|
||||||
|
@ -11,14 +11,8 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<dl class="row">
|
<dl class="row">
|
||||||
<dt class="col-xl-6 text-right">{% trans 'last name'|capfirst %}</dt>
|
<dt class="col-xl-6 text-right">{% trans 'user'|capfirst %}</dt>
|
||||||
<dd class="col-xl-6">{{ object.user.last_name }}</dd>
|
<dd class="col-xl-6"><a href="{% url 'member:user_detail' pk=object.user.pk %}">{{ object.user }}</a></dd>
|
||||||
|
|
||||||
<dt class="col-xl-6 text-right">{% trans 'first name'|capfirst %}</dt>
|
|
||||||
<dd class="col-xl-6">{{ object.user.first_name }}</dd>
|
|
||||||
|
|
||||||
<dt class="col-xl-6 text-right">{% trans 'username'|capfirst %}</dt>
|
|
||||||
<dd class="col-xl-6"><a href="{% url 'member:user_detail' pk=object.user.pk %}">{{ object.user.username }}</a></dd>
|
|
||||||
|
|
||||||
{% if "note.view_note_balance"|has_perm:object.user.note %}
|
{% if "note.view_note_balance"|has_perm:object.user.note %}
|
||||||
<dt class="col-xl-6 text-right">{% trans 'balance'|capfirst %}</dt>
|
<dt class="col-xl-6 text-right">{% trans 'balance'|capfirst %}</dt>
|
||||||
|
@ -2,12 +2,12 @@
|
|||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth import login
|
|
||||||
from django.contrib.auth.models import AnonymousUser, User
|
from django.contrib.auth.models import AnonymousUser, User
|
||||||
from django.contrib.sessions.backends.db import SessionStore
|
|
||||||
|
|
||||||
from threading import local
|
from threading import local
|
||||||
|
|
||||||
|
from django.contrib.sessions.backends.db import SessionStore
|
||||||
|
|
||||||
USER_ATTR_NAME = getattr(settings, 'LOCAL_USER_ATTR_NAME', '_current_user')
|
USER_ATTR_NAME = getattr(settings, 'LOCAL_USER_ATTR_NAME', '_current_user')
|
||||||
SESSION_ATTR_NAME = getattr(settings, 'LOCAL_SESSION_ATTR_NAME', '_current_session')
|
SESSION_ATTR_NAME = getattr(settings, 'LOCAL_SESSION_ATTR_NAME', '_current_session')
|
||||||
IP_ATTR_NAME = getattr(settings, 'LOCAL_IP_ATTR_NAME', '_current_ip')
|
IP_ATTR_NAME = getattr(settings, 'LOCAL_IP_ATTR_NAME', '_current_ip')
|
||||||
@ -78,41 +78,6 @@ class SessionMiddleware(object):
|
|||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
class LoginByIPMiddleware(object):
|
|
||||||
"""
|
|
||||||
Allow some users to be authenticated based on their IP address.
|
|
||||||
For example, the "note" account should not be used elsewhere than the Kfet computer,
|
|
||||||
and should not have any password.
|
|
||||||
The password that is stored in database should be on the form "ipbased$my.public.ip.address".
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, get_response):
|
|
||||||
self.get_response = get_response
|
|
||||||
|
|
||||||
def __call__(self, request):
|
|
||||||
"""
|
|
||||||
If the user is not authenticated, get the used IP address
|
|
||||||
and check if an user is authorized to be automatically logged with this address.
|
|
||||||
If it is the case, the logging is performed with the full rights.
|
|
||||||
"""
|
|
||||||
if not request.user.is_authenticated:
|
|
||||||
if 'HTTP_X_REAL_IP' in request.META:
|
|
||||||
ip = request.META.get('HTTP_X_REAL_IP')
|
|
||||||
elif 'HTTP_X_FORWARDED_FOR' in request.META:
|
|
||||||
ip = request.META.get('HTTP_X_FORWARDED_FOR').split(', ')[0]
|
|
||||||
else:
|
|
||||||
ip = request.META.get('REMOTE_ADDR')
|
|
||||||
|
|
||||||
qs = User.objects.filter(password=f"ipbased${ip}")
|
|
||||||
if qs.exists():
|
|
||||||
login(request, qs.get())
|
|
||||||
session = request.session
|
|
||||||
session["permission_mask"] = 42
|
|
||||||
session.save()
|
|
||||||
|
|
||||||
return self.get_response(request)
|
|
||||||
|
|
||||||
|
|
||||||
class TurbolinksMiddleware(object):
|
class TurbolinksMiddleware(object):
|
||||||
"""
|
"""
|
||||||
Send the `Turbolinks-Location` header in response to a visit that was redirected,
|
Send the `Turbolinks-Location` header in response to a visit that was redirected,
|
||||||
|
@ -49,6 +49,9 @@ try:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
if "logs" in INSTALLED_APPS:
|
||||||
|
MIDDLEWARE += ('note_kfet.middlewares.SessionMiddleware',)
|
||||||
|
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
PASSWORD_HASHERS += ['member.hashers.DebugSuperuserBackdoor']
|
PASSWORD_HASHERS += ['member.hashers.DebugSuperuserBackdoor']
|
||||||
if "debug_toolbar" in INSTALLED_APPS:
|
if "debug_toolbar" in INSTALLED_APPS:
|
||||||
|
@ -79,8 +79,6 @@ MIDDLEWARE = [
|
|||||||
'django.middleware.locale.LocaleMiddleware',
|
'django.middleware.locale.LocaleMiddleware',
|
||||||
'django.contrib.sites.middleware.CurrentSiteMiddleware',
|
'django.contrib.sites.middleware.CurrentSiteMiddleware',
|
||||||
'django_htcpcp_tea.middleware.HTCPCPTeaMiddleware',
|
'django_htcpcp_tea.middleware.HTCPCPTeaMiddleware',
|
||||||
'note_kfet.middlewares.SessionMiddleware',
|
|
||||||
'note_kfet.middlewares.LoginByIPMiddleware',
|
|
||||||
'note_kfet.middlewares.TurbolinksMiddleware',
|
'note_kfet.middlewares.TurbolinksMiddleware',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user