directus 9.3.0 → 9.4.0
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 +5 -3
- 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 +0 -2
- package/dist/auth/drivers/local.d.ts +2 -2
- package/dist/auth/drivers/local.js +5 -12
- package/dist/auth/drivers/oauth2.d.ts +3 -3
- package/dist/auth/drivers/oauth2.js +2 -3
- package/dist/auth/drivers/openid.d.ts +3 -3
- package/dist/auth/drivers/openid.js +2 -3
- package/dist/cli/commands/schema/apply.js +1 -1
- package/dist/constants.d.ts +8 -0
- package/dist/constants.js +16 -2
- 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/migrations/20211211A-add-shares.d.ts +3 -0
- package/dist/database/migrations/20211211A-add-shares.js +37 -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/sessions.yaml +1 -1
- package/dist/database/system-data/fields/shares.yaml +73 -0
- package/dist/database/system-data/fields/users.yaml +1 -1
- package/dist/database/system-data/relations/relations.yaml +15 -0
- package/dist/extensions.js +5 -3
- package/dist/middleware/authenticate.js +5 -15
- package/dist/middleware/check-ip.js +9 -6
- 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/graphql.js +16 -5
- 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/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/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/get-ast-from-query.js +3 -3
- 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/package.json +12 -12
package/dist/app.js
CHANGED
|
@@ -51,6 +51,7 @@ const settings_1 = __importDefault(require("./controllers/settings"));
|
|
|
51
51
|
const users_1 = __importDefault(require("./controllers/users"));
|
|
52
52
|
const utils_1 = __importDefault(require("./controllers/utils"));
|
|
53
53
|
const webhooks_1 = __importDefault(require("./controllers/webhooks"));
|
|
54
|
+
const shares_1 = __importDefault(require("./controllers/shares"));
|
|
54
55
|
const database_1 = require("./database");
|
|
55
56
|
const emitter_1 = __importDefault(require("./emitter"));
|
|
56
57
|
const env_1 = __importDefault(require("./env"));
|
|
@@ -112,14 +113,14 @@ async function createApp() {
|
|
|
112
113
|
});
|
|
113
114
|
app.use((0, cookie_parser_1.default)());
|
|
114
115
|
app.use(extract_token_1.default);
|
|
115
|
-
app.use((
|
|
116
|
+
app.use((_req, res, next) => {
|
|
116
117
|
res.setHeader('X-Powered-By', 'Directus');
|
|
117
118
|
next();
|
|
118
119
|
});
|
|
119
120
|
if (env_1.default.CORS_ENABLED === true) {
|
|
120
121
|
app.use(cors_1.default);
|
|
121
122
|
}
|
|
122
|
-
app.get('/', (
|
|
123
|
+
app.get('/', (_req, res, next) => {
|
|
123
124
|
if (env_1.default.ROOT_REDIRECT) {
|
|
124
125
|
res.redirect(env_1.default.ROOT_REDIRECT);
|
|
125
126
|
}
|
|
@@ -133,7 +134,7 @@ async function createApp() {
|
|
|
133
134
|
// Set the App's base path according to the APIs public URL
|
|
134
135
|
const html = await fs_extra_1.default.readFile(adminPath, 'utf8');
|
|
135
136
|
const htmlWithBase = html.replace(/<base \/>/, `<base href="${adminUrl.toString({ rootRelative: true })}/" />`);
|
|
136
|
-
const noCacheIndexHtmlHandler = (
|
|
137
|
+
const noCacheIndexHtmlHandler = (_req, res) => {
|
|
137
138
|
res.setHeader('Cache-Control', 'no-cache');
|
|
138
139
|
res.send(htmlWithBase);
|
|
139
140
|
};
|
|
@@ -173,6 +174,7 @@ async function createApp() {
|
|
|
173
174
|
app.use('/roles', roles_1.default);
|
|
174
175
|
app.use('/server', server_1.default);
|
|
175
176
|
app.use('/settings', settings_1.default);
|
|
177
|
+
app.use('/shares', shares_1.default);
|
|
176
178
|
app.use('/users', users_1.default);
|
|
177
179
|
app.use('/utils', utils_1.default);
|
|
178
180
|
app.use('/webhooks', webhooks_1.default);
|
package/dist/auth/auth.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Knex } from 'knex';
|
|
2
|
-
import { AuthDriverOptions, SchemaOverview, User
|
|
2
|
+
import { AuthDriverOptions, SchemaOverview, User } from '../types';
|
|
3
3
|
export declare abstract class AuthDriver {
|
|
4
4
|
knex: Knex;
|
|
5
5
|
schema: SchemaOverview;
|
|
@@ -28,20 +28,18 @@ export declare abstract class AuthDriver {
|
|
|
28
28
|
* @throws InvalidCredentialsException
|
|
29
29
|
* @returns Data to be stored with the session
|
|
30
30
|
*/
|
|
31
|
-
login(_user: User, _payload: Record<string, any>): Promise<
|
|
31
|
+
login(_user: User, _payload: Record<string, any>): Promise<void>;
|
|
32
32
|
/**
|
|
33
33
|
* Handle user session refresh
|
|
34
34
|
*
|
|
35
35
|
* @param _user User information
|
|
36
|
-
* @param _sessionData Session data
|
|
37
36
|
* @throws InvalidCredentialsException
|
|
38
37
|
*/
|
|
39
|
-
refresh(_user: User
|
|
38
|
+
refresh(_user: User): Promise<void>;
|
|
40
39
|
/**
|
|
41
40
|
* Handle user session termination
|
|
42
41
|
*
|
|
43
42
|
* @param _user User information
|
|
44
|
-
* @param _sessionData Session data
|
|
45
43
|
*/
|
|
46
|
-
logout(_user: User
|
|
44
|
+
logout(_user: User): Promise<void>;
|
|
47
45
|
}
|
package/dist/auth/auth.js
CHANGED
|
@@ -15,28 +15,24 @@ class AuthDriver {
|
|
|
15
15
|
* @returns Data to be stored with the session
|
|
16
16
|
*/
|
|
17
17
|
async login(_user, _payload) {
|
|
18
|
-
|
|
19
|
-
return null;
|
|
18
|
+
return;
|
|
20
19
|
}
|
|
21
20
|
/**
|
|
22
21
|
* Handle user session refresh
|
|
23
22
|
*
|
|
24
23
|
* @param _user User information
|
|
25
|
-
* @param _sessionData Session data
|
|
26
24
|
* @throws InvalidCredentialsException
|
|
27
25
|
*/
|
|
28
|
-
async refresh(_user
|
|
29
|
-
|
|
30
|
-
return sessionData;
|
|
26
|
+
async refresh(_user) {
|
|
27
|
+
return;
|
|
31
28
|
}
|
|
32
29
|
/**
|
|
33
30
|
* Handle user session termination
|
|
34
31
|
*
|
|
35
32
|
* @param _user User information
|
|
36
|
-
* @param _sessionData Session data
|
|
37
33
|
*/
|
|
38
|
-
async logout(_user
|
|
39
|
-
|
|
34
|
+
async logout(_user) {
|
|
35
|
+
return;
|
|
40
36
|
}
|
|
41
37
|
}
|
|
42
38
|
exports.AuthDriver = AuthDriver;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Router } from 'express';
|
|
2
2
|
import { Client } from 'ldapjs';
|
|
3
3
|
import { AuthDriver } from '../auth';
|
|
4
|
-
import { AuthDriverOptions, User
|
|
4
|
+
import { AuthDriverOptions, User } from '../../types';
|
|
5
5
|
import { UsersService } from '../../services';
|
|
6
6
|
export declare class LDAPAuthDriver extends AuthDriver {
|
|
7
7
|
bindClient: Client;
|
|
@@ -15,7 +15,7 @@ export declare class LDAPAuthDriver extends AuthDriver {
|
|
|
15
15
|
private fetchUserId;
|
|
16
16
|
getUserID(payload: Record<string, any>): Promise<string>;
|
|
17
17
|
verify(user: User, password?: string): Promise<void>;
|
|
18
|
-
login(user: User, payload: Record<string, any>): Promise<
|
|
19
|
-
refresh(user: User): Promise<
|
|
18
|
+
login(user: User, payload: Record<string, any>): Promise<void>;
|
|
19
|
+
refresh(user: User): Promise<void>;
|
|
20
20
|
}
|
|
21
21
|
export declare function createLDAPAuthRouter(provider: string): Router;
|
|
@@ -260,7 +260,6 @@ class LDAPAuthDriver extends auth_1.AuthDriver {
|
|
|
260
260
|
}
|
|
261
261
|
async login(user, payload) {
|
|
262
262
|
await this.verify(user, payload.password);
|
|
263
|
-
return null;
|
|
264
263
|
}
|
|
265
264
|
async refresh(user) {
|
|
266
265
|
await this.validateBindClient();
|
|
@@ -268,7 +267,6 @@ class LDAPAuthDriver extends auth_1.AuthDriver {
|
|
|
268
267
|
if ((userInfo === null || userInfo === void 0 ? void 0 : userInfo.userAccountControl) && userInfo.userAccountControl & INVALID_ACCOUNT_FLAGS) {
|
|
269
268
|
throw new exceptions_1.InvalidCredentialsException();
|
|
270
269
|
}
|
|
271
|
-
return null;
|
|
272
270
|
}
|
|
273
271
|
}
|
|
274
272
|
exports.LDAPAuthDriver = LDAPAuthDriver;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Router } from 'express';
|
|
2
2
|
import { AuthDriver } from '../auth';
|
|
3
|
-
import { User
|
|
3
|
+
import { User } from '../../types';
|
|
4
4
|
export declare class LocalAuthDriver extends AuthDriver {
|
|
5
5
|
getUserID(payload: Record<string, any>): Promise<string>;
|
|
6
6
|
verify(user: User, password?: string): Promise<void>;
|
|
7
|
-
login(user: User, payload: Record<string, any>): Promise<
|
|
7
|
+
login(user: User, payload: Record<string, any>): Promise<void>;
|
|
8
8
|
}
|
|
9
9
|
export declare function createLocalAuthRouter(provider: string): Router;
|
|
@@ -6,7 +6,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.createLocalAuthRouter = exports.LocalAuthDriver = void 0;
|
|
7
7
|
const express_1 = require("express");
|
|
8
8
|
const argon2_1 = __importDefault(require("argon2"));
|
|
9
|
-
const ms_1 = __importDefault(require("ms"));
|
|
10
9
|
const joi_1 = __importDefault(require("joi"));
|
|
11
10
|
const auth_1 = require("../auth");
|
|
12
11
|
const exceptions_1 = require("../../exceptions");
|
|
@@ -14,6 +13,7 @@ const services_1 = require("../../services");
|
|
|
14
13
|
const async_handler_1 = __importDefault(require("../../utils/async-handler"));
|
|
15
14
|
const env_1 = __importDefault(require("../../env"));
|
|
16
15
|
const respond_1 = require("../../middleware/respond");
|
|
16
|
+
const constants_1 = require("../../constants");
|
|
17
17
|
class LocalAuthDriver extends auth_1.AuthDriver {
|
|
18
18
|
async getUserID(payload) {
|
|
19
19
|
if (!payload.email) {
|
|
@@ -36,20 +36,19 @@ class LocalAuthDriver extends auth_1.AuthDriver {
|
|
|
36
36
|
}
|
|
37
37
|
async login(user, payload) {
|
|
38
38
|
await this.verify(user, payload.password);
|
|
39
|
-
return null;
|
|
40
39
|
}
|
|
41
40
|
}
|
|
42
41
|
exports.LocalAuthDriver = LocalAuthDriver;
|
|
43
42
|
function createLocalAuthRouter(provider) {
|
|
44
43
|
const router = (0, express_1.Router)();
|
|
45
|
-
const
|
|
44
|
+
const userLoginSchema = joi_1.default.object({
|
|
46
45
|
email: joi_1.default.string().email().required(),
|
|
47
46
|
password: joi_1.default.string().required(),
|
|
48
47
|
mode: joi_1.default.string().valid('cookie', 'json'),
|
|
49
48
|
otp: joi_1.default.string(),
|
|
50
49
|
}).unknown();
|
|
51
50
|
router.post('/', (0, async_handler_1.default)(async (req, res, next) => {
|
|
52
|
-
var _a
|
|
51
|
+
var _a;
|
|
53
52
|
const accountability = {
|
|
54
53
|
ip: req.ip,
|
|
55
54
|
userAgent: req.get('user-agent'),
|
|
@@ -59,7 +58,7 @@ function createLocalAuthRouter(provider) {
|
|
|
59
58
|
accountability: accountability,
|
|
60
59
|
schema: req.schema,
|
|
61
60
|
});
|
|
62
|
-
const { error } =
|
|
61
|
+
const { error } = userLoginSchema.validate(req.body);
|
|
63
62
|
if (error) {
|
|
64
63
|
throw new exceptions_1.InvalidPayloadException(error.message);
|
|
65
64
|
}
|
|
@@ -72,13 +71,7 @@ function createLocalAuthRouter(provider) {
|
|
|
72
71
|
payload.data.refresh_token = refreshToken;
|
|
73
72
|
}
|
|
74
73
|
if (mode === 'cookie') {
|
|
75
|
-
res.cookie(env_1.default.REFRESH_TOKEN_COOKIE_NAME, refreshToken,
|
|
76
|
-
httpOnly: true,
|
|
77
|
-
domain: env_1.default.REFRESH_TOKEN_COOKIE_DOMAIN,
|
|
78
|
-
maxAge: (0, ms_1.default)(env_1.default.REFRESH_TOKEN_TTL),
|
|
79
|
-
secure: (_b = env_1.default.REFRESH_TOKEN_COOKIE_SECURE) !== null && _b !== void 0 ? _b : false,
|
|
80
|
-
sameSite: env_1.default.REFRESH_TOKEN_COOKIE_SAME_SITE || 'strict',
|
|
81
|
-
});
|
|
74
|
+
res.cookie(env_1.default.REFRESH_TOKEN_COOKIE_NAME, refreshToken, constants_1.COOKIE_OPTIONS);
|
|
82
75
|
}
|
|
83
76
|
res.locals.payload = payload;
|
|
84
77
|
return next();
|
|
@@ -2,7 +2,7 @@ import { Router } from 'express';
|
|
|
2
2
|
import { Client } from 'openid-client';
|
|
3
3
|
import { LocalAuthDriver } from './local';
|
|
4
4
|
import { UsersService } from '../../services';
|
|
5
|
-
import { AuthDriverOptions, User
|
|
5
|
+
import { AuthDriverOptions, User } from '../../types';
|
|
6
6
|
export declare class OAuth2AuthDriver extends LocalAuthDriver {
|
|
7
7
|
client: Client;
|
|
8
8
|
redirectUrl: string;
|
|
@@ -13,7 +13,7 @@ export declare class OAuth2AuthDriver extends LocalAuthDriver {
|
|
|
13
13
|
generateAuthUrl(codeVerifier: string, prompt?: boolean): string;
|
|
14
14
|
private fetchUserId;
|
|
15
15
|
getUserID(payload: Record<string, any>): Promise<string>;
|
|
16
|
-
login(user: User): Promise<
|
|
17
|
-
refresh(user: User
|
|
16
|
+
login(user: User): Promise<void>;
|
|
17
|
+
refresh(user: User): Promise<void>;
|
|
18
18
|
}
|
|
19
19
|
export declare function createOAuth2AuthRouter(providerName: string): Router;
|
|
@@ -130,9 +130,9 @@ class OAuth2AuthDriver extends local_1.LocalAuthDriver {
|
|
|
130
130
|
return (await this.fetchUserId(identifier));
|
|
131
131
|
}
|
|
132
132
|
async login(user) {
|
|
133
|
-
return this.refresh(user
|
|
133
|
+
return this.refresh(user);
|
|
134
134
|
}
|
|
135
|
-
async refresh(user
|
|
135
|
+
async refresh(user) {
|
|
136
136
|
let authData = user.auth_data;
|
|
137
137
|
if (typeof authData === 'string') {
|
|
138
138
|
try {
|
|
@@ -156,7 +156,6 @@ class OAuth2AuthDriver extends local_1.LocalAuthDriver {
|
|
|
156
156
|
throw handleError(e);
|
|
157
157
|
}
|
|
158
158
|
}
|
|
159
|
-
return sessionData;
|
|
160
159
|
}
|
|
161
160
|
}
|
|
162
161
|
exports.OAuth2AuthDriver = OAuth2AuthDriver;
|
|
@@ -2,7 +2,7 @@ import { Router } from 'express';
|
|
|
2
2
|
import { Client } from 'openid-client';
|
|
3
3
|
import { LocalAuthDriver } from './local';
|
|
4
4
|
import { UsersService } from '../../services';
|
|
5
|
-
import { AuthDriverOptions, User
|
|
5
|
+
import { AuthDriverOptions, User } from '../../types';
|
|
6
6
|
export declare class OpenIDAuthDriver extends LocalAuthDriver {
|
|
7
7
|
client: Promise<Client>;
|
|
8
8
|
redirectUrl: string;
|
|
@@ -13,7 +13,7 @@ export declare class OpenIDAuthDriver extends LocalAuthDriver {
|
|
|
13
13
|
generateAuthUrl(codeVerifier: string, prompt?: boolean): Promise<string>;
|
|
14
14
|
private fetchUserId;
|
|
15
15
|
getUserID(payload: Record<string, any>): Promise<string>;
|
|
16
|
-
login(user: User): Promise<
|
|
17
|
-
refresh(user: User
|
|
16
|
+
login(user: User): Promise<void>;
|
|
17
|
+
refresh(user: User): Promise<void>;
|
|
18
18
|
}
|
|
19
19
|
export declare function createOpenIDAuthRouter(providerName: string): Router;
|
|
@@ -135,9 +135,9 @@ class OpenIDAuthDriver extends local_1.LocalAuthDriver {
|
|
|
135
135
|
return (await this.fetchUserId(identifier));
|
|
136
136
|
}
|
|
137
137
|
async login(user) {
|
|
138
|
-
return this.refresh(user
|
|
138
|
+
return this.refresh(user);
|
|
139
139
|
}
|
|
140
|
-
async refresh(user
|
|
140
|
+
async refresh(user) {
|
|
141
141
|
let authData = user.auth_data;
|
|
142
142
|
if (typeof authData === 'string') {
|
|
143
143
|
try {
|
|
@@ -162,7 +162,6 @@ class OpenIDAuthDriver extends local_1.LocalAuthDriver {
|
|
|
162
162
|
throw handleError(e);
|
|
163
163
|
}
|
|
164
164
|
}
|
|
165
|
-
return sessionData;
|
|
166
165
|
}
|
|
167
166
|
}
|
|
168
167
|
exports.OpenIDAuthDriver = OpenIDAuthDriver;
|
|
@@ -135,7 +135,7 @@ async function apply(snapshotPath, options) {
|
|
|
135
135
|
else {
|
|
136
136
|
continue;
|
|
137
137
|
}
|
|
138
|
-
// Related collection doesn't exist for
|
|
138
|
+
// Related collection doesn't exist for a2o relationship types
|
|
139
139
|
if (related_collection) {
|
|
140
140
|
message += `-> ${related_collection}`;
|
|
141
141
|
}
|
package/dist/constants.d.ts
CHANGED
|
@@ -5,3 +5,11 @@ export declare const FILTER_VARIABLES: string[];
|
|
|
5
5
|
export declare const ALIAS_TYPES: string[];
|
|
6
6
|
export declare const DEFAULT_AUTH_PROVIDER = "default";
|
|
7
7
|
export declare const COLUMN_TRANSFORMS: string[];
|
|
8
|
+
export declare const UUID_REGEX = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}";
|
|
9
|
+
export declare const COOKIE_OPTIONS: {
|
|
10
|
+
httpOnly: boolean;
|
|
11
|
+
domain: any;
|
|
12
|
+
maxAge: number;
|
|
13
|
+
secure: any;
|
|
14
|
+
sameSite: "lax" | "strict" | "none";
|
|
15
|
+
};
|
package/dist/constants.js
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
var _a;
|
|
2
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.COLUMN_TRANSFORMS = exports.DEFAULT_AUTH_PROVIDER = exports.ALIAS_TYPES = exports.FILTER_VARIABLES = exports.ASSET_TRANSFORM_QUERY_KEYS = exports.SYSTEM_ASSET_ALLOW_LIST = void 0;
|
|
7
|
+
exports.COOKIE_OPTIONS = exports.UUID_REGEX = exports.COLUMN_TRANSFORMS = exports.DEFAULT_AUTH_PROVIDER = exports.ALIAS_TYPES = exports.FILTER_VARIABLES = exports.ASSET_TRANSFORM_QUERY_KEYS = exports.SYSTEM_ASSET_ALLOW_LIST = void 0;
|
|
8
|
+
const env_1 = __importDefault(require("./env"));
|
|
9
|
+
const ms_1 = __importDefault(require("ms"));
|
|
4
10
|
exports.SYSTEM_ASSET_ALLOW_LIST = [
|
|
5
11
|
{
|
|
6
12
|
key: 'system-small-cover',
|
|
@@ -38,6 +44,14 @@ exports.ASSET_TRANSFORM_QUERY_KEYS = [
|
|
|
38
44
|
'withoutEnlargement',
|
|
39
45
|
];
|
|
40
46
|
exports.FILTER_VARIABLES = ['$NOW', '$CURRENT_USER', '$CURRENT_ROLE'];
|
|
41
|
-
exports.ALIAS_TYPES = ['alias', 'o2m', 'm2m', 'm2a', 'files', 'translations'];
|
|
47
|
+
exports.ALIAS_TYPES = ['alias', 'o2m', 'm2m', 'm2a', 'o2a', 'files', 'translations'];
|
|
42
48
|
exports.DEFAULT_AUTH_PROVIDER = 'default';
|
|
43
49
|
exports.COLUMN_TRANSFORMS = ['year', 'month', 'day', 'weekday', 'hour', 'minute', 'second'];
|
|
50
|
+
exports.UUID_REGEX = '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}';
|
|
51
|
+
exports.COOKIE_OPTIONS = {
|
|
52
|
+
httpOnly: true,
|
|
53
|
+
domain: env_1.default.REFRESH_TOKEN_COOKIE_DOMAIN,
|
|
54
|
+
maxAge: (0, ms_1.default)(env_1.default.REFRESH_TOKEN_TTL),
|
|
55
|
+
secure: (_a = env_1.default.REFRESH_TOKEN_COOKIE_SECURE) !== null && _a !== void 0 ? _a : false,
|
|
56
|
+
sameSite: env_1.default.REFRESH_TOKEN_COOKIE_SAME_SITE || 'strict',
|
|
57
|
+
};
|
|
@@ -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: '$NOW',
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
date_start: {
|
|
112
|
+
_null: true,
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
_or: [
|
|
119
|
+
{
|
|
120
|
+
date_end: {
|
|
121
|
+
_gte: '$NOW',
|
|
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();
|