mirror of
https://gitlab.crans.org/bde/nk20
synced 2025-06-21 01:48:21 +02:00
Merge branch 'beta' into JS_translations
# Conflicts: # apps/note/static/note/js/consos.js # locale/de/LC_MESSAGES/django.po # locale/es/LC_MESSAGES/django.po # locale/fr/LC_MESSAGES/django.po
This commit is contained in:
@ -26,6 +26,14 @@ admin_site = StrongAdminSite()
|
||||
admin_site.register(Site, SiteAdmin)
|
||||
|
||||
# Add external apps model
|
||||
if "oauth2_provider" in settings.INSTALLED_APPS:
|
||||
from oauth2_provider.admin import Application, ApplicationAdmin, Grant, \
|
||||
GrantAdmin, AccessToken, AccessTokenAdmin, RefreshToken, RefreshTokenAdmin
|
||||
admin_site.register(Application, ApplicationAdmin)
|
||||
admin_site.register(Grant, GrantAdmin)
|
||||
admin_site.register(AccessToken, AccessTokenAdmin)
|
||||
admin_site.register(RefreshToken, RefreshTokenAdmin)
|
||||
|
||||
if "django_htcpcp_tea" in settings.INSTALLED_APPS:
|
||||
from django_htcpcp_tea.admin import *
|
||||
from django_htcpcp_tea.models import *
|
||||
@ -44,9 +52,3 @@ if "rest_framework" in settings.INSTALLED_APPS:
|
||||
from rest_framework.authtoken.admin import *
|
||||
from rest_framework.authtoken.models import *
|
||||
admin_site.register(Token, TokenAdmin)
|
||||
|
||||
if "cas_server" in settings.INSTALLED_APPS:
|
||||
from cas_server.admin import *
|
||||
from cas_server.models import *
|
||||
admin_site.register(ServicePattern, ServicePatternAdmin)
|
||||
admin_site.register(FederatedIendityProvider, FederatedIendityProviderAdmin)
|
||||
|
@ -1,11 +0,0 @@
|
||||
[
|
||||
{
|
||||
"model": "cas_server.servicepattern",
|
||||
"pk": 1,
|
||||
"fields": {
|
||||
"pos": 1,
|
||||
"pattern": ".*",
|
||||
"name": "REPLACEME"
|
||||
}
|
||||
}
|
||||
]
|
@ -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,
|
||||
|
@ -49,16 +49,6 @@ try:
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
if "cas_server" in INSTALLED_APPS:
|
||||
# CAS Settings
|
||||
CAS_AUTO_CREATE_USER = False
|
||||
CAS_LOGO_URL = "/static/img/Saperlistpopette.png"
|
||||
CAS_FAVICON_URL = "/static/favicon/favicon-32x32.png"
|
||||
CAS_SHOW_POWERED = False
|
||||
|
||||
if "logs" in INSTALLED_APPS:
|
||||
MIDDLEWARE += ('note_kfet.middlewares.SessionMiddleware',)
|
||||
|
||||
if DEBUG:
|
||||
PASSWORD_HASHERS += ['member.hashers.DebugSuperuserBackdoor']
|
||||
if "debug_toolbar" in INSTALLED_APPS:
|
||||
|
@ -35,8 +35,10 @@ INSTALLED_APPS = [
|
||||
'mailer',
|
||||
'phonenumber_field',
|
||||
'polymorphic',
|
||||
'oauth2_provider',
|
||||
|
||||
# Django contrib
|
||||
# Django Admin will autodiscover our apps for our custom admin site.
|
||||
'django.contrib.admin',
|
||||
'django.contrib.admindocs',
|
||||
'django.contrib.auth',
|
||||
@ -77,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',
|
||||
]
|
||||
|
||||
@ -214,6 +218,16 @@ EMAIL_HOST_PASSWORD = os.getenv('EMAIL_PASSWORD', None)
|
||||
SERVER_EMAIL = os.getenv("NOTE_MAIL", "notekfet@example.com")
|
||||
DEFAULT_FROM_EMAIL = "NoteKfet2020 <" + SERVER_EMAIL + ">"
|
||||
|
||||
# Cache
|
||||
# https://docs.djangoproject.com/en/2.2/topics/cache/#setting-up-the-cache
|
||||
cache_address = os.getenv("CACHE_ADDRESS", "127.0.0.1:11211")
|
||||
CACHES = {
|
||||
'default': {
|
||||
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
|
||||
'LOCATION': cache_address,
|
||||
}
|
||||
}
|
||||
|
||||
# Django REST Framework
|
||||
REST_FRAMEWORK = {
|
||||
'DEFAULT_PERMISSION_CLASSES': [
|
||||
@ -233,7 +247,7 @@ REST_FRAMEWORK = {
|
||||
FORM_RENDERER = 'django.forms.renderers.TemplatesSetting'
|
||||
|
||||
# After login redirect user to transfer page
|
||||
LOGIN_REDIRECT_URL = '/note/transfer/'
|
||||
LOGIN_REDIRECT_URL = '/'
|
||||
|
||||
# An user session will expired after 3 hours
|
||||
SESSION_COOKIE_AGE = 60 * 60 * 3
|
||||
|
@ -24,6 +24,14 @@ if os.getenv("DJANGO_DEV_STORE_METHOD", "sqlite") != "postgresql":
|
||||
}
|
||||
}
|
||||
|
||||
# Dummy cache for development
|
||||
# https://docs.djangoproject.com/en/2.2/topics/cache/#setting-up-the-cache
|
||||
CACHES = {
|
||||
'default': {
|
||||
'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
|
||||
}
|
||||
}
|
||||
|
||||
# Break it, fix it!
|
||||
DEBUG = True
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
# CAS
|
||||
OPTIONAL_APPS = [
|
||||
# 'cas_server',
|
||||
# 'debug_toolbar'
|
||||
]
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
{% load static i18n pretty_money static getenv perms %}
|
||||
{% load static i18n pretty_money static getenv perms memberinfo %}
|
||||
{% comment %}
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
{% endcomment %}
|
||||
@ -67,7 +67,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
||||
<a class="nav-link {% if request.path_info == url %}active{% endif %}" href="{{ url }}"><i class="fa fa-coffee"></i> {% trans 'Consumptions' %}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if "note.transaction"|not_empty_model_list %}
|
||||
{% if user.is_authenticated and user|is_member:"Kfet" %}
|
||||
<li class="nav-item">
|
||||
{% url 'note:transfer' as url %}
|
||||
<a class="nav-link {% if request.path_info == url %}active{% endif %}" href="{{ url }}"><i class="fa fa-exchange"></i> {% trans 'Transfer' %} </a>
|
||||
@ -153,12 +153,36 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
||||
</div>
|
||||
</nav>
|
||||
<div class="{% block containertype %}container{% endblock %} my-3">
|
||||
{% if request.user.is_authenticated and not request.user.profile.email_confirmed %}
|
||||
<div class="alert alert-warning">
|
||||
{% trans "Your e-mail address is not validated. Please check your mail inbox and click on the validation link." %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div id="messages"></div>
|
||||
<div id="messages">
|
||||
{% if user.is_authenticated %}
|
||||
{% if not user|is_member:"BDE" %}
|
||||
<div class="alert alert-danger">
|
||||
{% trans "You are not a BDE member anymore. Please renew your membership if you want to use the note." %}
|
||||
</div>
|
||||
{% elif not user|is_member:"Kfet" %}
|
||||
<div class="alert alert-warning">
|
||||
{% trans "You are not a Kfet member, so you can't use your note account." %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if not user.profile.email_confirmed %}
|
||||
<div class="alert alert-warning">
|
||||
{% trans "Your e-mail address is not validated. Please check your mail inbox and click on the validation link." %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if user.sogecredit and not user.sogecredit.valid %}
|
||||
<div class="alert alert-info">
|
||||
{% blocktrans trimmed %}
|
||||
You declared that you opened a bank account in the Société générale. The bank did not validate the creation of the account to the BDE,
|
||||
so the registration bonus of 80 € is not credited and the membership is not paid yet.
|
||||
This verification procedure may last a few days.
|
||||
Please make sure that you go to the end of the account creation.
|
||||
{% endblocktrans %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{# TODO Add banners #}
|
||||
</div>
|
||||
{% block content %}
|
||||
<p>Default content...</p>
|
||||
{% endblock %}
|
||||
|
@ -1,99 +0,0 @@
|
||||
{% load i18n %}{% load static %}{% get_current_language as LANGUAGE_CODE %}<!DOCTYPE html>
|
||||
<html{% if LANGUAGE_CODE %} lang="{{LANGUAGE_CODE}}"{% endif %}>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge" /><![endif]-->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{% block title %}{% trans "Central Authentication Service" %}{% endblock %}</title>
|
||||
<link href="{{settings.CAS_COMPONENT_URLS.bootstrap3_css}}" rel="stylesheet">
|
||||
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="{{settings.CAS_COMPONENT_URLS.html5shiv}}"></script>
|
||||
<script src="{{settings.CAS_COMPONENT_URLS.respond}}"></script>
|
||||
<![endif]-->
|
||||
{% if settings.CAS_FAVICON_URL %}<link rel="shortcut icon" href="{{settings.CAS_FAVICON_URL}}" />{% endif %}
|
||||
<link href="{% static "cas_server/styles.css" %}" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<div id="wrap">
|
||||
<div class="container">
|
||||
{% if auto_submit %}<noscript>{% endif %}
|
||||
<div class="row">
|
||||
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
|
||||
<h1 id="app-name">
|
||||
{% if settings.CAS_LOGO_URL %}<img src="{{settings.CAS_LOGO_URL}}" alt="cas-logo" />{% endif %}
|
||||
Authentification Note Kfet 2020</h1>
|
||||
</div>
|
||||
</div>
|
||||
{% if auto_submit %}</noscript>{% endif %}
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-3 col-sm-2 col-xs-12"></div>
|
||||
<div class="col-lg-6 col-md-6 col-sm-8 col-xs-12">
|
||||
{% if auto_submit %}<noscript>{% endif %}
|
||||
{% for msg in CAS_INFO_RENDER %}
|
||||
<div class="alert alert-{{msg.type}}{% if msg.discardable %} alert-dismissable{% endif %}">
|
||||
{% if msg.discardable %}<button type="button" class="close" data-dismiss="alert" aria-hidden="true" id="info-{{msg.name}}">×</button>{% endif %}
|
||||
<p>{{msg.message}}</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% if settings.CAS_NEW_VERSION_HTML_WARNING and upgrade_available %}
|
||||
<div class="alert alert-info alert-dismissable">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-hidden="true" id="alert-version">×</button>
|
||||
<p>{% blocktrans %}A new version of the application is available. This instance runs {{VERSION}} and the last version is {{LAST_VERSION}}. Please consider upgrading.{% endblocktrans %}</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% block ante_messages %}{% endblock %}
|
||||
{% for message in messages %}
|
||||
<div {% spaceless %}
|
||||
{% if message.level == message_levels.DEBUG %}
|
||||
class="alert alert-warning"
|
||||
{% elif message.level == message_levels.INFO %}
|
||||
class="alert alert-info"
|
||||
{% elif message.level == message_levels.SUCCESS %}
|
||||
class="alert alert-success"
|
||||
{% elif message.level == message_levels.WARNING %}
|
||||
class="alert alert-warning"
|
||||
{% else %}
|
||||
class="alert alert-danger"
|
||||
{% endif %}
|
||||
{% endspaceless %}>
|
||||
<p>{{message}}</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% if auto_submit %}</noscript>{% endif %}
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
<div class="col-lg-3 col-md-3 col-sm-2 col-xs-0"></div>
|
||||
</div>
|
||||
</div> <!-- /container -->
|
||||
</div>
|
||||
<div style="clear: both;"></div>
|
||||
{% if settings.CAS_SHOW_POWERED %}
|
||||
<div id="footer">
|
||||
<p><a class="text-muted" href="https://pypi.org/project/django-cas-server/">django-cas-server powered</a></p>
|
||||
</div>
|
||||
{% endif %}
|
||||
<script src="{{settings.CAS_COMPONENT_URLS.jquery}}"></script>
|
||||
<script src="{{settings.CAS_COMPONENT_URLS.bootstrap3_js}}"></script>
|
||||
<script src="{% static "cas_server/functions.js" %}"></script>
|
||||
<script type="text/javascript">
|
||||
{% if settings.CAS_NEW_VERSION_HTML_WARNING and upgrade_available %}
|
||||
discard_and_remember("#alert-version", "cas-alert-version", "{{LAST_VERSION}}");
|
||||
{% endif %}
|
||||
{% for msg in CAS_INFO_RENDER %}
|
||||
{% if msg.discardable %}
|
||||
discard_and_remember("#info-{{msg.name}}", "cas-info-{{msg.name}}", "{{msg.hash}}");
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% block javascript_inline %}{% endblock %}
|
||||
</script>
|
||||
{% block javascript %}{% endblock %}
|
||||
</body>
|
||||
</html>
|
||||
<!--
|
||||
Powered by django-cas-server version {{VERSION}}
|
||||
|
||||
Pypi: https://pypi.org/project/django-cas-server/
|
||||
github: https://github.com/nitmir/django-cas-server
|
||||
-->
|
@ -23,6 +23,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
{{ profile_form|crispy }}
|
||||
{{ soge_form|crispy }}
|
||||
<button class="btn btn-success" type="submit">
|
||||
{% trans "Sign up" %}
|
||||
</button>
|
||||
|
@ -5,15 +5,14 @@ from django.conf import settings
|
||||
from django.conf.urls.static import static
|
||||
from django.urls import path, include
|
||||
from django.views.defaults import bad_request, permission_denied, page_not_found, server_error
|
||||
from django.views.generic import RedirectView
|
||||
|
||||
from member.views import CustomLoginView
|
||||
|
||||
from .admin import admin_site
|
||||
from .views import IndexView
|
||||
|
||||
urlpatterns = [
|
||||
# Dev so redirect to something random
|
||||
path('', RedirectView.as_view(pattern_name='note:transfer'), name='index'),
|
||||
path('', IndexView.as_view(), name='index'),
|
||||
|
||||
# Include project routers
|
||||
path('note/', include('note.urls')),
|
||||
@ -40,12 +39,11 @@ urlpatterns = [
|
||||
if settings.DEBUG:
|
||||
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||
|
||||
|
||||
if "cas_server" in settings.INSTALLED_APPS:
|
||||
urlpatterns += [
|
||||
# Include CAS Server routers
|
||||
path('cas/', include('cas_server.urls', namespace="cas_server")),
|
||||
]
|
||||
if "oauth2_provider" in settings.INSTALLED_APPS:
|
||||
# OAuth2 provider
|
||||
urlpatterns.append(
|
||||
path('o/', include('oauth2_provider.urls', namespace='oauth2_provider'))
|
||||
)
|
||||
|
||||
if "debug_toolbar" in settings.INSTALLED_APPS:
|
||||
import debug_toolbar
|
||||
|
30
note_kfet/views.py
Normal file
30
note_kfet/views.py
Normal file
@ -0,0 +1,30 @@
|
||||
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.urls import reverse
|
||||
from django.views.generic import RedirectView
|
||||
from note.models import Alias
|
||||
from permission.backends import PermissionBackend
|
||||
|
||||
|
||||
class IndexView(LoginRequiredMixin, RedirectView):
|
||||
def get_redirect_url(self, *args, **kwargs):
|
||||
"""
|
||||
Calculate the index page according to the roles.
|
||||
A normal user will have access to the transfer page.
|
||||
A non-Kfet member will have access to its user detail page.
|
||||
The user "note" will display the consumption interface.
|
||||
"""
|
||||
user = self.request.user
|
||||
|
||||
# The account note will have the consumption page as default page
|
||||
if not PermissionBackend.check_perm(user, "auth.view_user", user):
|
||||
return reverse("note:consos")
|
||||
|
||||
# People that can see the alias BDE are Kfet members
|
||||
if PermissionBackend.check_perm(user, "alias.view_alias", Alias.objects.get(name="BDE")):
|
||||
return reverse("note:transfer")
|
||||
|
||||
# Non-Kfet members will don't see the transfer page, but their profile page
|
||||
return reverse("member:user_detail", args=(user.pk,))
|
Reference in New Issue
Block a user