@things-factory/board-service 6.0.49 → 6.0.53

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.
Files changed (29) hide show
  1. package/dist-server/controllers/fonts.js +57 -2
  2. package/dist-server/controllers/fonts.js.map +1 -1
  3. package/dist-server/controllers/headless-pool-for-label.js +3 -2
  4. package/dist-server/controllers/headless-pool-for-label.js.map +1 -1
  5. package/dist-server/controllers/pdf.js +3 -1
  6. package/dist-server/controllers/pdf.js.map +1 -1
  7. package/dist-server/controllers/screenshot.js +3 -1
  8. package/dist-server/controllers/screenshot.js.map +1 -1
  9. package/dist-server/routers/board-print-router.js +0 -3
  10. package/dist-server/routers/board-print-router.js.map +1 -1
  11. package/dist-server/routers/standalone-board-service-router.js +30 -6
  12. package/dist-server/routers/standalone-board-service-router.js.map +1 -1
  13. package/dist-server/service/board/board-mutation.js +3 -0
  14. package/dist-server/service/board/board-mutation.js.map +1 -1
  15. package/dist-server/service/board/board-query.js +2 -0
  16. package/dist-server/service/board/board-query.js.map +1 -1
  17. package/dist-server/tsconfig.tsbuildinfo +1 -1
  18. package/package.json +4 -4
  19. package/server/controllers/fonts.ts +64 -5
  20. package/server/controllers/headless-pool-for-label.ts +3 -2
  21. package/server/controllers/pdf.ts +4 -1
  22. package/server/controllers/screenshot.ts +4 -1
  23. package/server/routers/board-print-router.ts +0 -3
  24. package/server/routers/standalone-board-service-router.ts +43 -7
  25. package/server/service/board/board-mutation.ts +3 -0
  26. package/server/service/board/board-query.ts +3 -1
  27. package/views/internal-board-full-feature-view.html +12 -2
  28. package/views/internal-board-service-view.html +12 -2
  29. package/views/internal-label-command-view.html +12 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@things-factory/board-service",
3
- "version": "6.0.49",
3
+ "version": "6.0.53",
4
4
  "main": "dist-server/index.js",
5
5
  "browser": "client/index.js",
6
6
  "things-factory": true,
@@ -23,9 +23,9 @@
23
23
  "migration:create": "node ../../node_modules/typeorm/cli.js migration:create -d ./server/migrations"
24
24
  },
25
25
  "dependencies": {
26
- "@things-factory/auth-base": "^6.0.49",
26
+ "@things-factory/auth-base": "^6.0.53",
27
27
  "@things-factory/env": "^6.0.49",
28
- "@things-factory/font-base": "^6.0.49",
28
+ "@things-factory/font-base": "^6.0.53",
29
29
  "content-disposition": "^0.5.3",
30
30
  "generic-pool": "^3.8.2"
31
31
  },
@@ -36,5 +36,5 @@
36
36
  "devDependencies": {
37
37
  "@types/puppeteer": "^5.4.6"
38
38
  },
39
- "gitHead": "e107d6f692d008add950e000d2653bcbbd711a24"
39
+ "gitHead": "1b60f52b7e043286423881b8fb41f1fa08f9ba6d"
40
40
  }
@@ -1,11 +1,70 @@
1
1
  import { SelectQueryBuilder } from 'typeorm'
2
2
 
3
3
  import { Font } from '@things-factory/font-base'
4
- import { getRepository } from '@things-factory/shell'
4
+ import { Attachment } from '@things-factory/attachment-base'
5
+ import { getRepository, Domain } from '@things-factory/shell'
5
6
 
6
- export const fonts = async () => {
7
+ export const fonts = async (domain?: Domain) => {
7
8
  const qb: SelectQueryBuilder<Font> = await getRepository(Font).createQueryBuilder('FONT')
8
- return (await qb.select('name').distinct(true).where({ active: true }).getRawMany()).map(
9
- (f: { name: string }) => f.name
10
- )
9
+
10
+ const fonts = domain
11
+ ? await qb
12
+ .select('name')
13
+ .distinct(true)
14
+ .addSelect('provider')
15
+ .addSelect('id')
16
+ .addSelect('uri')
17
+ .where({ domain: { id: domain.id }, active: true })
18
+ .getRawMany()
19
+ : await qb.select('name').distinct(true).where({ active: true }).getRawMany()
20
+
21
+ var googleFonts = fonts.filter(({ provider }) => provider == 'google')
22
+ var customFonts = fonts.filter(({ provider }) => provider == 'custom')
23
+
24
+ var customFontCSS: string = ''
25
+
26
+ for (const font of customFonts) {
27
+ var files: Attachment = domain
28
+ ? await getRepository(Attachment).findBy({
29
+ domain: { id: domain.id },
30
+ refBy: font.id
31
+ })
32
+ : await getRepository(Attachment).findBy({
33
+ refBy: font.id
34
+ })
35
+
36
+ if (files && files.length > 0) {
37
+ customFontCSS += files
38
+ .map(file => {
39
+ const { name: filename, fullpath } = file
40
+ const bold = filename.toUpperCase().indexOf('BOLD') !== -1
41
+
42
+ return `@font-face {
43
+ font-family: '${font.name}';
44
+ src: local('${font.name}'), url(${fullpath});
45
+ font-weight: ${bold ? 'bold' : 'normal'};
46
+ }
47
+ `
48
+ })
49
+ .join('\n')
50
+ } else {
51
+ customFontCSS += `@font-face {
52
+ font-family: '${font.name}';
53
+ src: local('${font.name}')${font.uri ? `, url(${font.uri})` : ''};
54
+ }
55
+ `
56
+ }
57
+ }
58
+
59
+ return [
60
+ {
61
+ google: {
62
+ families: googleFonts.map(({ name }) => name)
63
+ },
64
+ custom: {
65
+ families: customFonts.map(({ name }) => name)
66
+ }
67
+ },
68
+ customFontCSS
69
+ ]
11
70
  }
@@ -95,7 +95,7 @@ async function initializeScenePage() {
95
95
  const url = `${protocol}://${host}:${port}${path}`
96
96
 
97
97
  const page = await browser.newPage()
98
- const fontsToUse = await fonts()
98
+ const [fontsToUse, fontStyles] = await fonts()
99
99
 
100
100
  await page.setRequestInterception(true)
101
101
  page.on('console', msg => {
@@ -111,7 +111,8 @@ async function initializeScenePage() {
111
111
  'Content-Type': 'application/json'
112
112
  },
113
113
  postData: JSON.stringify({
114
- fonts: fontsToUse
114
+ fonts: fontsToUse,
115
+ fontStyles
115
116
  })
116
117
  })
117
118
  } else {
@@ -24,7 +24,10 @@ export const pdf = async ({
24
24
  const { domain, user } = context.state
25
25
 
26
26
  var { model, base } = await headlessModel({ domain, id, model })
27
- model.fonts = await fonts()
27
+ const [fontsToUse, fontStyles] = await fonts(domain)
28
+
29
+ model.fonts = fontsToUse
30
+ model.fontStyles = fontStyles
28
31
 
29
32
  let { width, height } = model
30
33
 
@@ -25,7 +25,10 @@ export const screenshot = async ({
25
25
  const { domain, user } = context.state
26
26
 
27
27
  var { model, base } = await headlessModel({ domain, id, model })
28
- model.fonts = await fonts()
28
+ const [fontsToUse, fontStyles] = await fonts(domain)
29
+
30
+ model.fonts = fontsToUse
31
+ model.fontStyles = fontStyles
29
32
 
30
33
  var { width, height } = model
31
34
 
@@ -9,7 +9,6 @@ export const boardPrintRouter = new Router()
9
9
  * ?printerId=printer_id&data=grf_string
10
10
  */
11
11
  boardPrintRouter.get('/print', async (context, next) => {
12
- const { domain } = context.state
13
12
  let data = Object.keys(context.query).length ? context.query : null
14
13
 
15
14
  context.body = await printDirect(data.printerId, data.data)
@@ -19,7 +18,6 @@ boardPrintRouter.get('/print', async (context, next) => {
19
18
  * { printerId: 'printer driver ID', data: 'grf string' }
20
19
  */
21
20
  boardPrintRouter.post('/print', async (context, next) => {
22
- const { domain } = context.state
23
21
  let params = context.request.body
24
22
 
25
23
  context.type = 'text/plain'
@@ -27,7 +25,6 @@ boardPrintRouter.post('/print', async (context, next) => {
27
25
  })
28
26
 
29
27
  boardPrintRouter.get('/print-label/:id', async (context, next) => {
30
- const { domain } = context.state
31
28
  const { id } = context.params
32
29
  let data = Object.keys(context.query).length ? context.query : null
33
30
 
@@ -1,7 +1,7 @@
1
1
  import contentDisposition from 'content-disposition'
2
2
  import Router from 'koa-router'
3
3
 
4
- import { setAccessTokenCookie } from '@things-factory/auth-base'
4
+ import { User, setAccessTokenCookie } from '@things-factory/auth-base'
5
5
  import { getRepository } from '@things-factory/shell'
6
6
 
7
7
  import { fonts } from '../controllers/fonts'
@@ -13,13 +13,22 @@ import { Board } from '../service/board/board'
13
13
 
14
14
  export const standaloneBoardServiceRouter = new Router()
15
15
 
16
- // for board headless
16
+ // for board headless-full
17
17
  standaloneBoardServiceRouter.get('/headless-full/:id', async (context, next) => {
18
18
  const { domain, user } = context.state
19
+
20
+ if (!(await User.hasPrivilege('query', 'board', domain, user))) {
21
+ context.status = 403
22
+ return
23
+ }
24
+
19
25
  const { id } = context.params
20
26
 
21
27
  const { model, base } = await headlessModel({ domain, id })
22
- model.fonts = await fonts()
28
+ const [fontsToUse, fontStyles] = await fonts(domain)
29
+
30
+ model.fonts = fontsToUse
31
+ model.fontStyles = fontStyles
23
32
 
24
33
  setAccessTokenCookie(context, await user.sign({ domain }))
25
34
 
@@ -29,10 +38,19 @@ standaloneBoardServiceRouter.get('/headless-full/:id', async (context, next) =>
29
38
  // for board headless
30
39
  standaloneBoardServiceRouter.get('/headless/:id', async (context, next) => {
31
40
  const { domain, user } = context.state
41
+
42
+ if (!(await User.hasPrivilege('query', 'board', domain, user))) {
43
+ context.status = 403
44
+ return
45
+ }
46
+
32
47
  const { id } = context.params
33
48
 
34
49
  const { model, base } = await headlessModel({ domain, id })
35
- model.fonts = await fonts()
50
+ const [fontsToUse, fontStyles] = await fonts(domain)
51
+
52
+ model.fonts = fontsToUse
53
+ model.fontStyles = fontStyles
36
54
 
37
55
  setAccessTokenCookie(context, await user.sign({ domain }))
38
56
 
@@ -41,7 +59,13 @@ standaloneBoardServiceRouter.get('/headless/:id', async (context, next) => {
41
59
 
42
60
  // for board thumbnail
43
61
  standaloneBoardServiceRouter.get('/thumbnail/:id', async (context, next) => {
44
- const { domain } = context.state
62
+ const { domain, user } = context.state
63
+
64
+ if (!(await User.hasPrivilege('query', 'board', domain, user))) {
65
+ context.status = 403
66
+ return
67
+ }
68
+
45
69
  const { id } = context.params
46
70
 
47
71
  const { name, thumbnail } = (await getRepository(Board).findOneBy({ domain: { id: domain.id }, id })) || {}
@@ -61,7 +85,13 @@ standaloneBoardServiceRouter.get('/thumbnail/:id', async (context, next) => {
61
85
 
62
86
  // for webpage scrap
63
87
  standaloneBoardServiceRouter.get('/screenshot/:id', async (context, next) => {
64
- const { domain } = context.state
88
+ const { domain, user } = context.state
89
+
90
+ if (!(await User.hasPrivilege('query', 'board', domain, user))) {
91
+ context.status = 403
92
+ return
93
+ }
94
+
65
95
  const { id } = context.params
66
96
 
67
97
  const { model, board } = await headlessModel({ domain, id })
@@ -74,7 +104,13 @@ standaloneBoardServiceRouter.get('/screenshot/:id', async (context, next) => {
74
104
 
75
105
  // for webpage scrap
76
106
  standaloneBoardServiceRouter.get('/board/pdf/:id', async (context, next) => {
77
- const { domain } = context.state
107
+ const { domain, user } = context.state
108
+
109
+ if (!(await User.hasPrivilege('query', 'board', domain, user))) {
110
+ context.status = 403
111
+ return
112
+ }
113
+
78
114
  const { id } = context.params
79
115
 
80
116
  const { model, board } = await headlessModel({ domain, id })
@@ -9,6 +9,7 @@ import { BoardPatch, NewBoard } from './board-type'
9
9
  @Resolver(Board)
10
10
  export class BoardMutation {
11
11
  @Directive('@transaction')
12
+ @Directive('@privilege(category: "board", privilege: "mutation", domainOwnerGranted: true)')
12
13
  @Mutation(returns => Board, { description: 'To create new Board' })
13
14
  async createBoard(@Arg('board') board: NewBoard, @Ctx() context: ResolverContext): Promise<Board> {
14
15
  const { domain, user, notify, tx } = context.state
@@ -64,6 +65,7 @@ export class BoardMutation {
64
65
  }
65
66
 
66
67
  @Directive('@transaction')
68
+ @Directive('@privilege(category: "board", privilege: "mutation", domainOwnerGranted: true)')
67
69
  @Mutation(returns => Board, { description: 'To modify Board information' })
68
70
  async updateBoard(
69
71
  @Arg('id') id: string,
@@ -118,6 +120,7 @@ export class BoardMutation {
118
120
  }
119
121
 
120
122
  @Directive('@transaction')
123
+ @Directive('@privilege(category: "board", privilege: "mutation", domainOwnerGranted: true)')
121
124
  @Mutation(returns => Boolean, { description: 'To delete Board' })
122
125
  async deleteBoard(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<boolean> {
123
126
  const { domain, user, notify, tx } = context.state
@@ -1,4 +1,4 @@
1
- import { Arg, Args, Ctx, FieldResolver, Query, Resolver, Root } from 'type-graphql'
1
+ import { Arg, Args, Ctx, FieldResolver, Query, Resolver, Root, Directive } from 'type-graphql'
2
2
 
3
3
  import { User } from '@things-factory/auth-base'
4
4
  import { Domain, getQueryBuilderFromListParams, getRepository, ListParam } from '@things-factory/shell'
@@ -11,6 +11,7 @@ import { BoardList } from './board-type'
11
11
  @Resolver(Board)
12
12
  export class BoardQuery {
13
13
  @Query(returns => Board, { description: 'To fetch a Board' })
14
+ @Directive('@privilege(category: "board", privilege: "query")')
14
15
  async board(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<Board> {
15
16
  const { domain } = context.state
16
17
 
@@ -37,6 +38,7 @@ export class BoardQuery {
37
38
  }
38
39
 
39
40
  @Query(returns => BoardList, { description: 'To fetch multiple Boards' })
41
+ @Directive('@privilege(category: "board", privilege: "query")')
40
42
  async boards(@Args() params: ListParam, @Ctx() context: ResolverContext): Promise<BoardList> {
41
43
  const { domain } = context.state
42
44
 
@@ -34,9 +34,19 @@
34
34
 
35
35
  <script>
36
36
  var model = <%- JSON.stringify(model) %>;
37
+
38
+ let style = document.head.querySelector('#custom-fonts')
39
+ if (!style) {
40
+ style = document.createElement('style')
41
+ style.id = 'custom-fonts'
42
+ document.head.appendChild(style)
43
+ }
44
+ style.innerHTML = model.fontStyles
45
+
37
46
  WebFont.load({
38
- google: {
39
- families: model.fonts || []
47
+ ...model.fonts,
48
+ fontactive: () => {
49
+ window.dispatchEvent(new CustomEvent('resize'))
40
50
  }
41
51
  })
42
52
  </script>
@@ -25,9 +25,19 @@
25
25
  <script src="https://ajax.googleapis.com/ajax/libs/webfont/1.6.26/webfont.js"></script>
26
26
  <script>
27
27
  var model = <%- JSON.stringify(model) %>;
28
+
29
+ let style = document.head.querySelector('#custom-fonts')
30
+ if (!style) {
31
+ style = document.createElement('style')
32
+ style.id = 'custom-fonts'
33
+ document.head.appendChild(style)
34
+ }
35
+ style.innerHTML = model.fontStyles
36
+
28
37
  WebFont.load({
29
- google: {
30
- families: model.fonts || []
38
+ ...model.fonts,
39
+ fontactive: () => {
40
+ window.dispatchEvent(new CustomEvent('resize'))
31
41
  }
32
42
  })
33
43
  </script>
@@ -23,9 +23,19 @@
23
23
  <script src="https://ajax.googleapis.com/ajax/libs/webfont/1.6.26/webfont.js"></script>
24
24
  <script>
25
25
  var model = <%- JSON.stringify(model) %>;
26
+
27
+ let style = document.head.querySelector('#custom-fonts')
28
+ if (!style) {
29
+ style = document.createElement('style')
30
+ style.id = 'custom-fonts'
31
+ document.head.appendChild(style)
32
+ }
33
+ style.innerHTML = model.fontStyles
34
+
26
35
  WebFont.load({
27
- google: {
28
- families: model.fonts || []
36
+ ...model.fonts,
37
+ fontactive: () => {
38
+ window.dispatchEvent(new CustomEvent('resize'))
29
39
  }
30
40
  })
31
41
  </script>