Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions core/loadConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import _ from 'underscore';

import { console } from '../lib/Cluster.js';
import SaplingError from '../lib/SaplingError.js';
import Utils from '../lib/Utils.js';


/**
Expand All @@ -24,6 +25,7 @@ export async function digest() {
let config = {};

const argv = yargs(hideBin(process.argv)).argv;
const utils = new Utils();

/* Default configuration values */
const defaultConfig = {
Expand All @@ -36,7 +38,7 @@ export async function digest() {
hooks: 'hooks.json',
permissions: 'permissions.json',
extension: 'html',
secret: this.utils.randString(),
secret: utils.randString(),

Check failure

Code scanning / CodeQL

Insecure randomness

Cryptographically insecure [random value](1) in a security context.
showError: true,
strict: false,
limit: 100,
Expand All @@ -54,7 +56,7 @@ export async function digest() {
mail: {
host: process.env.MAIL_HOST || '',
port: process.env.MAIL_PORT || 465,
secure: this.utils.trueBoolean(process.env.MAIL_TLS) || true,
secure: utils.trueBoolean(process.env.MAIL_TLS) || true,
auth: {
user: process.env.MAIL_USER,
pass: process.env.MAIL_PASS,
Expand Down Expand Up @@ -86,7 +88,7 @@ export async function digest() {
const configPath = path.join(this.dir, this.configFile || 'config.json');

/* Load the configuration */
if (await this.utils.exists(configPath)) {
if (await utils.exists(configPath)) {
/* If we have a config file, let's load it */
const file = await fs.readFile(configPath);

Expand Down Expand Up @@ -122,7 +124,7 @@ export async function digest() {
/* Check if there's a separate production config */
const prodConfigPath = path.join(this.dir, (this.configFile && this.configFile.replace('.json', `.${process.env.NODE_ENV}.json`)) || `config.${process.env.NODE_ENV}.json`);

if (await this.utils.exists(prodConfigPath)) {
if (await utils.exists(prodConfigPath)) {
/* If we have a config file, let's load it */
const file = await fs.readFile(prodConfigPath);

Expand Down
9 changes: 6 additions & 3 deletions core/loadController.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import path from 'node:path';

import { console } from '../lib/Cluster.js';
import Templating from '../lib/Templating.js';
import Utils from '../lib/Utils.js';


/**
Expand All @@ -18,16 +19,18 @@ import Templating from '../lib/Templating.js';
export async function digest() {
let controller = {};

const utils = new Utils();

/* Generate a controller from the available views */
if ((this.config.autoRouting === 'on' || this.config.autoRouting === true) && this.config.viewsDir !== null) {
const viewsPath = path.join(this.dir, this.config.viewsDir);

if (await this.utils.exists(viewsPath)) {
if (await utils.exists(viewsPath)) {
const viewsLstat = await fs.lstat(viewsPath);

if (viewsLstat.isDirectory()) {
/* Load all views in the views directory */
const views = await this.utils.getFiles(viewsPath);
const views = await utils.getFiles(viewsPath);

/* Go through each view */
for (const view_ of views) {
Expand Down Expand Up @@ -68,7 +71,7 @@ export async function digest() {
const controllerPath = path.join(this.dir, this.config.routes || '');

/* Load the controller file */
if (await this.utils.exists(controllerPath)) {
if (await utils.exists(controllerPath)) {
const controllerLstat = await fs.lstat(controllerPath);

if (controllerLstat.isFile()) {
Expand Down
5 changes: 4 additions & 1 deletion core/loadHooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import path from 'node:path';
import { console } from '../lib/Cluster.js';
import Response from '../lib/Response.js';
import SaplingError from '../lib/SaplingError.js';
import Utils from '../lib/Utils.js';


/**
Expand All @@ -17,13 +18,15 @@ import SaplingError from '../lib/SaplingError.js';
* @returns {object} Hooks
*/
export async function digest() {
const utils = new Utils();

/* Location of the hooks file */
const hooksPath = path.join(this.dir, this.config.hooks);

const formattedHooks = {};

/* Load the hooks file */
if (await this.utils.exists(hooksPath)) {
if (await utils.exists(hooksPath)) {
/* If we have a hooks file, let's load it */
let file = null;
let hooks = {};
Expand Down
5 changes: 4 additions & 1 deletion core/loadModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import path from 'node:path';
import { console } from '../lib/Cluster.js';
import SaplingError from '../lib/SaplingError.js';
import Storage from '../lib/Storage.js';
import Utils from '../lib/Utils.js';


/**
Expand All @@ -17,12 +18,14 @@ import Storage from '../lib/Storage.js';
* @returns {object} Schema
*/
export async function digest() {
const utils = new Utils();

const modelPath = path.join(this.dir, this.config.modelsDir);
const schema = {};
let files = {};

/* Load all models in the model directory */
if (await this.utils.exists(modelPath)) {
if (await utils.exists(modelPath)) {
files = await fs.readdir(modelPath);
} else {
console.warn(`Models directory \`${modelPath}\` does not exist`);
Expand Down
70 changes: 35 additions & 35 deletions lib/Storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,38 +16,6 @@ import Response from './Response.js';
import Utils from './Utils.js';


/* Default user structure */
/* Extensible through a users model */
const userStructure = {
email: { type: 'String', minlen: 3, email: true, unique: true, required: true, identifiable: true },
password: { type: 'String', minlen: 3, required: true, access: { r: 'owner', w: 'owner' } },
_salt: { type: 'String', access: { r: 'owner', w: 'owner' } },
role: { type: 'String', values: ['admin', 'member'], default: 'member', access: { r: 'anyone', w: 'admin' } },
_authkey: { type: 'String', access: { r: 'owner', w: 'owner' } },
};


/* File uploads structure */
const uploadStructure = {
// URL to the full original file
url: { type: 'String', required: true },
// Type, one of "image", "document", "archive", "other"
type: { type: 'String', values: ['image', 'video', 'audio', 'document', 'archive', 'font', 'other'], default: 'other' },
// URL to a Sapling-generated thumbnail
// thumbnail_url: {type: "String"},
// Filesize of the original in bytes
filesize: { type: 'Number' },
// File extension as presented
extension: { type: 'String' },
// Detected mimetype
mimetype: { type: 'String' },
// Width in pixels for uploads of the "image" type
// width: {type: "Number"},
// Height in pixels for uploads of the "image" type
// height: {type: "Number"}
};


/**
* The Storage class
*/
Expand All @@ -58,6 +26,38 @@ export default class Storage {
db = null;


/* Default user structure */
/* Extensible through a users model */
userStructure = {
email: { type: 'String', minlen: 3, email: true, unique: true, required: true, identifiable: true },
password: { type: 'String', minlen: 3, required: true, access: { r: 'owner', w: 'owner' } },
_salt: { type: 'String', access: { r: 'owner', w: 'owner' } },
role: { type: 'String', values: ['admin', 'member'], default: 'member', access: { r: 'anyone', w: 'admin' } },
_authkey: { type: 'String', access: { r: 'owner', w: 'owner' } },
};


/* File uploads structure */
uploadStructure = {
// URL to the full original file
url: { type: 'String', required: true },
// Type, one of "image", "document", "archive", "other"
type: { type: 'String', values: ['image', 'video', 'audio', 'document', 'archive', 'font', 'other'], default: 'other' },
// URL to a Sapling-generated thumbnail
// thumbnail_url: {type: "String"},
// Filesize of the original in bytes
filesize: { type: 'Number' },
// File extension as presented
extension: { type: 'String' },
// Detected mimetype
mimetype: { type: 'String' },
// Width in pixels for uploads of the "image" type
// width: {type: "Number"},
// Height in pixels for uploads of the "image" type
// height: {type: "Number"}
};


/**
* Initialise the Storage class
*
Expand All @@ -72,15 +72,15 @@ export default class Storage {
/* Every app with storage needs a users collection */
if ('users' in this.schema) {
/* Allow customization of the structure */
_.defaults(this.schema.users, userStructure);
_.defaults(this.schema.users, this.userStructure);
} else {
this.schema.users = userStructure;
this.schema.users = this.userStructure;
}

/* Create uploads collection if uploads are enabled */
/* Cold override as this cannot be customised by a model */
if (this.app.uploads) {
this.schema.uploads = uploadStructure;
this.schema.uploads = this.uploadStructure;
}
}

Expand Down