migrate ScoDoc7 user db

This commit is contained in:
Emmanuel Viennet 2021-07-05 00:07:17 +02:00
parent 4526a6b934
commit 7f6a21f040
6 changed files with 115 additions and 8 deletions

View File

@ -5,7 +5,6 @@
import base64
from datetime import datetime, timedelta
from hashlib import md5
import json
import os
import re
@ -40,6 +39,7 @@ class User(UserMixin, db.Model):
active = db.Column(db.Boolean, default=True, index=True)
password_hash = db.Column(db.String(128))
password_scodoc7 = db.Column(db.String(42))
last_seen = db.Column(db.DateTime, default=datetime.utcnow)
date_modif_passwd = db.Column(db.DateTime, default=datetime.utcnow)
date_created = db.Column(db.DateTime, default=datetime.utcnow)
@ -55,7 +55,6 @@ class User(UserMixin, db.Model):
self.roles = []
self.user_roles = []
super(User, self).__init__(**kwargs)
self._format_noms()
# Ajoute roles:
if (
not self.roles
@ -89,6 +88,18 @@ class User(UserMixin, db.Model):
"""
if not self.active: # inactived users can't login
return False
if (not self.password_hash) and self.password_scodoc7:
# Special case: user freshly migrated from ScoDoc7
if scu.check_scodoc7_password(self.password_scodoc7, password):
current_app.logger.warning(
"migrating legacy ScoDoc7 password for {}".format(self)
)
self.set_password(password)
self.password_scodoc7 = None
db.session.add(self)
db.session.commit()
return True
return False
if not self.password_hash: # user without password can't login
return False
return check_password_hash(self.password_hash, password)
@ -161,7 +172,6 @@ class User(UserMixin, db.Model):
for r_d in data["roles_string"].split(","):
role, dept = UserRole.role_dept_from_string(r_d)
self.add_role(role, dept)
self._format_noms()
def get_token(self, expires_in=3600):
now = datetime.utcnow()
@ -342,10 +352,10 @@ class Role(db.Model):
def insert_roles():
"""Create default roles"""
default_role = "Observateur"
for r, permissions in SCO_ROLES_DEFAULTS.items():
role = Role.query.filter_by(name=r).first()
for role_name, permissions in SCO_ROLES_DEFAULTS.items():
role = Role.query.filter_by(name=role_name).first()
if role is None:
role = Role(name=r)
role = Role(name=role_name)
role.reset_permissions()
for perm in permissions:
role.add_permission(perm)

View File

@ -28,10 +28,12 @@
""" Common definitions
"""
import base64
import bisect
import copy
import datetime
import json
from hashlib import md5
import numbers
import os
import re
@ -672,6 +674,16 @@ def get_scodoc_version():
return os.popen("cd %s; ./get_scodoc_version.sh -s" % SCO_TOOLS_DIR).read().strip()
def check_scodoc7_password(scodoc7_hash, password):
"""Check a password vs scodoc7 hash
used only during old databases migrations"""
m = md5()
m.update(password.encode("utf-8"))
# encodestring à remplacer par encodebytes #py3
h = base64.encodestring(m.digest()).decode("utf-8").strip()
return h == scodoc7_hash
# Simple string manipulations
# on utf-8 encoded python strings
# (yes, we should only use unicode strings, but... we use only strings)

View File

@ -4,8 +4,11 @@
{% block app_content %}
<h2>ScoDoc: gestion scolarité</h2>
<p>Bonjour <font color="red"><b>{{current_user.get_nomcomplet()}}</b></font>.</p>
{% if not current_user.is_anonymous %}
<p>Bonjour <font color="red"><b>{{current_user.get_nomcomplet()}}</b>
</font>.</p>
<p>N'oubliez pas de vous <a href="{{url_for('auth.logout')}}">déconnecter</a> après usage.</p>
{% endif %}
<ul class="main">
{% for dept in dept_ids %}

7
app/utils/__init__.py Normal file
View File

@ -0,0 +1,7 @@
# -*- mode: python -*-
# -*- coding: utf-8 -*-
# Utilitaires divers, à utiliser en ligne de commande
# via flask
from app.utils.import_scodoc7_user_db import import_scodoc7_user_db

View File

@ -0,0 +1,64 @@
# -*- mode: python -*-
# -*- coding: utf-8 -*-
import pdb
import re
import psycopg2
import psycopg2.extras
from flask import current_app
from app import app, db
from app.auth.models import User, Role
def import_scodoc7_user_db(scodoc7_db="dbname=SCOUSERS"):
"""Create users from existing ScoDoc7 db (SCOUSERS)
The resulting users are in SCO8USERS,
handled via Flask/SQLAlchemy ORM.
"""
cnx = psycopg2.connect(scodoc7_db)
cursor = cnx.cursor(cursor_factory=psycopg2.extras.DictCursor)
cursor.execute("SELECT * FROM sco_users;")
for u7 in cursor:
if User.query.filter_by(user_name=u7["user_name"]).first():
# user with same name exists !
current_app.logger.warning(
"User {} exists and is left unchanged".format(u7["user_name"])
)
else:
u = User(
user_name=u7["user_name"],
email=u7["email"],
date_modif_passwd=u7["date_modif_passwd"],
nom=u7["nom"],
prenom=u7["prenom"],
dept=u7["dept"],
passwd_temp=u7["passwd_temp"],
date_expiration=u7["date_expiration"],
password_scodoc7=u7["passwd"],
active=(u7["status"] == None),
)
# Set roles:
# ScoDoc7 roles are stored as 'AdminRT,EnsRT'
for role_dept in u7["roles"].split(","):
m = re.match(r"^([A-Za-z0-9]+?)([A-Z][A-Za-z0-9]*?)$", role_dept)
if not m:
current_app.logger.warning(
"User {}: ignoring role {}".format(u7["user_name"], role_dept)
)
else:
role_name = m.group(1)
dept = m.group(2)
role = Role.query.filter_by(name=role_name).first()
if not role:
current_app.logger.warning(
"User {}: ignoring role {}".format(
u7["user_name"], role_dept
)
)
else:
u.add_role(role, dept)
db.session.add(u)
current_app.logger.info("imported user {}".format(u))
db.session.commit()

View File

@ -20,6 +20,7 @@ from app import create_app, cli, db
from app.auth.models import User, Role, UserRole
from app.views import notes, scolar, absences
import app.utils as utils
from config import Config
@ -44,7 +45,7 @@ def make_shell_context():
@app.cli.command()
def user_db_init():
def user_db_init(): # user-db-init
"""Initialize the users database."""
click.echo("Init the db")
# Create roles:
@ -166,3 +167,13 @@ def test_interactive(filename=None):
exec(open(filename).read())
click.echo("Done.")
@app.cli.command()
@with_appcontext
def user_db_import_scodoc7(): # user-db-import-scodoc7
"""Import used defined in ScoDoc7 postgresql database into ScoDoc8
The old database SCOUSERS must be alive and readable by the current user.
This script is typically run as unix user www-data.
"""
utils.import_scodoc7_user_db()