@saltcorn/server 0.6.1-beta.1 → 0.6.2-beta.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/auth/index.js +15 -2
- package/index.js +17 -1
- package/locales/en.json +7 -1
- package/markup/admin.js +24 -17
- package/markup/index.js +14 -1
- package/package.json +14 -8
- package/public/saltcorn.js +17 -1
- package/restart_watcher.js +146 -0
- package/routes/fields.js +13 -13
- package/routes/homepage.js +124 -104
- package/routes/index.js +37 -0
- package/routes/tables.js +21 -19
- package/routes/tenant.js +58 -25
- package/routes/utils.js +1 -1
- package/routes/view.js +4 -4
- package/serve.js +125 -113
package/routes/homepage.js
CHANGED
|
@@ -21,8 +21,8 @@ const Trigger = require("@saltcorn/data/models/trigger");
|
|
|
21
21
|
const { fileUploadForm } = require("../markup/forms");
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
|
-
* @param {*} tables
|
|
25
|
-
* @param {object} req
|
|
24
|
+
* @param {*} tables
|
|
25
|
+
* @param {object} req
|
|
26
26
|
* @returns {Table}
|
|
27
27
|
*/
|
|
28
28
|
const tableTable = (tables, req) =>
|
|
@@ -38,8 +38,8 @@ const tableTable = (tables, req) =>
|
|
|
38
38
|
);
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
|
-
* @param {*} tables
|
|
42
|
-
* @param {object} req
|
|
41
|
+
* @param {*} tables
|
|
42
|
+
* @param {object} req
|
|
43
43
|
* @returns {object}
|
|
44
44
|
*/
|
|
45
45
|
const tableCard = (tables, req) => ({
|
|
@@ -67,8 +67,8 @@ const tableCard = (tables, req) => ({
|
|
|
67
67
|
});
|
|
68
68
|
|
|
69
69
|
/**
|
|
70
|
-
* @param {*} views
|
|
71
|
-
* @param {object} req
|
|
70
|
+
* @param {*} views
|
|
71
|
+
* @param {object} req
|
|
72
72
|
* @returns {Table}
|
|
73
73
|
*/
|
|
74
74
|
const viewTable = (views, req) =>
|
|
@@ -88,8 +88,8 @@ const viewTable = (views, req) =>
|
|
|
88
88
|
);
|
|
89
89
|
|
|
90
90
|
/**
|
|
91
|
-
* @param {*} views
|
|
92
|
-
* @param {object} req
|
|
91
|
+
* @param {*} views
|
|
92
|
+
* @param {object} req
|
|
93
93
|
* @returns {object}
|
|
94
94
|
*/
|
|
95
95
|
const viewCard = (views, req) => ({
|
|
@@ -119,8 +119,8 @@ const viewCard = (views, req) => ({
|
|
|
119
119
|
});
|
|
120
120
|
|
|
121
121
|
/**
|
|
122
|
-
* @param {*} pages
|
|
123
|
-
* @param {object} req
|
|
122
|
+
* @param {*} pages
|
|
123
|
+
* @param {object} req
|
|
124
124
|
* @returns {Table}
|
|
125
125
|
*/
|
|
126
126
|
const pageTable = (pages, req) =>
|
|
@@ -140,8 +140,8 @@ const pageTable = (pages, req) =>
|
|
|
140
140
|
);
|
|
141
141
|
|
|
142
142
|
/**
|
|
143
|
-
* @param {*} pages
|
|
144
|
-
* @param {object} req
|
|
143
|
+
* @param {*} pages
|
|
144
|
+
* @param {object} req
|
|
145
145
|
* @returns {object}
|
|
146
146
|
*/
|
|
147
147
|
const pageCard = (pages, req) => ({
|
|
@@ -172,11 +172,11 @@ const pageCard = (pages, req) => ({
|
|
|
172
172
|
});
|
|
173
173
|
|
|
174
174
|
/**
|
|
175
|
-
* @param {object} req
|
|
175
|
+
* @param {object} req
|
|
176
176
|
* @returns {Promise<div>}
|
|
177
177
|
*/
|
|
178
178
|
const filesTab = async (req) => {
|
|
179
|
-
const files = await File.find({}, { orderBy: "filename" });
|
|
179
|
+
const files = await File.find({}, { orderBy: "filename", cached: true });
|
|
180
180
|
return div(
|
|
181
181
|
files.length == 0
|
|
182
182
|
? p(req.__("No files"))
|
|
@@ -196,16 +196,10 @@ const filesTab = async (req) => {
|
|
|
196
196
|
};
|
|
197
197
|
|
|
198
198
|
/**
|
|
199
|
-
* @param {object} req
|
|
199
|
+
* @param {object} req
|
|
200
200
|
* @returns {Promise<div>}
|
|
201
201
|
*/
|
|
202
|
-
const usersTab = async (req) => {
|
|
203
|
-
const users = await User.find({}, { orderBy: "id" });
|
|
204
|
-
const roles = await User.get_roles();
|
|
205
|
-
var roleMap = {};
|
|
206
|
-
roles.forEach((r) => {
|
|
207
|
-
roleMap[r.id] = r.role;
|
|
208
|
-
});
|
|
202
|
+
const usersTab = async (req, users, roleMap) => {
|
|
209
203
|
return div(
|
|
210
204
|
mkTable(
|
|
211
205
|
[
|
|
@@ -219,20 +213,19 @@ const usersTab = async (req) => {
|
|
|
219
213
|
users
|
|
220
214
|
),
|
|
221
215
|
a(
|
|
222
|
-
{ href: `/useradmin/new`, class: "btn btn-secondary" },
|
|
216
|
+
{ href: `/useradmin/new`, class: "btn btn-secondary my-3" },
|
|
223
217
|
req.__("Create user")
|
|
224
218
|
)
|
|
225
219
|
);
|
|
226
220
|
};
|
|
227
221
|
|
|
228
222
|
/**
|
|
229
|
-
* @param {object} req
|
|
223
|
+
* @param {object} req
|
|
230
224
|
* @returns {Promise<div>}
|
|
231
225
|
*/
|
|
232
|
-
const actionsTab = async (req) => {
|
|
233
|
-
const triggers = await Trigger.findAllWithTableName();
|
|
234
|
-
|
|
226
|
+
const actionsTab = async (req, triggers) => {
|
|
235
227
|
return div(
|
|
228
|
+
{ class: "pb-3" },
|
|
236
229
|
triggers.length <= 1 &&
|
|
237
230
|
p(
|
|
238
231
|
{ class: "mt-2 pr-2" },
|
|
@@ -259,14 +252,73 @@ const actionsTab = async (req) => {
|
|
|
259
252
|
triggers
|
|
260
253
|
),
|
|
261
254
|
a(
|
|
262
|
-
{ href: "/actions/new", class: "btn btn-secondary
|
|
255
|
+
{ href: "/actions/new", class: "btn btn-secondary my-3" },
|
|
263
256
|
req.__("Add trigger")
|
|
264
257
|
)
|
|
265
258
|
);
|
|
266
259
|
};
|
|
260
|
+
const packTab = (req, packlist) =>
|
|
261
|
+
div(
|
|
262
|
+
{ class: "pb-3 pt-2 pr-4" },
|
|
263
|
+
p(req.__("Instead of building, get up and running in no time with packs")),
|
|
264
|
+
p(
|
|
265
|
+
{ class: "font-italic" },
|
|
266
|
+
req.__(
|
|
267
|
+
"Packs are collections of tables, views and plugins that give you a full application which you can then edit to suit your needs."
|
|
268
|
+
)
|
|
269
|
+
),
|
|
270
|
+
mkTable(
|
|
271
|
+
[
|
|
272
|
+
{ label: req.__("Name"), key: "name" },
|
|
273
|
+
{
|
|
274
|
+
label: req.__("Description"),
|
|
275
|
+
key: "description",
|
|
276
|
+
},
|
|
277
|
+
],
|
|
278
|
+
packlist,
|
|
279
|
+
{ noHeader: true }
|
|
280
|
+
),
|
|
281
|
+
a(
|
|
282
|
+
{ href: `/plugins?set=packs`, class: "btn btn-primary" },
|
|
283
|
+
req.__("Go to pack store »")
|
|
284
|
+
)
|
|
285
|
+
);
|
|
286
|
+
|
|
287
|
+
const helpCard = (req) =>
|
|
288
|
+
div(
|
|
289
|
+
{ class: "pb-3 pt-2 pr-4" },
|
|
290
|
+
p(req.__("Confused?")),
|
|
291
|
+
p(
|
|
292
|
+
req.__(
|
|
293
|
+
"The Wiki contains the documentation and tutorials on installing and using Saltcorn"
|
|
294
|
+
)
|
|
295
|
+
),
|
|
296
|
+
a(
|
|
297
|
+
{
|
|
298
|
+
href: `https://wiki.saltcorn.com/`,
|
|
299
|
+
class: "btn btn-primary",
|
|
300
|
+
},
|
|
301
|
+
req.__("Go to Wiki »")
|
|
302
|
+
),
|
|
303
|
+
p(req.__("The YouTube channel has some video tutorials")),
|
|
304
|
+
a(
|
|
305
|
+
{
|
|
306
|
+
href: `https://www.youtube.com/channel/UCBOpAcH8ep7ESbuocxcq0KQ`,
|
|
307
|
+
class: "btn btn-secondary",
|
|
308
|
+
},
|
|
309
|
+
req.__("Go to YouTube »")
|
|
310
|
+
),
|
|
311
|
+
div(
|
|
312
|
+
{ class: "mt-3" },
|
|
313
|
+
a(
|
|
314
|
+
{ href: `https://blog.saltcorn.com/` },
|
|
315
|
+
req.__("What's new? Read the blog »")
|
|
316
|
+
)
|
|
317
|
+
)
|
|
318
|
+
);
|
|
267
319
|
|
|
268
320
|
/**
|
|
269
|
-
* @param {object} req
|
|
321
|
+
* @param {object} req
|
|
270
322
|
* @returns {Promise<object>}
|
|
271
323
|
*/
|
|
272
324
|
const welcome_page = async (req) => {
|
|
@@ -275,10 +327,16 @@ const welcome_page = async (req) => {
|
|
|
275
327
|
...packs_available.slice(0, 5),
|
|
276
328
|
{ name: req.__("More..."), description: "" },
|
|
277
329
|
];
|
|
278
|
-
const tables = await Table.find({}, {
|
|
279
|
-
const views = await View.find({});
|
|
280
|
-
const pages = await Page.find({});
|
|
281
|
-
|
|
330
|
+
const tables = await Table.find({}, { cached: true });
|
|
331
|
+
const views = await View.find({}, { cached: true });
|
|
332
|
+
const pages = await Page.find({}, { cached: true });
|
|
333
|
+
const triggers = await Trigger.findAllWithTableName();
|
|
334
|
+
const users = await User.find({}, { orderBy: "id" });
|
|
335
|
+
const roles = await User.get_roles();
|
|
336
|
+
let roleMap = {};
|
|
337
|
+
roles.forEach((r) => {
|
|
338
|
+
roleMap[r.id] = r.role;
|
|
339
|
+
});
|
|
282
340
|
return {
|
|
283
341
|
above: [
|
|
284
342
|
{
|
|
@@ -293,75 +351,37 @@ const welcome_page = async (req) => {
|
|
|
293
351
|
{
|
|
294
352
|
type: "card",
|
|
295
353
|
//title: req.__("Install pack"),
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
{ label: req.__("Name"), key: "name" },
|
|
312
|
-
{
|
|
313
|
-
label: req.__("Description"),
|
|
314
|
-
key: "description",
|
|
315
|
-
},
|
|
316
|
-
],
|
|
317
|
-
packlist,
|
|
318
|
-
{ noHeader: true }
|
|
319
|
-
),
|
|
320
|
-
a(
|
|
321
|
-
{ href: `/plugins?set=packs`, class: "btn btn-primary" },
|
|
322
|
-
req.__("Go to pack store »")
|
|
323
|
-
)
|
|
324
|
-
),
|
|
325
|
-
Triggers: await actionsTab(req),
|
|
326
|
-
Files: await filesTab(req),
|
|
327
|
-
},
|
|
354
|
+
bodyClass: "py-0 pr-0",
|
|
355
|
+
class: "welcome-page-entity-list",
|
|
356
|
+
|
|
357
|
+
tabContents:
|
|
358
|
+
triggers.length > 0
|
|
359
|
+
? {
|
|
360
|
+
Triggers: await actionsTab(req, triggers),
|
|
361
|
+
Files: await filesTab(req),
|
|
362
|
+
Packs: packTab(req, packlist),
|
|
363
|
+
}
|
|
364
|
+
: {
|
|
365
|
+
Packs: packTab(req, packlist),
|
|
366
|
+
Triggers: await actionsTab(req, triggers),
|
|
367
|
+
Files: await filesTab(req),
|
|
368
|
+
},
|
|
328
369
|
},
|
|
329
370
|
{
|
|
330
371
|
type: "card",
|
|
331
372
|
//title: req.__("Learn"),
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
class: "btn btn-primary",
|
|
373
|
+
bodyClass: "py-0 pr-0",
|
|
374
|
+
class: "welcome-page-entity-list",
|
|
375
|
+
tabContents:
|
|
376
|
+
users.length > 4
|
|
377
|
+
? {
|
|
378
|
+
Users: await usersTab(req, users, roleMap),
|
|
379
|
+
Help: helpCard(req),
|
|
380
|
+
}
|
|
381
|
+
: {
|
|
382
|
+
Help: helpCard(req),
|
|
383
|
+
Users: await usersTab(req, users, roleMap),
|
|
344
384
|
},
|
|
345
|
-
req.__("Go to Wiki »")
|
|
346
|
-
),
|
|
347
|
-
p(req.__("The YouTube channel has some video tutorials")),
|
|
348
|
-
a(
|
|
349
|
-
{
|
|
350
|
-
href: `https://www.youtube.com/channel/UCBOpAcH8ep7ESbuocxcq0KQ`,
|
|
351
|
-
class: "btn btn-secondary",
|
|
352
|
-
},
|
|
353
|
-
req.__("Go to YouTube »")
|
|
354
|
-
),
|
|
355
|
-
div(
|
|
356
|
-
{ class: "mt-3" },
|
|
357
|
-
a(
|
|
358
|
-
{ href: `https://blog.saltcorn.com/` },
|
|
359
|
-
req.__("What's new? Read the blog »")
|
|
360
|
-
)
|
|
361
|
-
)
|
|
362
|
-
),
|
|
363
|
-
Users: await usersTab(req),
|
|
364
|
-
},
|
|
365
385
|
},
|
|
366
386
|
],
|
|
367
387
|
},
|
|
@@ -370,8 +390,8 @@ const welcome_page = async (req) => {
|
|
|
370
390
|
};
|
|
371
391
|
|
|
372
392
|
/**
|
|
373
|
-
* @param {object} req
|
|
374
|
-
* @param {object} res
|
|
393
|
+
* @param {object} req
|
|
394
|
+
* @param {object} res
|
|
375
395
|
* @returns {Promise<void>}
|
|
376
396
|
*/
|
|
377
397
|
const no_views_logged_in = async (req, res) => {
|
|
@@ -400,9 +420,9 @@ const no_views_logged_in = async (req, res) => {
|
|
|
400
420
|
};
|
|
401
421
|
|
|
402
422
|
/**
|
|
403
|
-
* @param {number} role_id
|
|
404
|
-
* @param {object} res
|
|
405
|
-
* @param {object} req
|
|
423
|
+
* @param {number} role_id
|
|
424
|
+
* @param {object} res
|
|
425
|
+
* @param {object} req
|
|
406
426
|
* @returns {Promise<boolean>}
|
|
407
427
|
*/
|
|
408
428
|
const get_config_response = async (role_id, res, req) => {
|
|
@@ -431,8 +451,8 @@ const get_config_response = async (role_id, res, req) => {
|
|
|
431
451
|
|
|
432
452
|
/**
|
|
433
453
|
* Function assigned to 'module.exports'.
|
|
434
|
-
* @param {object} req
|
|
435
|
-
* @param {object} res
|
|
454
|
+
* @param {object} req
|
|
455
|
+
* @param {object} res
|
|
436
456
|
* @returns {Promise<void>}
|
|
437
457
|
*/
|
|
438
458
|
module.exports = async (req, res) => {
|
package/routes/index.js
CHANGED
|
@@ -4,6 +4,43 @@
|
|
|
4
4
|
* @module routes/index
|
|
5
5
|
* @subcategory routes
|
|
6
6
|
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* All files in the routes module.
|
|
10
|
+
* @namespace routes_overview
|
|
11
|
+
* @property {module:routes/actions} actions
|
|
12
|
+
* @property {module:routes/admin} admin
|
|
13
|
+
* @property {module:routes/api} api
|
|
14
|
+
* @property {module:routes/config} config
|
|
15
|
+
* @property {module:routes/crashlog} crashlog
|
|
16
|
+
* @property {module:routes/delete} delete
|
|
17
|
+
* @property {module:routes/edit} edit
|
|
18
|
+
* @property {module:routes/eventlog} eventlog
|
|
19
|
+
* @property {module:routes/events} events
|
|
20
|
+
* @property {module:routes/fields} fields
|
|
21
|
+
* @property {module:routes/files} files
|
|
22
|
+
* @property {module:routes/homepage} homepage
|
|
23
|
+
* @property {module:routes/infoarch} infoarch
|
|
24
|
+
* @property {module:routes/library} library
|
|
25
|
+
* @property {module:routes/list} list
|
|
26
|
+
* @property {module:routes/menu} menu
|
|
27
|
+
* @property {module:routes/packs} packs
|
|
28
|
+
* @property {module:routes/page} page
|
|
29
|
+
* @property {module:routes/pageedit} pageedit
|
|
30
|
+
* @property {module:routes/plugins} plugins
|
|
31
|
+
* @property {module:routes/scapi} scapi
|
|
32
|
+
* @property {module:routes/search} search
|
|
33
|
+
* @property {module:routes/settings} settings
|
|
34
|
+
* @property {module:routes/tables} tables
|
|
35
|
+
* @property {module:routes/tenant} tenant
|
|
36
|
+
* @property {module:routes/utils} utils
|
|
37
|
+
* @property {module:routes/view} view
|
|
38
|
+
* @property {module:routes/viewedit} viewedit
|
|
39
|
+
*
|
|
40
|
+
* @category server
|
|
41
|
+
* @subcategory routes
|
|
42
|
+
*/
|
|
43
|
+
|
|
7
44
|
const table = require("./tables");
|
|
8
45
|
const field = require("./fields");
|
|
9
46
|
const list = require("./list");
|
package/routes/tables.js
CHANGED
|
@@ -347,8 +347,8 @@ router.get(
|
|
|
347
347
|
})
|
|
348
348
|
);
|
|
349
349
|
|
|
350
|
-
/**
|
|
351
|
-
* Create Table from CSV file (post)
|
|
350
|
+
/**
|
|
351
|
+
* Create Table from CSV file (post)
|
|
352
352
|
* @name post/create-from-csv
|
|
353
353
|
* @function
|
|
354
354
|
* @memberof module:routes/tables~tablesRouter
|
|
@@ -396,7 +396,7 @@ router.post(
|
|
|
396
396
|
})
|
|
397
397
|
);
|
|
398
398
|
|
|
399
|
-
/**
|
|
399
|
+
/**
|
|
400
400
|
* Show Relational Diagram (get)
|
|
401
401
|
* @name get/relationship-diagram
|
|
402
402
|
* @function
|
|
@@ -489,16 +489,16 @@ router.get(
|
|
|
489
489
|
);
|
|
490
490
|
|
|
491
491
|
/**
|
|
492
|
-
* @param {string} col
|
|
493
|
-
* @param {string} lbl
|
|
492
|
+
* @param {string} col
|
|
493
|
+
* @param {string} lbl
|
|
494
494
|
* @returns {string}
|
|
495
495
|
*/
|
|
496
496
|
const badge = (col, lbl) =>
|
|
497
497
|
`<span class="badge badge-${col}">${lbl}</span> `;
|
|
498
498
|
|
|
499
499
|
/**
|
|
500
|
-
* @param {object} f
|
|
501
|
-
* @param {object} req
|
|
500
|
+
* @param {object} f
|
|
501
|
+
* @param {object} req
|
|
502
502
|
* @returns {string}
|
|
503
503
|
*/
|
|
504
504
|
const typeBadges = (f, req) => {
|
|
@@ -512,7 +512,7 @@ const typeBadges = (f, req) => {
|
|
|
512
512
|
};
|
|
513
513
|
|
|
514
514
|
/**
|
|
515
|
-
* @param {object} f
|
|
515
|
+
* @param {object} f
|
|
516
516
|
* @returns {string}
|
|
517
517
|
*/
|
|
518
518
|
const attribBadges = (f) => {
|
|
@@ -526,7 +526,7 @@ const attribBadges = (f) => {
|
|
|
526
526
|
return s;
|
|
527
527
|
};
|
|
528
528
|
|
|
529
|
-
/**
|
|
529
|
+
/**
|
|
530
530
|
* Table Constructor (GET Handler)
|
|
531
531
|
* @name get/:idorname
|
|
532
532
|
* @function
|
|
@@ -762,6 +762,7 @@ router.get(
|
|
|
762
762
|
),
|
|
763
763
|
// rename table doesnt supported for sqlite
|
|
764
764
|
!db.isSQLite &&
|
|
765
|
+
table.name !== "users" &&
|
|
765
766
|
a(
|
|
766
767
|
{
|
|
767
768
|
class: "dropdown-item",
|
|
@@ -782,12 +783,13 @@ router.get(
|
|
|
782
783
|
req,
|
|
783
784
|
true
|
|
784
785
|
),
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
786
|
+
table.name !== "users" &&
|
|
787
|
+
post_dropdown_item(
|
|
788
|
+
`/table/forget-table/${table.id}`,
|
|
789
|
+
'<i class="fas fa-recycle"></i> ' + req.__("Forget table"),
|
|
790
|
+
req,
|
|
791
|
+
true
|
|
792
|
+
),
|
|
791
793
|
])
|
|
792
794
|
)
|
|
793
795
|
);
|
|
@@ -833,7 +835,7 @@ router.get(
|
|
|
833
835
|
})
|
|
834
836
|
);
|
|
835
837
|
|
|
836
|
-
/**
|
|
838
|
+
/**
|
|
837
839
|
* @name post
|
|
838
840
|
* @function
|
|
839
841
|
* @memberof module:routes/tables~tablesRouter
|
|
@@ -906,7 +908,7 @@ router.post(
|
|
|
906
908
|
})
|
|
907
909
|
);
|
|
908
910
|
|
|
909
|
-
/**
|
|
911
|
+
/**
|
|
910
912
|
* Delete Table Route Handler definition
|
|
911
913
|
* /delete:/id, where id is table id in _sc_tables
|
|
912
914
|
* @name post/delete/:id
|
|
@@ -1084,7 +1086,7 @@ router.get(
|
|
|
1084
1086
|
})
|
|
1085
1087
|
);
|
|
1086
1088
|
|
|
1087
|
-
/**
|
|
1089
|
+
/**
|
|
1088
1090
|
* Download CSV file
|
|
1089
1091
|
* @name get/download/:name
|
|
1090
1092
|
* @function
|
|
@@ -1190,7 +1192,7 @@ const constraintForm = (req, table_id, fields) =>
|
|
|
1190
1192
|
type: "Bool",
|
|
1191
1193
|
})),
|
|
1192
1194
|
});
|
|
1193
|
-
|
|
1195
|
+
|
|
1194
1196
|
/**
|
|
1195
1197
|
* Add constraint GET handler
|
|
1196
1198
|
* ${base_url}/table/add-constraint/:id
|
package/routes/tenant.js
CHANGED
|
@@ -34,7 +34,7 @@ const {
|
|
|
34
34
|
} = require("@saltcorn/markup/tags");
|
|
35
35
|
const db = require("@saltcorn/data/db");
|
|
36
36
|
const url = require("url");
|
|
37
|
-
const { loadAllPlugins } = require("../load_plugins");
|
|
37
|
+
const { loadAllPlugins, loadAndSaveNewPlugin } = require("../load_plugins");
|
|
38
38
|
const { setTenant, isAdmin, error_catcher } = require("./utils.js");
|
|
39
39
|
const User = require("@saltcorn/data/models/user");
|
|
40
40
|
const File = require("@saltcorn/data/models/file");
|
|
@@ -139,31 +139,37 @@ router.get(
|
|
|
139
139
|
"You are trying to create a tenant while connecting via an IP address rather than a domain. This will probably not work."
|
|
140
140
|
)
|
|
141
141
|
);
|
|
142
|
+
let create_tenant_warning = "";
|
|
142
143
|
if (getState().getConfig("create_tenant_warning"))
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
144
|
+
create_tenant_warning = div(
|
|
145
|
+
{
|
|
146
|
+
class: "alert alert-warning alert-dismissible fade show mt-5",
|
|
147
|
+
role: "alert",
|
|
148
|
+
},
|
|
149
|
+
h4(req.__("Warning")),
|
|
150
|
+
p(
|
|
151
|
+
req.__(
|
|
152
|
+
"Hosting on this site is provided for free and with no guarantee of availability or security of your application. "
|
|
153
|
+
) +
|
|
154
|
+
" " +
|
|
147
155
|
req.__(
|
|
148
|
-
"
|
|
156
|
+
"This facility is intended solely for you to evaluate the suitability of Saltcorn. "
|
|
149
157
|
) +
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
req.__(
|
|
160
|
-
'See <a href="https://github.com/saltcorn/saltcorn">GitHub repository</a> for instructions<p>'
|
|
161
|
-
)
|
|
162
|
-
)
|
|
158
|
+
" " +
|
|
159
|
+
req.__(
|
|
160
|
+
"If you would like to store private information that needs to be secure, please use self-hosted Saltcorn. "
|
|
161
|
+
) +
|
|
162
|
+
" " +
|
|
163
|
+
req.__(
|
|
164
|
+
'See <a href="https://github.com/saltcorn/saltcorn">GitHub repository</a> for instructions<p>'
|
|
165
|
+
)
|
|
166
|
+
)
|
|
163
167
|
);
|
|
168
|
+
|
|
164
169
|
res.sendWrap(
|
|
165
170
|
req.__("Create application"),
|
|
166
|
-
|
|
171
|
+
create_tenant_warning +
|
|
172
|
+
renderForm(tenant_form(req), req.csrfToken()) +
|
|
167
173
|
p(
|
|
168
174
|
{ class: "mt-2" },
|
|
169
175
|
req.__("To login to a previously created application, go to: "),
|
|
@@ -245,7 +251,19 @@ router.post(
|
|
|
245
251
|
);
|
|
246
252
|
} else {
|
|
247
253
|
const newurl = getNewURL(req, subdomain);
|
|
248
|
-
await create_tenant(
|
|
254
|
+
await create_tenant(
|
|
255
|
+
subdomain,
|
|
256
|
+
loadAllPlugins,
|
|
257
|
+
newurl,
|
|
258
|
+
false,
|
|
259
|
+
loadAndSaveNewPlugin
|
|
260
|
+
);
|
|
261
|
+
let new_url_create = newurl;
|
|
262
|
+
const hasTemplate = getState().getConfig("tenant_template");
|
|
263
|
+
if (hasTemplate) {
|
|
264
|
+
new_url_create += "auth/create_first_user";
|
|
265
|
+
}
|
|
266
|
+
|
|
249
267
|
res.sendWrap(
|
|
250
268
|
req.__("Create application"),
|
|
251
269
|
div(
|
|
@@ -253,14 +271,25 @@ router.post(
|
|
|
253
271
|
|
|
254
272
|
div(
|
|
255
273
|
{ class: "my-3", style: "font-size: 22px" },
|
|
256
|
-
a(
|
|
274
|
+
a(
|
|
275
|
+
{ href: new_url_create, class: "new-tenant-link" },
|
|
276
|
+
new_url_create
|
|
277
|
+
)
|
|
257
278
|
),
|
|
258
279
|
p(
|
|
259
280
|
req.__(
|
|
260
281
|
"Please click the above link now to create the first user."
|
|
261
282
|
) +
|
|
262
283
|
" " +
|
|
263
|
-
|
|
284
|
+
hasTemplate
|
|
285
|
+
? req.__(
|
|
286
|
+
'Use this link: <a href="%s">%s</a> to revisit your application at any time.',
|
|
287
|
+
newurl,
|
|
288
|
+
newurl
|
|
289
|
+
)
|
|
290
|
+
: req.__(
|
|
291
|
+
"Use this link to revisit your application at any time."
|
|
292
|
+
)
|
|
264
293
|
)
|
|
265
294
|
)
|
|
266
295
|
);
|
|
@@ -339,13 +368,17 @@ router.get(
|
|
|
339
368
|
);
|
|
340
369
|
|
|
341
370
|
/**
|
|
342
|
-
* @param {object} req
|
|
371
|
+
* @param {object} req
|
|
343
372
|
* @returns {Form}
|
|
344
373
|
*/
|
|
345
374
|
const tenant_settings_form = (req) =>
|
|
346
375
|
config_fields_form({
|
|
347
376
|
req,
|
|
348
|
-
field_names: [
|
|
377
|
+
field_names: [
|
|
378
|
+
"role_to_create_tenant",
|
|
379
|
+
"create_tenant_warning",
|
|
380
|
+
"tenant_template",
|
|
381
|
+
],
|
|
349
382
|
action: "/tenant/settings",
|
|
350
383
|
submitLabel: req.__("Save"),
|
|
351
384
|
});
|
package/routes/utils.js
CHANGED
package/routes/view.js
CHANGED
|
@@ -68,7 +68,7 @@ router.get(
|
|
|
68
68
|
what: req.__("View"),
|
|
69
69
|
url: `/viewedit/edit/${encodeURIComponent(view.name)}`,
|
|
70
70
|
contents,
|
|
71
|
-
req
|
|
71
|
+
req,
|
|
72
72
|
})
|
|
73
73
|
);
|
|
74
74
|
})
|
|
@@ -92,18 +92,18 @@ router.post(
|
|
|
92
92
|
res.send("");
|
|
93
93
|
return;
|
|
94
94
|
}
|
|
95
|
-
let query = {};
|
|
95
|
+
let query = req.body || {};
|
|
96
96
|
let row;
|
|
97
97
|
let table;
|
|
98
98
|
const sfs = await view.get_state_fields();
|
|
99
99
|
for (const sf of sfs) {
|
|
100
|
-
if (sf.required) {
|
|
100
|
+
if (sf.required && !query[sf.name]) {
|
|
101
101
|
if (!row) {
|
|
102
102
|
if (!table)
|
|
103
103
|
table = await Table.findOne(view.table_id || view.exttable_name);
|
|
104
104
|
row = await table.getRow({});
|
|
105
105
|
}
|
|
106
|
-
if(row) query[sf.name] = row[sf.name];
|
|
106
|
+
if (row) query[sf.name] = row[sf.name];
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
109
|
const contents = await view.run(query, { req, res });
|