From 412e6f7daefc05577b7168de320ba81d84e37972 Mon Sep 17 00:00:00 2001 From: lesion Date: Wed, 3 Jul 2019 16:58:24 +0200 Subject: [PATCH] improve installation/documentation --- README.md | 61 ++++++++++++---- config/default.json | 3 +- package.json | 1 + pages/login.vue | 1 - server/api/controller/bot.js | 4 +- server/api/models/comment.js | 6 +- server/api/storage.js | 6 +- server/cli.js | 134 +++++++++++++++-------------------- server/config.js | 24 ------- server/firstrun.js | 18 +++-- server/index.js | 2 +- 11 files changed, 131 insertions(+), 129 deletions(-) delete mode 100644 server/config.js diff --git a/README.md b/README.md index 886744aa..a6b3f9c6 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,54 @@ -## gancio -### shared agenda for local communities +# gancio +#### a shared agenda for local communities -> :warning: Gancio is under heavy development, -> if something is not working as expected, it's expected :D +> :warning: WARNING :warning: +> Gancio is under heavy development, if something is not working as expected, it's expected :D +Please be patient and open an [issue](/cisti/gancio/issues)! -## Install -You will need `npm` or `yarn` installed in your system. +## Installation +##### Install node +```bash +# source https://github.com/nodesource/distributions/blob/master/README.md +curl -sL https://deb.nodesource.com/setup_12.x | bash - +apt-get install -y nodejs +``` + +##### Install postgres +```bash +apt install postgresql +``` +##### Create database +```bash +sudo -u postgres psql +postgres=# create database gancio; +postgres=# create user gancio with encrypted password 'gancio'; +postgres=# grant all privileges on database gancio to gancio; +``` +##### Install gancio +```bash +npm install --global gancio +``` + +##### Create a new user +```bash +adduser gancio +su gancio +``` + +##### Setup & test +```bash +gancio --help +gancio setup +gancio start +``` + + + + +### Hacking ``` bash # clone this repo @@ -18,18 +58,9 @@ cd gancio # install dependencies yarn install -# edit configuration -cp config.example.js config.js - -# - migrate/create test sqlite db -yarn migrate:dev - # testing with sqlite db yarn dev -# - migrate/create production db -yarn migrate - # build for production and launch server yarn build yarn start diff --git a/config/default.json b/config/default.json index 2c55779b..bea1db9a 100644 --- a/config/default.json +++ b/config/default.json @@ -8,8 +8,7 @@ }, "db": { "dialect": "sqlite", - "storage": "./db.sqlite", - "logging": false + "storage": "./db.sqlite" }, "upload_path": "./", "smtp": { diff --git a/package.json b/package.json index 322fe6e9..bc087dc9 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "nuxt.config.js", "locales/", "dist/", + "views/", "store/", "config/", ".nuxt" diff --git a/pages/login.vue b/pages/login.vue index a225e979..927648b8 100644 --- a/pages/login.vue +++ b/pages/login.vue @@ -58,7 +58,6 @@ export default { Message({ message: this.$t('login.check_email'), type: 'success' }) }, async submit (e) { - console.error('dentro submit', e) e.preventDefault() try { this.loading = true diff --git a/server/api/controller/bot.js b/server/api/controller/bot.js index 0878bbf2..d5adf0f9 100644 --- a/server/api/controller/bot.js +++ b/server/api/controller/bot.js @@ -59,13 +59,13 @@ ${event.description.length > 200 ? event.description.substr(0, 200) + '...' : ev const type = msg.event if (type === 'delete') { - const activitypub_id = msg.data + const activitypub_id = String(msg.data) const event = await Comment.findOne({ where: { activitypub_id } }) if (event) await event.destroy() return } - const activitypub_id = msg.data.in_reply_to_id + const activitypub_id = String(msg.data.in_reply_to_id) if (!activitypub_id) return let event = await Event.findOne({ where: { activitypub_id } }) if (!event) { diff --git a/server/api/models/comment.js b/server/api/models/comment.js index 9c5d2ce0..f773fb0a 100644 --- a/server/api/models/comment.js +++ b/server/api/models/comment.js @@ -1,7 +1,11 @@ 'use strict' module.exports = (sequelize, DataTypes) => { const comment = sequelize.define('comment', { - activitypub_id: DataTypes.STRING(18), + activitypub_id: { + type: DataTypes.STRING(18), + index: true, + unique: true, + }, data: DataTypes.JSON }, {}) comment.associate = function (models) { diff --git a/server/api/storage.js b/server/api/storage.js index 75fbdc67..70f84d9e 100644 --- a/server/api/storage.js +++ b/server/api/storage.js @@ -6,7 +6,11 @@ const sharp = require('sharp') const consola = require('consola') const config = require('config') -mkdirp.sync(config.upload_path + '/thumb') +try { + mkdirp.sync(config.upload_path + '/thumb') +} catch (e) { + consola.error(e) +} const DiskStorage = { _handleFile(req, file, cb) { diff --git a/server/cli.js b/server/cli.js index f2540fbc..541e007c 100755 --- a/server/cli.js +++ b/server/cli.js @@ -1,56 +1,19 @@ #!/usr/bin/env node -process.env.NODE_ENV = "production" +process.env.NODE_ENV = 'production' + +const fs = require('fs') +const consola = require('consola') +const sequelize = require('sequelize') +const inquirer = require('inquirer') +const package = require('../package.json') +const firstrun = require('./firstrun') const path = require('path') + const cwd = process.cwd() // needed by nuxt process.chdir(path.resolve(__dirname, '..')) -const arg = require('arg') -const inquirer = require('inquirer') -const package = require('../package.json') -const consola = require('consola') -const firstrun = require('./firstrun') -const fs = require('fs') -const sequelize = require('sequelize') - -/** - * initial setup: - * - check first run - * - ask title, description, baseurl - * - ask and create upload path and thumb dir - * - ask and inizialite db - * - create first admin account - * - enable open registration? - * - enable anon event? - * - enable email export? - * - enable email notification? - * - enable notifier? - * - enable pm2 - * - * start gancio: - * - * update gancio: - * - yarn/npm global update... - * - sequelize migrate ! - */ - -function parseArguments(rawArgs) { - const args = arg({ - '--config': String, - '--install': Boolean, - '--upgrade': Boolean - }, { - argv: rawArgs.slice(2), - }); - - return { - config: path.resolve(cwd, args['--config'] || '/etc/gancio_config.json') , - install: args['--install'] || false, - upgrade: args['--upgrade'] || false - }; -} - function notEmpty (value) { return value.length>0 } @@ -58,10 +21,17 @@ function notEmpty (value) { async function setupQuestionnaire() { const questions = [] + questions.push({ + name: 'title', + message: 'Name of your instance', + default: 'Gancio', + validate: notEmpty + }) + questions.push({ message: 'Specify a baseurl for this gancio installation! (eg. http://gancio.cisti.org)', name: 'baseurl', - default: 'http://localhost:3000', + default: 'http://localhost:13120', validate: notEmpty }) @@ -88,7 +58,7 @@ async function setupQuestionnaire() { questions.push({ name: 'db.storage', message: 'sqlite db path', - default: '/var/gancio/db.sqlite', + default: './db.sqlite', filter: p => path.resolve(cwd, p), when: answers => answers.db.dialect === 'sqlite', validate: db_path => db_path.length>0 && fs.existsSync(path.dirname(db_path)) @@ -128,7 +98,7 @@ async function setupQuestionnaire() { try { const db = new sequelize({ ...options.db, dialect: 'postgres' , password, logging: false }) return db.authenticate().then( () => { - // consola.info(`DB connected`) + db.close() return true }) } catch(e) { @@ -141,7 +111,7 @@ async function setupQuestionnaire() { questions.push({ name: 'upload_path', message: 'Where gancio has to store media?', - default: '/var/gancio/', + default: './uploads', filter: p => path.resolve(cwd, p), validate: p => { const exists = fs.existsSync(p) @@ -187,38 +157,48 @@ async function setupQuestionnaire() { return answers } -async function cli(args) { - - const options = parseArguments(args) - consola.info(`${package.name} - v${package.version} - ${package.description}`) - - // install flag specified? - if (options.install) { - consola.info(`Cool! You're going to setup gancio on this machine.`) - const config = await setupQuestionnaire() - await firstrun.setup(config, options.config) - consola.info(`You can edit '${options.config}' to modify your configuration. `) - consola.info(`- Run "gancio --config ${options.config}"`) - process.exit(0) - } - - // upgrade gancio / TODO npm/yarn global upgrade gancio ? - if (options.upgrade) { - consola.warn('Not implemented yet but should be an easy task! PR welcome!') - process.exit(-1) - } - +async function start (options) { // is first run? if (firstrun.check(options.config)) { consola.error(`Configuration file "${options.config}" not found! This is your first run? You could create it using --install flag`) - process.exit(-1) - } else { - process.env.config_path = options.config - require('./index') } - + require('./index') } -cli(process.argv) +async function setup (options) { + consola.info(`You're going to setup gancio on this machine.`) + const config = await setupQuestionnaire() + await firstrun.setup(config, options.config) + consola.info(`You can edit '${options.config}' to modify your configuration. `) + consola.info(`Run "gancio --config ${options.config}"`) + process.exit(0) +} + +async function upgrade (options) { + consola.warn('Not implemented yet but should be an easy task! PR welcome!') + process.exit(-1) +} + +consola.info(`${package.name} - v${package.version} - ${package.description}`) + +require('yargs') +.usage('Usage $0 [options]') +.option('config', { + alias: 'c', + describe: 'Configuration file', + default: './gancio_config.json', +}) +.coerce('config', config_path => { + const absolute_config_path = path.resolve(cwd, config_path) + process.env.config_path = absolute_config_path + return absolute_config_path +}) +.command(['start', 'run', '$0'], 'Start gancio', {}, start) +.command('setup', 'Setup a new instance', {}, setup) +.command('upgrade', 'Upgrade gancio to a new release (interactive)', {}, upgrade) +.help('h') +.alias('h', 'help') +.epilog('Made with ❤ by underscore hacklab - https://autistici.org/underscore') +.argv diff --git a/server/config.js b/server/config.js deleted file mode 100644 index af428bc7..00000000 --- a/server/config.js +++ /dev/null @@ -1,24 +0,0 @@ -// const argv = require('yargs').argv -// const path = require('path') -// const fs = require('fs') - -// const config_path = path.resolve(argv.config || './config.js') - -// let user_config -// if (fs.existsSync(config_path)) { -// user_config = require(config_path) -// } - -// const config = { -// baseurl: 'PLEASE CONFIGURE YOUR BASEURL!', -// server: { -// host: 'localhost', -// port: 3000 -// }, -// secret: '', -// db: { -// dialect: 'sqlite' -// } -// } - -// module.exports = Object.assign( config, user_config ) diff --git a/server/firstrun.js b/server/firstrun.js index ad8799a0..67210b7b 100644 --- a/server/firstrun.js +++ b/server/firstrun.js @@ -12,34 +12,39 @@ module.exports = { consola.info('Generate random salt') config.secret = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15) + // do not save admin's password in config file const admin = { email: config.admin.email, password: config.admin.password } delete config.admin + config.admin_email = admin.email - consola.info(`Save configuration into ${config_path}`) + config.db.logging = false + consola.info(`Save configuration to ${config_path}`) fs.writeFileSync(config_path, JSON.stringify(config, null, 2)) // sync db const db = require('./api/models') + try { await db.user.findAll() - consola.warning(`!WARNING! Non empty db!`) + consola.warn(`⚠️ Non empty db! Please move your current db elsewhere than retry. +If you want to `) return -1 - } catch(e) {} + } catch(e) { console.error(e) } + consola.info(`Create tables schema`) await db.sequelize.sync().catch(e => { consola.error('Error creating tables', e) return -1 }) // create admin user - consola.info('Create admin user') + consola.info('Create admin user', admin) await db.user.create({ ...admin, is_admin: true, is_active: true }) - // set default settings consola.info('Set default settings') const settings = require('./api/controller/settings') @@ -54,5 +59,8 @@ module.exports = { // send every event to admin await db.notification.create({ type: 'admin_email' }) + + // close db connection + await db.sequelize.close() } } \ No newline at end of file diff --git a/server/index.js b/server/index.js index 5e04a4a8..336c0728 100644 --- a/server/index.js +++ b/server/index.js @@ -4,7 +4,7 @@ const express = require('express') const consola = require('consola') const morgan = require('morgan') const { Nuxt, Builder } = require('nuxt') -const firstRun = require('./firstrun') + // Import and Set Nuxt.js options const nuxt_config = require('../nuxt.config.js') const config = require('config')