Skip to content

Commit

Permalink
WIP dirty - user access, secure API
Browse files Browse the repository at this point in the history
  • Loading branch information
eboileau committed Mar 8, 2024
1 parent 99f0792 commit 3f7907d
Show file tree
Hide file tree
Showing 12 changed files with 159 additions and 27 deletions.
4 changes: 4 additions & 0 deletions client/src/components/layout/NavigationBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,9 @@
<RouterLink :to="{ name: 'documentation' }">
<span>Documentation</span>
</RouterLink>

<RouterLink :to="{ name: 'access' }">
<span>User</span>
</RouterLink>
</nav>
</template>
6 changes: 6 additions & 0 deletions client/src/router/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down Expand Up @@ -41,6 +42,11 @@ const router = createRouter({
name: 'documentation',
component: DocumentationView
},
{
path: '/',
name: 'access',
component: AccessView
},
{
path: '/',
name: 'roadmap',
Expand Down
54 changes: 52 additions & 2 deletions client/src/services/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
45 changes: 45 additions & 0 deletions client/src/views/AccessView.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<script setup>
import { ref } from 'vue'
import { useAccessToken } from '@/utils/AccessToken.js'
import { HTTPSecure } from '@/services'
const accessToken = useAccessToken()
// cannot call accessToken.get() if not defined this results in error...
const headers = { Authorization: `Bearer ${accessToken.access_token}` }
// there must be a nicer way to set the Authorization directly using the HTTPSecure config
// does this overwrite the config?
// passing headers with null token results in 422 'Not enough segments'...
const user = ref()
const testlogin = () => {
HTTPSecure.get('/access/testlogin', { headers })
.then((response) => {
user.value = response.data
})
.catch((err) => {
console.log(err.response.status)
// on error what to do
})
}
</script>

<template>
<DefaultLayout>
<SectionLayout>
<div class="flex">
<Button
@click="testlogin()"
type="button"
size="small"
icon="pi pi-eye"
label="Check it!"
/>
</div>
<div class="mt-4">
<p>USER IS : {{ user }}</p>
</div>
</SectionLayout>
</DefaultLayout>
</template>
8 changes: 0 additions & 8 deletions server/src/scimodom/api/__init__.py
Original file line number Diff line number Diff line change
@@ -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
18 changes: 18 additions & 0 deletions server/src/scimodom/api/access.py
Original file line number Diff line number Diff line change
@@ -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
5 changes: 3 additions & 2 deletions server/src/scimodom/api/public.py
Original file line number Diff line number Diff line change
@@ -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,
Expand Down Expand Up @@ -34,6 +33,8 @@
from scimodom.utils.operations import get_op
import scimodom.utils.specifications as specs

api = Blueprint("api", __name__)

FEATURES = sorted(
list(
{
Expand Down
11 changes: 0 additions & 11 deletions server/src/scimodom/api/secure.py

This file was deleted.

16 changes: 16 additions & 0 deletions server/src/scimodom/api/upload.py
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion server/src/scimodom/api/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"])
Expand Down
13 changes: 11 additions & 2 deletions server/src/scimodom/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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():
Expand All @@ -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)
Expand Down
4 changes: 3 additions & 1 deletion server/src/scimodom/utils/url_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down

0 comments on commit 3f7907d

Please sign in to comment.