Compare commits
5 commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3644c47843 | |||
| b60149d3ec | |||
| 567ddbd41c | |||
| 122d0e7af6 | |||
|
|
06fae502df |
126 changed files with 16 additions and 4941 deletions
30
.github/workflows/docker-image.yml
vendored
30
.github/workflows/docker-image.yml
vendored
|
|
@ -1,30 +0,0 @@
|
|||
name: Push-Development
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Push Development
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
- name: Run tests
|
||||
run: docker-compose run test
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USER }}
|
||||
password: ${{ secrets.DOCKER_PASS }}
|
||||
- name: Build and push
|
||||
id: docker_build
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
push: true
|
||||
tags: user/app:latest
|
||||
16
README.md
Normal file
16
README.md
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
# Projet Sécurité INFO5A 2022
|
||||
|
||||
**Auteurs**:
|
||||
- Baptiste Peupier
|
||||
- Wilfried Vallée
|
||||
- Mihary Ranaivoson
|
||||
- Yûki Vachot
|
||||
|
||||
**Branches**:
|
||||
- db1: Base de données Utilisateur
|
||||
- db2: Base de données Log
|
||||
- backend: Flask Backend
|
||||
- frontend: Serveur Angular avec un autre serveur Flask Backend communiquant avec la "branche" backend
|
||||
- development: non mis à jour ne pas cloner
|
||||
|
||||
docker compose up pour chaque branche
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
FROM python:latest
|
||||
WORKDIR /data/backend
|
||||
COPY requirements.txt requirements.txt
|
||||
RUN pip install --upgrade pip
|
||||
RUN pip install -r requirements.txt
|
||||
COPY . .
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,8 +0,0 @@
|
|||
from application import create_app
|
||||
import os
|
||||
|
||||
app = create_app(os.environ.get('FLASK_ENV', None))
|
||||
|
||||
if __name__ == "__main__":
|
||||
PORT = os.environ.get('PORT', 33507)
|
||||
app.run(host='0.0.0.0', port=PORT, DEBUG=True)
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
from flask import Flask
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
from flask_cors import CORS
|
||||
import sys
|
||||
|
||||
db = SQLAlchemy()
|
||||
|
||||
|
||||
def create_app(flask_env='development'):
|
||||
app = Flask(__name__, instance_relative_config=False)
|
||||
origin = app.config.get('ALLOW_ORIGIN')
|
||||
if origin is None:
|
||||
origin = ['http://127.0.0.1:4200', 'http://localhost:4200']
|
||||
CORS(app, supports_credentials=True, origins=origin)
|
||||
if flask_env == 'production':
|
||||
app.config.from_object("config.ProductionConfig")
|
||||
elif flask_env == 'testing':
|
||||
app.config.from_object("config.TestingConfig")
|
||||
elif flask_env == 'development':
|
||||
app.config.from_object("config.DevelopmentConfig")
|
||||
else:
|
||||
app.config.from_object("config.Config")
|
||||
|
||||
if app.config['SQLALCHEMY_DATABASE_URI_1'] is None or app.config['SQLALCHEMY_DATABASE_URI_2'] is None:
|
||||
print('No ENV Variable for DATABASE_URL_USERS or DATABASE_URL_LOGS')
|
||||
sys.exit(1)
|
||||
else:
|
||||
print('ENV Variables passed : ', app.config['SQLALCHEMY_BINDS'])
|
||||
|
||||
db.init_app(app)
|
||||
with app.app_context():
|
||||
from . import routes
|
||||
app.register_blueprint(routes.bp)
|
||||
db.create_all()
|
||||
return app
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,364 +0,0 @@
|
|||
import hashlib
|
||||
import os
|
||||
from datetime import datetime
|
||||
from flask_sqlalchemy import inspect
|
||||
from sqlalchemy import asc, desc, or_
|
||||
from .users_model import Users, db
|
||||
from .logs_model import Logs
|
||||
|
||||
|
||||
def db_create_log(ip, action, message, has_succeeded, status_code, table=None, id_user=None):
|
||||
log = Logs(
|
||||
date=datetime.now().strftime('%Y-%m-%dT%H:%M:%S'),
|
||||
ip=ip,
|
||||
action=action,
|
||||
message=message,
|
||||
has_succeeded=has_succeeded,
|
||||
status_code=status_code,
|
||||
table=table,
|
||||
id_user=id_user
|
||||
)
|
||||
db.session.add(log)
|
||||
db.session.commit()
|
||||
return log.json()
|
||||
|
||||
|
||||
def hash_password(salt, password):
|
||||
return hashlib.pbkdf2_hmac('sha256', password.encode('utf-8'), salt, 100000)
|
||||
|
||||
|
||||
def db_login(ip, email, password):
|
||||
user = Users.query.filter(
|
||||
Users.email == email
|
||||
).scalar()
|
||||
|
||||
# Check User and Hash Pass
|
||||
if user and user.hash_pass == hash_password(user.salt, password):
|
||||
message = 'User authenticated.'
|
||||
db_create_log(
|
||||
ip=ip,
|
||||
action='login',
|
||||
message=message,
|
||||
has_succeeded=True,
|
||||
status_code=0,
|
||||
table='users',
|
||||
id_user=user.id
|
||||
)
|
||||
return {'status': 0, 'message': message, 'data': user.json()}
|
||||
else:
|
||||
message = f'Email or password invalid'
|
||||
db_create_log(
|
||||
ip=ip,
|
||||
action='login',
|
||||
message=message,
|
||||
has_succeeded=False,
|
||||
status_code=1,
|
||||
table='users',
|
||||
id_user=None
|
||||
)
|
||||
return {'status': 1, 'message': message} # Email or password invalid
|
||||
|
||||
|
||||
def db_register(ip, email, nickname, password, is_admin=False):
|
||||
user = Users.query.filter(
|
||||
Users.email == email
|
||||
).scalar()
|
||||
if user:
|
||||
message = f'{email} already exist.'
|
||||
db_create_log(
|
||||
ip=ip,
|
||||
action='register',
|
||||
message=message,
|
||||
has_succeeded=False,
|
||||
status_code=1,
|
||||
table='users',
|
||||
id_user=None
|
||||
)
|
||||
return {'status': 1, 'message': message} # User already exist
|
||||
|
||||
# Salt Hash Pass with SHA256
|
||||
salt = os.urandom(32)
|
||||
hash_pass = hash_password(salt, password)
|
||||
|
||||
user = Users(
|
||||
email=email,
|
||||
hash_pass=hash_pass,
|
||||
nickname=nickname,
|
||||
salt=salt,
|
||||
is_admin=is_admin
|
||||
)
|
||||
user_inspect = inspect(user)
|
||||
db.session.add(user)
|
||||
check_inspect = user_inspect.pending
|
||||
db.session.commit()
|
||||
|
||||
# Add to logs
|
||||
if check_inspect:
|
||||
id_user = user.json()['id']
|
||||
message = 'User registered.'
|
||||
has_succeeded = True
|
||||
status_code = 0
|
||||
else:
|
||||
id_user = None
|
||||
message = 'Internal Error: User not registered.'
|
||||
has_succeeded = False
|
||||
status_code = 1
|
||||
|
||||
db_create_log(
|
||||
ip=ip,
|
||||
action='register',
|
||||
message=message,
|
||||
has_succeeded=has_succeeded,
|
||||
status_code=status_code,
|
||||
table='users',
|
||||
id_user=id_user
|
||||
)
|
||||
if status_code == 0:
|
||||
return {'status': 0, 'message': message, 'data': user.json()}
|
||||
elif status_code == 1:
|
||||
return {'status': 1, 'message': message}
|
||||
|
||||
|
||||
def db_user_update(ip, user_id, nickname, password):
|
||||
user = Users.query.filter(
|
||||
Users.id == user_id
|
||||
).scalar()
|
||||
if user:
|
||||
has_succeeded = False
|
||||
status_code = 2
|
||||
if nickname and password:
|
||||
# Salt Hash Pass with SHA256
|
||||
salt = os.urandom(32)
|
||||
hash_pass = hash_password(salt, password)
|
||||
Users.query.filter(Users.id == user_id).update({'nickname': nickname, 'hash_pass': hash_pass, 'salt': salt})
|
||||
db.session.commit()
|
||||
message = 'User nickname and password updated.'
|
||||
has_succeeded = True
|
||||
status_code = 0
|
||||
elif nickname:
|
||||
Users.query.filter(Users.id == user_id).update({'nickname': nickname})
|
||||
db.session.commit()
|
||||
message = 'User nickname updated.'
|
||||
has_succeeded = True
|
||||
status_code = 0
|
||||
elif password:
|
||||
# Salt Hash Pass with SHA256
|
||||
salt = os.urandom(32)
|
||||
hash_pass = hash_password(salt, password)
|
||||
Users.query.filter(Users.id == user_id).update({'hash_pass': hash_pass, 'salt': salt})
|
||||
db.session.commit()
|
||||
message = 'User password updated.'
|
||||
has_succeeded = True
|
||||
status_code = 0
|
||||
else:
|
||||
message = 'Only nickname and/or password can be changed.'
|
||||
|
||||
db_create_log(
|
||||
ip=ip,
|
||||
action='user_update',
|
||||
message=message,
|
||||
has_succeeded=has_succeeded,
|
||||
status_code=status_code,
|
||||
table='users',
|
||||
id_user=user_id
|
||||
)
|
||||
return {'status': status_code, 'message': message, 'data': user.json()}
|
||||
else:
|
||||
message = 'User do not exist.'
|
||||
db_create_log(
|
||||
ip=ip,
|
||||
action='user_update',
|
||||
message=message,
|
||||
has_succeeded=False,
|
||||
status_code=1,
|
||||
table='users',
|
||||
id_user=user_id
|
||||
)
|
||||
return {'status': 1, 'message': message}
|
||||
|
||||
|
||||
def db_user_delete(ip, user_id):
|
||||
user_to_delete = Users.query.filter(Users.id == user_id).scalar()
|
||||
if user_to_delete:
|
||||
is_admin = bool(user_to_delete.json()['is_admin'])
|
||||
if is_admin and (Users.query.filter(Users.is_admin == True).count() <= 1 or user_id == 0):
|
||||
message = 'Can\'t delete last admin'
|
||||
db_create_log(
|
||||
ip=ip,
|
||||
action='user_delete',
|
||||
message=message,
|
||||
has_succeeded=False,
|
||||
status_code=2,
|
||||
table='users',
|
||||
id_user=user_id
|
||||
)
|
||||
return {'status': 2, 'message': message}
|
||||
else:
|
||||
test = Users.query.filter(Users.id == user_id).delete()
|
||||
if test == 1:
|
||||
db.session.commit()
|
||||
message = 'User deleted.'
|
||||
db_create_log(
|
||||
ip=ip,
|
||||
action='user_delete',
|
||||
message=message,
|
||||
has_succeeded=True,
|
||||
status_code=0,
|
||||
table='users',
|
||||
id_user=user_id
|
||||
)
|
||||
return {'status': 0, 'message': message, 'data': None}
|
||||
else:
|
||||
message = 'User do not exist.'
|
||||
db_create_log(
|
||||
ip=ip,
|
||||
action='user_delete',
|
||||
message=message,
|
||||
has_succeeded=False,
|
||||
status_code=1,
|
||||
table='users',
|
||||
id_user=user_id
|
||||
)
|
||||
return {'status': 1, 'message': message}
|
||||
else:
|
||||
message = 'User do not exist.'
|
||||
db_create_log(
|
||||
ip=ip,
|
||||
action='user_delete',
|
||||
message=message,
|
||||
has_succeeded=False,
|
||||
status_code=1,
|
||||
table='users',
|
||||
id_user=user_id
|
||||
)
|
||||
return {'status': 1, 'message': message}
|
||||
|
||||
|
||||
def db_admin_update_user(ip, user_id, is_admin, password):
|
||||
user = Users.query.filter(
|
||||
Users.id == user_id
|
||||
).scalar()
|
||||
if user:
|
||||
has_succeeded = False
|
||||
status_code = 2
|
||||
if is_admin is not None and password:
|
||||
# Salt Hash Pass with SHA256
|
||||
salt = os.urandom(32)
|
||||
hash_pass = hash_password(salt, password)
|
||||
Users.query.filter(Users.id == user_id).update({'is_admin': is_admin, 'hash_pass': hash_pass, 'salt': salt})
|
||||
db.session.commit()
|
||||
message = 'User is_admin and password updated.'
|
||||
has_succeeded = True
|
||||
status_code = 0
|
||||
elif is_admin is not None:
|
||||
Users.query.filter(Users.id == user_id).update({'is_admin': is_admin})
|
||||
db.session.commit()
|
||||
message = 'User is_admin updated.'
|
||||
has_succeeded = True
|
||||
status_code = 0
|
||||
elif password:
|
||||
# Salt Hash Pass with SHA256
|
||||
salt = os.urandom(32)
|
||||
hash_pass = hash_password(salt, password)
|
||||
Users.query.filter(Users.id == user_id).update({'hash_pass': hash_pass, 'salt': salt})
|
||||
db.session.commit()
|
||||
message = 'User password updated.'
|
||||
has_succeeded = True
|
||||
status_code = 0
|
||||
else:
|
||||
message = 'Only is_admin and/or password can be changed.'
|
||||
|
||||
db_create_log(
|
||||
ip=ip,
|
||||
action='user_update',
|
||||
message=message,
|
||||
has_succeeded=has_succeeded,
|
||||
status_code=status_code,
|
||||
table='users',
|
||||
id_user=user_id
|
||||
)
|
||||
return {'status': status_code, 'message': message, 'data': user.json()}
|
||||
else:
|
||||
message = 'User do not exist.'
|
||||
db_create_log(
|
||||
ip=ip,
|
||||
action='user_update',
|
||||
message=message,
|
||||
has_succeeded=False,
|
||||
status_code=1,
|
||||
table='users',
|
||||
id_user=user_id
|
||||
)
|
||||
return {'status': 1, 'message': message}
|
||||
|
||||
|
||||
def db_users(ip, user_id, query, by='email,nickname', id=None, is_admin=None, order_by='email,asc'):
|
||||
# q= or id =
|
||||
# if q= then by= (default: email,nickname) or email or nickname
|
||||
# is_admin =
|
||||
# order_by = (default: email,asc), (nickname,asc), (id,desc), (is_admin,desc)
|
||||
|
||||
users = Users.query
|
||||
if query is id and query is not None:
|
||||
message = 'Query or id field'
|
||||
db_create_log(
|
||||
ip=ip,
|
||||
action='users',
|
||||
message=message,
|
||||
has_succeeded=False,
|
||||
status_code=1,
|
||||
table='users',
|
||||
id_user=user_id
|
||||
)
|
||||
return {'status': 1, 'message': message}
|
||||
|
||||
if query and by:
|
||||
if by == 'email':
|
||||
users = users.filter(Users.email.like('%' + query + '%'))
|
||||
elif by == 'nickname':
|
||||
users = users.filter(Users.nickname.like('%' + query + '%'))
|
||||
else:
|
||||
users = users.filter(or_(Users.nickname.like('%' + query + '%'), Users.email.like('%' + query + '%')))
|
||||
elif query and not by:
|
||||
users = users.filter(or_(Users.nickname.like('%' + query + '%'), Users.email.like('%' + query + '%')))
|
||||
elif id:
|
||||
users = users.filter(Users.id == id)
|
||||
else:
|
||||
pass
|
||||
|
||||
if is_admin is not None:
|
||||
users = users.filter(Users.is_admin == is_admin)
|
||||
|
||||
order_by = order_by.split(',')
|
||||
if order_by[0] == 'nickname':
|
||||
order = Users.nickname
|
||||
elif order_by[0] == 'id':
|
||||
order = Users.id
|
||||
elif order_by[0] == 'is_admin':
|
||||
order = Users.is_admin
|
||||
else:
|
||||
order = Users.email
|
||||
|
||||
if len(order_by) > 1:
|
||||
if order_by[1] == 'asc':
|
||||
users = users.order_by(asc(order))
|
||||
elif order_by[1] == 'desc':
|
||||
users = users.order_by(desc(order))
|
||||
else:
|
||||
users = users.order_by(asc(order))
|
||||
else:
|
||||
users = users.order_by(asc(order))
|
||||
|
||||
users = users.all()
|
||||
|
||||
message = f'query({query}), by({by}), id({id}), is_admin({is_admin}) and order_by({order_by}): {len(users)} result(s)'
|
||||
db_create_log(
|
||||
ip=ip,
|
||||
action='users',
|
||||
message=message,
|
||||
has_succeeded=True,
|
||||
status_code=0,
|
||||
table='users',
|
||||
id_user=user_id
|
||||
)
|
||||
return {'status': 0, 'message': message, 'data': [user.json() for user in users]}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
from . import db
|
||||
|
||||
|
||||
class Logs(db.Model):
|
||||
__bind_key__ = 'db-logs'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
date = db.Column(db.TIMESTAMP(), nullable=False)
|
||||
id_user = db.Column(db.Integer, nullable=True)
|
||||
ip = db.Column(db.String(), nullable=False)
|
||||
table = db.Column(db.String(), nullable=False)
|
||||
action = db.Column(db.String(), nullable=False)
|
||||
message = db.Column(db.String(), nullable=False)
|
||||
has_succeeded = db.Column(db.Boolean, nullable=False)
|
||||
status_code = db.Column(db.Integer, nullable=False)
|
||||
|
||||
def __init__(self, date, id_user, ip, table, action, message, has_succeeded, status_code):
|
||||
self.date = date
|
||||
self.id_user = id_user
|
||||
self.ip = ip
|
||||
self.table = table
|
||||
self.action = action
|
||||
self.message = message
|
||||
self.has_succeeded = has_succeeded
|
||||
self.status_code = status_code
|
||||
|
||||
def __repr__(self):
|
||||
return {
|
||||
'id': self.id,
|
||||
'date': self.date,
|
||||
'id_user': self.id_user,
|
||||
'ip': self.ip,
|
||||
'table': self.table,
|
||||
'action': self.action,
|
||||
'message': self.message,
|
||||
'has_succeeded': self.has_succeeded,
|
||||
'status_code': self.status_code
|
||||
}
|
||||
|
||||
def json(self):
|
||||
return self.__repr__()
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
from flask import current_app as app
|
||||
import json
|
||||
|
||||
|
||||
def send_error(status_code, message, token=None):
|
||||
data_json = {
|
||||
'status': 'error',
|
||||
'message': message
|
||||
}
|
||||
res = app.response_class(
|
||||
response=json.dumps(data_json),
|
||||
status=status_code,
|
||||
mimetype='application/json'
|
||||
)
|
||||
if token is not None:
|
||||
res.set_cookie('SESSIONID', token)
|
||||
return res
|
||||
|
||||
|
||||
def send_message(message, data, token=None, token_delete=False):
|
||||
data_json = {
|
||||
'status': 'success',
|
||||
'message': message,
|
||||
'data': data
|
||||
}
|
||||
res = app.response_class(
|
||||
response=json.dumps(data_json),
|
||||
status=200,
|
||||
mimetype='application/json'
|
||||
)
|
||||
if token is not None:
|
||||
res.set_cookie('SESSIONID', token)
|
||||
if token_delete:
|
||||
res.delete_cookie('SESSIONID')
|
||||
return res
|
||||
|
|
@ -1,345 +0,0 @@
|
|||
from flask import request, Blueprint
|
||||
from werkzeug.exceptions import HTTPException
|
||||
from .responses import send_message, send_error
|
||||
from .api_functions import db_login, db_register, db_user_update, db_create_log, db_user_delete, db_admin_update_user, db_users
|
||||
from .sessionJWT import create_auth_token, check_auth_token
|
||||
|
||||
bp = Blueprint('myapp', __name__)
|
||||
|
||||
|
||||
@bp.app_errorhandler(HTTPException)
|
||||
def handle_exception(e):
|
||||
return send_error(e.code, e.name)
|
||||
|
||||
|
||||
# Login
|
||||
@bp.route('/api/login', methods=['POST'])
|
||||
def login():
|
||||
post_json = request.json
|
||||
try:
|
||||
post_email = str(post_json['email'])
|
||||
post_password = str(post_json['password'])
|
||||
if post_email != '' and post_password != '':
|
||||
ip = request.remote_addr
|
||||
res = db_login(ip, post_email, post_password)
|
||||
if res['status'] == 0:
|
||||
user = res['data']
|
||||
token = create_auth_token(user)
|
||||
return send_message(res['message'], user, token)
|
||||
elif res['status'] == 1:
|
||||
user = None
|
||||
token = create_auth_token(user)
|
||||
return send_error(400, res['message'], token)
|
||||
else:
|
||||
return send_error(400, 'Empty email and/or password fields.')
|
||||
except KeyError as e:
|
||||
return send_error(400, 'Need email, password fields.')
|
||||
|
||||
|
||||
# Register
|
||||
@bp.route('/api/register', methods=['POST'])
|
||||
def register():
|
||||
post_json = request.json
|
||||
try:
|
||||
post_email = str(post_json['email'])
|
||||
post_nickname = str(post_json['nickname'])
|
||||
post_password = str(post_json['password'])
|
||||
if post_email != '' and post_password != '' and post_nickname != '':
|
||||
ip = request.remote_addr
|
||||
res = db_register(ip, post_email, post_nickname, post_password)
|
||||
if res['status'] == 1:
|
||||
return send_error(500, res['message'])
|
||||
elif res['status'] == 0:
|
||||
return send_message(res['message'], res['data'])
|
||||
else:
|
||||
return send_error(400, 'Empty email and/or password and/or nickname fields.')
|
||||
except KeyError as e:
|
||||
return send_error(400, 'Need ' + str(e) + 'field.')
|
||||
|
||||
|
||||
# Logout
|
||||
@bp.route('/api/logout', methods=['DELETE'])
|
||||
def logout():
|
||||
token = check_auth_token(request)
|
||||
if token['success']:
|
||||
ip = request.remote_addr
|
||||
message = 'User disconnected.'
|
||||
db_create_log(
|
||||
ip=ip,
|
||||
action='logout',
|
||||
message=message,
|
||||
has_succeeded=True,
|
||||
status_code=0,
|
||||
table='users',
|
||||
id_user=token['payload']['id']
|
||||
)
|
||||
return send_message(message, None, token_delete=True)
|
||||
else:
|
||||
return send_error(500, token['message'])
|
||||
|
||||
|
||||
# Update User (Nickname, Password)
|
||||
@bp.route('/api/user/update', methods=['PUT'])
|
||||
def user_update():
|
||||
token = check_auth_token(request)
|
||||
if token['success']:
|
||||
post_json = request.json
|
||||
post_nickname = None
|
||||
post_password = None
|
||||
fields = ''
|
||||
if 'nickname' in post_json:
|
||||
post_nickname = str(post_json['nickname'])
|
||||
else:
|
||||
fields += 'nickname '
|
||||
|
||||
if 'password' in post_json:
|
||||
post_password = str(post_json['password'])
|
||||
else:
|
||||
fields += 'password '
|
||||
|
||||
if post_nickname is not None or post_password is not None:
|
||||
if post_nickname != '' and post_password != '':
|
||||
ip = request.remote_addr
|
||||
user_id = token['payload']['id']
|
||||
res = db_user_update(ip, user_id, post_nickname, post_password)
|
||||
if res['status'] == 1:
|
||||
return send_error(500, res['message'])
|
||||
elif res['status'] == 0:
|
||||
return send_message(res['message'], res['data'])
|
||||
else:
|
||||
return send_error(400, 'Empty nickname and/or password fields.')
|
||||
else:
|
||||
return send_error(400, 'Need ' + fields + 'field.')
|
||||
else:
|
||||
return send_error(500, token['message'])
|
||||
|
||||
|
||||
# Delete User
|
||||
@bp.route('/api/user/delete', methods=['DELETE'])
|
||||
def user_delete():
|
||||
token = check_auth_token(request)
|
||||
if token['success']:
|
||||
ip = request.remote_addr
|
||||
user_id = token['payload']['id']
|
||||
res = db_user_delete(ip, user_id)
|
||||
if res['status'] != 0:
|
||||
return send_error(500, res['message'])
|
||||
else:
|
||||
db_create_log(
|
||||
ip=ip,
|
||||
action='delete',
|
||||
message='User deleted.',
|
||||
has_succeeded=True,
|
||||
status_code=0,
|
||||
table='users',
|
||||
id_user=token['payload']['id']
|
||||
)
|
||||
return send_message(res['message'], None, token_delete=True)
|
||||
else:
|
||||
return send_error(500, token['message'])
|
||||
|
||||
|
||||
# Admin : Create User
|
||||
@bp.route('/api/admin/create/user', methods=['POST'])
|
||||
def admin_create_user():
|
||||
token = check_auth_token(request)
|
||||
if token['success']:
|
||||
ip = request.remote_addr
|
||||
user_id = token['payload']['id']
|
||||
is_admin = token['payload']['is_admin']
|
||||
if is_admin:
|
||||
post_json = request.json
|
||||
post_email = None
|
||||
post_nickname = None
|
||||
post_password = None
|
||||
post_is_admin = None
|
||||
fields = ''
|
||||
if 'email' in post_json:
|
||||
post_email = str(post_json['email'])
|
||||
else:
|
||||
fields += 'email '
|
||||
|
||||
if 'nickname' in post_json:
|
||||
post_nickname = str(post_json['nickname'])
|
||||
else:
|
||||
fields += 'nickname '
|
||||
|
||||
if 'password' in post_json:
|
||||
post_password = str(post_json['password'])
|
||||
else:
|
||||
fields += 'password '
|
||||
|
||||
if 'is_admin' in post_json:
|
||||
post_is_admin = bool(post_json['is_admin'])
|
||||
else:
|
||||
fields += 'is_admin '
|
||||
|
||||
if post_email is not None or post_nickname is not None or post_password is not None or post_is_admin is not None:
|
||||
if post_email != '' and post_nickname != '' and post_password != '' and str(post_is_admin) != '':
|
||||
res = db_register(ip, post_email, post_nickname, post_password, is_admin=post_is_admin)
|
||||
if res['status'] == 1:
|
||||
db_create_log(
|
||||
ip=ip,
|
||||
action='admin/create/user',
|
||||
message=res['message'],
|
||||
has_succeeded=False,
|
||||
status_code=res['status'],
|
||||
table='users',
|
||||
id_user=user_id
|
||||
)
|
||||
return send_error(500, res['message'])
|
||||
elif res['status'] == 0:
|
||||
db_create_log(
|
||||
ip=ip,
|
||||
action='admin/create/user',
|
||||
message=res['message'],
|
||||
has_succeeded=True,
|
||||
status_code=res['status'],
|
||||
table='users',
|
||||
id_user=user_id
|
||||
)
|
||||
return send_message(res['message'], res['data'])
|
||||
else:
|
||||
return send_error(400, 'Empty email and/or nickname and/or password and/or is_admin fields.')
|
||||
else:
|
||||
return send_error(400, 'Need ' + fields + 'field.')
|
||||
else:
|
||||
return send_error(500, 'User does not have permission.')
|
||||
else:
|
||||
return send_error(500, token['message'])
|
||||
|
||||
|
||||
# Admin : Change User password and/or role
|
||||
@bp.route('/api/admin/update/user', methods=['PUT'])
|
||||
def admin_update_user():
|
||||
token = check_auth_token(request)
|
||||
if token['success']:
|
||||
user_id = token['payload']['id']
|
||||
is_admin = token['payload']['is_admin']
|
||||
if is_admin:
|
||||
post_json = request.json
|
||||
post_is_admin = None
|
||||
post_password = None
|
||||
post_user_id_delete = None
|
||||
fields = ''
|
||||
if 'id' in post_json:
|
||||
post_user_id_delete = int(post_json['id'])
|
||||
else:
|
||||
fields += 'id '
|
||||
|
||||
if 'is_admin' in post_json:
|
||||
post_is_admin = bool(post_json['is_admin'])
|
||||
else:
|
||||
fields += 'is_admin '
|
||||
|
||||
if 'password' in post_json:
|
||||
post_password = str(post_json['password'])
|
||||
else:
|
||||
fields += 'password '
|
||||
|
||||
if post_user_id_delete is not None and (post_is_admin is not None or post_password is not None):
|
||||
if str(post_is_admin) != '' and post_password != '' and str(post_user_id_delete) != '':
|
||||
ip = request.remote_addr
|
||||
res = db_admin_update_user(ip, post_user_id_delete, post_is_admin, post_password)
|
||||
if res['status'] == 1:
|
||||
db_create_log(
|
||||
ip=ip,
|
||||
action='admin/update/user',
|
||||
message=res['message'],
|
||||
has_succeeded=False,
|
||||
status_code=res['status'],
|
||||
table='users',
|
||||
id_user=user_id
|
||||
)
|
||||
return send_error(500, res['message'])
|
||||
elif res['status'] == 0:
|
||||
db_create_log(
|
||||
ip=ip,
|
||||
action='admin/update/user',
|
||||
message=res['message'],
|
||||
has_succeeded=True,
|
||||
status_code=res['status'],
|
||||
table='users',
|
||||
id_user=user_id
|
||||
)
|
||||
return send_message(res['message'], res['data'])
|
||||
else:
|
||||
return send_error(400, 'Empty is_admin and/or password fields.')
|
||||
else:
|
||||
return send_error(400, 'Need ' + fields + 'field.')
|
||||
else:
|
||||
return send_error(500, 'User does not have permission.')
|
||||
else:
|
||||
return send_error(500, token['message'])
|
||||
|
||||
|
||||
# Admin : Delete User
|
||||
@bp.route('/api/admin/delete/user/<id>', methods=['DELETE'])
|
||||
def admin_delete_user(id):
|
||||
token = check_auth_token(request)
|
||||
if token['success']:
|
||||
ip = request.remote_addr
|
||||
user_id = token['payload']['id']
|
||||
is_admin = token['payload']['is_admin']
|
||||
if is_admin:
|
||||
post_json = {'id': id}
|
||||
post_user_id_delete = None
|
||||
fields = ''
|
||||
if 'id' in post_json:
|
||||
post_user_id_delete = int(post_json['id'])
|
||||
else:
|
||||
fields += 'id'
|
||||
if post_user_id_delete is not None:
|
||||
if str(post_user_id_delete) != '':
|
||||
res = db_user_delete(ip, int(post_user_id_delete))
|
||||
if res['status'] == 1:
|
||||
db_create_log(
|
||||
ip=ip,
|
||||
action='admin/delete/user',
|
||||
message=res['message'],
|
||||
has_succeeded=False,
|
||||
status_code=res['status'],
|
||||
table='users',
|
||||
id_user=user_id
|
||||
)
|
||||
return send_error(500, res['message'])
|
||||
else:
|
||||
db_create_log(
|
||||
ip=ip,
|
||||
action='admin/delete/user',
|
||||
message=res['message'],
|
||||
has_succeeded=True,
|
||||
status_code=res['status'],
|
||||
table='users',
|
||||
id_user=user_id
|
||||
)
|
||||
return send_message(res['message'], None)
|
||||
else:
|
||||
return send_error(400, 'Empty id field.')
|
||||
else:
|
||||
return send_error(400, 'Need ' + fields + 'field.')
|
||||
else:
|
||||
return send_error(500, 'User does not have permission.')
|
||||
else:
|
||||
return send_error(500, token['message'])
|
||||
|
||||
|
||||
# List of User (must be authenticated) & Search
|
||||
@bp.route('/api/users', methods=['GET'])
|
||||
def users():
|
||||
token = check_auth_token(request)
|
||||
if token['success']:
|
||||
ip = request.remote_addr
|
||||
user_id = token['payload']['id']
|
||||
get_query = request.args.get('q')
|
||||
get_by = request.args.get('by')
|
||||
get_id = request.args.get('id')
|
||||
get_is_admin = request.args.get('is_admin')
|
||||
get_order_by = request.args.get('order_by')
|
||||
res = db_users(ip, user_id, get_query, get_by, get_id, get_is_admin, get_order_by)
|
||||
if res['status'] == 1:
|
||||
return send_error(500, res['message'])
|
||||
else:
|
||||
return send_message(res['message'], res['data'])
|
||||
else:
|
||||
return send_error(500, token['message'])
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
from datetime import datetime, timedelta
|
||||
from flask import current_app as app
|
||||
import jwt
|
||||
|
||||
|
||||
def create_auth_token(user, time_second=1800):
|
||||
try:
|
||||
time = datetime.now()
|
||||
payload = {
|
||||
'exp': time + timedelta(days=0, seconds=time_second),
|
||||
'iat': time,
|
||||
'user': user
|
||||
}
|
||||
return jwt.encode(
|
||||
payload,
|
||||
app.config.get('SECRET_KEY'),
|
||||
algorithm='HS256'
|
||||
)
|
||||
except Exception as e:
|
||||
return e
|
||||
|
||||
|
||||
def decode_auth_token(auth_token):
|
||||
try:
|
||||
payload = jwt.decode(
|
||||
auth_token,
|
||||
app.config.get('SECRET_KEY'),
|
||||
algorithms='HS256'
|
||||
)
|
||||
return {'success': True, 'payload': payload['user']}
|
||||
except jwt.ExpiredSignatureError:
|
||||
return {'success': False, 'message': 'Signature expired . Please log in again.'}
|
||||
except jwt.InvalidTokenError as e:
|
||||
return {'success': False, 'message': 'User not authenticated.'}
|
||||
|
||||
|
||||
def check_auth_token(request):
|
||||
token = request.cookies.get('SESSIONID')
|
||||
return decode_auth_token(token)
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
from . import db
|
||||
|
||||
|
||||
class Users(db.Model):
|
||||
__bind_key__ = 'db-users'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
||||
email = db.Column(db.String(), nullable=False, unique=True)
|
||||
nickname = db.Column(db.String(), nullable=False)
|
||||
hash_pass = db.Column(db.LargeBinary(), nullable=False)
|
||||
salt = db.Column(db.LargeBinary(), nullable=False)
|
||||
is_admin = db.Column(db.Boolean, default=False, nullable=False)
|
||||
|
||||
def __init__(self, email, nickname, hash_pass, salt, is_admin):
|
||||
self.email = email
|
||||
self.hash_pass = hash_pass
|
||||
self.nickname = nickname
|
||||
self.salt = salt
|
||||
self.is_admin = is_admin
|
||||
|
||||
def __repr__(self):
|
||||
return {
|
||||
'id': self.id,
|
||||
'email': self.email,
|
||||
'nickname': self.nickname,
|
||||
'hash_pass': self.hash_pass,
|
||||
'salt': self.salt,
|
||||
'is_admin': self.is_admin
|
||||
}
|
||||
|
||||
def json(self):
|
||||
return {
|
||||
'id': self.id,
|
||||
'email': self.email,
|
||||
'nickname': self.nickname,
|
||||
'is_admin': self.is_admin
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
import os
|
||||
|
||||
basedir = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
|
||||
class Config(object):
|
||||
DEBUG = False
|
||||
TESTING = False
|
||||
CSRF_ENABLED = True
|
||||
|
||||
FLASK_APP = os.environ.get('FLASK_APP', None)
|
||||
FLASK_ENV = os.environ.get('FLASK_ENV', None)
|
||||
|
||||
SQLALCHEMY_ECHO = False
|
||||
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
||||
SQLALCHEMY_DATABASE_URI_1 = os.environ.get('DATABASE_URL_USERS', None)
|
||||
SQLALCHEMY_DATABASE_URI_2 = os.environ.get('DATABASE_URL_LOGS', None)
|
||||
SQLALCHEMY_BINDS = {
|
||||
'db-users': SQLALCHEMY_DATABASE_URI_1,
|
||||
'db-logs': SQLALCHEMY_DATABASE_URI_2
|
||||
}
|
||||
|
||||
SECRET_KEY = os.environ.get('SECRET_KEY', 'default_secret_key')
|
||||
ALLOW_ORIGIN = os.environ.get('ALLOW_ORIGIN', None)
|
||||
|
||||
|
||||
class ProductionConfig(Config):
|
||||
DEBUG = False
|
||||
SQLALCHEMY_ECHO = False
|
||||
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
||||
|
||||
|
||||
class TestingConfig(Config):
|
||||
TESTING = True
|
||||
SQLALCHEMY_ECHO = False
|
||||
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
||||
|
||||
|
||||
class DevelopmentConfig(Config):
|
||||
DEVELOPMENT = True
|
||||
DEBUG = True
|
||||
SQLALCHEMY_ECHO = True
|
||||
SQLALCHEMY_TRACK_MODIFICATIONS = True
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
export FLASK_APP=app.py
|
||||
export FLASK_ENV=development
|
||||
export FLASK_DEBUG=1
|
||||
export PYTHONUNBUFFERED=1
|
||||
export DATABASE_URL_USERS=postgresql://flaskaled1:aled1@localhost:5433/flaskaledDb1
|
||||
export DATABASE_URL_LOGS=postgresql://flaskaled2:aled2@localhost:5434/flaskaledDb2
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
import os
|
||||
from application.users_model import Users
|
||||
from application.api_functions import hash_password
|
||||
|
||||
TAB_USER_WITH_PASSWORD = [
|
||||
{
|
||||
"id": 1,
|
||||
"email": "riri@gmail.com",
|
||||
"nickname": "Riri",
|
||||
"password": "ririPass",
|
||||
"is_admin": False
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"email": "fifi@gmail.com",
|
||||
"nickname": "Fifi",
|
||||
"password": "fifiPass",
|
||||
"is_admin": False
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"email": "donald@gmail.com",
|
||||
"nickname": "Donald",
|
||||
"password": "donaldPass",
|
||||
"is_admin": False
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"email": "daisy@gmail.com",
|
||||
"nickname": "Daisy",
|
||||
"password": "daisyPass",
|
||||
"is_admin": True
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
# Convert user with passord (uwp) to user
|
||||
def uwp_to_user(uwp):
|
||||
salt0 = os.urandom(32)
|
||||
hash_pass0 = hash_password(salt0, uwp["password"])
|
||||
return Users(
|
||||
email=uwp["email"],
|
||||
nickname=uwp["nickname"],
|
||||
hash_pass=hash_pass0,
|
||||
salt=salt0,
|
||||
is_admin=uwp["is_admin"]
|
||||
)
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
-- Table: users
|
||||
|
||||
CREATE TABLE IF NOT EXISTS users
|
||||
(
|
||||
id serial PRIMARY KEY,
|
||||
email character varying(320) NOT NULL,
|
||||
nickname character varying(50) NOT NULL,
|
||||
hash_pass bytea NOT NULL,
|
||||
salt bytea NOT NULL,
|
||||
is_admin boolean NOT NULL DEFAULT FALSE
|
||||
);
|
||||
|
||||
INSERT INTO users VALUES(0,'admin@admin.admin','Admin',decode('e5ed79b503704ed20a1d250770db68182118de7fe0236db9bbfb0dd9684087d6', 'hex'),decode('7012f69f1ac7c23c5dca498c30fa94527b507cc9e40fab9bae284d1465a37724', 'hex'),TRUE);
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
-- Table: logs
|
||||
|
||||
CREATE TABLE IF NOT EXISTS logs
|
||||
(
|
||||
id serial PRIMARY KEY,
|
||||
date timestamp NOT NULL,
|
||||
id_user integer,
|
||||
ip character varying(15) NOT NULL,
|
||||
"table" character varying(25) NOT NULL,
|
||||
action character varying(50) NOT NULL,
|
||||
message character varying(512) NOT NULL,
|
||||
has_succeeded boolean NOT NULL,
|
||||
status_code smallint NOT NULL
|
||||
);
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
alembic==1.7.5
|
||||
Flask==2.0.2
|
||||
Flask-Migrate==3.1.0
|
||||
Flask-Script==2.0.6
|
||||
Flask-Testing==0.8.1
|
||||
Flask-SQLAlchemy==2.5.1
|
||||
Flask-WTF==0.15.1
|
||||
pipreqs==0.4.10
|
||||
PyJWT==2.3.0
|
||||
pytest==6.2.5
|
||||
SQLAlchemy==1.4.27
|
||||
psycopg2==2.9.2
|
||||
Flask-Cors==3.0.10
|
||||
542
backend/test.py
542
backend/test.py
|
|
@ -1,542 +0,0 @@
|
|||
import unittest
|
||||
from flask_testing import TestCase
|
||||
from fictive_users import TAB_USER_WITH_PASSWORD, uwp_to_user
|
||||
from application import db, create_app
|
||||
|
||||
|
||||
class BaseTestCase(TestCase):
|
||||
|
||||
def create_app(self):
|
||||
app = create_app('testing')
|
||||
return app
|
||||
|
||||
def setUp(self):
|
||||
db.drop_all()
|
||||
db.create_all()
|
||||
for uwp in TAB_USER_WITH_PASSWORD:
|
||||
db.session.add(uwp_to_user(uwp))
|
||||
db.session.commit()
|
||||
|
||||
def tearDown(self):
|
||||
db.session.remove()
|
||||
db.drop_all()
|
||||
|
||||
|
||||
class FlaskTestCase(BaseTestCase):
|
||||
|
||||
# -- UTILS ---
|
||||
|
||||
def login(self, email, password):
|
||||
data0 = {
|
||||
"email": email,
|
||||
"password": password
|
||||
}
|
||||
response = self.client.post('/api/login', json=data0)
|
||||
return response
|
||||
|
||||
# --- LOGIN ---
|
||||
|
||||
def test_login_NoFields_statusCode(self):
|
||||
response = self.client.post('/api/login', json={})
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
def test_login_NoFields_message(self):
|
||||
response = self.client.post('/api/login', json={})
|
||||
self.assertEqual(response.json['message'], 'Need email, password fields.')
|
||||
|
||||
def test_login_emptyFields_statusCode(self):
|
||||
data0 = {
|
||||
"email": "",
|
||||
"password": "blabla"
|
||||
}
|
||||
response = self.client.post('/api/login', json=data0)
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
def test_login_emptyFields_message(self):
|
||||
data0 = {
|
||||
"email": "",
|
||||
"password": "blabla"
|
||||
}
|
||||
response = self.client.post('/api/login', json=data0)
|
||||
self.assertEqual(response.json['message'], 'Empty email and/or password fields.')
|
||||
|
||||
def test_login_wrongFields_statusCode(self):
|
||||
data0 = {
|
||||
"email": "nimp@gmail.com",
|
||||
"password": "nimp"
|
||||
}
|
||||
response = self.client.post('/api/login', json=data0)
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
def test_login_wrongFields_message(self):
|
||||
data0 = {
|
||||
"email": "nimp@gmail.com",
|
||||
"password": "nimp"
|
||||
}
|
||||
response = self.client.post('/api/login', json=data0)
|
||||
self.assertEqual(response.json['message'], 'Email or password invalid')
|
||||
|
||||
def test_login_success_statusCode(self):
|
||||
data0 = {
|
||||
"email": "riri@gmail.com",
|
||||
"password": "ririPass"
|
||||
}
|
||||
response = self.client.post('/api/login', json=data0)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_login_success_message(self):
|
||||
data0 = {
|
||||
"email": "riri@gmail.com",
|
||||
"password": "ririPass"
|
||||
}
|
||||
response = self.client.post('/api/login', json=data0)
|
||||
self.assertEqual(response.json['message'], 'User authenticated.')
|
||||
|
||||
# --- REGISTER ---
|
||||
|
||||
def test_register_noFields_statusCode(self):
|
||||
response = self.client.post('/api/register', json={})
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
def test_register_noFields_message(self):
|
||||
response = self.client.post('/api/register', json={})
|
||||
self.assertIn('Need', response.json['message'])
|
||||
|
||||
def test_register_emptyFields_statusCode(self):
|
||||
data0 = {
|
||||
"email": "",
|
||||
"password": "blabla",
|
||||
"nickname": "blabla"
|
||||
}
|
||||
response = self.client.post('/api/register', json=data0)
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
def test_register_emptyFields_message(self):
|
||||
data0 = {
|
||||
"email": "",
|
||||
"password": "blabla",
|
||||
"nickname": "blabla"
|
||||
}
|
||||
response = self.client.post('/api/register', json=data0)
|
||||
self.assertEqual(response.json['message'], 'Empty email and/or password and/or nickname fields.')
|
||||
|
||||
def test_register_alreadyExist_statusCode(self):
|
||||
data0 = {
|
||||
"email": "riri@gmail.com",
|
||||
"password": "blabla",
|
||||
"nickname": "blabla"
|
||||
}
|
||||
response = self.client.post('/api/register', json=data0)
|
||||
self.assertEqual(response.status_code, 500)
|
||||
|
||||
def test_register_alreadyExist_statusCode(self):
|
||||
data0 = {
|
||||
"email": "riri@gmail.com",
|
||||
"password": "blabla",
|
||||
"nickname": "blabla"
|
||||
}
|
||||
response = self.client.post('/api/register', json=data0)
|
||||
self.assertIn('already exist', response.json['message'])
|
||||
|
||||
def test_register_success_statusCode(self):
|
||||
data0 = {
|
||||
"email": "loulou@gmail.com",
|
||||
"password": "loulouPass",
|
||||
"nickname": "Loulou"
|
||||
}
|
||||
response = self.client.post('/api/register', json=data0)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_register_success_message(self):
|
||||
data0 = {
|
||||
"email": "loulou@gmail.com",
|
||||
"password": "loulouPass",
|
||||
"nickname": "Loulou"
|
||||
}
|
||||
response = self.client.post('/api/register', json=data0)
|
||||
self.assertEqual(response.json['message'], 'User registered.')
|
||||
|
||||
# --- LOGOUT ---
|
||||
|
||||
def test_logout_fail_(self):
|
||||
response = self.client.delete('/api/logout')
|
||||
self.assertEqual(response.status_code, 500)
|
||||
|
||||
def test_logout_success(self):
|
||||
response = self.login("riri@gmail.com", "ririPass")
|
||||
self.assertEqual(response.status_code, 200)
|
||||
response = self.client.delete('/api/logout')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
# --- USER/UPDATE ---
|
||||
|
||||
def test_userUpdate_notConnected_statusCode(self):
|
||||
response = self.client.put('/api/user/update', json={})
|
||||
self.assertEqual(response.status_code, 500)
|
||||
|
||||
def test_userUpdate_notConnected_message(self):
|
||||
response = self.client.put('/api/user/update', json={})
|
||||
self.assertEqual(response.json['message'], 'User not authenticated.')
|
||||
|
||||
def test_userUpdate_noFields_statusCode(self):
|
||||
response = self.login("riri@gmail.com", "ririPass")
|
||||
self.assertEqual(response.status_code, 200)
|
||||
response = self.client.put('/api/user/update', json={})
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
def test_userUpdate_noFields_message(self):
|
||||
response = self.login("riri@gmail.com", "ririPass")
|
||||
self.assertEqual(response.status_code, 200)
|
||||
response = self.client.put('/api/user/update', json={})
|
||||
self.assertIn('Need', response.json['message'])
|
||||
|
||||
def test_userUpdate_emptyFields_statusCode(self):
|
||||
response = self.login("riri@gmail.com", "ririPass")
|
||||
self.assertEqual(response.status_code, 200)
|
||||
data0 = {
|
||||
"nickname": "",
|
||||
"password": "blabla"
|
||||
}
|
||||
response = self.client.put('/api/user/update', json=data0)
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
def test_userUpdate_emptyFields_message(self):
|
||||
response = self.login("riri@gmail.com", "ririPass")
|
||||
self.assertEqual(response.status_code, 200)
|
||||
data0 = {
|
||||
"nickname": "",
|
||||
"password": "blabla"
|
||||
}
|
||||
response = self.client.put('/api/user/update', json=data0)
|
||||
self.assertEqual(response.json['message'], 'Empty nickname and/or password fields.')
|
||||
|
||||
def test_self_update_success_statusCode(self):
|
||||
response = self.login("riri@gmail.com", "ririPass")
|
||||
self.assertEqual(response.status_code, 200)
|
||||
data0 = {
|
||||
"nickname": "Ririri",
|
||||
"password": "ririPass"
|
||||
}
|
||||
response = self.client.put('/api/user/update', json=data0)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
# --- USER/DELETE ---
|
||||
|
||||
def test_userDelete_notConnected_statusCode(self):
|
||||
response = self.client.delete('/api/user/delete')
|
||||
self.assertEqual(response.status_code, 500)
|
||||
|
||||
def test_userDelete_notConnected_message(self):
|
||||
response = self.client.delete('/api/user/delete')
|
||||
self.assertEqual(response.json['message'], 'User not authenticated.')
|
||||
|
||||
def test_userDelete_success_statusCode(self):
|
||||
response = self.login('riri@gmail.com', 'ririPass')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
response = self.client.delete('/api/user/delete')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_userDelete_success_message(self):
|
||||
response = self.login('riri@gmail.com', 'ririPass')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
response = self.client.delete('/api/user/delete')
|
||||
self.assertEqual(response.json['message'], 'User deleted.')
|
||||
|
||||
def test_userDelete_lastAdmin_statusCode(self):
|
||||
response = self.login('donald@gmail.com', 'donaldPass')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
response = self.client.delete('/api/user/delete')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
response = self.login('daisy@gmail.com', 'daisyPass')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
response = self.client.delete('/api/user/delete')
|
||||
self.assertEqual(response.status_code, 500)
|
||||
|
||||
def test_userDelete_lastAdmin_message(self):
|
||||
response = self.login('donald@gmail.com', 'donaldPass')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
response = self.client.delete('/api/user/delete')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
response = self.login('daisy@gmail.com', 'daisyPass')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
response = self.client.delete('/api/user/delete')
|
||||
self.assertEqual(response.json['message'], 'Can\'t delete last admin')
|
||||
|
||||
# --- ADMIN/CREATE/USER ---
|
||||
|
||||
def test_adminCreate_notConnected_statusCode(self):
|
||||
response = self.client.post('/api/admin/create/user', json={})
|
||||
self.assertEqual(response.status_code, 500)
|
||||
|
||||
def test_adminCreate_notConnected_message(self):
|
||||
response = self.client.post('/api/admin/create/user', json={})
|
||||
self.assertEqual(response.json['message'], 'User not authenticated.')
|
||||
|
||||
def test_adminCreate_noPermission_statusCode(self):
|
||||
response = self.login('riri@gmail.com', 'ririPass')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
response = self.client.post('/api/admin/create/user', json={})
|
||||
self.assertEqual(response.status_code, 500)
|
||||
|
||||
def test_adminCreate_noPermission_message(self):
|
||||
response = self.login('riri@gmail.com', 'ririPass')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
response = self.client.post('/api/admin/create/user', json={})
|
||||
self.assertEqual(response.json['message'], 'User does not have permission.')
|
||||
|
||||
def test_adminCreate_noFields_statusCode(self):
|
||||
response = self.login('daisy@gmail.com', 'daisyPass')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
response = self.client.post('/api/admin/create/user', json={})
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
def test_adminCreate_noFields_message(self):
|
||||
response = self.login('daisy@gmail.com', 'daisyPass')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
response = self.client.post('/api/admin/create/user', json={})
|
||||
self.assertIn('Need', response.json['message'])
|
||||
|
||||
def test_adminCreate_emptyFields_statusCode(self):
|
||||
response = self.login('daisy@gmail.com', 'daisyPass')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
data0 = {
|
||||
"email": "",
|
||||
"nickname": "Mickey",
|
||||
"password": "mickeyPass",
|
||||
"is_admin": True,
|
||||
}
|
||||
response = self.client.post('/api/admin/create/user', json=data0)
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
def test_adminCreate_emptyFields_message(self):
|
||||
response = self.login('daisy@gmail.com', 'daisyPass')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
data0 = {
|
||||
"email": "",
|
||||
"nickname": "Mickey",
|
||||
"password": "mickeyPass",
|
||||
"is_admin": True,
|
||||
}
|
||||
response = self.client.post('/api/admin/create/user', json=data0)
|
||||
self.assertEqual(response.json['message'],
|
||||
'Empty email and/or nickname and/or password and/or is_admin fields.')
|
||||
|
||||
def test_adminCreate_alreadyExist_statusCode(self):
|
||||
response = self.login('daisy@gmail.com', 'daisyPass')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
data0 = {
|
||||
"email": "riri@gmail.com",
|
||||
"passord": "blabla",
|
||||
"nickname": "blabla",
|
||||
}
|
||||
response = self.client.post('/api/admin/create/user', json=data0)
|
||||
self.assertEqual(response.status_code, 500)
|
||||
|
||||
def test_adminCreate_alreadyExist_message(self):
|
||||
response = self.login('daisy@gmail.com', 'daisyPass')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
data0 = {
|
||||
"email": "riri@gmail.com",
|
||||
"passord": "blabla",
|
||||
"nickname": "blabla",
|
||||
}
|
||||
response = self.client.post('/api/admin/create/user', json=data0)
|
||||
self.assertIn('already exist', response.json['message'])
|
||||
|
||||
def test_adminCreate_success_statusCode(self):
|
||||
response = self.login('daisy@gmail.com', 'daisyPass')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
data0 = {
|
||||
"email": "mickey@gmail.com",
|
||||
"nickname": "Mickey",
|
||||
"password": "mickeyPass",
|
||||
"is_admin": True,
|
||||
}
|
||||
response = self.client.post('/api/admin/create/user', json=data0)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_adminCreate_success_message(self):
|
||||
response = self.login('daisy@gmail.com', 'daisyPass')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
data0 = {
|
||||
"email": "mickey@gmail.com",
|
||||
"nickname": "Mickey",
|
||||
"password": "mickeyPass",
|
||||
"is_admin": True,
|
||||
}
|
||||
response = self.client.post('/api/admin/create/user', json=data0)
|
||||
self.assertEqual(response.json['message'], 'User registered.')
|
||||
|
||||
# --- ADMIN/UPDATE/USER ---
|
||||
|
||||
def test_adminUpdate_notConnected_statusCode(self):
|
||||
response = self.client.put('/api/admin/update/user', json={})
|
||||
self.assertEqual(response.status_code, 500)
|
||||
|
||||
def test_adminUpdate_notConnected_message(self):
|
||||
response = self.client.put('/api/admin/update/user', json={})
|
||||
self.assertEqual(response.json['message'], 'User not authenticated.')
|
||||
|
||||
def test_adminUpdate_noPermission_statusCode(self):
|
||||
response = self.login('riri@gmail.com', 'ririPass')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
response = self.client.put('/api/admin/update/user', json={})
|
||||
self.assertEqual(response.status_code, 500)
|
||||
|
||||
def test_adminUpdate_noPermission_message(self):
|
||||
response = self.login('riri@gmail.com', 'ririPass')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
response = self.client.put('/api/admin/update/user', json={})
|
||||
self.assertEqual(response.json['message'], 'User does not have permission.')
|
||||
|
||||
def test_adminUpdate_noFields_statusCode(self):
|
||||
response = self.login('daisy@gmail.com', 'daisyPass')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
response = self.client.put('/api/admin/update/user', json={})
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
def test_adminUpdate_noFields_message(self):
|
||||
response = self.login('daisy@gmail.com', 'daisyPass')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
response = self.client.put('/api/admin/update/user', json={})
|
||||
self.assertIn('Need', response.json['message'])
|
||||
|
||||
def test_adminUpdate_emptyFields_statusCode(self):
|
||||
response = self.login('daisy@gmail.com', 'daisyPass')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
data0 = {
|
||||
"id": 1,
|
||||
"password": "",
|
||||
"is_admin": False,
|
||||
}
|
||||
response = self.client.put('/api/admin/update/user', json=data0)
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
def test_adminUpdate_emptyFields_message(self):
|
||||
response = self.login('daisy@gmail.com', 'daisyPass')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
data0 = {
|
||||
"id": 1,
|
||||
"password": "",
|
||||
"is_admin": False,
|
||||
}
|
||||
response = self.client.put('/api/admin/update/user', json=data0)
|
||||
self.assertEqual(response.json['message'], 'Empty is_admin and/or password fields.')
|
||||
|
||||
def test_adminUpdate_notExists_statusCode(self):
|
||||
response = self.login('daisy@gmail.com', 'daisyPass')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
data0 = {
|
||||
"id": 99,
|
||||
"password": "blabla",
|
||||
"is_admin": False
|
||||
}
|
||||
response = self.client.put('/api/admin/update/user', json=data0)
|
||||
self.assertEqual(response.status_code, 500)
|
||||
|
||||
def test_adminUpdate_notExists_message(self):
|
||||
response = self.login('daisy@gmail.com', 'daisyPass')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
data0 = {
|
||||
"id": 99,
|
||||
"password": "blabla",
|
||||
"is_admin": False
|
||||
}
|
||||
response = self.client.put('/api/admin/update/user', json=data0)
|
||||
self.assertEqual(response.json['message'], 'User do not exist.')
|
||||
|
||||
def test_adminUpdate_success_message(self):
|
||||
response = self.login('daisy@gmail.com', 'daisyPass')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
data0 = {
|
||||
"id": 1,
|
||||
"password": "roroPass",
|
||||
"is_admin": False,
|
||||
}
|
||||
response = self.client.put('/api/admin/update/user', json=data0)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_adminUpdate_success_statusCode(self):
|
||||
response = self.login('daisy@gmail.com', 'daisyPass')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
data0 = {
|
||||
"id": 1,
|
||||
"password": "roroPass",
|
||||
"is_admin": False,
|
||||
}
|
||||
response = self.client.put('/api/admin/update/user', json=data0)
|
||||
self.assertIn("updated", response.json['message'])
|
||||
|
||||
# --- ADMIN/DELETE/USER ---
|
||||
|
||||
def test_adminDelete_notConnected_statusCode(self):
|
||||
response = self.client.delete('/api/admin/delete/user/1')
|
||||
self.assertEqual(response.status_code, 500)
|
||||
|
||||
def test_adminDelete_notConnected_message(self):
|
||||
response = self.client.delete('/api/admin/delete/user/1')
|
||||
self.assertEqual(response.json['message'], 'User not authenticated.')
|
||||
|
||||
def test_adminDelete_noPermission_statusCode(self):
|
||||
response = self.login('riri@gmail.com', 'ririPass')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
response = self.client.delete('/api/admin/delete/user/1')
|
||||
self.assertEqual(response.status_code, 500)
|
||||
|
||||
def test_adminDelete_noPermission_message(self):
|
||||
response = self.login('riri@gmail.com', 'ririPass')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
response = self.client.delete('/api/admin/delete/user/1')
|
||||
self.assertEqual(response.json['message'], 'User does not have permission.')
|
||||
|
||||
def test_adminDelete_noFields_statusCode(self):
|
||||
response = self.login('daisy@gmail.com', 'daisyPass')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
response = self.client.delete('/api/admin/delete/user/')
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
def test_adminDelete_no_fields(self):
|
||||
response = self.login('daisy@gmail.com', 'daisyPass')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
response = self.client.delete('/api/admin/delete/user')
|
||||
self.assertEqual('Not Found', response.json['message'])
|
||||
|
||||
def test_adminDelete_notExists_statusCode(self):
|
||||
response = self.login('daisy@gmail.com', 'daisyPass')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
response = self.client.delete('/api/admin/delete/user/99')
|
||||
self.assertEqual(response.status_code, 500)
|
||||
|
||||
def test_adminDelete_notExists_message(self):
|
||||
response = self.login('daisy@gmail.com', 'daisyPass')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
response = self.client.delete('/api/admin/delete/user/99')
|
||||
self.assertEqual(response.json['message'], 'User do not exist.')
|
||||
|
||||
def test_adminDelete_success_statusCode(self):
|
||||
response = self.login('daisy@gmail.com', 'daisyPass')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
response = self.client.delete('/api/admin/delete/user/2')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_adminDelete_success_message(self):
|
||||
response = self.login('daisy@gmail.com', 'daisyPass')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
response = self.client.delete('/api/admin/delete/user/2')
|
||||
self.assertEqual(response.json['message'], 'User deleted.')
|
||||
|
||||
# --- LIST OF USER ---
|
||||
|
||||
def test_listOfUsers_fail(self):
|
||||
response = self.client.get('/api/users')
|
||||
self.assertEqual(response.status_code, 500)
|
||||
|
||||
def test_listOfUsers_success(self):
|
||||
response = self.login('riri@gmail.com', 'ririPass')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
response = self.client.get('/api/users?order_by=nickname')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
version: '3.8'
|
||||
|
||||
services:
|
||||
flaskaled-srv1:
|
||||
image: postgres:latest
|
||||
container_name: flaskaled-srv1
|
||||
ports:
|
||||
- "5433:5432"
|
||||
volumes:
|
||||
- ./backend/init-db1.sql:/docker-entrypoint-initdb.d/init-db1.sql
|
||||
environment:
|
||||
- POSTGRES_HOST=flaskaled-srv1
|
||||
- POSTGRES_PORT=5432
|
||||
- POSTGRES_DB=flaskaledDb1
|
||||
- POSTGRES_USER=flaskaled1
|
||||
- POSTGRES_PASSWORD=aled1
|
||||
restart: unless-stopped
|
||||
|
||||
flaskaled-srv2:
|
||||
image: postgres:latest
|
||||
container_name: flaskaled-srv2
|
||||
ports:
|
||||
- "5434:5432"
|
||||
volumes:
|
||||
- ./backend/init-db2.sql:/docker-entrypoint-initdb.d/init-db2.sql
|
||||
environment:
|
||||
- POSTGRES_HOST=flaskaled-srv2
|
||||
- POSTGRES_PORT=5432
|
||||
- POSTGRES_DB=flaskaledDb2
|
||||
- POSTGRES_USER=flaskaled2
|
||||
- POSTGRES_PASSWORD=aled2
|
||||
restart: unless-stopped
|
||||
|
||||
backend:
|
||||
container_name: backend
|
||||
build: ./backend
|
||||
command: python -m flask run --host=0.0.0.0
|
||||
ports:
|
||||
- "5000:5000"
|
||||
volumes:
|
||||
- ./backend:/data/backend
|
||||
depends_on:
|
||||
- flaskaled-srv1
|
||||
- flaskaled-srv2
|
||||
links:
|
||||
- flaskaled-srv1
|
||||
- flaskaled-srv2
|
||||
environment:
|
||||
- FLASK_APP=app.py
|
||||
- FLASK_ENV=development
|
||||
- FLASK_DEBUG=1
|
||||
- PYTHONUNBUFFERED=1
|
||||
- DATABASE_URL_USERS=postgresql://flaskaled1:aled1@flaskaled-srv1/flaskaledDb1
|
||||
- DATABASE_URL_LOGS=postgresql://flaskaled2:aled2@flaskaled-srv2/flaskaledDb2
|
||||
- ALLOW_ORIGIN=frontend
|
||||
- SECRET_KEY=default_secret_key
|
||||
|
||||
frontend:
|
||||
container_name: frontend
|
||||
build: ./frontend
|
||||
command: npm start
|
||||
ports:
|
||||
- "4200:4200"
|
||||
volumes:
|
||||
- ./frontend:/data/frontend
|
||||
- ./frontend/node_modules:/data/frontend/node_modules
|
||||
depends_on:
|
||||
- backend
|
||||
links:
|
||||
- backend
|
||||
environment:
|
||||
- NODE_ENV=development
|
||||
|
||||
test:
|
||||
container_name: test
|
||||
build: ./backend
|
||||
command: python test.py
|
||||
volumes:
|
||||
- ./backend:/data/backend
|
||||
depends_on:
|
||||
- flaskaled-srv1
|
||||
- flaskaled-srv2
|
||||
links:
|
||||
- flaskaled-srv1
|
||||
- flaskaled-srv2
|
||||
environment:
|
||||
- FLASK_APP=app.py
|
||||
- FLASK_ENV=test
|
||||
- FLASK_DEBUG=0
|
||||
- PYTHONUNBUFFERED=1
|
||||
- DATABASE_URL_USERS=postgresql://flaskaled1:aled1@flaskaled-srv1/flaskaledDb1
|
||||
- DATABASE_URL_LOGS=postgresql://flaskaled2:aled2@flaskaled-srv2/flaskaledDb2
|
||||
- SECRET_KEY=default_secret_key
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
|
||||
# For additional information regarding the format and rule options, please see:
|
||||
# https://github.com/browserslist/browserslist#queries
|
||||
|
||||
# For the full list of supported browsers by the Angular framework, please see:
|
||||
# https://angular.io/guide/browser-support
|
||||
|
||||
# You can see what browsers were selected by your queries by running:
|
||||
# npx browserslist
|
||||
|
||||
last 1 Chrome version
|
||||
last 1 Firefox version
|
||||
last 2 Edge major versions
|
||||
last 2 Safari major versions
|
||||
last 2 iOS major versions
|
||||
Firefox ESR
|
||||
not IE 11 # Angular supports IE 11 only as an opt-in. To opt-in, remove the 'not' prefix on this line.
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
# Editor configuration, see https://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.ts]
|
||||
quote_type = single
|
||||
|
||||
[*.md]
|
||||
max_line_length = off
|
||||
trim_trailing_whitespace = false
|
||||
49
frontend/.gitignore
vendored
49
frontend/.gitignore
vendored
|
|
@ -1,49 +0,0 @@
|
|||
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
# compiled output
|
||||
/dist
|
||||
/tmp
|
||||
/out-tsc
|
||||
# Only exists if Bazel was run
|
||||
/bazel-out
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
|
||||
# profiling files
|
||||
chrome-profiler-events*.json
|
||||
|
||||
# IDEs and editors
|
||||
/.idea
|
||||
.project
|
||||
.classpath
|
||||
.c9/
|
||||
*.launch
|
||||
.settings/
|
||||
*.sublime-workspace
|
||||
|
||||
# IDE - VSCode
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
.history/*
|
||||
.idea/*
|
||||
|
||||
# misc
|
||||
/.angular/cache
|
||||
/.sass-cache
|
||||
/connect.lock
|
||||
/coverage
|
||||
/libpeerconnection.log
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
testem.log
|
||||
/typings
|
||||
|
||||
# System Files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
package-lock.json
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
FROM node:latest
|
||||
WORKDIR /data/frontend
|
||||
COPY ["package.json", "package-lock.json*", "./"]
|
||||
RUN npm install --NODE_ENV
|
||||
RUN npm install -g @angular/cli
|
||||
COPY . .
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
# Frontend
|
||||
|
||||
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 12.2.10.
|
||||
|
||||
## Development server
|
||||
|
||||
Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
|
||||
|
||||
## Code scaffolding
|
||||
|
||||
Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
|
||||
|
||||
## Build
|
||||
|
||||
Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory.
|
||||
|
||||
## Running unit tests
|
||||
|
||||
Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
|
||||
|
||||
## Running end-to-end tests
|
||||
|
||||
Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities.
|
||||
|
||||
## Further help
|
||||
|
||||
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.
|
||||
|
|
@ -1,113 +0,0 @@
|
|||
{
|
||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||
"version": 1,
|
||||
"newProjectRoot": "projects",
|
||||
"projects": {
|
||||
"frontend": {
|
||||
"projectType": "application",
|
||||
"schematics": {
|
||||
"@schematics/angular:component": {
|
||||
"style": "scss"
|
||||
},
|
||||
"@schematics/angular:application": {
|
||||
"strict": true
|
||||
}
|
||||
},
|
||||
"root": "",
|
||||
"sourceRoot": "src",
|
||||
"prefix": "app",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:browser",
|
||||
"options": {
|
||||
"outputPath": "dist/frontend",
|
||||
"index": "src/index.html",
|
||||
"main": "src/main.ts",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
"tsConfig": "tsconfig.app.json",
|
||||
"inlineStyleLanguage": "scss",
|
||||
"assets": [
|
||||
"src/favicon.ico",
|
||||
"src/assets"
|
||||
],
|
||||
"styles": [
|
||||
"./node_modules/@angular/material/prebuilt-themes/indigo-pink.css",
|
||||
"./node_modules/bootstrap/scss/bootstrap.scss",
|
||||
"src/styles.scss"
|
||||
],
|
||||
"scripts": []
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"budgets": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "500kb",
|
||||
"maximumError": "1mb"
|
||||
},
|
||||
{
|
||||
"type": "anyComponentStyle",
|
||||
"maximumWarning": "2kb",
|
||||
"maximumError": "4kb"
|
||||
}
|
||||
],
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "src/environments/environment.ts",
|
||||
"with": "src/environments/environment.prod.ts"
|
||||
}
|
||||
],
|
||||
"outputHashing": "all"
|
||||
},
|
||||
"development": {
|
||||
"buildOptimizer": false,
|
||||
"optimization": false,
|
||||
"vendorChunk": true,
|
||||
"extractLicenses": false,
|
||||
"sourceMap": true,
|
||||
"namedChunks": true
|
||||
}
|
||||
},
|
||||
"defaultConfiguration": "production"
|
||||
},
|
||||
"serve": {
|
||||
"builder": "@angular-devkit/build-angular:dev-server",
|
||||
"configurations": {
|
||||
"production": {
|
||||
"browserTarget": "frontend:build:production"
|
||||
},
|
||||
"development": {
|
||||
"browserTarget": "frontend:build:development"
|
||||
}
|
||||
},
|
||||
"defaultConfiguration": "development"
|
||||
},
|
||||
"extract-i18n": {
|
||||
"builder": "@angular-devkit/build-angular:extract-i18n",
|
||||
"options": {
|
||||
"browserTarget": "frontend:build"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"main": "src/test.ts",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
"tsConfig": "tsconfig.spec.json",
|
||||
"karmaConfig": "karma.conf.js",
|
||||
"inlineStyleLanguage": "scss",
|
||||
"assets": [
|
||||
"src/favicon.ico",
|
||||
"src/assets"
|
||||
],
|
||||
"styles": [
|
||||
"src/styles.scss"
|
||||
],
|
||||
"scripts": []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"defaultProject": "frontend"
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
// Karma configuration file, see link for more information
|
||||
// https://karma-runner.github.io/1.0/config/configuration-file.html
|
||||
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
basePath: '',
|
||||
frameworks: ['jasmine', '@angular-devkit/build-angular'],
|
||||
plugins: [
|
||||
require('karma-jasmine'),
|
||||
require('karma-chrome-launcher'),
|
||||
require('karma-jasmine-html-reporter'),
|
||||
require('karma-coverage'),
|
||||
require('@angular-devkit/build-angular/plugins/karma')
|
||||
],
|
||||
client: {
|
||||
jasmine: {
|
||||
// you can add configuration options for Jasmine here
|
||||
// the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
|
||||
// for example, you can disable the random execution with `random: false`
|
||||
// or set a specific seed with `seed: 4321`
|
||||
},
|
||||
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
||||
},
|
||||
jasmineHtmlReporter: {
|
||||
suppressAll: true // removes the duplicated traces
|
||||
},
|
||||
coverageReporter: {
|
||||
dir: require('path').join(__dirname, './coverage/frontend'),
|
||||
subdir: '.',
|
||||
reporters: [
|
||||
{ type: 'html' },
|
||||
{ type: 'text-summary' }
|
||||
]
|
||||
},
|
||||
reporters: ['progress', 'kjhtml'],
|
||||
port: 9876,
|
||||
colors: true,
|
||||
logLevel: config.LOG_INFO,
|
||||
autoWatch: true,
|
||||
browsers: ['Chrome'],
|
||||
singleRun: false,
|
||||
restartOnFileChange: true
|
||||
});
|
||||
};
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
{
|
||||
"name": "frontend",
|
||||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"start": "ng serve --host 0.0.0.0",
|
||||
"build": "ng build",
|
||||
"watch": "ng build --watch --configuration development",
|
||||
"test": "ng test"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/animations": "~13.1.1",
|
||||
"@angular/cdk": "^13.0.2",
|
||||
"@angular/common": "~13.1.1",
|
||||
"@angular/compiler": "~13.1.1",
|
||||
"@angular/core": "~13.1.1",
|
||||
"@angular/forms": "~13.1.1",
|
||||
"@angular/material": "^13.0.2",
|
||||
"@angular/platform-browser": "~13.1.1",
|
||||
"@angular/platform-browser-dynamic": "~13.1.1",
|
||||
"@angular/router": "~13.1.1",
|
||||
"bootstrap": "^5.1.3",
|
||||
"jquery": "^3.6.0",
|
||||
"popper": "^1.0.1",
|
||||
"rxjs": "~6.6.0",
|
||||
"tslib": "^2.3.0",
|
||||
"zone.js": "~0.11.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^13.1.4",
|
||||
"@angular/cli": "~13.1.2",
|
||||
"@angular/compiler-cli": "~13.1.1",
|
||||
"@types/jasmine": "~3.8.0",
|
||||
"@types/node": "^12.11.1",
|
||||
"jasmine-core": "~3.8.0",
|
||||
"karma": "~6.3.0",
|
||||
"karma-chrome-launcher": "~3.1.0",
|
||||
"karma-coverage": "~2.0.3",
|
||||
"karma-jasmine": "~4.0.0",
|
||||
"karma-jasmine-html-reporter": "~1.7.0",
|
||||
"typescript": "~4.5.4"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
La page "admin/myProfil" contient:
|
||||
- les informations de l'admin (composant "page-profil")
|
||||
- un bouton "modifier profil" pour modifier les informations de l'admin (composant "popup-update-profil")
|
||||
|
||||
Cette page est la même que la page de la partie utilisateur.
|
||||
|
||||
Ainsi, on a rangé cette page dans le dossier "common/components/profil".
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
<div>
|
||||
|
||||
<app-navbar pour="admin"></app-navbar>
|
||||
|
||||
|
||||
<div class="btnContainer">
|
||||
<button mat-button class="btnAjouter" (click)="onCreate()">
|
||||
<mat-icon>add_circle</mat-icon> Ajouter un utilisateur
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
<div style="text-align: center">
|
||||
<mat-form-field appearance="standard" class="filtre">
|
||||
<mat-label>Filter</mat-label>
|
||||
<input matInput (keyup)="applyFilter($event)" placeholder="Ex. Riri" #input>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
|
||||
<table *ngIf="(dataSource !== undefined) && (dataSource !== null) && (dataSource.data.length !== 0)"
|
||||
mat-table [dataSource]="dataSource" matSort class="mat-elevation-z8">
|
||||
|
||||
<!-- Pseudo Column -->
|
||||
<ng-container matColumnDef="nickname">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Pseudo</th>
|
||||
<td mat-cell *matCellDef="let person">{{person.nickname}}</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Email Column -->
|
||||
<ng-container matColumnDef="email">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Email</th>
|
||||
<td mat-cell *matCellDef="let person">{{person.email}}</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Role Column -->
|
||||
<ng-container matColumnDef="role">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Rôle</th>
|
||||
<td mat-cell *matCellDef="let person">{{person.role}}</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Actions Column -->
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Actions</th>
|
||||
<td mat-cell *matCellDef="let person">
|
||||
<button mat-icon-button (click)="onUpdate(person)">
|
||||
<mat-icon>edit</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button (click)="onDelete(person)">
|
||||
<mat-icon>delete</mat-icon>
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||
</table>
|
||||
|
||||
|
||||
<mat-paginator [pageSizeOptions]="[10, 20, 50, 100]"
|
||||
showFirstLastButtons
|
||||
aria-label="Select page of periodic elements"
|
||||
class="mat-elevation-z8"></mat-paginator>
|
||||
|
||||
|
||||
</div>
|
||||
<br><br>
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
mat-paginator, table {
|
||||
width: 80%;
|
||||
margin: auto 10%;
|
||||
}
|
||||
|
||||
.btnContainer {
|
||||
margin: 50px 10% 20px 0px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.btnAjouter {
|
||||
border: solid 1px black;
|
||||
}
|
||||
|
||||
.filtre {
|
||||
text-align: center;
|
||||
width: 33%;
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { PageUserListComponent } from './page-user-list.component';
|
||||
|
||||
describe('PageAdminComponent', () => {
|
||||
let component: PageUserListComponent;
|
||||
let fixture: ComponentFixture<PageUserListComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ PageUserListComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(PageUserListComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
@ -1,152 +0,0 @@
|
|||
import {AfterViewInit, Component, ViewChild} from '@angular/core';
|
||||
import {MatTableDataSource} from "@angular/material/table";
|
||||
import {MatSort} from "@angular/material/sort";
|
||||
import {MatPaginator} from "@angular/material/paginator";
|
||||
import {MatDialog} from "@angular/material/dialog";
|
||||
import {PopupCreatePersonComponent} from "../popup-create-person/popup-create-person.component";
|
||||
import {MatSnackBar} from "@angular/material/snack-bar";
|
||||
import {PopupUpdatePersonAdminComponent} from "../popup-update-person-admin/popup-update-person-admin.component";
|
||||
import {PopupDeleteProfilComponent} from "../../../common/components/popup-delete-profil/popup-delete-profil.component";
|
||||
import {MessageService} from "../../../common/services/message/message.service";
|
||||
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-page-user-list',
|
||||
templateUrl: './page-user-list.component.html',
|
||||
styleUrls: ['./page-user-list.component.scss']
|
||||
})
|
||||
export class PageUserListComponent implements AfterViewInit
|
||||
{
|
||||
displayedColumns: string[] = [ "nickname", "email", "role", "actions" ];
|
||||
dataSource: MatTableDataSource<any> = new MatTableDataSource<any>();
|
||||
@ViewChild(MatSort) sort: MatSort;
|
||||
@ViewChild(MatPaginator) paginator: MatPaginator;
|
||||
configSnackBar = { duration: 2000, panelClass: "custom-class" };
|
||||
|
||||
|
||||
constructor( private messageService: MessageService,
|
||||
public dialog: MatDialog,
|
||||
private snackBar: MatSnackBar) { }
|
||||
|
||||
|
||||
ngAfterViewInit(): void
|
||||
{
|
||||
this.messageService
|
||||
.get('users?order_by=nickname')
|
||||
.subscribe(retour => this.ngAfterViewInitCallback(retour), err => this.ngAfterViewInitCallback(err));
|
||||
}
|
||||
|
||||
|
||||
ngAfterViewInitCallback(retour: any): void
|
||||
{
|
||||
if(retour.status !== "success") {
|
||||
console.log(retour);
|
||||
}
|
||||
else {
|
||||
let tabPerson: { id: number, email: string, nickname: string, is_admin: boolean }[] = retour.data;
|
||||
tabPerson = tabPerson.map( person => {
|
||||
if(!person.is_admin) return Object.assign(person, {role: "utilisateur"});
|
||||
else return Object.assign(person, {role: "admin"});
|
||||
});
|
||||
this.dataSource = new MatTableDataSource(tabPerson);
|
||||
this.dataSource.sort = this.sort;
|
||||
this.dataSource.paginator = this.paginator;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
applyFilter(event: Event)
|
||||
{
|
||||
const filterValue = (event.target as HTMLInputElement).value;
|
||||
this.dataSource.filter = filterValue.trim().toLowerCase();
|
||||
}
|
||||
|
||||
|
||||
// Appuie sur le bouton "create"
|
||||
onCreate(): void
|
||||
{
|
||||
const config = { width: '50%' };
|
||||
this.dialog
|
||||
.open(PopupCreatePersonComponent, config)
|
||||
.afterClosed()
|
||||
.subscribe( retour => {
|
||||
|
||||
if((retour === null) || (retour === undefined))
|
||||
{
|
||||
this.snackBar.open( "Opération annulée", "", this.configSnackBar);
|
||||
}
|
||||
else {
|
||||
if(retour.data.is_admin) retour.data.role = "admin" ;
|
||||
else retour.data.role = "utilisateur" ;
|
||||
this.dataSource.data.push(retour.data);
|
||||
this.dataSource.data = this.dataSource.data;
|
||||
this.dataSource = this.dataSource;
|
||||
this.snackBar.open( "L'utilisateur a bien été créé ✔", "", this.configSnackBar);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Appuie sur le bouton "edit"
|
||||
onUpdate(personToUpdate: any): void
|
||||
{
|
||||
const config = {
|
||||
width: '50%',
|
||||
data: { person: personToUpdate }
|
||||
};
|
||||
this.dialog
|
||||
.open(PopupUpdatePersonAdminComponent, config)
|
||||
.afterClosed()
|
||||
.subscribe( is_admin => {
|
||||
|
||||
if((is_admin === null) || (is_admin === undefined))
|
||||
{
|
||||
this.snackBar.open("Opération annulée", "", this.configSnackBar);
|
||||
}
|
||||
else {
|
||||
const index = this.dataSource.data.findIndex(elt => (elt.id === personToUpdate.id));
|
||||
this.dataSource.data[index].is_admin = is_admin;
|
||||
if(is_admin) this.dataSource.data[index].role = "admin";
|
||||
else this.dataSource.data[index].role = "utilisateur";
|
||||
this.snackBar.open("L'utilisateur a bien été modifié ✔", "", this.configSnackBar);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Appuie sur le bouton "delete"
|
||||
onDelete(personToDelete: any): void
|
||||
{
|
||||
const config = {
|
||||
data: {
|
||||
id: personToDelete.id,
|
||||
email: personToDelete.email,
|
||||
me: false,
|
||||
}
|
||||
};
|
||||
this.dialog
|
||||
.open(PopupDeleteProfilComponent, config)
|
||||
.afterClosed()
|
||||
.subscribe( retour => {
|
||||
|
||||
if((retour === null) || (retour === undefined))
|
||||
{
|
||||
this.snackBar.open("Opération annulée", "", this.configSnackBar);
|
||||
}
|
||||
else if(retour.status === "error")
|
||||
{
|
||||
this.snackBar.open(retour.error.message, "", this.configSnackBar);
|
||||
}
|
||||
else {
|
||||
const index = this.dataSource.data.findIndex( elt => (elt.id === personToDelete.id));
|
||||
this.dataSource.data.splice(index, 1);
|
||||
this.dataSource.data = this.dataSource.data;
|
||||
this.dataSource = this.dataSource;
|
||||
this.snackBar.open("L'utilisateur a bien été supprimé ✔", "", this.configSnackBar);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
<div class="myContainer">
|
||||
|
||||
<h3>Ajouter un utilisateur</h3>
|
||||
|
||||
<mat-divider style="margin: 20px 0px 20px 0px"></mat-divider>
|
||||
|
||||
<!-- nickname -->
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-label>Pseudo</mat-label>
|
||||
<input matInput type="text" [(ngModel)]="nickname" required>
|
||||
</mat-form-field><br>
|
||||
|
||||
<!-- email -->
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-label>Email</mat-label>
|
||||
<input matInput type="text" [(ngModel)]="email" required>
|
||||
</mat-form-field><br>
|
||||
|
||||
<!-- mot de passe -->
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-label>Mot de passe</mat-label>
|
||||
<input matInput type="password" [(ngModel)]="password" required>
|
||||
</mat-form-field><br>
|
||||
|
||||
<!-- confirmation mot de passe -->
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-label>Confirmation mot de passe</mat-label>
|
||||
<input matInput type="password" [(ngModel)]="confirmPassword" required>
|
||||
</mat-form-field><br>
|
||||
|
||||
<!-- role -->
|
||||
<mat-radio-group aria-labelledby="label-radio-group" [(ngModel)]="is_admin">
|
||||
<mat-radio-button [value]="false" checked>Utilisateur </mat-radio-button>
|
||||
<mat-radio-button [value]="true">Admin</mat-radio-button>
|
||||
</mat-radio-group><br><br>
|
||||
|
||||
<mat-divider style="margin-bottom: 10px"></mat-divider>
|
||||
|
||||
<!-- message d'erreur -->
|
||||
<div *ngIf="hasError">
|
||||
<mat-error>{{errorMessage}}</mat-error>
|
||||
</div>
|
||||
|
||||
<!-- bouton -->
|
||||
<button mat-button (click)="onValider()">Valider</button>
|
||||
|
||||
</div>
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
.myContainer {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
::ng-deep .mat-radio-inner-circle {
|
||||
color: black !important;
|
||||
background-color: black !important;
|
||||
}
|
||||
|
||||
::ng-deep .mat-radio-outer-circle{
|
||||
color: black !important;
|
||||
border: solid 1px gray !important;
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { PopupCreatePersonComponent } from './popup-create-person.component';
|
||||
|
||||
describe('PopupCreerUtilisateurComponent', () => {
|
||||
let component: PopupCreatePersonComponent;
|
||||
let fixture: ComponentFixture<PopupCreatePersonComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ PopupCreatePersonComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(PopupCreatePersonComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
import {Component, Inject} from '@angular/core';
|
||||
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
|
||||
import {CheckEmailService} from "../../../common/services/checkEmail/check-email.service";
|
||||
import {MessageService} from "../../../common/services/message/message.service";
|
||||
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-popup-create-person',
|
||||
templateUrl: './popup-create-person.component.html',
|
||||
styleUrls: ['./popup-create-person.component.scss']
|
||||
})
|
||||
export class PopupCreatePersonComponent
|
||||
{
|
||||
nickname: string = "";
|
||||
email: string = "";
|
||||
is_admin: boolean = false;
|
||||
password: string = "";
|
||||
|
||||
confirmPassword: string = "" ;
|
||||
hasError: boolean = false;
|
||||
errorMessage: string = "" ;
|
||||
|
||||
|
||||
constructor( public dialogRef: MatDialogRef<PopupCreatePersonComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: any,
|
||||
private checkEmailService: CheckEmailService,
|
||||
private messageService: MessageService ) { }
|
||||
|
||||
|
||||
// Appuie sur le bouton "valider"
|
||||
onValider(): void
|
||||
{
|
||||
this.checkField();
|
||||
if(!this.hasError)
|
||||
{
|
||||
const data = {
|
||||
email: this.email,
|
||||
nickname: this.nickname,
|
||||
password: this.password,
|
||||
is_admin: this.is_admin
|
||||
};
|
||||
this.messageService
|
||||
.post("admin/create/user", data)
|
||||
.subscribe(ret => this.onValiderCallback(ret), err => this.onValiderCallback(err));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Callback de 'onValider'
|
||||
onValiderCallback(retour: any)
|
||||
{
|
||||
if(retour.status !== 'success')
|
||||
{
|
||||
console.log(retour);
|
||||
this.errorMessage = retour.error.message;
|
||||
this.hasError = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.dialogRef.close(retour);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Check les champs saisis par l'utilisateur
|
||||
checkField(): void
|
||||
{
|
||||
if(this.nickname.length === 0) {
|
||||
this.errorMessage = "Veuillez remplir le champ 'pseudo'.";
|
||||
this.hasError = true;
|
||||
}
|
||||
else if(this.email.length === 0) {
|
||||
this.errorMessage = "Veuillez remplir le champ 'email'.";
|
||||
this.hasError = true;
|
||||
}
|
||||
else if(!this.checkEmailService.isValidEmail(this.email)) {
|
||||
this.errorMessage = "Email invalide.";
|
||||
this.hasError = true;
|
||||
}
|
||||
else if(this.password.length === 0) {
|
||||
this.errorMessage = "Veuillez remplir le champ 'mot de passe'.";
|
||||
this.hasError = true;
|
||||
}
|
||||
else if(this.password !== this.confirmPassword) {
|
||||
this.errorMessage = "Le mot de passe est différent de sa confirmation.";
|
||||
this.hasError = true;
|
||||
}
|
||||
else {
|
||||
this.errorMessage = "" ;
|
||||
this.hasError = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
<div class="myContainer">
|
||||
<div class="boite">
|
||||
|
||||
<h3>Modifier</h3>
|
||||
|
||||
<!-- divider -->
|
||||
<mat-divider></mat-divider><br>
|
||||
|
||||
<!-- role -->
|
||||
<mat-radio-group [(ngModel)]="is_admin">
|
||||
<mat-radio-button [value]="false"
|
||||
[checked]="!is_admin">Utilisateur</mat-radio-button>
|
||||
<mat-radio-button [value]="true"
|
||||
[checked]="is_admin">Admin</mat-radio-button>
|
||||
</mat-radio-group><br><br>
|
||||
|
||||
<!-- divider -->
|
||||
<mat-divider></mat-divider><br>
|
||||
|
||||
<!-- Modifier mot de passe -->
|
||||
<div>
|
||||
Modifier mot de passe:
|
||||
<mat-checkbox [(ngModel)]="changePassword"></mat-checkbox>
|
||||
</div>
|
||||
|
||||
<!-- nouveau mot de passe -->
|
||||
<div *ngIf="changePassword" style="margin-top: 10px">
|
||||
<!-- Nouveau mot de passe -->
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-label>Nouveau mot de passe</mat-label>
|
||||
<input matInput type="password" [(ngModel)]="newPassword">
|
||||
</mat-form-field>
|
||||
<br>
|
||||
<!-- Confirmation npuveau mot de passe -->
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-label>Confirmation nouveau mot de passe</mat-label>
|
||||
<input matInput type="password" [(ngModel)]="confirmNewPassword">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div *ngIf="!changePassword"><br></div>
|
||||
|
||||
<!-- divider -->
|
||||
<mat-divider></mat-divider><br>
|
||||
|
||||
<!-- message d'erreur -->
|
||||
<div *ngIf="hasError" style="text-align: center; margin-bottom: 20px;">
|
||||
<span class="mat-error">{{errorMessage}}</span>
|
||||
</div>
|
||||
|
||||
<!-- boutons -->
|
||||
<div style="width: 100%; text-align: right">
|
||||
<button mat-button (click)="this.dialogRef.close(null)"> Annuler </button>
|
||||
<button mat-button (click)="onValider()"> Enregistrer </button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
.boite {
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
h3 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
button {
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
img {
|
||||
margin: 0px 0px 10px 0px;
|
||||
width: 5vw;
|
||||
height: 5vw;
|
||||
border: solid 2px black;
|
||||
border-radius: 50%;
|
||||
font-size: xxx-large;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// aura
|
||||
::ng-deep .mat-checkbox-ripple .mat-ripple-element {
|
||||
background-color: grey !important;
|
||||
}
|
||||
|
||||
// contenu coche
|
||||
::ng-deep .mat-checkbox-checked.mat-accent .mat-checkbox-background {
|
||||
background-color: black !important;
|
||||
}
|
||||
|
||||
// indeterminate
|
||||
::ng-deep .mat-checkbox .mat-checkbox-frame {
|
||||
background-color: white !important;
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { PopupUpdatePersonAdminComponent } from './popup-update-person-admin.component';
|
||||
|
||||
describe('PopupUpdatePersonAdminComponent', () => {
|
||||
let component: PopupUpdatePersonAdminComponent;
|
||||
let fixture: ComponentFixture<PopupUpdatePersonAdminComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ PopupUpdatePersonAdminComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(PopupUpdatePersonAdminComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
import {Component, Inject, OnInit} from '@angular/core';
|
||||
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
|
||||
import {CheckEmailService} from "../../../common/services/checkEmail/check-email.service";
|
||||
import {MessageService} from "../../../common/services/message/message.service";
|
||||
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-popup-update-person-admin',
|
||||
templateUrl: './popup-update-person-admin.component.html',
|
||||
styleUrls: ['./popup-update-person-admin.component.scss']
|
||||
})
|
||||
export class PopupUpdatePersonAdminComponent implements OnInit
|
||||
{
|
||||
id: number = 0;
|
||||
is_admin: boolean = false;
|
||||
newPassword: string = "";
|
||||
|
||||
confirmNewPassword: string = "" ;
|
||||
changePassword: boolean = false ;
|
||||
hasError: boolean = false;
|
||||
errorMessage: string = "" ;
|
||||
|
||||
|
||||
constructor( public dialogRef: MatDialogRef<PopupUpdatePersonAdminComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: any,
|
||||
private checkEmailService: CheckEmailService,
|
||||
private messageService: MessageService ) { }
|
||||
|
||||
|
||||
ngOnInit(): void
|
||||
{
|
||||
this.id = this.data.person.id;
|
||||
this.is_admin = this.data.person.is_admin;
|
||||
}
|
||||
|
||||
|
||||
// Appuie sur le bouton "valider"
|
||||
onValider(): void
|
||||
{
|
||||
this.checkField();
|
||||
if(!this.hasError)
|
||||
{
|
||||
let data = {};
|
||||
if(this.changePassword) data = { id: this.id, is_admin: this.is_admin, password: this.newPassword }
|
||||
else data = { id: this.id, is_admin: this.is_admin };
|
||||
this.messageService
|
||||
.put("admin/update/user", data)
|
||||
.subscribe(ret => this.onValiderCallback(ret), err => this.onValiderCallback(err));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Callback de 'onValider'
|
||||
onValiderCallback(retour: any)
|
||||
{
|
||||
if(retour.status !== 'success')
|
||||
{
|
||||
console.log(retour);
|
||||
this.errorMessage = retour.error.message;
|
||||
this.hasError = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.dialogRef.close(this.is_admin);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Check les champs saisis par l'utilisateur
|
||||
checkField(): void
|
||||
{
|
||||
if((this.changePassword) && (this.newPassword.length === 0)) {
|
||||
this.errorMessage = "Veuillez remplir le champ 'mot de passe'";
|
||||
this.hasError = true;
|
||||
}
|
||||
else if((this.changePassword) && (this.newPassword !== this.confirmNewPassword)) {
|
||||
this.errorMessage = "Le mot de passe est différent de sa confirmation";
|
||||
this.hasError = true;
|
||||
}
|
||||
else {
|
||||
this.errorMessage = "" ;
|
||||
this.hasError = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import {PageLoginComponent} from "./login/page-login/page-login.component";
|
||||
import {PageRegisterComponent} from "./register/page-register/page-register.component";
|
||||
import {PageProfilComponent} from "./common/components/page-profil/page-profil.component";
|
||||
import {PageUserListComponent} from "./admin/userList/page-user-list/page-user-list.component";
|
||||
import {PageRegistryComponent} from "./user/page-registry/page-registry.component";
|
||||
import {UserGuard} from "./common/guards/user/user.guard";
|
||||
import {AdminGuard} from "./common/guards/admin/admin.guard";
|
||||
|
||||
const routes: Routes = [
|
||||
|
||||
{ path: "", component: PageLoginComponent },
|
||||
{ path: "login", component: PageLoginComponent },
|
||||
|
||||
{ path: "register", component: PageRegisterComponent },
|
||||
|
||||
{ path: "user", component: PageRegistryComponent, canActivate: [UserGuard] },
|
||||
{ path: "user/registry", component: PageRegistryComponent, canActivate: [UserGuard] },
|
||||
{ path: "user/myProfil", component: PageProfilComponent, canActivate: [UserGuard] },
|
||||
|
||||
{ path: "admin", component: PageUserListComponent, canActivate: [AdminGuard] },
|
||||
{ path: "admin/userList", component: PageUserListComponent, canActivate: [AdminGuard] },
|
||||
{ path: "admin/myProfil", component: PageProfilComponent, canActivate: [AdminGuard] },
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forRoot(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class AppRoutingModule { }
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
||||
<router-outlet></router-outlet>
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
import { TestBed } from '@angular/core/testing';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
describe('AppComponent', () => {
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [
|
||||
RouterTestingModule
|
||||
],
|
||||
declarations: [
|
||||
AppComponent
|
||||
],
|
||||
}).compileComponents();
|
||||
});
|
||||
|
||||
it('should create the app', () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.componentInstance;
|
||||
expect(app).toBeTruthy();
|
||||
});
|
||||
|
||||
it(`should have as title 'frontend'`, () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.componentInstance;
|
||||
expect(app.title).toEqual('frontend');
|
||||
});
|
||||
|
||||
it('should render title', () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
fixture.detectChanges();
|
||||
const compiled = fixture.nativeElement as HTMLElement;
|
||||
expect(compiled.querySelector('.content span')?.textContent).toContain('frontend app is running!');
|
||||
});
|
||||
});
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.scss']
|
||||
})
|
||||
export class AppComponent {
|
||||
title = 'frontend';
|
||||
}
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
import { AppComponent } from './app.component';
|
||||
import { PageRegisterComponent } from './register/page-register/page-register.component';
|
||||
import {FormsModule} from "@angular/forms";
|
||||
import {BrowserAnimationsModule} from "@angular/platform-browser/animations";
|
||||
import {MatFormFieldModule} from "@angular/material/form-field";
|
||||
import {MatInputModule} from "@angular/material/input";
|
||||
import {PageLoginComponent} from "./login/page-login/page-login.component";
|
||||
import { NavbarComponent } from './common/components/navbar/navbar.component';
|
||||
import {MatButtonModule} from "@angular/material/button";
|
||||
import { PageProfilComponent } from './common/components/page-profil/page-profil.component';
|
||||
import { PopupUpdateProfilComponent } from './common/components/popup-update-profil/popup-update-profil.component';
|
||||
import {MatDividerModule} from "@angular/material/divider";
|
||||
import {MatCheckboxModule} from "@angular/material/checkbox";
|
||||
import {MatDialogModule} from "@angular/material/dialog";
|
||||
import {MatSnackBarModule} from "@angular/material/snack-bar";
|
||||
import { PageUserListComponent } from './admin/userList/page-user-list/page-user-list.component';
|
||||
import { PopupCreatePersonComponent } from './admin/userList/popup-create-person/popup-create-person.component';
|
||||
import {MatTableModule} from "@angular/material/table";
|
||||
import {MatPaginatorModule} from "@angular/material/paginator";
|
||||
import { PopupConfirmRegisterComponent } from './register/popup-confirm-register/popup-confirm-register.component';
|
||||
import {MatIconModule} from "@angular/material/icon";
|
||||
import {MatRadioModule} from "@angular/material/radio";
|
||||
import { PageRegistryComponent } from './user/page-registry/page-registry.component';
|
||||
import { PopupDeleteProfilComponent } from './common/components/popup-delete-profil/popup-delete-profil.component';
|
||||
import {MatSortModule} from "@angular/material/sort";
|
||||
import { PopupUpdatePersonAdminComponent } from './admin/userList/popup-update-person-admin/popup-update-person-admin.component';
|
||||
import {HttpClientModule} from "@angular/common/http";
|
||||
|
||||
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent,
|
||||
PageLoginComponent,
|
||||
PageRegisterComponent,
|
||||
NavbarComponent,
|
||||
PageProfilComponent,
|
||||
PopupUpdateProfilComponent,
|
||||
PageUserListComponent,
|
||||
PopupCreatePersonComponent,
|
||||
PopupConfirmRegisterComponent,
|
||||
PageRegistryComponent,
|
||||
PopupDeleteProfilComponent,
|
||||
PopupUpdatePersonAdminComponent
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
AppRoutingModule,
|
||||
FormsModule,
|
||||
BrowserAnimationsModule,
|
||||
HttpClientModule,
|
||||
MatFormFieldModule,
|
||||
MatInputModule,
|
||||
MatButtonModule,
|
||||
MatDividerModule,
|
||||
MatCheckboxModule,
|
||||
MatDialogModule,
|
||||
MatSnackBarModule,
|
||||
MatTableModule,
|
||||
MatPaginatorModule,
|
||||
MatSortModule,
|
||||
MatIconModule,
|
||||
MatRadioModule
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
export class AppModule { }
|
||||
|
|
@ -1,108 +0,0 @@
|
|||
<!-- Login -->
|
||||
<div *ngIf="pour === 'nickname'">
|
||||
<nav class="navbar navbar-expand-lg">
|
||||
|
||||
<!-- FlaskAled -->
|
||||
<a class="navbar-brand" routerLink=""> FlaskAled </a>
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<!-- Rien -->
|
||||
<div class="collapse navbar-collapse"></div>
|
||||
|
||||
<!-- S'inscrire -->
|
||||
<button mat-button class="btnDeconnexion" routerLink="/register">
|
||||
S'inscrire
|
||||
</button>
|
||||
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- --------------------------------------------------------------------------------------------------------- -->
|
||||
|
||||
|
||||
<!-- Register -->
|
||||
<div *ngIf="pour === 'register'">
|
||||
<nav class="navbar navbar-expand-lg">
|
||||
|
||||
<!-- FlaskAled -->
|
||||
<a class="navbar-brand" routerLink=""> FlaskAled </a>
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<!-- Rien -->
|
||||
<div class="collapse navbar-collapse"></div>
|
||||
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- --------------------------------------------------------------------------------------------------------- -->
|
||||
|
||||
|
||||
<!-- User -->
|
||||
<div *ngIf="pour === 'user'">
|
||||
<nav class="navbar navbar-expand-lg">
|
||||
|
||||
<!-- FlaskAled -->
|
||||
<a class="navbar-brand" routerLink="/user"> FlaskAled </a>
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<!-- [userList] [myProfil] -->
|
||||
<div class="collapse navbar-collapse">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item active monLi">
|
||||
<a class="nav-link" routerLink="/user/registry">Annuaire</a>
|
||||
</li>
|
||||
<li class="nav-item active monLi">
|
||||
<a class="nav-link" routerLink="/user/myProfil">Mon profil</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Deconnexion -->
|
||||
<button mat-button class="btnDeconnexion" (click)="onDeconnexion()" routerLink="/login">
|
||||
Deconnexion
|
||||
</button>
|
||||
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- --------------------------------------------------------------------------------------------------------- -->
|
||||
|
||||
|
||||
<!-- Admin -->
|
||||
<div *ngIf="pour === 'admin'">
|
||||
<nav class="navbar navbar-expand-lg">
|
||||
|
||||
<!-- FlaskAled -->
|
||||
<a class="navbar-brand" routerLink="/admin/userList"> FlaskAled </a>
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<!-- [userList] [myProfil] -->
|
||||
<div class="collapse navbar-collapse">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item active monLi">
|
||||
<a class="nav-link" routerLink="/admin/userList">Liste des utillisateurs</a>
|
||||
</li>
|
||||
<li class="nav-item active monLi">
|
||||
<a class="nav-link" routerLink="/admin/myProfil">Mon profil</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Deconnexion -->
|
||||
<button mat-button class="btnDeconnexion" (click)="onDeconnexion()" routerLink="/login">
|
||||
Deconnexion
|
||||
</button>
|
||||
|
||||
</nav>
|
||||
</div>
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
.navbar {
|
||||
background-color: black;
|
||||
height: 60px;
|
||||
font-size: medium;
|
||||
color: white;
|
||||
}
|
||||
|
||||
|
||||
.navbar-expand-lg {
|
||||
border-bottom: solid;
|
||||
border-color: white;
|
||||
border-bottom-width: 2px;
|
||||
}
|
||||
|
||||
|
||||
// PolyNotFound
|
||||
.navbar-brand {
|
||||
font-family: cursive;
|
||||
font-weight: bold;
|
||||
font-size: x-large;
|
||||
margin-left: 15px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
|
||||
// Recherche, Mes Playlists, Historique
|
||||
.nav-link {
|
||||
color: white;
|
||||
}
|
||||
.nav-link:hover {
|
||||
color: grey;
|
||||
}
|
||||
|
||||
|
||||
// Bonton deconnexion
|
||||
.btnDeconnexion {
|
||||
font-size: medium;
|
||||
margin: 0px 10px 0px 10px
|
||||
}
|
||||
.btnDeconnexion:hover {
|
||||
color: grey;
|
||||
}
|
||||
|
||||
|
||||
.monLi {
|
||||
margin: 0px 10px 0px 10px;
|
||||
}
|
||||
|
||||
|
||||
img {
|
||||
border: solid 2px white;
|
||||
border-radius: 50px;
|
||||
margin: 0px 10px 0px 15px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
img:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { NavbarComponent } from './navbar.component';
|
||||
|
||||
describe('NavbarComponent', () => {
|
||||
let component: NavbarComponent;
|
||||
let fixture: ComponentFixture<NavbarComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ NavbarComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(NavbarComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
import {Component, Input, OnInit} from '@angular/core';
|
||||
import {ProfilService} from "../../services/profil/profil.service";
|
||||
import {MessageService} from "../../services/message/message.service";
|
||||
|
||||
@Component({
|
||||
selector: 'app-navbar',
|
||||
templateUrl: './navbar.component.html',
|
||||
styleUrls: ['./navbar.component.scss']
|
||||
})
|
||||
export class NavbarComponent implements OnInit
|
||||
{
|
||||
@Input() pour = "login";
|
||||
|
||||
constructor(private profilService: ProfilService, private messageService: MessageService) { }
|
||||
|
||||
ngOnInit(): void {}
|
||||
|
||||
onDeconnexion(): void
|
||||
{
|
||||
this.messageService
|
||||
.delete('logout')
|
||||
.subscribe(retour => this.onDeconnexionCallback(retour), err => this.onDeconnexionCallback(err));
|
||||
this.profilService.setId(-1);
|
||||
this.profilService.setIsAdmin(false);
|
||||
}
|
||||
|
||||
onDeconnexionCallback(retour: any): void
|
||||
{
|
||||
if(retour.status !== "success") console.log(retour);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
<div class="myContainer">
|
||||
|
||||
<!-- NavBar -->
|
||||
<app-navbar [pour]="from"></app-navbar>
|
||||
|
||||
|
||||
<!-- Boite -->
|
||||
<div class="boite">
|
||||
|
||||
<!-- nickname -->
|
||||
<div class="row myRow">
|
||||
<div class="col-6 myLabel">Pseudo:</div>
|
||||
<div class="col-6 myValue"> {{person.nickname}} </div>
|
||||
</div>
|
||||
|
||||
<!-- email -->
|
||||
<div class="row myRow">
|
||||
<div class="col-6 myLabel">Mail:</div>
|
||||
<div class="col-6 myValue"> {{person.email}} </div>
|
||||
</div>
|
||||
|
||||
<!-- role -->
|
||||
<div class="row myRow">
|
||||
<div class="col-6 myLabel">Rôle:</div>
|
||||
<div class="col-6 myValue">
|
||||
<span *ngIf="this.from === 'user'">utilisateur</span>
|
||||
<span *ngIf="this.from === 'admin'">admin</span>
|
||||
</div>
|
||||
|
||||
<!-- boutons -->
|
||||
<div class="row">
|
||||
<!-- bouton modifier -->
|
||||
<div class="col-6">
|
||||
<div class="btnContainer">
|
||||
<button mat-button class="myBtn" (click)="onModifier()">
|
||||
<mat-icon>edit</mat-icon> Modifier compte
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- bouton supprimer -->
|
||||
<div class="col-6">
|
||||
<div class="btnContainer">
|
||||
<button mat-button class="myBtn" (click)="onSupprimer()">
|
||||
<mat-icon>delete</mat-icon> Supprimer compte
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
.myContainer {
|
||||
max-width: 100vw;
|
||||
height: 100vh;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
|
||||
.boite {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
width: 50%;
|
||||
margin-top: 10vh;
|
||||
border: solid 3px;
|
||||
border-radius: 10px;
|
||||
padding: 20px 40px 20px 40px;
|
||||
background-color: #ffffff;
|
||||
text-align: center;
|
||||
box-shadow: 10px 5px 5px black;
|
||||
}
|
||||
|
||||
|
||||
.myRow {
|
||||
margin: 15px 0px 15px 0px;
|
||||
}
|
||||
.myLabel {
|
||||
text-align: right;
|
||||
padding: 0px 5px 0px 0px;
|
||||
margin: 0px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.myValue {
|
||||
text-align: left;
|
||||
padding: 0px 0px 0px 5px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
|
||||
.btnContainer {
|
||||
text-align: center;
|
||||
margin-top: 40px;
|
||||
}
|
||||
.myBtn {
|
||||
border: solid 1px black;
|
||||
background-color: white;
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { PageProfilComponent } from './page-profil.component';
|
||||
|
||||
describe('PageUtilisateurComponent', () => {
|
||||
let component: PageProfilComponent;
|
||||
let fixture: ComponentFixture<PageProfilComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ PageProfilComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(PageProfilComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
@ -1,110 +0,0 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import {MatDialog} from "@angular/material/dialog";
|
||||
import {MatSnackBar} from "@angular/material/snack-bar";
|
||||
import {PopupUpdateProfilComponent} from "../popup-update-profil/popup-update-profil.component";
|
||||
import {Router} from "@angular/router";
|
||||
import {PopupDeleteProfilComponent} from "../popup-delete-profil/popup-delete-profil.component";
|
||||
import {MessageService} from "../../services/message/message.service";
|
||||
import {HttpParams} from "@angular/common/http";
|
||||
import {ProfilService} from "../../services/profil/profil.service";
|
||||
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-page-profil',
|
||||
templateUrl: './page-profil.component.html',
|
||||
styleUrls: ['./page-profil.component.scss']
|
||||
})
|
||||
export class PageProfilComponent implements OnInit
|
||||
{
|
||||
person = {
|
||||
id: "",
|
||||
nickname: "",
|
||||
email: "",
|
||||
is_admin: false,
|
||||
};
|
||||
from: string = "" ;
|
||||
configSnackbar = { duration: 3000, panelClass: "custom-class" };
|
||||
|
||||
|
||||
constructor( private messageService: MessageService,
|
||||
private profilService: ProfilService,
|
||||
public dialog: MatDialog,
|
||||
private snackBar: MatSnackBar,
|
||||
private router: Router ) { }
|
||||
|
||||
|
||||
ngOnInit(): void
|
||||
{
|
||||
if(this.router.url.startsWith("/user")) this.from = "user" ;
|
||||
else if(this.router.url.startsWith("/admin")) this.from = "admin" ;
|
||||
|
||||
let params = new HttpParams()
|
||||
params = params.set("order_by", "nickname");
|
||||
params = params.set("id", this.profilService.getId());
|
||||
this.messageService
|
||||
.get("users", params)
|
||||
.subscribe(ret => this.ngOnInitCallback(ret), err => this.ngOnInitCallback(err));
|
||||
}
|
||||
|
||||
|
||||
// Callback de ngOnInit
|
||||
ngOnInitCallback(retour: any): void
|
||||
{
|
||||
if(retour.status !== "success") {
|
||||
console.log(retour);
|
||||
}
|
||||
else {
|
||||
this.person = retour.data[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Appuie sur le bouton modifier
|
||||
onModifier(): void
|
||||
{
|
||||
const config = {
|
||||
width: '25%',
|
||||
data: { person: this.person }
|
||||
};
|
||||
this.dialog
|
||||
.open(PopupUpdateProfilComponent, config)
|
||||
.afterClosed()
|
||||
.subscribe(retour => this.onModifierCallback(retour));
|
||||
}
|
||||
|
||||
|
||||
// Callback de onModifier
|
||||
onModifierCallback(retour: any): void
|
||||
{
|
||||
if((retour === null) || (retour === undefined)) this.snackBar.open( "Opération annulé", "", this.configSnackbar);
|
||||
else if(retour.status === "success") this.person = retour.data;
|
||||
}
|
||||
|
||||
|
||||
// Appuie sur le bouton supprimer
|
||||
onSupprimer(): void
|
||||
{
|
||||
const config = {
|
||||
data: {
|
||||
id: this.person.id,
|
||||
email: this.person.email,
|
||||
me: true,
|
||||
}
|
||||
};
|
||||
this.dialog
|
||||
.open(PopupDeleteProfilComponent, config)
|
||||
.afterClosed()
|
||||
.subscribe(retour => this.onSupprimerCallback(retour));
|
||||
}
|
||||
|
||||
|
||||
// Callback de onSupprimer
|
||||
onSupprimerCallback(retour: any): void
|
||||
{
|
||||
if((retour === null) || (retour === undefined)) this.snackBar.open( "Opération annulé", "", this.configSnackbar);
|
||||
else if(retour.status === "error") this.snackBar.open(retour.error.message, "", this.configSnackbar);
|
||||
else if(retour.status === "success") this.router.navigateByUrl("/login");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
<mat-dialog-content class="mat-typography" *ngIf="me">
|
||||
Êtes-vous sûr de vouloir supprimer votre compte ?
|
||||
</mat-dialog-content>
|
||||
|
||||
|
||||
<mat-dialog-content class="mat-typography" *ngIf="!me">
|
||||
Êtes-vous sûr de vouloir supprimer <i>{{email}}</i> ?
|
||||
</mat-dialog-content>
|
||||
|
||||
|
||||
<mat-dialog-actions align="end">
|
||||
<button mat-button (click)="dialogRef.close();">Annuler</button>
|
||||
<button mat-button (click)="onValider()" cdkFocusInitial>Valider</button>
|
||||
</mat-dialog-actions>
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { PopupDeleteProfilComponent } from './popup-delete-profil.component';
|
||||
|
||||
describe('PopupDeleteProfilComponent', () => {
|
||||
let component: PopupDeleteProfilComponent;
|
||||
let fixture: ComponentFixture<PopupDeleteProfilComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ PopupDeleteProfilComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(PopupDeleteProfilComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
import {Component, Inject, OnInit} from '@angular/core';
|
||||
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
|
||||
import {MessageService} from "../../services/message/message.service";
|
||||
import {HttpParams} from "@angular/common/http";
|
||||
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-popup-delete-profil',
|
||||
templateUrl: './popup-delete-profil.component.html',
|
||||
styleUrls: ['./popup-delete-profil.component.scss']
|
||||
})
|
||||
export class PopupDeleteProfilComponent implements OnInit
|
||||
{
|
||||
id: number;
|
||||
me: boolean = false; // on se supprime soi-même
|
||||
email: string = "";
|
||||
|
||||
|
||||
constructor( private messageService: MessageService,
|
||||
public dialogRef: MatDialogRef<PopupDeleteProfilComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: any ) { }
|
||||
|
||||
|
||||
ngOnInit(): void {
|
||||
this.id = this.data.id;
|
||||
this.me = this.data.me;
|
||||
this.email = this.data.email;
|
||||
}
|
||||
|
||||
|
||||
// Appuie sur 'valider'
|
||||
onValider(): void
|
||||
{
|
||||
if(this.me)
|
||||
{
|
||||
this.messageService
|
||||
.delete("user/delete")
|
||||
.subscribe(ret => this.onValiderCallback(ret), err => this.onValiderCallback(err));
|
||||
}
|
||||
else {
|
||||
//let params = (new HttpParams()).set("id", this.id);
|
||||
this.messageService
|
||||
.delete("admin/delete/user/"+this.id)
|
||||
.subscribe(ret => this.onValiderCallback(ret), err => this.onValiderCallback(err));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Callback de onValider
|
||||
onValiderCallback(retour: any): void
|
||||
{
|
||||
if(retour.status === "success")
|
||||
{
|
||||
this.dialogRef.close(retour);
|
||||
}
|
||||
else if(retour.status === "error")
|
||||
{
|
||||
console.log(retour);
|
||||
this.dialogRef.close(retour);
|
||||
}
|
||||
else {
|
||||
console.log(retour);
|
||||
this.dialogRef.close(null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
<div class="myContainer">
|
||||
<div class="boite">
|
||||
|
||||
<h3>Modifier</h3>
|
||||
|
||||
<!-- divider -->
|
||||
<br><mat-divider></mat-divider><br>
|
||||
|
||||
<!-- nickname -->
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-label>Pseudo</mat-label>
|
||||
<input matInput type="text" [(ngModel)]="personCopy.nickname" required>
|
||||
</mat-form-field><br>
|
||||
|
||||
<!-- divider -->
|
||||
<mat-divider></mat-divider><br>
|
||||
|
||||
<!-- Modifier mot de passe -->
|
||||
<div>
|
||||
Modifier mot de passe:
|
||||
<mat-checkbox [(ngModel)]="changePassword"></mat-checkbox>
|
||||
</div>
|
||||
|
||||
<!-- nouveau mot de passe -->
|
||||
<div *ngIf="changePassword" style="margin-top: 10px">
|
||||
<!-- Nouveau mot de passe -->
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-label>Nouveau mot de passe</mat-label>
|
||||
<input matInput type="password" [(ngModel)]="newPassword">
|
||||
</mat-form-field>
|
||||
<br>
|
||||
<!-- Confirmation npuveau mot de passe -->
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-label>Confirmation nouveau mot de passe</mat-label>
|
||||
<input matInput type="password" [(ngModel)]="confirmNewPassword">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div *ngIf="!changePassword"><br></div>
|
||||
|
||||
<!-- divider -->
|
||||
<mat-divider></mat-divider><br>
|
||||
|
||||
<!-- message d'erreur -->
|
||||
<div *ngIf="hasError" style="text-align: center; margin-bottom: 20px;">
|
||||
<span class="mat-error">{{errorMessage}}</span>
|
||||
</div>
|
||||
|
||||
<!-- boutons -->
|
||||
<div style="width: 100%; text-align: right">
|
||||
<button mat-button (click)="this.dialogRef.close(null)"> Annuler </button>
|
||||
<button mat-button (click)="onValider()"> Enregistrer </button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
.boite {
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
h3 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
button {
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
img {
|
||||
margin: 0px 0px 10px 0px;
|
||||
width: 5vw;
|
||||
height: 5vw;
|
||||
border: solid 2px black;
|
||||
border-radius: 50%;
|
||||
font-size: xxx-large;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// aura
|
||||
::ng-deep .mat-checkbox-ripple .mat-ripple-element {
|
||||
background-color: grey !important;
|
||||
}
|
||||
|
||||
// contenu coche
|
||||
::ng-deep .mat-checkbox-checked.mat-accent .mat-checkbox-background {
|
||||
background-color: black !important;
|
||||
}
|
||||
|
||||
// indeterminate
|
||||
::ng-deep .mat-checkbox .mat-checkbox-frame {
|
||||
background-color: white !important;
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { PopupUpdateProfilComponent } from './popup-update-profil.component';
|
||||
|
||||
describe('PopupModifierUtilisateurComponent', () => {
|
||||
let component: PopupUpdateProfilComponent;
|
||||
let fixture: ComponentFixture<PopupUpdateProfilComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ PopupUpdateProfilComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(PopupUpdateProfilComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
@ -1,108 +0,0 @@
|
|||
import {Component, Inject, OnInit} from '@angular/core';
|
||||
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
|
||||
import {CheckEmailService} from "../../services/checkEmail/check-email.service";
|
||||
import {MessageService} from "../../services/message/message.service";
|
||||
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-popup-update-profil',
|
||||
templateUrl: './popup-update-profil.component.html',
|
||||
styleUrls: ['./popup-update-profil.component.scss']
|
||||
})
|
||||
export class PopupUpdateProfilComponent implements OnInit
|
||||
{
|
||||
personCopy: any;
|
||||
newPassword: string = "";
|
||||
confirmNewPassword: string = "" ;
|
||||
changePassword: boolean = false ;
|
||||
hasError: boolean = false;
|
||||
errorMessage: string = "" ;
|
||||
|
||||
|
||||
constructor( private checkEmailService: CheckEmailService,
|
||||
private messageService: MessageService,
|
||||
public dialogRef: MatDialogRef<PopupUpdateProfilComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: any ) { }
|
||||
|
||||
|
||||
ngOnInit(): void
|
||||
{
|
||||
const person = this.data.person;
|
||||
this.personCopy = {
|
||||
id: person.id,
|
||||
nickname: person.nickname,
|
||||
email: person.email,
|
||||
is_admin: person.is_admin
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// Appuie sur le bouton "valider"
|
||||
onValider(): void
|
||||
{
|
||||
this.checkField();
|
||||
if(!this.hasError)
|
||||
{
|
||||
let data: any = {nickname: this.personCopy.nickname};
|
||||
if(this.changePassword) data = {
|
||||
nickname: this.personCopy.nickname,
|
||||
password: this.newPassword
|
||||
};
|
||||
this.messageService
|
||||
.put("user/update", data)
|
||||
.subscribe(ret => this.onValiderCallback(ret), err => this.onValiderCallback(err));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Callback de 'onValider'
|
||||
onValiderCallback(retour: any)
|
||||
{
|
||||
if(retour.status === "success")
|
||||
{
|
||||
this.dialogRef.close(retour);
|
||||
}
|
||||
else if(retour.status === "error")
|
||||
{
|
||||
console.log(retour);
|
||||
this.errorMessage = retour.message;
|
||||
this.hasError = true;
|
||||
}
|
||||
else {
|
||||
console.log(retour);
|
||||
this.dialogRef.close(null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Check les champs saisis par l'utilisateur
|
||||
checkField(): void
|
||||
{
|
||||
if(this.personCopy.nickname.length === 0) {
|
||||
this.errorMessage = "Veuillez remplir le champ 'pseudo'" ;
|
||||
this.hasError = true;
|
||||
}
|
||||
else if(this.personCopy.email.length === 0) {
|
||||
this.errorMessage = "Veuillez remplir le champ 'email'" ;
|
||||
this.hasError = true;
|
||||
}
|
||||
else if(!this.checkEmailService.isValidEmail(this.personCopy.email)) {
|
||||
this.errorMessage = "Email invalide" ;
|
||||
this.hasError = true;
|
||||
}
|
||||
else if((this.changePassword) && (this.newPassword.length === 0)) {
|
||||
this.errorMessage = "Veuillez remplir le champ 'mot de passe'";
|
||||
this.hasError = true;
|
||||
}
|
||||
else if((this.changePassword) && (this.newPassword !== this.confirmNewPassword)) {
|
||||
this.errorMessage = "Le mot de passe est différent de sa confirmation";
|
||||
this.hasError = true;
|
||||
}
|
||||
else {
|
||||
this.errorMessage = "" ;
|
||||
this.hasError = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { AdminGuard } from './admin.guard';
|
||||
|
||||
describe('AdminGuard', () => {
|
||||
let guard: AdminGuard;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
guard = TestBed.inject(AdminGuard);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(guard).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import {ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree} from '@angular/router';
|
||||
import { Observable } from 'rxjs';
|
||||
import {ProfilService} from "../../services/profil/profil.service";
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class AdminGuard implements CanActivate
|
||||
{
|
||||
|
||||
constructor(private profilService: ProfilService, private router: Router) {}
|
||||
|
||||
|
||||
canActivate( route: ActivatedRouteSnapshot, state: RouterStateSnapshot ): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree
|
||||
{
|
||||
if(this.profilService.getId() === -1) // si non connecté
|
||||
{
|
||||
this.router.navigateByUrl("/login");
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if(this.profilService.isAdmin()) return true;
|
||||
else {
|
||||
this.router.navigateByUrl("/login");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { UserGuard } from './user.guard';
|
||||
|
||||
describe('UserGuard', () => {
|
||||
let guard: UserGuard;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
guard = TestBed.inject(UserGuard);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(guard).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import {ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree} from '@angular/router';
|
||||
import { Observable } from 'rxjs';
|
||||
import {ProfilService} from "../../services/profil/profil.service";
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class UserGuard implements CanActivate
|
||||
{
|
||||
|
||||
constructor(private profilService: ProfilService, private router: Router) {}
|
||||
|
||||
|
||||
canActivate( route: ActivatedRouteSnapshot, state: RouterStateSnapshot ): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree
|
||||
{
|
||||
if(this.profilService.getId() === -1) // si non connecté
|
||||
{
|
||||
this.router.navigateByUrl("/login");
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if(!this.profilService.isAdmin()) return true;
|
||||
else {
|
||||
this.router.navigateByUrl("/login");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { CheckEmailService } from './check-email.service';
|
||||
|
||||
describe('CheckEmailService', () => {
|
||||
let service: CheckEmailService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(CheckEmailService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class CheckEmailService
|
||||
{
|
||||
|
||||
isValidEmail(email: string): boolean
|
||||
{
|
||||
let re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
||||
return re.test(email);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { FictitiousDatasService } from './fictitious-datas.service';
|
||||
|
||||
describe('FictitiousDatasService', () => {
|
||||
let service: FictitiousDatasService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(FictitiousDatasService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class FictitiousDatasService
|
||||
{
|
||||
|
||||
getUser()
|
||||
{
|
||||
const id = (Math.floor(Math.random()*100000)).toString()
|
||||
return {
|
||||
id: id,
|
||||
nickname: "Riri"+id,
|
||||
email: "riri"+id+"@gmail.com",
|
||||
hash_pass: "blablabla",
|
||||
is_admin: false,
|
||||
}
|
||||
}
|
||||
|
||||
getAdmin()
|
||||
{
|
||||
const id = (Math.floor(Math.random()*100000)).toString()
|
||||
return {
|
||||
id: id,
|
||||
nickname: "Fifi"+id,
|
||||
email: "fifi"+id+"@gmail.com",
|
||||
hash_pass: "blablabla",
|
||||
is_admin: true,
|
||||
}
|
||||
}
|
||||
|
||||
getTabPerson(n: number)
|
||||
{
|
||||
let tab = [];
|
||||
|
||||
for(let i=0 ; i<n ; i++)
|
||||
{
|
||||
if(Math.random() < 0.5) tab.push(this.getUser());
|
||||
else tab.push(this.getAdmin());
|
||||
}
|
||||
|
||||
return tab;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { HashageService } from './hashage.service';
|
||||
|
||||
describe('HashageService', () => {
|
||||
let service: HashageService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(HashageService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class HashageService
|
||||
{
|
||||
// Fonction de hashage (faible)
|
||||
run(input: string): string
|
||||
{
|
||||
let hash = 0;
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
let ch = input.charCodeAt(i);
|
||||
hash = ((hash << 5) - hash) + ch;
|
||||
hash = hash & hash;
|
||||
}
|
||||
return hash.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { MessageService } from './message.service';
|
||||
|
||||
describe('MessageService', () => {
|
||||
let service: MessageService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(MessageService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import {HttpClient, HttpParams} from "@angular/common/http";
|
||||
import {Observable} from "rxjs";
|
||||
import {environment} from "../../../../environments/environment";
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class MessageService
|
||||
{
|
||||
|
||||
constructor( private http: HttpClient ) { }
|
||||
|
||||
post(url: string, data: any): Observable<any>
|
||||
{
|
||||
const urlComplete = environment.debutUrl + url ;
|
||||
return this.http.post<any>(urlComplete, data, {withCredentials: true});
|
||||
}
|
||||
|
||||
get(url: string, params:HttpParams = new HttpParams()): Observable<any>
|
||||
{
|
||||
const urlComplete = environment.debutUrl + url ;
|
||||
return this.http.get<any>(urlComplete,{ withCredentials: true, params: params });
|
||||
}
|
||||
|
||||
put(url: string, data: any): Observable<any>
|
||||
{
|
||||
const urlComplete = environment.debutUrl + url ;
|
||||
return this.http.put<any>(urlComplete, data, {withCredentials: true});
|
||||
}
|
||||
|
||||
delete(url: string, params:HttpParams = new HttpParams()): Observable<any>
|
||||
{
|
||||
const urlComplete = environment.debutUrl + url ;
|
||||
return this.http.delete<any>(urlComplete,{withCredentials: true});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ProfilService } from './profil.service';
|
||||
|
||||
describe('ProfilService', () => {
|
||||
let service: ProfilService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(ProfilService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ProfilService
|
||||
{
|
||||
|
||||
constructor()
|
||||
{
|
||||
if(localStorage.getItem('id') === null) this.setId(-1);
|
||||
if(localStorage.getItem('isAdmin') === null) this.setIsAdmin(false);
|
||||
}
|
||||
|
||||
getId(): number
|
||||
{
|
||||
let idString = localStorage.getItem('id');
|
||||
if(idString === null) return -1;
|
||||
else return parseInt(idString);
|
||||
}
|
||||
|
||||
setId(id: number): void
|
||||
{
|
||||
localStorage.setItem('id', id.toString());
|
||||
}
|
||||
|
||||
isAdmin(): boolean
|
||||
{
|
||||
let isAdminString = localStorage.getItem('isAdmin');
|
||||
if(isAdminString === "T") return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
setIsAdmin(isAdmin: boolean): void
|
||||
{
|
||||
let isAdminString = "" ;
|
||||
if(isAdmin) isAdminString = "T";
|
||||
else isAdminString = "F";
|
||||
localStorage.setItem('isAdmin', isAdminString);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
<div>
|
||||
<div class="bg">
|
||||
|
||||
|
||||
<!-- NavBar -->
|
||||
<app-navbar pour="nickname"></app-navbar>
|
||||
|
||||
|
||||
<!--contenu -->
|
||||
<div class="wrapper fadeInDown">
|
||||
<div id="formContent">
|
||||
|
||||
<!-- Icon -->
|
||||
<div class="fadeIn first">
|
||||
<h1 style="font-family: cursive; font-size: 45px; margin-top: 20px; margin-bottom: 10px">FlaskAled</h1>
|
||||
<img src="/assets/logo.png" id="icon" alt="User Icon" style="margin-top: 10px"/>
|
||||
</div>
|
||||
|
||||
<!-- Login Form -->
|
||||
<form>
|
||||
<input [(ngModel)]="email" type="text" id="email" class="fadeIn second" name="email" placeholder="Email">
|
||||
<input [(ngModel)]="password" type="password" id="password" class="fadeIn third" name="password" placeholder="Mot de passe">
|
||||
<!-- Message d'erreur -->
|
||||
<div *ngIf="hasError" style="text-align: center; margin-bottom: 20px;">
|
||||
<span class="mat-error"> {{errorMessage}} </span>
|
||||
</div>
|
||||
<input type="submit" class="fadeIn fourth" value="Se connecter" (click)="onSeConnecter()">
|
||||
</form>
|
||||
|
||||
<!-- Oubli mot de passe -->
|
||||
<div id="formFooter">
|
||||
<a class="underlineHover" href="https://disney.fandom.com/fr/wiki/Tristesse">J'ai oublié mon mot de passe</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -1,271 +0,0 @@
|
|||
html {
|
||||
background-color: #56baed;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: "Poppins", sans-serif;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #5E89FF;
|
||||
display:inline-block;
|
||||
text-decoration: none;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
h2 {
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
display:inline-block;
|
||||
margin: 40px 8px 10px 8px;
|
||||
color: #cccccc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* STRUCTURE */
|
||||
|
||||
.wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
min-height: 80%;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
#formContent {
|
||||
-webkit-border-radius: 10px 10px 10px 10px;
|
||||
border-radius: 10px 10px 10px 10px;
|
||||
background: #fff;
|
||||
padding: 30px;
|
||||
width: 90%;
|
||||
max-width: 450px;
|
||||
position: relative;
|
||||
padding: 0px;
|
||||
-webkit-box-shadow: 0 30px 60px 0 rgba(0,0,0,0.3);
|
||||
box-shadow: 0 30px 60px 0 rgba(0,0,0,0.3);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#formFooter {
|
||||
background-color: #f6f6f6;
|
||||
border-top: 1px solid #dce8f1;
|
||||
padding: 25px;
|
||||
text-align: center;
|
||||
-webkit-border-radius: 0 0 10px 10px;
|
||||
border-radius: 0 0 10px 10px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* TABS */
|
||||
|
||||
h2.inactive {
|
||||
color: #cccccc;
|
||||
}
|
||||
|
||||
h2.active {
|
||||
color: #0d0d0d;
|
||||
border-bottom: 2px solid #5fbae9;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* FORM TYPOGRAPHY*/
|
||||
|
||||
input[type=button], input[type=submit], input[type=reset] {
|
||||
background-color: #5E89FF;
|
||||
border: none;
|
||||
color: white;
|
||||
padding: 15px 80px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
text-transform: uppercase;
|
||||
font-size: 13px;
|
||||
-webkit-box-shadow: 0 10px 30px 0 rgba(95,186,233,0.4);
|
||||
box-shadow: 0 10px 30px 0 rgba(95,186,233,0.4);
|
||||
-webkit-border-radius: 5px 5px 5px 5px;
|
||||
border-radius: 5px 5px 5px 5px;
|
||||
margin: 5px 20px 40px 20px;
|
||||
-webkit-transition: all 0.3s ease-in-out;
|
||||
-moz-transition: all 0.3s ease-in-out;
|
||||
-ms-transition: all 0.3s ease-in-out;
|
||||
-o-transition: all 0.3s ease-in-out;
|
||||
transition: all 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
input[type=button]:hover, input[type=submit]:hover, input[type=reset]:hover {
|
||||
background-color: #39ace7;
|
||||
}
|
||||
|
||||
input[type=button]:active, input[type=submit]:active, input[type=reset]:active {
|
||||
-moz-transform: scale(0.95);
|
||||
-webkit-transform: scale(0.95);
|
||||
-o-transform: scale(0.95);
|
||||
-ms-transform: scale(0.95);
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
input[type=text], input[type=password] {
|
||||
background-color: #f6f6f6;
|
||||
border: none;
|
||||
color: #0d0d0d;
|
||||
padding: 15px 32px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
font-size: 16px;
|
||||
margin: 5px;
|
||||
width: 85%;
|
||||
border: 2px solid #f6f6f6;
|
||||
-webkit-transition: all 0.5s ease-in-out;
|
||||
-moz-transition: all 0.5s ease-in-out;
|
||||
-ms-transition: all 0.5s ease-in-out;
|
||||
-o-transition: all 0.5s ease-in-out;
|
||||
transition: all 0.5s ease-in-out;
|
||||
-webkit-border-radius: 5px 5px 5px 5px;
|
||||
border-radius: 5px 5px 5px 5px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
input[type=text]:focus, input[type=password]:focus {
|
||||
background-color: #fff;
|
||||
border-bottom: 2px solid #5fbae9;
|
||||
}
|
||||
|
||||
input[type=text]::placeholder, input[type=password]::placeholder {
|
||||
color: #cccccc;
|
||||
}
|
||||
|
||||
.bg{
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
overflow-y: hidden;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
/* ANIMATIONS */
|
||||
|
||||
/* Simple CSS3 Fade-in-down Animation */
|
||||
.fadeInDown {
|
||||
-webkit-animation-name: fadeInDown;
|
||||
animation-name: fadeInDown;
|
||||
-webkit-animation-duration: 1s;
|
||||
animation-duration: 1s;
|
||||
-webkit-animation-fill-mode: both;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
|
||||
@-webkit-keyframes fadeInDown {
|
||||
0% {
|
||||
opacity: 0;
|
||||
-webkit-transform: translate3d(0, -100%, 0);
|
||||
transform: translate3d(0, -100%, 0);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
-webkit-transform: none;
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInDown {
|
||||
0% {
|
||||
opacity: 0;
|
||||
-webkit-transform: translate3d(0, -100%, 0);
|
||||
transform: translate3d(0, -100%, 0);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
-webkit-transform: none;
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Simple CSS3 Fade-in Animation */
|
||||
@-webkit-keyframes fadeIn { from { opacity:0; } to { opacity:1; } }
|
||||
@-moz-keyframes fadeIn { from { opacity:0; } to { opacity:1; } }
|
||||
@keyframes fadeIn { from { opacity:0; } to { opacity:1; } }
|
||||
|
||||
.fadeIn {
|
||||
opacity:0;
|
||||
-webkit-animation:fadeIn ease-in 1;
|
||||
-moz-animation:fadeIn ease-in 1;
|
||||
animation:fadeIn ease-in 1;
|
||||
|
||||
-webkit-animation-fill-mode:forwards;
|
||||
-moz-animation-fill-mode:forwards;
|
||||
animation-fill-mode:forwards;
|
||||
|
||||
-webkit-animation-duration:1s;
|
||||
-moz-animation-duration:1s;
|
||||
animation-duration:1s;
|
||||
}
|
||||
|
||||
.fadeIn.first {
|
||||
-webkit-animation-delay: 0.4s;
|
||||
-moz-animation-delay: 0.4s;
|
||||
animation-delay: 0.4s;
|
||||
}
|
||||
|
||||
.fadeIn.second {
|
||||
-webkit-animation-delay: 0.6s;
|
||||
-moz-animation-delay: 0.6s;
|
||||
animation-delay: 0.6s;
|
||||
}
|
||||
|
||||
.fadeIn.third {
|
||||
-webkit-animation-delay: 0.8s;
|
||||
-moz-animation-delay: 0.8s;
|
||||
animation-delay: 0.8s;
|
||||
}
|
||||
|
||||
.fadeIn.fourth {
|
||||
-webkit-animation-delay: 1s;
|
||||
-moz-animation-delay: 1s;
|
||||
animation-delay: 1s;
|
||||
}
|
||||
|
||||
/* Simple CSS3 Fade-in Animation */
|
||||
.underlineHover:after {
|
||||
display: block;
|
||||
left: 0;
|
||||
bottom: -10px;
|
||||
width: 0;
|
||||
height: 2px;
|
||||
//background-color: #5E89FF;
|
||||
background-color: #5E89FF;
|
||||
content: "";
|
||||
transition: width 0.2s;
|
||||
}
|
||||
|
||||
.underlineHover:hover {
|
||||
color: #0d0d0d;
|
||||
}
|
||||
|
||||
.underlineHover:hover:after{
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
h1{
|
||||
color: black;
|
||||
}
|
||||
|
||||
/* OTHERS */
|
||||
|
||||
*:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
#icon {
|
||||
width:30%;
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { PageConnexionComponent } from './page-connexion.component';
|
||||
|
||||
describe('PageConnexionComponent', () => {
|
||||
let component: PageConnexionComponent;
|
||||
let fixture: ComponentFixture<PageConnexionComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ PageConnexionComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(PageConnexionComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
import {Component} from '@angular/core';
|
||||
import {Router} from "@angular/router";
|
||||
import {MessageService} from "../../common/services/message/message.service";
|
||||
import {ProfilService} from "../../common/services/profil/profil.service";
|
||||
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-page-nickname',
|
||||
templateUrl: './page-login.component.html',
|
||||
styleUrls: ['./page-login.component.scss']
|
||||
})
|
||||
export class PageLoginComponent
|
||||
{
|
||||
email: string = "" ;
|
||||
password: string = "" ;
|
||||
hasError: boolean = false;
|
||||
errorMessage: string = "";
|
||||
|
||||
|
||||
constructor( private messageService: MessageService,
|
||||
private router: Router,
|
||||
private profilService: ProfilService ) { }
|
||||
|
||||
|
||||
// Appuie sur le bouton "seConnecter"
|
||||
onSeConnecter(): void
|
||||
{
|
||||
this.checkField();
|
||||
if(!this.hasError)
|
||||
{
|
||||
const data = {
|
||||
email: this.email,
|
||||
password: this.password
|
||||
};
|
||||
this.messageService
|
||||
.post('login', data)
|
||||
.subscribe( retour => this.onSeConnecterCallback(retour), err => this.onSeConnecterCallback(err));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Callback de "onSeConnecter"
|
||||
onSeConnecterCallback(retour: any): void
|
||||
{
|
||||
if(retour.status !== "success")
|
||||
{
|
||||
console.log(retour);
|
||||
this.errorMessage = retour.error.message;
|
||||
this.hasError = true;
|
||||
}
|
||||
else {
|
||||
this.profilService.setId(retour.data.id);
|
||||
this.profilService.setIsAdmin(retour.data.is_admin)
|
||||
if(retour.data.is_admin) this.router.navigateByUrl('admin/userList');
|
||||
else this.router.navigateByUrl('user/registry');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Check les champs saisis par l'utilisateur
|
||||
checkField(): void
|
||||
{
|
||||
if(this.email === "") {
|
||||
this.errorMessage = "Veuillez remplir le champ email" ;
|
||||
this.hasError = true;
|
||||
}
|
||||
else if(this.password === "") {
|
||||
this.errorMessage = "Veuillez remplir le champ mot de passe" ;
|
||||
this.hasError = true;
|
||||
}
|
||||
else {
|
||||
this.errorMessage = "" ;
|
||||
this.hasError = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
<div class="myContainer">
|
||||
|
||||
|
||||
<!-- navbar -->
|
||||
<app-navbar pour="register"></app-navbar>
|
||||
|
||||
|
||||
<!-- contenu -->
|
||||
<div class="boite">
|
||||
|
||||
<!-- nickname -->
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-label>Pseudo</mat-label>
|
||||
<input matInput type="text" [(ngModel)]="nickname" required>
|
||||
</mat-form-field><br>
|
||||
|
||||
<!-- email -->
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-label>Email</mat-label>
|
||||
<input matInput type="text" [(ngModel)]="email" required>
|
||||
</mat-form-field><br>
|
||||
|
||||
<!-- Mot de passe -->
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-label>Mot de passe</mat-label>
|
||||
<input matInput type="password" [(ngModel)]="password" required>
|
||||
</mat-form-field><br>
|
||||
|
||||
<!-- Confirmation mot de passe -->
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-label>Confirmation mot de passe</mat-label>
|
||||
<input matInput type="password" [(ngModel)]="confirmPassword" required>
|
||||
</mat-form-field><br>
|
||||
|
||||
<!-- Message d'erreur -->
|
||||
<div *ngIf="hasError">
|
||||
<mat-error>{{errorMessage}}</mat-error>
|
||||
</div>
|
||||
|
||||
<!-- bouton -->
|
||||
<button mat-button style="border: solid 1px black" (click)="onValider()">
|
||||
Valider
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue