From cc025b23935daaa94d4b25b586afa3b47eeb676c Mon Sep 17 00:00:00 2001 From: Jonatan Nilsson Date: Fri, 22 Feb 2019 14:53:43 +0000 Subject: [PATCH] More updates --- api/access/middleware.mjs | 2 +- api/jwt.mjs | 3 +-- api/media/upload.mjs | 6 +++++ app/admin/admin.scss | 7 +++++- app/admin/editcat.js | 3 +++ app/api/common.js | 20 ++++++++++++++++ app/api/media.js | 13 +++++++++++ app/app.scss | 1 + app/authentication.js | 10 ++++---- app/login/login.js | 6 +++-- app/widgets/common.scss | 47 ++++++++++++++++++++++++++++++++++++++ app/widgets/fileupload.js | 34 +++++++++++++++++++++++---- config/config.default.json | 2 +- package.json | 3 ++- 14 files changed, 140 insertions(+), 17 deletions(-) create mode 100644 app/api/common.js create mode 100644 app/api/media.js diff --git a/api/access/middleware.mjs b/api/access/middleware.mjs index b058f90..055d715 100644 --- a/api/access/middleware.mjs +++ b/api/access/middleware.mjs @@ -18,7 +18,7 @@ export function restrict(level = orgAccess.Normal) { return ctx.throw(403, 'Authentication token was not found (did you forget to login?)') } - if (!ctx.state.user || !ctx.state.user.id || !ctx.state.user.level) { + if (!ctx.state.user || !ctx.state.user.email || !ctx.state.user.level) { return ctx.throw(403, 'You must be authenticated to access this resource') } diff --git a/api/jwt.mjs b/api/jwt.mjs index 2fc61fb..0cabbaf 100644 --- a/api/jwt.mjs +++ b/api/jwt.mjs @@ -53,8 +53,7 @@ export default class Jwt { static jwtMiddleware() { return koaJwt({ secret: (header, payload) => - Staff.getSingle(payload.id) - .then(staff => `${config.get('jwt:secret')}${staff.get('password')}`), + `${config.get('jwt:secret')}${payload.email}`, passthrough: true, }) } diff --git a/api/media/upload.mjs b/api/media/upload.mjs index 9a257a0..50e945a 100644 --- a/api/media/upload.mjs +++ b/api/media/upload.mjs @@ -1,6 +1,7 @@ import http from 'http' import path from 'path' import fs from 'fs' +import Agent from 'socks5-http-client/lib/Agent' let stub @@ -38,6 +39,11 @@ export function uploadFile(token, file) { 'Content-Type': 'multipart/form-data; boundary=' + boundary, 'Content-Length': multipartBody.length, }, + agentClass: Agent, + agentOptions: { + socksHost: '127.0.0.1', + socksPort: 5555, + }, } const req = http.request(options) diff --git a/app/admin/admin.scss b/app/admin/admin.scss index 19a6e18..814477e 100644 --- a/app/admin/admin.scss +++ b/app/admin/admin.scss @@ -21,6 +21,11 @@ article.editcat { } } + fileupload { + margin: 0 20px 20px; + min-height: 100px; + } + form { align-items: center; align-self: center; @@ -31,7 +36,7 @@ article.editcat { margin-bottom: 20px; } - .loading-spinner { + & > .loading-spinner { width: 240px; height: 50px; position: relative; diff --git a/app/admin/editcat.js b/app/admin/editcat.js index 85cd13b..5e92386 100644 --- a/app/admin/editcat.js +++ b/app/admin/editcat.js @@ -1,5 +1,6 @@ const m = require('mithril') const Authentication = require('../authentication') +const FileUpload = require('../widgets/fileupload') const EditCategory = { loading: true, @@ -16,7 +17,9 @@ const EditCategory = { : m('div.admin-wrapper', m('article.editcat', [ m('header', m('h1', 'Edit category')), + m(FileUpload), m('form.editcat', [ + ]) ]) ) diff --git a/app/api/common.js b/app/api/common.js new file mode 100644 index 0000000..5c31f95 --- /dev/null +++ b/app/api/common.js @@ -0,0 +1,20 @@ +const m = require('mithril') +const Authentication = require('../authentication') + +exports.sendRequest = function(options) { + let token = Authentication.getToken() + + if (token) { + options.headers = options.headers || {} + options.headers['Authorization'] = 'Bearer ' + token + } + + return m.request(options) + .catch(function (error) { + if (error.code === 403) { + Authentication.clearToken() + m.route.set('/login', { redirect: m.route.get() }) + } + return Promise.reject(error) + }) +} diff --git a/app/api/media.js b/app/api/media.js new file mode 100644 index 0000000..fdfdf58 --- /dev/null +++ b/app/api/media.js @@ -0,0 +1,13 @@ +const m = require('mithril') +const { sendRequest } = require('./common') + +exports.uploadMedia = function(file) { + let formData = new FormData() + formData.append('file', file) + + return sendRequest({ + method: 'POST', + url: '/api/media', + data: formData, + }) +} diff --git a/app/app.scss b/app/app.scss index b4ba63e..0052cbb 100644 --- a/app/app.scss +++ b/app/app.scss @@ -110,3 +110,4 @@ article { @import 'menu/menu'; @import 'login/login'; @import 'admin/admin'; +@import 'widgets/common'; diff --git a/app/authentication.js b/app/authentication.js index 30f99e8..40f080e 100644 --- a/app/authentication.js +++ b/app/authentication.js @@ -44,13 +44,13 @@ const Authentication = { gscript.src = 'https://apis.google.com/js/platform.js?onload=googleLoaded' document.body.appendChild(gscript) }) - } + }, + + getToken: function() { + return localStorage.getItem(storageName) + }, } Authentication.updateToken(localStorage.getItem(storageName)) -if (Authentication.currentUser) { - // Authentication.createGoogleScript() -} - module.exports = Authentication diff --git a/app/login/login.js b/app/login/login.js index eae01be..854b138 100644 --- a/app/login/login.js +++ b/app/login/login.js @@ -4,6 +4,7 @@ const Authentication = require('../authentication') const Login = { loadedGoogle: false, loading: false, + redirect: '', error: '', initGoogleButton: function() { @@ -29,7 +30,7 @@ const Login = { }) .then(function(result) { Authentication.updateToken(result.token) - m.route.set('/') + m.route.set(Login.redirect || '/') }) .catch(function(error) { Login.error = 'Error while logging into NFP! ' + error.code + ': ' + error.response.message @@ -48,7 +49,8 @@ const Login = { Authentication.createGoogleScript() }, - oninit: function() { + oninit: function(vnode) { + Login.redirect = vnode.attrs.redirect || '' if (Authentication.currentUser) return m.route.set('/') Login.error = '' }, diff --git a/app/widgets/common.scss b/app/widgets/common.scss index e69de29..f737c50 100644 --- a/app/widgets/common.scss +++ b/app/widgets/common.scss @@ -0,0 +1,47 @@ +fileupload { + position: relative; + display: flex; + align-items: stretch; + + .showicon, + .display { + border: 3px solid $title-fg; + border-style: dashed; + flex-grow: 2; + } + + .showicon { + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHaSURBVHhe7dfPScRAAIXxFSxAPHjUkrx61DaswCJsw5MdCDYkgs6DDIQlu5l/Sd5Ovh88WDJ7yPCdcgAAAAAAAEDvHofBwFPYzzD9xoaew37D/obpt55hAy9h4xjjKDrDik7FiCPKiuZixBFlBakx4oiyoNwYcURZQGmMOKI0VBsjjigNtIoRR5QKrWPEEaVASoyPiWdx5840omRIifEe9nD0bDyd6T9TZ3FESZAa4yrsfvTseDrTf4hSISeGzAURohTKjSEpQYQomUpiSGoQIUqi0hiSE0SIMqMmhuQGEaKcUBtDSoIIUY60iCGlQYQog1YxpCaI7D5KyxhSG0R2G+U67Cts6sJxOTGkRRBJiaJ31x26chv2HTZ14dwY0iqInIuid9a7d2kqSkkMaRlEpqJ0HSMaRymNIa2DyDjKLmJEuuhrWGkMWSKI6J30bruJ0cpSQVCIIGYIYoYgZghihiBmCGKGIGYIYoYgZghihiBmCGKGIGYIYoYgZghihiBmCGKGIGYIYoYgZghihiBmCGKGIGYIYoYgZghihiBmCGKGIGYIYoYgZggCAACAjd2FfXY+3fFinPtG6GUX9a1DEDMEMUMQMwQxcxP21vl0RwAAAAAAAGCnDod/1p4xx4l+w0cAAAAASUVORK5CYII='); + background-position: center; + background-repeat: no-repeat; + background-size: 32px; + } + + .display { + border: none; + background-size: contain; + } + + .loading-spinner { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: #33333388; + width: 100%; + } + + input { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + opacity: 0.01; + width: 100%; + cursor: pointer; + text-indent: -9999px; + z-index: 2; + } +} diff --git a/app/widgets/fileupload.js b/app/widgets/fileupload.js index 6e0e098..192fe95 100644 --- a/app/widgets/fileupload.js +++ b/app/widgets/fileupload.js @@ -1,7 +1,27 @@ const m = require('mithril') +const { uploadMedia } = require('../api/media') + +const FileUpload = { + uploadFile(vnode, event) { + if (!event.target.files[0]) return + vnode.state.loading = true + + uploadMedia(event.target.files[0]) + .then(function(res) { + vnode.state.media = res + console.log(vnode.state.media) + }) + .catch(function(err) { + console.log(err) + }) + .then(function() { + vnode.state.loading = false + m.redraw() + }) + }, -const Login = { oninit: function(vnode) { + vnode.state.loading = false vnode.state.media = null vnode.state.error = '' }, @@ -11,16 +31,22 @@ const Login = { return m('fileupload', [ (media ? - m('a', { + m('a.display', { href: media.large_url, style: { 'background-image': 'url(' + media.medium_url + ')', } }) : - m('div.empty') + m('div.showicon') ), + m('input', { + accept: 'image/*', + type: 'file', + onchange: FileUpload.uploadFile.bind(this, vnode), + }), + (vnode.state.loading ? m('div.loading-spinner') : null), ]) } } -module.exports = Login +module.exports = FileUpload diff --git a/config/config.default.json b/config/config.default.json index 251fa2a..e3110d3 100644 --- a/config/config.default.json +++ b/config/config.default.json @@ -38,6 +38,6 @@ "fileSize": 524288000, "upload": { "name": "nfpmoe-dev", - "secret": "TJlAbWgpQy0zMGu01XoW" + "secret": "nfpmoe-dev" } } diff --git a/package.json b/package.json index 8bfa019..c99560d 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,8 @@ "multer": "^1.4.1", "nconf": "^0.10.0", "pg": "^7.8.0", - "sharp": "^0.21.3" + "sharp": "^0.21.3", + "socks5-http-client": "^1.0.4" }, "devDependencies": { "browserify": "^16.2.3",