@things-factory/auth-base 7.0.0-alpha.1 → 7.0.0-alpha.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,13 +5,13 @@ import { User } from './service/user/user';
5
5
  declare global {
6
6
  export type ResolverContext = {
7
7
  state: IContextState;
8
- t: TFunction;
8
+ t?: TFunction;
9
9
  [key: string]: any;
10
10
  };
11
11
  interface IContextState {
12
12
  domain: Domain;
13
13
  user: User;
14
- tx: EntityManager;
14
+ tx?: EntityManager;
15
15
  [key: string]: any;
16
16
  }
17
17
  }
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../server/types.ts"],"names":[],"mappings":"","sourcesContent":["import { TFunction } from 'i18next'\nimport { EntityManager } from 'typeorm'\n\nimport { Domain } from '@things-factory/shell'\n\nimport { User } from './service/user/user'\n\ndeclare global {\n export type ResolverContext = {\n state: IContextState\n t: TFunction\n [key: string]: any\n }\n\n interface IContextState {\n domain: Domain\n user: User\n tx: EntityManager\n [key: string]: any\n }\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../server/types.ts"],"names":[],"mappings":"","sourcesContent":["import { TFunction } from 'i18next'\nimport { EntityManager } from 'typeorm'\n\nimport { Domain } from '@things-factory/shell'\n\nimport { User } from './service/user/user'\n\ndeclare global {\n export type ResolverContext = {\n state: IContextState\n t?: TFunction\n [key: string]: any\n }\n\n interface IContextState {\n domain: Domain\n user: User\n tx?: EntityManager\n [key: string]: any\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@things-factory/auth-base",
3
- "version": "7.0.0-alpha.1",
3
+ "version": "7.0.0-alpha.18",
4
4
  "main": "dist-server/index.js",
5
5
  "browser": "dist-client/index.js",
6
6
  "things-factory": true,
@@ -30,10 +30,10 @@
30
30
  "migration:create": "node ../../node_modules/typeorm/cli.js migration:create -d ./server/migrations"
31
31
  },
32
32
  "dependencies": {
33
- "@things-factory/email-base": "^7.0.0-alpha.1",
33
+ "@things-factory/email-base": "^7.0.0-alpha.18",
34
34
  "@things-factory/env": "^7.0.0-alpha.0",
35
- "@things-factory/i18n-base": "^7.0.0-alpha.1",
36
- "@things-factory/shell": "^7.0.0-alpha.1",
35
+ "@things-factory/i18n-base": "^7.0.0-alpha.18",
36
+ "@things-factory/shell": "^7.0.0-alpha.18",
37
37
  "@things-factory/utils": "^7.0.0-alpha.0",
38
38
  "jsonwebtoken": "^9.0.0",
39
39
  "koa-passport": "^6.0.0",
@@ -43,5 +43,5 @@
43
43
  "passport-local": "^1.0.0",
44
44
  "popsicle-cookie-jar": "^1.0.0"
45
45
  },
46
- "gitHead": "778315d165d7f15e147583a45d5079c3d7cbce38"
46
+ "gitHead": "f695ce9c0e3a8f2d715d27a2e7674c9b9c6b1ee1"
47
47
  }
@@ -75,8 +75,8 @@ authPrivateProcessRouter
75
75
  var privileges = await User.getPrivilegesByDomain(user, domain)
76
76
 
77
77
  if (prohibitedPrivileges) {
78
- prohibitedPrivileges.forEach(({ category, name }) => {
79
- privileges = privileges.filter(p => p.category != category || p.name != name)
78
+ prohibitedPrivileges.forEach(({ category, privilege }) => {
79
+ privileges = privileges.filter(p => p.category != category || p.privilege != privilege)
80
80
  })
81
81
  }
82
82
 
@@ -33,6 +33,24 @@ export class ApplianceQuery {
33
33
  return { items, total }
34
34
  }
35
35
 
36
+ @Directive('@privilege(category: "user", privilege: "query", domainOwnerGranted: true, superUserGranted: true)')
37
+ @Query(returns => ApplianceList, { description: 'To fetch multiple appliance' })
38
+ async edges(@Args() params: ListParam, @Ctx() context: ResolverContext): Promise<ApplianceList> {
39
+ const { domain } = context.state
40
+
41
+ const queryBuilder = getQueryBuilderFromListParams({
42
+ domain,
43
+ params,
44
+ repository: getRepository(Appliance),
45
+ alias: 'appliance',
46
+ searchables: ['name', 'description']
47
+ })
48
+
49
+ const [items, total] = await queryBuilder.getManyAndCount()
50
+
51
+ return { items, total }
52
+ }
53
+
36
54
  @FieldResolver(type => String)
37
55
  async accessToken(@Root() appliance: Appliance, @Ctx() context: ResolverContext) {
38
56
  return appliance.accessToken
@@ -28,31 +28,14 @@ export class PrivilegeQuery {
28
28
  return { items, total }
29
29
  }
30
30
 
31
- @Query(returns => [Privilege], {
32
- description: 'To fetch current users privileges for current domain'
33
- })
34
- async myPrivileges(@Ctx() context: ResolverContext): Promise<Privilege[]> {
35
- const { user, domain } = context.state
36
-
37
- return User.getPrivilegesByDomain(user, domain)
38
- }
39
-
40
31
  @Query(returns => Boolean, { description: 'To query whether I have the given permission' })
41
- async hasPrivilege(
42
- @Arg('privilege') privilege: string,
43
- @Arg('category') category: string,
44
- @Ctx() context: ResolverContext
45
- ): Promise<Boolean> {
32
+ async hasPrivilege(@Arg('privilege') privilege: string, @Arg('category') category: string, @Ctx() context: ResolverContext): Promise<Boolean> {
46
33
  const { domain, user } = context.state
47
34
  return await User.hasPrivilege(privilege, category, domain, user)
48
35
  }
49
36
 
50
37
  @Query(returns => [Domain], { description: 'To fetch domains with given privilege for user' })
51
- async domainsWithPrivilege(
52
- @Arg('privilege') privilege: string,
53
- @Arg('category') category: string,
54
- @Ctx() context: ResolverContext
55
- ): Promise<Partial<Domain>[]> {
38
+ async domainsWithPrivilege(@Arg('privilege') privilege: string, @Arg('category') category: string, @Ctx() context: ResolverContext): Promise<Partial<Domain>[]> {
56
39
  const { user } = context.state
57
40
  return await User.getDomainsWithPrivilege(privilege, category, user)
58
41
  }
@@ -83,38 +83,6 @@ export class UserQuery {
83
83
  return Boolean(defaultPassword)
84
84
  }
85
85
 
86
- // @Query(returns => [User], { description: '...' })
87
- // async domainUsers(@Ctx() context: ResolverContext): Promise<User[]> {
88
- // const { domain } = context.state
89
-
90
- // const qb: SelectQueryBuilder<User> = buildDomainUsersQueryBuilder(domain.id, 'USER')
91
- // const domainUsers: User[] = await qb
92
- // .orWhere(qb => {
93
- // const subQuery = qb
94
- // .subQuery()
95
- // .select('CAST(APPLICATION.id as TEXT)')
96
- // .from(Application, 'APPLICATION')
97
- // .where('APPLICATION.domain_id = :domainId', { domainId: domain.id })
98
- // .getQuery()
99
- // return 'USER.reference IN ' + subQuery
100
- // })
101
- // .orWhere(qb => {
102
- // const subQuery = qb
103
- // .subQuery()
104
- // .select('CAST(APPLIANCE.id as TEXT)')
105
- // .from(Appliance, 'APPLIANCE')
106
- // .where('APPLIANCE.domain_id = :domainId', { domainId: domain.id })
107
- // .getQuery()
108
- // return 'USER.reference IN ' + subQuery
109
- // })
110
- // .getMany()
111
-
112
- // return domainUsers.map((user: User & { owner: boolean }) => {
113
- // user.owner = user.id === domain.owner
114
- // return user
115
- // })
116
- // }
117
-
118
86
  @Directive('@privilege(category: "user", privilege: "query")')
119
87
  @Query(returns => Boolean, { description: '...' })
120
88
  async checkUserExistence(@Arg('email', type => GraphQLEmailAddress) email: string): Promise<Boolean> {
@@ -2,19 +2,7 @@ import crypto from 'crypto'
2
2
  import jwt from 'jsonwebtoken'
3
3
  import { Directive, Field, ID, ObjectType } from 'type-graphql'
4
4
  import { GraphQLEmailAddress } from 'graphql-scalars'
5
- import {
6
- Column,
7
- CreateDateColumn,
8
- Entity,
9
- Index,
10
- JoinTable,
11
- ManyToMany,
12
- ManyToOne,
13
- OneToMany,
14
- PrimaryGeneratedColumn,
15
- RelationId,
16
- UpdateDateColumn
17
- } from 'typeorm'
5
+ import { Column, CreateDateColumn, Entity, Index, JoinTable, ManyToMany, ManyToOne, OneToMany, PrimaryGeneratedColumn, RelationId, UpdateDateColumn } from 'typeorm'
18
6
 
19
7
  import { config } from '@things-factory/env'
20
8
  import { Domain, getRepository } from '@things-factory/shell'
@@ -23,6 +11,7 @@ import { validatePasswordByRule } from '../../controllers/utils/password-rule'
23
11
  import { AuthError } from '../../errors/auth-error'
24
12
  import { SECRET } from '../../utils/get-secret'
25
13
  import { Role } from '../role/role'
14
+ import { Privilege } from '../privilege/privilege'
26
15
  import { UsersAuthProviders } from '../users-auth-providers/users-auth-providers'
27
16
  import { getDomainsWithPrivilege } from '../../utils/get-user-domains'
28
17
 
@@ -71,12 +60,7 @@ export class User {
71
60
  @Directive('@privilege(category: "security", privilege: "query", domainOwnerGranted: true)')
72
61
  @Column({
73
62
  nullable: true,
74
- type:
75
- DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb'
76
- ? 'longtext'
77
- : DATABASE_TYPE == 'oracle'
78
- ? 'clob'
79
- : 'varchar'
63
+ type: DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb' ? 'longtext' : DATABASE_TYPE == 'oracle' ? 'clob' : 'varchar'
80
64
  })
81
65
  password: string
82
66
 
@@ -113,12 +97,7 @@ export class User {
113
97
  ssoId: string
114
98
 
115
99
  @Column({
116
- type:
117
- DATABASE_TYPE == 'postgres' || DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb'
118
- ? 'enum'
119
- : DATABASE_TYPE == 'oracle'
120
- ? 'varchar2'
121
- : 'smallint',
100
+ type: DATABASE_TYPE == 'postgres' || DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb' ? 'enum' : DATABASE_TYPE == 'oracle' ? 'varchar2' : 'smallint',
122
101
  enum: UserStatus,
123
102
  default: UserStatus.INACTIVE
124
103
  })
@@ -313,39 +292,41 @@ export class User {
313
292
  }
314
293
  }
315
294
 
316
- static async hasPrivilege(privilege: string, category: string, domain: Domain, user: User) {
317
- const result = await getRepository(User).query(
318
- `
319
- SELECT COUNT(1) AS "has_privilege" FROM "privileges" "PRIVILEGES"
320
- WHERE "PRIVILEGES"."category" = '${category}'
321
- AND "PRIVILEGES"."name" = '${privilege}'
322
- AND "PRIVILEGES"."id" IN (
323
- SELECT "RP"."privileges_id"
324
- FROM "users_roles" "UR"
325
- INNER JOIN "roles_privileges" "RP" ON "UR"."roles_id" = "RP"."roles_id"
326
- LEFT JOIN "roles" "R" ON "R"."id" = "UR"."roles_id"
327
- WHERE "UR"."users_id" = '${user?.id}'
328
- AND "R"."domain_id" = '${domain?.id}'
329
- )
330
- `
331
- )
332
-
333
- return result[0].has_privilege > 0
295
+ static async hasPrivilege(privilege: string, category: string, domain: Domain, user: User): Promise<boolean> {
296
+ const result = await getRepository(Privilege)
297
+ .createQueryBuilder('privilege')
298
+ .innerJoin('privilege.roles', 'role')
299
+ .innerJoin('role.users', 'user')
300
+ .where('privilege.category = :category', { category })
301
+ .andWhere('privilege.name = :privilege', { privilege })
302
+ .andWhere('user.id = :userId', { userId: user.id })
303
+ .andWhere('role.domain.id = :domainId', { domainId: domain.id })
304
+ .getCount()
305
+
306
+ return result > 0
334
307
  }
335
308
 
336
- static async getPrivilegesByDomain(user: User, domain: Domain) {
337
- const result = await getRepository(User).query(`
338
- SELECT name privilege, category FROM "privileges" "PRIVILEGES"
339
- WHERE "PRIVILEGES"."id" IN (
340
- SELECT "RP"."privileges_id"
341
- FROM "users_roles" "UR"
342
- INNER JOIN "roles_privileges" "RP" ON "UR"."roles_id" = "RP"."roles_id"
343
- LEFT JOIN "roles" "R" ON "R"."id" = "UR"."roles_id"
344
- WHERE "UR"."users_id" = '${user.id}'
345
- AND "R"."domain_id" = '${domain.id}'
346
- )`)
347
-
348
- return result
309
+ static async getPrivilegesByDomain(user: User, domain: Domain): Promise<{ category: string; privilege: string }[]> {
310
+ const result = await getRepository(User)
311
+ .createQueryBuilder('user')
312
+ .leftJoinAndSelect('user.roles', 'role')
313
+ .leftJoinAndSelect('role.privileges', 'privilege')
314
+ .select(['privilege.name AS privilege', 'privilege.category AS category'])
315
+ .where('user.id = :userId', { userId: user.id })
316
+ .andWhere('role.domain.id = :domainId', { domainId: domain.id })
317
+ .orderBy('privilege.category')
318
+ .addOrderBy('privilege.name')
319
+ .getRawMany()
320
+
321
+ const distinct = result.reduce((acc, current) => {
322
+ const last = acc[acc.length - 1]
323
+ if (!last || last.privilege !== current.privilege || last.category !== current.category) {
324
+ acc.push(current)
325
+ }
326
+ return acc
327
+ }, [])
328
+
329
+ return distinct
349
330
  }
350
331
 
351
332
  static async getDomainsWithPrivilege(privilege: string, category: string, user: User) {
package/server/types.ts CHANGED
@@ -8,14 +8,14 @@ import { User } from './service/user/user'
8
8
  declare global {
9
9
  export type ResolverContext = {
10
10
  state: IContextState
11
- t: TFunction
11
+ t?: TFunction
12
12
  [key: string]: any
13
13
  }
14
14
 
15
15
  interface IContextState {
16
16
  domain: Domain
17
17
  user: User
18
- tx: EntityManager
18
+ tx?: EntityManager
19
19
  [key: string]: any
20
20
  }
21
21
  }