directus 9.2.2 → 9.4.2
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/dist/app.js +16 -4
- package/dist/auth/auth.d.ts +4 -6
- package/dist/auth/auth.js +5 -9
- package/dist/auth/drivers/ldap.d.ts +3 -3
- package/dist/auth/drivers/ldap.js +2 -3
- package/dist/auth/drivers/local.d.ts +2 -2
- package/dist/auth/drivers/local.js +7 -13
- package/dist/auth/drivers/oauth2.d.ts +3 -3
- package/dist/auth/drivers/oauth2.js +4 -4
- package/dist/auth/drivers/openid.d.ts +3 -3
- package/dist/auth/drivers/openid.js +4 -4
- package/dist/cache.js +1 -3
- package/dist/cli/commands/bootstrap/index.js +3 -2
- package/dist/cli/commands/init/index.js +3 -7
- package/dist/cli/commands/schema/apply.js +1 -1
- package/dist/cli/utils/defaults.d.ts +11 -0
- package/dist/cli/utils/defaults.js +14 -0
- package/dist/constants.d.ts +8 -0
- package/dist/constants.js +16 -2
- package/dist/controllers/activity.js +2 -1
- package/dist/controllers/auth.js +5 -4
- package/dist/controllers/shares.d.ts +2 -0
- package/dist/controllers/shares.js +212 -0
- package/dist/controllers/users.js +21 -9
- package/dist/database/index.js +3 -0
- package/dist/database/migrations/20211211A-add-shares.d.ts +3 -0
- package/dist/database/migrations/20211211A-add-shares.js +38 -0
- package/dist/database/migrations/20211230A-add-project-descriptor.d.ts +3 -0
- package/dist/database/migrations/20211230A-add-project-descriptor.js +15 -0
- package/dist/database/run-ast.js +5 -5
- package/dist/database/system-data/app-access-permissions/app-access-permissions.yaml +0 -15
- package/dist/database/system-data/app-access-permissions/index.d.ts +1 -0
- package/dist/database/system-data/app-access-permissions/index.js +4 -2
- package/dist/database/system-data/app-access-permissions/schema-access-permissions.yaml +17 -0
- package/dist/database/system-data/collections/collections.yaml +3 -0
- package/dist/database/system-data/fields/_defaults.yaml +2 -0
- package/dist/database/system-data/fields/sessions.yaml +1 -1
- package/dist/database/system-data/fields/settings.yaml +20 -1
- package/dist/database/system-data/fields/shares.yaml +77 -0
- package/dist/database/system-data/fields/users.yaml +1 -1
- package/dist/database/system-data/relations/relations.yaml +15 -0
- package/dist/emitter.d.ts +3 -2
- package/dist/emitter.js +13 -6
- package/dist/env.js +3 -1
- package/dist/extensions.d.ts +1 -0
- package/dist/extensions.js +10 -4
- package/dist/middleware/authenticate.js +7 -16
- package/dist/middleware/check-ip.js +9 -6
- package/dist/middleware/rate-limiter.js +2 -1
- package/dist/middleware/respond.js +4 -1
- package/dist/services/activity.d.ts +2 -1
- package/dist/services/activity.js +2 -2
- package/dist/services/authentication.d.ts +2 -7
- package/dist/services/authentication.js +81 -41
- package/dist/services/authorization.js +3 -3
- package/dist/services/collections.d.ts +1 -2
- package/dist/services/collections.js +2 -2
- package/dist/services/files.d.ts +2 -2
- package/dist/services/files.js +14 -8
- package/dist/services/graphql.d.ts +1 -1
- package/dist/services/graphql.js +47 -6
- package/dist/services/index.d.ts +1 -0
- package/dist/services/index.js +1 -0
- package/dist/services/items.d.ts +1 -15
- package/dist/services/notifications.d.ts +2 -2
- package/dist/services/permissions.d.ts +2 -2
- package/dist/services/roles.d.ts +2 -2
- package/dist/services/server.js +1 -0
- package/dist/services/shares.d.ts +17 -0
- package/dist/services/shares.js +135 -0
- package/dist/services/specifications.js +1 -1
- package/dist/services/users.d.ts +2 -2
- package/dist/services/webhooks.d.ts +2 -2
- package/dist/types/ast.d.ts +3 -3
- package/dist/types/auth.d.ts +31 -0
- package/dist/types/extensions.d.ts +2 -0
- package/dist/types/items.d.ts +14 -0
- package/dist/utils/apply-query.d.ts +0 -38
- package/dist/utils/apply-query.js +66 -67
- package/dist/utils/apply-snapshot.js +69 -14
- package/dist/utils/get-ast-from-query.js +3 -3
- package/dist/utils/get-default-value.js +3 -1
- package/dist/utils/get-ip-from-req.d.ts +2 -0
- package/dist/utils/get-ip-from-req.js +24 -0
- package/dist/utils/get-permissions.js +15 -7
- package/dist/utils/get-relation-type.d.ts +1 -1
- package/dist/utils/get-relation-type.js +1 -1
- package/dist/utils/merge-permissions-for-share.d.ts +5 -0
- package/dist/utils/merge-permissions-for-share.js +116 -0
- package/dist/utils/merge-permissions.d.ts +13 -1
- package/dist/utils/merge-permissions.js +27 -19
- package/dist/utils/reduce-schema.d.ts +2 -2
- package/dist/utils/reduce-schema.js +7 -7
- package/dist/utils/user-name.js +3 -0
- package/example.env +1 -1
- package/package.json +15 -14
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const express_1 = __importDefault(require("express"));
|
|
7
|
+
const exceptions_1 = require("../exceptions");
|
|
8
|
+
const respond_1 = require("../middleware/respond");
|
|
9
|
+
const use_collection_1 = __importDefault(require("../middleware/use-collection"));
|
|
10
|
+
const validate_batch_1 = require("../middleware/validate-batch");
|
|
11
|
+
const services_1 = require("../services");
|
|
12
|
+
const async_handler_1 = __importDefault(require("../utils/async-handler"));
|
|
13
|
+
const constants_1 = require("../constants");
|
|
14
|
+
const joi_1 = __importDefault(require("joi"));
|
|
15
|
+
const env_1 = __importDefault(require("../env"));
|
|
16
|
+
const router = express_1.default.Router();
|
|
17
|
+
router.use((0, use_collection_1.default)('directus_shares'));
|
|
18
|
+
const sharedLoginSchema = joi_1.default.object({
|
|
19
|
+
share: joi_1.default.string().required(),
|
|
20
|
+
password: joi_1.default.string(),
|
|
21
|
+
}).unknown();
|
|
22
|
+
router.post('/auth', (0, async_handler_1.default)(async (req, res, next) => {
|
|
23
|
+
// This doesn't use accountability, as the user isn't logged in at this point
|
|
24
|
+
const service = new services_1.SharesService({
|
|
25
|
+
schema: req.schema,
|
|
26
|
+
});
|
|
27
|
+
const { error } = sharedLoginSchema.validate(req.body);
|
|
28
|
+
if (error) {
|
|
29
|
+
throw new exceptions_1.InvalidPayloadException(error.message);
|
|
30
|
+
}
|
|
31
|
+
const { accessToken, refreshToken, expires } = await service.login(req.body);
|
|
32
|
+
res.cookie(env_1.default.REFRESH_TOKEN_COOKIE_NAME, refreshToken, constants_1.COOKIE_OPTIONS);
|
|
33
|
+
res.locals.payload = { data: { access_token: accessToken, expires } };
|
|
34
|
+
return next();
|
|
35
|
+
}), respond_1.respond);
|
|
36
|
+
const sharedInviteSchema = joi_1.default.object({
|
|
37
|
+
share: joi_1.default.string().required(),
|
|
38
|
+
emails: joi_1.default.array().items(joi_1.default.string()),
|
|
39
|
+
}).unknown();
|
|
40
|
+
router.post('/invite', (0, async_handler_1.default)(async (req, res, next) => {
|
|
41
|
+
const service = new services_1.SharesService({
|
|
42
|
+
schema: req.schema,
|
|
43
|
+
accountability: req.accountability,
|
|
44
|
+
});
|
|
45
|
+
const { error } = sharedInviteSchema.validate(req.body);
|
|
46
|
+
if (error) {
|
|
47
|
+
throw new exceptions_1.InvalidPayloadException(error.message);
|
|
48
|
+
}
|
|
49
|
+
await service.invite(req.body);
|
|
50
|
+
return next();
|
|
51
|
+
}), respond_1.respond);
|
|
52
|
+
router.post('/', (0, async_handler_1.default)(async (req, res, next) => {
|
|
53
|
+
const service = new services_1.SharesService({
|
|
54
|
+
accountability: req.accountability,
|
|
55
|
+
schema: req.schema,
|
|
56
|
+
});
|
|
57
|
+
const savedKeys = [];
|
|
58
|
+
if (Array.isArray(req.body)) {
|
|
59
|
+
const keys = await service.createMany(req.body);
|
|
60
|
+
savedKeys.push(...keys);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
const key = await service.createOne(req.body);
|
|
64
|
+
savedKeys.push(key);
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
if (Array.isArray(req.body)) {
|
|
68
|
+
const items = await service.readMany(savedKeys, req.sanitizedQuery);
|
|
69
|
+
res.locals.payload = { data: items };
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
const item = await service.readOne(savedKeys[0], req.sanitizedQuery);
|
|
73
|
+
res.locals.payload = { data: item };
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
if (error instanceof exceptions_1.ForbiddenException) {
|
|
78
|
+
return next();
|
|
79
|
+
}
|
|
80
|
+
throw error;
|
|
81
|
+
}
|
|
82
|
+
return next();
|
|
83
|
+
}), respond_1.respond);
|
|
84
|
+
const readHandler = (0, async_handler_1.default)(async (req, res, next) => {
|
|
85
|
+
const service = new services_1.SharesService({
|
|
86
|
+
accountability: req.accountability,
|
|
87
|
+
schema: req.schema,
|
|
88
|
+
});
|
|
89
|
+
const records = await service.readByQuery(req.sanitizedQuery);
|
|
90
|
+
res.locals.payload = { data: records || null };
|
|
91
|
+
return next();
|
|
92
|
+
});
|
|
93
|
+
router.get('/', (0, validate_batch_1.validateBatch)('read'), readHandler, respond_1.respond);
|
|
94
|
+
router.search('/', (0, validate_batch_1.validateBatch)('read'), readHandler, respond_1.respond);
|
|
95
|
+
router.get(`/info/:pk(${constants_1.UUID_REGEX})`, (0, async_handler_1.default)(async (req, res, next) => {
|
|
96
|
+
const service = new services_1.SharesService({
|
|
97
|
+
schema: req.schema,
|
|
98
|
+
});
|
|
99
|
+
const record = await service.readOne(req.params.pk, {
|
|
100
|
+
fields: ['id', 'collection', 'item', 'password', 'max_uses', 'times_used', 'date_start', 'date_end'],
|
|
101
|
+
filter: {
|
|
102
|
+
_and: [
|
|
103
|
+
{
|
|
104
|
+
_or: [
|
|
105
|
+
{
|
|
106
|
+
date_start: {
|
|
107
|
+
_lte: new Date().toISOString(),
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
date_start: {
|
|
112
|
+
_null: true,
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
_or: [
|
|
119
|
+
{
|
|
120
|
+
date_end: {
|
|
121
|
+
_gte: new Date().toISOString(),
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
date_end: {
|
|
126
|
+
_null: true,
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
],
|
|
130
|
+
},
|
|
131
|
+
],
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
res.locals.payload = { data: record || null };
|
|
135
|
+
return next();
|
|
136
|
+
}), respond_1.respond);
|
|
137
|
+
router.get(`/:pk(${constants_1.UUID_REGEX})`, (0, async_handler_1.default)(async (req, res, next) => {
|
|
138
|
+
const service = new services_1.SharesService({
|
|
139
|
+
accountability: req.accountability,
|
|
140
|
+
schema: req.schema,
|
|
141
|
+
});
|
|
142
|
+
const record = await service.readOne(req.params.pk, req.sanitizedQuery);
|
|
143
|
+
res.locals.payload = { data: record || null };
|
|
144
|
+
return next();
|
|
145
|
+
}), respond_1.respond);
|
|
146
|
+
router.patch('/', (0, validate_batch_1.validateBatch)('update'), (0, async_handler_1.default)(async (req, res, next) => {
|
|
147
|
+
const service = new services_1.SharesService({
|
|
148
|
+
accountability: req.accountability,
|
|
149
|
+
schema: req.schema,
|
|
150
|
+
});
|
|
151
|
+
let keys = [];
|
|
152
|
+
if (req.body.keys) {
|
|
153
|
+
keys = await service.updateMany(req.body.keys, req.body.data);
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
keys = await service.updateByQuery(req.body.query, req.body.data);
|
|
157
|
+
}
|
|
158
|
+
try {
|
|
159
|
+
const result = await service.readMany(keys, req.sanitizedQuery);
|
|
160
|
+
res.locals.payload = { data: result };
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
if (error instanceof exceptions_1.ForbiddenException) {
|
|
164
|
+
return next();
|
|
165
|
+
}
|
|
166
|
+
throw error;
|
|
167
|
+
}
|
|
168
|
+
return next();
|
|
169
|
+
}), respond_1.respond);
|
|
170
|
+
router.patch(`/:pk(${constants_1.UUID_REGEX})`, (0, async_handler_1.default)(async (req, res, next) => {
|
|
171
|
+
const service = new services_1.SharesService({
|
|
172
|
+
accountability: req.accountability,
|
|
173
|
+
schema: req.schema,
|
|
174
|
+
});
|
|
175
|
+
const primaryKey = await service.updateOne(req.params.pk, req.body);
|
|
176
|
+
try {
|
|
177
|
+
const item = await service.readOne(primaryKey, req.sanitizedQuery);
|
|
178
|
+
res.locals.payload = { data: item || null };
|
|
179
|
+
}
|
|
180
|
+
catch (error) {
|
|
181
|
+
if (error instanceof exceptions_1.ForbiddenException) {
|
|
182
|
+
return next();
|
|
183
|
+
}
|
|
184
|
+
throw error;
|
|
185
|
+
}
|
|
186
|
+
return next();
|
|
187
|
+
}), respond_1.respond);
|
|
188
|
+
router.delete('/', (0, async_handler_1.default)(async (req, _res, next) => {
|
|
189
|
+
const service = new services_1.SharesService({
|
|
190
|
+
accountability: req.accountability,
|
|
191
|
+
schema: req.schema,
|
|
192
|
+
});
|
|
193
|
+
if (Array.isArray(req.body)) {
|
|
194
|
+
await service.deleteMany(req.body);
|
|
195
|
+
}
|
|
196
|
+
else if (req.body.keys) {
|
|
197
|
+
await service.deleteMany(req.body.keys);
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
await service.deleteByQuery(req.body.query);
|
|
201
|
+
}
|
|
202
|
+
return next();
|
|
203
|
+
}), respond_1.respond);
|
|
204
|
+
router.delete(`/:pk(${constants_1.UUID_REGEX})`, (0, async_handler_1.default)(async (req, _res, next) => {
|
|
205
|
+
const service = new services_1.SharesService({
|
|
206
|
+
accountability: req.accountability,
|
|
207
|
+
schema: req.schema,
|
|
208
|
+
});
|
|
209
|
+
await service.deleteOne(req.params.pk);
|
|
210
|
+
return next();
|
|
211
|
+
}), respond_1.respond);
|
|
212
|
+
exports.default = router;
|
|
@@ -62,8 +62,20 @@ const readHandler = (0, async_handler_1.default)(async (req, res, next) => {
|
|
|
62
62
|
router.get('/', (0, validate_batch_1.validateBatch)('read'), readHandler, respond_1.respond);
|
|
63
63
|
router.search('/', (0, validate_batch_1.validateBatch)('read'), readHandler, respond_1.respond);
|
|
64
64
|
router.get('/me', (0, async_handler_1.default)(async (req, res, next) => {
|
|
65
|
-
var _a;
|
|
66
|
-
if (
|
|
65
|
+
var _a, _b, _c;
|
|
66
|
+
if ((_a = req.accountability) === null || _a === void 0 ? void 0 : _a.share_scope) {
|
|
67
|
+
const user = {
|
|
68
|
+
share: (_b = req.accountability) === null || _b === void 0 ? void 0 : _b.share,
|
|
69
|
+
role: {
|
|
70
|
+
id: req.accountability.role,
|
|
71
|
+
admin_access: false,
|
|
72
|
+
app_access: false,
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
res.locals.payload = { data: user };
|
|
76
|
+
return next();
|
|
77
|
+
}
|
|
78
|
+
if (!((_c = req.accountability) === null || _c === void 0 ? void 0 : _c.user)) {
|
|
67
79
|
throw new exceptions_1.InvalidCredentialsException();
|
|
68
80
|
}
|
|
69
81
|
const service = new services_1.UsersService({
|
|
@@ -108,7 +120,7 @@ router.patch('/me', (0, async_handler_1.default)(async (req, res, next) => {
|
|
|
108
120
|
res.locals.payload = { data: item || null };
|
|
109
121
|
return next();
|
|
110
122
|
}), respond_1.respond);
|
|
111
|
-
router.patch('/me/track/page', (0, async_handler_1.default)(async (req,
|
|
123
|
+
router.patch('/me/track/page', (0, async_handler_1.default)(async (req, _res, next) => {
|
|
112
124
|
var _a;
|
|
113
125
|
if (!((_a = req.accountability) === null || _a === void 0 ? void 0 : _a.user)) {
|
|
114
126
|
throw new exceptions_1.InvalidCredentialsException();
|
|
@@ -162,7 +174,7 @@ router.patch('/:pk', (0, async_handler_1.default)(async (req, res, next) => {
|
|
|
162
174
|
}
|
|
163
175
|
return next();
|
|
164
176
|
}), respond_1.respond);
|
|
165
|
-
router.delete('/', (0, validate_batch_1.validateBatch)('delete'), (0, async_handler_1.default)(async (req,
|
|
177
|
+
router.delete('/', (0, validate_batch_1.validateBatch)('delete'), (0, async_handler_1.default)(async (req, _res, next) => {
|
|
166
178
|
const service = new services_1.UsersService({
|
|
167
179
|
accountability: req.accountability,
|
|
168
180
|
schema: req.schema,
|
|
@@ -178,7 +190,7 @@ router.delete('/', (0, validate_batch_1.validateBatch)('delete'), (0, async_hand
|
|
|
178
190
|
}
|
|
179
191
|
return next();
|
|
180
192
|
}), respond_1.respond);
|
|
181
|
-
router.delete('/:pk', (0, async_handler_1.default)(async (req,
|
|
193
|
+
router.delete('/:pk', (0, async_handler_1.default)(async (req, _res, next) => {
|
|
182
194
|
const service = new services_1.UsersService({
|
|
183
195
|
accountability: req.accountability,
|
|
184
196
|
schema: req.schema,
|
|
@@ -191,7 +203,7 @@ const inviteSchema = joi_1.default.object({
|
|
|
191
203
|
role: joi_1.default.string().uuid({ version: 'uuidv4' }).required(),
|
|
192
204
|
invite_url: joi_1.default.string().uri(),
|
|
193
205
|
});
|
|
194
|
-
router.post('/invite', (0, async_handler_1.default)(async (req,
|
|
206
|
+
router.post('/invite', (0, async_handler_1.default)(async (req, _res, next) => {
|
|
195
207
|
const { error } = inviteSchema.validate(req.body);
|
|
196
208
|
if (error)
|
|
197
209
|
throw new exceptions_1.InvalidPayloadException(error.message);
|
|
@@ -206,7 +218,7 @@ const acceptInviteSchema = joi_1.default.object({
|
|
|
206
218
|
token: joi_1.default.string().required(),
|
|
207
219
|
password: joi_1.default.string().required(),
|
|
208
220
|
});
|
|
209
|
-
router.post('/invite/accept', (0, async_handler_1.default)(async (req,
|
|
221
|
+
router.post('/invite/accept', (0, async_handler_1.default)(async (req, _res, next) => {
|
|
210
222
|
const { error } = acceptInviteSchema.validate(req.body);
|
|
211
223
|
if (error)
|
|
212
224
|
throw new exceptions_1.InvalidPayloadException(error.message);
|
|
@@ -238,7 +250,7 @@ router.post('/me/tfa/generate/', (0, async_handler_1.default)(async (req, res, n
|
|
|
238
250
|
res.locals.payload = { data: { secret, otpauth_url: url } };
|
|
239
251
|
return next();
|
|
240
252
|
}), respond_1.respond);
|
|
241
|
-
router.post('/me/tfa/enable/', (0, async_handler_1.default)(async (req,
|
|
253
|
+
router.post('/me/tfa/enable/', (0, async_handler_1.default)(async (req, _res, next) => {
|
|
242
254
|
var _a;
|
|
243
255
|
if (!((_a = req.accountability) === null || _a === void 0 ? void 0 : _a.user)) {
|
|
244
256
|
throw new exceptions_1.InvalidCredentialsException();
|
|
@@ -256,7 +268,7 @@ router.post('/me/tfa/enable/', (0, async_handler_1.default)(async (req, res, nex
|
|
|
256
268
|
await service.enableTFA(req.accountability.user, req.body.otp, req.body.secret);
|
|
257
269
|
return next();
|
|
258
270
|
}), respond_1.respond);
|
|
259
|
-
router.post('/me/tfa/disable', (0, async_handler_1.default)(async (req,
|
|
271
|
+
router.post('/me/tfa/disable', (0, async_handler_1.default)(async (req, _res, next) => {
|
|
260
272
|
var _a;
|
|
261
273
|
if (!((_a = req.accountability) === null || _a === void 0 ? void 0 : _a.user)) {
|
|
262
274
|
throw new exceptions_1.InvalidCredentialsException();
|
package/dist/database/index.js
CHANGED
|
@@ -88,6 +88,9 @@ function getDatabase() {
|
|
|
88
88
|
// act the same
|
|
89
89
|
(0, lodash_1.merge)(knexConfig, { connection: { options: { useUTC: false } } });
|
|
90
90
|
}
|
|
91
|
+
if (env_1.default.DB_CLIENT === 'mysql' && !env_1.default.DB_CHARSET) {
|
|
92
|
+
logger_1.default.warn(`DB_CHARSET hasn't been set. Please make sure DB_CHARSET matches your database's collation.`);
|
|
93
|
+
}
|
|
91
94
|
database = (0, knex_1.knex)(knexConfig);
|
|
92
95
|
const times = {};
|
|
93
96
|
database
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.down = exports.up = void 0;
|
|
4
|
+
async function up(knex) {
|
|
5
|
+
await knex.schema.createTable('directus_shares', (table) => {
|
|
6
|
+
table.uuid('id').primary();
|
|
7
|
+
table.string('name');
|
|
8
|
+
table.string('collection', 64).references('collection').inTable('directus_collections').onDelete('CASCADE');
|
|
9
|
+
table.string('item');
|
|
10
|
+
table.uuid('role').references('id').inTable('directus_roles').onDelete('CASCADE');
|
|
11
|
+
table.string('password');
|
|
12
|
+
table.uuid('user_created').references('id').inTable('directus_users').onDelete('SET NULL');
|
|
13
|
+
table.timestamp('date_created').defaultTo(knex.fn.now());
|
|
14
|
+
// This was changed after the migration went live to retroactively fix mysql5, see #10693
|
|
15
|
+
table.timestamp('date_start').nullable().defaultTo(null);
|
|
16
|
+
table.timestamp('date_end').nullable().defaultTo(null);
|
|
17
|
+
table.integer('times_used').defaultTo(0);
|
|
18
|
+
table.integer('max_uses');
|
|
19
|
+
});
|
|
20
|
+
await knex.schema.alterTable('directus_sessions', (table) => {
|
|
21
|
+
table.dropColumn('data');
|
|
22
|
+
});
|
|
23
|
+
await knex.schema.alterTable('directus_sessions', (table) => {
|
|
24
|
+
table.uuid('user').nullable().alter();
|
|
25
|
+
table.uuid('share').references('id').inTable('directus_shares').onDelete('CASCADE');
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
exports.up = up;
|
|
29
|
+
async function down(knex) {
|
|
30
|
+
await knex.schema.alterTable('directus_sessions', (table) => {
|
|
31
|
+
table.uuid('user').notNullable().alter();
|
|
32
|
+
table.json('data');
|
|
33
|
+
table.dropForeign('share');
|
|
34
|
+
table.dropColumn('share');
|
|
35
|
+
});
|
|
36
|
+
await knex.schema.dropTable('directus_shares');
|
|
37
|
+
}
|
|
38
|
+
exports.down = down;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.down = exports.up = void 0;
|
|
4
|
+
async function up(knex) {
|
|
5
|
+
await knex.schema.alterTable('directus_settings', (table) => {
|
|
6
|
+
table.string('project_descriptor', 100).nullable();
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
exports.up = up;
|
|
10
|
+
async function down(knex) {
|
|
11
|
+
await knex.schema.alterTable('directus_settings', (table) => {
|
|
12
|
+
table.dropColumn('project_descriptor');
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
exports.down = down;
|
package/dist/database/run-ast.js
CHANGED
|
@@ -18,7 +18,7 @@ const helpers_1 = require("../database/helpers");
|
|
|
18
18
|
async function runAST(originalAST, schema, options) {
|
|
19
19
|
const ast = (0, lodash_1.cloneDeep)(originalAST);
|
|
20
20
|
const knex = (options === null || options === void 0 ? void 0 : options.knex) || (0, _1.default)();
|
|
21
|
-
if (ast.type === '
|
|
21
|
+
if (ast.type === 'a2o') {
|
|
22
22
|
const results = {};
|
|
23
23
|
for (const collection of ast.names) {
|
|
24
24
|
results[collection] = await run(collection, ast.children[collection], ast.query[collection]);
|
|
@@ -85,7 +85,7 @@ async function parseCurrentLevel(schema, collection, children, query) {
|
|
|
85
85
|
if (child.type === 'm2o') {
|
|
86
86
|
columnsToSelectInternal.push(child.fieldKey);
|
|
87
87
|
}
|
|
88
|
-
if (child.type === '
|
|
88
|
+
if (child.type === 'a2o') {
|
|
89
89
|
columnsToSelectInternal.push(child.relation.field);
|
|
90
90
|
columnsToSelectInternal.push(child.relation.meta.one_collection_field);
|
|
91
91
|
}
|
|
@@ -182,7 +182,7 @@ function applyParentFilters(schema, nestedCollectionNodes, parentItem) {
|
|
|
182
182
|
nestedNode.query.union = [foreignField, foreignIds];
|
|
183
183
|
}
|
|
184
184
|
}
|
|
185
|
-
else if (nestedNode.type === '
|
|
185
|
+
else if (nestedNode.type === 'a2o') {
|
|
186
186
|
const keysPerCollection = {};
|
|
187
187
|
for (const parentItem of parentItems) {
|
|
188
188
|
const collection = parentItem[nestedNode.relation.meta.one_collection_field];
|
|
@@ -256,7 +256,7 @@ function mergeWithParentItems(schema, nestedItem, parentItem, nestedNode) {
|
|
|
256
256
|
parentItem[nestedNode.fieldKey] = itemChildren.length > 0 ? itemChildren : [];
|
|
257
257
|
}
|
|
258
258
|
}
|
|
259
|
-
else if (nestedNode.type === '
|
|
259
|
+
else if (nestedNode.type === 'a2o') {
|
|
260
260
|
for (const parentItem of parentItems) {
|
|
261
261
|
if (!((_a = nestedNode.relation.meta) === null || _a === void 0 ? void 0 : _a.one_collection_field)) {
|
|
262
262
|
parentItem[nestedNode.fieldKey] = null;
|
|
@@ -279,7 +279,7 @@ function removeTemporaryFields(schema, rawItem, ast, primaryKeyField, parentItem
|
|
|
279
279
|
var _a;
|
|
280
280
|
const rawItems = (0, lodash_1.cloneDeep)((0, utils_1.toArray)(rawItem));
|
|
281
281
|
const items = [];
|
|
282
|
-
if (ast.type === '
|
|
282
|
+
if (ast.type === 'a2o') {
|
|
283
283
|
const fields = {};
|
|
284
284
|
const nestedCollectionNodes = {};
|
|
285
285
|
for (const relatedCollection of ast.names) {
|
|
@@ -13,18 +13,6 @@
|
|
|
13
13
|
comment:
|
|
14
14
|
_nnull: true
|
|
15
15
|
|
|
16
|
-
- collection: directus_collections
|
|
17
|
-
action: read
|
|
18
|
-
|
|
19
|
-
- collection: directus_fields
|
|
20
|
-
action: read
|
|
21
|
-
|
|
22
|
-
- collection: directus_permissions
|
|
23
|
-
action: read
|
|
24
|
-
permissions:
|
|
25
|
-
role:
|
|
26
|
-
_eq: $CURRENT_ROLE
|
|
27
|
-
|
|
28
16
|
- collection: directus_presets
|
|
29
17
|
action: read
|
|
30
18
|
permissions:
|
|
@@ -60,9 +48,6 @@
|
|
|
60
48
|
user:
|
|
61
49
|
_eq: $CURRENT_USER
|
|
62
50
|
|
|
63
|
-
- collection: directus_relations
|
|
64
|
-
action: read
|
|
65
|
-
|
|
66
51
|
- collection: directus_roles
|
|
67
52
|
action: read
|
|
68
53
|
permissions:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.appAccessMinimalPermissions = void 0;
|
|
3
|
+
exports.appAccessMinimalPermissions = exports.schemaPermissions = void 0;
|
|
4
4
|
const lodash_1 = require("lodash");
|
|
5
5
|
const require_yaml_1 = require("../../../utils/require-yaml");
|
|
6
6
|
const defaults = {
|
|
@@ -11,5 +11,7 @@ const defaults = {
|
|
|
11
11
|
fields: ['*'],
|
|
12
12
|
system: true,
|
|
13
13
|
};
|
|
14
|
+
const schemaPermissionsRaw = (0, require_yaml_1.requireYAML)(require.resolve('./schema-access-permissions.yaml'));
|
|
14
15
|
const permissions = (0, require_yaml_1.requireYAML)(require.resolve('./app-access-permissions.yaml'));
|
|
15
|
-
exports.
|
|
16
|
+
exports.schemaPermissions = schemaPermissionsRaw.map((row) => (0, lodash_1.merge)({}, defaults, row));
|
|
17
|
+
exports.appAccessMinimalPermissions = [...exports.schemaPermissions, ...permissions].map((row) => (0, lodash_1.merge)({}, defaults, row));
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# NOTE: Activity/collections/fields/presets/relations/revisions will have an extra hardcoded filter
|
|
2
|
+
# to filter out collections you don't have read access
|
|
3
|
+
|
|
4
|
+
- collection: directus_collections
|
|
5
|
+
action: read
|
|
6
|
+
|
|
7
|
+
- collection: directus_fields
|
|
8
|
+
action: read
|
|
9
|
+
|
|
10
|
+
- collection: directus_permissions
|
|
11
|
+
action: read
|
|
12
|
+
permissions:
|
|
13
|
+
role:
|
|
14
|
+
_eq: $CURRENT_ROLE
|
|
15
|
+
|
|
16
|
+
- collection: directus_relations
|
|
17
|
+
action: read
|
|
@@ -14,6 +14,16 @@ fields:
|
|
|
14
14
|
translations: Name
|
|
15
15
|
width: half
|
|
16
16
|
|
|
17
|
+
- field: project_descriptor
|
|
18
|
+
interface: input
|
|
19
|
+
options:
|
|
20
|
+
iconRight: title
|
|
21
|
+
placeholder: $t:field_options.directus_settings.project_name_placeholder
|
|
22
|
+
translations:
|
|
23
|
+
language: en-US
|
|
24
|
+
translations: Name
|
|
25
|
+
width: half
|
|
26
|
+
|
|
17
27
|
- field: project_url
|
|
18
28
|
interface: input
|
|
19
29
|
options:
|
|
@@ -22,7 +32,7 @@ fields:
|
|
|
22
32
|
translations:
|
|
23
33
|
language: en-US
|
|
24
34
|
translations: Website
|
|
25
|
-
width:
|
|
35
|
+
width: full
|
|
26
36
|
|
|
27
37
|
- field: branding_divider
|
|
28
38
|
interface: presentation-divider
|
|
@@ -343,3 +353,12 @@ fields:
|
|
|
343
353
|
type:
|
|
344
354
|
_neq: 'raster'
|
|
345
355
|
hidden: true
|
|
356
|
+
- field: attribution
|
|
357
|
+
name: $t:fields.directus_settings.attribution
|
|
358
|
+
type: string
|
|
359
|
+
schema:
|
|
360
|
+
is_nullable: true
|
|
361
|
+
meta:
|
|
362
|
+
interface: input
|
|
363
|
+
options:
|
|
364
|
+
placeholder: $t:fields.directus_settings.attribution_placeholder
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
table: directus_shares
|
|
2
|
+
|
|
3
|
+
fields:
|
|
4
|
+
- field: id
|
|
5
|
+
special: uuid
|
|
6
|
+
readonly: true
|
|
7
|
+
hidden: true
|
|
8
|
+
|
|
9
|
+
- field: name
|
|
10
|
+
|
|
11
|
+
- field: collection
|
|
12
|
+
width: half
|
|
13
|
+
hidden: true
|
|
14
|
+
|
|
15
|
+
- field: item
|
|
16
|
+
width: half
|
|
17
|
+
hidden: true
|
|
18
|
+
|
|
19
|
+
- field: role
|
|
20
|
+
interface: select-dropdown-m2o
|
|
21
|
+
width: half
|
|
22
|
+
options:
|
|
23
|
+
template: '{{name}}'
|
|
24
|
+
filter:
|
|
25
|
+
admin_access:
|
|
26
|
+
_eq: false
|
|
27
|
+
|
|
28
|
+
- field: password
|
|
29
|
+
special: hash,conceal
|
|
30
|
+
interface: input-hash
|
|
31
|
+
options:
|
|
32
|
+
iconRight: lock
|
|
33
|
+
masked: true
|
|
34
|
+
width: half
|
|
35
|
+
note: $t:shared_leave_blank_for_unlimited
|
|
36
|
+
|
|
37
|
+
- field: date_start
|
|
38
|
+
width: half
|
|
39
|
+
note: $t:shared_leave_blank_for_unlimited
|
|
40
|
+
|
|
41
|
+
- field: date_end
|
|
42
|
+
width: half
|
|
43
|
+
note: $t:shared_leave_blank_for_unlimited
|
|
44
|
+
|
|
45
|
+
- field: max_uses
|
|
46
|
+
width: half
|
|
47
|
+
note: $t:shared_leave_blank_for_unlimited
|
|
48
|
+
|
|
49
|
+
- field: times_used
|
|
50
|
+
width: half
|
|
51
|
+
readonly: true
|
|
52
|
+
|
|
53
|
+
- field: date_created
|
|
54
|
+
special: date-created
|
|
55
|
+
width: half
|
|
56
|
+
readonly: true
|
|
57
|
+
conditions:
|
|
58
|
+
- name: notCreatedYet
|
|
59
|
+
rule:
|
|
60
|
+
id:
|
|
61
|
+
_null: true
|
|
62
|
+
hidden: true
|
|
63
|
+
|
|
64
|
+
- field: user_created
|
|
65
|
+
special: user-created
|
|
66
|
+
interface: select-dropdown-m2o
|
|
67
|
+
width: half
|
|
68
|
+
display: user
|
|
69
|
+
options:
|
|
70
|
+
template: '{{avatar.$thumbnail}} {{first_name}} {{last_name}}'
|
|
71
|
+
readonly: true
|
|
72
|
+
conditions:
|
|
73
|
+
- name: notCreatedYet
|
|
74
|
+
rule:
|
|
75
|
+
id:
|
|
76
|
+
_null: true
|
|
77
|
+
hidden: true
|
|
@@ -12,6 +12,9 @@ defaults:
|
|
|
12
12
|
sort_field: null
|
|
13
13
|
|
|
14
14
|
data:
|
|
15
|
+
- many_collection: directus_collections
|
|
16
|
+
many_field: group
|
|
17
|
+
one_collection: directus_collections
|
|
15
18
|
- many_collection: directus_users
|
|
16
19
|
many_field: role
|
|
17
20
|
one_collection: directus_roles
|
|
@@ -73,6 +76,9 @@ data:
|
|
|
73
76
|
- many_collection: directus_sessions
|
|
74
77
|
many_field: user
|
|
75
78
|
one_collection: directus_users
|
|
79
|
+
- many_collection: directus_sessions
|
|
80
|
+
many_field: share
|
|
81
|
+
one_collection: directus_shares
|
|
76
82
|
- many_collection: directus_settings
|
|
77
83
|
many_field: storage_default_folder
|
|
78
84
|
one_collection: directus_folders
|
|
@@ -88,3 +94,12 @@ data:
|
|
|
88
94
|
- many_collection: directus_notifications
|
|
89
95
|
many_field: sender
|
|
90
96
|
one_collection: directus_users
|
|
97
|
+
- many_collection: directus_shares
|
|
98
|
+
many_field: role
|
|
99
|
+
one_collection: directus_roles
|
|
100
|
+
- many_collection: directus_shares
|
|
101
|
+
many_field: collection
|
|
102
|
+
one_collection: directus_collections
|
|
103
|
+
- many_collection: directus_shares
|
|
104
|
+
many_field: user_created
|
|
105
|
+
one_collection: directus_users
|