More development

This commit is contained in:
Jonatan Nilsson 2022-04-05 16:47:24 +00:00
parent f35c195680
commit a2b1fc9bc8
13 changed files with 114 additions and 208 deletions

1
.gitignore vendored
View file

@ -59,6 +59,7 @@ typings/
# Local development config file # Local development config file
config/config.json config/config.json
config.json
package-lock.json package-lock.json
public/assets/app.js public/assets/app.js
public/assets/app.css public/assets/app.css

View file

@ -149,122 +149,6 @@ Article.prototype = createPrototype({
is_featured: false, is_featured: false,
}) })
}, },
/*parent() {
return this.belongsTo(Page, 'parent_id')
},
banner() {
return this.belongsTo(Media, 'banner_id')
},
media() {
return this.belongsTo(Media, 'media_id')
},
staff() {
return this.belongsTo(Staff, 'staff_id')
},
files() {
return this.hasManyFiltered(File, 'file', 'article_id')
.query(qb => {
qb.orderBy('id', 'asc')
})
},*/
/*getAll(ctx, where = {}, withRelated = [], orderBy = 'id', limitToday = false) {
return this.query(qb => {
this.baseQueryAll(ctx, qb, where, orderBy)
if (limitToday) {
qb.where('published_at', '<=', (new Date()).toISOString())
}
})
.fetchPage({
pageSize: ctx.state.pagination.perPage,
page: ctx.state.pagination.page,
withRelated,
ctx: ctx,
})
.then(result => {
ctx.state.pagination.total = result.pagination.rowCount
return result
})
},
getSingle(id, withRelated = [], require = true, ctx = null, limitToday = false) {
return this.query(qb => {
qb.where(subq => {
subq.where({ id: Number(id) || 0 })
.orWhere({ path: id })
})
if (limitToday && (!ctx || !ctx.state.user || ctx.state.user.level < 10)) {
qb.where('published_at', '<=', (new Date()).toISOString())
}
})
.fetch({ require, withRelated, ctx })
},
async getFeatured(withRelated = [], ctx = null) {
let data = await this.query(qb => {
qb.where({ is_featured: true })
.where('published_at', '<=', (new Date()).toISOString())
})
.fetch({ require: false, withRelated, ctx })
if (!data) {
data = await this.query(qb => {
qb.where('published_at', '<=', (new Date()).toISOString())
.whereNotNull('banner_id')
})
.fetch({ require: false, withRelated, ctx })
}
return data
},
getAllFromPage(ctx, pageId, withRelated = [], orderBy = 'id', limitToday = false) {
return this.query(qb => {
this.baseQueryAll(ctx, qb, {}, orderBy)
qb.leftOuterJoin('pages', 'articles.parent_id', 'pages.id')
qb.where(subq => {
subq.where('pages.id', pageId)
.orWhere('pages.parent_id', pageId)
})
if (limitToday) {
qb.where('published_at', '<=', (new Date()).toISOString())
}
qb.select('articles.*')
})
.fetchPage({
pageSize: ctx.state.pagination.perPage,
page: ctx.state.pagination.page,
withRelated,
ctx: ctx,
})
.then(result => {
ctx.state.pagination.total = result.pagination.rowCount
return result
})
},
setAllUnfeatured() {
return bookshelf.knex('articles')
.where({ is_featured: true })
.update({
is_featured: false,
})
},
getFrontpageArticles(page = 1) {
return this.query(qb => {
qb.orderBy('published_at', 'DESC')
.where('published_at', '<=', (new Date()).toISOString())
})
.fetchPage({
pageSize: 10,
page: page,
withRelated: ['files', 'media', 'banner', 'parent', 'staff'],
})
},*/
}) })
const articleInstance = new Article() const articleInstance = new Article()

View file

@ -46,45 +46,44 @@ nconf.env({
}) })
// Load package.json for name and such // Load empty overrides that can be overwritten later
let pckg = JSON.parse(readFileSync('./package.json')) nconf.overrides({})
pckg = _.pick(pckg, ['name', 'version', 'description', 'author', 'license', 'homepage']) nconf.defaults({
"NODE_ENV": "development",
if (nconf.get('DATABASE_URL')) { "knex": {
pckg.knex = { connection: nconf.get('DATABASE_URL') } "client": "pg",
} "connection": {
"host" : "127.0.0.1",
// Load overrides as second priority "user" : "postgres",
nconf.overrides(pckg) "password" : "postgres",
"database" : "nfpmoe"
},
// Load any overrides from the appropriate config file "connectionslave": null,
let configFile = 'config/config.json' "migrations": {
},
/* istanbul ignore else */ "acquireConnectionTimeout": 10000
if (nconf.get('NODE_ENV') === 'test') { },
configFile = 'config/config.test.json' "frontend": {
} "url": "http://beta01.nfp.moe"
},
/* istanbul ignore if */ "jwt": {
if (nconf.get('NODE_ENV') === 'production') { "secret": "this-is-my-secret",
configFile = 'config/config.production.json' "options": {
} "expiresIn": 604800
}
nconf.file('main', configFile) },
"sessionsecret": "this-is-session-secret-lol",
// Load defaults "bcrypt": 5,
nconf.file('default', 'config/config.default.json') "fileSize": 524288000,
"upload": {
"baseurl": "https://cdn.nfp.is",
// Final sanity checks "port": "2111",
/* istanbul ignore if */ "host": "storage01.nfp.is",
if (typeof global.it === 'function' & !nconf.inTest()) { "name": "nfpmoe-dev",
// eslint-disable-next-line no-console "secret": "nfpmoe-dev"
console.log('Critical: potentially running test on production enviroment. Shutting down.') }
process.exit(1) })
}
export default nconf export default nconf

View file

@ -3,7 +3,6 @@ import knexCore from 'knex-core'
import config from './config.mjs' import config from './config.mjs'
import defaults from './defaults.mjs' import defaults from './defaults.mjs'
import log from './log.mjs'
const knex = knexCore(config.get('knex')) const knex = knexCore(config.get('knex'))
@ -73,14 +72,24 @@ export function createPrototype(opts) {
}, },
async getAllQuery(query, queryContext = null) { async getAllQuery(query, queryContext = null) {
console.log('1')
let context = (queryContext || query).queryContext() let context = (queryContext || query).queryContext()
if (!context.tables) throw new Error('getAll was called before query') if (!context.tables) throw new Error('getAll was called before query')
let tables = context.tables let tables = context.tables
let tableMap = new Map(tables) let tableMap = new Map(tables)
try {
console.log(query)
console.log(query.toString())
let data = await query let data = await query
} catch (err) {
console.log(err)
throw err
}
console.log('3')
if (data.length === 0) { if (data.length === 0) {
console.log('e1')
return data return data
} }
@ -176,6 +185,8 @@ export function createPrototype(opts) {
} }
} }
console.log('2')
return out return out
}, },

View file

@ -1,28 +0,0 @@
import bunyan from 'bunyan-lite'
import config from './config.mjs'
import * as defaults from './defaults.mjs'
// Clone the settings as we will be touching
// on them slightly.
let settings = defaults.default(config.get('bunyan'))
// Replace any instance of 'process.stdout' with the
// actual reference to the process.stdout.
for (let i = 0; i < settings.streams.length; i++) {
/* istanbul ignore else */
if (settings.streams[i].stream === 'process.stdout') {
settings.streams[i].stream = process.stdout
}
}
// Create our logger.
const log = bunyan.createLogger(settings)
export default log
log.logMiddleware = () =>
(ctx, next) => {
ctx.log = log
return next()
}

View file

@ -25,7 +25,7 @@ export default class PageRoutes {
async getSinglePage(ctx) { async getSinglePage(ctx) {
await this.security.ensureIncludes(ctx) await this.security.ensureIncludes(ctx)
ctx.body = await this.Page.getSingle(ctx.params.id, ctx.state.filter.includes, true, ctx) ctx.body = await this.Page.getSingle(ctx.params.pageId, ctx.state.filter.includes, true, ctx)
} }
/** POST: /api/pages */ /** POST: /api/pages */

View file

@ -11,11 +11,9 @@ export default class ParserMiddleware {
} }
contextParser() { contextParser() {
return (ctx, next) => { return (ctx) => {
ctx.state.pagination = this.pagination.parsePagination(ctx) ctx.state.pagination = this.pagination.parsePagination(ctx)
ctx.state.filter = this.pagination.parseFilter(ctx) ctx.state.filter = this.pagination.parseFilter(ctx)
return next()
} }
} }

View file

@ -1,6 +1,11 @@
import path from 'path' import path from 'path'
import fs from 'fs/promises' import fs from 'fs/promises'
import { Flaska, FileResponse, HttpError } from 'flaska' import { Flaska, FileResponse, HttpError, QueryHandler } from 'flaska'
import config from './config.mjs'
import PageRoutes from './page/routes.mjs'
import ArticleRoutes from './article/routes.mjs'
import ParserMiddleware from './parser/middleware.mjs'
export function run(http, port, core) { export function run(http, port, core) {
let localUtil = new core.sc.Util(import.meta.url) let localUtil = new core.sc.Util(import.meta.url)
@ -8,11 +13,29 @@ export function run(http, port, core) {
const flaska = new Flaska({ const flaska = new Flaska({
log: core.log, log: core.log,
nonce: ['script-src'],
nonceCacheLength: 50,
defaultHeaders: {
'Server': 'Flaska',
'X-Content-Type-Options': 'nosniff',
'Content-Security-Policy': `default-src 'self'; style-src 'self' 'unsafe-inline'; img-src * data: blob:; object-src 'none'; frame-ancestors 'none'; script-src 'self'`,
'Cross-Origin-Opener-Policy': 'same-origin',
'Cross-Origin-Resource-Policy': 'same-origin',
'Cross-Origin-Embedder-Policy': 'require-corp',
},
}, http) }, http)
if (config.get('NODE_ENV') === 'development') {
flaska.devMode()
}
const parser = new ParserMiddleware()
flaska.before(function(ctx) { flaska.before(function(ctx) {
ctx.state.started = new Date().getTime() ctx.state.started = new Date().getTime()
}) })
flaska.before(QueryHandler())
flaska.before(parser.contextParser())
flaska.after(function(ctx) { flaska.after(function(ctx) {
let ended = new Date().getTime() let ended = new Date().getTime()
@ -34,6 +57,16 @@ export function run(http, port, core) {
}, `<-- ${status}${ctx.method} ${ctx.url}`) }, `<-- ${status}${ctx.method} ${ctx.url}`)
}) })
const page = new PageRoutes()
flaska.get('/api/pagetree', page.getPageTree.bind(page))
flaska.get('/api/pages', page.getAllPages.bind(page))
flaska.get('/api/pages/:pageId', page.getSinglePage.bind(page))
const article = new ArticleRoutes()
flaska.get('/api/articles/public', article.getPublicAllArticles.bind(article))
flaska.get('/api/articles/public/:id', article.getPublicSingleArticle.bind(article))
flaska.get('/api/pages/:pageId/articles/public', article.getPublicAllPageArticles.bind(article))
flaska.get('/::file', function(ctx) { flaska.get('/::file', function(ctx) {
if (ctx.params.file.startsWith('api/')) { if (ctx.params.file.startsWith('api/')) {
throw new HttpError(404, 'Not Found: ' + ctx.params.file, { status: 404, message: 'Not Found: ' + ctx.params.file }) throw new HttpError(404, 'Not Found: ' + ctx.params.file, { status: 404, message: 'Not Found: ' + ctx.params.file })

View file

@ -1,5 +1,5 @@
import { createPrototype, safeColumns } from '../knex.mjs' import { createPrototype, safeColumns } from '../knex.mjs'
import bcrypt from 'bcrypt' // import bcrypt from 'bcrypt'
/*import config from '../config.mjs'*/ /*import config from '../config.mjs'*/
/* Staff model: /* Staff model:

11
db.json
View file

@ -1,11 +0,0 @@
{
"core": {
"version": 1,
"nfp_moe": {
"active": "static",
"latestInstalled": "",
"updater": "",
"versions": []
}
}
}

20
dev.mjs
View file

@ -1,10 +1,22 @@
import fs from 'fs'
import { ServiceCore } from 'service-core' import { ServiceCore } from 'service-core'
import * as index from './index.mjs' import * as index from './index.mjs'
var core = new ServiceCore('nfp_moe', import.meta.url) var core = new ServiceCore('nfp_moe', import.meta.url, 4030, '')
core.setConfig({
port: 4030, let config = {
}) frontend: {
url: 'http://localhost:4030'
}
}
try {
config = JSON.parse(fs.readFileSync('./config.json'))
} catch {}
config.port = 4030
core.setConfig(config)
core.init(index).then(function() { core.init(index).then(function() {
return core.run() return core.run()
}) })

View file

@ -1,7 +1,12 @@
import { run } from "./api/server_flaska.mjs" import config from './api/config.mjs'
export function start(http, port, ctx) { export function start(http, port, ctx) {
return run(http, port, ctx) config.stores.overrides.store = ctx.config
return import('./api/server_flaska.mjs')
.then(function(server) {
return server.run(http, port, ctx)
})
} }
/* /*

View file

@ -9,7 +9,9 @@
"scripts": { "scripts": {
"start": "node --experimental-modules index.mjs", "start": "node --experimental-modules index.mjs",
"test": "echo \"Error: no test specified\" && exit 1", "test": "echo \"Error: no test specified\" && exit 1",
"build": "asbundle app/index.js public/assets/app.js && asbundle app/admin.js public/assets/admin.js", "bla": "sass --help",
"build:prod": "sass -s compressed app/app.scss public/assets/app.css && sass -s compressed app/admin.scss public/assets/admin.css && asbundle app/index.js public/assets/app.js && asbundle app/admin.js public/assets/admin.js",
"build": "sass app/app.scss public/assets/app.css && sass app/admin.scss public/assets/admin.css && asbundle app/index.js public/assets/app.js && asbundle app/admin.js public/assets/admin.js",
"build:watch": "npm-watch build", "build:watch": "npm-watch build",
"dev:server": "node dev.mjs | bunyan", "dev:server": "node dev.mjs | bunyan",
"dev:server:watch": "npm-watch dev:server", "dev:server:watch": "npm-watch dev:server",