directus 9.2.0 → 9.2.1
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/auth/drivers/ldap.js +5 -2
- package/dist/auth/drivers/oauth2.d.ts +1 -1
- package/dist/auth/drivers/oauth2.js +46 -19
- package/dist/auth/drivers/openid.d.ts +1 -1
- package/dist/auth/drivers/openid.js +34 -17
- package/dist/exceptions/index.d.ts +1 -0
- package/dist/exceptions/index.js +1 -0
- package/dist/exceptions/invalid-token.d.ts +4 -0
- package/dist/exceptions/invalid-token.js +10 -0
- package/dist/utils/apply-query.js +1 -2
- package/dist/utils/merge-permissions.js +2 -2
- package/package.json +13 -13
|
@@ -94,7 +94,10 @@ class LDAPAuthDriver extends auth_1.AuthDriver {
|
|
|
94
94
|
const { userDn, userAttribute, userScope } = this.config;
|
|
95
95
|
return new Promise((resolve, reject) => {
|
|
96
96
|
// Search for the user in LDAP by attribute
|
|
97
|
-
this.bindClient.search(userDn, {
|
|
97
|
+
this.bindClient.search(userDn, {
|
|
98
|
+
filter: new ldapjs_1.EqualityFilter({ attribute: userAttribute !== null && userAttribute !== void 0 ? userAttribute : 'cn', value: identifier }),
|
|
99
|
+
scope: userScope !== null && userScope !== void 0 ? userScope : 'one',
|
|
100
|
+
}, (err, res) => {
|
|
98
101
|
if (err) {
|
|
99
102
|
reject(handleError(err));
|
|
100
103
|
return;
|
|
@@ -151,7 +154,7 @@ class LDAPAuthDriver extends auth_1.AuthDriver {
|
|
|
151
154
|
// Search for the user info in LDAP by group attribute
|
|
152
155
|
this.bindClient.search(groupDn, {
|
|
153
156
|
attributes: ['cn'],
|
|
154
|
-
filter:
|
|
157
|
+
filter: new ldapjs_1.EqualityFilter({ attribute: groupAttribute !== null && groupAttribute !== void 0 ? groupAttribute : 'member', value: userDn }),
|
|
155
158
|
scope: groupScope !== null && groupScope !== void 0 ? groupScope : 'one',
|
|
156
159
|
}, (err, res) => {
|
|
157
160
|
if (err) {
|
|
@@ -10,7 +10,7 @@ export declare class OAuth2AuthDriver extends LocalAuthDriver {
|
|
|
10
10
|
config: Record<string, any>;
|
|
11
11
|
constructor(options: AuthDriverOptions, config: Record<string, any>);
|
|
12
12
|
generateCodeVerifier(): string;
|
|
13
|
-
generateAuthUrl(codeVerifier: string): string;
|
|
13
|
+
generateAuthUrl(codeVerifier: string, prompt?: boolean): string;
|
|
14
14
|
private fetchUserId;
|
|
15
15
|
getUserID(payload: Record<string, any>): Promise<string>;
|
|
16
16
|
login(user: User): Promise<SessionData>;
|
|
@@ -32,7 +32,8 @@ class OAuth2AuthDriver extends local_1.LocalAuthDriver {
|
|
|
32
32
|
authorization_endpoint: authorizeUrl,
|
|
33
33
|
token_endpoint: accessUrl,
|
|
34
34
|
userinfo_endpoint: profileUrl,
|
|
35
|
-
|
|
35
|
+
// Required for openid providers (openid flow should be preferred!)
|
|
36
|
+
issuer: additionalConfig.issuerUrl,
|
|
36
37
|
});
|
|
37
38
|
this.client = new issuer.Client({
|
|
38
39
|
client_id: clientId,
|
|
@@ -44,17 +45,20 @@ class OAuth2AuthDriver extends local_1.LocalAuthDriver {
|
|
|
44
45
|
generateCodeVerifier() {
|
|
45
46
|
return openid_client_1.generators.codeVerifier();
|
|
46
47
|
}
|
|
47
|
-
generateAuthUrl(codeVerifier) {
|
|
48
|
+
generateAuthUrl(codeVerifier, prompt = false) {
|
|
48
49
|
var _a;
|
|
49
50
|
try {
|
|
50
51
|
const codeChallenge = openid_client_1.generators.codeChallenge(codeVerifier);
|
|
52
|
+
const paramsConfig = typeof this.config.params === 'object' ? this.config.params : {};
|
|
51
53
|
return this.client.authorizationUrl({
|
|
52
54
|
scope: (_a = this.config.scope) !== null && _a !== void 0 ? _a : 'email',
|
|
55
|
+
access_type: 'offline',
|
|
56
|
+
prompt: prompt ? 'consent' : undefined,
|
|
57
|
+
...paramsConfig,
|
|
53
58
|
code_challenge: codeChallenge,
|
|
54
59
|
code_challenge_method: 'S256',
|
|
55
60
|
// Some providers require state even with PKCE
|
|
56
61
|
state: codeChallenge,
|
|
57
|
-
access_type: 'offline',
|
|
58
62
|
});
|
|
59
63
|
}
|
|
60
64
|
catch (e) {
|
|
@@ -72,6 +76,7 @@ class OAuth2AuthDriver extends local_1.LocalAuthDriver {
|
|
|
72
76
|
async getUserID(payload) {
|
|
73
77
|
var _a;
|
|
74
78
|
if (!payload.code || !payload.codeVerifier) {
|
|
79
|
+
logger_1.default.trace('[OAuth2] No code or codeVerifier in payload');
|
|
75
80
|
throw new exceptions_1.InvalidCredentialsException();
|
|
76
81
|
}
|
|
77
82
|
let tokenSet;
|
|
@@ -112,6 +117,7 @@ class OAuth2AuthDriver extends local_1.LocalAuthDriver {
|
|
|
112
117
|
}
|
|
113
118
|
// Is public registration allowed?
|
|
114
119
|
if (!allowPublicRegistration) {
|
|
120
|
+
logger_1.default.trace(`[OAuth2] User doesn't exist, and public registration not allowed for provider "${this.config.provider}"`);
|
|
115
121
|
throw new exceptions_1.InvalidCredentialsException();
|
|
116
122
|
}
|
|
117
123
|
await this.usersService.createOne({
|
|
@@ -136,35 +142,44 @@ class OAuth2AuthDriver extends local_1.LocalAuthDriver {
|
|
|
136
142
|
logger_1.default.warn(`Session data isn't valid JSON: ${authData}`);
|
|
137
143
|
}
|
|
138
144
|
}
|
|
139
|
-
if (
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
145
|
+
if (authData === null || authData === void 0 ? void 0 : authData.refreshToken) {
|
|
146
|
+
try {
|
|
147
|
+
const tokenSet = await this.client.refresh(authData.refreshToken);
|
|
148
|
+
// Update user refreshToken if provided
|
|
149
|
+
if (tokenSet.refresh_token) {
|
|
150
|
+
await this.usersService.updateOne(user.id, {
|
|
151
|
+
auth_data: JSON.stringify({ refreshToken: tokenSet.refresh_token }),
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
catch (e) {
|
|
156
|
+
throw handleError(e);
|
|
157
|
+
}
|
|
148
158
|
}
|
|
159
|
+
return sessionData;
|
|
149
160
|
}
|
|
150
161
|
}
|
|
151
162
|
exports.OAuth2AuthDriver = OAuth2AuthDriver;
|
|
152
163
|
const handleError = (e) => {
|
|
153
164
|
if (e instanceof openid_client_1.errors.OPError) {
|
|
154
165
|
if (e.error === 'invalid_grant') {
|
|
166
|
+
logger_1.default.trace(e, `[OAuth2] Invalid grant.`);
|
|
155
167
|
// Invalid token
|
|
156
|
-
return new exceptions_1.
|
|
168
|
+
return new exceptions_1.InvalidTokenException();
|
|
157
169
|
}
|
|
170
|
+
logger_1.default.trace(e, `[OAuth2] Unknown OP error.`);
|
|
158
171
|
// Server response error
|
|
159
172
|
return new exceptions_1.ServiceUnavailableException('Service returned unexpected response', {
|
|
160
|
-
service: '
|
|
173
|
+
service: 'oauth2',
|
|
161
174
|
message: e.error_description,
|
|
162
175
|
});
|
|
163
176
|
}
|
|
164
177
|
else if (e instanceof openid_client_1.errors.RPError) {
|
|
165
178
|
// Internal client error
|
|
179
|
+
logger_1.default.trace(e, `[OAuth2] Unknown RP error.`);
|
|
166
180
|
return new exceptions_1.InvalidCredentialsException();
|
|
167
181
|
}
|
|
182
|
+
logger_1.default.trace(e, `[OAuth2] Unknown error.`);
|
|
168
183
|
return e;
|
|
169
184
|
};
|
|
170
185
|
function createOAuth2AuthRouter(providerName) {
|
|
@@ -172,7 +187,8 @@ function createOAuth2AuthRouter(providerName) {
|
|
|
172
187
|
router.get('/', (req, res) => {
|
|
173
188
|
const provider = (0, auth_1.getAuthProvider)(providerName);
|
|
174
189
|
const codeVerifier = provider.generateCodeVerifier();
|
|
175
|
-
const
|
|
190
|
+
const prompt = !!req.query.prompt;
|
|
191
|
+
const token = jsonwebtoken_1.default.sign({ verifier: codeVerifier, redirect: req.query.redirect, prompt }, env_1.default.SECRET, {
|
|
176
192
|
expiresIn: '5m',
|
|
177
193
|
issuer: 'directus',
|
|
178
194
|
});
|
|
@@ -180,7 +196,7 @@ function createOAuth2AuthRouter(providerName) {
|
|
|
180
196
|
httpOnly: true,
|
|
181
197
|
sameSite: 'lax',
|
|
182
198
|
});
|
|
183
|
-
return res.redirect(provider.generateAuthUrl(codeVerifier));
|
|
199
|
+
return res.redirect(provider.generateAuthUrl(codeVerifier, prompt));
|
|
184
200
|
}, respond_1.respond);
|
|
185
201
|
router.get('/callback', (0, async_handler_1.default)(async (req, res, next) => {
|
|
186
202
|
var _a;
|
|
@@ -189,9 +205,10 @@ function createOAuth2AuthRouter(providerName) {
|
|
|
189
205
|
tokenData = jsonwebtoken_1.default.verify(req.cookies[`oauth2.${providerName}`], env_1.default.SECRET, { issuer: 'directus' });
|
|
190
206
|
}
|
|
191
207
|
catch (e) {
|
|
208
|
+
logger_1.default.warn(e, `[OAuth2] Couldn't verify OAuth2 cookie`);
|
|
192
209
|
throw new exceptions_1.InvalidCredentialsException();
|
|
193
210
|
}
|
|
194
|
-
const { verifier, redirect } = tokenData;
|
|
211
|
+
const { verifier, redirect, prompt } = tokenData;
|
|
195
212
|
const authenticationService = new services_1.AuthenticationService({
|
|
196
213
|
accountability: {
|
|
197
214
|
ip: req.ip,
|
|
@@ -204,7 +221,7 @@ function createOAuth2AuthRouter(providerName) {
|
|
|
204
221
|
try {
|
|
205
222
|
res.clearCookie(`oauth2.${providerName}`);
|
|
206
223
|
if (!req.query.code || !req.query.state) {
|
|
207
|
-
logger_1.default.warn(`Couldn't extract OAuth2 code or state from query: ${JSON.stringify(req.query)}`);
|
|
224
|
+
logger_1.default.warn(`[OAuth2]Couldn't extract OAuth2 code or state from query: ${JSON.stringify(req.query)}`);
|
|
208
225
|
}
|
|
209
226
|
authResponse = await authenticationService.login(providerName, {
|
|
210
227
|
code: req.query.code,
|
|
@@ -213,7 +230,10 @@ function createOAuth2AuthRouter(providerName) {
|
|
|
213
230
|
});
|
|
214
231
|
}
|
|
215
232
|
catch (error) {
|
|
216
|
-
|
|
233
|
+
// Prompt user for a new refresh_token if invalidated
|
|
234
|
+
if (error instanceof exceptions_1.InvalidTokenException && !prompt) {
|
|
235
|
+
return res.redirect(`./?${redirect ? `redirect=${redirect}&` : ''}prompt=true`);
|
|
236
|
+
}
|
|
217
237
|
if (redirect) {
|
|
218
238
|
let reason = 'UNKNOWN_EXCEPTION';
|
|
219
239
|
if (error instanceof exceptions_1.ServiceUnavailableException) {
|
|
@@ -222,8 +242,15 @@ function createOAuth2AuthRouter(providerName) {
|
|
|
222
242
|
else if (error instanceof exceptions_1.InvalidCredentialsException) {
|
|
223
243
|
reason = 'INVALID_USER';
|
|
224
244
|
}
|
|
245
|
+
else if (error instanceof exceptions_1.InvalidTokenException) {
|
|
246
|
+
reason = 'INVALID_TOKEN';
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
logger_1.default.warn(error, `[OAuth2] Unexpected error during OAuth2 login`);
|
|
250
|
+
}
|
|
225
251
|
return res.redirect(`${redirect.split('?')[0]}?reason=${reason}`);
|
|
226
252
|
}
|
|
253
|
+
logger_1.default.warn(error, `[OAuth2] Unexpected error during OAuth2 login`);
|
|
227
254
|
throw error;
|
|
228
255
|
}
|
|
229
256
|
const { accessToken, refreshToken, expires } = authResponse;
|
|
@@ -10,7 +10,7 @@ export declare class OpenIDAuthDriver extends LocalAuthDriver {
|
|
|
10
10
|
config: Record<string, any>;
|
|
11
11
|
constructor(options: AuthDriverOptions, config: Record<string, any>);
|
|
12
12
|
generateCodeVerifier(): string;
|
|
13
|
-
generateAuthUrl(codeVerifier: string): Promise<string>;
|
|
13
|
+
generateAuthUrl(codeVerifier: string, prompt?: boolean): Promise<string>;
|
|
14
14
|
private fetchUserId;
|
|
15
15
|
getUserID(payload: Record<string, any>): Promise<string>;
|
|
16
16
|
login(user: User): Promise<SessionData>;
|
|
@@ -50,18 +50,21 @@ class OpenIDAuthDriver extends local_1.LocalAuthDriver {
|
|
|
50
50
|
generateCodeVerifier() {
|
|
51
51
|
return openid_client_1.generators.codeVerifier();
|
|
52
52
|
}
|
|
53
|
-
async generateAuthUrl(codeVerifier) {
|
|
53
|
+
async generateAuthUrl(codeVerifier, prompt = false) {
|
|
54
54
|
var _a;
|
|
55
55
|
try {
|
|
56
56
|
const client = await this.client;
|
|
57
57
|
const codeChallenge = openid_client_1.generators.codeChallenge(codeVerifier);
|
|
58
|
+
const paramsConfig = typeof this.config.params === 'object' ? this.config.params : {};
|
|
58
59
|
return client.authorizationUrl({
|
|
59
60
|
scope: (_a = this.config.scope) !== null && _a !== void 0 ? _a : 'openid profile email',
|
|
61
|
+
access_type: 'offline',
|
|
62
|
+
prompt: prompt ? 'consent' : undefined,
|
|
63
|
+
...paramsConfig,
|
|
60
64
|
code_challenge: codeChallenge,
|
|
61
65
|
code_challenge_method: 'S256',
|
|
62
66
|
// Some providers require state even with PKCE
|
|
63
67
|
state: codeChallenge,
|
|
64
|
-
access_type: 'offline',
|
|
65
68
|
});
|
|
66
69
|
}
|
|
67
70
|
catch (e) {
|
|
@@ -144,17 +147,22 @@ class OpenIDAuthDriver extends local_1.LocalAuthDriver {
|
|
|
144
147
|
logger_1.default.warn(`Session data isn't valid JSON: ${authData}`);
|
|
145
148
|
}
|
|
146
149
|
}
|
|
147
|
-
if (
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
150
|
+
if (authData === null || authData === void 0 ? void 0 : authData.refreshToken) {
|
|
151
|
+
try {
|
|
152
|
+
const client = await this.client;
|
|
153
|
+
const tokenSet = await client.refresh(authData.refreshToken);
|
|
154
|
+
// Update user refreshToken if provided
|
|
155
|
+
if (tokenSet.refresh_token) {
|
|
156
|
+
await this.usersService.updateOne(user.id, {
|
|
157
|
+
auth_data: JSON.stringify({ refreshToken: tokenSet.refresh_token }),
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
catch (e) {
|
|
162
|
+
throw handleError(e);
|
|
163
|
+
}
|
|
157
164
|
}
|
|
165
|
+
return sessionData;
|
|
158
166
|
}
|
|
159
167
|
}
|
|
160
168
|
exports.OpenIDAuthDriver = OpenIDAuthDriver;
|
|
@@ -162,7 +170,7 @@ const handleError = (e) => {
|
|
|
162
170
|
if (e instanceof openid_client_1.errors.OPError) {
|
|
163
171
|
if (e.error === 'invalid_grant') {
|
|
164
172
|
// Invalid token
|
|
165
|
-
return new exceptions_1.
|
|
173
|
+
return new exceptions_1.InvalidTokenException();
|
|
166
174
|
}
|
|
167
175
|
// Server response error
|
|
168
176
|
return new exceptions_1.ServiceUnavailableException('Service returned unexpected response', {
|
|
@@ -181,7 +189,8 @@ function createOpenIDAuthRouter(providerName) {
|
|
|
181
189
|
router.get('/', (0, async_handler_1.default)(async (req, res) => {
|
|
182
190
|
const provider = (0, auth_1.getAuthProvider)(providerName);
|
|
183
191
|
const codeVerifier = provider.generateCodeVerifier();
|
|
184
|
-
const
|
|
192
|
+
const prompt = !!req.query.prompt;
|
|
193
|
+
const token = jsonwebtoken_1.default.sign({ verifier: codeVerifier, redirect: req.query.redirect, prompt }, env_1.default.SECRET, {
|
|
185
194
|
expiresIn: '5m',
|
|
186
195
|
issuer: 'directus',
|
|
187
196
|
});
|
|
@@ -189,7 +198,7 @@ function createOpenIDAuthRouter(providerName) {
|
|
|
189
198
|
httpOnly: true,
|
|
190
199
|
sameSite: 'lax',
|
|
191
200
|
});
|
|
192
|
-
return res.redirect(await provider.generateAuthUrl(codeVerifier));
|
|
201
|
+
return res.redirect(await provider.generateAuthUrl(codeVerifier, prompt));
|
|
193
202
|
}), respond_1.respond);
|
|
194
203
|
router.get('/callback', (0, async_handler_1.default)(async (req, res, next) => {
|
|
195
204
|
var _a;
|
|
@@ -198,9 +207,10 @@ function createOpenIDAuthRouter(providerName) {
|
|
|
198
207
|
tokenData = jsonwebtoken_1.default.verify(req.cookies[`openid.${providerName}`], env_1.default.SECRET, { issuer: 'directus' });
|
|
199
208
|
}
|
|
200
209
|
catch (e) {
|
|
210
|
+
logger_1.default.warn(e, `[OpenID] Couldn't verify OpenID cookie`);
|
|
201
211
|
throw new exceptions_1.InvalidCredentialsException();
|
|
202
212
|
}
|
|
203
|
-
const { verifier, redirect } = tokenData;
|
|
213
|
+
const { verifier, redirect, prompt } = tokenData;
|
|
204
214
|
const authenticationService = new services_1.AuthenticationService({
|
|
205
215
|
accountability: {
|
|
206
216
|
ip: req.ip,
|
|
@@ -213,7 +223,7 @@ function createOpenIDAuthRouter(providerName) {
|
|
|
213
223
|
try {
|
|
214
224
|
res.clearCookie(`openid.${providerName}`);
|
|
215
225
|
if (!req.query.code || !req.query.state) {
|
|
216
|
-
logger_1.default.warn(`Couldn't extract OpenID code or state from query: ${JSON.stringify(req.query)}`);
|
|
226
|
+
logger_1.default.warn(`[OpenID] Couldn't extract OpenID code or state from query: ${JSON.stringify(req.query)}`);
|
|
217
227
|
}
|
|
218
228
|
authResponse = await authenticationService.login(providerName, {
|
|
219
229
|
code: req.query.code,
|
|
@@ -222,6 +232,10 @@ function createOpenIDAuthRouter(providerName) {
|
|
|
222
232
|
});
|
|
223
233
|
}
|
|
224
234
|
catch (error) {
|
|
235
|
+
// Prompt user for a new refresh_token if invalidated
|
|
236
|
+
if (error instanceof exceptions_1.InvalidTokenException && !prompt) {
|
|
237
|
+
return res.redirect(`./?${redirect ? `redirect=${redirect}&` : ''}prompt=true`);
|
|
238
|
+
}
|
|
225
239
|
logger_1.default.warn(error);
|
|
226
240
|
if (redirect) {
|
|
227
241
|
let reason = 'UNKNOWN_EXCEPTION';
|
|
@@ -231,6 +245,9 @@ function createOpenIDAuthRouter(providerName) {
|
|
|
231
245
|
else if (error instanceof exceptions_1.InvalidCredentialsException) {
|
|
232
246
|
reason = 'INVALID_USER';
|
|
233
247
|
}
|
|
248
|
+
else if (error instanceof exceptions_1.InvalidTokenException) {
|
|
249
|
+
reason = 'INVALID_TOKEN';
|
|
250
|
+
}
|
|
234
251
|
return res.redirect(`${redirect.split('?')[0]}?reason=${reason}`);
|
|
235
252
|
}
|
|
236
253
|
throw error;
|
|
@@ -8,6 +8,7 @@ export * from './invalid-ip';
|
|
|
8
8
|
export * from './invalid-otp';
|
|
9
9
|
export * from './invalid-payload';
|
|
10
10
|
export * from './invalid-query';
|
|
11
|
+
export * from './invalid-token';
|
|
11
12
|
export * from './method-not-allowed';
|
|
12
13
|
export * from './range-not-satisfiable';
|
|
13
14
|
export * from './route-not-found';
|
package/dist/exceptions/index.js
CHANGED
|
@@ -20,6 +20,7 @@ __exportStar(require("./invalid-ip"), exports);
|
|
|
20
20
|
__exportStar(require("./invalid-otp"), exports);
|
|
21
21
|
__exportStar(require("./invalid-payload"), exports);
|
|
22
22
|
__exportStar(require("./invalid-query"), exports);
|
|
23
|
+
__exportStar(require("./invalid-token"), exports);
|
|
23
24
|
__exportStar(require("./method-not-allowed"), exports);
|
|
24
25
|
__exportStar(require("./range-not-satisfiable"), exports);
|
|
25
26
|
__exportStar(require("./route-not-found"), exports);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InvalidTokenException = void 0;
|
|
4
|
+
const exceptions_1 = require("@directus/shared/exceptions");
|
|
5
|
+
class InvalidTokenException extends exceptions_1.BaseException {
|
|
6
|
+
constructor(message = 'Invalid token') {
|
|
7
|
+
super(message, 403, 'INVALID_TOKEN');
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
exports.InvalidTokenException = InvalidTokenException;
|
|
@@ -8,7 +8,6 @@ const lodash_1 = require("lodash");
|
|
|
8
8
|
const nanoid_1 = require("nanoid");
|
|
9
9
|
const uuid_validate_1 = __importDefault(require("uuid-validate"));
|
|
10
10
|
const exceptions_1 = require("../exceptions");
|
|
11
|
-
const apply_function_to_column_name_1 = require("./apply-function-to-column-name");
|
|
12
11
|
const get_column_1 = require("./get-column");
|
|
13
12
|
const get_relation_type_1 = require("./get-relation-type");
|
|
14
13
|
const helpers_1 = require("../database/helpers");
|
|
@@ -44,7 +43,7 @@ function applyQuery(knex, collection, dbQuery, query, schema, subQuery = false)
|
|
|
44
43
|
applySearch(schema, dbQuery, query.search, collection);
|
|
45
44
|
}
|
|
46
45
|
if (query.group) {
|
|
47
|
-
dbQuery.groupBy(
|
|
46
|
+
dbQuery.groupBy(query.group.map((column) => (0, get_column_1.getColumn)(knex, collection, column, false)));
|
|
48
47
|
}
|
|
49
48
|
if (query.aggregate) {
|
|
50
49
|
applyAggregate(dbQuery, query.aggregate, collection);
|
|
@@ -23,13 +23,13 @@ function mergePerm(currentPerm, newPerm) {
|
|
|
23
23
|
let validation = currentPerm.validation;
|
|
24
24
|
let fields = currentPerm.fields;
|
|
25
25
|
let presets = currentPerm.presets;
|
|
26
|
-
if (newPerm.permissions
|
|
26
|
+
if (newPerm.permissions) {
|
|
27
27
|
if (currentPerm.permissions && Object.keys(currentPerm.permissions)[0] === '_or') {
|
|
28
28
|
permissions = {
|
|
29
29
|
_or: [...currentPerm.permissions._or, newPerm.permissions],
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
|
-
else if (currentPerm.permissions
|
|
32
|
+
else if (currentPerm.permissions) {
|
|
33
33
|
permissions = {
|
|
34
34
|
_or: [currentPerm.permissions, newPerm.permissions],
|
|
35
35
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "directus",
|
|
3
|
-
"version": "9.2.
|
|
3
|
+
"version": "9.2.1",
|
|
4
4
|
"license": "GPL-3.0-only",
|
|
5
5
|
"homepage": "https://github.com/directus/directus#readme",
|
|
6
6
|
"description": "Directus is a real-time API and App dashboard for managing SQL database content.",
|
|
@@ -76,16 +76,16 @@
|
|
|
76
76
|
],
|
|
77
77
|
"dependencies": {
|
|
78
78
|
"@aws-sdk/client-ses": "^3.40.0",
|
|
79
|
-
"@directus/app": "9.2.
|
|
80
|
-
"@directus/drive": "9.2.
|
|
81
|
-
"@directus/drive-azure": "9.2.
|
|
82
|
-
"@directus/drive-gcs": "9.2.
|
|
83
|
-
"@directus/drive-s3": "9.2.
|
|
84
|
-
"@directus/extensions-sdk": "9.2.
|
|
85
|
-
"@directus/format-title": "9.2.
|
|
86
|
-
"@directus/schema": "9.2.
|
|
87
|
-
"@directus/shared": "9.2.
|
|
88
|
-
"@directus/specs": "9.2.
|
|
79
|
+
"@directus/app": "9.2.1",
|
|
80
|
+
"@directus/drive": "9.2.1",
|
|
81
|
+
"@directus/drive-azure": "9.2.1",
|
|
82
|
+
"@directus/drive-gcs": "9.2.1",
|
|
83
|
+
"@directus/drive-s3": "9.2.1",
|
|
84
|
+
"@directus/extensions-sdk": "9.2.1",
|
|
85
|
+
"@directus/format-title": "9.2.1",
|
|
86
|
+
"@directus/schema": "9.2.1",
|
|
87
|
+
"@directus/shared": "9.2.1",
|
|
88
|
+
"@directus/specs": "9.2.1",
|
|
89
89
|
"@godaddy/terminus": "^4.9.0",
|
|
90
90
|
"@rollup/plugin-alias": "^3.1.2",
|
|
91
91
|
"@rollup/plugin-virtual": "^2.0.3",
|
|
@@ -169,7 +169,7 @@
|
|
|
169
169
|
"sqlite3": "^5.0.2",
|
|
170
170
|
"tedious": "^13.0.0"
|
|
171
171
|
},
|
|
172
|
-
"gitHead": "
|
|
172
|
+
"gitHead": "1d4e9c425c10bcdc5831ae63c1bd03649648eb5e",
|
|
173
173
|
"devDependencies": {
|
|
174
174
|
"@types/async": "3.2.10",
|
|
175
175
|
"@types/atob": "2.1.2",
|
|
@@ -199,7 +199,7 @@
|
|
|
199
199
|
"@types/nodemailer": "6.4.4",
|
|
200
200
|
"@types/object-hash": "2.2.1",
|
|
201
201
|
"@types/qs": "6.9.7",
|
|
202
|
-
"@types/sanitize-html": "
|
|
202
|
+
"@types/sanitize-html": "2.5.0",
|
|
203
203
|
"@types/sharp": "0.29.4",
|
|
204
204
|
"@types/stream-json": "1.7.1",
|
|
205
205
|
"@types/supertest": "2.0.11",
|