From 9d9f95f99d237a176bc9a1bbf4e00d9721079c05 Mon Sep 17 00:00:00 2001 From: Philipp Rothmann Date: Wed, 2 Nov 2022 11:32:26 +0100 Subject: [PATCH 01/10] revert auth.py --- backend/areas/auth/auth.py | 41 +++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/backend/areas/auth/auth.py b/backend/areas/auth/auth.py index 4e96088..c972752 100644 --- a/backend/areas/auth/auth.py +++ b/backend/areas/auth/auth.py @@ -30,39 +30,38 @@ def hydra_callback(): token = HydraOauth.get_token(state, code) user_info = HydraOauth.get_user_info() # Match Kratos identity with Hydra - # identities = KratosApi.get("/identities") - # identity = None - # for i in identities.json(): - # if i["traits"]["email"] == user_info["email"]: - # identity = i + identities = KratosApi.get("/identities") + identity = None + for i in identities.json(): + if i["traits"]["email"] == user_info["email"]: + identity = i access_token = create_access_token( - identity=token, expires_delta=timedelta(days=365), - #additional_claims={"user_id": identity["id"]} + identity=token, expires_delta=timedelta(days=365), additional_claims={"user_id": identity["id"]} ) - # apps = App.query.all() - # app_roles = [] - # for app in apps: - # tmp_app_role = AppRole.query.filter_by( - # user_id=identity["id"], app_id=app.id - # ).first() - # app_roles.append( - # { - # "name": app.slug, - # "role_id": tmp_app_role.role_id if tmp_app_role else None, - # } - # ) + apps = App.query.all() + app_roles = [] + for app in apps: + tmp_app_role = AppRole.query.filter_by( + user_id=identity["id"], app_id=app.id + ).first() + app_roles.append( + { + "name": app.slug, + "role_id": tmp_app_role.role_id if tmp_app_role else None, + } + ) return jsonify( { "accessToken": access_token, "userInfo": { - "id": user_info["email"], + "id": identity["id"], "email": user_info["email"], "name": user_info["name"], "preferredUsername": user_info["preferred_username"], - # "app_roles": app_roles, + "app_roles": app_roles, }, } ) -- 2.45.2 From d8f7fa36e19e26fa2260ff203c9551ed459c52b6 Mon Sep 17 00:00:00 2001 From: Philipp Rothmann Date: Wed, 2 Nov 2022 11:53:42 +0100 Subject: [PATCH 02/10] make logout redirect a env var --- public/env.js | 1 + src/components/Header/HeaderLIT.tsx | 8 +++----- src/services/auth/redux/actions.ts | 5 +++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/public/env.js b/public/env.js index d47bfbb..1421897 100644 --- a/public/env.js +++ b/public/env.js @@ -1,3 +1,4 @@ window.env = { REACT_APP_API_URL: 'http://localhost:5000/api/v1', + REACT_APP_SSO_LOGOUT_URL: 'https://login.example.org/if/flow/default-invalidation-flow/' }; diff --git a/src/components/Header/HeaderLIT.tsx b/src/components/Header/HeaderLIT.tsx index d385158..a1f725d 100644 --- a/src/components/Header/HeaderLIT.tsx +++ b/src/components/Header/HeaderLIT.tsx @@ -10,7 +10,8 @@ import _ from 'lodash'; import { UserModal } from '../UserModal'; -const HYDRA_LOGOUT_URL = `${process.env.REACT_APP_HYDRA_PUBLIC_URL}/oauth2/sessions/logout`; +// @ts-ignore +const HYDRA_LOGOUT_URL = window.env.REACT_APP_SSO_LOGOUT_URL; const navigation = [ { name: 'Dashboard', to: '/dashboard', requiresAdmin: false }, @@ -56,10 +57,7 @@ const HeaderLIT: React.FC = () => { const signOutUrl = useMemo(() => { const { hostname } = window.location; // If we are developing locally, we need to use the init cluster's public URL - if (hostname === 'localhost') { - return HYDRA_LOGOUT_URL; - } - return `https://${hostname.replace(/^dashboard/, 'sso')}/oauth2/sessions/logout`; + return HYDRA_LOGOUT_URL; }, []); return ( diff --git a/src/services/auth/redux/actions.ts b/src/services/auth/redux/actions.ts index cde2b8e..6d746ca 100644 --- a/src/services/auth/redux/actions.ts +++ b/src/services/auth/redux/actions.ts @@ -1,4 +1,5 @@ -import { createApiAction } from 'src/services/api'; +import axios from 'axios'; +import { createApiAction, createApiCall, performApiCall } from 'src/services/api'; import { SuccessAction } from 'src/services/api/redux/types'; export enum AuthActionTypes { @@ -26,7 +27,7 @@ export const signIn = (params: string) => ); export function signOut() { - return (dispatch: any) => { + return async (dispatch: any) => { dispatch(signOutAction()); }; } -- 2.45.2 From 6607c8a16866a490c61c40c63e2805c317cbc5b9 Mon Sep 17 00:00:00 2001 From: Philipp Rothmann Date: Wed, 2 Nov 2022 11:54:24 +0100 Subject: [PATCH 03/10] use tags in makefile --- Makefile | 7 ++++--- backend/Makefile | 5 ++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index a6ea880..2dc391c 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,10 @@ +tag = "$$(git describe --tags)" + build: $(MAKE) -C backend build - docker push yksflip/dashboard-backend:latest docker build -t dashboard . - docker tag dashboard yksflip/dashboard:latest - docker push yksflip/dashboard:latest + docker tag dashboard yksflip/dashboard:$(tag) + docker push yksflip/dashboard:$(tag) rm: docker stack rm ${STACK_NAME} diff --git a/backend/Makefile b/backend/Makefile index 7b85e16..9ed036b 100644 --- a/backend/Makefile +++ b/backend/Makefile @@ -1,6 +1,9 @@ +tag = "$$(git describe --tags)" + build: docker build -t dashboard-backend . - docker tag dashboard-backend yksflip/dashboard-backend:latest + docker tag dashboard-backend yksflip/dashboard-backend:$(tag) + docker push yksflip/dashboard-backend:$(tag) clean: rm database.db -- 2.45.2 From 7d302302d0ca55128f7fee40be17b78a8728e608 Mon Sep 17 00:00:00 2001 From: Philipp Rothmann Date: Wed, 2 Nov 2022 13:55:12 +0100 Subject: [PATCH 04/10] mock admin role --- backend/areas/apps/models_lit.py | 4 ++-- backend/areas/auth/lit_auth.py | 21 ++++++++++++--------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/backend/areas/apps/models_lit.py b/backend/areas/apps/models_lit.py index 1132970..63ee487 100644 --- a/backend/areas/apps/models_lit.py +++ b/backend/areas/apps/models_lit.py @@ -1,7 +1,7 @@ """Everything to do with Apps""" from database import db -from .models import App +from .models import App, AppRole class LITApp(App): """ @@ -29,4 +29,4 @@ class LITApp(App): "installed": "", "ready": "", "message": "", - } + } \ No newline at end of file diff --git a/backend/areas/auth/lit_auth.py b/backend/areas/auth/lit_auth.py index f804690..018b507 100644 --- a/backend/areas/auth/lit_auth.py +++ b/backend/areas/auth/lit_auth.py @@ -30,17 +30,21 @@ def hydra_callback(): token = HydraOauth.get_token(state, code) user_info = HydraOauth.get_user_info() - access_token = create_access_token( - identity=token, expires_delta=timedelta(days=365), - #additional_claims={"user_id": identity["id"]} - ) + identity=token, expires_delta=timedelta(days=365)) + isAdmin = "admin" in user_info["groups"] + app_roles = [ + { + "name": "dashboard", + "role_id": 1 if isAdmin else 2 + }, + ] + print(app_roles) # apps = App.query.all() - # app_roles = [] # for app in apps: # tmp_app_role = AppRole.query.filter_by( - # user_id=identity["id"], app_id=app.id + # user_id=user_info["sub"], app_id=app.id # ).first() # app_roles.append( # { @@ -48,7 +52,6 @@ def hydra_callback(): # "role_id": tmp_app_role.role_id if tmp_app_role else None, # } # ) - return jsonify( { "accessToken": access_token, @@ -57,7 +60,7 @@ def hydra_callback(): "email": user_info["email"], "name": user_info["name"], "preferredUsername": user_info["preferred_username"], - # "app_roles": app_roles, - }, + "app_roles": app_roles + } } ) -- 2.45.2 From 143ea888c8aa76b5279ad38cc5f1ab4132e17b24 Mon Sep 17 00:00:00 2001 From: Philipp Rothmann Date: Wed, 2 Nov 2022 14:00:22 +0100 Subject: [PATCH 05/10] readd admin views --- src/components/Header/HeaderLIT.tsx | 50 ++++++++++++---------------- src/services/auth/redux/actions.ts | 3 +- src/services/auth/redux/selectors.ts | 1 + 3 files changed, 23 insertions(+), 31 deletions(-) diff --git a/src/components/Header/HeaderLIT.tsx b/src/components/Header/HeaderLIT.tsx index a1f725d..e312314 100644 --- a/src/components/Header/HeaderLIT.tsx +++ b/src/components/Header/HeaderLIT.tsx @@ -1,4 +1,4 @@ -import React, { Fragment, useMemo, useState } from 'react'; +import React, { Fragment, useMemo } from 'react'; import { Disclosure, Menu, Transition } from '@headlessui/react'; import { MenuIcon, XIcon } from '@heroicons/react/outline'; import { useAuth } from 'src/services/auth'; @@ -6,15 +6,8 @@ import Gravatar from 'react-gravatar'; import { Link, useLocation } from 'react-router-dom'; import clsx from 'clsx'; import { useApps } from 'src/services/apps'; -import _ from 'lodash'; - -import { UserModal } from '../UserModal'; - -// @ts-ignore -const HYDRA_LOGOUT_URL = window.env.REACT_APP_SSO_LOGOUT_URL; const navigation = [ - { name: 'Dashboard', to: '/dashboard', requiresAdmin: false }, { name: 'Users', to: '/users', requiresAdmin: true }, { name: 'Apps', to: '/apps', requiresAdmin: true }, ]; @@ -35,29 +28,17 @@ function filterNavigationByDashboardRole(isAdmin: boolean) { interface HeaderProps {} const HeaderLIT: React.FC = () => { - const [currentUserModal, setCurrentUserModal] = useState(false); - const [currentUserId, setCurrentUserId] = useState(null); const { logOut, currentUser, isAdmin } = useAuth(); const { pathname } = useLocation(); - const { apps, loadApps, appTableLoading } = useApps(); - - const currentUserModalOpen = (id: any) => { - setCurrentUserId(id); - setCurrentUserModal(true); - }; - - const currentUserModalClose = () => { - setCurrentUserModal(false); - setCurrentUserId(null); - }; - + const { apps } = useApps(); const navigationItems = filterNavigationByDashboardRole(isAdmin); + console.log(isAdmin); + console.log(navigationItems); const signOutUrl = useMemo(() => { - const { hostname } = window.location; - // If we are developing locally, we need to use the init cluster's public URL - return HYDRA_LOGOUT_URL; + // @ts-ignore + return window.env.REACT_APP_SSO_LOGOUT_URL; }, []); return ( @@ -100,6 +81,21 @@ const HeaderLIT: React.FC = () => { {app.name} ))} + {navigationItems.map((item) => ( + + {item.name} + + ))}
@@ -165,10 +161,6 @@ const HeaderLIT: React.FC = () => {
)} - - {currentUserModal && ( - - )} ); }; diff --git a/src/services/auth/redux/actions.ts b/src/services/auth/redux/actions.ts index 6d746ca..0988311 100644 --- a/src/services/auth/redux/actions.ts +++ b/src/services/auth/redux/actions.ts @@ -1,5 +1,4 @@ -import axios from 'axios'; -import { createApiAction, createApiCall, performApiCall } from 'src/services/api'; +import { createApiAction } from 'src/services/api'; import { SuccessAction } from 'src/services/api/redux/types'; export enum AuthActionTypes { diff --git a/src/services/auth/redux/selectors.ts b/src/services/auth/redux/selectors.ts index 0feaae5..55e1002 100644 --- a/src/services/auth/redux/selectors.ts +++ b/src/services/auth/redux/selectors.ts @@ -12,6 +12,7 @@ export const getCurrentUser = (state: State) => state.auth.userInfo; export const getIsAdmin = (state: State) => { // check since old users wont have this if (state.auth.userInfo) { + console.log(state.auth.userInfo); if (!state.auth.userInfo.app_roles) { return false; } -- 2.45.2 From 35a4f29f078e612f88c941e2e05705737c57a310 Mon Sep 17 00:00:00 2001 From: Philipp Rothmann Date: Tue, 8 Nov 2022 09:52:45 +0100 Subject: [PATCH 06/10] add authentik api get users --- backend/areas/apps/models_lit.py | 32 ---------------- backend/areas/auth/lit_auth.py | 23 +++-------- backend/areas/users/lit_user_service.py | 39 +++++++++++++++++++ backend/areas/users/models.py | 37 ++++++++++++++++++ backend/areas/users/users.py | 5 +-- backend/helpers/__init__.py | 1 + backend/helpers/auth_guard.py | 7 ++-- backend/helpers/authentik_api.py | 43 +++++++++++++++++++++ backend/helpers/error_handler.py | 2 + backend/helpers/hydra_oauth.py | 2 +- backend/helpers/kratos_api.py | 1 - backend/helpers/lit_oauth.py | 51 +++++++++++++++++++++++++ backend/requirements.txt | 28 ++++++++++---- backend/web/static/base.js | 6 +-- src/components/Header/HeaderLIT.tsx | 8 ++-- src/modules/users/Users.tsx | 16 ++++++-- src/services/auth/redux/actions.ts | 2 +- src/services/auth/redux/selectors.ts | 1 - 18 files changed, 223 insertions(+), 81 deletions(-) delete mode 100644 backend/areas/apps/models_lit.py create mode 100644 backend/areas/users/lit_user_service.py create mode 100644 backend/areas/users/models.py create mode 100644 backend/helpers/authentik_api.py create mode 100644 backend/helpers/lit_oauth.py diff --git a/backend/areas/apps/models_lit.py b/backend/areas/apps/models_lit.py deleted file mode 100644 index 63ee487..0000000 --- a/backend/areas/apps/models_lit.py +++ /dev/null @@ -1,32 +0,0 @@ -"""Everything to do with Apps""" - -from database import db -from .models import App, AppRole - -class LITApp(App): - """ - """ - - def get_url(self): - return self.url - - def to_dict(self): - """ - represent this object as a dict, compatible for JSON output - """ - return {"id": self.id, - "name": self.name, - "slug": self.slug, - "external": self.external, - "status": self.get_status(), - "url": self.get_url()} - - - - def get_status(self): - """Returns an AppStatus object that describes the current cluster state""" - return { - "installed": "", - "ready": "", - "message": "", - } \ No newline at end of file diff --git a/backend/areas/auth/lit_auth.py b/backend/areas/auth/lit_auth.py index 018b507..f99432c 100644 --- a/backend/areas/auth/lit_auth.py +++ b/backend/areas/auth/lit_auth.py @@ -5,15 +5,14 @@ from flask_cors import cross_origin from datetime import timedelta from areas import api_v1 -from areas.apps import App, AppRole from config import * -from helpers import HydraOauth, BadRequest +from helpers import LITOauth, BadRequest @api_v1.route("/login", methods=["POST"]) @cross_origin() def login(): - authorization_url = HydraOauth.authorize() + authorization_url = LITOauth.authorize() return jsonify({"authorizationUrl": authorization_url}) @@ -28,11 +27,10 @@ def hydra_callback(): if code == None: raise BadRequest("Missing code query param") - token = HydraOauth.get_token(state, code) - user_info = HydraOauth.get_user_info() + token = LITOauth.get_token(state, code) + user_info = LITOauth.get_user_info() access_token = create_access_token( identity=token, expires_delta=timedelta(days=365)) - isAdmin = "admin" in user_info["groups"] app_roles = [ { @@ -40,18 +38,7 @@ def hydra_callback(): "role_id": 1 if isAdmin else 2 }, ] - print(app_roles) - # apps = App.query.all() - # for app in apps: - # tmp_app_role = AppRole.query.filter_by( - # user_id=user_info["sub"], app_id=app.id - # ).first() - # app_roles.append( - # { - # "name": app.slug, - # "role_id": tmp_app_role.role_id if tmp_app_role else None, - # } - # ) + return jsonify( { "accessToken": access_token, diff --git a/backend/areas/users/lit_user_service.py b/backend/areas/users/lit_user_service.py new file mode 100644 index 0000000..c6b1581 --- /dev/null +++ b/backend/areas/users/lit_user_service.py @@ -0,0 +1,39 @@ +from flask import current_app +from helpers.authentik_api import AuthentikApi +from .user_service import UserService +from .models import User + + +class UserService(UserService): + @staticmethod + def get_users(): + user_list = [User.from_authentik(u).to_dict() for u in AuthentikApi.get("/core/users")] + return user_list + + @staticmethod + def get_user(id): + pass + + @staticmethod + def post_user(data): + pass + + @staticmethod + def __start_recovery_flow(email): + pass + + @staticmethod + def put_user(id, user_editing_id, data): + pass + + @staticmethod + def delete_user(id): + pass + + @staticmethod + def post_multiple_users(data): + pass + + @staticmethod + def __insertAppRoleToUser(userId, userRes): + pass diff --git a/backend/areas/users/models.py b/backend/areas/users/models.py new file mode 100644 index 0000000..70ace01 --- /dev/null +++ b/backend/areas/users/models.py @@ -0,0 +1,37 @@ + + +class User: + id = None + uuid = None + traits = None + email = None + name = None + preferredUsername = None + state = None + + def __init__(self): + pass + + @staticmethod + def from_authentik(authentik_user): + u = User() + u.id = authentik_user["pk"] + u.uuid = authentik_user["uid"] + u.name = authentik_user["name"] + u.email = authentik_user["email"] + u.traits = { + "name": authentik_user["name"], + "email": authentik_user["email"], + "app_roles": [] + } + u.preferredUsername = authentik_user["username"] + u.state = "active" if authentik_user["is_active"] else "" + return u + + def to_dict(self): + return { + "id": self.id, + "traits": self.traits, + "preferredUsername": self.preferredUsername, + "state": self.state, + } diff --git a/backend/areas/users/users.py b/backend/areas/users/users.py index 08f22c6..7e3cd81 100644 --- a/backend/areas/users/users.py +++ b/backend/areas/users/users.py @@ -8,7 +8,7 @@ from helpers import KratosApi from helpers.auth_guard import admin_required from .validation import schema, schema_multiple -from .user_service import UserService +from .lit_user_service import UserService @api_v1.route("/users", methods=["GET"]) @@ -16,8 +16,7 @@ from .user_service import UserService @cross_origin() @admin_required() def get_users(): - res = UserService.get_users() - return jsonify(res) + return jsonify(UserService.get_users()) @api_v1.route("/users/", methods=["GET"]) diff --git a/backend/helpers/__init__.py b/backend/helpers/__init__.py index 9302e8e..bc10551 100644 --- a/backend/helpers/__init__.py +++ b/backend/helpers/__init__.py @@ -2,3 +2,4 @@ from .kratos_api import * from .error_handler import * from .hydra_oauth import * from .kratos_user import * +from .lit_oauth import * \ No newline at end of file diff --git a/backend/helpers/auth_guard.py b/backend/helpers/auth_guard.py index 36bbeeb..fdab7df 100644 --- a/backend/helpers/auth_guard.py +++ b/backend/helpers/auth_guard.py @@ -11,9 +11,10 @@ def admin_required(): @wraps(fn) def decorator(*args, **kwargs): verify_jwt_in_request() - claims = get_jwt() - user_id = claims["user_id"] - is_admin = RoleService.is_user_admin(user_id) + # claims = get_jwt() + # user_id = claims["user_id"] + is_admin = True # RoleService.is_user_admin(user_id) + # TODO: actually check if admin if is_admin: return fn(*args, **kwargs) else: diff --git a/backend/helpers/authentik_api.py b/backend/helpers/authentik_api.py new file mode 100644 index 0000000..e0dc69d --- /dev/null +++ b/backend/helpers/authentik_api.py @@ -0,0 +1,43 @@ +from typing import List +from flask_jwt_extended import get_jwt +import requests +from .error_handler import AuthentikError + +AUTHENTIK_BASEURL = "https://dev.local-it.cloud/api/v3" + + +class AuthentikApi: # TODO: check if can be replaced with apispec generated api? + @staticmethod + def __handleError(res): + if res.status_code >= 400: + message = res.json()["error"]["message"] + raise AuthentikError(message, res.status_code) + + @staticmethod + def __token(): + jwt = get_jwt() + return jwt["sub"]["refresh_token"] + + @staticmethod + def get(url): + try: + res = requests.get(f"{AUTHENTIK_BASEURL}{url}", headers={ + "Authorization": f"Bearer {AuthentikApi.__token()}"}) + AuthentikApi.__handleError(res) + if (res.json()["pagination"]): + return AuthentikApi.__paginate(res) + return res.json() + except AuthentikError as err: + raise err + except: + raise AuthentikError() + + @staticmethod + def __paginate(res: requests.Response): # TODO: test this + results = res.json()["results"] + for page in range(1, res.json()["pagination"]["total_pages"]): + res = requests.get( + f"{res.request.url}", headers=res.request.headers, params={'page': page}) + AuthentikApi.__handleError(res) + results.append(res.json()["results"]) + return results \ No newline at end of file diff --git a/backend/helpers/error_handler.py b/backend/helpers/error_handler.py index d4009b8..b1edcb7 100644 --- a/backend/helpers/error_handler.py +++ b/backend/helpers/error_handler.py @@ -5,6 +5,8 @@ from jsonschema import ValidationError class KratosError(Exception): pass +class AuthentikError(Exception): + pass class HydraError(Exception): pass diff --git a/backend/helpers/hydra_oauth.py b/backend/helpers/hydra_oauth.py index 5143487..b75d615 100644 --- a/backend/helpers/hydra_oauth.py +++ b/backend/helpers/hydra_oauth.py @@ -9,7 +9,7 @@ class HydraOauth: @staticmethod def authorize(): try: - hydra = OAuth2Session(HYDRA_CLIENT_ID, redirect_uri=REDIRECT_URL) + hydra = OAuth2Session(HYDRA_CLIENT_ID) authorization_url, state = hydra.authorization_url( HYDRA_AUTHORIZATION_BASE_URL ) diff --git a/backend/helpers/kratos_api.py b/backend/helpers/kratos_api.py index eb83c82..af9f6e0 100644 --- a/backend/helpers/kratos_api.py +++ b/backend/helpers/kratos_api.py @@ -4,7 +4,6 @@ import requests from config import * from .error_handler import KratosError - class KratosApi: @staticmethod def __handleError(res): diff --git a/backend/helpers/lit_oauth.py b/backend/helpers/lit_oauth.py new file mode 100644 index 0000000..3df84d2 --- /dev/null +++ b/backend/helpers/lit_oauth.py @@ -0,0 +1,51 @@ +from flask import request, session +from requests_oauthlib import OAuth2Session + +from config import * +from helpers import HydraError + + +class LITOauth: + @staticmethod + def authorize(): + try: + scopes = ["openid", "email", "profile", "goauthentik.io/api"] + oauth = OAuth2Session(HYDRA_CLIENT_ID, redirect_uri=REDIRECT_URL, scope=scopes) + authorization_url, state = oauth.authorization_url( + HYDRA_AUTHORIZATION_BASE_URL + ) + return authorization_url + except Exception as err: + raise HydraError(str(err), 500) + + @staticmethod + def get_token(state, code): + try: + oauth = OAuth2Session( + client_id=HYDRA_CLIENT_ID, + state=state, + ) + token = oauth.fetch_token( + token_url=TOKEN_URL, + code=code, + client_secret=HYDRA_CLIENT_SECRET, + include_client_id=True, + ) + + session["oauth_token"] = token + + return token + except Exception as err: + raise HydraError(str(err), 500) + + @staticmethod + def get_user_info(): + try: + hydra = OAuth2Session( + client_id=HYDRA_CLIENT_ID, token=session["oauth_token"] + ) + user_info = hydra.get("{}/userinfo".format(HYDRA_PUBLIC_URL)) + + return user_info.json() + except Exception as err: + raise HydraError(str(err), 500) diff --git a/backend/requirements.txt b/backend/requirements.txt index eae5bd2..a1e705d 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -1,5 +1,8 @@ +alembic==1.8.1 attrs==21.4.0 black==22.1.0 +cachelib==0.9.0 +cachetools==5.2.0 certifi==2021.10.8 cffi==1.15.0 charset-normalizer==2.0.12 @@ -9,32 +12,43 @@ Flask==2.0.3 Flask-Cors==3.0.10 flask-expects-json==1.7.0 Flask-JWT-Extended==4.3.1 +Flask-Migrate==3.1.0 +Flask-Session==0.4.0 +Flask-SQLAlchemy==2.5.1 +google-auth==2.14.0 +greenlet==2.0.0.post0 gunicorn==20.1.0 +hydra-client==0.4.0 idna==3.3 install==1.3.5 itsdangerous==2.1.1 -jsonschema==4.4.0 Jinja2==3.0.3 jinja2-base64-filters==0.1.4 +jsonschema==4.4.0 kubernetes==24.2.0 +Mako==1.2.3 MarkupSafe==2.1.1 mypy-extensions==0.4.3 oauthlib==3.2.0 +ory-kratos-client==0.9.0a2 pathspec==0.9.0 platformdirs==2.5.1 +pyasn1==0.4.8 +pyasn1-modules==0.2.8 pycparser==2.21 PyJWT==2.3.0 +PyMySQL==1.0.2 pyrsistent==0.18.1 +python-dateutil==2.8.2 +PyYAML==6.0 regex==2022.3.15 requests==2.27.1 requests-oauthlib==1.3.1 +rsa==4.9 six==1.16.0 +SQLAlchemy==1.4.42 tomli==1.2.3 -typing-extensions==4.1.1 +typing_extensions==4.1.1 urllib3==1.26.8 +websocket-client==1.4.2 Werkzeug==2.0.3 -ory-kratos-client==0.9.0a2 -pymysql -Flask-SQLAlchemy -hydra-client -Flask-Migrate diff --git a/backend/web/static/base.js b/backend/web/static/base.js index 0e142ed..2ca8456 100644 --- a/backend/web/static/base.js +++ b/backend/web/static/base.js @@ -1,6 +1,6 @@ /* base.js This is the base JS file to render the user interfaces of kratos and provide - the end user with flows for login, recovery etc. + the end user with flows for login, recovery etc. check_flow_*(): These functions check the status of the flow and based on the status do some @@ -261,8 +261,6 @@ function render_messages(data) { // value: If there is already a value known, show it // messages: error messages related to the field function getFormElement(type, name, value, messages) { - console.log('Getting form element', type, name, value, messages); - if (value == undefined) { value = ''; } @@ -350,7 +348,6 @@ function getFormInput(type, name, value, label, placeHolder, help, messages) { if (typeof help == 'undefined' || help == null) { help = ''; } - console.log('Messages: ', messages); // Id field for help element var nameHelp = name + 'Help'; @@ -362,7 +359,6 @@ function getFormInput(type, name, value, label, placeHolder, help, messages) { // messages get appended to help info if (messages.length) { for (message in messages) { - console.log('adding message', messages[message]); help += messages[message]['text']; } } diff --git a/src/components/Header/HeaderLIT.tsx b/src/components/Header/HeaderLIT.tsx index e312314..8deba39 100644 --- a/src/components/Header/HeaderLIT.tsx +++ b/src/components/Header/HeaderLIT.tsx @@ -9,7 +9,7 @@ import { useApps } from 'src/services/apps'; const navigation = [ { name: 'Users', to: '/users', requiresAdmin: true }, - { name: 'Apps', to: '/apps', requiresAdmin: true }, + // { name: 'Apps', to: '/apps', requiresAdmin: true }, ]; function classNames(...classes: any[]) { @@ -33,8 +33,6 @@ const HeaderLIT: React.FC = () => { const { pathname } = useLocation(); const { apps } = useApps(); const navigationItems = filterNavigationByDashboardRole(isAdmin); - console.log(isAdmin); - console.log(navigationItems); const signOutUrl = useMemo(() => { // @ts-ignore @@ -86,9 +84,9 @@ const HeaderLIT: React.FC = () => { key={item.name} to={item.to} className={clsx( - 'border-primary-50 text-gray-900 inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium', + 'border-primary-50 inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium litbutton', { - 'border-primary-500 text-gray-500 hover:border-gray-300 hover:text-gray-700 inline-flex items-center px-1 pt-1 text-sm font-medium': + 'border-primary-500 litbutton-active hover:border-gray-300 inline-flex items-center px-1 pt-1 text-sm font-medium': pathname.includes(item.to), }, )} diff --git a/src/modules/users/Users.tsx b/src/modules/users/Users.tsx index 5d45dd5..df0321d 100644 --- a/src/modules/users/Users.tsx +++ b/src/modules/users/Users.tsx @@ -53,6 +53,11 @@ export const Users: React.FC = () => { const columns: any = React.useMemo( () => [ + { + Header: 'Username', + accessor: 'preferredUsername', + width: 'auto', + }, { Header: 'Name', accessor: 'name', @@ -75,11 +80,12 @@ export const Users: React.FC = () => { if (isAdmin) { return ( -
+