1
0
mirror of https://gitlab.crans.org/bde/nk20 synced 2025-07-01 13:31:16 +02:00

Compare commits

..

8 Commits

10 changed files with 127 additions and 15 deletions

View File

@ -0,0 +1,50 @@
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),
]

View File

@ -799,12 +799,12 @@
"member",
"membership"
],
"query": "{\"club\": [\"club\"]}",
"query": "{}",
"type": "change",
"mask": 3,
"field": "roles",
"permanent": false,
"description": "Modifier les rôles d'un adhérent d'un club"
"description": "Modifier les rôles d'une adhésion"
}
},
{
@ -2081,7 +2081,7 @@
],
"query": "{}",
"type": "change",
"mask": 1,
"mask": 2,
"field": "invalidity_reason",
"permanent": false,
"description": "Modifier la raison d'invalidité d'une transaction"
@ -3402,7 +3402,6 @@
135,
136,
137,
138,
139,
140,
143,
@ -3415,6 +3414,26 @@
]
}
},
{
"model": "permission.role",
"pk": 20,
"fields": {
"for_club": 2,
"name": "PC Kfet",
"permissions": [
6,
24,
25,
26,
27,
30,
150,
166,
167,
168
]
}
},
{
"model": "wei.weirole",
"pk": 12,

View File

@ -4,6 +4,8 @@
import django_tables2 as tables
from django.contrib.auth.models import User
from treasury.models import SogeCredit
class FutureUserTable(tables.Table):
"""
@ -21,6 +23,7 @@ class FutureUserTable(tables.Table):
fields = ('last_name', 'first_name', 'username', 'email', )
model = User
row_attrs = {
'class': 'table-row',
'class': lambda record: 'table-row'
+ (' bg-warning' if SogeCredit.objects.filter(user=record).exists() else ''),
'data-href': lambda record: record.pk
}

View File

@ -235,7 +235,7 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, FormMixin,
fee += 8000
ctx["total_fee"] = "{:.02f}".format(fee / 100, )
ctx["declare_soge_account"] = True
ctx["declare_soge_account"] = SogeCredit.objects.filter(user=user).exists()
return ctx

View File

@ -147,4 +147,4 @@ class SogeCreditTable(tables.Table):
class Meta:
model = SogeCredit
fields = ('user', 'amount', 'valid', )
fields = ('user', 'user__last_name', 'user__first_name', 'amount', 'valid', )

View File

@ -11,8 +11,14 @@ SPDX-License-Identifier: GPL-3.0-or-later
</div>
<div class="card-body">
<dl class="row">
<dt class="col-xl-6 text-right">{% trans 'user'|capfirst %}</dt>
<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 'last name'|capfirst %}</dt>
<dd class="col-xl-6">{{ object.user.last_name }}</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 %}
<dt class="col-xl-6 text-right">{% trans 'balance'|capfirst %}</dt>

View File

@ -2,12 +2,12 @@
# SPDX-License-Identifier: GPL-3.0-or-later
from django.conf import settings
from django.contrib.auth import login
from django.contrib.auth.models import AnonymousUser, User
from django.contrib.sessions.backends.db import SessionStore
from threading import local
from django.contrib.sessions.backends.db import SessionStore
USER_ATTR_NAME = getattr(settings, 'LOCAL_USER_ATTR_NAME', '_current_user')
SESSION_ATTR_NAME = getattr(settings, 'LOCAL_SESSION_ATTR_NAME', '_current_session')
IP_ATTR_NAME = getattr(settings, 'LOCAL_IP_ATTR_NAME', '_current_ip')
@ -78,6 +78,41 @@ class SessionMiddleware(object):
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):
"""
Send the `Turbolinks-Location` header in response to a visit that was redirected,

View File

@ -49,9 +49,6 @@ try:
except ImportError:
pass
if "logs" in INSTALLED_APPS:
MIDDLEWARE += ('note_kfet.middlewares.SessionMiddleware',)
if DEBUG:
PASSWORD_HASHERS += ['member.hashers.DebugSuperuserBackdoor']
if "debug_toolbar" in INSTALLED_APPS:

View File

@ -79,6 +79,8 @@ MIDDLEWARE = [
'django.middleware.locale.LocaleMiddleware',
'django.contrib.sites.middleware.CurrentSiteMiddleware',
'django_htcpcp_tea.middleware.HTCPCPTeaMiddleware',
'note_kfet.middlewares.SessionMiddleware',
'note_kfet.middlewares.LoginByIPMiddleware',
'note_kfet.middlewares.TurbolinksMiddleware',
]