@saltcorn/server 1.0.0-rc.1 → 1.0.0-rc.10
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/routes.js +4 -1
- package/help/index.js +2 -1
- package/load_plugins.js +1 -0
- package/locales/en.json +2 -1
- package/package.json +9 -9
- package/public/gridedit.js +3 -1
- package/public/saltcorn-builder.css +0 -7
- package/public/saltcorn-common.js +1 -1
- package/public/saltcorn.js +22 -5
- package/routes/actions.js +1 -1
- package/routes/api.js +36 -1
- package/routes/delete.js +4 -1
- package/routes/files.js +9 -2
- package/routes/list.js +1 -1
- package/routes/pageedit.js +2 -1
- package/routes/plugins.js +6 -5
- package/routes/sync.js +4 -7
- package/routes/viewedit.js +7 -4
- package/tests/api.test.js +29 -0
package/auth/routes.js
CHANGED
|
@@ -1133,7 +1133,10 @@ router.post(
|
|
|
1133
1133
|
}
|
|
1134
1134
|
if (getState().get2FApolicy(req.user) === "Mandatory") {
|
|
1135
1135
|
res.redirect("/auth/twofa/setup/totp");
|
|
1136
|
-
} else if (
|
|
1136
|
+
} else if (
|
|
1137
|
+
req.body.dest &&
|
|
1138
|
+
is_relative_url(decodeURIComponent(req.body.dest))
|
|
1139
|
+
) {
|
|
1137
1140
|
res.redirect(decodeURIComponent(req.body.dest));
|
|
1138
1141
|
} else res.redirect("/");
|
|
1139
1142
|
})
|
package/help/index.js
CHANGED
|
@@ -13,7 +13,8 @@ const { getState } = require("@saltcorn/data/db/state");
|
|
|
13
13
|
const { oneOf } = require("@saltcorn/types/generators");
|
|
14
14
|
const get_md_file = async (topic) => {
|
|
15
15
|
try {
|
|
16
|
-
const fp =
|
|
16
|
+
const fp = File.normalise_in_base(__dirname, `${topic}.tmd`);
|
|
17
|
+
if (!fp) return false;
|
|
17
18
|
const fileBuf = await fs.readFile(fp);
|
|
18
19
|
return fileBuf.toString();
|
|
19
20
|
} catch (e) {
|
package/load_plugins.js
CHANGED
|
@@ -231,6 +231,7 @@ const loadAndSaveNewPlugin = async (
|
|
|
231
231
|
const loadMsgs = [];
|
|
232
232
|
const loader = new PluginInstaller(plugin, {
|
|
233
233
|
scVersion: packagejson.version,
|
|
234
|
+
envVars: { PUPPETEER_SKIP_DOWNLOAD: "1" },
|
|
234
235
|
});
|
|
235
236
|
const { version, plugin_module, location, loadedWithReload, msgs } =
|
|
236
237
|
await loader.install(force);
|
package/locales/en.json
CHANGED
|
@@ -1476,5 +1476,6 @@
|
|
|
1476
1476
|
"clean node_modules": "clean node_modules",
|
|
1477
1477
|
"After delete": "After delete",
|
|
1478
1478
|
"Search only on exact match, not substring match. Useful for large tables": "Search only on exact match, not substring match. Useful for large tables",
|
|
1479
|
-
"Please select an entry point.": "Please select an entry point."
|
|
1479
|
+
"Please select an entry point.": "Please select an entry point.",
|
|
1480
|
+
"Group by": "Group by"
|
|
1480
1481
|
}
|
package/package.json
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saltcorn/server",
|
|
3
|
-
"version": "1.0.0-rc.
|
|
3
|
+
"version": "1.0.0-rc.10",
|
|
4
4
|
"description": "Server app for Saltcorn, open-source no-code platform",
|
|
5
5
|
"homepage": "https://saltcorn.com",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"dependencies": {
|
|
9
9
|
"@aws-sdk/client-s3": "^3.451.0",
|
|
10
|
-
"@saltcorn/base-plugin": "1.0.0-rc.
|
|
11
|
-
"@saltcorn/builder": "1.0.0-rc.
|
|
12
|
-
"@saltcorn/data": "1.0.0-rc.
|
|
13
|
-
"@saltcorn/admin-models": "1.0.0-rc.
|
|
14
|
-
"@saltcorn/filemanager": "1.0.0-rc.
|
|
15
|
-
"@saltcorn/markup": "1.0.0-rc.
|
|
16
|
-
"@saltcorn/plugins-loader": "1.0.0-rc.
|
|
17
|
-
"@saltcorn/sbadmin2": "1.0.0-rc.
|
|
10
|
+
"@saltcorn/base-plugin": "1.0.0-rc.10",
|
|
11
|
+
"@saltcorn/builder": "1.0.0-rc.10",
|
|
12
|
+
"@saltcorn/data": "1.0.0-rc.10",
|
|
13
|
+
"@saltcorn/admin-models": "1.0.0-rc.10",
|
|
14
|
+
"@saltcorn/filemanager": "1.0.0-rc.10",
|
|
15
|
+
"@saltcorn/markup": "1.0.0-rc.10",
|
|
16
|
+
"@saltcorn/plugins-loader": "1.0.0-rc.10",
|
|
17
|
+
"@saltcorn/sbadmin2": "1.0.0-rc.10",
|
|
18
18
|
"@socket.io/cluster-adapter": "^0.2.1",
|
|
19
19
|
"@socket.io/sticky": "^1.0.1",
|
|
20
20
|
"adm-zip": "0.5.10",
|
package/public/gridedit.js
CHANGED
|
@@ -87,7 +87,9 @@ function isoDateFormatter(cell, formatterParams, onRendered) {
|
|
|
87
87
|
if (formatterParams && formatterParams.format)
|
|
88
88
|
return dayjs(val).format(formatterParams.format);
|
|
89
89
|
|
|
90
|
-
return new Date(val).toLocaleDateString(window.detected_locale || "en"
|
|
90
|
+
return new Date(val).toLocaleDateString(window.detected_locale || "en", {
|
|
91
|
+
timeZone: "UTC",
|
|
92
|
+
});
|
|
91
93
|
}
|
|
92
94
|
function colorFormatter(cell, formatterParams, onRendered) {
|
|
93
95
|
const val = cell.getValue();
|
|
@@ -525,10 +525,3 @@ div.componets-and-library-accordion {
|
|
|
525
525
|
.toolbox-card:nth-child(2) {
|
|
526
526
|
margin-bottom: 0px;
|
|
527
527
|
}
|
|
528
|
-
#builder-main-canvas {
|
|
529
|
-
height: calc(100dvh - 50px) !important;
|
|
530
|
-
min-height: 600px;
|
|
531
|
-
}
|
|
532
|
-
#builder-main-canvas.h-100 {
|
|
533
|
-
height: 100% !important;
|
|
534
|
-
}
|
|
@@ -1352,7 +1352,7 @@ function buildToast(txt, type, spin) {
|
|
|
1352
1352
|
role="alert"
|
|
1353
1353
|
aria-live="assertive"
|
|
1354
1354
|
aria-atomic="true"
|
|
1355
|
-
style="min-width: 350px; max-width: 50vw; width: auto; z-index:
|
|
1355
|
+
style="min-width: 350px; max-width: 50vw; width: auto; z-index: 9999; ${
|
|
1356
1356
|
!isNode ? "transform: translateX(-50%);" : ""
|
|
1357
1357
|
}"
|
|
1358
1358
|
>
|
package/public/saltcorn.js
CHANGED
|
@@ -350,16 +350,18 @@ function expand_thumbnail(img_id, filename) {
|
|
|
350
350
|
}
|
|
351
351
|
|
|
352
352
|
function ajax_modal(url, opts = {}) {
|
|
353
|
-
ensure_modal_exists_and_closed();
|
|
354
|
-
$("#scmodal").removeClass("no-submit-reload");
|
|
355
|
-
$("#scmodal").attr("data-on-close-reload-view", opts.reload_view || null);
|
|
356
|
-
|
|
357
|
-
if (opts.submitReload === false) $("#scmodal").addClass("no-submit-reload");
|
|
358
353
|
$.ajax(url, {
|
|
359
354
|
headers: {
|
|
360
355
|
SaltcornModalRequest: "true",
|
|
361
356
|
},
|
|
362
357
|
success: function (res, textStatus, request) {
|
|
358
|
+
ensure_modal_exists_and_closed();
|
|
359
|
+
$("#scmodal").removeClass("no-submit-reload");
|
|
360
|
+
$("#scmodal").attr("data-on-close-reload-view", opts.reload_view || null);
|
|
361
|
+
|
|
362
|
+
if (opts.submitReload === false)
|
|
363
|
+
$("#scmodal").addClass("no-submit-reload");
|
|
364
|
+
|
|
363
365
|
var title = request.getResponseHeader("Page-Title");
|
|
364
366
|
var width = request.getResponseHeader("SaltcornModalWidth");
|
|
365
367
|
var minwidth = request.getResponseHeader("SaltcornModalMinWidth");
|
|
@@ -430,6 +432,20 @@ function saveAndContinue(e, k, event) {
|
|
|
430
432
|
)
|
|
431
433
|
return;
|
|
432
434
|
var form = $(e).closest("form");
|
|
435
|
+
let focusedEl = null;
|
|
436
|
+
if (!event || !event.srcElement) {
|
|
437
|
+
const el = form.find("select[sc-received-focus]")[0];
|
|
438
|
+
if (el) {
|
|
439
|
+
el.removeAttribute("sc-received-focus");
|
|
440
|
+
if (el.getAttribute("previous-val") === el.value) return;
|
|
441
|
+
}
|
|
442
|
+
} else if (
|
|
443
|
+
event.srcElement.tagName === "SELECT" &&
|
|
444
|
+
event.srcElement.getAttribute("previous-val") !== undefined
|
|
445
|
+
) {
|
|
446
|
+
focusedEl = event.srcElement;
|
|
447
|
+
}
|
|
448
|
+
|
|
433
449
|
const valres = form[0].reportValidity();
|
|
434
450
|
if (!valres) return;
|
|
435
451
|
submitWithEmptyAction(form[0]);
|
|
@@ -452,6 +468,7 @@ function saveAndContinue(e, k, event) {
|
|
|
452
468
|
reloadEmbeddedEditOwnViews(form, res.id);
|
|
453
469
|
}
|
|
454
470
|
common_done(res, form.attr("data-viewname"));
|
|
471
|
+
if (focusedEl) focusedEl.setAttribute("previous-val", focusedEl.value);
|
|
455
472
|
},
|
|
456
473
|
error: function (request) {
|
|
457
474
|
var ct = request.getResponseHeader("content-type") || "";
|
package/routes/actions.js
CHANGED
|
@@ -755,7 +755,7 @@ router.post(
|
|
|
755
755
|
req.flash("success", req.__("Action configuration saved"));
|
|
756
756
|
res.redirect(
|
|
757
757
|
req.query.on_done_redirect &&
|
|
758
|
-
is_relative_url(req.query.on_done_redirect)
|
|
758
|
+
is_relative_url("/" + req.query.on_done_redirect)
|
|
759
759
|
? `/${req.query.on_done_redirect}`
|
|
760
760
|
: "/actions/"
|
|
761
761
|
);
|
package/routes/api.js
CHANGED
|
@@ -27,6 +27,7 @@ const Table = require("@saltcorn/data/models/table");
|
|
|
27
27
|
const View = require("@saltcorn/data/models/view");
|
|
28
28
|
//const Field = require("@saltcorn/data/models/field");
|
|
29
29
|
const Trigger = require("@saltcorn/data/models/trigger");
|
|
30
|
+
const File = require("@saltcorn/data/models/file");
|
|
30
31
|
//const load_plugins = require("../load_plugins");
|
|
31
32
|
const passport = require("passport");
|
|
32
33
|
|
|
@@ -189,6 +190,39 @@ router.post(
|
|
|
189
190
|
)(req, res, next);
|
|
190
191
|
})
|
|
191
192
|
);
|
|
193
|
+
|
|
194
|
+
router.get(
|
|
195
|
+
"/serve-files/*",
|
|
196
|
+
//passport.authenticate("api-bearer", { session: false }),
|
|
197
|
+
error_catcher(async (req, res, next) => {
|
|
198
|
+
await passport.authenticate(
|
|
199
|
+
"api-bearer",
|
|
200
|
+
{ session: false },
|
|
201
|
+
async function (err, user, info) {
|
|
202
|
+
const role = req?.user?.role_id || user?.role_id || 100;
|
|
203
|
+
const user_id = req?.user?.id || user?.id;
|
|
204
|
+
const serve_path = req.params[0];
|
|
205
|
+
const file = await File.findOne(serve_path);
|
|
206
|
+
if (
|
|
207
|
+
file &&
|
|
208
|
+
(role <= file.min_role_read || (user_id && user_id === file.user_id))
|
|
209
|
+
) {
|
|
210
|
+
res.type(file.mimetype);
|
|
211
|
+
const cacheability =
|
|
212
|
+
file.min_role_read === 100 ? "public" : "private";
|
|
213
|
+
const maxAge = getState().getConfig("files_cache_maxage", 86400);
|
|
214
|
+
res.set("Cache-Control", `${cacheability}, max-age=${maxAge}`);
|
|
215
|
+
if (file.s3_store)
|
|
216
|
+
res.status(404).json({ error: req.__("Not found") });
|
|
217
|
+
else res.sendFile(file.location);
|
|
218
|
+
} else {
|
|
219
|
+
res.status(404).json({ error: req.__("Not found") });
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
)(req, res, next);
|
|
223
|
+
})
|
|
224
|
+
);
|
|
225
|
+
|
|
192
226
|
/**
|
|
193
227
|
*
|
|
194
228
|
*/
|
|
@@ -294,11 +328,12 @@ router.get(
|
|
|
294
328
|
} else {
|
|
295
329
|
const tbl_fields = table.getFields();
|
|
296
330
|
readState(req_query, tbl_fields, req);
|
|
297
|
-
const qstate =
|
|
331
|
+
const qstate = stateFieldsToWhere({
|
|
298
332
|
fields: tbl_fields,
|
|
299
333
|
approximate: !!approximate,
|
|
300
334
|
state: req_query,
|
|
301
335
|
table,
|
|
336
|
+
prefix: "a.",
|
|
302
337
|
});
|
|
303
338
|
const joinFields = {};
|
|
304
339
|
const derefs = Array.isArray(dereference)
|
package/routes/delete.js
CHANGED
|
@@ -38,7 +38,10 @@ router.post(
|
|
|
38
38
|
try {
|
|
39
39
|
if (role <= table.min_role_write)
|
|
40
40
|
await table.deleteRows({ id }, req.user || { role_id: 100 });
|
|
41
|
-
else if (
|
|
41
|
+
else if (
|
|
42
|
+
(table.ownership_field_id || table.ownership_formula) &&
|
|
43
|
+
req.user
|
|
44
|
+
) {
|
|
42
45
|
const row = await table.getRow(
|
|
43
46
|
{ id },
|
|
44
47
|
{ forUser: req.user, forPublic: !req.user }
|
package/routes/files.js
CHANGED
|
@@ -94,11 +94,15 @@ router.get(
|
|
|
94
94
|
const { dir, no_subdirs } = req.query;
|
|
95
95
|
const noSubdirs = no_subdirs === "true";
|
|
96
96
|
const safeDir = File.normalise(dir || "/");
|
|
97
|
-
const absFolder =
|
|
97
|
+
const absFolder = File.normalise_in_base(
|
|
98
98
|
db.connectObj.file_store,
|
|
99
99
|
db.getTenantSchema(),
|
|
100
|
-
|
|
100
|
+
dir || "/"
|
|
101
101
|
);
|
|
102
|
+
if (absFolder === null) {
|
|
103
|
+
res.json({ error: "Invalid path" });
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
102
106
|
const dirOnDisk = await File.from_file_on_disk(
|
|
103
107
|
path.basename(absFolder),
|
|
104
108
|
path.dirname(absFolder)
|
|
@@ -594,6 +598,9 @@ router.get(
|
|
|
594
598
|
isAdmin,
|
|
595
599
|
error_catcher(async (req, res) => {
|
|
596
600
|
const form = await storage_form(req);
|
|
601
|
+
form.blurb = [
|
|
602
|
+
`<div class="alert alert-warning">S3 storage options may not work for this release. Enabling S3 storage is not recommended</div>`,
|
|
603
|
+
];
|
|
597
604
|
send_files_page({
|
|
598
605
|
res,
|
|
599
606
|
req,
|
package/routes/list.js
CHANGED
|
@@ -411,7 +411,7 @@ router.get(
|
|
|
411
411
|
ajax_indicator(false);
|
|
412
412
|
//if (item._versions) item._versions = +item._versions + 1;
|
|
413
413
|
//data.resolve(fixKeys(item));
|
|
414
|
-
if(resp.success &&typeof resp.success ==="number" && !row.id) {
|
|
414
|
+
if(resp.success &&(typeof resp.success ==="number" || typeof resp.success ==="string") && !row.id) {
|
|
415
415
|
window.tabulator_table.updateRow(cell.getRow(), {id: resp.success});
|
|
416
416
|
}
|
|
417
417
|
|
package/routes/pageedit.js
CHANGED
|
@@ -648,7 +648,8 @@ router.post(
|
|
|
648
648
|
const { pagename } = req.params;
|
|
649
649
|
|
|
650
650
|
let redirectTarget =
|
|
651
|
-
req.query.on_done_redirect &&
|
|
651
|
+
req.query.on_done_redirect &&
|
|
652
|
+
is_relative_url("/" + req.query.on_done_redirect)
|
|
652
653
|
? `/${req.query.on_done_redirect}`
|
|
653
654
|
: "/pageedit";
|
|
654
655
|
const page = await Page.findOne({ name: pagename });
|
package/routes/plugins.js
CHANGED
|
@@ -899,12 +899,13 @@ router.post(
|
|
|
899
899
|
};
|
|
900
900
|
await plugin.upsert();
|
|
901
901
|
await load_plugins.loadPlugin(plugin);
|
|
902
|
+
|
|
903
|
+
getState().processSend({
|
|
904
|
+
refresh_plugin_cfg: plugin.name,
|
|
905
|
+
tenant: db.getTenantSchema(),
|
|
906
|
+
});
|
|
907
|
+
res.json({ success: "ok" });
|
|
902
908
|
}
|
|
903
|
-
getState().processSend({
|
|
904
|
-
refresh_plugin_cfg: plugin.name,
|
|
905
|
-
tenant: db.getTenantSchema(),
|
|
906
|
-
});
|
|
907
|
-
res.json({ success: "ok" });
|
|
908
909
|
}
|
|
909
910
|
})
|
|
910
911
|
);
|
package/routes/sync.js
CHANGED
|
@@ -335,16 +335,13 @@ router.post(
|
|
|
335
335
|
"/clean_sync_dir",
|
|
336
336
|
error_catcher(async (req, res) => {
|
|
337
337
|
const { dir_name } = req.body;
|
|
338
|
-
const safe_dir_name = File.normalise(dir_name);
|
|
339
338
|
try {
|
|
340
339
|
const rootFolder = await File.rootFolder();
|
|
341
|
-
const syncDir =
|
|
342
|
-
rootFolder.location,
|
|
343
|
-
|
|
344
|
-
"sync",
|
|
345
|
-
safe_dir_name
|
|
340
|
+
const syncDir = File.normalise_in_base(
|
|
341
|
+
path.join(rootFolder.location, "mobile_app", "sync"),
|
|
342
|
+
dir_name
|
|
346
343
|
);
|
|
347
|
-
await fs.rm(syncDir, { recursive: true, force: true });
|
|
344
|
+
if (syncDir) await fs.rm(syncDir, { recursive: true, force: true });
|
|
348
345
|
res.status(200).send("");
|
|
349
346
|
} catch (error) {
|
|
350
347
|
getState().log(2, `POST /sync/clean_sync_dir: '${error.message}'`);
|
package/routes/viewedit.js
CHANGED
|
@@ -766,7 +766,8 @@ router.post(
|
|
|
766
766
|
)
|
|
767
767
|
);
|
|
768
768
|
let redirectTarget =
|
|
769
|
-
req.query.on_done_redirect &&
|
|
769
|
+
req.query.on_done_redirect &&
|
|
770
|
+
is_relative_url("/" + req.query.on_done_redirect)
|
|
770
771
|
? `/${req.query.on_done_redirect}`
|
|
771
772
|
: "/viewedit";
|
|
772
773
|
res.redirect(redirectTarget);
|
|
@@ -791,7 +792,8 @@ router.post(
|
|
|
791
792
|
req.__("View %s duplicated as %s", view.name, newview.name)
|
|
792
793
|
);
|
|
793
794
|
let redirectTarget =
|
|
794
|
-
req.query.on_done_redirect &&
|
|
795
|
+
req.query.on_done_redirect &&
|
|
796
|
+
is_relative_url("/" + req.query.on_done_redirect)
|
|
795
797
|
? `/${req.query.on_done_redirect}`
|
|
796
798
|
: "/viewedit";
|
|
797
799
|
res.redirect(redirectTarget);
|
|
@@ -812,7 +814,8 @@ router.post(
|
|
|
812
814
|
await View.delete({ id });
|
|
813
815
|
req.flash("success", req.__("View deleted"));
|
|
814
816
|
let redirectTarget =
|
|
815
|
-
req.query.on_done_redirect &&
|
|
817
|
+
req.query.on_done_redirect &&
|
|
818
|
+
is_relative_url("/" + req.query.on_done_redirect)
|
|
816
819
|
? `/${req.query.on_done_redirect}`
|
|
817
820
|
: "/viewedit";
|
|
818
821
|
res.redirect(redirectTarget);
|
|
@@ -910,7 +913,7 @@ router.post(
|
|
|
910
913
|
req.flash("success", message);
|
|
911
914
|
let redirectTarget =
|
|
912
915
|
req.query.on_done_redirect &&
|
|
913
|
-
is_relative_url(req.query.on_done_redirect)
|
|
916
|
+
is_relative_url("/" + req.query.on_done_redirect)
|
|
914
917
|
? `/${req.query.on_done_redirect}`
|
|
915
918
|
: "/viewedit";
|
|
916
919
|
res.redirect(redirectTarget);
|
package/tests/api.test.js
CHANGED
|
@@ -2,6 +2,8 @@ const request = require("supertest");
|
|
|
2
2
|
const getApp = require("../app");
|
|
3
3
|
const Table = require("@saltcorn/data/models/table");
|
|
4
4
|
const Trigger = require("@saltcorn/data/models/trigger");
|
|
5
|
+
const File = require("@saltcorn/data/models/file");
|
|
6
|
+
const fs = require("fs").promises;
|
|
5
7
|
|
|
6
8
|
const Field = require("@saltcorn/data/models/field");
|
|
7
9
|
const {
|
|
@@ -19,6 +21,19 @@ const User = require("@saltcorn/data/models/user");
|
|
|
19
21
|
|
|
20
22
|
beforeAll(async () => {
|
|
21
23
|
await resetToFixtures();
|
|
24
|
+
await File.ensure_file_store();
|
|
25
|
+
await File.from_req_files(
|
|
26
|
+
{
|
|
27
|
+
mimetype: "image/png",
|
|
28
|
+
name: "rick1.png",
|
|
29
|
+
mv: async (fnm) => {
|
|
30
|
+
await fs.writeFile(fnm, "nevergonnagiveyouup");
|
|
31
|
+
},
|
|
32
|
+
size: 245752,
|
|
33
|
+
},
|
|
34
|
+
1,
|
|
35
|
+
80
|
|
36
|
+
);
|
|
22
37
|
});
|
|
23
38
|
afterAll(db.close);
|
|
24
39
|
|
|
@@ -352,6 +367,20 @@ describe("API authentication", () => {
|
|
|
352
367
|
|
|
353
368
|
.expect(succeedJsonWith((rows) => rows.length == 2));
|
|
354
369
|
});
|
|
370
|
+
it("should not show file to public", async () => {
|
|
371
|
+
const app = await getApp();
|
|
372
|
+
await request(app)
|
|
373
|
+
.get("/api/serve-files/rick1.png")
|
|
374
|
+
.expect(respondJsonWith(404, (b) => b.error === "Not found"));
|
|
375
|
+
});
|
|
376
|
+
it("should show file to user", async () => {
|
|
377
|
+
const app = await getApp();
|
|
378
|
+
const u = await User.findOne({ id: 1 });
|
|
379
|
+
await request(app)
|
|
380
|
+
.get("/api/serve-files/rick1.png")
|
|
381
|
+
.set("Authorization", "Bearer " + u.api_token)
|
|
382
|
+
.expect(200);
|
|
383
|
+
});
|
|
355
384
|
});
|
|
356
385
|
|
|
357
386
|
describe("API action", () => {
|