diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml deleted file mode 100644 index 7b13ff2..0000000 --- a/.github/workflows/docker-image.yml +++ /dev/null @@ -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 \ No newline at end of file diff --git a/backend/__pycache__/app.cpython-310.pyc b/backend/__pycache__/app.cpython-310.pyc deleted file mode 100644 index 56671cd..0000000 Binary files a/backend/__pycache__/app.cpython-310.pyc and /dev/null differ diff --git a/backend/__pycache__/app.cpython-38.pyc b/backend/__pycache__/app.cpython-38.pyc deleted file mode 100644 index 951bfbe..0000000 Binary files a/backend/__pycache__/app.cpython-38.pyc and /dev/null differ diff --git a/backend/__pycache__/config.cpython-310.pyc b/backend/__pycache__/config.cpython-310.pyc deleted file mode 100644 index 6ca6f0b..0000000 Binary files a/backend/__pycache__/config.cpython-310.pyc and /dev/null differ diff --git a/backend/__pycache__/config.cpython-38.pyc b/backend/__pycache__/config.cpython-38.pyc deleted file mode 100644 index 6e1dae2..0000000 Binary files a/backend/__pycache__/config.cpython-38.pyc and /dev/null differ diff --git a/backend/__pycache__/fictive_users.cpython-38.pyc b/backend/__pycache__/fictive_users.cpython-38.pyc deleted file mode 100644 index 477bdc3..0000000 Binary files a/backend/__pycache__/fictive_users.cpython-38.pyc and /dev/null differ diff --git a/backend/app.py b/backend/app.py deleted file mode 100644 index 50e795c..0000000 --- a/backend/app.py +++ /dev/null @@ -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) diff --git a/backend/application/__pycache__/__init__.cpython-310.pyc b/backend/application/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index 4f97792..0000000 Binary files a/backend/application/__pycache__/__init__.cpython-310.pyc and /dev/null differ diff --git a/backend/application/__pycache__/__init__.cpython-38.pyc b/backend/application/__pycache__/__init__.cpython-38.pyc deleted file mode 100644 index b057e9d..0000000 Binary files a/backend/application/__pycache__/__init__.cpython-38.pyc and /dev/null differ diff --git a/backend/application/__pycache__/api_functions.cpython-310.pyc b/backend/application/__pycache__/api_functions.cpython-310.pyc deleted file mode 100644 index 037557d..0000000 Binary files a/backend/application/__pycache__/api_functions.cpython-310.pyc and /dev/null differ diff --git a/backend/application/__pycache__/api_functions.cpython-38.pyc b/backend/application/__pycache__/api_functions.cpython-38.pyc deleted file mode 100644 index 9f49edf..0000000 Binary files a/backend/application/__pycache__/api_functions.cpython-38.pyc and /dev/null differ diff --git a/backend/application/__pycache__/logs_model.cpython-310.pyc b/backend/application/__pycache__/logs_model.cpython-310.pyc deleted file mode 100644 index c317af2..0000000 Binary files a/backend/application/__pycache__/logs_model.cpython-310.pyc and /dev/null differ diff --git a/backend/application/__pycache__/logs_model.cpython-38.pyc b/backend/application/__pycache__/logs_model.cpython-38.pyc deleted file mode 100644 index f7aa63a..0000000 Binary files a/backend/application/__pycache__/logs_model.cpython-38.pyc and /dev/null differ diff --git a/backend/application/__pycache__/responses.cpython-310.pyc b/backend/application/__pycache__/responses.cpython-310.pyc deleted file mode 100644 index 05d2496..0000000 Binary files a/backend/application/__pycache__/responses.cpython-310.pyc and /dev/null differ diff --git a/backend/application/__pycache__/responses.cpython-38.pyc b/backend/application/__pycache__/responses.cpython-38.pyc deleted file mode 100644 index 7975ba1..0000000 Binary files a/backend/application/__pycache__/responses.cpython-38.pyc and /dev/null differ diff --git a/backend/application/__pycache__/routes.cpython-310.pyc b/backend/application/__pycache__/routes.cpython-310.pyc deleted file mode 100644 index d5552d7..0000000 Binary files a/backend/application/__pycache__/routes.cpython-310.pyc and /dev/null differ diff --git a/backend/application/__pycache__/routes.cpython-38.pyc b/backend/application/__pycache__/routes.cpython-38.pyc deleted file mode 100644 index 7a95df1..0000000 Binary files a/backend/application/__pycache__/routes.cpython-38.pyc and /dev/null differ diff --git a/backend/application/__pycache__/sessionJWT.cpython-310.pyc b/backend/application/__pycache__/sessionJWT.cpython-310.pyc deleted file mode 100644 index 2b9734d..0000000 Binary files a/backend/application/__pycache__/sessionJWT.cpython-310.pyc and /dev/null differ diff --git a/backend/application/__pycache__/sessionJWT.cpython-38.pyc b/backend/application/__pycache__/sessionJWT.cpython-38.pyc deleted file mode 100644 index 2ea8bca..0000000 Binary files a/backend/application/__pycache__/sessionJWT.cpython-38.pyc and /dev/null differ diff --git a/backend/application/__pycache__/users_model.cpython-310.pyc b/backend/application/__pycache__/users_model.cpython-310.pyc deleted file mode 100644 index e386a6a..0000000 Binary files a/backend/application/__pycache__/users_model.cpython-310.pyc and /dev/null differ diff --git a/backend/application/__pycache__/users_model.cpython-38.pyc b/backend/application/__pycache__/users_model.cpython-38.pyc deleted file mode 100644 index 43995d7..0000000 Binary files a/backend/application/__pycache__/users_model.cpython-38.pyc and /dev/null differ diff --git a/backend/application/api_functions.py b/backend/application/api_functions.py deleted file mode 100644 index bb67cbd..0000000 --- a/backend/application/api_functions.py +++ /dev/null @@ -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]} diff --git a/backend/application/logs_model.py b/backend/application/logs_model.py deleted file mode 100644 index 53ac617..0000000 --- a/backend/application/logs_model.py +++ /dev/null @@ -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__() diff --git a/backend/application/users_model.py b/backend/application/users_model.py deleted file mode 100644 index b932328..0000000 --- a/backend/application/users_model.py +++ /dev/null @@ -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 - } diff --git a/backend/env.sh b/backend/env.sh deleted file mode 100755 index da2fa7f..0000000 --- a/backend/env.sh +++ /dev/null @@ -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 diff --git a/backend/fictive_users.py b/backend/fictive_users.py deleted file mode 100644 index 6f97529..0000000 --- a/backend/fictive_users.py +++ /dev/null @@ -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"] - ) diff --git a/backend/init-db1.sql b/backend/init-db1.sql deleted file mode 100755 index bbec183..0000000 --- a/backend/init-db1.sql +++ /dev/null @@ -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); \ No newline at end of file diff --git a/backend/init-db2.sql b/backend/init-db2.sql deleted file mode 100644 index 02ebdc9..0000000 --- a/backend/init-db2.sql +++ /dev/null @@ -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 -); \ No newline at end of file diff --git a/backend/requirements.txt b/backend/requirements.txt deleted file mode 100644 index 6317cbe..0000000 --- a/backend/requirements.txt +++ /dev/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 \ No newline at end of file diff --git a/backend/test.py b/backend/test.py deleted file mode 100644 index 2aa595f..0000000 --- a/backend/test.py +++ /dev/null @@ -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() diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index f5519be..0000000 --- a/docker-compose.yml +++ /dev/null @@ -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 diff --git a/frontend/.browserslistrc b/frontend/.browserslistrc index 427441d..8651e3c 100644 --- a/frontend/.browserslistrc +++ b/frontend/.browserslistrc @@ -15,3 +15,5 @@ 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. +not ios_saf 15.2-15.3 +not safari 15.2-15.3 diff --git a/frontend/.gitignore b/frontend/.gitignore index bac05b4..350e08c 100644 --- a/frontend/.gitignore +++ b/frontend/.gitignore @@ -47,3 +47,5 @@ testem.log Thumbs.db package-lock.json + +backend/dist diff --git a/frontend/Dockerfile b/frontend/Dockerfile index b0c17cc..e936fe3 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -1,6 +1,6 @@ FROM node:latest -WORKDIR /data/frontend +WORKDIR /app-frontend COPY ["package.json", "package-lock.json*", "./"] -RUN npm install --NODE_ENV +RUN npm install RUN npm install -g @angular/cli COPY . . diff --git a/frontend/angular.json b/frontend/angular.json index 99c397a..c961521 100644 --- a/frontend/angular.json +++ b/frontend/angular.json @@ -42,13 +42,13 @@ "budgets": [ { "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" + "maximumWarning": "1mb", + "maximumError": "2mb" }, { "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" + "maximumWarning": "4kb", + "maximumError": "8kb" } ], "fileReplacements": [ diff --git a/backend/Dockerfile b/frontend/backend/Dockerfile similarity index 80% rename from backend/Dockerfile rename to frontend/backend/Dockerfile index 2987276..0b0cc90 100644 --- a/backend/Dockerfile +++ b/frontend/backend/Dockerfile @@ -1,6 +1,5 @@ FROM python:latest -WORKDIR /data/backend COPY requirements.txt requirements.txt RUN pip install --upgrade pip RUN pip install -r requirements.txt -COPY . . \ No newline at end of file +COPY . . diff --git a/frontend/backend/app.py b/frontend/backend/app.py new file mode 100644 index 0000000..62d5d48 --- /dev/null +++ b/frontend/backend/app.py @@ -0,0 +1,7 @@ +from application import create_app +import os + +app = create_app(os.environ.get('FLASK_ENV')) + +if __name__ == "__main__": + app.run(host='0.0.0.0', DEBUG=True) diff --git a/backend/application/__init__.py b/frontend/backend/application/__init__.py similarity index 55% rename from backend/application/__init__.py rename to frontend/backend/application/__init__.py index b68cd09..1f773b6 100644 --- a/backend/application/__init__.py +++ b/frontend/backend/application/__init__.py @@ -1,16 +1,13 @@ 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) + print("create app") + app = Flask(__name__, instance_relative_config=False, static_url_path='') origin = app.config.get('ALLOW_ORIGIN') if origin is None: - origin = ['http://127.0.0.1:4200', 'http://localhost:4200'] + origin = ['http://10.1.1.10'] CORS(app, supports_credentials=True, origins=origin) if flask_env == 'production': app.config.from_object("config.ProductionConfig") @@ -21,15 +18,7 @@ def create_app(flask_env='development'): 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 diff --git a/backend/application/responses.py b/frontend/backend/application/responses.py similarity index 94% rename from backend/application/responses.py rename to frontend/backend/application/responses.py index 03e11a6..32453c8 100644 --- a/backend/application/responses.py +++ b/frontend/backend/application/responses.py @@ -1,4 +1,6 @@ +print("Import responses Flask") from flask import current_app as app +print("Import Json") import json diff --git a/backend/application/routes.py b/frontend/backend/application/routes.py similarity index 67% rename from backend/application/routes.py rename to frontend/backend/application/routes.py index 70d5160..b510218 100644 --- a/backend/application/routes.py +++ b/frontend/backend/application/routes.py @@ -1,9 +1,33 @@ -from flask import request, Blueprint +print("Import Flask") +from flask import request, Blueprint, send_from_directory, current_app as app +print("Import Requests") +import requests +print("Import werkzeug") 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 + +# Request Post +def request_post(url, data_json): + return requests.post(app.config['API_URL'] + url, json=data_json) + + +# Request Put +def request_put(url, data_json): + return requests.put(app.config['API_URL'] + url, json=data_json) + + +# Request Get +def request_get(url): + return requests.get(app.config['API_URL'] + url) + + +# Request Delete +def request_delete(url, data_json): + return requests.delete(app.config['API_URL'] + url, json=data_json) + + bp = Blueprint('myapp', __name__) @@ -21,12 +45,13 @@ def login(): 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: + # res = db_login(ip, post_email, post_password) + res = request_post('login', {'ip': ip, 'email': post_email, 'password': post_password}).json() + if res['status'] == 'success': user = res['data'] token = create_auth_token(user) return send_message(res['message'], user, token) - elif res['status'] == 1: + elif res['status'] == 'error': user = None token = create_auth_token(user) return send_error(400, res['message'], token) @@ -46,10 +71,12 @@ def register(): 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: + # res = db_register(ip, post_email, post_nickname, post_password) + res = request_post('register', {'ip': ip, 'email': post_email, 'nickname': post_nickname, + 'password': post_password}).json() + if res['status'] == 'error': return send_error(500, res['message']) - elif res['status'] == 0: + elif res['status'] == 'success': return send_message(res['message'], res['data']) else: return send_error(400, 'Empty email and/or password and/or nickname fields.') @@ -63,17 +90,9 @@ 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) + user_id = token['payload']['id'] + res = request_delete('logout', {'ip': ip, 'user_id': user_id}).json() + return send_message(res['message'], None, token_delete=True) else: return send_error(500, token['message']) @@ -101,10 +120,12 @@ def user_update(): 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: + # res = db_user_update(ip, user_id, post_nickname, post_password) + res = request_put('user/update', {'ip': ip, 'user_id': user_id, 'nickname': post_nickname, + 'password': post_password}).json() + if res['status'] == 'error': return send_error(500, res['message']) - elif res['status'] == 0: + elif res['status'] == 'success': return send_message(res['message'], res['data']) else: return send_error(400, 'Empty nickname and/or password fields.') @@ -121,19 +142,11 @@ def user_delete(): if token['success']: ip = request.remote_addr user_id = token['payload']['id'] - res = db_user_delete(ip, user_id) - if res['status'] != 0: + # res = db_user_delete(ip, user_id) + res = request_delete('user/delete', {'ip': ip, 'user_id': user_id}).json() + if res['status'] != 'success': 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']) @@ -176,28 +189,19 @@ def admin_create_user(): 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 - ) + # res = db_register(ip, post_email, post_nickname, post_password, is_admin=post_is_admin) + res = request_post('admin/create/user', { + 'ip': ip, + 'user_id': user_id, + 'token_is_admin': is_admin, + 'email': post_email, + 'nickname': post_nickname, + 'password': post_password, + 'is_admin': post_is_admin + }).json() + if res['status'] == 'error': 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 - ) + elif res['status'] == 'success': 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.') @@ -240,28 +244,18 @@ def admin_update_user(): 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 - ) + # res = db_admin_update_user(ip, post_user_id_delete, post_is_admin, post_password) + res = request_put('admin/update/user', { + 'ip': ip, + 'user_id': user_id, + 'token_is_admin': is_admin, + 'id': post_user_id_delete, + 'is_admin': post_is_admin, + 'password': post_password + }).json() + if res['status'] == 'error': 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 - ) + elif res['status'] == 'success': return send_message(res['message'], res['data']) else: return send_error(400, 'Empty is_admin and/or password fields.') @@ -291,28 +285,16 @@ def admin_delete_user(id): 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 - ) + # res = db_user_delete(ip, int(post_user_id_delete)) + res = request_delete('admin/delete/user', { + 'ip': ip, + 'user_id': user_id, + 'token_is_admin': is_admin, + 'id': post_user_id_delete + }).json() + if res['status'] == 'error': 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.') @@ -331,13 +313,35 @@ def users(): if token['success']: ip = request.remote_addr user_id = token['payload']['id'] + + filter = '' get_query = request.args.get('q') + if get_query is not None: + filter += f'&q={get_query}' + get_by = request.args.get('by') + if get_by is not None: + filter += f'&by={get_by}' + get_id = request.args.get('id') + if get_id is not None: + filter += f'&id={get_id}' + get_is_admin = request.args.get('is_admin') + if get_is_admin is not None: + filter += f'&is_admin={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: + if get_order_by is not None: + filter += f'&order_by={get_order_by}' + # res = db_users(ip, user_id, get_query, get_by, get_id, get_is_admin, get_order_by) + res = request_get( + 'users' + f'?ip={ip}' + f'&user_id={user_id}' + f'{filter}' + ).json() + if res['status'] == 'error': return send_error(500, res['message']) else: return send_message(res['message'], res['data']) diff --git a/backend/application/sessionJWT.py b/frontend/backend/application/sessionJWT.py similarity index 93% rename from backend/application/sessionJWT.py rename to frontend/backend/application/sessionJWT.py index ef228fb..2722453 100644 --- a/backend/application/sessionJWT.py +++ b/frontend/backend/application/sessionJWT.py @@ -1,5 +1,8 @@ +print("Import datetime") from datetime import datetime, timedelta +print("Import sessionJWT Flask") from flask import current_app as app +print("Import jwt") import jwt diff --git a/backend/config.py b/frontend/backend/config.py similarity index 50% rename from backend/config.py rename to frontend/backend/config.py index ae0e613..75fbce5 100644 --- a/backend/config.py +++ b/frontend/backend/config.py @@ -1,3 +1,4 @@ +print("Import os") import os basedir = os.path.abspath(os.path.dirname(__file__)) @@ -10,15 +11,9 @@ class Config(object): FLASK_APP = os.environ.get('FLASK_APP', None) FLASK_ENV = os.environ.get('FLASK_ENV', None) + FLASK_RUN_PORT = os.environ.get('FLASK_RUN_PORT', 5000) - 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 - } + API_URL = os.environ.get('API_URL', 'http://127.0.0.1:5000/api/') SECRET_KEY = os.environ.get('SECRET_KEY', 'default_secret_key') ALLOW_ORIGIN = os.environ.get('ALLOW_ORIGIN', None) @@ -26,18 +21,13 @@ class Config(object): class ProductionConfig(Config): DEBUG = False - SQLALCHEMY_ECHO = False - SQLALCHEMY_TRACK_MODIFICATIONS = False + API_URL = os.environ.get('API_URL', 'http://10.1.2.10:5000/api/') 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 diff --git a/frontend/backend/requirements.txt b/frontend/backend/requirements.txt new file mode 100644 index 0000000..887af13 --- /dev/null +++ b/frontend/backend/requirements.txt @@ -0,0 +1,8 @@ +Flask==2.0.2 +Flask-Testing==0.8.1 +Flask-WTF==0.15.1 +PyJWT==2.3.0 +pytest==6.2.5 +psycopg2==2.9.2 +Flask-Cors==3.0.10 +requests==2.22.0 diff --git a/frontend/conf/nginx.conf b/frontend/conf/nginx.conf new file mode 100644 index 0000000..e1ee6c3 --- /dev/null +++ b/frontend/conf/nginx.conf @@ -0,0 +1,42 @@ +events { + worker_connections 1024; +} + +http { + + resolver 127.0.0.11 ipv6=off; + + proxy_redirect off; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + client_max_body_size 100m; + client_body_buffer_size 128k; + proxy_connect_timeout 90; + proxy_send_timeout 90; + proxy_read_timeout 90; + proxy_buffers 32 4k; + + upstream frontend { + server frontend:4200; + } + + upstream flask-frontend { + server flask-frontend:5000; + } + + + server { + listen 80; + access_log logs/access.log; + + location / { + proxy_pass http://frontend; + } + + location /api { + proxy_pass http://flask-frontend; + } + } + +} diff --git a/frontend/docker-compose.yml b/frontend/docker-compose.yml new file mode 100644 index 0000000..f29551a --- /dev/null +++ b/frontend/docker-compose.yml @@ -0,0 +1,48 @@ +version: '3.8' + +services: + nginx-front: + image: nginx:latest + volumes: + - ./conf/nginx.conf:/etc/nginx/nginx.conf + - ./logs/nginx:/etc/nginx/logs + - ./cert:/etc/nginx/cert + networks: + - net + ports: + - 80:80 + depends_on: + - frontend + - flask-frontend + + frontend: + container_name: frontend + build: . + command: npm start + volumes: + - ./src:/data/frontend + - ./node_modules:/data/frontend/node_modules + environment: + - NODE_ENV=production + networks: + - net + + flask-frontend: + container_name: flask-frontend + build: backend + command: python -m flask run + volumes: + - ./backend:/data/backend + environment: + - FLASK_APP=app.py + - FLASK_ENV=production + - FLASK_DEBUG=0 + - FLASK_RUN_PORT=5000 + networks: + - net + depends_on: + - frontend + +networks: + net: + driver: bridge diff --git a/frontend/logs/nginx/access.log b/frontend/logs/nginx/access.log new file mode 100644 index 0000000..b657bb1 --- /dev/null +++ b/frontend/logs/nginx/access.log @@ -0,0 +1,49 @@ +192.168.0.1 - - [28/Jan/2022:11:02:32 +0000] "GET / HTTP/1.1" 200 2713 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 OPR/82.0.4227.50" +192.168.0.1 - - [28/Jan/2022:11:02:32 +0000] "GET /polyfills.0cf80192f5858f6f.js HTTP/1.1" 200 37090 "http://localhost/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 OPR/82.0.4227.50" +192.168.0.1 - - [28/Jan/2022:11:02:32 +0000] "GET /runtime.aaedba49815d2ab0.js HTTP/1.1" 200 1066 "http://localhost/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 OPR/82.0.4227.50" +192.168.0.1 - - [28/Jan/2022:11:02:32 +0000] "GET /styles.f64087845b474dd2.css HTTP/1.1" 200 235504 "http://localhost/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 OPR/82.0.4227.50" +192.168.0.1 - - [28/Jan/2022:11:02:32 +0000] "GET /main.d1e7791aa69a6ada.js HTTP/1.1" 200 694159 "http://localhost/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 OPR/82.0.4227.50" +192.168.0.1 - - [28/Jan/2022:11:02:33 +0000] "GET /assets/logo.png HTTP/1.1" 200 201990 "http://localhost/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 OPR/82.0.4227.50" +192.168.0.1 - - [28/Jan/2022:11:02:33 +0000] "GET /favicon.ico HTTP/1.1" 200 948 "http://localhost/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 OPR/82.0.4227.50" +192.168.0.1 - - [28/Jan/2022:11:02:41 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 OPR/82.0.4227.50" +192.168.0.1 - - [28/Jan/2022:11:02:41 +0000] "GET /polyfills.0cf80192f5858f6f.js HTTP/1.1" 304 0 "http://localhost/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 OPR/82.0.4227.50" +192.168.0.1 - - [28/Jan/2022:11:02:41 +0000] "GET /runtime.aaedba49815d2ab0.js HTTP/1.1" 304 0 "http://localhost/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 OPR/82.0.4227.50" +192.168.0.1 - - [28/Jan/2022:11:02:41 +0000] "GET /main.d1e7791aa69a6ada.js HTTP/1.1" 304 0 "http://localhost/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 OPR/82.0.4227.50" +192.168.16.1 - - [28/Jan/2022:11:03:38 +0000] "GET / HTTP/1.1" 200 2713 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 OPR/82.0.4227.50" +192.168.16.1 - - [28/Jan/2022:11:03:38 +0000] "GET /styles.f64087845b474dd2.css HTTP/1.1" 200 235504 "http://localhost/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 OPR/82.0.4227.50" +192.168.16.1 - - [28/Jan/2022:11:03:38 +0000] "GET /assets/logo.png HTTP/1.1" 200 201990 "http://localhost/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 OPR/82.0.4227.50" +192.168.16.1 - - [28/Jan/2022:11:04:23 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 OPR/82.0.4227.50" +192.168.16.1 - - [28/Jan/2022:11:04:23 +0000] "GET /runtime.aaedba49815d2ab0.js HTTP/1.1" 200 1066 "http://localhost/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 OPR/82.0.4227.50" +192.168.16.1 - - [28/Jan/2022:11:04:23 +0000] "GET /polyfills.0cf80192f5858f6f.js HTTP/1.1" 200 37090 "http://localhost/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 OPR/82.0.4227.50" +192.168.16.1 - - [28/Jan/2022:11:04:23 +0000] "GET /main.d1e7791aa69a6ada.js HTTP/1.1" 200 694159 "http://localhost/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 OPR/82.0.4227.50" +192.168.16.1 - - [28/Jan/2022:11:04:23 +0000] "GET /styles.f64087845b474dd2.css HTTP/1.1" 304 0 "http://localhost/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 OPR/82.0.4227.50" +192.168.16.1 - - [28/Jan/2022:11:04:23 +0000] "GET /assets/logo.png HTTP/1.1" 304 0 "http://localhost/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 OPR/82.0.4227.50" +192.168.16.1 - - [28/Jan/2022:11:04:23 +0000] "GET /favicon.ico HTTP/1.1" 200 948 "http://localhost/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 OPR/82.0.4227.50" +172.21.0.1 - - [01/Feb/2022:14:58:24 +0000] "GET / HTTP/1.1" 502 559 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36" +172.21.0.1 - - [01/Feb/2022:14:58:25 +0000] "GET /favicon.ico HTTP/1.1" 502 559 "http://localhost/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36" +172.21.0.1 - - [01/Feb/2022:14:58:30 +0000] "GET / HTTP/1.1" 502 559 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36" +172.21.0.1 - - [01/Feb/2022:14:58:30 +0000] "GET /favicon.ico HTTP/1.1" 502 559 "http://127.0.0.1/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36" +172.21.0.1 - - [01/Feb/2022:15:01:07 +0000] "GET / HTTP/1.1" 502 559 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36" +172.21.0.1 - - [01/Feb/2022:15:01:07 +0000] "GET /favicon.ico HTTP/1.1" 502 559 "http://127.0.0.1/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36" +172.22.0.1 - - [01/Feb/2022:15:14:43 +0000] "GET / HTTP/1.1" 502 559 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36" +172.22.0.1 - - [01/Feb/2022:15:14:43 +0000] "GET /favicon.ico HTTP/1.1" 502 559 "http://127.0.0.1/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36" +172.22.0.1 - - [01/Feb/2022:15:19:49 +0000] "GET / HTTP/1.1" 502 559 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36" +172.22.0.1 - - [01/Feb/2022:15:19:52 +0000] "GET /favicon.ico HTTP/1.1" 502 559 "http://localhost/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36" +172.22.0.1 - - [01/Feb/2022:15:22:17 +0000] "GET / HTTP/1.1" 502 559 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36" +172.22.0.1 - - [01/Feb/2022:15:22:18 +0000] "GET /favicon.ico HTTP/1.1" 502 559 "http://localhost/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36" +172.22.0.1 - - [01/Feb/2022:15:22:19 +0000] "GET / HTTP/1.1" 502 559 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36" +172.22.0.1 - - [01/Feb/2022:15:22:19 +0000] "GET /favicon.ico HTTP/1.1" 502 559 "http://localhost/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36" +172.28.0.1 - - [02/Feb/2022:08:44:58 +0000] "GET / HTTP/1.1" 200 2713 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 OPR/82.0.4227.50" +172.28.0.1 - - [02/Feb/2022:08:44:59 +0000] "GET /runtime.aaedba49815d2ab0.js HTTP/1.1" 200 1066 "http://localhost/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 OPR/82.0.4227.50" +172.28.0.1 - - [02/Feb/2022:08:44:59 +0000] "GET /polyfills.0cf80192f5858f6f.js HTTP/1.1" 200 37090 "http://localhost/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 OPR/82.0.4227.50" +172.28.0.1 - - [02/Feb/2022:08:44:59 +0000] "GET /styles.f64087845b474dd2.css HTTP/1.1" 200 235504 "http://localhost/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 OPR/82.0.4227.50" +172.28.0.1 - - [02/Feb/2022:08:44:59 +0000] "GET /main.100f2196b68e9ba2.js HTTP/1.1" 200 694159 "http://localhost/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 OPR/82.0.4227.50" +172.28.0.1 - - [02/Feb/2022:08:44:59 +0000] "GET /assets/logo.png HTTP/1.1" 200 201990 "http://localhost/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 OPR/82.0.4227.50" +172.28.0.1 - - [02/Feb/2022:08:45:01 +0000] "GET /styles.f64087845b474dd2.css HTTP/1.1" 304 0 "http://localhost/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 OPR/82.0.4227.50" +172.28.0.1 - - [02/Feb/2022:08:45:52 +0000] "GET / HTTP/1.1" 200 2713 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 OPR/82.0.4227.50" +172.28.0.1 - - [02/Feb/2022:08:45:52 +0000] "GET /runtime.aaedba49815d2ab0.js HTTP/1.1" 200 1066 "http://localhost/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 OPR/82.0.4227.50" +172.28.0.1 - - [02/Feb/2022:08:45:52 +0000] "GET /polyfills.0cf80192f5858f6f.js HTTP/1.1" 200 37090 "http://localhost/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 OPR/82.0.4227.50" +172.28.0.1 - - [02/Feb/2022:08:45:52 +0000] "GET /main.100f2196b68e9ba2.js HTTP/1.1" 200 694159 "http://localhost/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 OPR/82.0.4227.50" +172.28.0.1 - - [02/Feb/2022:08:45:52 +0000] "GET /styles.f64087845b474dd2.css HTTP/1.1" 200 235504 "http://localhost/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 OPR/82.0.4227.50" +172.28.0.1 - - [02/Feb/2022:08:45:52 +0000] "GET /assets/logo.png HTTP/1.1" 200 201990 "http://localhost/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 OPR/82.0.4227.50" +172.28.0.1 - - [02/Feb/2022:08:45:52 +0000] "GET /favicon.ico HTTP/1.1" 200 948 "http://localhost/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 OPR/82.0.4227.50" diff --git a/frontend/package.json b/frontend/package.json index 43ae649..2f177c9 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -3,7 +3,7 @@ "version": "0.0.0", "scripts": { "ng": "ng", - "start": "ng serve --host 0.0.0.0", + "start": "ng build && node server.js", "build": "ng build", "watch": "ng build --watch --configuration development", "test": "ng test" @@ -21,6 +21,7 @@ "@angular/platform-browser-dynamic": "~13.1.1", "@angular/router": "~13.1.1", "bootstrap": "^5.1.3", + "express": "^4.17.2", "jquery": "^3.6.0", "popper": "^1.0.1", "rxjs": "~6.6.0", diff --git a/frontend/server.js b/frontend/server.js new file mode 100644 index 0000000..7398651 --- /dev/null +++ b/frontend/server.js @@ -0,0 +1,13 @@ +const path = require('path'); +const express = require('express'); +const app = express(); +const port = process.env.PORT || 4200; + +app.use(express.static(__dirname + '/dist/frontend')); +app.get('/*', function(req,res) { + res.sendFile(path.join(__dirname+ '/dist/frontend/index.html')); +}); + +app.listen(port, '0.0.0.0',() => { + console.log (`listening on port ${port}`); +}); diff --git a/frontend/src/environments/environment.prod.ts b/frontend/src/environments/environment.prod.ts index 3612073..e664d27 100644 --- a/frontend/src/environments/environment.prod.ts +++ b/frontend/src/environments/environment.prod.ts @@ -1,3 +1,4 @@ export const environment = { - production: true + production: true, + debutUrl: 'http://10.1.1.10/api/' };