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 @@ + + + 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()