forked from ScoDoc/ScoDoc
API users: password, plus de tests unitaires, correctifs.
This commit is contained in:
parent
64f9de95a5
commit
c6a99dc7d2
@ -14,9 +14,9 @@ from flask_login import current_user, login_required
|
||||
|
||||
from app import db, log
|
||||
from app.api import api_bp as bp, api_web_bp
|
||||
from app.models.etudiants import Identite
|
||||
from app.scodoc.sco_utils import json_error
|
||||
from app.auth.models import User, Role, UserRole
|
||||
from app.auth.models import is_valid_password
|
||||
from app.decorators import scodoc, permission_required
|
||||
from app.models import Departement
|
||||
from app.scodoc.sco_exceptions import ScoValueError
|
||||
@ -38,7 +38,7 @@ def user_info(uid: int):
|
||||
return json_error(404, "user not found")
|
||||
if g.scodoc_dept:
|
||||
allowed_depts = current_user.get_depts_with_permission(Permission.ScoUsersView)
|
||||
if user.dept not in allowed_depts:
|
||||
if (None not in allowed_depts) and (user.dept not in allowed_depts):
|
||||
return json_error(404, "user not found")
|
||||
|
||||
return jsonify(user.to_dict())
|
||||
@ -109,7 +109,7 @@ def user_create():
|
||||
if dept == "@all":
|
||||
dept = None
|
||||
allowed_depts = current_user.get_depts_with_permission(Permission.ScoUsersAdmin)
|
||||
if dept not in allowed_depts:
|
||||
if (None not in allowed_depts) and (dept not in allowed_depts):
|
||||
return json_error(403, "user_create: departement non autorise")
|
||||
if (dept is not None) and (
|
||||
Departement.query.filter_by(acronym=dept).first() is None
|
||||
@ -168,6 +168,35 @@ def user_edit(uid: int):
|
||||
return jsonify(user.to_dict())
|
||||
|
||||
|
||||
@bp.route("/user/<int:uid>/password", methods=["POST"])
|
||||
@api_web_bp.route("/user/<int:uid>/password", methods=["POST"])
|
||||
@login_required
|
||||
@scodoc
|
||||
@permission_required(Permission.ScoUsersAdmin)
|
||||
def user_password(uid: int):
|
||||
"""Modification du mot de passe d'un utilisateur
|
||||
Champs modifiables:
|
||||
{
|
||||
"password": str
|
||||
}
|
||||
Si le mot de passe ne convient pas, erreur 400.
|
||||
"""
|
||||
data = request.get_json(force=True) # may raise 400 Bad Request
|
||||
user: User = User.query.get_or_404(uid)
|
||||
password = data.get("password")
|
||||
if not password:
|
||||
return json_error(404, "user_password: missing password")
|
||||
if not is_valid_password(password):
|
||||
return json_error(400, "user_password: invalid password")
|
||||
allowed_depts = current_user.get_depts_with_permission(Permission.ScoUsersAdmin)
|
||||
if (None not in allowed_depts) and ((user.dept not in allowed_depts)):
|
||||
return json_error(403, "user_password: departement non autorise")
|
||||
user.set_password(password)
|
||||
db.session.add(user)
|
||||
db.session.commit()
|
||||
return jsonify(user.to_dict())
|
||||
|
||||
|
||||
@bp.route("/user/<int:uid>/role/<string:role_name>/add", methods=["POST"])
|
||||
@api_web_bp.route("/user/<int:uid>/role/<string:role_name>/add", methods=["POST"])
|
||||
@bp.route(
|
||||
|
@ -51,6 +51,7 @@ print(f"API URL={API_URL}")
|
||||
|
||||
|
||||
HEADERS = get_auth_headers(API_USER, API_PASSWORD)
|
||||
admin_h = get_auth_headers("admin_api", "admin_api")
|
||||
|
||||
departements = GET("/departements", headers=HEADERS)
|
||||
pp(departements)
|
||||
|
@ -76,10 +76,14 @@ def GET(path: str, headers: dict = None, errmsg=None, dept=None):
|
||||
return r.json() # decode la reponse JSON
|
||||
|
||||
|
||||
def POST_JSON(path: str, data: dict = {}, headers: dict = None, errmsg=None):
|
||||
def POST_JSON(path: str, data: dict = {}, headers: dict = None, errmsg=None, dept=None):
|
||||
"""Post"""
|
||||
if dept:
|
||||
url = SCODOC_URL + f"/ScoDoc/{dept}/api" + path
|
||||
else:
|
||||
url = API_URL + path
|
||||
r = requests.post(
|
||||
API_URL + path,
|
||||
url,
|
||||
json=data,
|
||||
headers=headers or {},
|
||||
verify=CHECK_CERTIFICATE,
|
||||
|
@ -8,6 +8,7 @@ Utilisation :
|
||||
|
||||
from tests.api.setup_test_api import (
|
||||
API_URL,
|
||||
APIError,
|
||||
CHECK_CERTIFICATE,
|
||||
GET,
|
||||
POST_JSON,
|
||||
@ -83,7 +84,7 @@ def test_edit_users(api_admin_headers):
|
||||
assert (nb_users + 1) == len(GET("/users/query", headers=admin_h))
|
||||
# Change le dept et rend inactif
|
||||
user = POST_JSON(
|
||||
f"/user/edit/{user['id']}",
|
||||
f"/user/{user['id']}/edit",
|
||||
{"active": False, "dept": "TAPI"},
|
||||
headers=admin_h,
|
||||
)
|
||||
@ -129,3 +130,102 @@ def test_roles(api_admin_headers):
|
||||
assert set(role["permissions"]) == {"ScoView", "ScoAbsAddBillet"}
|
||||
ans = POST_JSON("/role/Test_Y/delete", headers=admin_h)
|
||||
assert ans["OK"] is True
|
||||
|
||||
|
||||
def test_modif_users_depts(api_admin_headers):
|
||||
"""
|
||||
Ce test vise à vérifier qu'un admin déclaré sur deux départements peut
|
||||
bien modifier les utilisateurs de ses départements mais pas ceux des autres.
|
||||
"""
|
||||
admin_h = api_admin_headers
|
||||
depts = GET("/departements", headers=admin_h)
|
||||
assert len(depts) > 2
|
||||
dept1, dept2, dept3 = depts[:3]
|
||||
# On va utiliser les 3 1er dept (TAPI, AA, BB)
|
||||
# On crée un nouvel utilisateur "chef2", admin dans les 2 premiers dept
|
||||
# puis un utilisateur lambda, dans le dept 2 (AA)
|
||||
chef2 = POST_JSON(
|
||||
"/user/create",
|
||||
{
|
||||
"user_name": "chef2",
|
||||
"nom": "Chef",
|
||||
"prenom": "Test",
|
||||
"dept": dept1["acronym"], # rattaché à dept1
|
||||
},
|
||||
headers=admin_h,
|
||||
)
|
||||
role_chef = POST_JSON(
|
||||
"/role/create/chef",
|
||||
{"permissions": ["ScoView", "ScoUsersAdmin", "ScoUsersView"]},
|
||||
headers=admin_h,
|
||||
)
|
||||
_ = POST_JSON(
|
||||
f"/user/{chef2['id']}/role/chef/add/departement/{dept1['acronym']}",
|
||||
headers=admin_h,
|
||||
)
|
||||
_ = POST_JSON(
|
||||
f"/user/{chef2['id']}/role/chef/add/departement/{dept2['acronym']}",
|
||||
headers=admin_h,
|
||||
)
|
||||
# Un mot de passe trop simple:
|
||||
ok = False
|
||||
try:
|
||||
_ = POST_JSON(
|
||||
f"/user/{chef2['id']}/password",
|
||||
{"password": "123456"},
|
||||
headers=admin_h,
|
||||
)
|
||||
except APIError as exc:
|
||||
if exc.args[1]["status"] == 400:
|
||||
ok = True
|
||||
assert ok
|
||||
# Un "vrai" mot de passe:
|
||||
chef2_password = "17HIOPpYhabb8qw'E:/jd7FFddjd"
|
||||
_ = POST_JSON(
|
||||
f"/user/{chef2['id']}/password",
|
||||
{"password": chef2_password},
|
||||
headers=admin_h,
|
||||
)
|
||||
# Création user lambda:
|
||||
u_lambda = POST_JSON(
|
||||
"/user/create",
|
||||
{
|
||||
"user_name": "lambda",
|
||||
"nom": "Lambda",
|
||||
"prenom": "Test",
|
||||
"dept": dept2["acronym"],
|
||||
},
|
||||
headers=admin_h,
|
||||
)
|
||||
|
||||
# Le chef va modifier u_lambda:
|
||||
chef_h = get_auth_headers(chef2["user_name"], chef2_password)
|
||||
# on utilise une URL avec département car on n'a pas le droit sur tous:
|
||||
u = POST_JSON(
|
||||
f"/user/{u_lambda['id']}/edit",
|
||||
{"nom": "toto"},
|
||||
headers=chef_h,
|
||||
dept=dept1["acronym"],
|
||||
)
|
||||
assert u["nom"] == "toto"
|
||||
# Dans l'autre ?
|
||||
u = POST_JSON(
|
||||
f"/user/{u_lambda['id']}/edit",
|
||||
{"nom": "toto"},
|
||||
headers=chef_h,
|
||||
dept=dept2["acronym"],
|
||||
)
|
||||
# mais pas dans le troisième:
|
||||
ok = False
|
||||
try:
|
||||
u = POST_JSON(
|
||||
f"/user/{u_lambda['id']}/edit",
|
||||
{"nom": "toto"},
|
||||
headers=chef_h,
|
||||
dept=dept3["acronym"],
|
||||
)
|
||||
except APIError as exc:
|
||||
if exc.args[1]["status"] == 401:
|
||||
ok = True
|
||||
assert ok
|
||||
# Nettoyage:
|
||||
|
Loading…
Reference in New Issue
Block a user