jxp 2.16.0 → 4.0.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/.env.sample +31 -6
- package/README.md +27 -13
- package/dist/bin/init_db.d.ts +3 -0
- package/dist/bin/init_db.d.ts.map +1 -0
- package/dist/bin/init_db.js +48 -0
- package/dist/bin/init_db.js.map +1 -0
- package/dist/bin/server.d.ts +4 -0
- package/dist/bin/server.d.ts.map +1 -0
- package/dist/bin/server.js +132 -0
- package/dist/bin/server.js.map +1 -0
- package/dist/bin/setup.d.ts +3 -0
- package/dist/bin/setup.d.ts.map +1 -0
- package/dist/bin/setup.js +185 -0
- package/dist/bin/setup.js.map +1 -0
- package/dist/globals.d.ts +14 -0
- package/dist/globals.d.ts.map +1 -0
- package/dist/globals.js +3 -0
- package/dist/globals.js.map +1 -0
- package/dist/libs/aggregate_guard.d.ts +5 -0
- package/dist/libs/aggregate_guard.d.ts.map +1 -0
- package/dist/libs/aggregate_guard.js +58 -0
- package/dist/libs/aggregate_guard.js.map +1 -0
- package/dist/libs/bulkwrite_guard.d.ts +5 -0
- package/dist/libs/bulkwrite_guard.d.ts.map +1 -0
- package/dist/libs/bulkwrite_guard.js +44 -0
- package/dist/libs/bulkwrite_guard.js.map +1 -0
- package/dist/libs/cache.d.ts +2 -0
- package/dist/libs/cache.d.ts.map +1 -0
- package/dist/libs/cache.js +94 -0
- package/dist/libs/cache.js.map +1 -0
- package/dist/libs/call_guard.d.ts +3 -0
- package/dist/libs/call_guard.d.ts.map +1 -0
- package/dist/libs/call_guard.js +17 -0
- package/dist/libs/call_guard.js.map +1 -0
- package/dist/libs/connection_string.d.ts +3 -0
- package/dist/libs/connection_string.d.ts.map +1 -0
- package/dist/libs/connection_string.js +4 -0
- package/dist/libs/connection_string.js.map +1 -0
- package/dist/libs/datamunging.d.ts +2 -0
- package/dist/libs/datamunging.d.ts.map +1 -0
- package/dist/libs/datamunging.js +320 -0
- package/dist/libs/datamunging.js.map +1 -0
- package/dist/libs/docs.d.ts +2 -0
- package/dist/libs/docs.d.ts.map +1 -0
- package/dist/libs/docs.js +307 -0
- package/dist/libs/docs.js.map +1 -0
- package/dist/libs/groups.d.ts +2 -0
- package/dist/libs/groups.d.ts.map +1 -0
- package/dist/libs/groups.js +136 -0
- package/dist/libs/groups.js.map +1 -0
- package/dist/libs/jxp.d.ts +4 -0
- package/dist/libs/jxp.d.ts.map +1 -0
- package/dist/libs/jxp.js +1157 -0
- package/dist/libs/jxp.js.map +1 -0
- package/dist/libs/link_index.d.ts +14 -0
- package/dist/libs/link_index.d.ts.map +1 -0
- package/dist/libs/link_index.js +37 -0
- package/dist/libs/link_index.js.map +1 -0
- package/dist/libs/load-config.d.ts +16 -0
- package/dist/libs/load-config.d.ts.map +1 -0
- package/dist/libs/load-config.js +155 -0
- package/dist/libs/load-config.js.map +1 -0
- package/dist/libs/login.d.ts +2 -0
- package/dist/libs/login.d.ts.map +1 -0
- package/dist/libs/login.js +244 -0
- package/dist/libs/login.js.map +1 -0
- package/dist/libs/modeldir.d.ts +5 -0
- package/dist/libs/modeldir.d.ts.map +1 -0
- package/dist/libs/modeldir.js +15 -0
- package/dist/libs/modeldir.js.map +1 -0
- package/dist/libs/query_limits.d.ts +2 -0
- package/dist/libs/query_limits.d.ts.map +1 -0
- package/dist/libs/query_limits.js +84 -0
- package/dist/libs/query_limits.js.map +1 -0
- package/dist/libs/query_manipulation.d.ts +3 -0
- package/dist/libs/query_manipulation.d.ts.map +1 -0
- package/{libs → dist/libs}/query_manipulation.js +22 -21
- package/dist/libs/query_manipulation.js.map +1 -0
- package/dist/libs/query_sanitize.d.ts +5 -0
- package/dist/libs/query_sanitize.d.ts.map +1 -0
- package/dist/libs/query_sanitize.js +109 -0
- package/dist/libs/query_sanitize.js.map +1 -0
- package/dist/libs/response_sanitize.d.ts +7 -0
- package/dist/libs/response_sanitize.d.ts.map +1 -0
- package/dist/libs/response_sanitize.js +57 -0
- package/dist/libs/response_sanitize.js.map +1 -0
- package/dist/libs/safe_error.d.ts +3 -0
- package/dist/libs/safe_error.d.ts.map +1 -0
- package/dist/libs/safe_error.js +14 -0
- package/dist/libs/safe_error.js.map +1 -0
- package/dist/libs/schema.d.ts +14 -0
- package/dist/libs/schema.d.ts.map +1 -0
- package/dist/libs/schema.js +98 -0
- package/dist/libs/schema.js.map +1 -0
- package/dist/libs/schema_description.d.ts +3 -0
- package/dist/libs/schema_description.d.ts.map +1 -0
- package/{libs → dist/libs}/schema_description.js +12 -21
- package/dist/libs/schema_description.js.map +1 -0
- package/dist/libs/security.d.ts +2 -0
- package/dist/libs/security.d.ts.map +1 -0
- package/dist/libs/security.js +428 -0
- package/dist/libs/security.js.map +1 -0
- package/dist/libs/setup.d.ts +2 -0
- package/dist/libs/setup.d.ts.map +1 -0
- package/dist/libs/setup.js +87 -0
- package/dist/libs/setup.js.map +1 -0
- package/dist/libs/startup-deprecations.d.ts +2 -0
- package/dist/libs/startup-deprecations.d.ts.map +1 -0
- package/dist/libs/startup-deprecations.js +21 -0
- package/dist/libs/startup-deprecations.js.map +1 -0
- package/dist/libs/startup.d.ts +16 -0
- package/dist/libs/startup.d.ts.map +1 -0
- package/dist/libs/startup.js +63 -0
- package/dist/libs/startup.js.map +1 -0
- package/dist/libs/ws.d.ts +2 -0
- package/dist/libs/ws.d.ts.map +1 -0
- package/{libs → dist/libs}/ws.js +114 -73
- package/dist/libs/ws.js.map +1 -0
- package/dist/models/apikey_model.d.ts +10 -0
- package/dist/models/apikey_model.d.ts.map +1 -0
- package/dist/models/apikey_model.js +14 -0
- package/dist/models/apikey_model.js.map +1 -0
- package/dist/models/link_model.d.ts +9 -0
- package/dist/models/link_model.d.ts.map +1 -0
- package/dist/models/link_model.js +20 -0
- package/dist/models/link_model.js.map +1 -0
- package/dist/models/refreshtoken_model.d.ts +11 -0
- package/dist/models/refreshtoken_model.d.ts.map +1 -0
- package/dist/models/refreshtoken_model.js +22 -0
- package/dist/models/refreshtoken_model.js.map +1 -0
- package/dist/models/test_model.d.ts +24 -0
- package/dist/models/test_model.d.ts.map +1 -0
- package/dist/models/test_model.js +44 -0
- package/dist/models/test_model.js.map +1 -0
- package/dist/models/token_model.d.ts +14 -0
- package/dist/models/token_model.d.ts.map +1 -0
- package/dist/models/token_model.js +25 -0
- package/dist/models/token_model.js.map +1 -0
- package/dist/models/user_model.d.ts +15 -0
- package/dist/models/user_model.d.ts.map +1 -0
- package/dist/models/user_model.js +38 -0
- package/dist/models/user_model.js.map +1 -0
- package/dist/models/usergroups_model.d.ts +9 -0
- package/dist/models/usergroups_model.d.ts.map +1 -0
- package/dist/models/usergroups_model.js +18 -0
- package/dist/models/usergroups_model.js.map +1 -0
- package/dist/types/jxp-config.d.ts +134 -0
- package/dist/types/jxp-config.d.ts.map +1 -0
- package/dist/types/jxp-config.js +3 -0
- package/dist/types/jxp-config.js.map +1 -0
- package/dist/types/schema-fields.d.ts +43 -0
- package/dist/types/schema-fields.d.ts.map +1 -0
- package/dist/types/schema-fields.js +3 -0
- package/dist/types/schema-fields.js.map +1 -0
- package/docs/aggregations.md +40 -21
- package/docs/api.md +55 -15
- package/docs/authentication.md +60 -37
- package/docs/bulk_writes.md +11 -8
- package/docs/caching.md +28 -11
- package/docs/changelog.md +237 -31
- package/docs/configuration.md +99 -118
- package/docs/hooks.md +12 -8
- package/docs/index.md +17 -17
- package/docs/installation.md +23 -18
- package/docs/permissions.md +33 -19
- package/docs/queries.md +9 -5
- package/docs/schemas.md +21 -10
- package/docs/special.md +4 -4
- package/docs/typescript.md +86 -0
- package/docs/websocket.md +99 -1
- package/mkdocs.yml +1 -0
- package/package.json +121 -69
- package/templates/api.pug +32 -0
- package/templates/app-server.js +43 -0
- package/templates/app.env.sample +8 -0
- package/templates/assets/api-console.js +133 -0
- package/templates/assets/docs.css +227 -0
- package/templates/index.pug +62 -2
- package/templates/layout.pug +17 -11
- package/templates/md.pug +1 -1
- package/templates/model.pug +117 -68
- package/templates/navbar.pug +14 -21
- package/templates/sidebar.pug +30 -0
- package/.env +0 -9
- package/.eslintrc.json +0 -20
- package/.jshintrc +0 -4
- package/.vscode/launch.json +0 -29
- package/.vscode/settings.json +0 -3
- package/Dockerfile +0 -7
- package/bin/init_db.js +0 -54
- package/bin/server.js +0 -84
- package/bin/setup.js +0 -190
- package/config_sample.json +0 -10
- package/docker-compose.yml +0 -32
- package/libs/cache.js +0 -92
- package/libs/connection_string.js +0 -24
- package/libs/datamunging.js +0 -335
- package/libs/docs.js +0 -162
- package/libs/groups.js +0 -133
- package/libs/jxp.js +0 -1208
- package/libs/login.js +0 -218
- package/libs/modeldir.js +0 -14
- package/libs/schema.js +0 -99
- package/libs/security.js +0 -410
- package/libs/setup.js +0 -90
- package/models/apikey_model.js +0 -10
- package/models/link_model.js +0 -17
- package/models/refreshtoken_model.js +0 -20
- package/models/test_model.js +0 -50
- package/models/token_model.js +0 -23
- package/models/user_model.js +0 -38
- package/models/usergroups_model.js +0 -15
- package/setup.sh +0 -3
- package/test/.eslintrc.json +0 -13
- package/test/init.js +0 -92
- package/test/setup.test.js +0 -62
- package/test/test.js +0 -1527
- package/test/wstest.js.old +0 -124
package/libs/login.js
DELETED
|
@@ -1,218 +0,0 @@
|
|
|
1
|
-
const axios = require("axios");
|
|
2
|
-
const jwt = require("jsonwebtoken");
|
|
3
|
-
const bcrypt = require('bcryptjs');
|
|
4
|
-
const security = require("../libs/security");
|
|
5
|
-
const nodemailer = require('nodemailer');
|
|
6
|
-
const errors = require("restify-errors");
|
|
7
|
-
const smtpTransport = require('nodemailer-smtp-transport');
|
|
8
|
-
const path = require("path");
|
|
9
|
-
let User = null;
|
|
10
|
-
|
|
11
|
-
var init = function (config) {
|
|
12
|
-
User = require(path.join(config.model_dir, 'user_model'));
|
|
13
|
-
security.init(config);
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
const recover = async (req, res) => {
|
|
17
|
-
try {
|
|
18
|
-
// create reusable transporter object using SMTP transport
|
|
19
|
-
const transporter = nodemailer.createTransport(smtpTransport({
|
|
20
|
-
host: req.config.smtp_server,
|
|
21
|
-
port: 25,
|
|
22
|
-
auth: {
|
|
23
|
-
user: req.config.smtp_username,
|
|
24
|
-
pass: req.config.smtp_password,
|
|
25
|
-
},
|
|
26
|
-
// secure: true,
|
|
27
|
-
tls: { rejectUnauthorized: false }
|
|
28
|
-
}));
|
|
29
|
-
const email = req.body.email;
|
|
30
|
-
if (!email) {
|
|
31
|
-
console.error("Missing email parameter");
|
|
32
|
-
throw new errors.BadRequestError("Missing email parameter");
|
|
33
|
-
}
|
|
34
|
-
const user = await User.findOne({ email });
|
|
35
|
-
if (!user) {
|
|
36
|
-
throw new errors.NotFoundError(`User with email ${email} Not Found`);
|
|
37
|
-
}
|
|
38
|
-
const result = await security.generateApiKey(user._id);
|
|
39
|
-
const token = jwt.sign({ apikey: result.apikey, email: user.email, id: user._id }, req.config.shared_secret, { expiresIn: "2d" });
|
|
40
|
-
var text = `Someone (hopefully you) requested a password reset. Please click on the following url to recover your password. If you did not request a password reset, you can ignore this message. \n${req.config.password_recovery_url}/${token}`;
|
|
41
|
-
var html = text;
|
|
42
|
-
var mail_format = req.params.mail_format || req.body.mail_format;
|
|
43
|
-
if (mail_format) {
|
|
44
|
-
html = mail_format;
|
|
45
|
-
html = html.replace(/\{\{recover_url\}\}/i, req.config.password_recovery_url + "/" + token);
|
|
46
|
-
}
|
|
47
|
-
transporter.sendMail({
|
|
48
|
-
from: req.config.smtp_from,
|
|
49
|
-
to: user.email,
|
|
50
|
-
subject: "Password Recovery",
|
|
51
|
-
text: text,
|
|
52
|
-
html: html
|
|
53
|
-
}, function (result) {
|
|
54
|
-
console.log({ msg: "Mailer result", result });
|
|
55
|
-
});
|
|
56
|
-
res.send({ status: "ok", message: "Sent recovery email" });
|
|
57
|
-
} catch (err) {
|
|
58
|
-
if (err.code) throw err;
|
|
59
|
-
throw new errors.UnauthorizedError(err.toString());
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const logout = async (req, res) => {
|
|
64
|
-
try {
|
|
65
|
-
if (!res.user) throw new errors.ForbiddenError("You don't seem to be logged in");
|
|
66
|
-
await security.revokeToken(res.user._id);
|
|
67
|
-
res.send({ status: "ok", message: "User logged out" });
|
|
68
|
-
} catch(err) {
|
|
69
|
-
console.error(err);
|
|
70
|
-
if (err.code) throw err;
|
|
71
|
-
throw new errors.InternalServerError(err.toString());
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const oauth = (req, res, next) => { // Log in through an OAuth2 provider, defined in config.js
|
|
76
|
-
const provider_config = req.config.oauth[req.params.provider];
|
|
77
|
-
if (!provider_config) {
|
|
78
|
-
throw new errors.InternalServerError(`oAuth ${req.params.provider} config not defined`);
|
|
79
|
-
}
|
|
80
|
-
const state = Math.random().toString(36).substring(7);
|
|
81
|
-
const uri = `${provider_config.auth_uri}?client_id=${provider_config.app_id}&redirect_uri=${req.config.url}/login/oauth/callback/${req.params.provider}&scope=${provider_config.scope}&state=${state}&response_type=code`;
|
|
82
|
-
res.redirect(uri, next);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const oauth_callback = async (req, res) => {
|
|
86
|
-
const provider = req.params.provider;
|
|
87
|
-
const provider_config = req.config.oauth[provider];
|
|
88
|
-
const code = req.query.code;
|
|
89
|
-
try {
|
|
90
|
-
if (req.query.error) {
|
|
91
|
-
throw (req.query.error);
|
|
92
|
-
}
|
|
93
|
-
if (!code) {
|
|
94
|
-
throw ("missing_code");
|
|
95
|
-
}
|
|
96
|
-
const token = (await axios.post(provider_config.token_uri, {
|
|
97
|
-
client_id: provider_config.app_id,
|
|
98
|
-
redirect_uri: `${req.config.url}/login/oauth/callback/${req.params.provider}`,
|
|
99
|
-
client_secret: provider_config.app_secret,
|
|
100
|
-
code: code,
|
|
101
|
-
grant_type: "authorization_code"
|
|
102
|
-
})).data;
|
|
103
|
-
if (!token.access_token) {
|
|
104
|
-
throw ("missing_access_token");
|
|
105
|
-
}
|
|
106
|
-
const data = (await axios.get(provider_config.api_uri, { headers: { Authorization: `Bearer ${token.access_token}` } })).data;
|
|
107
|
-
if (data.emailAddress) {
|
|
108
|
-
data.email = data.emailAddress;
|
|
109
|
-
}
|
|
110
|
-
if (data.elements && data.elements[0] && data.elements[0]["handle~"] && data.elements[0]["handle~"].emailAddress) { // LinkedIn
|
|
111
|
-
data.email = data.elements[0]["handle~"].emailAddress;
|
|
112
|
-
}
|
|
113
|
-
if (!data.email) {
|
|
114
|
-
throw ("missing_data");
|
|
115
|
-
}
|
|
116
|
-
var search = {};
|
|
117
|
-
search[provider + ".id"] = data.id;
|
|
118
|
-
const user = await User.findOne(search);
|
|
119
|
-
if (!user) {
|
|
120
|
-
throw ("no_user");
|
|
121
|
-
}
|
|
122
|
-
user[provider] = data;
|
|
123
|
-
await user.save();
|
|
124
|
-
const apikey = await security.generateApiKey(user._id)
|
|
125
|
-
var jwt_token = jwt.sign({ apikey: apikey.apikey, user: user }, req.config.shared_secret, {
|
|
126
|
-
expiresIn: "1m"
|
|
127
|
-
});
|
|
128
|
-
res.redirect(`${req.config.oauth.success_uri}?token=${jwt_token}`);
|
|
129
|
-
} catch (err) {
|
|
130
|
-
console.error(err);
|
|
131
|
-
if (typeof err === 'string' || err instanceof String) {
|
|
132
|
-
res.redirect(`${req.config.oauth.fail_uri}?error=${err}&provider=${provider}`);
|
|
133
|
-
} else {
|
|
134
|
-
res.redirect(`${req.config.oauth.fail_uri}?error=unknown&provider=${provider}`);
|
|
135
|
-
}
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
const login = async (req, res) => {
|
|
141
|
-
const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
|
|
142
|
-
let email = req.params.email || req.body.email;
|
|
143
|
-
let password = req.params.password || req.body.password;
|
|
144
|
-
const userpass = security.basicAuthData(req);
|
|
145
|
-
if (userpass) {
|
|
146
|
-
email = userpass[0];
|
|
147
|
-
password = userpass[1];
|
|
148
|
-
}
|
|
149
|
-
if ((!password) || (!email)) {
|
|
150
|
-
console.error(new Date(), "Missing email or password parameters");
|
|
151
|
-
return new errors.ForbiddenError("Missing email or password parameters");
|
|
152
|
-
}
|
|
153
|
-
try {
|
|
154
|
-
const user = await User.findOne({ email });
|
|
155
|
-
if (!user) throw (`Incorrect email; email: ${email}`);
|
|
156
|
-
if (!(await bcrypt.compare(password, user.password))) {
|
|
157
|
-
throw (`Incorrect password; email: ${email}`);
|
|
158
|
-
}
|
|
159
|
-
const token = await security.refreshToken(user._id);
|
|
160
|
-
const refreshtoken = await security.ensureRefreshToken(user._id);
|
|
161
|
-
const apikey = await security.generateApiKey(user._id)
|
|
162
|
-
res.result = ({
|
|
163
|
-
user_id: user._id,
|
|
164
|
-
token: token.access_token,
|
|
165
|
-
apikey: apikey.apikey,
|
|
166
|
-
token_expires: security.tokenExpires(token),
|
|
167
|
-
refresh_token: refreshtoken.refresh_token,
|
|
168
|
-
refresh_token_expires: security.tokenExpires(refreshtoken),
|
|
169
|
-
provider: token.provider,
|
|
170
|
-
});
|
|
171
|
-
} catch (err) {
|
|
172
|
-
console.error(new Date(), `Authentication failed`, ip, err);
|
|
173
|
-
if (err.code) throw err;
|
|
174
|
-
return new errors.ForbiddenError(err.toString());
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
const getJWT = async (req, res) => {
|
|
179
|
-
var user = null;
|
|
180
|
-
if (!res.user.admin) {
|
|
181
|
-
throw new errors.UnauthorizedError("Unauthorized");
|
|
182
|
-
}
|
|
183
|
-
var email = req.params.email || req.body.email;
|
|
184
|
-
if (!email) {
|
|
185
|
-
throw new errors.BadRequestError("Email required");
|
|
186
|
-
}
|
|
187
|
-
try {
|
|
188
|
-
const result = await User.findOne({ email: email });
|
|
189
|
-
if (!result || !result._id) {
|
|
190
|
-
throw new errors.NotFoundError("User not found");
|
|
191
|
-
}
|
|
192
|
-
user = result;
|
|
193
|
-
try {
|
|
194
|
-
const apikey = await security.generateApiKey(user._id)
|
|
195
|
-
var token = jwt.sign({ apikey: apikey.apikey, email: user.email, id: user._id }, req.config.shared_secret, {
|
|
196
|
-
expiresIn: "2d"
|
|
197
|
-
});
|
|
198
|
-
res.send({ email: user.email, token: token });
|
|
199
|
-
} catch (err) {
|
|
200
|
-
throw new errors.UnauthorizedError("Unauthorized");
|
|
201
|
-
}
|
|
202
|
-
} catch (err) {
|
|
203
|
-
if (err.code) throw err;
|
|
204
|
-
throw new errors.InternalServerError(err.toString());
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
const Login = {
|
|
209
|
-
init,
|
|
210
|
-
recover,
|
|
211
|
-
logout,
|
|
212
|
-
oauth,
|
|
213
|
-
oauth_callback,
|
|
214
|
-
login,
|
|
215
|
-
getJWT
|
|
216
|
-
};
|
|
217
|
-
|
|
218
|
-
module.exports = Login;
|
package/libs/modeldir.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
const glob = require("glob");
|
|
2
|
-
const path = require("path");
|
|
3
|
-
|
|
4
|
-
const findModelDir = (dir) => {
|
|
5
|
-
if (dir === "/") throw("Model dir not found");
|
|
6
|
-
let result = glob.sync(path.join(dir, "**/user_model.js"));
|
|
7
|
-
if (result.length) {
|
|
8
|
-
return path.dirname(result.pop());
|
|
9
|
-
}
|
|
10
|
-
const found = findModelDir(path.join(dir, "../"));
|
|
11
|
-
return found;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
module.exports = { findModelDir }
|
package/libs/schema.js
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
/* global ObjectId */
|
|
2
|
-
|
|
3
|
-
// Our general requirements
|
|
4
|
-
const mongoose = require('mongoose');
|
|
5
|
-
const path = require("path");
|
|
6
|
-
const config = require("config");
|
|
7
|
-
const JXPHelper = require('jxp-helper');
|
|
8
|
-
const modeldir = require("./modeldir");
|
|
9
|
-
|
|
10
|
-
// Set some global types
|
|
11
|
-
global.ObjectId = mongoose.Schema.Types.ObjectId;
|
|
12
|
-
global.Mixed = mongoose.Schema.Types.Mixed;
|
|
13
|
-
// Add this to the top of your model to avoid eslint warnings: /* global ObjectId Mixed */
|
|
14
|
-
|
|
15
|
-
const model_dir = config.model_dir || modeldir.findModelDir(path.dirname(process.argv[1]));
|
|
16
|
-
|
|
17
|
-
const getModelFileFromRef = ref => {
|
|
18
|
-
return path.join(model_dir, `${String(ref).toLowerCase()}_model`);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
class Schema extends mongoose.Schema {
|
|
22
|
-
constructor(definition, opts) {
|
|
23
|
-
// Set default options
|
|
24
|
-
opts = Object.assign({
|
|
25
|
-
timestamps: true,
|
|
26
|
-
toJSON: { virtuals: true },
|
|
27
|
-
toObject: { virtuals: true }
|
|
28
|
-
}, opts);
|
|
29
|
-
// Set default defiitions
|
|
30
|
-
definition = Object.assign({
|
|
31
|
-
_deleted: { type: Boolean, default: false, index: true },
|
|
32
|
-
_owner_id: { type: ObjectId, link: "User", map_to: "_owner", index: true },
|
|
33
|
-
_updated_by_id: { type: ObjectId, link: "User", map_to: "_updated_by", index: true },
|
|
34
|
-
}, definition);
|
|
35
|
-
// Set up our jxp-helper so that we call call the API from within the API (if we've set config.apikey)
|
|
36
|
-
if (!global.jxphelper) {
|
|
37
|
-
const jxp_settings = {};
|
|
38
|
-
if (global.apikey) jxp_settings.apikey = global.apikey;
|
|
39
|
-
if (global.server) jxp_settings.server = global.server;
|
|
40
|
-
if (jxp_settings.apikey && jxp_settings.server) global.jxphelper = new JXPHelper(jxp_settings);
|
|
41
|
-
}
|
|
42
|
-
// construct our parent
|
|
43
|
-
super(definition, opts);
|
|
44
|
-
// Some properties
|
|
45
|
-
this.opts = opts;
|
|
46
|
-
this.definition = definition;
|
|
47
|
-
// Action!
|
|
48
|
-
this.index({ createdAt: -1 });
|
|
49
|
-
this.index({ updatedAt: -1 });
|
|
50
|
-
this.setPerms();
|
|
51
|
-
this.generateLinks();
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
setPerms() {
|
|
55
|
-
// Create the perms
|
|
56
|
-
this.set("_perms", Object.assign({
|
|
57
|
-
admin: "", // CRUD = Create, Retrieve, Update and Delete
|
|
58
|
-
owner: "",
|
|
59
|
-
user: "",
|
|
60
|
-
all: "" // Unauthenticated users will be able to read from test, but that is all
|
|
61
|
-
}, this.opts.perms));
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
generateLinks() {
|
|
65
|
-
let loaded_files = [];
|
|
66
|
-
// Find the links in our definitions and create virtuals for non-destructive populating
|
|
67
|
-
// Example: link_id: { type: ObjectId, link: "link", }
|
|
68
|
-
// Example with a custom key: link_id: { type: ObjectId, link: "link", map_to: "custom_name" }
|
|
69
|
-
for (let key of Object.keys(this.definition)) {
|
|
70
|
-
let def = this.definition[key];
|
|
71
|
-
let is_array = false;
|
|
72
|
-
if (def[0]) {
|
|
73
|
-
def = def[0];
|
|
74
|
-
is_array = true;
|
|
75
|
-
}
|
|
76
|
-
if (!def.link) continue;
|
|
77
|
-
const virtual_name = def.map_to || def.virtual || String(def.link).toLowerCase();
|
|
78
|
-
if (!loaded_files.includes(def.link)) {
|
|
79
|
-
require(getModelFileFromRef(def.link));
|
|
80
|
-
loaded_files.push(def.link);
|
|
81
|
-
}
|
|
82
|
-
this.virtual(virtual_name, {
|
|
83
|
-
ref: def.link,
|
|
84
|
-
localField: key,
|
|
85
|
-
foreignField: "_id",
|
|
86
|
-
justOne: def.justOne || !is_array,
|
|
87
|
-
options: Object.assign({}, def.options)
|
|
88
|
-
})
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Now we don't even need to import mongoose into our models for type
|
|
94
|
-
Schema.Types = mongoose.Schema.Types;
|
|
95
|
-
|
|
96
|
-
// Slightly self-referential, try not to think about it
|
|
97
|
-
Schema.model = mongoose.model;
|
|
98
|
-
|
|
99
|
-
module.exports = Schema;
|