Skip to content

Commit

Permalink
Add UserBitmap to User to validate user permissions (#419)
Browse files Browse the repository at this point in the history
This patch add the user-bitmap to the authentication token, internal API only

* Update authentication.ts

* Create user-bitmap.model.ts

* add `terms-of-use` service to set the terms of use date in the DB

* add `user-requests`service (only find method)

* add `user-requests-review` service (only find method)

* add groups and authentication in payload and in SlimUser

* Move models User and Group to typescript, Group class implements new Sequelize 6 typescript

* Create users.model.test.ts and add simple tests for related services

* Use current NODE_ENV configuration to test sequelize connection and get info about any users

* add subscription dataset

* printout bitmap along with subscriptions

Minor changes, long due

* check existing users (email or username) on `users/create`

* Update password-reset.class.js

* Delete users.queries.cyp

* remove console.error for wrong validation, use debug

* update deps

* remove unused obfuscatedUser and use number to avid JSON output problems with BigInt

* fix typescript for celery client to get the `get()`method on AsyncResult

* add AvailablePlans to the configuration, mostly in default


---------

Co-authored-by: Roman Kalyakin <[email protected]>
Co-authored-by: Daniele Guido <[email protected]>
  • Loading branch information
3 people authored Nov 25, 2024
1 parent 7d9c9e6 commit a3f3dce
Show file tree
Hide file tree
Showing 40 changed files with 2,148 additions and 978 deletions.
1 change: 1 addition & 0 deletions config/default.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"isPublicApi": true,
"availablePlans": ["plan-basic", "plan-educational", "plan-researcher"],
"allowedCorsOrigins": [
"http://localhost:8080",
"https://impresso-project.ch/app",
Expand Down
45 changes: 40 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"watch": "tsc -p ./tsconfig.json -w & tscp -w",
"build": "tsc -p ./tsconfig.json",
"copy-files": "tscp",
"mocha": "mocha --require ts-node/register",
"test": "mocha --require ts-node/register 'test/**/*.test.{js,ts}'",
"test-watch": "mocha --require ts-node/register --watch 'test/**/*.test.{js,ts}'",
"integration-test": "NODE_ENV=test mocha --config ./.mocharc-integration.json 'test/integration/**/*.test.js'",
Expand Down Expand Up @@ -113,7 +114,7 @@
"pg": "^8.11.3",
"pg-hstore": "^2.3.2",
"redis": "4.6.13",
"sequelize": "^6.21.0",
"sequelize": "^6.37.3",
"serve-favicon": "^2.5.0",
"sharp": "^0.32.6",
"short-hash": "^1.0.0",
Expand All @@ -134,7 +135,8 @@
"@types/cache-manager": "^2.10.3",
"@types/generic-pool": "^3.1.9",
"@types/ioredis": "^4.28.5",
"@types/mocha": "10.0.6",
"@types/mocha": "^10.0.6",
"@types/node": "^22.5.5",
"@types/node-fetch": "^2.5.6",
"@types/wikidata-sdk": "^5.15.0",
"eslint": "^8.18.0",
Expand Down
17 changes: 13 additions & 4 deletions src/authentication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,24 @@ import { createSwaggerServiceOptions } from 'feathers-swagger'
import User from './models/users.model'
import { docs } from './services/authentication/authentication.schema'
import { ImpressoApplication } from './types'
import { BufferUserPlanGuest } from './models/user-bitmap.model'

const debug = initDebug('impresso/authentication')

type AuthPayload = Omit<SlimUser, 'uid' | 'id'> & { userId: string }

class CustomisedAuthenticationService extends AuthenticationService {
async getPayload(authResult: AuthenticationResult, params: AuthenticationParams) {
const payload = await super.getPayload(authResult, params)
const payload = (await super.getPayload(authResult, params)) as AuthPayload
const { user } = authResult as { user: User }

if (user) {
payload.userId = user.uid
if (user.groups.length) {
payload.userGroups = user.groups.map(d => d.name)
payload.groups = user.groups.map(d => d.name)
}
payload.isStaff = user.isStaff
payload.bitmap = user.bitmap ?? Number(BufferUserPlanGuest)
}
return payload
}
Expand Down Expand Up @@ -59,6 +64,10 @@ export interface SlimUser {
uid: string
id: number
isStaff: boolean
/**
* Bitmap as number Number(BigInt)
*/
bitmap?: number
groups: string[]
}

Expand Down Expand Up @@ -87,12 +96,12 @@ class NoDBJWTStrategy extends JWTStrategy {
if (entity === null) {
return result
}

const slimUser: SlimUser = {
uid: payload.userId,
id: parseInt(payload.sub),
bitmap: payload.bitmap ?? Number(BufferUserPlanGuest),
isStaff: payload.isStaff ?? false,
groups: payload.userGroups ?? [],
groups: payload.groups ?? [],
}
return {
...result,
Expand Down
4 changes: 3 additions & 1 deletion src/celery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { logger } from './logger'
import Job from './models/jobs.model'
import type { LogData } from './services/logs/logs.class'
import { ImpressoApplication } from './types'
import { AsyncResult } from 'celery-node/dist/app/result'

const debug = debugModule('impresso/celery')

Expand All @@ -17,7 +18,7 @@ export const JobStatusTranslations: Record<string, string> = {
}

export interface CeleryClient {
run: (task: { task: string; args: any[] }) => void
run: (task: { task: string; args: any[] }) => Promise<AsyncResult>
}

const getCeleryClient = (config: CeleryConfiguration, app: ImpressoApplication) => {
Expand Down Expand Up @@ -66,6 +67,7 @@ const getCeleryClient = (config: CeleryConfiguration, app: ImpressoApplication)
debug(`run celery task ${task}`)
const celeryTask = client.createTask(task)
return celeryTask.applyAsync(args)

// @todo: fix this and add errror mnagement
// const result = celeryTask.applyAsync(args)
// return result
Expand Down
15 changes: 15 additions & 0 deletions src/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,13 @@ export interface PaginationConfiguration {
max: number
}

export interface AvailablePlansConfiguration {
availablePlans: ('plan-basic' | 'plan-educational' | 'plan-researcher')[]
}

export interface Configuration {
isPublicApi?: boolean
availablePlans: AvailablePlansConfiguration
allowedCorsOrigins?: string[]
redis?: RedisConfiguration
rateLimiter?: RateLimiterConfiguration & { enabled?: boolean }
Expand Down Expand Up @@ -133,6 +138,16 @@ const configurationSchema: JSONSchemaDefinition = {
type: 'object',
properties: {
isPublicApi: { type: 'boolean', description: 'If `true`, the app serves a public API' },
plans: {
type: 'array',
items: {
type: 'array',
items: { type: 'string' },
minItems: 3,
maxItems: 5,
},
description: 'List of plans for users',
},
allowedCorsOrigins: {
type: 'array',
items: {
Expand Down
1 change: 0 additions & 1 deletion src/hooks/params.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,6 @@ const _validateOne = (key, item, rule) => {

if (Object.keys(_errors).length) {
debug('_validateOne: errors:', _errors)
console.error('_validateOne throws errors:', _errors, '- item:', item)
throw new errors.BadRequest(_errors)
}

Expand Down
9 changes: 6 additions & 3 deletions src/hooks/resolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,10 @@ export const resolveCollections = () => async (context: HookContext<ImpressoAppl

// get collections as dictionary
const client = context.app.get('sequelizeClient')

const index = await Collection.sequelize(client)
if (!client) {
throw new Error('Sequelize client not available')
}
const index = (await Collection.sequelize(client)
.findAll({
where: {
uid: uids,
Expand All @@ -106,7 +108,8 @@ export const resolveCollections = () => async (context: HookContext<ImpressoAppl
.catch((err: Error) => {
console.error('hook resolveCollections ERROR')
console.error(err)
})
return {}
})) as lodash.Dictionary<any>

items.forEach(d => {
if (d.type !== 'collection') return
Expand Down
Loading

0 comments on commit a3f3dce

Please sign in to comment.