mirror of
https://github.com/Paris-est-Ludique/intranet.git
synced 2025-06-10 01:24:20 +02:00
Add roles support server and client side
This commit is contained in:
parent
ba0753b85a
commit
57057780d8
@ -57,7 +57,12 @@ export default class ExpressAccessors<
|
|||||||
|
|
||||||
// custom can be async
|
// custom can be async
|
||||||
get<Ret = Element>(
|
get<Ret = Element>(
|
||||||
custom?: (list: Element[], body: Request["body"], id: number) => Promise<Ret> | Ret
|
custom?: (
|
||||||
|
list: Element[],
|
||||||
|
body: Request["body"],
|
||||||
|
id: number,
|
||||||
|
roles: string[]
|
||||||
|
) => Promise<Ret> | Ret
|
||||||
) {
|
) {
|
||||||
return async (request: Request, response: Response, _next: NextFunction): Promise<void> => {
|
return async (request: Request, response: Response, _next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
@ -69,7 +74,8 @@ export default class ExpressAccessors<
|
|||||||
toCaller = list.find((e: Element) => e.id === id)
|
toCaller = list.find((e: Element) => e.id === id)
|
||||||
} else {
|
} else {
|
||||||
const memberId = response?.locals?.jwt?.id || -1
|
const memberId = response?.locals?.jwt?.id || -1
|
||||||
toCaller = await custom(list, request.body, memberId)
|
const roles: string[] = response?.locals?.jwt?.roles || []
|
||||||
|
toCaller = await custom(list, request.body, memberId, roles)
|
||||||
if (toCaller?.jwt && toCaller?.id) {
|
if (toCaller?.jwt && toCaller?.id) {
|
||||||
response.cookie("jwt", toCaller.jwt, { maxAge: 365 * 24 * 60 * 60 })
|
response.cookie("jwt", toCaller.jwt, { maxAge: 365 * 24 * 60 * 60 })
|
||||||
response.cookie("id", toCaller.id, { maxAge: 365 * 24 * 60 * 60 })
|
response.cookie("id", toCaller.id, { maxAge: 365 * 24 * 60 * 60 })
|
||||||
@ -101,7 +107,8 @@ export default class ExpressAccessors<
|
|||||||
custom?: (
|
custom?: (
|
||||||
list: Element[],
|
list: Element[],
|
||||||
body: RequestBody,
|
body: RequestBody,
|
||||||
id: number
|
id: number,
|
||||||
|
roles: string[]
|
||||||
) => Promise<CustomSetReturn<Element>> | CustomSetReturn<Element>
|
) => Promise<CustomSetReturn<Element>> | CustomSetReturn<Element>
|
||||||
) {
|
) {
|
||||||
return async (request: Request, response: Response, _next: NextFunction): Promise<void> => {
|
return async (request: Request, response: Response, _next: NextFunction): Promise<void> => {
|
||||||
@ -112,8 +119,14 @@ export default class ExpressAccessors<
|
|||||||
response.status(200)
|
response.status(200)
|
||||||
} else {
|
} else {
|
||||||
const memberId = response?.locals?.jwt?.id || -1
|
const memberId = response?.locals?.jwt?.id || -1
|
||||||
|
const roles: string[] = response?.locals?.jwt?.roles || []
|
||||||
const list = (await sheet.getList()) || []
|
const list = (await sheet.getList()) || []
|
||||||
const { toDatabase, toCaller } = await custom(list, request.body, memberId)
|
const { toDatabase, toCaller } = await custom(
|
||||||
|
list,
|
||||||
|
request.body,
|
||||||
|
memberId,
|
||||||
|
roles
|
||||||
|
)
|
||||||
if (toDatabase !== undefined) {
|
if (toDatabase !== undefined) {
|
||||||
await sheet.set(toDatabase)
|
await sheet.set(toDatabase)
|
||||||
}
|
}
|
||||||
|
@ -51,8 +51,9 @@ export const volunteerLogin = expressAccessor.get<VolunteerLogin>(async (list, b
|
|||||||
const jwt = await getJwt(volunteer.id, volunteer.roles)
|
const jwt = await getJwt(volunteer.id, volunteer.roles)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: volunteer.id,
|
|
||||||
jwt,
|
jwt,
|
||||||
|
id: volunteer.id,
|
||||||
|
roles: volunteer.roles,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -142,10 +143,12 @@ export const volunteerNotifsSet = expressAccessor.set(async (list, body, id) =>
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export const volunteerTeamWishesSet = expressAccessor.set(async (list, body, id) => {
|
export const volunteerTeamWishesSet = expressAccessor.set(async (list, body, id, roles) => {
|
||||||
const requestedId = +body[0] || id
|
const requestedId = +body[0] || id
|
||||||
if (requestedId !== id && requestedId !== 0) {
|
if (requestedId !== id && requestedId !== 0 && !roles.includes("repartiteur")) {
|
||||||
throw Error(`On ne peut acceder qu'à ses propres envies d'équipes`)
|
throw Error(
|
||||||
|
`À moins d'être répartiteur de bénévole dans les équipes, on ne peut acceder qu'à ses propres envies d'équipes`
|
||||||
|
)
|
||||||
}
|
}
|
||||||
const wishes = body[1] as VolunteerTeamWishes
|
const wishes = body[1] as VolunteerTeamWishes
|
||||||
const volunteer = list.find((v) => v.id === requestedId)
|
const volunteer = list.find((v) => v.id === requestedId)
|
||||||
|
@ -15,8 +15,8 @@ import routes from "../routes"
|
|||||||
import { getCookieJWT } from "../services/auth"
|
import { getCookieJWT } from "../services/auth"
|
||||||
|
|
||||||
export default async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
export default async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||||
const { jwt, id } = getCookieJWT(req.headers.cookie)
|
const { jwt, id, roles } = getCookieJWT(req.headers.cookie)
|
||||||
const { store } = createStore({ url: req.url, jwt, id })
|
const { store } = createStore({ url: req.url, jwt, id, roles })
|
||||||
|
|
||||||
// The method for loading data from server-side
|
// The method for loading data from server-side
|
||||||
const loadBranchData = (): Promise<any> => {
|
const loadBranchData = (): Promise<any> => {
|
||||||
|
@ -7,10 +7,11 @@ export const axiosConfig: AxiosRequestConfig = {
|
|||||||
headers: {},
|
headers: {},
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setJWT(token: string, id: number): void {
|
export function setJWT(token: string, id: number, roles: string[]): void {
|
||||||
axiosConfig.headers.Authorization = `Bearer ${token}`
|
axiosConfig.headers.Authorization = `Bearer ${token}`
|
||||||
Cookies.set("jwt", token, { expires: 3650 })
|
Cookies.set("jwt", token, { expires: 3650 })
|
||||||
Cookies.set("id", `${id}`, { expires: 3650 })
|
Cookies.set("id", `${id}`, { expires: 3650 })
|
||||||
|
Cookies.set("roles", roles.join(","), { expires: 3650 })
|
||||||
}
|
}
|
||||||
|
|
||||||
export function unsetJWT(): void {
|
export function unsetJWT(): void {
|
||||||
@ -18,6 +19,7 @@ export function unsetJWT(): void {
|
|||||||
|
|
||||||
Cookies.remove("jwt")
|
Cookies.remove("jwt")
|
||||||
Cookies.remove("id")
|
Cookies.remove("id")
|
||||||
|
Cookies.remove("roles")
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getCookieJWT(cookie = ""): VolunteerLogin {
|
export function getCookieJWT(cookie = ""): VolunteerLogin {
|
||||||
@ -28,5 +30,5 @@ export function getCookieJWT(cookie = ""): VolunteerLogin {
|
|||||||
res[k.trim()] = v
|
res[k.trim()] = v
|
||||||
return res
|
return res
|
||||||
}, {})
|
}, {})
|
||||||
return { jwt: cookies.jwt, id: +cookies.id }
|
return { jwt: cookies.jwt, id: +cookies.id, roles: cookies.roles?.split(",") || [] }
|
||||||
}
|
}
|
||||||
|
@ -107,8 +107,9 @@ export const passwordMinLength = 4
|
|||||||
export type VolunteerWithoutId = Omit<Volunteer, "id">
|
export type VolunteerWithoutId = Omit<Volunteer, "id">
|
||||||
|
|
||||||
export interface VolunteerLogin {
|
export interface VolunteerLogin {
|
||||||
id: number
|
|
||||||
jwt: string
|
jwt: string
|
||||||
|
id: number
|
||||||
|
roles: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface VolunteerForgot {
|
export interface VolunteerForgot {
|
||||||
|
@ -4,12 +4,14 @@ import { AppState } from "."
|
|||||||
// Define a type for the slice state
|
// Define a type for the slice state
|
||||||
interface AuthState {
|
interface AuthState {
|
||||||
id: number
|
id: number
|
||||||
|
roles: string[]
|
||||||
jwt: string
|
jwt: string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define the initial state using that type
|
// Define the initial state using that type
|
||||||
const initialState: AuthState = {
|
const initialState: AuthState = {
|
||||||
id: 0,
|
id: 0,
|
||||||
|
roles: [],
|
||||||
jwt: "",
|
jwt: "",
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -19,11 +21,13 @@ export const auth = createSlice({
|
|||||||
reducers: {
|
reducers: {
|
||||||
setCurrentUser: (state, action: PayloadAction<AuthState>) => {
|
setCurrentUser: (state, action: PayloadAction<AuthState>) => {
|
||||||
state.id = action.payload.id
|
state.id = action.payload.id
|
||||||
|
state.roles = action.payload.roles
|
||||||
state.jwt = action.payload.jwt
|
state.jwt = action.payload.jwt
|
||||||
},
|
},
|
||||||
logoutUser: (state) => {
|
logoutUser: (state) => {
|
||||||
// Unused, just reload page :/
|
// Unused, just reload page :/
|
||||||
state.id = 0
|
state.id = 0
|
||||||
|
state.roles = []
|
||||||
state.jwt = ""
|
state.jwt = ""
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -35,6 +39,8 @@ export const selectAuthData = (state: AppState): AuthState => state.auth
|
|||||||
|
|
||||||
export const selectUserJwtToken = createSelector(selectAuthData, (authData) => authData.jwt)
|
export const selectUserJwtToken = createSelector(selectAuthData, (authData) => authData.jwt)
|
||||||
|
|
||||||
|
export const selectUserRoles = createSelector(selectAuthData, (authData) => authData.roles)
|
||||||
|
|
||||||
export const isUserConnected = createSelector(selectUserJwtToken, (token) => !!token)
|
export const isUserConnected = createSelector(selectUserJwtToken, (token) => !!token)
|
||||||
|
|
||||||
export default auth.reducer
|
export default auth.reducer
|
||||||
|
@ -13,11 +13,12 @@ interface Arg {
|
|||||||
url?: string
|
url?: string
|
||||||
jwt?: string
|
jwt?: string
|
||||||
id?: number
|
id?: number
|
||||||
|
roles?: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use inferred return type for making correctly Redux types
|
// Use inferred return type for making correctly Redux types
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||||
const createStore = ({ initialState, url, jwt, id }: Arg = {}) => {
|
const createStore = ({ initialState, url, jwt, id, roles }: Arg = {}) => {
|
||||||
const history = __SERVER__
|
const history = __SERVER__
|
||||||
? createMemoryHistory({ initialEntries: [url || "/"] })
|
? createMemoryHistory({ initialEntries: [url || "/"] })
|
||||||
: createBrowserHistory()
|
: createBrowserHistory()
|
||||||
@ -32,8 +33,8 @@ const createStore = ({ initialState, url, jwt, id }: Arg = {}) => {
|
|||||||
devTools: __DEV__,
|
devTools: __DEV__,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (jwt && id) {
|
if (jwt && id && roles) {
|
||||||
store.dispatch(setCurrentUser({ jwt, id }))
|
store.dispatch(setCurrentUser({ jwt, id, roles }))
|
||||||
} else {
|
} else {
|
||||||
store.dispatch(logoutUser())
|
store.dispatch(logoutUser())
|
||||||
}
|
}
|
||||||
@ -42,12 +43,14 @@ const createStore = ({ initialState, url, jwt, id }: Arg = {}) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const id = +(Cookies.get("id") || 0)
|
const id = +(Cookies.get("id") || 0)
|
||||||
|
const roles = Cookies.get("roles")?.split(",") || []
|
||||||
const jwt = Cookies.get("jwt")
|
const jwt = Cookies.get("jwt")
|
||||||
if (id && jwt) {
|
if (id && jwt && roles) {
|
||||||
Cookies.set("id", `${id}`, { expires: 3650 })
|
Cookies.set("id", `${id}`, { expires: 3650 })
|
||||||
|
Cookies.set("roles", roles.join(","), { expires: 3650 })
|
||||||
Cookies.set("jwt", jwt, { expires: 3650 })
|
Cookies.set("jwt", jwt, { expires: 3650 })
|
||||||
}
|
}
|
||||||
const { store } = createStore({ id, jwt })
|
const { store } = createStore({ jwt, id, roles })
|
||||||
|
|
||||||
export type AppState = ReturnType<typeof store.getState>
|
export type AppState = ReturnType<typeof store.getState>
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ export const fetchVolunteerLogin = elementFetch<VolunteerLogin, Parameters<typeo
|
|||||||
getFailure,
|
getFailure,
|
||||||
undefined,
|
undefined,
|
||||||
(login: VolunteerLogin) => {
|
(login: VolunteerLogin) => {
|
||||||
setJWT(login.jwt, login.id)
|
setJWT(login.jwt, login.id, login.roles)
|
||||||
// eslint-disable-next-line no-restricted-globals
|
// eslint-disable-next-line no-restricted-globals
|
||||||
location?.reload()
|
location?.reload()
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user