mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
refactored isAuthorized & implemented a new role & rights based system
This commit is contained in:
parent
963bff1c0b
commit
44365bccf1
5
backend/src/auth/CustomJwtPayload.ts
Normal file
5
backend/src/auth/CustomJwtPayload.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import { JwtPayload } from 'jsonwebtoken'
|
||||
|
||||
export interface CustomJwtPayload extends JwtPayload {
|
||||
pubKey: Buffer
|
||||
}
|
||||
13
backend/src/auth/INALIENABLE_RIGHTS.ts
Normal file
13
backend/src/auth/INALIENABLE_RIGHTS.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { RIGHTS } from './RIGHTS'
|
||||
|
||||
export const INALIENABLE_RIGHTS = [
|
||||
RIGHTS.LOGIN,
|
||||
RIGHTS.GET_COMMUNITY_INFO,
|
||||
RIGHTS.COMMUNITIES,
|
||||
RIGHTS.LOGIN_VIA_EMAIL_VERIFICATION_CODE,
|
||||
RIGHTS.CREATE_USER,
|
||||
RIGHTS.SEND_RESET_PASSWORD_EMAIL,
|
||||
RIGHTS.RESET_PASSWORD,
|
||||
RIGHTS.CHECK_USERNAME,
|
||||
RIGHTS.CHECK_EMAIL,
|
||||
]
|
||||
23
backend/src/auth/RIGHTS.ts
Normal file
23
backend/src/auth/RIGHTS.ts
Normal file
@ -0,0 +1,23 @@
|
||||
export enum RIGHTS {
|
||||
LOGIN = 'LOGIN',
|
||||
BALANCE = 'BALANCE',
|
||||
GET_COMMUNITY_INFO = 'GET_COMMUNITY_INFO',
|
||||
COMMUNITIES = 'COMMUNITIES',
|
||||
LIST_GDT_ENTRIES = 'LIST_GDT_ENTRIES',
|
||||
EXIST_PID = 'EXIST_PID',
|
||||
GET_KLICKTIPP_USER = 'GET_KLICKTIPP_USER',
|
||||
GET_KLICKTIPP_TAG_MAP = 'GET_KLICKTIPP_TAG_MAP',
|
||||
UNSUBSCRIBE_NEWSLETTER = 'UNSUBSCRIBE_NEWSLETTER',
|
||||
SUBSCRIBE_NEWSLETTER = 'SUBSCRIBE_NEWSLETTER',
|
||||
TRANSACTION_LIST = 'TRANSACTION_LIST',
|
||||
SEND_COINS = 'SEND_COINS',
|
||||
LOGIN_VIA_EMAIL_VERIFICATION_CODE = 'LOGIN_VIA_EMAIL_VERIFICATION_CODE',
|
||||
LOGOUT = 'LOGOUT',
|
||||
CREATE_USER = 'CREATE_USER',
|
||||
SEND_RESET_PASSWORD_EMAIL = 'SEND_RESET_PASSWORD_EMAIL',
|
||||
RESET_PASSWORD = 'RESET_PASSWORD',
|
||||
UPDATE_USER_INFOS = 'UPDATE_USER_INFOS',
|
||||
CHECK_USERNAME = 'CHECK_USERNAME',
|
||||
CHECK_EMAIL = 'CHECK_EMAIL',
|
||||
HAS_ELOPAGE = 'HAS_ELOPAGE',
|
||||
}
|
||||
24
backend/src/auth/ROLES.ts
Normal file
24
backend/src/auth/ROLES.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import { INALIENABLE_RIGHTS } from './INALIENABLE_RIGHTS'
|
||||
import { RIGHTS } from './RIGHTS'
|
||||
import { Role } from './Role'
|
||||
|
||||
// TODO from database
|
||||
export const ROLES = [
|
||||
new Role('unauthorized', INALIENABLE_RIGHTS), // inalienable rights
|
||||
new Role('user', [
|
||||
...INALIENABLE_RIGHTS,
|
||||
RIGHTS.BALANCE,
|
||||
RIGHTS.LIST_GDT_ENTRIES,
|
||||
RIGHTS.EXIST_PID,
|
||||
RIGHTS.GET_KLICKTIPP_USER,
|
||||
RIGHTS.GET_KLICKTIPP_TAG_MAP,
|
||||
RIGHTS.UNSUBSCRIBE_NEWSLETTER,
|
||||
RIGHTS.SUBSCRIBE_NEWSLETTER,
|
||||
RIGHTS.TRANSACTION_LIST,
|
||||
RIGHTS.SEND_COINS,
|
||||
RIGHTS.LOGOUT,
|
||||
RIGHTS.UPDATE_USER_INFOS,
|
||||
RIGHTS.HAS_ELOPAGE,
|
||||
]),
|
||||
new Role('admin', Object.values(RIGHTS)), // all rights
|
||||
]
|
||||
11
backend/src/auth/Role.ts
Normal file
11
backend/src/auth/Role.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { RIGHTS } from './RIGHTS'
|
||||
|
||||
export class Role {
|
||||
id: string
|
||||
rights: RIGHTS[]
|
||||
|
||||
constructor(id: string, rights: RIGHTS[]) {
|
||||
this.id = id
|
||||
this.rights = rights
|
||||
}
|
||||
}
|
||||
6
backend/src/auth/hasRight.ts
Normal file
6
backend/src/auth/hasRight.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import { RIGHTS } from './RIGHTS'
|
||||
import { Role } from './Role'
|
||||
|
||||
export const hasRight = (right: RIGHTS, role: Role): boolean => {
|
||||
return role.rights.includes(right)
|
||||
}
|
||||
@ -2,19 +2,36 @@
|
||||
|
||||
import { AuthChecker } from 'type-graphql'
|
||||
|
||||
import decode from '../../jwt/decode'
|
||||
import encode from '../../jwt/encode'
|
||||
import { decode, encode } from '../../auth/JWT'
|
||||
import { ROLES } from '../../auth/ROLES'
|
||||
import { hasRight } from '../../auth/hasRight'
|
||||
import { RIGHTS } from '../../auth/RIGHTS'
|
||||
|
||||
const isAuthorized: AuthChecker<any> = async (
|
||||
{ /* root, args, */ context /*, info */ } /*, roles */,
|
||||
) => {
|
||||
const isAuthorized: AuthChecker<any> = async ({ context }, rights) => {
|
||||
context.role = ROLES[0] // unauthorized user
|
||||
|
||||
// Do we have a token?
|
||||
if (context.token) {
|
||||
const decoded = decode(context.token)
|
||||
context.pubKey = Buffer.from(decoded.pubKey).toString('hex')
|
||||
context.setHeaders.push({ key: 'token', value: encode(decoded.pubKey) })
|
||||
return true
|
||||
if (!decoded) {
|
||||
// we always throw on an invalid token
|
||||
throw new Error('403.13 - Client certificate revoked')
|
||||
}
|
||||
// Set context pubKey
|
||||
context.pubKey = Buffer.from(decoded.pubKey).toString('hex')
|
||||
// set new header token
|
||||
context.setHeaders.push({ key: 'token', value: encode(decoded.pubKey) })
|
||||
// TODO - load from database dynamically & admin - maybe encode this in the token to prevent many database requests
|
||||
context.role = ROLES[1] // logged in user
|
||||
}
|
||||
|
||||
// check for correct rights
|
||||
const missingRights = (<RIGHTS[]>rights).filter((right) => !hasRight(right, context.role))
|
||||
if (missingRights.length !== 0) {
|
||||
throw new Error('401 Unauthorized')
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
export default isAuthorized
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user