mirror of
https://github.com/jambonz/jambonz-webapp.git
synced 2026-07-04 19:21:58 +00:00
Feature: Multi-user: Changes to initial admin login processing / implement JWT (#140)
* Add simple JWT parsing function * Implement user action for global store
This commit is contained in:
committed by
GitHub
parent
50d93b0089
commit
3093f40e00
@@ -1,5 +1,7 @@
|
||||
{
|
||||
"token": "327a2d17-ce9b-45a7-b0ff-a556536d27fb",
|
||||
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX3NpZCI6IjFjNTc4MWQyLTY5MGItNDIwYy1iZDUzLTVkN2Y1NjMwMDVjOCIsInNjb3BlIjoiYWRtaW4iLCJmb3JjZV9jaGFuZ2UiOnRydWUsInBlcm1pc3Npb25zIjpbIlBST1ZJU0lPTl9VU0VSUyIsIlBST1ZJU0lPTl9TRVJWSUNFUyIsIlZJRVdfT05MWSJdLCJpYXQiOjE2NjY3OTgzMTEsImV4cCI6MTY2NjgwMTkxMX0.ZV3KnRit8WGpipfiiMAZ2AVLQ25csWje1-K6hdqxktE",
|
||||
"scope": "admin",
|
||||
"user_sid": "78131ad5-f041-4d5d-821c-47b2d8c6d015",
|
||||
"force_change": false
|
||||
"force_change": false,
|
||||
"permissions": ["VIEW_ONLY", "PROVISION_SERVICES", "PROVISION_USERS"]
|
||||
}
|
||||
|
||||
+19
-2
@@ -10,6 +10,22 @@ export type IpType = "ip" | "fqdn" | "fqdn-top-level" | "invalid";
|
||||
|
||||
export type LimitCategories = "api_rate" | "voice_call_session" | "device";
|
||||
|
||||
/** User roles / permissions */
|
||||
|
||||
export type UserScopes = "admin" | "service_provider" | "account";
|
||||
|
||||
export type UserPermissions =
|
||||
| "VIEW_ONLY"
|
||||
| "PROVISION_SERVICES"
|
||||
| "PROVISION_USERS";
|
||||
|
||||
// We'll want something like this for actual permissions implementation...
|
||||
// export enum UserPermissions {
|
||||
// VIEW_ONLY = 0,
|
||||
// PROVISION_SERVICES = 1,
|
||||
// PROVISION_USERS = 2,
|
||||
// }
|
||||
|
||||
/** Status codes */
|
||||
|
||||
export enum StatusCodes {
|
||||
@@ -90,12 +106,13 @@ export interface PasswordSettings {
|
||||
/** API responses/payloads */
|
||||
|
||||
export interface User {
|
||||
scope: UserScopes;
|
||||
user_sid: string;
|
||||
permissions: UserPermissions[];
|
||||
}
|
||||
|
||||
export interface UserLogin {
|
||||
export interface UserLogin extends User {
|
||||
token: string;
|
||||
user_sid: string;
|
||||
force_change: boolean;
|
||||
}
|
||||
|
||||
|
||||
@@ -108,6 +108,7 @@ export const Navi = ({
|
||||
|
||||
/** Fetch service providers */
|
||||
useEffect(() => {
|
||||
dispatch({ type: "user" });
|
||||
dispatch({ type: "serviceProviders" });
|
||||
}, []);
|
||||
|
||||
@@ -166,12 +167,12 @@ export const Navi = ({
|
||||
<Icons.PlusCircle />
|
||||
</button>
|
||||
</div>
|
||||
{/* Until we have the APIs this initial UI is not accessible */}
|
||||
{user && (
|
||||
{/* Intentionally hiding this as we will need to work this out as we go... */}
|
||||
{/* ACL component will need to be updated for new user scope/permissions handling */}
|
||||
{false && user && (
|
||||
<div className="navi__user">
|
||||
{/* Seed should be user sid when we have the APIs for it... */}
|
||||
<Blockies
|
||||
seed="jambonz"
|
||||
seed={user!.user_sid}
|
||||
size={6}
|
||||
scale={6}
|
||||
color={getCssVar("--jambonz")}
|
||||
|
||||
@@ -60,6 +60,26 @@ export const setToken = (token: string) => {
|
||||
localStorage.setItem(storageKey, token);
|
||||
};
|
||||
|
||||
/**
|
||||
* Decode data from a JWT
|
||||
* https://stackoverflow.com/questions/38552003/how-to-decode-jwt-token-in-javascript-without-using-a-library
|
||||
*/
|
||||
export const parseJwt = (token: string) => {
|
||||
const base64Url = token.split(".")[1];
|
||||
const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
|
||||
const jsonPayload = decodeURIComponent(
|
||||
window
|
||||
.atob(base64)
|
||||
.split("")
|
||||
.map((c) => {
|
||||
return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
|
||||
})
|
||||
.join("")
|
||||
);
|
||||
|
||||
return JSON.parse(jsonPayload);
|
||||
};
|
||||
|
||||
/**
|
||||
* Provider hook that creates auth object and handles state
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { getUser, getServiceProviders } from "src/api";
|
||||
import { getServiceProviders } from "src/api";
|
||||
import { sortLocaleName } from "src/utils";
|
||||
import { getToken, parseJwt } from "src/router/auth";
|
||||
|
||||
import type { State, Action } from "./types";
|
||||
import type { ServiceProvider, User } from "src/api/types";
|
||||
@@ -61,8 +62,9 @@ export const currentServiceProviderAction = (
|
||||
};
|
||||
|
||||
export const userAsyncAction = async (): Promise<User> => {
|
||||
const response = await getUser("user_sid");
|
||||
return response.json;
|
||||
const token = getToken();
|
||||
const { user_sid, permissions, scope } = parseJwt(token);
|
||||
return { user_sid, permissions, scope };
|
||||
};
|
||||
|
||||
export const serviceProvidersAsyncAction = async (): Promise<
|
||||
|
||||
+2
-1
@@ -6,6 +6,7 @@ import { AuthContext } from "src/router/auth";
|
||||
import { MSG_SOMETHING_WRONG } from "src/constants";
|
||||
|
||||
import type { AuthStateContext } from "src/router/auth";
|
||||
import type { UserLogin } from "src/api/types";
|
||||
|
||||
import userLogin from "../../cypress/fixtures/userLogin.json";
|
||||
|
||||
@@ -19,7 +20,7 @@ type LayoutProviderProps = TestProviderProps & {
|
||||
};
|
||||
|
||||
export const signinError = () => Promise.reject(MSG_SOMETHING_WRONG);
|
||||
export const signinSuccess = () => Promise.resolve(userLogin);
|
||||
export const signinSuccess = () => Promise.resolve(userLogin as UserLogin);
|
||||
export const signout = () => undefined;
|
||||
export const authProps: AuthStateContext = {
|
||||
token: "",
|
||||
|
||||
Reference in New Issue
Block a user