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.
Files changed (96) hide show
  1. package/dist/app.js +16 -4
  2. package/dist/auth/auth.d.ts +4 -6
  3. package/dist/auth/auth.js +5 -9
  4. package/dist/auth/drivers/ldap.d.ts +3 -3
  5. package/dist/auth/drivers/ldap.js +2 -3
  6. package/dist/auth/drivers/local.d.ts +2 -2
  7. package/dist/auth/drivers/local.js +7 -13
  8. package/dist/auth/drivers/oauth2.d.ts +3 -3
  9. package/dist/auth/drivers/oauth2.js +4 -4
  10. package/dist/auth/drivers/openid.d.ts +3 -3
  11. package/dist/auth/drivers/openid.js +4 -4
  12. package/dist/cache.js +1 -3
  13. package/dist/cli/commands/bootstrap/index.js +3 -2
  14. package/dist/cli/commands/init/index.js +3 -7
  15. package/dist/cli/commands/schema/apply.js +1 -1
  16. package/dist/cli/utils/defaults.d.ts +11 -0
  17. package/dist/cli/utils/defaults.js +14 -0
  18. package/dist/constants.d.ts +8 -0
  19. package/dist/constants.js +16 -2
  20. package/dist/controllers/activity.js +2 -1
  21. package/dist/controllers/auth.js +5 -4
  22. package/dist/controllers/shares.d.ts +2 -0
  23. package/dist/controllers/shares.js +212 -0
  24. package/dist/controllers/users.js +21 -9
  25. package/dist/database/index.js +3 -0
  26. package/dist/database/migrations/20211211A-add-shares.d.ts +3 -0
  27. package/dist/database/migrations/20211211A-add-shares.js +38 -0
  28. package/dist/database/migrations/20211230A-add-project-descriptor.d.ts +3 -0
  29. package/dist/database/migrations/20211230A-add-project-descriptor.js +15 -0
  30. package/dist/database/run-ast.js +5 -5
  31. package/dist/database/system-data/app-access-permissions/app-access-permissions.yaml +0 -15
  32. package/dist/database/system-data/app-access-permissions/index.d.ts +1 -0
  33. package/dist/database/system-data/app-access-permissions/index.js +4 -2
  34. package/dist/database/system-data/app-access-permissions/schema-access-permissions.yaml +17 -0
  35. package/dist/database/system-data/collections/collections.yaml +3 -0
  36. package/dist/database/system-data/fields/_defaults.yaml +2 -0
  37. package/dist/database/system-data/fields/sessions.yaml +1 -1
  38. package/dist/database/system-data/fields/settings.yaml +20 -1
  39. package/dist/database/system-data/fields/shares.yaml +77 -0
  40. package/dist/database/system-data/fields/users.yaml +1 -1
  41. package/dist/database/system-data/relations/relations.yaml +15 -0
  42. package/dist/emitter.d.ts +3 -2
  43. package/dist/emitter.js +13 -6
  44. package/dist/env.js +3 -1
  45. package/dist/extensions.d.ts +1 -0
  46. package/dist/extensions.js +10 -4
  47. package/dist/middleware/authenticate.js +7 -16
  48. package/dist/middleware/check-ip.js +9 -6
  49. package/dist/middleware/rate-limiter.js +2 -1
  50. package/dist/middleware/respond.js +4 -1
  51. package/dist/services/activity.d.ts +2 -1
  52. package/dist/services/activity.js +2 -2
  53. package/dist/services/authentication.d.ts +2 -7
  54. package/dist/services/authentication.js +81 -41
  55. package/dist/services/authorization.js +3 -3
  56. package/dist/services/collections.d.ts +1 -2
  57. package/dist/services/collections.js +2 -2
  58. package/dist/services/files.d.ts +2 -2
  59. package/dist/services/files.js +14 -8
  60. package/dist/services/graphql.d.ts +1 -1
  61. package/dist/services/graphql.js +47 -6
  62. package/dist/services/index.d.ts +1 -0
  63. package/dist/services/index.js +1 -0
  64. package/dist/services/items.d.ts +1 -15
  65. package/dist/services/notifications.d.ts +2 -2
  66. package/dist/services/permissions.d.ts +2 -2
  67. package/dist/services/roles.d.ts +2 -2
  68. package/dist/services/server.js +1 -0
  69. package/dist/services/shares.d.ts +17 -0
  70. package/dist/services/shares.js +135 -0
  71. package/dist/services/specifications.js +1 -1
  72. package/dist/services/users.d.ts +2 -2
  73. package/dist/services/webhooks.d.ts +2 -2
  74. package/dist/types/ast.d.ts +3 -3
  75. package/dist/types/auth.d.ts +31 -0
  76. package/dist/types/extensions.d.ts +2 -0
  77. package/dist/types/items.d.ts +14 -0
  78. package/dist/utils/apply-query.d.ts +0 -38
  79. package/dist/utils/apply-query.js +66 -67
  80. package/dist/utils/apply-snapshot.js +69 -14
  81. package/dist/utils/get-ast-from-query.js +3 -3
  82. package/dist/utils/get-default-value.js +3 -1
  83. package/dist/utils/get-ip-from-req.d.ts +2 -0
  84. package/dist/utils/get-ip-from-req.js +24 -0
  85. package/dist/utils/get-permissions.js +15 -7
  86. package/dist/utils/get-relation-type.d.ts +1 -1
  87. package/dist/utils/get-relation-type.js +1 -1
  88. package/dist/utils/merge-permissions-for-share.d.ts +5 -0
  89. package/dist/utils/merge-permissions-for-share.js +116 -0
  90. package/dist/utils/merge-permissions.d.ts +13 -1
  91. package/dist/utils/merge-permissions.js +27 -19
  92. package/dist/utils/reduce-schema.d.ts +2 -2
  93. package/dist/utils/reduce-schema.js +7 -7
  94. package/dist/utils/user-name.js +3 -0
  95. package/example.env +1 -1
  96. package/package.json +15 -14
@@ -34,6 +34,7 @@ const revisions_1 = require("./revisions");
34
34
  const roles_1 = require("./roles");
35
35
  const server_1 = require("./server");
36
36
  const settings_1 = require("./settings");
37
+ const shares_1 = require("./shares");
37
38
  const specifications_1 = require("./specifications");
38
39
  const tfa_1 = require("./tfa");
39
40
  const users_1 = require("./users");
@@ -112,15 +113,23 @@ class GraphQLService {
112
113
  return formattedResult;
113
114
  }
114
115
  getSchema(type = 'schema') {
115
- var _a, _b, _c, _d;
116
+ var _a, _b, _c, _d, _e, _f, _g, _h;
116
117
  // eslint-disable-next-line @typescript-eslint/no-this-alias
117
118
  const self = this;
118
119
  const schemaComposer = new graphql_compose_1.SchemaComposer();
119
120
  const schema = {
120
- read: ((_a = this.accountability) === null || _a === void 0 ? void 0 : _a.admin) === true ? this.schema : (0, reduce_schema_1.reduceSchema)(this.schema, this.accountability, ['read']),
121
- create: ((_b = this.accountability) === null || _b === void 0 ? void 0 : _b.admin) === true ? this.schema : (0, reduce_schema_1.reduceSchema)(this.schema, this.accountability, ['create']),
122
- update: ((_c = this.accountability) === null || _c === void 0 ? void 0 : _c.admin) === true ? this.schema : (0, reduce_schema_1.reduceSchema)(this.schema, this.accountability, ['update']),
123
- delete: ((_d = this.accountability) === null || _d === void 0 ? void 0 : _d.admin) === true ? this.schema : (0, reduce_schema_1.reduceSchema)(this.schema, this.accountability, ['delete']),
121
+ read: ((_a = this.accountability) === null || _a === void 0 ? void 0 : _a.admin) === true
122
+ ? this.schema
123
+ : (0, reduce_schema_1.reduceSchema)(this.schema, ((_b = this.accountability) === null || _b === void 0 ? void 0 : _b.permissions) || null, ['read']),
124
+ create: ((_c = this.accountability) === null || _c === void 0 ? void 0 : _c.admin) === true
125
+ ? this.schema
126
+ : (0, reduce_schema_1.reduceSchema)(this.schema, ((_d = this.accountability) === null || _d === void 0 ? void 0 : _d.permissions) || null, ['create']),
127
+ update: ((_e = this.accountability) === null || _e === void 0 ? void 0 : _e.admin) === true
128
+ ? this.schema
129
+ : (0, reduce_schema_1.reduceSchema)(this.schema, ((_f = this.accountability) === null || _f === void 0 ? void 0 : _f.permissions) || null, ['update']),
130
+ delete: ((_g = this.accountability) === null || _g === void 0 ? void 0 : _g.admin) === true
131
+ ? this.schema
132
+ : (0, reduce_schema_1.reduceSchema)(this.schema, ((_h = this.accountability) === null || _h === void 0 ? void 0 : _h.permissions) || null, ['delete']),
124
133
  };
125
134
  const { ReadCollectionTypes } = getReadableTypes();
126
135
  const { CreateCollectionTypes, UpdateCollectionTypes, DeleteCollectionTypes } = getWritableTypes();
@@ -325,6 +334,8 @@ class GraphQLService {
325
334
  }
326
335
  for (const relation of schema[action].relations) {
327
336
  if (relation.related_collection) {
337
+ if (SYSTEM_DENY_LIST.includes(relation.related_collection))
338
+ continue;
328
339
  (_a = CollectionTypes[relation.collection]) === null || _a === void 0 ? void 0 : _a.addFields({
329
340
  [relation.field]: {
330
341
  type: CollectionTypes[relation.related_collection],
@@ -759,6 +770,8 @@ class GraphQLService {
759
770
  }
760
771
  for (const relation of schema.read.relations) {
761
772
  if (relation.related_collection) {
773
+ if (SYSTEM_DENY_LIST.includes(relation.related_collection))
774
+ continue;
762
775
  (_a = ReadableCollectionFilterTypes[relation.collection]) === null || _a === void 0 ? void 0 : _a.addFields({
763
776
  [relation.field]: ReadableCollectionFilterTypes[relation.related_collection],
764
777
  });
@@ -1268,6 +1281,8 @@ class GraphQLService {
1268
1281
  return new users_1.UsersService(opts);
1269
1282
  case 'directus_webhooks':
1270
1283
  return new webhooks_1.WebhooksService(opts);
1284
+ case 'directus_shares':
1285
+ return new shares_1.SharesService(opts);
1271
1286
  default:
1272
1287
  return new items_1.ItemsService(collection, opts);
1273
1288
  }
@@ -1292,7 +1307,7 @@ class GraphQLService {
1292
1307
  })).filter((s) => s);
1293
1308
  return result;
1294
1309
  }
1295
- injectSystemResolvers(schemaComposer, { CreateCollectionTypes, ReadCollectionTypes, DeleteCollectionTypes, }, schema) {
1310
+ injectSystemResolvers(schemaComposer, { CreateCollectionTypes, ReadCollectionTypes, UpdateCollectionTypes, DeleteCollectionTypes, }, schema) {
1296
1311
  var _a, _b, _c, _d, _e;
1297
1312
  const AuthTokens = schemaComposer.createObjectTC({
1298
1313
  name: 'auth_tokens',
@@ -2116,6 +2131,32 @@ class GraphQLService {
2116
2131
  },
2117
2132
  });
2118
2133
  }
2134
+ if ('directus_users' in schema.update.collections) {
2135
+ schemaComposer.Mutation.addFields({
2136
+ update_users_me: {
2137
+ type: ReadCollectionTypes['directus_users'],
2138
+ args: {
2139
+ data: (0, graphql_compose_1.toInputObjectType)(UpdateCollectionTypes['directus_users']),
2140
+ },
2141
+ resolve: async (_, args, __, info) => {
2142
+ var _a, _b, _c;
2143
+ if (!((_a = this.accountability) === null || _a === void 0 ? void 0 : _a.user))
2144
+ return null;
2145
+ const service = new users_1.UsersService({
2146
+ schema: this.schema,
2147
+ accountability: this.accountability,
2148
+ });
2149
+ await service.updateOne(this.accountability.user, args.data);
2150
+ if ('directus_users' in ReadCollectionTypes) {
2151
+ const selections = this.replaceFragmentsInSelections((_c = (_b = info.fieldNodes[0]) === null || _b === void 0 ? void 0 : _b.selectionSet) === null || _c === void 0 ? void 0 : _c.selections, info.fragments);
2152
+ const query = this.getQuery(args, selections || [], info.variableValues);
2153
+ return await service.readOne(this.accountability.user, query);
2154
+ }
2155
+ return true;
2156
+ },
2157
+ },
2158
+ });
2159
+ }
2119
2160
  if ('directus_activity' in schema.create.collections) {
2120
2161
  schemaComposer.Mutation.addFields({
2121
2162
  create_comment: {
@@ -26,3 +26,4 @@ export * from './tfa';
26
26
  export * from './users';
27
27
  export * from './utils';
28
28
  export * from './webhooks';
29
+ export * from './shares';
@@ -39,3 +39,4 @@ __exportStar(require("./tfa"), exports);
39
39
  __exportStar(require("./users"), exports);
40
40
  __exportStar(require("./utils"), exports);
41
41
  __exportStar(require("./webhooks"), exports);
42
+ __exportStar(require("./shares"), exports);
@@ -1,25 +1,11 @@
1
1
  import { Knex } from 'knex';
2
2
  import Keyv from 'keyv';
3
3
  import { Accountability, Query, PermissionsAction } from '@directus/shared/types';
4
- import { AbstractService, AbstractServiceOptions, Item as AnyItem, PrimaryKey, SchemaOverview } from '../types';
4
+ import { AbstractService, AbstractServiceOptions, Item as AnyItem, PrimaryKey, SchemaOverview, MutationOptions } from '../types';
5
5
  export declare type QueryOptions = {
6
6
  stripNonRequested?: boolean;
7
7
  permissionsAction?: PermissionsAction;
8
8
  };
9
- export declare type MutationOptions = {
10
- /**
11
- * Callback function that's fired whenever a revision is made in the mutation
12
- */
13
- onRevisionCreate?: (pk: PrimaryKey) => void;
14
- /**
15
- * Flag to disable the auto purging of the cache. Is ignored when CACHE_AUTO_PURGE isn't enabled.
16
- */
17
- autoPurgeCache?: false;
18
- /**
19
- * Allow disabling the emitting of hooks. Useful if a custom hook is fired (like files.upload)
20
- */
21
- emitEvents?: boolean;
22
- };
23
9
  export declare class ItemsService<Item extends AnyItem = AnyItem> implements AbstractService {
24
10
  collection: string;
25
11
  knex: Knex;
@@ -1,6 +1,6 @@
1
1
  import { UsersService, MailService } from '.';
2
- import { AbstractServiceOptions, PrimaryKey } from '../types';
3
- import { ItemsService, MutationOptions } from './items';
2
+ import { AbstractServiceOptions, PrimaryKey, MutationOptions } from '../types';
3
+ import { ItemsService } from './items';
4
4
  import { Notification } from '@directus/shared/types';
5
5
  export declare class NotificationsService extends ItemsService {
6
6
  usersService: UsersService;
@@ -1,5 +1,5 @@
1
- import { ItemsService, QueryOptions, MutationOptions } from '../services/items';
2
- import { AbstractServiceOptions, Item, PrimaryKey } from '../types';
1
+ import { ItemsService, QueryOptions } from '../services/items';
2
+ import { AbstractServiceOptions, Item, PrimaryKey, MutationOptions } from '../types';
3
3
  import { Query, PermissionsAction } from '@directus/shared/types';
4
4
  import Keyv from 'keyv';
5
5
  export declare class PermissionsService extends ItemsService {
@@ -1,6 +1,6 @@
1
- import { AbstractServiceOptions, PrimaryKey } from '../types';
1
+ import { AbstractServiceOptions, MutationOptions, PrimaryKey } from '../types';
2
2
  import { Query } from '@directus/shared/types';
3
- import { ItemsService, MutationOptions } from './items';
3
+ import { ItemsService } from './items';
4
4
  export declare class RolesService extends ItemsService {
5
5
  constructor(options: AbstractServiceOptions);
6
6
  private checkForOtherAdminRoles;
@@ -52,6 +52,7 @@ class ServerService {
52
52
  const projectInfo = await this.settingsService.readSingleton({
53
53
  fields: [
54
54
  'project_name',
55
+ 'project_descriptor',
55
56
  'project_logo',
56
57
  'project_color',
57
58
  'public_foreground',
@@ -0,0 +1,17 @@
1
+ import { AbstractServiceOptions, LoginResult, Item, PrimaryKey, MutationOptions } from '../types';
2
+ import { ItemsService } from './items';
3
+ import { AuthorizationService } from './authorization';
4
+ export declare class SharesService extends ItemsService {
5
+ authorizationService: AuthorizationService;
6
+ constructor(options: AbstractServiceOptions);
7
+ createOne(data: Partial<Item>, opts?: MutationOptions): Promise<PrimaryKey>;
8
+ login(payload: Record<string, any>): Promise<LoginResult>;
9
+ /**
10
+ * Send a link to the given share ID to the given email(s). Note: you can only send a link to a share
11
+ * if you have read access to that particular share
12
+ */
13
+ invite(payload: {
14
+ emails: string[];
15
+ share: PrimaryKey;
16
+ }): Promise<void>;
17
+ }
@@ -0,0 +1,135 @@
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
+ exports.SharesService = void 0;
7
+ const items_1 = require("./items");
8
+ const argon2_1 = __importDefault(require("argon2"));
9
+ const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
10
+ const ms_1 = __importDefault(require("ms"));
11
+ const exceptions_1 = require("../exceptions");
12
+ const env_1 = __importDefault(require("../env"));
13
+ const nanoid_1 = require("nanoid");
14
+ const authorization_1 = require("./authorization");
15
+ const users_1 = require("./users");
16
+ const mail_1 = require("./mail");
17
+ const user_name_1 = require("../utils/user-name");
18
+ const md_1 = require("../utils/md");
19
+ class SharesService extends items_1.ItemsService {
20
+ constructor(options) {
21
+ super('directus_shares', options);
22
+ this.authorizationService = new authorization_1.AuthorizationService({
23
+ accountability: this.accountability,
24
+ knex: this.knex,
25
+ schema: this.schema,
26
+ });
27
+ }
28
+ async createOne(data, opts) {
29
+ await this.authorizationService.checkAccess('share', data.collection, data.item);
30
+ return super.createOne(data, opts);
31
+ }
32
+ async login(payload) {
33
+ var _a, _b;
34
+ const record = await this.knex
35
+ .select({
36
+ share_id: 'id',
37
+ share_role: 'role',
38
+ share_item: 'item',
39
+ share_collection: 'collection',
40
+ share_start: 'date_start',
41
+ share_end: 'date_end',
42
+ share_times_used: 'times_used',
43
+ share_max_uses: 'max_uses',
44
+ share_password: 'password',
45
+ })
46
+ .from('directus_shares')
47
+ .where('id', payload.share)
48
+ .andWhere((subQuery) => {
49
+ subQuery.whereNull('date_end').orWhere('date_end', '>=', new Date());
50
+ })
51
+ .andWhere((subQuery) => {
52
+ subQuery.whereNull('date_start').orWhere('date_start', '<=', new Date());
53
+ })
54
+ .andWhere((subQuery) => {
55
+ subQuery.whereNull('max_uses').orWhere('max_uses', '>=', this.knex.ref('times_used'));
56
+ })
57
+ .first();
58
+ if (!record) {
59
+ throw new exceptions_1.InvalidCredentialsException();
60
+ }
61
+ if (record.share_password && !(await argon2_1.default.verify(record.share_password, payload.password))) {
62
+ throw new exceptions_1.InvalidCredentialsException();
63
+ }
64
+ await this.knex('directus_shares')
65
+ .update({ times_used: record.share_times_used + 1 })
66
+ .where('id', record.share_id);
67
+ const tokenPayload = {
68
+ app_access: false,
69
+ admin_access: false,
70
+ role: record.share_role,
71
+ share: record.share_id,
72
+ share_scope: {
73
+ item: record.share_item,
74
+ collection: record.share_collection,
75
+ },
76
+ };
77
+ const accessToken = jsonwebtoken_1.default.sign(tokenPayload, env_1.default.SECRET, {
78
+ expiresIn: env_1.default.ACCESS_TOKEN_TTL,
79
+ issuer: 'directus',
80
+ });
81
+ const refreshToken = (0, nanoid_1.nanoid)(64);
82
+ const refreshTokenExpiration = new Date(Date.now() + (0, ms_1.default)(env_1.default.REFRESH_TOKEN_TTL));
83
+ await this.knex('directus_sessions').insert({
84
+ token: refreshToken,
85
+ expires: refreshTokenExpiration,
86
+ ip: (_a = this.accountability) === null || _a === void 0 ? void 0 : _a.ip,
87
+ user_agent: (_b = this.accountability) === null || _b === void 0 ? void 0 : _b.userAgent,
88
+ share: record.share_id,
89
+ });
90
+ await this.knex('directus_sessions').delete().where('expires', '<', new Date());
91
+ return {
92
+ accessToken,
93
+ refreshToken,
94
+ expires: (0, ms_1.default)(env_1.default.ACCESS_TOKEN_TTL),
95
+ };
96
+ }
97
+ /**
98
+ * Send a link to the given share ID to the given email(s). Note: you can only send a link to a share
99
+ * if you have read access to that particular share
100
+ */
101
+ async invite(payload) {
102
+ var _a;
103
+ if (!((_a = this.accountability) === null || _a === void 0 ? void 0 : _a.user))
104
+ throw new exceptions_1.ForbiddenException();
105
+ const share = await this.readOne(payload.share, { fields: ['collection'] });
106
+ const usersService = new users_1.UsersService({
107
+ knex: this.knex,
108
+ schema: this.schema,
109
+ });
110
+ const mailService = new mail_1.MailService({ schema: this.schema, accountability: this.accountability });
111
+ const userInfo = await usersService.readOne(this.accountability.user, {
112
+ fields: ['first_name', 'last_name', 'email', 'id'],
113
+ });
114
+ const message = `
115
+ Hello!
116
+
117
+ ${(0, user_name_1.userName)(userInfo)} has invited you to view an item in ${share.collection}.
118
+
119
+ [Open](${env_1.default.PUBLIC_URL}/admin/shared/${payload.share})
120
+ `;
121
+ for (const email of payload.emails) {
122
+ await mailService.send({
123
+ template: {
124
+ name: 'base',
125
+ data: {
126
+ html: (0, md_1.md)(message),
127
+ },
128
+ },
129
+ to: email,
130
+ subject: `${(0, user_name_1.userName)(userInfo)} has shared an item with you`,
131
+ });
132
+ }
133
+ }
134
+ }
135
+ exports.SharesService = SharesService;
@@ -442,7 +442,7 @@ class OASSpecsService {
442
442
  ],
443
443
  };
444
444
  }
445
- else if (relationType === 'm2a') {
445
+ else if (relationType === 'a2o') {
446
446
  const relatedTags = tags.filter((tag) => relation.meta.one_allowed_collections.includes(tag['x-collection']));
447
447
  propertyObject.type = 'array';
448
448
  propertyObject.items = {
@@ -1,8 +1,8 @@
1
1
  import { Knex } from 'knex';
2
- import { AbstractServiceOptions, Item, PrimaryKey, SchemaOverview } from '../types';
2
+ import { AbstractServiceOptions, Item, PrimaryKey, SchemaOverview, MutationOptions } from '../types';
3
3
  import { Query } from '@directus/shared/types';
4
4
  import { Accountability } from '@directus/shared/types';
5
- import { ItemsService, MutationOptions } from './items';
5
+ import { ItemsService } from './items';
6
6
  export declare class UsersService extends ItemsService {
7
7
  knex: Knex;
8
8
  accountability: Accountability | null;
@@ -1,5 +1,5 @@
1
- import { AbstractServiceOptions, Item, PrimaryKey, Webhook } from '../types';
2
- import { ItemsService, MutationOptions } from './items';
1
+ import { AbstractServiceOptions, Item, PrimaryKey, Webhook, MutationOptions } from '../types';
2
+ import { ItemsService } from './items';
3
3
  export declare class WebhooksService extends ItemsService<Webhook> {
4
4
  constructor(options: AbstractServiceOptions);
5
5
  createOne(data: Partial<Item>, opts?: MutationOptions): Promise<PrimaryKey>;
@@ -10,8 +10,8 @@ export declare type M2ONode = {
10
10
  parentKey: string;
11
11
  relatedKey: string;
12
12
  };
13
- export declare type M2ANode = {
14
- type: 'm2a';
13
+ export declare type A2MNode = {
14
+ type: 'a2o';
15
15
  names: string[];
16
16
  children: {
17
17
  [collection: string]: (NestedCollectionNode | FieldNode)[];
@@ -36,7 +36,7 @@ export declare type O2MNode = {
36
36
  parentKey: string;
37
37
  relatedKey: string;
38
38
  };
39
- export declare type NestedCollectionNode = M2ONode | O2MNode | M2ANode;
39
+ export declare type NestedCollectionNode = M2ONode | O2MNode | A2MNode;
40
40
  export declare type FieldNode = {
41
41
  type: 'field';
42
42
  name: string;
@@ -15,11 +15,42 @@ export interface User {
15
15
  provider: string;
16
16
  external_identifier: string | null;
17
17
  auth_data: string | Record<string, unknown> | null;
18
+ app_access: boolean;
19
+ admin_access: boolean;
18
20
  }
19
21
  export declare type AuthData = Record<string, any> | null;
20
22
  export interface Session {
21
23
  token: string;
22
24
  expires: Date;
23
25
  data: string | Record<string, unknown> | null;
26
+ share: string;
24
27
  }
25
28
  export declare type SessionData = Record<string, any> | null;
29
+ export declare type DirectusTokenPayload = {
30
+ id?: string;
31
+ role: string | null;
32
+ app_access: boolean | number;
33
+ admin_access: boolean | number;
34
+ share?: string;
35
+ share_scope?: {
36
+ collection: string;
37
+ item: string;
38
+ };
39
+ };
40
+ export declare type ShareData = {
41
+ share_id: string;
42
+ share_role: string;
43
+ share_item: string;
44
+ share_collection: string;
45
+ share_start: Date;
46
+ share_end: Date;
47
+ share_times_used: number;
48
+ share_max_uses?: number;
49
+ share_password?: string;
50
+ };
51
+ export declare type LoginResult = {
52
+ accessToken: any;
53
+ refreshToken: any;
54
+ expires: any;
55
+ id?: any;
56
+ };
@@ -5,6 +5,7 @@ import { Logger } from 'pino';
5
5
  import env from '../env';
6
6
  import * as exceptions from '../exceptions';
7
7
  import * as services from '../services';
8
+ import { Emitter } from '../emitter';
8
9
  import { getSchema } from '../utils/get-schema';
9
10
  import { SchemaOverview } from './schema';
10
11
  export declare type ExtensionContext = {
@@ -12,6 +13,7 @@ export declare type ExtensionContext = {
12
13
  exceptions: typeof exceptions;
13
14
  database: Knex;
14
15
  env: typeof env;
16
+ emitter: Emitter;
15
17
  logger: Logger;
16
18
  getSchema: typeof getSchema;
17
19
  };
@@ -13,3 +13,17 @@ export declare type Alterations = {
13
13
  }[];
14
14
  delete: (number | string)[];
15
15
  };
16
+ export declare type MutationOptions = {
17
+ /**
18
+ * Callback function that's fired whenever a revision is made in the mutation
19
+ */
20
+ onRevisionCreate?: (pk: PrimaryKey) => void;
21
+ /**
22
+ * Flag to disable the auto purging of the cache. Is ignored when CACHE_AUTO_PURGE isn't enabled.
23
+ */
24
+ autoPurgeCache?: false;
25
+ /**
26
+ * Allow disabling the emitting of hooks. Useful if a custom hook is fired (like files.upload)
27
+ */
28
+ emitEvents?: boolean;
29
+ };
@@ -5,44 +5,6 @@ import { Aggregate, Filter, Query } from '@directus/shared/types';
5
5
  * Apply the Query to a given Knex query builder instance
6
6
  */
7
7
  export default function applyQuery(knex: Knex, collection: string, dbQuery: Knex.QueryBuilder, query: Query, schema: SchemaOverview, subQuery?: boolean): Knex.QueryBuilder;
8
- /**
9
- * Apply a given filter object to the Knex QueryBuilder instance.
10
- *
11
- * Relational nested filters, like the following example:
12
- *
13
- * ```json
14
- * // Fetch pages that have articles written by Rijk
15
- *
16
- * {
17
- * "articles": {
18
- * "author": {
19
- * "name": {
20
- * "_eq": "Rijk"
21
- * }
22
- * }
23
- * }
24
- * }
25
- * ```
26
- *
27
- * are handled by joining the nested tables, and using a where statement on the top level on the
28
- * nested field through the join. This allows us to filter the top level items based on nested data.
29
- * The where on the root is done with a subquery to prevent duplicates, any nested joins are done
30
- * with aliases to prevent naming conflicts.
31
- *
32
- * The output SQL for the above would look something like:
33
- *
34
- * ```sql
35
- * SELECT *
36
- * FROM pages
37
- * WHERE
38
- * pages.id in (
39
- * SELECT articles.page_id AS page_id
40
- * FROM articles
41
- * LEFT JOIN authors AS xviqp ON articles.author = xviqp.id
42
- * WHERE xviqp.name = 'Rijk'
43
- * )
44
- * ```
45
- */
46
8
  export declare function applyFilter(knex: Knex, schema: SchemaOverview, rootQuery: Knex.QueryBuilder, rootFilter: Filter, collection: string, subQuery?: boolean): Knex.QueryBuilder<any, any>;
47
9
  export declare function applySearch(schema: SchemaOverview, dbQuery: Knex.QueryBuilder, searchQuery: string, collection: string): Promise<void>;
48
10
  export declare function applyAggregate(dbQuery: Knex.QueryBuilder, aggregate: Aggregate, collection: string): void;