forked from ScoDoc/ScoDoc
migrate ScoDoc7 user db
This commit is contained in:
parent
4526a6b934
commit
7f6a21f040
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
7
app/utils/__init__.py
Normal 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
|
64
app/utils/import_scodoc7_user_db.py
Normal file
64
app/utils/import_scodoc7_user_db.py
Normal 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()
|
13
scodoc.py
13
scodoc.py
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user