diff --git a/morphocut_server/api.py b/morphocut_server/api.py
index d040ae7..c6de98f 100644
--- a/morphocut_server/api.py
+++ b/morphocut_server/api.py
@@ -20,7 +20,7 @@
from flask.blueprints import Blueprint
from flask.helpers import send_from_directory
from flask_cors import CORS
-from flask_login import logout_user
+from flask_login import logout_user, login_user
from flask_user import (UserManager, UserMixin, current_user, login_required,
roles_required)
from rq import Queue
@@ -39,6 +39,7 @@
from morphocut_server.frontend import frontend
from morphocut_server.worker import redis_conn
from morphocut_server.pipeline import *
+from flask_jwt_extended import jwt_required, get_jwt_identity
api = Blueprint("api", __name__)
@@ -49,14 +50,14 @@
@api.route("/users", methods=['GET', 'POST'])
-@login_required
-@roles_required('admin')
+# @login_required
+# @roles_required('admin')
def get_current_users_route():
"""Get the users currently registered.
Returns
-------
- repsonse : str
+ response : str
The jsonified response object.
"""
@@ -65,6 +66,9 @@ def get_current_users_route():
user = request.get_json()
morphocut.add_user_to_database(
user['email'], user['password'], user['admin'])
+
+ response_object = {'status': 'success', 'message': 'User added successfully'}
+ return jsonify(response_object)
else:
response_object = {'status': 'success'}
users = models.User.query.all()
@@ -80,8 +84,7 @@ def get_current_users_route():
'users': user_list
}
- return jsonify(response_object)
-
+ return jsonify(response_object)
@api.route("/users/current", methods=['GET'])
def get_current_user_route():
@@ -171,8 +174,8 @@ def get_user_jobs_route(id):
# Projects Routes
# ===============================================================================
-
@api.route('/projects', methods=['GET', 'POST'])
+@login_required
def get_projects_route():
"""Get the projects from the database.
@@ -190,6 +193,10 @@ def get_projects_route():
response_object['message'] = 'Project added!'
else:
response_object['projects'] = get_projects()
+
+ if not current_user.is_authenticated:
+ return jsonify({'status': 'error', 'message': 'User not authenticated'}), 401
+
return jsonify(response_object)
@@ -358,14 +365,14 @@ def remove_project(project_id):
response_object = {'status': 'success'}
with database.engine.begin() as connection:
- stmt = select([models.projects.c.path]).where(
+ stmt = select(models.projects.c.path).where(
models.projects.c.project_id == project_id)
project = connection.execute(stmt).first()
if project:
app = flask.current_app
project_path = os.path.join(
- app.root_path, app.config['DATA_DIRECTORY'], project['path'])
+ app.root_path, app.config['DATA_DIRECTORY'], project._asdict()['path'])
if 'morphocut' in project_path and app.config['DATA_DIRECTORY'] in project_path:
print('removing project with id {}'.format(project_id))
if os.path.exists(project_path):
@@ -519,8 +526,8 @@ def get_running_task_dicts(tasks):
for task in tasks:
print(json.loads(task.meta))
job = Job.fetch(task.id, connection=redis_conn)
- project = connection.execute(select([sqlalchemy.text(
- '*')]).select_from(models.projects).where(models.projects.c.project_id == task.project_id)).first()
+ project = connection.execute(select(sqlalchemy.text(
+ '*')).select_from(models.projects).where(models.projects.c.project_id == task.project_id)).first()
task_dict = dict(id=task.id, name=task.name, description=task.description,
complete=task.complete, result=task.result, progress=task.get_progress(), project_id=task.project_id)
task_dict['meta'] = json.loads(
@@ -532,7 +539,7 @@ def get_running_task_dicts(tasks):
# task_dict['meta']['scheduled_at'])
# print('scheduled_at: {}'.format(task_dict['started_at']))
if project:
- task_dict['project_name'] = project['name']
+ task_dict['project_name'] = project[1]
running_task_dicts.append(task_dict)
return running_task_dicts
@@ -561,10 +568,10 @@ def get_finished_task_dicts(tasks):
task_dict['meta'] = json.loads(
task.meta) if task.meta is not None else {}
finished_task_dicts.append(task_dict)
- project = connection.execute(select([sqlalchemy.text(
- '*')]).select_from(models.projects).where(models.projects.c.project_id == task.project_id)).first()
+ project = connection.execute(select(sqlalchemy.text(
+ '*')).select_from(models.projects).where(models.projects.c.project_id == task.project_id)).first()
if project:
- task_dict['project_name'] = project['name']
+ task_dict['project_name'] = project[1]
except Exception as err:
print('exception in api.get_finished_task_dicts')
print(err)
@@ -590,12 +597,12 @@ def process_project(project_id, params):
app = flask.current_app
with database.engine.begin() as connection:
result = connection.execute(select(
- [models.projects.c.path])
+ models.projects.c.path)
.select_from(models.projects)
.where(models.projects.c.project_id == project_id))
r = result.fetchone()
if (r is not None):
- rel_project_path = r['path']
+ rel_project_path = r._asdict()['path']
abs_project_path = os.path.join(
app.root_path, app.config['DATA_DIRECTORY'], rel_project_path)
export_filename = 'ecotaxa_segmentation_{:%Y_%m_%d}_{}.zip'.format(
@@ -641,6 +648,7 @@ def process_and_zip(import_path, export_path, params=None):
return export_path
+@login_required
def get_projects():
"""Get the projects belonging to the current user.
@@ -650,16 +658,28 @@ def get_projects():
The projects belonging to the current user.
"""
+ print("Access token received")
+ print("get_projects called, current_user ID:", current_user.get_id()) # Add this line
+
if current_user.get_id() is None:
return
with database.engine.begin() as connection:
- result = connection.execute(select(
- [models.projects.c.project_id, models.projects.c.name, models.projects.c.path, models.projects.c.creation_date, models.projects.c.user_id, func.count(models.objects.c.object_id).label('object_count')])
+ result = connection.execute(
+ select(
+ models.projects.c.project_id,
+ models.projects.c.name,
+ models.projects.c.path,
+ models.projects.c.creation_date,
+ models.projects.c.user_id,
+ func.count(models.objects.c.object_id).label('object_count')
+ )
.select_from(models.projects.outerjoin(models.objects))
.where(and_(models.projects.c.active == True, models.projects.c.user_id == current_user.id))
.group_by(models.projects.c.project_id)
- .order_by(models.projects.c.project_id))
- projects = [dict(row) for row in result]
+ .order_by(models.projects.c.project_id)
+ )
+ projects = [row._asdict() for row in result]
+ print("Fetched projects:", projects) # Add this line
for project in projects:
user = models.User.query.filter_by(
id=project['user_id']).first()
@@ -684,26 +704,28 @@ def get_project_files(id):
"""
with database.engine.begin() as connection:
result = connection.execute(select(
- [models.objects.c.filename, models.objects.c.object_id, models.objects.c.modification_date, models.objects.c.creation_date])
+ models.objects.c.filename, models.objects.c.object_id, models.objects.c.modification_date, models.objects.c.creation_date)
.select_from(models.objects)
.where(models.objects.c.project_id == id))
+ print(f'Query result for project_id {id}: {result}')
project = connection.execute(select(
- [models.projects.c.path])
+ models.projects.c.path)
.select_from(models.projects)
.where(models.projects.c.project_id == id))
r = project.fetchone()
project = ''
if (r is not None):
- project_path = r['path']
- return [dict(filename=row['filename'],
- object_id=row['object_id'],
- modification_date=row['modification_date'],
- creation_date=row['creation_date'],
+ project_path = r._asdict()['path']
+ objects = [dict(filename=row._asdict()['filename'],
+ object_id=row._asdict()['object_id'],
+ modification_date=row._asdict()['modification_date'],
+ creation_date=row._asdict()['creation_date'],
filepath=url_for(
- 'data', path=os.path.join(project_path, row['filename']))
- )
-
- for row in result]
+ 'data', path=os.path.join(project_path, row._asdict()['filename']))
+ )
+ for row in result]
+ print(f'Objects for project_id {id}: {objects}')
+ return objects
def get_project(id):
@@ -722,12 +744,12 @@ def get_project(id):
"""
with database.engine.begin() as connection:
result = connection.execute(select(
- [sqlalchemy.text('*')])
+ sqlalchemy.text('*'))
.select_from(models.projects)
.where(models.projects.c.project_id == id))
row = result.fetchone()
if (row is not None):
- return dict(row)
+ return row._asdict()
return
@@ -748,7 +770,6 @@ def add_project(project):
try_insert_or_update(models.projects.insert(), # pylint: disable=no-value-for-parameter
[dict(
name=project['name'], path=project['name'], active=True, user_id=current_user.id)])
- return
def add_object(_object):
@@ -769,6 +790,7 @@ def add_object(_object):
models.objects.insert(), # pylint: disable=no-value-for-parameter
[dict(
project_id=_object['project_id'], filename=_object['filename'])])
+ print(f'Object added: {_object}')
def try_insert_or_update(insert_function, data):
diff --git a/morphocut_server/frontend/package-lock.json b/morphocut_server/frontend/package-lock.json
index 76b2cfe..c924c14 100644
--- a/morphocut_server/frontend/package-lock.json
+++ b/morphocut_server/frontend/package-lock.json
@@ -1137,15 +1137,6 @@
"integrity": "sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q==",
"dev": true
},
- "@types/mini-css-extract-plugin": {
- "version": "0.9.1",
- "resolved": "https://registry.npmjs.org/@types/mini-css-extract-plugin/-/mini-css-extract-plugin-0.9.1.tgz",
- "integrity": "sha512-+mN04Oszdz9tGjUP/c1ReVwJXxSniLd7lF++sv+8dkABxVNthg6uccei+4ssKxRHGoMmPxdn7uBdJWONSJGTGQ==",
- "dev": true,
- "requires": {
- "@types/webpack": "*"
- }
- },
"@types/minimatch": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
@@ -1889,6 +1880,12 @@
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
"dev": true
},
+ "big.js": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
+ "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==",
+ "dev": true
+ },
"browserslist": {
"version": "4.13.0",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.13.0.tgz",
@@ -1972,6 +1969,21 @@
"integrity": "sha512-sJAofoarcm76ZGpuooaO0eDy8saEy+YoZBLjC4h8srt4jeBnkYeOgqxgsJQTpyt2LjI5PTfLJHSL+41Yu4fEJA==",
"dev": true
},
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
"debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
@@ -1987,6 +1999,12 @@
"integrity": "sha512-WDM5AAQdOrvLqSX8g3Zd5AujBXfMxf96oeZkff0U2HF5op3tjShE+on2yay3r1UD4M9I3p0iHpAS4+yV8U8A9A==",
"dev": true
},
+ "emojis-list": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
+ "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==",
+ "dev": true
+ },
"execa": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
@@ -2070,6 +2088,12 @@
"har-schema": "^2.0.0"
}
},
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true
+ },
"ignore": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
@@ -2082,6 +2106,23 @@
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
"dev": true
},
+ "json5": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "dev": true
+ },
+ "loader-utils": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
+ "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
+ "dev": true,
+ "requires": {
+ "big.js": "^5.2.2",
+ "emojis-list": "^3.0.0",
+ "json5": "^2.1.2"
+ }
+ },
"locate-path": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
@@ -2302,6 +2343,47 @@
"punycode": "^2.1.1"
}
},
+ "vue-loader-v16": {
+ "version": "npm:vue-loader@16.8.3",
+ "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.8.3.tgz",
+ "integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
+ "dev": true,
+ "requires": {
+ "chalk": "^4.1.0",
+ "hash-sum": "^2.0.0",
+ "loader-utils": "^2.0.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
+ }
+ },
"webpack-sources": {
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz",
@@ -13310,110 +13392,6 @@
}
}
},
- "vue-loader-v16": {
- "version": "npm:vue-loader@16.0.0-beta.7",
- "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.0.0-beta.7.tgz",
- "integrity": "sha512-xQ8/GZmRPdQ3EinnE0IXwdVoDzh7Dowo0MowoyBuScEBXrRabw6At5/IdtD3waKklKW5PGokPsm8KRN6rvQ1cw==",
- "dev": true,
- "requires": {
- "@types/mini-css-extract-plugin": "^0.9.1",
- "chalk": "^3.0.0",
- "hash-sum": "^2.0.0",
- "loader-utils": "^1.2.3",
- "merge-source-map": "^1.1.0",
- "source-map": "^0.6.1"
- },
- "dependencies": {
- "ansi-styles": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
- "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
- "dev": true,
- "requires": {
- "@types/color-name": "^1.1.1",
- "color-convert": "^2.0.1"
- }
- },
- "big.js": {
- "version": "5.2.2",
- "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
- "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==",
- "dev": true
- },
- "chalk": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
- "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
- "dev": true,
- "requires": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- }
- },
- "color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "dev": true,
- "requires": {
- "color-name": "~1.1.4"
- }
- },
- "color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "dev": true
- },
- "emojis-list": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
- "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==",
- "dev": true
- },
- "has-flag": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
- "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
- "dev": true
- },
- "json5": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
- "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
- "dev": true,
- "requires": {
- "minimist": "^1.2.0"
- }
- },
- "loader-utils": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz",
- "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==",
- "dev": true,
- "requires": {
- "big.js": "^5.2.2",
- "emojis-list": "^3.0.0",
- "json5": "^1.0.1"
- }
- },
- "source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true
- },
- "supports-color": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
- "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
- "dev": true,
- "requires": {
- "has-flag": "^4.0.0"
- }
- }
- }
- },
"vue-multiselect": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/vue-multiselect/-/vue-multiselect-2.1.4.tgz",
diff --git a/morphocut_server/frontend/src/App.vue b/morphocut_server/frontend/src/App.vue
index d871e18..3faa239 100644
--- a/morphocut_server/frontend/src/App.vue
+++ b/morphocut_server/frontend/src/App.vue
@@ -31,7 +31,7 @@
Change password
-
+
Logout
@@ -68,7 +68,12 @@ export default {
methods: {
logout() {
const path = "/api/logout";
- axios.get(path);
+ console.log("Logging out, path: " + path); // Add this line
+ axios.get(path).then(() => {
+ localStorage.removeItem('user_id');
+ this.user = {}; // Clear the user data
+ this.$router.push('/login'); // Redirect to the login page
+ });
},
getCurrentUser() {
const path = "/api/users/current";
diff --git a/morphocut_server/frontend/src/components/Login.vue b/morphocut_server/frontend/src/components/Login.vue
new file mode 100644
index 0000000..296d70c
--- /dev/null
+++ b/morphocut_server/frontend/src/components/Login.vue
@@ -0,0 +1,75 @@
+
+
+
Login
+
+
+
+
+
+
+
+
+
+ Login
+ {{ errorMessage }}
+
+
+
+
+
diff --git a/morphocut_server/frontend/src/router.js b/morphocut_server/frontend/src/router.js
index 7c9ab33..f25851f 100644
--- a/morphocut_server/frontend/src/router.js
+++ b/morphocut_server/frontend/src/router.js
@@ -5,6 +5,7 @@ import Upload from '@/components/Upload';
import Tasks from '@/components/Tasks';
import Project from '@/components/Project';
import Projects from '@/components/Projects';
+import Login from '@/components/Login.vue';
import Accounts from '@/components/Accounts';
import Landing from '@/components/Landing';
import Imprint from '@/components/Imprint';
@@ -70,5 +71,10 @@ export default new Router({
name: 'Imprint',
component: Imprint,
},
+ {
+ path: '/login',
+ name: 'login',
+ component: Login
+ },
]
})
\ No newline at end of file
diff --git a/morphocut_server/morphocut.py b/morphocut_server/morphocut.py
index 149a6c9..4cdb252 100644
--- a/morphocut_server/morphocut.py
+++ b/morphocut_server/morphocut.py
@@ -14,13 +14,13 @@
import datetime
from flask import (Flask, Response, abort, redirect, render_template, request,
- url_for, current_app)
+ url_for, current_app, make_response)
from flask_cors import CORS
from flask import jsonify
from flask.helpers import send_from_directory
from flask.blueprints import Blueprint
from flask_user import current_user, login_required, roles_required, UserManager, UserMixin
-from flask_login import logout_user, LoginManager
+from flask_login import logout_user, LoginManager, login_user
import sqlalchemy
from sqlalchemy import func
@@ -150,6 +150,8 @@ def add_user_to_database(email, password, admin):
)
database.session.add(user) # pylint: disable=no-member
database.session.commit() # pylint: disable=no-member
+ app.logger.info(f"User with email {email} added successfully.")
+ app.logger.info(user)
if admin:
check_admin_role()
@@ -158,6 +160,7 @@ def add_user_to_database(email, password, admin):
user_role = models.UserRoles(user_id=user.id, role_id=role.id)
database.session.add(user_role) # pylint: disable=no-member
database.session.commit() # pylint: disable=no-member
+ app.logger.info(f"User with email {email} granted admin role.")
def check_admin_role():
@@ -204,25 +207,49 @@ def imprint():
return redirect(url_for("frontend.imprint"))
-@app.route("/login")
-@login_required
+@app.route('/api/login', methods=['POST'])
def login():
- """Redirects index requests to the frontend index page.
-
- """
- print('login request')
-
- return redirect(url_for("frontend.routes"))
-
-
-@app.route("/logout")
+ # data = request.get_json()
+ # user = models.User.query.filter_by(email=data['email']).first()
+ #
+ # if user and user_manager.verify_password(data['password'], user.password):
+ # login_user(user)
+ #
+ # # Create a response with the access token as a cookie
+ # response = make_response(jsonify({'status': 'success', 'message': 'Logged in successfully'}))
+ # response.headers['X-User-Id'] = user.id
+ #
+ # return response
+ # else:
+ # return jsonify({'status': 'error', 'message': 'Invalid email or password'})
+
+ data = request.get_json()
+ user = models.User.query.filter_by(email=data['email']).first()
+
+ if user and user_manager.verify_password(data['password'], user.password):
+ login_user(user)
+
+ return jsonify({
+ 'status': 'success',
+ 'message': 'Logged in successfully',
+ 'user_id': user.id
+ })
+ else:
+ return jsonify({
+ 'status': 'error',
+ 'message': 'Invalid email or password'
+ })
+
+
+@app.route("/api/logout", methods=["GET"])
@login_required
def logout():
- """Logs out the current user and redirects to the index page.
-
- """
+ """Logs out the current user and redirects to the index page."""
logout_user()
- return redirect(url_for("index"))
+ return jsonify({
+ 'status': 'success',
+ 'message': 'Logged out successfully'
+ })
@app.route("/data/")
diff --git a/morphocut_server/tasks.py b/morphocut_server/tasks.py
index 9967d1d..f526e5f 100644
--- a/morphocut_server/tasks.py
+++ b/morphocut_server/tasks.py
@@ -19,10 +19,10 @@ def launch_task(name, description, *args, **kwargs):
`tasks.launch_task` will be removed soon, it is replaced by User.launch_task
`tasks.write_result` will be removed soon, it is replaced by User.launch_task
'''
- execute_and_save(name, description, 0, 0, *args, **kwargs)
+ execute_task_and_save_result(name, description, 0, 0, *args, **kwargs)
task, rq_job = current_user.launch_task(name, description, *args, **kwargs)
- database.session.commit() # pylint: disable=no-member
+ database.session.commit()
rq_job.meta['enqueued_at'] = datetime.datetime.now()