fix #10 choose upload path in config.js

This commit is contained in:
lesion 2019-06-11 17:44:11 +02:00
parent a557348b21
commit 5778c64108
16 changed files with 99 additions and 95 deletions

View file

@ -1,14 +1,15 @@
const path = require('path')
/**
* -[ GANCIO CONFIGURATION ]-
*
* search and replace 'CHANGE ME'
*
* -[ Database configuration ]-
* `development` configuration is enabled running `yarn dev`
* while `production` with `yarn start`
* ref: http://docs.sequelizejs.com/class/lib/sequelize.js~Sequelize.html#instance-constructor-constructor
*
*/
const path = require('path')
const DB_CONF = {
development: {
@ -16,8 +17,8 @@ const DB_CONF = {
dialect: 'sqlite'
},
production: {
username: '',
password: '',
username: 'CHANGE ME',
password: 'CHANGE ME',
database: 'gancio',
host: 'localhost',
dialect: 'postgres',
@ -26,7 +27,7 @@ const DB_CONF = {
}
const env = process.env.NODE_ENV || 'development'
const isDev = env === 'development'
/**
* -[ Main configuration ]-
*
@ -34,30 +35,34 @@ const env = process.env.NODE_ENV || 'development'
const config = {
server: {
port: '3000',
host: '0',
host: 'localhost', // use 0.0.0.0 to bind to all interface
// uncomment to use unix socket to serve gancio
// path: '/tmp/gancio_socket',
},
locale: 'it',
title: 'GANCIO',
description: 'A shared agenda for radical communities',
baseurl: '' || 'http://localhost:3000',
title: isDev ? 'GANCIO' : 'CHANGE ME',
description: isDev ? 'A shared agenda for radical communities' : 'CHANGE ME',
baseurl: isDev ? 'http://localhost:3000' : 'https://CHANGE_ME',
upload_path: isDev ? '/tmp/gancio_upload' : '/var/gancio/upload/',
// where events/users confirmation email are sent
admin: '',
admin: 'CHANGE ME',
// jwt salt secret, generate it randomly with
// < /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c${1:-32};echo;
secret: '',
secret: isDev ? 'notreallyrandom' : 'CHANGE ME',
// smtp account to send email
smtp: {
host: process.env.SMTP_HOST || 'mail.example.com',
secure: true,
host: 'CHANGE ME', // mail.example.com
auth: {
user: process.env.SMTP_USER || 'gancio@example.com',
pass: process.env.SMTP_PASS || ''
}
user: 'CHANGE ME',
pass: 'CHANGE ME'
},
secure: true
},
db: DB_CONF[env]
}

View file

@ -122,21 +122,21 @@ const it = {
},
settings: {
change_password: 'Cambia password'
change_password: 'Cambia password',
password_updated: 'Password modificata'
},
err: {
register_error: 'Errore nella registrazione'
}
// firstrun: {
// basic: `Inserisci titolo e descrizione della tua istanza di gancio.`,
// database: `Gancio ha bisogno di un database postgresql!`,
// smtp: `Inserisci un account SMTP relativo a questa istanza di gancio.`
// },
// email: {
// registration: `Abbiamo ricevuto la richiesta di registrazione. La confermeremo quanto prima.\n Ciao`
// }
}
export default it

View file

@ -223,6 +223,8 @@ export default {
const place = this.places.find( p => p.name === this.event.place.name )
if (place && place.address) {
this.event.place.address = place.address
} else {
this.event.place.address = ''
}
this.$refs.address.focus()
},

View file

@ -5,13 +5,13 @@
import { mapState } from 'vuex'
import List from '../../components/List'
import moment from 'dayjs'
import get from 'lodash/get'
export default {
layout: 'iframe',
components: { List },
computed: mapState(['config']),
async asyncData ({ $axios, req, res }) {
const title = req && req.query && req.query.title || this.config.title
const title = get(req, 'query.title')
const tags = req && req.query && req.query.tags
const places = req && req.query && req.query.places
const now = new Date()

View file

@ -1,6 +1,5 @@
<template lang="pug">
el-card#eventDetail
el-card#eventDetail(v-loading='!loaded')
//- close button
nuxt-link.float-right(to='/')
el-button(circle icon='el-icon-close' type='danger' size='small' plain)
@ -18,7 +17,7 @@
el-button(icon='el-icon-arrow-right' round type='success')
//- image
img(:src='imgPath' v-if='event.image_path')
img(:src='imgPath' v-if='event.image_path' @load='image_loaded')
.info
div {{event|event_when}}
@ -56,6 +55,11 @@ import { mapState, mapActions, mapGetters } from 'vuex'
export default {
name: 'Event',
data () {
return {
loaded: false,
}
},
// transition: null,
// Watch for $route.query.page to call Component methods (asyncData, fetch, validate, layout, etc.)
// watchQuery: ['id'],
@ -84,7 +88,8 @@ export default {
},
async asyncData ( { $axios, params }) {
const event = await $axios.$get(`/event/${params.id}`)
return { event, id: params.id}
const loaded = !event.image_path
return { event, id: params.id, loaded }
},
computed: {
...mapGetters(['filteredEvents']),
@ -112,6 +117,9 @@ export default {
},
},
methods: {
image_loaded (e, b) {
this.loaded = true
},
...mapActions(['delEvent']),
comment_filter (value) {
return value.replace(/<a.*href="([^">]+).*>(?:.(?!\<\/a\>))*.<\/a>/, (orig, url) => {

View file

@ -15,14 +15,14 @@
//- el-tag.ml-1(size='mini' v-for='place in filters.places' :key='place.id') {{place}}
el-tabs.mt-2(v-model='type')
el-tab-pane.pt-1(label='email' name='email')
p(v-html='$t(`export.email_description`)')
el-form(@submit.native.prevent)
//- el-switch(v-model='notification.notify_on_add' :active-text="$t('notify_on_insert')")
//- br
//- el-switch.mt-2(v-model='notification.send_notification' :active-text="$t('send_notification')")
el-input.mt-2(v-model='notification.email' :placeholder="$t('export.insert_your_address')" ref='email')
el-button.mt-2.float-right(native-type= 'submit' type='success' @click='add_notification') {{$t('common.send')}}
//- el-tab-pane.pt-1(label='email' name='email')
//- p(v-html='$t(`export.email_description`)')
//- el-form(@submit.native.prevent)
//- //- el-switch(v-model='notification.notify_on_add' :active-text="$t('notify_on_insert')")
//- //- br
//- //- el-switch.mt-2(v-model='notification.send_notification' :active-text="$t('send_notification')")
//- el-input.mt-2(v-model='notification.email' :placeholder="$t('export.insert_your_address')" ref='email')
//- el-button.mt-2.float-right(native-type= 'submit' type='success' @click='add_notification') {{$t('common.send')}}
el-tab-pane.pt-1(label='feed rss' name='feed')
span(v-html='$t(`export.feed_description`)')
@ -104,10 +104,14 @@ export default {
params.push(`title=${this.list.title}`)
}
if (this.filters.places) {
if (this.filters.places.length) {
params.push(`places=${this.filters.places}`)
}
if (this.filters.tags.length) {
params.push(`tags=${this.filters.tags}`)
}
return `<iframe src="${process.env.baseurl}/embed/list?${params.join('&')}"></iframe>`
},
link () {

View file

@ -5,21 +5,21 @@
v-icon(name='times' color='red')
h5 {{$t('common.settings')}}
//- el-form
//- el-form-item {{$t('settings.change_password')}}
el-divider {{$t('settings.change_password')}}
el-input(v-model='password' type='password')
el-button(slot='append' @click='change' type='success') {{$t('common.send')}}
el-form(action='/api/user' method='PUT' @submit.native.prevent='change')
el-form-item {{$t('settings.change_password')}}
el-input(v-model='password' type='password')
el-button(type='success' native-type='submit') {{$t('common.send')}}
</template>
<script>
import { mapState, mapActions } from 'vuex'
import { Message } from 'element-ui'
export default {
data () {
return {
password: '',
}
},
// computed: mapState(['user']),
// async asyncData ({ $axios, params }) {
// const user = await $axios.$get('/auth/user')
// user.mastodon_auth = ''
@ -31,6 +31,8 @@ export default {
const user_data = { id : this.$auth.user.id, password: this.password }
try {
const user = await this.$axios.$put('/user', user_data)
Message({ message: this.$t('settings.password_updated'), type: 'success' })
this.$router.replace('/')
} catch (e) {
console.log(e)
}

View file

@ -1,16 +1,20 @@
import Vue from 'vue'
import { Button, Select, Tag, Option, Table, FormItem, Card, Row, Col, Upload, Checkbox,
Form, Tabs, TabPane, Switch, Input, Loading, TimeSelect, Badge, ButtonGroup, Divider, Step, Steps,
TableColumn, ColorPicker, Pagination, Popover, Tooltip, Dialog,
Container, Footer , Timeline, TimelineItem, Menu, MenuItem } from 'element-ui'
import localeEn from 'element-ui/lib/locale/lang/en'
import localeIt from 'element-ui/lib/locale/lang/it'
TableColumn, ColorPicker, Pagination, Popover, Tooltip, Dialog, Image,
Container, Footer, Timeline, TimelineItem, Menu, MenuItem } from 'element-ui'
import locale from 'element-ui/lib/locale'
locale.use(localeIt)
const locales = {
it: require('element-ui/lib/locale/lang/it'),
en: require('element-ui/lib/locale/lang/en')
}
locale.use(locales[process.env.locale])
export default () => {
Vue.use(Button)
Vue.use(Divider)
Vue.use(Image)
Vue.use(Step)
Vue.use(Steps)
Vue.use(Checkbox)

View file

@ -48,7 +48,7 @@ ${event.description.length > 200 ? event.description.substr(0, 200) + '...' : ev
let media
if (event.image_path) {
const file = path.join(__dirname, '..', '..', '..', 'uploads', event.image_path)
const file = path.join(config.upload_path, event.image_path)
if (fs.statSync(file)) {
media = await bot.post('media', { file: fs.createReadStream(file) })
}

View file

@ -53,8 +53,8 @@ const userController = {
// check if event is mine (or user is admin)
if (event && (req.user.is_admin || req.user.id === event.userId)) {
if (event.image_path) {
const old_path = path.resolve(__dirname, '..', '..', 'uploads', event.image_path)
const old_thumb_path = path.resolve(__dirname, '..', '..', 'uploads', 'thumb', event.image_path)
const old_path = path.join(config.upload_path, event.image_path)
const old_thumb_path = path.join(config.upload_path, 'thumb', event.image_path)
try {
await fs.unlink(old_path)
await fs.unlink(old_thumb_path)
@ -126,8 +126,8 @@ const userController = {
if (req.file) {
if (event.image_path) {
const old_path = path.resolve(__dirname, '..', '..', 'uploads', event.image_path)
const old_thumb_path = path.resolve(__dirname, '..', '..', 'uploads', 'thumb', event.image_path)
const old_path = path.resolve(config.upload_path, event.image_path)
const old_thumb_path = path.resolve(config.upload_path, 'thumb', event.image_path)
await fs.unlink(old_path, e => console.error(e))
await fs.unlink(old_thumb_path, e => console.error(e))
}

View file

@ -11,9 +11,7 @@ const exportController = require('./controller/export')
const userController = require('./controller/user')
const settingsController = require('./controller/settings')
const storage = require('./storage')({
destination: 'uploads/'
})
const storage = require('./storage')
const upload = multer({ storage })
const api = express.Router()

View file

@ -1,62 +1,43 @@
const fs = require('fs')
const os = require('os')
const path = require('path')
const crypto = require('crypto')
const mkdirp = require('mkdirp')
const sharp = require('sharp')
const consola = require('consola')
const config = require('../config')
function getDestination(req, file, cb) {
cb(null, os.tmpdir())
}
function DiskStorage(opts) {
if (typeof opts.destination === 'string') {
mkdirp.sync(opts.destination)
this.getDestination = function ($0, $1, cb) { cb(null, opts.destination) }
} else {
this.getDestination = (opts.destination || getDestination)
}
}
DiskStorage.prototype._handleFile = function _handleFile(req, file, cb) {
const that = this
that.getDestination(req, file, function (err, destination) {
if (err) return cb(err)
mkdirp.sync(config.upload_path + '/thumb')
const DiskStorage = {
_handleFile(req, file, cb) {
const filename = crypto.randomBytes(16).toString('hex') + '.jpg'
const finalPath = path.join(destination, filename)
const thumbPath = path.join(destination, 'thumb', filename)
const finalPath = path.resolve(config.upload_path, filename)
const thumbPath = path.resolve(config.upload_path, 'thumb', filename)
const outStream = fs.createWriteStream(finalPath)
const thumbStream = fs.createWriteStream(thumbPath)
const resizer = sharp().resize(800).jpeg({ quality: 90 })
const thumbnailer = sharp().resize(400).jpeg({ quality: 90 })
file.stream.pipe(thumbnailer).pipe(thumbStream)
thumbStream.on('error', e => console.log('thumbStream error ', e))
thumbStream.on('error', e => consola.error('thumbStream error ', e))
file.stream.pipe(resizer).pipe(outStream)
outStream.on('error', cb)
outStream.on('finish', function () {
cb(null, {
destination,
destination: config.upload_path,
filename,
path: finalPath,
size: outStream.bytesWritten
})
})
})
},
_removeFile(req, file, cb) {
delete file.destination
delete file.filename
delete file.path
fs.unlink(path, cb)
}
}
DiskStorage.prototype._removeFile = function _removeFile(req, file, cb) {
let path = file.path
delete file.destination
delete file.filename
delete file.path
fs.unlink(path, cb)
}
module.exports = function (opts) {
return new DiskStorage(opts)
}
module.exports = DiskStorage

View file

@ -3,7 +3,7 @@ p Dove: #{event.place.name} - #{event.place.address}
p Quando: #{datetime(event.start_datetime)}
br
if event.image_path
<img style="width: 100%" src="#{config.apiurl}/uploads/#{event.image_path}" />
<img style="width: 100%" src="#{config.apiurl}/media/#{event.image_path}" />
p #{event.description}
each tag in event.tags

View file

@ -1,3 +1,3 @@
p= t('mail.recover')
p= t('email.recover')
<a href="#{config.baseurl}/recover/#{user.recover_code}">#{t('press here')}</a>
<a href="#{config.baseurl}/recover/#{user.recover_code}">#{t('email.press_here')}</a>

View file

@ -26,7 +26,7 @@ async function start() {
// Give nuxt middleware to express
app.use(morgan('dev'))
app.use('/media/', express.static(path.join(__dirname, '..', 'uploads')))
app.use('/media/', express.static(config.upload_path))
app.use(nuxt.render)
// Listen the server

View file

@ -16,7 +16,7 @@ rss(version='2.0')
| <h4>#{event.title}</h4>
| <strong>#{event.place.name} - #{event.place.address}</strong>
| #{moment(event.start_datetime).format("dddd, D MMMM HH:mm")}<br/>
| <img src="#{config.apiurl}/../uploads/#{event.image_path}"/>
| <img src="#{config.apiurl}/media/#{event.image_path}"/>
| <pre>!{event.description}</pre>
| ]]>
pubDate= new Date(event.createdAt).toUTCString()