adapt-authoring-adaptframework 2.0.10 → 2.1.0

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.
@@ -1,10 +1,10 @@
1
1
  import _ from 'lodash'
2
2
  import { App, Hook, ensureDir, writeJson } from 'adapt-authoring-core'
3
3
  import { parseObjectId } from 'adapt-authoring-mongodb'
4
- import { createWriteStream } from 'fs'
4
+ import { createWriteStream } from 'node:fs'
5
5
  import AdaptCli from 'adapt-cli'
6
6
  import { log, logDir, logMemory, copyFrameworkSource } from './utils.js'
7
- import fs from 'fs/promises'
7
+ import fs from 'node:fs/promises'
8
8
  import path from 'upath'
9
9
  import semver from 'semver'
10
10
  import zipper from 'zipper'
@@ -1,6 +1,6 @@
1
1
  import { App, Hook, spawn, readJson, writeJson } from 'adapt-authoring-core'
2
2
  import { parseObjectId } from 'adapt-authoring-mongodb'
3
- import fs from 'fs/promises'
3
+ import fs from 'node:fs/promises'
4
4
  import { glob } from 'glob'
5
5
  import octopus from 'adapt-octopus'
6
6
  import path from 'upath'
@@ -630,7 +630,8 @@ class AdaptFrameworkImport {
630
630
 
631
631
  let managedPluginUpdateBlocked = false
632
632
  Object.keys(this.usedContentPlugins).forEach(p => {
633
- const installedP = this.installedPlugins[p]
633
+ const { name: pluginName } = this.usedContentPlugins[p]
634
+ const installedP = this.installedPlugins[pluginName]
634
635
  let { version: importVersion } = this.usedContentPlugins[p]
635
636
  if (!semver.valid(importVersion)) {
636
637
  if (!installedP) {
@@ -677,8 +678,9 @@ class AdaptFrameworkImport {
677
678
  // pre-process: store update metadata and fix missing targetAttributes
678
679
  for (const p of allPlugins) {
679
680
  const isUpdate = pluginsToUpdate.includes(p)
680
- if (isUpdate && this.installedPlugins[p]) {
681
- this.updatedContentPlugins[p] = this.installedPlugins[p]
681
+ const { name: pName } = this.usedContentPlugins[p]
682
+ if (isUpdate && this.installedPlugins[pName]) {
683
+ this.updatedContentPlugins[p] = this.installedPlugins[pName]
682
684
  }
683
685
  const pluginBowerPath = path.join(this.usedContentPlugins[p].path, 'bower.json')
684
686
  const bowerJson = await readJson(pluginBowerPath)
@@ -1,11 +1,11 @@
1
1
  import { AbstractModule, Hook, readJson } from 'adapt-authoring-core'
2
2
  import AdaptFrameworkBuild from './AdaptFrameworkBuild.js'
3
3
  import AdaptFrameworkImport from './AdaptFrameworkImport.js'
4
- import ApiDefs from './apidefs.js'
5
- import fs from 'fs/promises'
4
+ import fs from 'node:fs/promises'
6
5
  import { getHandler, postHandler, importHandler, postUpdateHandler, getUpdateHandler } from './handlers.js'
6
+ import { loadRouteConfig } from 'adapt-authoring-server'
7
7
  import { runCliCommand } from './utils.js'
8
- import path from 'path'
8
+ import path from 'node:path'
9
9
  import semver from 'semver'
10
10
 
11
11
  /**
@@ -229,44 +229,16 @@ class AdaptFrameworkModule extends AbstractModule {
229
229
  * Router for handling all API calls
230
230
  * @type {Router}
231
231
  */
232
- this.apiRouter = server.api.createChildRouter('adapt')
233
- this.apiRouter.addRoute(
234
- {
235
- route: '/preview/:id',
236
- handlers: { post: postHandler },
237
- meta: ApiDefs.preview
238
- },
239
- {
240
- route: '/publish/:id',
241
- handlers: { post: postHandler, get: getHandler },
242
- meta: ApiDefs.publish
243
- },
244
- {
245
- route: '/import',
246
- handlers: { post: [importHandler] },
247
- meta: ApiDefs.import
248
- },
249
- {
250
- route: '/export/:id',
251
- handlers: { post: postHandler, get: getHandler },
252
- meta: ApiDefs.export
232
+ const config = await loadRouteConfig(this.rootDir, this, {
233
+ handlerAliases: { getHandler, postHandler, importHandler, postUpdateHandler, getUpdateHandler }
234
+ })
235
+ this.apiRouter = server.api.createChildRouter(config.root)
236
+ for (const r of config.routes) {
237
+ this.apiRouter.addRoute(r)
238
+ if (!r.permissions) continue
239
+ for (const [method, perms] of Object.entries(r.permissions)) {
240
+ auth.secureRoute(`${this.apiRouter.path}${r.route}`, method, perms)
253
241
  }
254
- )
255
- auth.secureRoute(`${this.apiRouter.path}/preview/:id`, 'post', ['preview:adapt'])
256
- auth.secureRoute(`${this.apiRouter.path}/publish/:id`, 'get', ['publish:adapt'])
257
- auth.secureRoute(`${this.apiRouter.path}/publish/:id`, 'post', ['publish:adapt'])
258
- auth.secureRoute(`${this.apiRouter.path}/import`, 'post', ['import:adapt'])
259
- auth.secureRoute(`${this.apiRouter.path}/export/:id`, 'get', ['export:adapt'])
260
- auth.secureRoute(`${this.apiRouter.path}/export/:id`, 'post', ['export:adapt'])
261
- auth.secureRoute(`${this.apiRouter.path}/update`, 'post', ['update:adapt'])
262
-
263
- if (this.getConfig('enableUpdateApi')) {
264
- this.apiRouter.addRoute({
265
- route: '/update',
266
- handlers: { post: postUpdateHandler, get: getUpdateHandler },
267
- meta: ApiDefs.update
268
- })
269
- auth.secureRoute(`${this.apiRouter.path}/update`, 'get', ['update:adapt'])
270
242
  }
271
243
  }
272
244
 
package/lib/handlers.js CHANGED
@@ -127,8 +127,11 @@ export async function importHandler (req, res, next) {
127
127
  */
128
128
  export async function postUpdateHandler (req, res, next) {
129
129
  try {
130
- log('info', 'running framework update')
131
130
  const framework = await App.instance.waitForModule('adaptframework')
131
+ if (!framework.getConfig('enableUpdateApi')) {
132
+ return next(App.instance.errors.NOT_FOUND.setData({ type: 'route', id: req.originalUrl }))
133
+ }
134
+ log('info', 'running framework update')
132
135
  const previousVersion = framework.version
133
136
  await framework.updateFramework(req.body.version)
134
137
  const currentVersion = framework.version !== previousVersion ? framework.version : undefined
@@ -151,6 +154,9 @@ export async function postUpdateHandler (req, res, next) {
151
154
  export async function getUpdateHandler (req, res, next) {
152
155
  try {
153
156
  const framework = await App.instance.waitForModule('adaptframework')
157
+ if (!framework.getConfig('enableUpdateApi')) {
158
+ return next(App.instance.errors.NOT_FOUND.setData({ type: 'route', id: req.originalUrl }))
159
+ }
154
160
  const current = framework.version
155
161
  const latest = await framework.getLatestVersion()
156
162
  res.json({
@@ -1,5 +1,5 @@
1
1
  import { App } from 'adapt-authoring-core'
2
- import fs from 'fs/promises'
2
+ import fs from 'node:fs/promises'
3
3
  import path from 'upath'
4
4
 
5
5
  /**
package/lib/utils/log.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { App } from 'adapt-authoring-core'
2
2
  import bytes from 'bytes'
3
- import fsSync from 'fs'
3
+ import fsSync from 'node:fs'
4
4
  import path from 'upath'
5
5
 
6
6
  let fw
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adapt-authoring-adaptframework",
3
- "version": "2.0.10",
3
+ "version": "2.1.0",
4
4
  "description": "Adapt framework integration for the Adapt authoring tool",
5
5
  "homepage": "https://github.com/adapt-security/adapt-authoring-adaptframework",
6
6
  "license": "GPL-3.0",
@@ -34,7 +34,7 @@
34
34
  "adapt-authoring-auth": "^2.0.0",
35
35
  "adapt-authoring-jsonschema": "^1.1.5",
36
36
  "adapt-authoring-middleware": "^1.0.1",
37
- "adapt-authoring-server": "^2.0.0",
37
+ "adapt-authoring-server": "^2.1.0",
38
38
  "adapt-authoring-tags": "^1.0.1"
39
39
  },
40
40
  "devDependencies": {
package/routes.json ADDED
@@ -0,0 +1,216 @@
1
+ {
2
+ "root": "adapt",
3
+ "routes": [
4
+ {
5
+ "route": "/preview/:id",
6
+ "handlers": { "post": "postHandler" },
7
+ "permissions": { "post": ["preview:adapt"] },
8
+ "meta": {
9
+ "post": {
10
+ "summary": "Build a preview of an Adapt course",
11
+ "responses": {
12
+ "200": {
13
+ "description": "The Adapt build data",
14
+ "content": {
15
+ "application/json": {
16
+ "schema": { "$ref": "#components/schemas/adaptbuild" }
17
+ }
18
+ }
19
+ }
20
+ }
21
+ }
22
+ }
23
+ },
24
+ {
25
+ "route": "/publish/:id",
26
+ "handlers": { "post": "postHandler", "get": "getHandler" },
27
+ "permissions": { "post": ["publish:adapt"], "get": ["publish:adapt"] },
28
+ "meta": {
29
+ "post": {
30
+ "summary": "Create a publish zip of an Adapt course",
31
+ "responses": {
32
+ "200": {
33
+ "description": "The Adapt build data",
34
+ "content": {
35
+ "application/json": {
36
+ "schema": { "$ref": "#components/schemas/adaptbuild" }
37
+ }
38
+ }
39
+ }
40
+ }
41
+ },
42
+ "get": {
43
+ "summary": "Retrieve an Adapt course publish zip",
44
+ "responses": {
45
+ "200": {
46
+ "description": "Course build zip file",
47
+ "content": { "application/zip": {} }
48
+ }
49
+ }
50
+ }
51
+ }
52
+ },
53
+ {
54
+ "route": "/import",
55
+ "handlers": { "post": "importHandler" },
56
+ "permissions": { "post": ["import:adapt"] },
57
+ "meta": {
58
+ "post": {
59
+ "summary": "Import an Adapt course",
60
+ "requestBody": {
61
+ "content": {
62
+ "application/json": {
63
+ "schema": {
64
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
65
+ "type": "object",
66
+ "properties": {
67
+ "path": { "type": "String" },
68
+ "isDryRun": { "type": "Boolean", "default": false },
69
+ "importContent": { "type": "Boolean", "default": true },
70
+ "importPlugins": { "type": "Boolean", "default": true },
71
+ "updatePlugins": { "type": "Boolean", "default": false }
72
+ }
73
+ }
74
+ }
75
+ }
76
+ },
77
+ "responses": {
78
+ "200": {
79
+ "description": "",
80
+ "content": {
81
+ "application/json": {
82
+ "schema": {
83
+ "properties": {
84
+ "title": { "type": "string" },
85
+ "courseId": { "type": "string" },
86
+ "versions": { "type": "object" },
87
+ "content": {
88
+ "type": "object",
89
+ "properties": {
90
+ "course": { "type": "number" },
91
+ "config": { "type": "number" },
92
+ "menu": { "type": "number" },
93
+ "page": { "type": "number" },
94
+ "article": { "type": "number" },
95
+ "block": { "type": "number" },
96
+ "component": { "type": "number" }
97
+ }
98
+ },
99
+ "statusReport": {
100
+ "type": "object",
101
+ "properties": {
102
+ "error": {
103
+ "type": "array",
104
+ "items": {
105
+ "type": "object",
106
+ "properties": {
107
+ "code": { "type": "string" },
108
+ "data": { "type": "string" }
109
+ }
110
+ }
111
+ },
112
+ "warn": {
113
+ "type": "array",
114
+ "items": {
115
+ "type": "object",
116
+ "properties": {
117
+ "code": { "type": "string" },
118
+ "data": { "type": "string" }
119
+ }
120
+ }
121
+ },
122
+ "info": {
123
+ "type": "array",
124
+ "items": {
125
+ "type": "object",
126
+ "properties": {
127
+ "code": { "type": "string" },
128
+ "data": { "type": "string" }
129
+ }
130
+ }
131
+ }
132
+ }
133
+ }
134
+ }
135
+ }
136
+ }
137
+ }
138
+ }
139
+ }
140
+ }
141
+ }
142
+ },
143
+ {
144
+ "route": "/export/:id",
145
+ "handlers": { "post": "postHandler", "get": "getHandler" },
146
+ "permissions": { "post": ["export:adapt"], "get": ["export:adapt"] },
147
+ "meta": {
148
+ "post": {
149
+ "summary": "Create an export zip of an Adapt course",
150
+ "responses": {
151
+ "200": {
152
+ "description": "The Adapt build data",
153
+ "content": {
154
+ "application/json": {
155
+ "schema": { "$ref": "#components/schemas/adaptbuild" }
156
+ }
157
+ }
158
+ }
159
+ }
160
+ },
161
+ "get": {
162
+ "summary": "Retrieve an Adapt course export zip",
163
+ "responses": {
164
+ "200": {
165
+ "description": "Course build zip file",
166
+ "content": { "application/zip": {} }
167
+ }
168
+ }
169
+ }
170
+ }
171
+ },
172
+ {
173
+ "route": "/update",
174
+ "handlers": { "post": "postUpdateHandler", "get": "getUpdateHandler" },
175
+ "permissions": { "post": ["update:adapt"], "get": ["update:adapt"] },
176
+ "meta": {
177
+ "post": {
178
+ "summary": "Updates the installed framework",
179
+ "responses": {
180
+ "200": {
181
+ "description": "Describes the upgraded elements",
182
+ "content": {
183
+ "application/json": {
184
+ "schema": {
185
+ "properties": {
186
+ "from": { "type": "string" },
187
+ "to": { "type": "string" }
188
+ }
189
+ }
190
+ }
191
+ }
192
+ }
193
+ }
194
+ },
195
+ "get": {
196
+ "summary": "Retrieve framework update data",
197
+ "responses": {
198
+ "200": {
199
+ "content": {
200
+ "application/json": {
201
+ "schema": {
202
+ "properties": {
203
+ "canBeUpdated": { "type": "boolean" },
204
+ "currentVersion": { "type": "string" },
205
+ "latestCompatibleVersion": { "type": "string" }
206
+ }
207
+ }
208
+ }
209
+ }
210
+ }
211
+ }
212
+ }
213
+ }
214
+ }
215
+ ]
216
+ }
@@ -337,7 +337,6 @@ describe('AdaptFrameworkImport', () => {
337
337
 
338
338
  describe('#cleanUp()', () => {
339
339
  const cleanUp = AdaptFrameworkImport.prototype.cleanUp
340
- const rollback = AdaptFrameworkImport.prototype.rollback
341
340
 
342
341
  it('should call rollback when an error is passed', async () => {
343
342
  let rollbackCalled = false
package/lib/apidefs.js DELETED
@@ -1,153 +0,0 @@
1
- const responseDataMeta = {
2
- 200: {
3
- description: 'The Adapt build data',
4
- content: {
5
- 'application/json': {
6
- schema: { $ref: '#components/schemas/adaptbuild' }
7
- }
8
- }
9
- }
10
- }
11
-
12
- const responseZipMeta = {
13
- 200: {
14
- description: 'Course build zip file',
15
- content: { 'application/zip': {} }
16
- }
17
- }
18
-
19
- const statusReportItemSchema = {
20
- type: 'array',
21
- items: {
22
- type: 'object',
23
- properties: {
24
- code: { type: 'string' },
25
- data: { type: 'string' }
26
- }
27
- }
28
- }
29
-
30
- export default {
31
- preview: {
32
- post: {
33
- summary: 'Build a preview of an Adapt course',
34
- responses: responseDataMeta
35
- }
36
- },
37
- publish: {
38
- post: {
39
- summary: 'Create a publish zip of an Adapt course',
40
- responses: responseDataMeta
41
- },
42
- get: {
43
- summary: 'Retrieve an Adapt course publish zip',
44
- responses: responseZipMeta
45
- }
46
- },
47
- import: {
48
- post: {
49
- summary: 'Import an Adapt course',
50
- requestBody: {
51
- content: {
52
- 'application/json': {
53
- schema: {
54
- $schema: 'https://json-schema.org/draft/2020-12/schema',
55
- type: 'object',
56
- properties: {
57
- path: { type: 'String' },
58
- isDryRun: { type: 'Boolean', default: false },
59
- importContent: { type: 'Boolean', default: true },
60
- importPlugins: { type: 'Boolean', default: true },
61
- updatePlugins: { type: 'Boolean', default: false }
62
- }
63
- }
64
- }
65
- }
66
- },
67
- responses: {
68
- 200: {
69
- description: '',
70
- content: {
71
- 'application/json': {
72
- schema: {
73
- properties: {
74
- title: { type: 'string' },
75
- courseId: { type: 'string' },
76
- versions: { type: 'object' },
77
- content: {
78
- type: 'object',
79
- properties: {
80
- course: { type: 'number' },
81
- config: { type: 'number' },
82
- menu: { type: 'number' },
83
- page: { type: 'number' },
84
- article: { type: 'number' },
85
- block: { type: 'number' },
86
- component: { type: 'number' }
87
- }
88
- },
89
- statusReport: {
90
- type: 'object',
91
- properties: {
92
- error: statusReportItemSchema,
93
- warn: statusReportItemSchema,
94
- info: statusReportItemSchema
95
- }
96
- }
97
- }
98
- }
99
- }
100
- }
101
- }
102
- }
103
- }
104
- },
105
- export: {
106
- post: {
107
- summary: 'Create an export zip of an Adapt course',
108
- responses: responseDataMeta
109
- },
110
- get: {
111
- summary: 'Retrieve an Adapt course export zip',
112
- responses: responseZipMeta
113
- }
114
- },
115
- update: {
116
- post: {
117
- summary: 'Updates the installed framework',
118
- responses: {
119
- 200: {
120
- description: 'Describes the upgraded elements',
121
- content: {
122
- 'application/json': {
123
- schema: {
124
- properties: {
125
- from: { type: 'string' },
126
- to: { type: 'string' }
127
- }
128
- }
129
- }
130
- }
131
- }
132
- }
133
- },
134
- get: {
135
- summary: 'Retrieve framework update data',
136
- responses: {
137
- 200: {
138
- content: {
139
- 'application/json': {
140
- schema: {
141
- properties: {
142
- canBeUpdated: { type: 'boolean' },
143
- currentVersion: { type: 'string' },
144
- latestCompatibleVersion: { type: 'string' }
145
- }
146
- }
147
- }
148
- }
149
- }
150
- }
151
- }
152
- }
153
- }