From 3f7907da0c7eca34ed033b914339d485208c06db Mon Sep 17 00:00:00 2001 From: Etienne Boileau Date: Fri, 8 Mar 2024 18:09:47 +0100 Subject: [PATCH] WIP dirty - user access, secure API --- .../src/components/layout/NavigationBar.vue | 4 ++ client/src/router/index.js | 6 +++ client/src/services/index.js | 54 ++++++++++++++++++- client/src/views/AccessView.vue | 45 ++++++++++++++++ server/src/scimodom/api/__init__.py | 8 --- server/src/scimodom/api/access.py | 18 +++++++ server/src/scimodom/api/public.py | 5 +- server/src/scimodom/api/secure.py | 11 ---- server/src/scimodom/api/upload.py | 16 ++++++ server/src/scimodom/api/user.py | 2 +- server/src/scimodom/app.py | 13 ++++- server/src/scimodom/utils/url_routes.py | 4 +- 12 files changed, 159 insertions(+), 27 deletions(-) create mode 100644 client/src/views/AccessView.vue create mode 100644 server/src/scimodom/api/access.py delete mode 100644 server/src/scimodom/api/secure.py create mode 100644 server/src/scimodom/api/upload.py diff --git a/client/src/components/layout/NavigationBar.vue b/client/src/components/layout/NavigationBar.vue index 0eb5ab04..846cda71 100644 --- a/client/src/components/layout/NavigationBar.vue +++ b/client/src/components/layout/NavigationBar.vue @@ -19,5 +19,9 @@ Documentation + + + User + diff --git a/client/src/router/index.js b/client/src/router/index.js index 364320f3..39381f56 100644 --- a/client/src/router/index.js +++ b/client/src/router/index.js @@ -5,6 +5,7 @@ import BrowseView from '@/views/BrowseView.vue' import CompareView from '@/views/CompareView.vue' import DownloadView from '@/views/DownloadView.vue' import DocumentationView from '@/views/DocumentationView.vue' +import AccessView from '@/views/AccessView.vue' import HomeRoadmap from '@/components/home/HomeRoadmap.vue' const router = createRouter({ @@ -41,6 +42,11 @@ const router = createRouter({ name: 'documentation', component: DocumentationView }, + { + path: '/', + name: 'access', + component: AccessView + }, { path: '/', name: 'roadmap', diff --git a/client/src/services/index.js b/client/src/services/index.js index 9b9b181d..d6751bb3 100644 --- a/client/src/services/index.js +++ b/client/src/services/index.js @@ -4,12 +4,62 @@ import { API_BASE_URL } from '/config.js?url' // TODO: refactor HTTP as HTTPPublic either export service, or // rename exported functions +// const HTTPSecure = { +// connection: null, +// get: (url) => { +// this.init() +// this.connection.get(url) +// }, +// init: () => { +// if ( this.connection !== null ) { +// return +// } +// this.connection = +// } +// } + const HTTPSecure = axios.create({ baseURL: API_BASE_URL, - withCredentials: true, - xsrfCookieName: 'csrf_access_token' + withCredentials: false + // default xsrfCookieName: 'XSRF-TOKEN' }) +// this dosn't work getActivePinia() was called but there was no active Pinia +// HTTPSecure.interceptors.request.use( +// (config) => { +// const token = accessToken.access_token +// const auth = token ? `Bearer ${token}` : '' +// config.headers.common['Authorization'] = auth +// return config +// }, +// (error) => Promise.reject(error), +// ) + +HTTPSecure.interceptors.response.use( + (response) => { + // 2xx + return response + }, + (error) => { + // outside 2xx + switch (error.response.status) { + case 401: + // jwt refresh needed - check COOKIE_EXPIRED_MSG = 'Token has expired' + // HTTPSecure.defaults.xsrfCookieName = 'csrf_refresh_token' + // here call api to refresh token + // HTTPSecure.defaults.xsrfCookieName = 'csrf_access_token' + // return HTTPSecure(error.config) + break + case 404: + // router push to 404 + break + default: + break + } + return Promise.reject(error) + } +) + const HTTP = axios.create({ baseURL: API_BASE_URL, withCredentials: false, diff --git a/client/src/views/AccessView.vue b/client/src/views/AccessView.vue new file mode 100644 index 00000000..c0170e3b --- /dev/null +++ b/client/src/views/AccessView.vue @@ -0,0 +1,45 @@ + + + diff --git a/server/src/scimodom/api/__init__.py b/server/src/scimodom/api/__init__.py index c3712b8c..e69de29b 100644 --- a/server/src/scimodom/api/__init__.py +++ b/server/src/scimodom/api/__init__.py @@ -1,8 +0,0 @@ -from flask import Blueprint - -api = Blueprint("api", __name__) - -# E402 module level import not at top of file -from . import public -from . import secure -from . import authorisation diff --git a/server/src/scimodom/api/access.py b/server/src/scimodom/api/access.py new file mode 100644 index 00000000..0a4b0efd --- /dev/null +++ b/server/src/scimodom/api/access.py @@ -0,0 +1,18 @@ +import logging + +from flask import Blueprint, request, jsonify +from flask_cors import cross_origin +from flask_jwt_extended import jwt_required, get_jwt_identity + +logger = logging.getLogger(__name__) + +access_api = Blueprint("access_api", __name__) + + +@access_api.route("/testlogin", methods=["GET"]) +@cross_origin(supports_credentials=True) +@jwt_required() +def testlogin(): + # Access the identity of the current user with get_jwt_identity + current_user = get_jwt_identity() + return jsonify(logged_in_as=current_user), 200 diff --git a/server/src/scimodom/api/public.py b/server/src/scimodom/api/public.py index 4712d53f..6e0f5185 100644 --- a/server/src/scimodom/api/public.py +++ b/server/src/scimodom/api/public.py @@ -1,11 +1,10 @@ import os from pathlib import Path -from flask import request +from flask import Blueprint, request from flask_cors import cross_origin from sqlalchemy import select, func -from . import api from scimodom.database.database import get_session from scimodom.database.models import ( Annotation, @@ -34,6 +33,8 @@ from scimodom.utils.operations import get_op import scimodom.utils.specifications as specs +api = Blueprint("api", __name__) + FEATURES = sorted( list( { diff --git a/server/src/scimodom/api/secure.py b/server/src/scimodom/api/secure.py deleted file mode 100644 index 7f8aab59..00000000 --- a/server/src/scimodom/api/secure.py +++ /dev/null @@ -1,11 +0,0 @@ -from flask import request - -# from flask_jwt_extended import jwt_required - -from . import api - - -@api.route("/secure", methods=["GET"]) -# @jwt_required -def secured_endpoint(): - pass diff --git a/server/src/scimodom/api/upload.py b/server/src/scimodom/api/upload.py new file mode 100644 index 00000000..bab09ba0 --- /dev/null +++ b/server/src/scimodom/api/upload.py @@ -0,0 +1,16 @@ +import logging + +from flask import Blueprint, request, jsonify +from flask_cors import cross_origin +from flask_jwt_extended import jwt_required, get_jwt_identity + +logger = logging.getLogger(__name__) + +upload_api = Blueprint("upload_api", __name__) + + +@upload_api.route("/upload", methods=["GET"]) +@cross_origin(supports_credentials=True) +@jwt_required() +def secure_endpoint(): + pass diff --git a/server/src/scimodom/api/user.py b/server/src/scimodom/api/user.py index 3e5935f7..02645cd9 100644 --- a/server/src/scimodom/api/user.py +++ b/server/src/scimodom/api/user.py @@ -13,7 +13,7 @@ logger = logging.getLogger(__name__) -user_api = Blueprint("api_user", __name__) +user_api = Blueprint("user_api", __name__) @user_api.route("/register_user", methods=["POST"]) diff --git a/server/src/scimodom/app.py b/server/src/scimodom/app.py index 549d8418..fc4a2b8c 100644 --- a/server/src/scimodom/app.py +++ b/server/src/scimodom/app.py @@ -5,8 +5,10 @@ from flask_jwt_extended import JWTManager from sqlalchemy.orm import scoped_session -from scimodom.api import api +from scimodom.api.public import api from scimodom.api.user import user_api +from scimodom.api.access import access_api +from scimodom.api.upload import upload_api from scimodom.app_singleton import create_app_singleton from scimodom.database.database import make_session, init from scimodom.frontend import frontend @@ -18,7 +20,12 @@ add_all, validate_dataset_title, ) -from scimodom.utils.url_routes import API_PREFIX, USER_API_ROUTE +from scimodom.utils.url_routes import ( + API_PREFIX, + USER_API_ROUTE, + UPLOAD_API_ROUTE, + ACCESS_API_ROUTE, +) def create_app(): @@ -37,6 +44,8 @@ def create_app(): app.register_blueprint(api, url_prefix=f"/{API_PREFIX}") app.register_blueprint(user_api, url_prefix=USER_API_ROUTE) + app.register_blueprint(access_api, url_prefix=ACCESS_API_ROUTE) + app.register_blueprint(upload_api, url_prefix=UPLOAD_API_ROUTE) app.register_blueprint(frontend, url_prefix="/") jwt = JWTManager(app) diff --git a/server/src/scimodom/utils/url_routes.py b/server/src/scimodom/utils/url_routes.py index f9783dec..fd559d7f 100644 --- a/server/src/scimodom/utils/url_routes.py +++ b/server/src/scimodom/utils/url_routes.py @@ -4,8 +4,10 @@ API_PREFIX = "api/v0" # must fit with client/public/config.js - USER_API_ROUTE = f"/{API_PREFIX}/user" +ACCESS_API_ROUTE = f"/{API_PREFIX}/access" +UPLOAD_API_ROUTE = f"/{API_PREFIX}/upload" + CONFIRM_USER_REGISTRATION_URI = "confirm_user_registration" REQUEST_PASSWORD_RESET_URI = "request_password_reset"