@ossy/workspaces 1.17.2 → 1.17.3
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.
- package/package.json +8 -4
- package/src/CreateWorkspacePage.jsx +7 -16
- package/src/Definition.js +1 -0
- package/src/GeneralSettings.jsx +77 -19
- package/src/Invitations.jsx +7 -7
- package/src/Invite.jsx +13 -25
- package/src/SchemasReadBootstrap.jsx +20 -0
- package/src/SelectWorkspacePage.jsx +5 -8
- package/src/Users.jsx +7 -7
- package/src/Users.page.jsx +3 -3
- package/src/accept-invitation.action.js +1 -1
- package/src/accept-invitation.api.js +46 -0
- package/src/accept-invitation.task.js +6 -5
- package/src/create-api-token.action.js +1 -1
- package/src/create-api-token.task.js +1 -1
- package/src/create.action.js +1 -1
- package/src/create.task.js +1 -1
- package/src/disable-service.action.js +1 -1
- package/src/disable-service.task.js +3 -15
- package/src/en.translations.json +36 -30
- package/src/enable-service.action.js +1 -1
- package/src/enable-service.task.js +3 -15
- package/src/entitlements.js +199 -0
- package/src/entitlements.spec.js +88 -0
- package/src/get-api-tokens.action.js +1 -1
- package/src/get-api-tokens.task.js +1 -1
- package/src/get-invitations.action.js +1 -1
- package/src/get-invitations.task.js +1 -1
- package/src/get-schemas.action.js +1 -0
- package/src/get-schemas.task.js +14 -0
- package/src/get-users.action.js +1 -1
- package/src/get-users.task.js +1 -1
- package/src/get.action.js +1 -1
- package/src/get.task.js +1 -1
- package/src/import-schemas.action.js +1 -0
- package/src/import-schemas.task.js +26 -0
- package/src/index.js +3 -2
- package/src/invite-user.action.js +1 -1
- package/src/invite-user.task.js +4 -3
- package/src/list.action.js +1 -1
- package/src/list.task.js +1 -1
- package/src/merge-workspace-schemas.js +13 -0
- package/src/merge-workspace-schemas.spec.js +16 -0
- package/src/remove-member.action.js +1 -1
- package/src/remove-member.task.js +1 -1
- package/src/schema-ids.js +3 -0
- package/src/select-workspace.api.js +50 -0
- package/src/selectWorkspace.js +11 -0
- package/src/service-keys.js +1 -0
- package/src/stories/Users.stories.jsx +35 -0
- package/src/stories/decorators.jsx +59 -0
- package/src/sv.translations.json +36 -30
- package/src/sync-workspace-membership.task.js +7 -6
- package/src/workspace-invitation.email.jsx +1 -1
- package/src/workspace-users.component.jsx +3 -3
- package/src/workspace.aggregate.js +35 -47
- package/src/workspace.schema.js +9 -0
- package/src/workspaces.events.js +61 -155
- package/src/{workspaces.spec.js → workspaces.integration.spec.js} +40 -38
- package/src/workspaces.queries.js +27 -12
- package/src/get-resource-templates.action.js +0 -1
- package/src/get-resource-templates.task.js +0 -18
- package/src/import-resource-templates.action.js +0 -1
- package/src/import-resource-templates.task.js +0 -26
package/src/workspaces.events.js
CHANGED
|
@@ -1,171 +1,77 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
* @typedef {Object} Field
|
|
4
|
-
* @property {string} type - field type
|
|
5
|
-
* @property {string} name - name of field
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* ResourceTemplate
|
|
10
|
-
* @typedef {Object} ResourceTemplate
|
|
11
|
-
* @property {string} name - Displayname of the resource template
|
|
12
|
-
* @property {Field[]} fields - Allowed fields
|
|
13
|
-
*/
|
|
14
|
-
|
|
1
|
+
import { nanoid } from 'nanoid'
|
|
2
|
+
import { WorkspaceSchema } from './schema-ids.js'
|
|
15
3
|
|
|
16
4
|
/**
|
|
17
|
-
|
|
18
|
-
|
|
5
|
+
* ADR 0008 workspace entity events.
|
|
6
|
+
*/
|
|
19
7
|
export class WorkspacesEvents {
|
|
20
8
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
9
|
+
static Created ({ resourceId, createdBy, name }) {
|
|
10
|
+
return {
|
|
11
|
+
type: WorkspaceSchema.workspace,
|
|
12
|
+
resourceId: resourceId ?? nanoid(),
|
|
13
|
+
event: 'Created',
|
|
14
|
+
createdBy,
|
|
15
|
+
payload: { name },
|
|
16
|
+
}
|
|
17
|
+
}
|
|
28
18
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
19
|
+
static SchemasImported ({ createdBy, schemas }) {
|
|
20
|
+
return {
|
|
21
|
+
event: 'SchemasImported',
|
|
22
|
+
createdBy,
|
|
23
|
+
payload: { schemas },
|
|
24
|
+
}
|
|
25
|
+
}
|
|
34
26
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
27
|
+
static ApiTokenCreated ({ createdBy, description, token }) {
|
|
28
|
+
return {
|
|
29
|
+
event: 'ApiTokenCreated',
|
|
30
|
+
createdBy,
|
|
31
|
+
payload: { description, token },
|
|
32
|
+
}
|
|
33
|
+
}
|
|
41
34
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
* @return {Created} - Workspace created event
|
|
47
|
-
*
|
|
48
|
-
* @example
|
|
49
|
-
* const name = 'ossy.se'
|
|
50
|
-
* const createdBy = 'fake-user-id-123'
|
|
51
|
-
*
|
|
52
|
-
* const event = WorkspacesEvents.Created({ name, createdBy })
|
|
53
|
-
*
|
|
54
|
-
* Aggregate.Of(Workspace, event)
|
|
55
|
-
*/
|
|
56
|
-
static Created({ createdBy, name }) {
|
|
57
|
-
return ({
|
|
58
|
-
type: 'Created',
|
|
59
|
-
createdBy: createdBy,
|
|
35
|
+
static UserInvited ({ createdBy, email, expiresAt }) {
|
|
36
|
+
return {
|
|
37
|
+
event: 'UserInvited',
|
|
38
|
+
createdBy,
|
|
60
39
|
payload: {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Return type of WorkspacesEvents.ResourceTemplatesImported
|
|
68
|
-
* @typedef {Object} ResourceTemplatesImported
|
|
69
|
-
* @property {string} type - ResourceTemplatesImported
|
|
70
|
-
* @property {string} createdBy - userId of user who created the workspace
|
|
71
|
-
* @property {ResourceTemplate[]} payload - event payload
|
|
72
|
-
*/
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Input for WorkspacesEvents.Created
|
|
76
|
-
* @typedef {Object} ResourceTemplatesImportedInput
|
|
77
|
-
* @property {ResourceTemplate[]} templates - List of resource templates
|
|
78
|
-
* @property {string} createdBy - userId of user who created the workspace
|
|
79
|
-
*/
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Use this to save imported resource templates
|
|
83
|
-
*
|
|
84
|
-
* @param {ResourceTemplatesImportedInput} input
|
|
85
|
-
* @return {ResourceTemplatesImported} - Resource templates imported event
|
|
86
|
-
*
|
|
87
|
-
* @example
|
|
88
|
-
* const templates = []
|
|
89
|
-
* const createdBy = 'fake-user-123'
|
|
90
|
-
*
|
|
91
|
-
* const event = WorkspacesEvents.Created({ templates, createdBy })
|
|
92
|
-
*
|
|
93
|
-
* Aggregate.Of(Workspace, userId)
|
|
94
|
-
* .then(Aggregate.Add(event))
|
|
95
|
-
*/
|
|
96
|
-
static ResourceTemplatesImported({ createdBy, templates }) {
|
|
97
|
-
return ({
|
|
98
|
-
type: 'ResourceTemplatesImported',
|
|
99
|
-
createdBy: createdBy,
|
|
100
|
-
payload: {
|
|
101
|
-
templates: templates
|
|
102
|
-
}
|
|
103
|
-
})
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// Not in use atm, use API TOKENS in the user aggregate instead.
|
|
107
|
-
// Caller is responsible for generating the token value.
|
|
108
|
-
static ApiTokenCreated({ createdBy, description, token }) {
|
|
109
|
-
return ({
|
|
110
|
-
type: 'ApiTokenCreated',
|
|
111
|
-
createdBy: createdBy,
|
|
112
|
-
payload: {
|
|
113
|
-
description: description,
|
|
114
|
-
token: token
|
|
115
|
-
}
|
|
116
|
-
})
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
static UserInvited({ createdBy, email, expiresAt }) {
|
|
121
|
-
return ({
|
|
122
|
-
type: 'UserInvited',
|
|
123
|
-
createdBy: createdBy,
|
|
124
|
-
payload: {
|
|
125
|
-
email: email,
|
|
126
|
-
expiresAt: new Date().getTime() + 1000 * 60 * 60 * 24 * 7, // One week
|
|
127
|
-
}
|
|
128
|
-
})
|
|
129
|
-
}
|
|
40
|
+
email,
|
|
41
|
+
expiresAt: expiresAt ?? Date.now() + 1000 * 60 * 60 * 24 * 7,
|
|
42
|
+
},
|
|
43
|
+
}
|
|
44
|
+
}
|
|
130
45
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
}
|
|
138
|
-
})
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
static ServiceEnabled({ createdBy, service }) {
|
|
142
|
-
return ({
|
|
143
|
-
type: 'ServiceEnabled',
|
|
144
|
-
createdBy: createdBy,
|
|
145
|
-
payload: {
|
|
146
|
-
service: service
|
|
147
|
-
}
|
|
148
|
-
})
|
|
46
|
+
static UserInvitationAccepted ({ createdBy, email }) {
|
|
47
|
+
return {
|
|
48
|
+
event: 'UserInvitationAccepted',
|
|
49
|
+
createdBy,
|
|
50
|
+
payload: { email },
|
|
51
|
+
}
|
|
149
52
|
}
|
|
150
53
|
|
|
151
|
-
static
|
|
152
|
-
return
|
|
153
|
-
|
|
154
|
-
createdBy
|
|
155
|
-
payload: {
|
|
156
|
-
|
|
157
|
-
}
|
|
158
|
-
})
|
|
54
|
+
static ServiceEnabled ({ createdBy, service }) {
|
|
55
|
+
return {
|
|
56
|
+
event: 'ServiceEnabled',
|
|
57
|
+
createdBy,
|
|
58
|
+
payload: { service },
|
|
59
|
+
}
|
|
159
60
|
}
|
|
160
61
|
|
|
161
|
-
static
|
|
162
|
-
return
|
|
163
|
-
|
|
164
|
-
createdBy
|
|
165
|
-
payload: {
|
|
166
|
-
|
|
167
|
-
}
|
|
168
|
-
})
|
|
62
|
+
static ServiceDisabled ({ createdBy, service }) {
|
|
63
|
+
return {
|
|
64
|
+
event: 'ServiceDisabled',
|
|
65
|
+
createdBy,
|
|
66
|
+
payload: { service },
|
|
67
|
+
}
|
|
169
68
|
}
|
|
170
69
|
|
|
70
|
+
static UserRemoved ({ createdBy, userId }) {
|
|
71
|
+
return {
|
|
72
|
+
event: 'UserRemoved',
|
|
73
|
+
createdBy,
|
|
74
|
+
payload: { userId },
|
|
75
|
+
}
|
|
76
|
+
}
|
|
171
77
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import casual from 'casual'
|
|
2
2
|
import { TestUtil } from '@ossy/platform/test'
|
|
3
3
|
|
|
4
|
+
const WORKSPACE_SCHEMA = '@ossy/workspaces/schema/workspace'
|
|
5
|
+
|
|
4
6
|
function authHeaders(token) {
|
|
5
7
|
return {
|
|
6
8
|
'Content-Type': 'application/json',
|
|
@@ -16,10 +18,10 @@ function workspaceHeaders(userToken, workspaceId) {
|
|
|
16
18
|
}
|
|
17
19
|
}
|
|
18
20
|
|
|
19
|
-
describe('[workspaces/create]', () => {
|
|
21
|
+
describe('[workspaces/actions/create]', () => {
|
|
20
22
|
|
|
21
23
|
TestUtil.AssertActionAuthenticationNeeded({
|
|
22
|
-
actionId: 'workspaces/create',
|
|
24
|
+
actionId: '@ossy/workspaces/actions/create',
|
|
23
25
|
})
|
|
24
26
|
|
|
25
27
|
describe('given a workspace name', () => {
|
|
@@ -28,7 +30,7 @@ describe('[workspaces/create]', () => {
|
|
|
28
30
|
const workspaceName = casual.word
|
|
29
31
|
|
|
30
32
|
const response = await TestUtil.InvokeAction({
|
|
31
|
-
actionId: 'workspaces/create',
|
|
33
|
+
actionId: '@ossy/workspaces/actions/create',
|
|
32
34
|
headers: authHeaders(user.token),
|
|
33
35
|
payload: { name: workspaceName },
|
|
34
36
|
})
|
|
@@ -36,8 +38,8 @@ describe('[workspaces/create]', () => {
|
|
|
36
38
|
const body = await response.json()
|
|
37
39
|
|
|
38
40
|
const workspaceCreatedEvent = await TestUtil.GetEvent({
|
|
39
|
-
|
|
40
|
-
|
|
41
|
+
type: WORKSPACE_SCHEMA,
|
|
42
|
+
event: 'Created',
|
|
41
43
|
createdBy: user.id,
|
|
42
44
|
'payload.name': workspaceName
|
|
43
45
|
})
|
|
@@ -45,35 +47,35 @@ describe('[workspaces/create]', () => {
|
|
|
45
47
|
expect(!!workspaceCreatedEvent).toEqual(true)
|
|
46
48
|
expect(response.status).toEqual(200)
|
|
47
49
|
expect(response.headers.get('Content-Type').includes('application/json')).toEqual(true)
|
|
48
|
-
expect(body.id).toEqual(workspaceCreatedEvent.
|
|
50
|
+
expect(body.id).toEqual(workspaceCreatedEvent.resourceId)
|
|
49
51
|
expect(body.name).toEqual(workspaceName)
|
|
50
52
|
expect(body.createdBy).toEqual(user.id)
|
|
51
53
|
expect(body.created).toEqual(workspaceCreatedEvent.created)
|
|
52
54
|
expect(body.apiTokens).toEqual([])
|
|
53
|
-
expect(Array.isArray(body.
|
|
54
|
-
expect(body.
|
|
55
|
+
expect(Array.isArray(body.schemas)).toBe(true)
|
|
56
|
+
expect(body.schemas.length).toEqual(0)
|
|
55
57
|
})
|
|
56
58
|
})
|
|
57
59
|
|
|
58
60
|
})
|
|
59
61
|
|
|
60
|
-
describe('[workspaces/list]', () => {
|
|
62
|
+
describe('[workspaces/actions/list]', () => {
|
|
61
63
|
|
|
62
64
|
TestUtil.AssertActionAuthenticationNeeded({
|
|
63
|
-
actionId: 'workspaces/list',
|
|
65
|
+
actionId: '@ossy/workspaces/actions/list',
|
|
64
66
|
})
|
|
65
67
|
|
|
66
68
|
it('must return a minified list of workspaces the user have created', async () => {
|
|
67
69
|
const user = await TestUtil.GetAuthenticatedTestUser()
|
|
68
70
|
|
|
69
71
|
const workspace = await TestUtil.InvokeAction({
|
|
70
|
-
actionId: 'workspaces/create',
|
|
72
|
+
actionId: '@ossy/workspaces/actions/create',
|
|
71
73
|
headers: authHeaders(user.token),
|
|
72
74
|
payload: { name: casual.word },
|
|
73
75
|
}).then(response => response.json())
|
|
74
76
|
|
|
75
77
|
const response = await TestUtil.InvokeAction({
|
|
76
|
-
actionId: 'workspaces/list',
|
|
78
|
+
actionId: '@ossy/workspaces/actions/list',
|
|
77
79
|
headers: authHeaders(user.token),
|
|
78
80
|
})
|
|
79
81
|
|
|
@@ -89,10 +91,10 @@ describe('[workspaces/list]', () => {
|
|
|
89
91
|
|
|
90
92
|
})
|
|
91
93
|
|
|
92
|
-
describe('[workspaces/get]', () => {
|
|
94
|
+
describe('[workspaces/actions/get]', () => {
|
|
93
95
|
|
|
94
96
|
TestUtil.AssertWorkspaceActionAuthenticationNeeded({
|
|
95
|
-
actionId: 'workspaces/get',
|
|
97
|
+
actionId: '@ossy/workspaces/actions/get',
|
|
96
98
|
payload: { workspaceId: '123' },
|
|
97
99
|
})
|
|
98
100
|
|
|
@@ -100,13 +102,13 @@ describe('[workspaces/get]', () => {
|
|
|
100
102
|
const user = await TestUtil.GetAuthenticatedTestUser()
|
|
101
103
|
|
|
102
104
|
const workspace = await TestUtil.InvokeAction({
|
|
103
|
-
actionId: 'workspaces/create',
|
|
105
|
+
actionId: '@ossy/workspaces/actions/create',
|
|
104
106
|
headers: authHeaders(user.token),
|
|
105
107
|
payload: { name: casual.word },
|
|
106
108
|
}).then(response => response.json())
|
|
107
109
|
|
|
108
110
|
const response = await TestUtil.InvokeAction({
|
|
109
|
-
actionId: 'workspaces/get',
|
|
111
|
+
actionId: '@ossy/workspaces/actions/get',
|
|
110
112
|
headers: workspaceHeaders(user.token, workspace.id),
|
|
111
113
|
payload: { workspaceId: workspace.id },
|
|
112
114
|
})
|
|
@@ -120,19 +122,19 @@ describe('[workspaces/get]', () => {
|
|
|
120
122
|
|
|
121
123
|
})
|
|
122
124
|
|
|
123
|
-
describe('[workspaces/import-
|
|
125
|
+
describe('[workspaces/actions/import-schemas]', () => {
|
|
124
126
|
|
|
125
127
|
TestUtil.AssertWorkspaceActionAuthenticationNeeded({
|
|
126
|
-
actionId: 'workspaces/import-
|
|
127
|
-
payload: {
|
|
128
|
+
actionId: '@ossy/workspaces/actions/import-schemas',
|
|
129
|
+
payload: { schemas: [] },
|
|
128
130
|
headers: { workspaceId: 'ws-test' },
|
|
129
131
|
})
|
|
130
132
|
|
|
131
|
-
it('must return the saved
|
|
133
|
+
it('must return the saved schemas and create a SchemasImported event', async () => {
|
|
132
134
|
const user = await TestUtil.GetAuthenticatedTestUser()
|
|
133
135
|
|
|
134
136
|
const workspace = await TestUtil.InvokeAction({
|
|
135
|
-
actionId: 'workspaces/create',
|
|
137
|
+
actionId: '@ossy/workspaces/actions/create',
|
|
136
138
|
headers: authHeaders(user.token),
|
|
137
139
|
payload: { name: casual.word },
|
|
138
140
|
}).then(response => response.json())
|
|
@@ -146,40 +148,40 @@ describe('[workspaces/import-resource-templates]', () => {
|
|
|
146
148
|
]
|
|
147
149
|
|
|
148
150
|
const response = await TestUtil.InvokeAction({
|
|
149
|
-
actionId: 'workspaces/import-
|
|
151
|
+
actionId: '@ossy/workspaces/actions/import-schemas',
|
|
150
152
|
headers: workspaceHeaders(user.token, workspace.id),
|
|
151
|
-
payload: {
|
|
153
|
+
payload: { schemas: imported },
|
|
152
154
|
})
|
|
153
155
|
|
|
154
156
|
const responseBody = await response.json()
|
|
155
157
|
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
|
|
158
|
+
const schemasImportedEvent = await TestUtil.GetEvent({
|
|
159
|
+
type: WORKSPACE_SCHEMA,
|
|
160
|
+
event: 'SchemasImported',
|
|
159
161
|
createdBy: user.id,
|
|
160
|
-
'payload.
|
|
162
|
+
'payload.schemas': imported
|
|
161
163
|
})
|
|
162
164
|
|
|
163
165
|
expect(response.status).toEqual(200)
|
|
164
166
|
expect(responseBody).toEqual(imported)
|
|
165
|
-
expect(!!
|
|
167
|
+
expect(!!schemasImportedEvent).toEqual(true)
|
|
166
168
|
|
|
167
169
|
})
|
|
168
170
|
|
|
169
171
|
})
|
|
170
172
|
|
|
171
|
-
describe('[workspaces/get-
|
|
173
|
+
describe('[workspaces/actions/get-schemas]', () => {
|
|
172
174
|
|
|
173
175
|
TestUtil.AssertWorkspaceActionAuthenticationNeeded({
|
|
174
|
-
actionId: 'workspaces/get-
|
|
176
|
+
actionId: '@ossy/workspaces/actions/get-schemas',
|
|
175
177
|
headers: { workspaceId: 'ws-test' },
|
|
176
178
|
})
|
|
177
179
|
|
|
178
|
-
it('must return the saved
|
|
180
|
+
it('must return the saved schemas', async () => {
|
|
179
181
|
const user = await TestUtil.GetAuthenticatedTestUser()
|
|
180
182
|
|
|
181
183
|
const workspace = await TestUtil.InvokeAction({
|
|
182
|
-
actionId: 'workspaces/create',
|
|
184
|
+
actionId: '@ossy/workspaces/actions/create',
|
|
183
185
|
headers: authHeaders(user.token),
|
|
184
186
|
payload: { name: casual.word },
|
|
185
187
|
}).then(response => response.json())
|
|
@@ -193,9 +195,9 @@ describe('[workspaces/get-resource-templates]', () => {
|
|
|
193
195
|
]
|
|
194
196
|
|
|
195
197
|
const response = await TestUtil.InvokeAction({
|
|
196
|
-
actionId: 'workspaces/import-
|
|
198
|
+
actionId: '@ossy/workspaces/actions/import-schemas',
|
|
197
199
|
headers: workspaceHeaders(user.token, workspace.id),
|
|
198
|
-
payload: {
|
|
200
|
+
payload: { schemas: imported },
|
|
199
201
|
})
|
|
200
202
|
|
|
201
203
|
const responseBody = await response.json()
|
|
@@ -207,10 +209,10 @@ describe('[workspaces/get-resource-templates]', () => {
|
|
|
207
209
|
|
|
208
210
|
})
|
|
209
211
|
|
|
210
|
-
describe('[workspaces/create-api-token]', () => {
|
|
212
|
+
describe('[workspaces/actions/create-api-token]', () => {
|
|
211
213
|
|
|
212
214
|
TestUtil.AssertWorkspaceActionAuthenticationNeeded({
|
|
213
|
-
actionId: 'workspaces/create-api-token',
|
|
215
|
+
actionId: '@ossy/workspaces/actions/create-api-token',
|
|
214
216
|
payload: { description: 'Api token for GitHub Actions' },
|
|
215
217
|
headers: { workspaceId: 'ws-test' },
|
|
216
218
|
})
|
|
@@ -219,13 +221,13 @@ describe('[workspaces/create-api-token]', () => {
|
|
|
219
221
|
const user = await TestUtil.GetAuthenticatedTestUser()
|
|
220
222
|
|
|
221
223
|
const workspace = await TestUtil.InvokeAction({
|
|
222
|
-
actionId: 'workspaces/create',
|
|
224
|
+
actionId: '@ossy/workspaces/actions/create',
|
|
223
225
|
headers: authHeaders(user.token),
|
|
224
226
|
payload: { name: casual.word },
|
|
225
227
|
}).then(response => response.json())
|
|
226
228
|
|
|
227
229
|
const response = await TestUtil.InvokeAction({
|
|
228
|
-
actionId: 'workspaces/create-api-token',
|
|
230
|
+
actionId: '@ossy/workspaces/actions/create-api-token',
|
|
229
231
|
headers: workspaceHeaders(user.token, workspace.id),
|
|
230
232
|
payload: { description: 'Api token for GitHub Actions' },
|
|
231
233
|
})
|
|
@@ -1,33 +1,48 @@
|
|
|
1
1
|
import { EventStore } from '@ossy/event-store'
|
|
2
2
|
import { createLogger } from '@ossy/observability'
|
|
3
|
+
import { WorkspaceSchema } from './schema-ids.js'
|
|
3
4
|
|
|
4
5
|
const log = createLogger('workspaces')
|
|
5
6
|
|
|
6
7
|
export class WorkspacesQueries {
|
|
7
|
-
static getAllByUserIncluded(userId) {
|
|
8
|
+
static getAllByUserIncluded (userId) {
|
|
8
9
|
log.info('[WorkspacesQueries] getAllByUserIncluded()')
|
|
9
10
|
return EventStore.Aggregate([
|
|
10
|
-
{ $
|
|
11
|
+
{ $match: { type: WorkspaceSchema.workspace, resourceId: { $exists: true } } },
|
|
12
|
+
{ $group: { _id: '$resourceId', events: { $push: '$$ROOT' } } },
|
|
11
13
|
{
|
|
12
14
|
$match: {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
$or: [
|
|
16
|
+
{ 'events.createdBy': userId },
|
|
17
|
+
{ 'events.event': 'UserInvitationAccepted', 'events.createdBy': userId },
|
|
18
|
+
],
|
|
19
|
+
'events.event': { $in: ['Created', 'UserInvitationAccepted'] },
|
|
16
20
|
},
|
|
17
21
|
},
|
|
18
22
|
{
|
|
19
23
|
$project: {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
$
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
id: '$_id',
|
|
25
|
+
name: {
|
|
26
|
+
$let: {
|
|
27
|
+
vars: {
|
|
28
|
+
created: {
|
|
29
|
+
$arrayElemAt: [
|
|
30
|
+
{
|
|
31
|
+
$filter: {
|
|
32
|
+
input: '$events',
|
|
33
|
+
as: 'e',
|
|
34
|
+
cond: { $eq: ['$$e.event', 'Created'] },
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
0,
|
|
38
|
+
],
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
in: '$$created.payload.name',
|
|
26
42
|
},
|
|
27
43
|
},
|
|
28
44
|
},
|
|
29
45
|
},
|
|
30
|
-
{ $project: { _id: 0, id: '$currentState.id', name: '$currentState.name' } },
|
|
31
46
|
]).catch(() => [])
|
|
32
47
|
}
|
|
33
48
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const metadata = { id: 'workspaces/get-resource-templates', access: 'workspace' }
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { Aggregate } from '@ossy/event-store'
|
|
2
|
-
import { Workspace } from '@ossy/workspaces/server'
|
|
3
|
-
import { getSystemResourceTemplates } from '@ossy/platform'
|
|
4
|
-
|
|
5
|
-
export const metadata = { id: 'workspaces/get-resource-templates' }
|
|
6
|
-
|
|
7
|
-
export async function run({ payload, req }) {
|
|
8
|
-
const workspaceId = payload?.workspaceId ?? req?.workspaceId
|
|
9
|
-
|
|
10
|
-
const workspace = await Aggregate.Of(Workspace, workspaceId).then(Aggregate.View())
|
|
11
|
-
const systemTemplates = getSystemResourceTemplates()
|
|
12
|
-
const workspaceTemplates = workspace.resourceTemplates || []
|
|
13
|
-
const workspaceIds = new Set(workspaceTemplates.map(t => t.id))
|
|
14
|
-
return [
|
|
15
|
-
...systemTemplates.filter(t => !workspaceIds.has(t.id)),
|
|
16
|
-
...workspaceTemplates,
|
|
17
|
-
]
|
|
18
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const metadata = { id: 'workspaces/import-resource-templates', access: 'workspace' }
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { Aggregate } from '@ossy/event-store'
|
|
2
|
-
import { Workspace, WorkspacesEvents } from '@ossy/workspaces/server'
|
|
3
|
-
import { validateResourceTemplatesForImport } from '@ossy/platform'
|
|
4
|
-
|
|
5
|
-
export const metadata = { id: 'workspaces/import-resource-templates' }
|
|
6
|
-
|
|
7
|
-
export async function run({ payload, req }) {
|
|
8
|
-
const userId = payload?.userId ?? req?.userId
|
|
9
|
-
const workspaceId = payload?.workspaceId ?? req?.workspaceId
|
|
10
|
-
const templates = payload?.templates ?? payload
|
|
11
|
-
|
|
12
|
-
if (!Array.isArray(templates)) {
|
|
13
|
-
throw Object.assign(new Error('templates must be an array'), { status: 400 })
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const reservedIds = new Set([])
|
|
17
|
-
const validation = validateResourceTemplatesForImport(templates, reservedIds)
|
|
18
|
-
if (!validation.ok) {
|
|
19
|
-
throw Object.assign(new Error(validation.message), { status: 400, type: validation.code })
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const event = WorkspacesEvents.ResourceTemplatesImported({ createdBy: userId, templates })
|
|
23
|
-
|
|
24
|
-
await Aggregate.Of(Workspace, workspaceId).then(Aggregate.Add(event))
|
|
25
|
-
return event.payload.templates
|
|
26
|
-
}
|