directus 9.1.1 → 9.2.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.
Files changed (93) hide show
  1. package/dist/auth/drivers/ldap.js +11 -2
  2. package/dist/auth/drivers/oauth2.d.ts +1 -1
  3. package/dist/auth/drivers/oauth2.js +46 -19
  4. package/dist/auth/drivers/openid.d.ts +1 -1
  5. package/dist/auth/drivers/openid.js +34 -17
  6. package/dist/auth.js +5 -3
  7. package/dist/cli/commands/database/install.js +2 -4
  8. package/dist/cli/commands/schema/apply.js +26 -10
  9. package/dist/controllers/assets.js +0 -27
  10. package/dist/controllers/auth.js +7 -2
  11. package/dist/controllers/extensions.js +1 -1
  12. package/dist/database/{functions/types.d.ts → helpers/date/dialects/mssql.d.ts} +2 -1
  13. package/dist/database/{functions → helpers/date}/dialects/mssql.js +4 -6
  14. package/dist/database/{functions → helpers/date}/dialects/mysql.d.ts +2 -4
  15. package/dist/database/{functions → helpers/date}/dialects/mysql.js +4 -6
  16. package/dist/database/{functions/dialects/mssql.d.ts → helpers/date/dialects/oracle.d.ts} +2 -4
  17. package/dist/database/{functions → helpers/date}/dialects/oracle.js +4 -6
  18. package/dist/database/helpers/date/dialects/postgres.d.ts +12 -0
  19. package/dist/database/{functions → helpers/date}/dialects/postgres.js +4 -6
  20. package/dist/database/{functions → helpers/date}/dialects/sqlite.d.ts +3 -4
  21. package/dist/database/helpers/date/dialects/sqlite.js +35 -0
  22. package/dist/database/helpers/date/index.d.ts +6 -0
  23. package/dist/database/helpers/date/index.js +15 -0
  24. package/dist/database/helpers/date/types.d.ts +13 -0
  25. package/dist/database/helpers/date/types.js +10 -0
  26. package/dist/database/helpers/geometry/dialects/mssql.d.ts +14 -0
  27. package/dist/database/helpers/geometry/dialects/mssql.js +36 -0
  28. package/dist/database/helpers/geometry/dialects/mysql.d.ts +7 -0
  29. package/dist/database/helpers/geometry/dialects/mysql.js +16 -0
  30. package/dist/database/helpers/geometry/dialects/oracle.d.ts +15 -0
  31. package/dist/database/helpers/geometry/dialects/oracle.js +39 -0
  32. package/dist/database/helpers/geometry/dialects/postgres.d.ts +10 -0
  33. package/dist/database/helpers/geometry/dialects/postgres.js +23 -0
  34. package/dist/database/helpers/geometry/dialects/redshift.d.ts +7 -0
  35. package/dist/database/helpers/geometry/dialects/redshift.js +16 -0
  36. package/dist/database/helpers/geometry/dialects/sqlite.d.ts +6 -0
  37. package/dist/database/helpers/geometry/dialects/sqlite.js +14 -0
  38. package/dist/database/helpers/geometry/index.d.ts +6 -0
  39. package/dist/database/helpers/geometry/index.js +15 -0
  40. package/dist/database/helpers/{geometry.d.ts → geometry/types.d.ts} +3 -7
  41. package/dist/database/helpers/geometry/types.js +54 -0
  42. package/dist/database/helpers/index.d.ts +8 -0
  43. package/dist/database/helpers/index.js +33 -0
  44. package/dist/database/helpers/types.d.ts +5 -0
  45. package/dist/database/helpers/types.js +9 -0
  46. package/dist/database/index.js +6 -6
  47. package/dist/database/run-ast.js +5 -5
  48. package/dist/database/seeds/run.js +3 -3
  49. package/dist/database/system-data/fields/notifications.yaml +1 -0
  50. package/dist/env.js +1 -0
  51. package/dist/exceptions/index.d.ts +2 -0
  52. package/dist/exceptions/index.js +2 -0
  53. package/dist/exceptions/invalid-token.d.ts +4 -0
  54. package/dist/exceptions/invalid-token.js +10 -0
  55. package/dist/exceptions/unexpected-response.d.ts +4 -0
  56. package/dist/exceptions/unexpected-response.js +10 -0
  57. package/dist/extensions.js +17 -2
  58. package/dist/middleware/sanitize-query.js +1 -1
  59. package/dist/services/activity.js +7 -2
  60. package/dist/services/assets.js +14 -0
  61. package/dist/services/fields.d.ts +2 -0
  62. package/dist/services/fields.js +57 -26
  63. package/dist/services/files.d.ts +1 -1
  64. package/dist/services/files.js +13 -11
  65. package/dist/services/graphql.js +3 -0
  66. package/dist/services/items.js +18 -29
  67. package/dist/services/payload.d.ts +2 -0
  68. package/dist/services/payload.js +3 -3
  69. package/dist/services/users.js +8 -6
  70. package/dist/tests/database/migrations/run.test.d.ts +1 -0
  71. package/dist/tests/database/migrations/run.test.js +29 -0
  72. package/dist/utils/apply-query.js +9 -12
  73. package/dist/utils/apply-snapshot.js +27 -28
  74. package/dist/utils/get-column.js +2 -2
  75. package/dist/utils/get-default-index-name.js +2 -2
  76. package/dist/utils/get-local-type.js +1 -12
  77. package/dist/utils/get-permissions.d.ts +2 -2
  78. package/dist/utils/get-permissions.js +103 -66
  79. package/dist/utils/sanitize-query.js +1 -12
  80. package/dist/utils/validate-query.js +1 -1
  81. package/dist/webhooks.js +16 -24
  82. package/package.json +15 -14
  83. package/dist/database/functions/dialects/oracle.d.ts +0 -14
  84. package/dist/database/functions/dialects/postgres.d.ts +0 -14
  85. package/dist/database/functions/dialects/sqlite.js +0 -33
  86. package/dist/database/functions/index.d.ts +0 -3
  87. package/dist/database/functions/index.js +0 -26
  88. package/dist/database/functions/types.js +0 -2
  89. package/dist/database/helpers/date.d.ts +0 -8
  90. package/dist/database/helpers/date.js +0 -44
  91. package/dist/database/helpers/geometry.js +0 -189
  92. package/dist/utils/get-simple-hash.d.ts +0 -5
  93. package/dist/utils/get-simple-hash.js +0 -15
@@ -87,6 +87,12 @@ class LDAPAuthDriver extends auth_1.AuthDriver {
87
87
  }
88
88
  });
89
89
  });
90
+ res.on('end', (result) => {
91
+ if ((result === null || result === void 0 ? void 0 : result.status) === 0) {
92
+ // Handle edge case with IBM systems where authenticated bind user could not fetch their DN
93
+ reject(new exceptions_1.UnexpectedResponseException('Failed to find bind user record'));
94
+ }
95
+ });
90
96
  });
91
97
  });
92
98
  }
@@ -94,7 +100,10 @@ class LDAPAuthDriver extends auth_1.AuthDriver {
94
100
  const { userDn, userAttribute, userScope } = this.config;
95
101
  return new Promise((resolve, reject) => {
96
102
  // Search for the user in LDAP by attribute
97
- this.bindClient.search(userDn, { filter: `(${userAttribute !== null && userAttribute !== void 0 ? userAttribute : 'cn'}=${identifier})`, scope: userScope !== null && userScope !== void 0 ? userScope : 'one' }, (err, res) => {
103
+ this.bindClient.search(userDn, {
104
+ filter: new ldapjs_1.EqualityFilter({ attribute: userAttribute !== null && userAttribute !== void 0 ? userAttribute : 'cn', value: identifier }),
105
+ scope: userScope !== null && userScope !== void 0 ? userScope : 'one',
106
+ }, (err, res) => {
98
107
  if (err) {
99
108
  reject(handleError(err));
100
109
  return;
@@ -151,7 +160,7 @@ class LDAPAuthDriver extends auth_1.AuthDriver {
151
160
  // Search for the user info in LDAP by group attribute
152
161
  this.bindClient.search(groupDn, {
153
162
  attributes: ['cn'],
154
- filter: `(${groupAttribute !== null && groupAttribute !== void 0 ? groupAttribute : 'member'}=${userDn})`,
163
+ filter: new ldapjs_1.EqualityFilter({ attribute: groupAttribute !== null && groupAttribute !== void 0 ? groupAttribute : 'member', value: userDn }),
155
164
  scope: groupScope !== null && groupScope !== void 0 ? groupScope : 'one',
156
165
  }, (err, res) => {
157
166
  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
- issuer: additionalConfig.provider,
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 (!(authData === null || authData === void 0 ? void 0 : authData.refreshToken)) {
140
- return sessionData;
141
- }
142
- try {
143
- const tokenSet = await this.client.refresh(authData.refreshToken);
144
- return { accessToken: tokenSet.access_token };
145
- }
146
- catch (e) {
147
- throw handleError(e);
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.InvalidCredentialsException();
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: 'openid',
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 token = jsonwebtoken_1.default.sign({ verifier: codeVerifier, redirect: req.query.redirect }, env_1.default.SECRET, {
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
- logger_1.default.warn(error);
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 (!(authData === null || authData === void 0 ? void 0 : authData.refreshToken)) {
148
- return sessionData;
149
- }
150
- try {
151
- const client = await this.client;
152
- const tokenSet = await client.refresh(authData.refreshToken);
153
- return { accessToken: tokenSet.access_token };
154
- }
155
- catch (e) {
156
- throw handleError(e);
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.InvalidCredentialsException();
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 token = jsonwebtoken_1.default.sign({ verifier: codeVerifier, redirect: req.query.redirect }, env_1.default.SECRET, {
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;
package/dist/auth.js CHANGED
@@ -24,9 +24,11 @@ function getAuthProvider(provider) {
24
24
  exports.getAuthProvider = getAuthProvider;
25
25
  async function registerAuthProviders() {
26
26
  const options = { knex: (0, database_1.default)(), schema: await (0, get_schema_1.getSchema)() };
27
- const defaultProvider = getProviderInstance('local', options);
28
- // Register default provider
29
- providers.set(constants_1.DEFAULT_AUTH_PROVIDER, defaultProvider);
27
+ // Register default provider if not disabled
28
+ if (!env_1.default.AUTH_DISABLE_DEFAULT) {
29
+ const defaultProvider = getProviderInstance('local', options);
30
+ providers.set(constants_1.DEFAULT_AUTH_PROVIDER, defaultProvider);
31
+ }
30
32
  if (!env_1.default.AUTH_PROVIDERS) {
31
33
  return;
32
34
  }
@@ -3,15 +3,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- const run_1 = __importDefault(require("../../../database/migrations/run"));
7
- const run_2 = __importDefault(require("../../../database/seeds/run"));
6
+ const run_1 = __importDefault(require("../../../database/seeds/run"));
8
7
  const database_1 = __importDefault(require("../../../database"));
9
8
  const logger_1 = __importDefault(require("../../../logger"));
10
9
  async function start() {
11
10
  const database = (0, database_1.default)();
12
11
  try {
13
- await (0, run_2.default)(database);
14
- await (0, run_1.default)(database, 'latest');
12
+ await (0, run_1.default)(database);
15
13
  database.destroy();
16
14
  process.exit(0);
17
15
  }
@@ -35,7 +35,7 @@ const get_snapshot_diff_1 = require("../../../utils/get-snapshot-diff");
35
35
  const apply_snapshot_1 = require("../../../utils/apply-snapshot");
36
36
  const cache_1 = require("../../../cache");
37
37
  async function apply(snapshotPath, options) {
38
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
38
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
39
39
  const filename = path_1.default.resolve(process.cwd(), snapshotPath);
40
40
  const database = (0, database_1.default)();
41
41
  await (0, database_1.validateDatabaseConnection)(database);
@@ -83,12 +83,15 @@ async function apply(snapshotPath, options) {
83
83
  else if (((_c = diff[0]) === null || _c === void 0 ? void 0 : _c.kind) === 'N') {
84
84
  message += `\n - ${chalk_1.default.green('Create')} ${collection}`;
85
85
  }
86
+ else if (((_d = diff[0]) === null || _d === void 0 ? void 0 : _d.kind) === 'A') {
87
+ message += `\n - ${chalk_1.default.blue('Update')} ${collection}`;
88
+ }
86
89
  }
87
90
  }
88
91
  if (snapshotDiff.fields.length > 0) {
89
92
  message += '\n\n' + chalk_1.default.black.underline.bold('Fields:');
90
93
  for (const { collection, field, diff } of snapshotDiff.fields) {
91
- if (((_d = diff[0]) === null || _d === void 0 ? void 0 : _d.kind) === 'E') {
94
+ if (((_e = diff[0]) === null || _e === void 0 ? void 0 : _e.kind) === 'E') {
92
95
  message += `\n - ${chalk_1.default.blue('Update')} ${collection}.${field}`;
93
96
  for (const change of diff) {
94
97
  if (change.kind === 'E') {
@@ -97,19 +100,22 @@ async function apply(snapshotPath, options) {
97
100
  }
98
101
  }
99
102
  }
100
- else if (((_e = diff[0]) === null || _e === void 0 ? void 0 : _e.kind) === 'D') {
103
+ else if (((_f = diff[0]) === null || _f === void 0 ? void 0 : _f.kind) === 'D') {
101
104
  message += `\n - ${chalk_1.default.red('Delete')} ${collection}.${field}`;
102
105
  }
103
- else if (((_f = diff[0]) === null || _f === void 0 ? void 0 : _f.kind) === 'N') {
106
+ else if (((_g = diff[0]) === null || _g === void 0 ? void 0 : _g.kind) === 'N') {
104
107
  message += `\n - ${chalk_1.default.green('Create')} ${collection}.${field}`;
105
108
  }
109
+ else if (((_h = diff[0]) === null || _h === void 0 ? void 0 : _h.kind) === 'A') {
110
+ message += `\n - ${chalk_1.default.blue('Update')} ${collection}.${field}`;
111
+ }
106
112
  }
107
113
  }
108
114
  if (snapshotDiff.relations.length > 0) {
109
115
  message += '\n\n' + chalk_1.default.black.underline.bold('Relations:');
110
116
  for (const { collection, field, related_collection, diff } of snapshotDiff.relations) {
111
- if (((_g = diff[0]) === null || _g === void 0 ? void 0 : _g.kind) === 'E') {
112
- message += `\n - ${chalk_1.default.blue('Update')} ${collection}.${field} -> ${related_collection}`;
117
+ if (((_j = diff[0]) === null || _j === void 0 ? void 0 : _j.kind) === 'E') {
118
+ message += `\n - ${chalk_1.default.blue('Update')} ${collection}.${field}`;
113
119
  for (const change of diff) {
114
120
  if (change.kind === 'E') {
115
121
  const path = change.path.slice(1).join('.');
@@ -117,11 +123,21 @@ async function apply(snapshotPath, options) {
117
123
  }
118
124
  }
119
125
  }
120
- else if (((_h = diff[0]) === null || _h === void 0 ? void 0 : _h.kind) === 'D') {
121
- message += `\n - ${chalk_1.default.red('Delete')} ${collection}.${field} -> ${related_collection}`;
126
+ else if (((_k = diff[0]) === null || _k === void 0 ? void 0 : _k.kind) === 'D') {
127
+ message += `\n - ${chalk_1.default.red('Delete')} ${collection}.${field}`;
128
+ }
129
+ else if (((_l = diff[0]) === null || _l === void 0 ? void 0 : _l.kind) === 'N') {
130
+ message += `\n - ${chalk_1.default.green('Create')} ${collection}.${field}`;
131
+ }
132
+ else if (((_m = diff[0]) === null || _m === void 0 ? void 0 : _m.kind) === 'A') {
133
+ message += `\n - ${chalk_1.default.blue('Update')} ${collection}.${field}`;
134
+ }
135
+ else {
136
+ continue;
122
137
  }
123
- else if (((_j = diff[0]) === null || _j === void 0 ? void 0 : _j.kind) === 'N') {
124
- message += `\n - ${chalk_1.default.green('Create')} ${collection}.${field} -> ${related_collection}`;
138
+ // Related collection doesn't exist for m2a relationship types
139
+ if (related_collection) {
140
+ message += `-> ${related_collection}`;
125
141
  }
126
142
  }
127
143
  }
@@ -6,44 +6,17 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const express_1 = require("express");
7
7
  const lodash_1 = require("lodash");
8
8
  const ms_1 = __importDefault(require("ms"));
9
- const uuid_validate_1 = __importDefault(require("uuid-validate"));
10
9
  const constants_1 = require("../constants");
11
10
  const database_1 = __importDefault(require("../database"));
12
11
  const env_1 = __importDefault(require("../env"));
13
12
  const exceptions_1 = require("../exceptions");
14
13
  const use_collection_1 = __importDefault(require("../middleware/use-collection"));
15
14
  const services_1 = require("../services");
16
- const storage_1 = __importDefault(require("../storage"));
17
15
  const assets_1 = require("../types/assets");
18
16
  const async_handler_1 = __importDefault(require("../utils/async-handler"));
19
17
  const router = (0, express_1.Router)();
20
18
  router.use((0, use_collection_1.default)('directus_files'));
21
19
  router.get('/:pk',
22
- // Check if file exists and if you have permission to read it
23
- (0, async_handler_1.default)(async (req, res, next) => {
24
- var _a;
25
- /**
26
- * We ignore everything in the id after the first 36 characters (uuid length). This allows the
27
- * user to add an optional extension, or other identifier for use in external software (#4067)
28
- */
29
- const id = (_a = req.params.pk) === null || _a === void 0 ? void 0 : _a.substring(0, 36);
30
- /**
31
- * This is a little annoying. Postgres will error out if you're trying to search in `where`
32
- * with a wrong type. In case of directus_files where id is a uuid, we'll have to verify the
33
- * validity of the uuid ahead of time.
34
- */
35
- const isValidUUID = (0, uuid_validate_1.default)(id, 4);
36
- if (isValidUUID === false)
37
- throw new exceptions_1.ForbiddenException();
38
- const database = (0, database_1.default)();
39
- const file = await database.select('id', 'storage', 'filename_disk').from('directus_files').where({ id }).first();
40
- if (!file)
41
- throw new exceptions_1.ForbiddenException();
42
- const { exists } = await storage_1.default.disk(file.storage).exists(file.filename_disk);
43
- if (!exists)
44
- throw new exceptions_1.ForbiddenException();
45
- return next();
46
- }),
47
20
  // Validate query params
48
21
  (0, async_handler_1.default)(async (req, res, next) => {
49
22
  const payloadService = new services_1.PayloadService('directus_settings', { schema: req.schema });
@@ -38,7 +38,9 @@ for (const authProvider of authProviders) {
38
38
  }
39
39
  router.use(`/login/${authProvider.name}`, authRouter);
40
40
  }
41
- router.use('/login', (0, drivers_1.createLocalAuthRouter)(constants_1.DEFAULT_AUTH_PROVIDER));
41
+ if (!env_1.default.AUTH_DISABLE_DEFAULT) {
42
+ router.use('/login', (0, drivers_1.createLocalAuthRouter)(constants_1.DEFAULT_AUTH_PROVIDER));
43
+ }
42
44
  router.post('/refresh', (0, async_handler_1.default)(async (req, res, next) => {
43
45
  var _a;
44
46
  const accountability = {
@@ -141,7 +143,10 @@ router.post('/password/reset', (0, async_handler_1.default)(async (req, res, nex
141
143
  return next();
142
144
  }), respond_1.respond);
143
145
  router.get('/', (0, async_handler_1.default)(async (req, res, next) => {
144
- res.locals.payload = { data: (0, get_auth_providers_1.getAuthProviders)() };
146
+ res.locals.payload = {
147
+ data: (0, get_auth_providers_1.getAuthProviders)(),
148
+ disableDefault: env_1.default.AUTH_DISABLE_DEFAULT,
149
+ };
145
150
  return next();
146
151
  }), respond_1.respond);
147
152
  exports.default = router;
@@ -33,7 +33,7 @@ router.get('/:type/index.js', (0, async_handler_1.default)(async (req, res) => {
33
33
  throw new exceptions_1.RouteNotFoundException(req.path);
34
34
  }
35
35
  res.setHeader('Content-Type', 'application/javascript; charset=UTF-8');
36
- res.setHeader('Cache-Control', 'no-cache');
36
+ res.setHeader('Cache-Control', 'no-store');
37
37
  res.setHeader('Vary', 'Origin, Cache-Control');
38
38
  res.end(extensionSource);
39
39
  }));
@@ -1,5 +1,6 @@
1
+ import { DateHelper } from '../types';
1
2
  import { Knex } from 'knex';
2
- export interface HelperFn {
3
+ export declare class DateHelperMSSQL extends DateHelper {
3
4
  year(table: string, column: string): Knex.Raw;
4
5
  month(table: string, column: string): Knex.Raw;
5
6
  week(table: string, column: string): Knex.Raw;
@@ -1,10 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.HelperMSSQL = void 0;
4
- class HelperMSSQL {
5
- constructor(knex) {
6
- this.knex = knex;
7
- }
3
+ exports.DateHelperMSSQL = void 0;
4
+ const types_1 = require("../types");
5
+ class DateHelperMSSQL extends types_1.DateHelper {
8
6
  year(table, column) {
9
7
  return this.knex.raw('DATEPART(year, ??.??)', [table, column]);
10
8
  }
@@ -30,4 +28,4 @@ class HelperMSSQL {
30
28
  return this.knex.raw('DATEPART(second, ??.??)', [table, column]);
31
29
  }
32
30
  }
33
- exports.HelperMSSQL = HelperMSSQL;
31
+ exports.DateHelperMSSQL = DateHelperMSSQL;
@@ -1,8 +1,6 @@
1
+ import { DateHelper } from '../types';
1
2
  import { Knex } from 'knex';
2
- import { HelperFn } from '../types';
3
- export declare class HelperMySQL implements HelperFn {
4
- private knex;
5
- constructor(knex: Knex);
3
+ export declare class DateHelperMySQL extends DateHelper {
6
4
  year(table: string, column: string): Knex.Raw;
7
5
  month(table: string, column: string): Knex.Raw;
8
6
  week(table: string, column: string): Knex.Raw;
@@ -1,10 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.HelperMySQL = void 0;
4
- class HelperMySQL {
5
- constructor(knex) {
6
- this.knex = knex;
7
- }
3
+ exports.DateHelperMySQL = void 0;
4
+ const types_1 = require("../types");
5
+ class DateHelperMySQL extends types_1.DateHelper {
8
6
  year(table, column) {
9
7
  return this.knex.raw('YEAR(??.??)', [table, column]);
10
8
  }
@@ -30,4 +28,4 @@ class HelperMySQL {
30
28
  return this.knex.raw('SECOND(??.??)', [table, column]);
31
29
  }
32
30
  }
33
- exports.HelperMySQL = HelperMySQL;
31
+ exports.DateHelperMySQL = DateHelperMySQL;
@@ -1,8 +1,6 @@
1
+ import { DateHelper } from '../types';
1
2
  import { Knex } from 'knex';
2
- import { HelperFn } from '../types';
3
- export declare class HelperMSSQL implements HelperFn {
4
- private knex;
5
- constructor(knex: Knex);
3
+ export declare class DateHelperOracle extends DateHelper {
6
4
  year(table: string, column: string): Knex.Raw;
7
5
  month(table: string, column: string): Knex.Raw;
8
6
  week(table: string, column: string): Knex.Raw;
@@ -1,10 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.HelperOracle = void 0;
4
- class HelperOracle {
5
- constructor(knex) {
6
- this.knex = knex;
7
- }
3
+ exports.DateHelperOracle = void 0;
4
+ const types_1 = require("../types");
5
+ class DateHelperOracle extends types_1.DateHelper {
8
6
  year(table, column) {
9
7
  return this.knex.raw("TO_CHAR(??.??, 'IYYY')", [table, column]);
10
8
  }
@@ -30,4 +28,4 @@ class HelperOracle {
30
28
  return this.knex.raw("TO_CHAR(??.??, 'SS')", [table, column]);
31
29
  }
32
30
  }
33
- exports.HelperOracle = HelperOracle;
31
+ exports.DateHelperOracle = DateHelperOracle;