Compare commits

...

9 commits

43 changed files with 244 additions and 65 deletions

View file

@ -1,3 +0,0 @@
include LICENSE
recursive-include authens/static *
recursive-include authens/templates *

View file

@ -96,7 +96,7 @@ AUTHENS_ALLOW_STAFF = True
### Création d'utilisateurices ### Création d'utilisateurices
AuthENS maintient une tables des comptes clipper connus. AuthENS maintient une table des comptes clipper connus.
Cette table est automatiquement mise à jour lors qu'une personne se connecte via Cette table est automatiquement mise à jour lors qu'une personne se connecte via
le CAS pour la première fois. le CAS pour la première fois.
En revanche lorsqu'un nouveau compte est créé manuellement et que ce compte En revanche lorsqu'un nouveau compte est créé manuellement et que ce compte

53
default.nix Normal file
View file

@ -0,0 +1,53 @@
{
sources ? import ./npins,
pkgs ? import sources.nixpkgs { },
}:
let
nix-pkgs = import sources.nix-pkgs { inherit pkgs; };
python3 = pkgs.python3.override { packageOverrides = _: _: { inherit (nix-pkgs) python-cas; }; };
deploy-pypi = pkgs.writeShellApplication {
name = "deploy-pypi";
runtimeInputs = [
(pkgs.python3.withPackages (ps: [
ps.setuptools
ps.build
ps.twine
]))
];
text = ''
# Clean the repository
rm -rf dist
python -m build
twine upload dist/*
'';
};
in
{
devShell = pkgs.mkShell {
name = "cas-eleves.dev";
packages = [
(python3.withPackages (ps: [
ps.django
ps.python-ldap
ps.python-cas
]))
pkgs.gettext
pkgs.gtranslator
];
};
publishShell = pkgs.mkShell {
name = "loadcredential.publish";
packages = [ deploy-pypi ];
};
}

80
npins/default.nix Normal file
View file

@ -0,0 +1,80 @@
# Generated by npins. Do not modify; will be overwritten regularly
let
data = builtins.fromJSON (builtins.readFile ./sources.json);
version = data.version;
mkSource =
spec:
assert spec ? type;
let
path =
if spec.type == "Git" then
mkGitSource spec
else if spec.type == "GitRelease" then
mkGitSource spec
else if spec.type == "PyPi" then
mkPyPiSource spec
else if spec.type == "Channel" then
mkChannelSource spec
else
builtins.throw "Unknown source type ${spec.type}";
in
spec // { outPath = path; };
mkGitSource =
{
repository,
revision,
url ? null,
hash,
branch ? null,
...
}:
assert repository ? type;
# At the moment, either it is a plain git repository (which has an url), or it is a GitHub/GitLab repository
# In the latter case, there we will always be an url to the tarball
if url != null then
(builtins.fetchTarball {
inherit url;
sha256 = hash;
})
else
assert repository.type == "Git";
let
urlToName =
url: rev:
let
matched = builtins.match "^.*/([^/]*)(\\.git)?$" repository.url;
short = builtins.substring 0 7 rev;
appendShort = if (builtins.match "[a-f0-9]*" rev) != null then "-${short}" else "";
in
"${if matched == null then "source" else builtins.head matched}${appendShort}";
name = urlToName repository.url revision;
in
builtins.fetchGit {
url = repository.url;
rev = revision;
inherit name;
narHash = hash;
};
mkPyPiSource =
{ url, hash, ... }:
builtins.fetchurl {
inherit url;
sha256 = hash;
};
mkChannelSource =
{ url, hash, ... }:
builtins.fetchTarball {
inherit url;
sha256 = hash;
};
in
if version == 4 then
builtins.mapAttrs (_: mkSource) data.pins
else
throw "Unsupported format version ${toString version} in sources.json. Try running `npins upgrade`"

22
npins/sources.json Normal file
View file

@ -0,0 +1,22 @@
{
"pins": {
"nix-pkgs": {
"type": "Git",
"repository": {
"type": "Git",
"url": "https://git.hubrecht.ovh/hubrecht/nix-pkgs.git"
},
"branch": "main",
"revision": "46879d052e4a694ceb3027dbcff641c44e0ae1bd",
"url": null,
"hash": "sha256-/Yn3NDYA76bv8x06jahLAJ2z54L0vFeAtQKzyW3MfGA="
},
"nixpkgs": {
"type": "Channel",
"name": "nixpkgs-unstable",
"url": "https://releases.nixos.org/nixpkgs/nixpkgs-24.11pre647329.6842b061970b/nixexprs.tar.xz",
"hash": "04inyzaffqclmymaphc4cwhywnyk51hi44508kfbsj9h57875hb6"
}
},
"version": 4
}

49
pyproject.toml Normal file
View file

@ -0,0 +1,49 @@
[build-system]
requires = ["setuptools", "setuptools_scm"]
build-backend = "setuptools.build_meta"
[project]
name = "authens"
dynamic = ["version"]
authors = [
{name = "Klub Dev ENS", email = "klub-dev@ens.fr"},
{name = "Tom Hubrecht", email = "pypi@mail.hubrecht.ovh"},
]
description = "CAS Authentication Client at the ENS."
license = {file = "LICENSE"}
readme = "README.md"
classifiers = [
"Development Status :: 4 - Beta",
"Environment :: Web Environment",
"Framework :: Django",
"Framework :: Django :: 4.1",
"Framework :: Django :: 4.2",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Topic :: Internet :: WWW/HTTP",
"Topic :: Internet :: WWW/HTTP :: Dynamic Content",
]
dependencies = [
"django >= 4.1",
"python-ldap >= 3, < 4",
"python-cas >= 1.5, < 2",
]
[project.urls]
Homepage = "https://git.dgnum.eu/DGNum/authens"
Repository = "https://git.dgnum.eu/DGNum/authens"
Issues = "https://git.dgnum.eu/DGNum/authens/issues"
[tool.setuptools.dynamic]
version = {attr = "authens.__VERSION__"}
[tool.setuptools.packages.find]
where = ["src"]

View file

@ -1,38 +0,0 @@
import setuptools
with open("README.md", "r") as file:
long_description = file.read()
setuptools.setup(
name="authens",
version="0.1b5",
author="Klub Dev ENS",
author_email="klub-dev@ens.fr",
description="CAS Authentication at the ENS",
long_description=long_description,
long_description_content_type="text/markdown",
url="https://git.eleves.ens.fr/klub-dev-ens/authens",
packages=setuptools.find_packages(),
include_package_data=True,
classifiers=[
"Environment :: Web Environment",
"Framework :: Django",
"Framework :: Django :: 2.2",
"Framework :: Django :: 3.1",
"Framework :: Django :: 3.2",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Topic :: Internet :: WWW/HTTP",
"Topic :: Internet :: WWW/HTTP :: Dynamic Content",
],
python_requires=">=3.5",
install_requires=["Django>=2.2", "python-ldap>=3,<4", "python-cas>=1.5,<2"],
)

1
shell.nix Normal file
View file

@ -0,0 +1 @@
(import ./. { }).devShell

5
src/authens/__init__.py Normal file
View file

@ -0,0 +1,5 @@
__VERSION__ = "0.2.0"
__all__ = [
"__VERSION__",
]

View file

@ -3,3 +3,4 @@ from django.apps import AppConfig
class AuthEnsConfig(AppConfig): class AuthEnsConfig(AppConfig):
name = "authens" name = "authens"
default_auto_field = "django.db.models.AutoField"

Binary file not shown.

View file

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: \n" "Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-01-28 20:40+0100\n" "POT-Creation-Date: 2022-11-02 10:22+0100\n"
"PO-Revision-Date: 2021-01-30 20:48+0100\n" "PO-Revision-Date: 2021-01-30 20:48+0100\n"
"Last-Translator: Tom Hubrecht <tom.hubrecht@ens.fr>\n" "Last-Translator: Tom Hubrecht <tom.hubrecht@ens.fr>\n"
"Language-Team: \n" "Language-Team: \n"
@ -22,7 +22,7 @@ msgstr ""
msgid "Ancien login clipper" msgid "Ancien login clipper"
msgstr "Old clipper username" msgstr "Old clipper username"
#: forms.py:18 templates/authens/login_switch.html:14 #: forms.py:18 templates/authens/login_switch.html:15
msgid "Mot de passe" msgid "Mot de passe"
msgstr "Password" msgstr "Password"
@ -39,7 +39,7 @@ msgstr ""
"No user exists with this username, this entrance year and/or this password. " "No user exists with this username, this entrance year and/or this password. "
"Please check your entry. Attention, all fields are case sensitive!" "Please check your entry. Attention, all fields are case sensitive!"
#: models.py:19 models.py:57 #: models.py:19 models.py:60
msgid "utilisateurice" msgid "utilisateurice"
msgstr "user" msgstr "user"
@ -47,36 +47,36 @@ msgstr "user"
msgid "login CAS" msgid "login CAS"
msgstr "CAS username" msgstr "CAS username"
#: models.py:30 models.py:67 #: models.py:30 models.py:70
msgid "année de création du compte CAS" msgid "année de création du compte CAS"
msgstr "year of CAS account creation" msgstr "year of CAS account creation"
#: models.py:34 #: models.py:37
msgid "Compte CAS" msgid "Compte CAS"
msgstr "CAS account" msgstr "CAS account"
#: models.py:35 #: models.py:38
msgid "Comptes CAS" msgid "Comptes CAS"
msgstr "CAS accounts" msgstr "CAS accounts"
#: models.py:39 #: models.py:42
#, python-format #, python-format
msgid "compte CAS %(cas_login)s (promo %(entrance_year)s) lié à %(user)s" msgid "compte CAS %(cas_login)s (promo %(entrance_year)s) lié à %(user)s"
msgstr "CAS account %(cas_login)s (year %(entrance_year)s) linked to %(user)s" msgstr "CAS account %(cas_login)s (year %(entrance_year)s) linked to %(user)s"
#: models.py:63 #: models.py:66
msgid "ancien login CAS" msgid "ancien login CAS"
msgstr "old CAS username" msgstr "old CAS username"
#: models.py:78 #: models.py:81
msgid "Ancien compte CAS" msgid "Ancien compte CAS"
msgstr "Old CAS account" msgstr "Old CAS account"
#: models.py:79 #: models.py:82
msgid "Anciens comptes CAS" msgid "Anciens comptes CAS"
msgstr "Old CAS accounts" msgstr "Old CAS accounts"
#: models.py:83 #: models.py:86
#, python-format #, python-format
msgid "" msgid ""
"Ancien compte CAS %(cas_login)s (promo %(entrance_year)s) lié à %(user)s" "Ancien compte CAS %(cas_login)s (promo %(entrance_year)s) lié à %(user)s"
@ -91,11 +91,11 @@ msgstr "Connection method"
msgid "Clipper" msgid "Clipper"
msgstr "Clipper" msgstr "Clipper"
#: templates/authens/login_switch.html:18 #: templates/authens/login_switch.html:20
msgid "Vieilleux" msgid "Vieilleux"
msgstr "Alumni" msgstr "Alumni"
#: templates/authens/login_switch.html:25 #: templates/authens/login_switch.html:27
#, python-format #, python-format
msgid "" msgid ""
"Si votre fin de scolarité approche, créez un mot de passe pour votre compte " "Si votre fin de scolarité approche, créez un mot de passe pour votre compte "
@ -153,16 +153,25 @@ msgstr "For your information, your username is the following: %(username)s"
msgid "L'équipe %(site_name)s" msgid "L'équipe %(site_name)s"
msgstr "The %(site_name)s team" msgstr "The %(site_name)s team"
#: views.py:86 #: views.py:89
msgid "Connexion échouée !" #, fuzzy
#| msgid "Connexion échouée !"
msgid "Connection échouée !"
msgstr "Connection failed!" msgstr "Connection failed!"
#: views.py:102 #: views.py:105
msgid "" msgid ""
"Un email de réinitialisation du mot de passe vient d'être envoyé à l'adresse " "Si un compte avec cet email existe, un email de réinitialisation vient de "
"indiquée !" "lui être envoyé !"
msgstr "A password reset email has just been sent to the indicated address!" msgstr ""
"A password reset email has just been send to the inidcated address, "
"provided an account with this email exists)"
#: views.py:112 #: views.py:115
msgid "Mot de passe modifié avec succès !" msgid "Mot de passe modifié avec succès !"
msgstr "Password changed successfully!" msgstr "Password changed successfully!"
#~ msgid ""
#~ "Un email de réinitialisation du mot de passe vient d'être envoyé à "
#~ "l'adresse indiquée !"
#~ msgstr "A password reset email has just been sent to the indicated address!"

View file

@ -102,7 +102,7 @@ class PasswordResetView(SuccessMessageMixin, auth_views.PasswordResetView):
success_url = reverse_lazy("authens:login") success_url = reverse_lazy("authens:login")
success_message = _( success_message = _(
"Un email de réinitialisation vient d'être envoyé à l'adresse indiquée !" "Si un compte avec cet email existe, un email de réinitialisation vient de lui être envoyé !"
) )
@ -138,8 +138,8 @@ class LogoutView(auth_views.LogoutView):
else: else:
self.cas_connected = False self.cas_connected = False
def get_next_page(self): def get_success_url(self):
next_page = super().get_next_page() next_page = super().get_success_url()
if self.cas_connected: if self.cas_connected:
cas_client = get_cas_client(self.request) cas_client = get_cas_client(self.request)