jxp 2.13.4 → 2.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env +6 -5
- package/bin/server.js +5 -190
- package/docs/configuration.md +16 -1
- package/libs/connection_string.js +12 -2
- package/package.json +9 -9
package/.env
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
MONGODB_HOST=127.0.0.1
|
|
2
|
+
MONGODB_PORT=27017
|
|
3
|
+
MONGODB_NAME=dev
|
|
4
|
+
MONGODB_AUTH_DB=admin
|
|
5
|
+
MONGODB_USER=
|
|
6
|
+
MONGODB_PASS=
|
|
6
7
|
|
|
7
8
|
NODE_LOCAL_PORT=4001
|
|
8
9
|
NODE_DOCKER_PORT=4001
|
package/bin/server.js
CHANGED
|
@@ -1,195 +1,11 @@
|
|
|
1
1
|
/*
|
|
2
|
-
|
|
3
|
-
API
|
|
4
|
-
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
/*
|
|
8
|
-
|
|
9
|
-
This Express route supports CRUD operations without having to define controllers for each type.
|
|
10
|
-
|
|
11
|
-
You do still have to define Mongoose models, which we expect to find at ../models.
|
|
12
|
-
|
|
13
|
-
Supports the following verbs:
|
|
14
|
-
- GET - Gets a list or a single object
|
|
15
|
-
- POST - Creates a single object
|
|
16
|
-
- PUT - Updates a single object
|
|
17
|
-
- DELETE - Deletes a single object
|
|
18
|
-
|
|
19
|
-
The format is /:modename for a GET list and a POST.
|
|
20
|
-
The format is /:modelname/:_id for a GET item, PUT and DELETE.
|
|
21
|
-
|
|
22
|
-
When GETting a list, you can add a Filter as a parameter, eg. /:modelname?filter[field]=value
|
|
23
|
-
|
|
24
|
-
To filter with $gte, $lte or similar, use a colon to divide the operator and query. Eg. /:modelname?filter[field]=$gte:value
|
|
25
|
-
|
|
26
|
-
There's also a special route, /:modelname/_describe, which returns the model
|
|
27
|
-
|
|
28
|
-
User model should look a bit like:
|
|
29
|
-
|
|
30
|
-
```
|
|
31
|
-
var mongoose = require('mongoose');
|
|
32
|
-
var Schema = mongoose.Schema;
|
|
33
|
-
|
|
34
|
-
var Objectid = mongoose.Schema.Types.ObjectId;
|
|
35
|
-
|
|
36
|
-
var UserSchema = new Schema({
|
|
37
|
-
name: String,
|
|
38
|
-
email: String,
|
|
39
|
-
password: String,
|
|
40
|
-
apikey: String,
|
|
41
|
-
admin: Boolean,
|
|
42
|
-
temp_hash: String,
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
UserSchema.set("_perms", {
|
|
46
|
-
admin: "rw",
|
|
47
|
-
owner: "rw",
|
|
48
|
-
user: "r"
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
module.exports = mongoose.model('User', UserSchema);
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
You can set permissions per model by setting _perms on the schema. Eg:
|
|
55
|
-
```
|
|
56
|
-
TestSchema.set("_perms", {
|
|
57
|
-
admin: "rw",
|
|
58
|
-
owner: "rw",
|
|
59
|
-
user: "r",
|
|
60
|
-
all: "r"
|
|
61
|
-
});
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
If you want to use the owner property, you need to have _owner_id in your model.
|
|
65
|
-
Eg.
|
|
66
|
-
```
|
|
67
|
-
_owner_id: mongoose.Schema.Types.ObjectId;
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
Possible permission keys are:
|
|
71
|
-
"admin" | anyone with "admin" set to true
|
|
72
|
-
"owner" | on a per-record basis, the person who originally wrote the record
|
|
73
|
-
"user" | any registered user
|
|
74
|
-
"all" | the w0rld
|
|
75
|
-
|
|
76
|
-
(See below for adding group permissions)
|
|
77
|
-
|
|
78
|
-
Possible values are:
|
|
79
|
-
"c" | create
|
|
80
|
-
"r" | read
|
|
81
|
-
"u" | update
|
|
82
|
-
"d" | delete
|
|
83
|
-
|
|
84
|
-
###Groups
|
|
85
|
-
|
|
86
|
-
To define groups, you need a usergroups model. It should look like this:
|
|
87
|
-
|
|
88
|
-
```
|
|
89
|
-
var mongoose = require('mongoose');
|
|
90
|
-
var Schema = mongoose.Schema;
|
|
91
|
-
var Objectid = mongoose.Schema.Types.ObjectId;
|
|
92
|
-
var UserGroupSchema = new Schema({
|
|
93
|
-
user_id: Objectid,
|
|
94
|
-
groups: [String],
|
|
95
|
-
_date: { type: Date, default: Date.now },
|
|
96
|
-
});
|
|
97
|
-
module.exports = mongoose.model('Usergroup', UserGroupSchema);
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
Note that it doesn't have a _perm section, because it is accessed directly,
|
|
101
|
-
not through the API. If you do want to access it through the API, feel free
|
|
102
|
-
to add a _perm section, but make sure you lock down permissions.
|
|
103
|
-
|
|
104
|
-
To set a user's groups, call the API as follows:
|
|
105
|
-
Type: POST
|
|
106
|
-
End-point: /_groups/:user_id
|
|
107
|
-
Data: { group: "group_name" }
|
|
108
|
-
|
|
109
|
-
To add a user to a group, call the API as follows:
|
|
110
|
-
Type: PUT
|
|
111
|
-
End-point: /_groups/:user_id
|
|
112
|
-
Data: { group: "group_name" }
|
|
113
|
-
|
|
114
|
-
* For POST and PUT, you can send multiple groups at once.
|
|
115
|
-
|
|
116
|
-
To remove a user from a group
|
|
117
|
-
TYPE: DELETE
|
|
118
|
-
End-point: /_groups/:user_id
|
|
119
|
-
Data: { group: "group_name" }
|
|
120
|
-
|
|
121
|
-
To check a user's groups:
|
|
122
|
-
Type: GET
|
|
123
|
-
End-point: /_groups/:user_id
|
|
124
|
-
|
|
125
|
-
Only Admins can use the /_groups endpoint.
|
|
126
|
-
|
|
127
|
-
To add permissions for a group to a model, just use the name, and give it permissions.
|
|
128
|
-
Eg:
|
|
129
|
-
|
|
130
|
-
```
|
|
131
|
-
TestSchema.set("_perms", {
|
|
132
|
-
admin: "crud",
|
|
133
|
-
no_delete: "cru",
|
|
134
|
-
read_only: "r"
|
|
135
|
-
});
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
Admins would be able to do anything, users in the "no_delete" group would be able to create, read and update, and users in the read_only group would only be able to read.
|
|
139
|
-
|
|
140
|
-
Note that groups *do not fail* permissions, so if the user passes for admin, owner, or user, and not for group, the transaction will still go ahead.
|
|
141
|
-
|
|
142
|
-
###Soft Delete
|
|
143
|
-
|
|
144
|
-
If you want a model to soft delete, add a _deleted property as follows:
|
|
145
|
-
|
|
146
|
-
```
|
|
147
|
-
_deleted: { type: Boolean, default: false, index: true },
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
If _deleted equals true, the document will not show up when you get the list of
|
|
151
|
-
documents, and calling it directly will result in a 404.
|
|
152
|
-
|
|
153
|
-
To show deleted documents when you get a list, add showDeleted=true to your query.
|
|
154
|
-
|
|
155
|
-
###Calling Static Methods
|
|
156
|
-
|
|
157
|
-
You can define a method for a Model in the model as follows:
|
|
158
|
-
```
|
|
159
|
-
TestSchema.statics.test = function() {
|
|
160
|
-
return "Testing OKAY!";
|
|
161
|
-
}
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
Then to call that method through the API, use `https://my.api/api/_call/test`.
|
|
165
|
-
If you POST, all variables will be passed through to the method.
|
|
166
|
-
|
|
167
|
-
###Adding custom permission logic
|
|
168
|
-
|
|
169
|
-
Maybe you want to do some more checks on permissions than the "crud" we offer. You can catch
|
|
170
|
-
the user object in your model as a virtual attribute. (I suppose you could use a real Mixed attribute too.)
|
|
171
|
-
|
|
172
|
-
Eg.
|
|
173
|
-
|
|
174
|
-
```
|
|
175
|
-
var sender;
|
|
176
|
-
|
|
177
|
-
LedgerSchema.virtual("__user").set(function(usr) {
|
|
178
|
-
sender = usr;
|
|
179
|
-
});
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
And then later, say in your pre- or post-save...
|
|
183
|
-
|
|
184
|
-
```
|
|
185
|
-
(!sender.admin)) {
|
|
186
|
-
return next(new Error( "Verboten!"));
|
|
187
|
-
}
|
|
188
|
-
```
|
|
2
|
+
=================
|
|
3
|
+
JXP - Express API
|
|
4
|
+
=================
|
|
189
5
|
|
|
190
|
-
|
|
6
|
+
Documentation:
|
|
7
|
+
https://jxp.readthedocs.io/en/latest/
|
|
191
8
|
|
|
192
|
-
Add the parameter `_silence` to supress callbacks. Useful to avoid infinite loops.
|
|
193
9
|
*/
|
|
194
10
|
|
|
195
11
|
const mongoose = require("mongoose");
|
|
@@ -236,7 +52,6 @@ config.pre_hooks = {
|
|
|
236
52
|
},
|
|
237
53
|
};
|
|
238
54
|
|
|
239
|
-
//DB connection
|
|
240
55
|
// ES6 promises
|
|
241
56
|
mongoose.Promise = Promise;
|
|
242
57
|
if (!config.mongo) config.mongo = {};
|
package/docs/configuration.md
CHANGED
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
# Configuring JXP
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
## Connecting to MongoDB
|
|
4
|
+
|
|
5
|
+
JXP uses MongoDB for storage. You can use a local MongoDB instance, or a hosted one such as Mongo Atlas.
|
|
6
|
+
|
|
7
|
+
The configuration for the MongoDB connection is set as environmental variables (for instance, if running in Docker), or in the `.env` file. Alternatively, you can set the connection string in the config file as described below, although this is not recommended.
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
MONGODB_HOST=127.0.0.1
|
|
11
|
+
MONGODB_PORT=27017
|
|
12
|
+
MONGODB_NAME=jxp
|
|
13
|
+
MONGODB_AUTH_DB=admin
|
|
14
|
+
MONGODB_USER=user
|
|
15
|
+
MONGODB_PASS=pass
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Config files
|
|
4
19
|
|
|
5
20
|
The config files are stored in `/config` in strict JSON format. (Remember to enclose your keys in inverted commas!) Typically, you'd use `/config/default.json` for a simple configuration, or `/config/development.json` and `/config/production.json` for separating development and production.
|
|
6
21
|
|
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
const config = require("config");
|
|
2
2
|
require("dotenv").config();
|
|
3
3
|
|
|
4
|
+
// mongodb connection
|
|
5
|
+
const {
|
|
6
|
+
MONGODB_USER,
|
|
7
|
+
MONGODB_PASSWORD,
|
|
8
|
+
MONGODB_HOST,
|
|
9
|
+
MONGODB_PORT,
|
|
10
|
+
MONGODB_NAME,
|
|
11
|
+
MONGODB_AUTH_DB,
|
|
12
|
+
} = process.env;
|
|
13
|
+
|
|
4
14
|
// mongodb connection
|
|
5
15
|
let connection_string = `mongodb://localhost:27017/jxp`;
|
|
6
16
|
if (config.mongo && config.mongo.connection_string) {
|
|
7
17
|
connection_string = config.mongo.connection_string;
|
|
8
18
|
console.warn("`config` to be deprecated in favour of dotenv in future versions");
|
|
9
19
|
}
|
|
10
|
-
if (
|
|
11
|
-
connection_string = `mongodb://${
|
|
20
|
+
if (MONGODB_HOST) {
|
|
21
|
+
connection_string = `mongodb://${ (MONGODB_USER && MONGODB_PASSWORD) ? `${MONGODB_USER}:${MONGODB_PASSWORD}@` : '' }${MONGODB_HOST}:${MONGODB_PORT}/${MONGODB_NAME}?${ (MONGODB_AUTH_DB) ? `authSource=${MONGODB_AUTH_DB}` : '' }`
|
|
12
22
|
}
|
|
13
23
|
|
|
14
24
|
module.exports = connection_string;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jxp",
|
|
3
3
|
"description:": "An opinionated RESTful API library based on Mongoose and Restify. Make an API by just writing Mongoose models.",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.14.1",
|
|
5
5
|
"private": false,
|
|
6
6
|
"main": "libs/jxp.js",
|
|
7
7
|
"scripts": {
|
|
@@ -29,15 +29,15 @@
|
|
|
29
29
|
"url": "https://github.com/j-norwood-young/jexpress-2/issues"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"axios": "^1.
|
|
32
|
+
"axios": "^1.4.0",
|
|
33
33
|
"bcryptjs": "^2.4.3",
|
|
34
34
|
"commander": "^10.0.0",
|
|
35
35
|
"config": "^3.3.9",
|
|
36
|
-
"dotenv": "^16.
|
|
36
|
+
"dotenv": "^16.3.1",
|
|
37
37
|
"glob": "8.1.0",
|
|
38
38
|
"js-yaml": "4.1.0",
|
|
39
39
|
"json2csv": "^5.0.7",
|
|
40
|
-
"jsonwebtoken": "^9.0.
|
|
40
|
+
"jsonwebtoken": "^9.0.1",
|
|
41
41
|
"jstransformer-markdown-it": "^3.0.0",
|
|
42
42
|
"jxp-helper": "^1.4.0",
|
|
43
43
|
"mkdirp": "^2.1.3",
|
|
@@ -46,23 +46,23 @@
|
|
|
46
46
|
"mongoose-friendly": "^0.1.4",
|
|
47
47
|
"morgan": "^1.10.0",
|
|
48
48
|
"node-cache": "^5.1.2",
|
|
49
|
-
"nodemailer": "^6.9.
|
|
49
|
+
"nodemailer": "^6.9.3",
|
|
50
50
|
"nodemailer-smtp-transport": "^2.7.4",
|
|
51
51
|
"path": "^0.12.7",
|
|
52
52
|
"pug": "^3.0.2",
|
|
53
53
|
"querystring": "^0.2.1",
|
|
54
54
|
"rand-token": "^1.0.1",
|
|
55
55
|
"readline-sync": "^1.4.10",
|
|
56
|
-
"restify": "^11.
|
|
57
|
-
"restify-cors-middleware2": "^2.2.
|
|
56
|
+
"restify": "^11.1.0",
|
|
57
|
+
"restify-cors-middleware2": "^2.2.1",
|
|
58
58
|
"restify-errors": "^8.0.2",
|
|
59
59
|
"traverse": "^0.6.7",
|
|
60
60
|
"underscore": "^1.13.6",
|
|
61
|
-
"ws": "^8.
|
|
61
|
+
"ws": "^8.13.0"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
64
|
"chai": "^4.3.7",
|
|
65
|
-
"chai-http": "^4.
|
|
65
|
+
"chai-http": "^4.4.0",
|
|
66
66
|
"mocha": "^10.2.0",
|
|
67
67
|
"moment": "^2.29.4",
|
|
68
68
|
"should": "^13.2.3"
|