#54 user accounts - jwt, page
This commit is contained in:
parent
89a9ed4bc2
commit
f9fe754655
|
@ -6,6 +6,8 @@
|
|||
/daemonise.json
|
||||
/daemonise.log
|
||||
|
||||
/keys
|
||||
|
||||
# Created by .ignore support plugin (hsz.mobi)
|
||||
### Node template
|
||||
# Logs
|
||||
|
|
7
Makefile
7
Makefile
|
@ -1,4 +1,11 @@
|
|||
include .env.dist
|
||||
-include .env
|
||||
|
||||
KEYS_DIR=./keys
|
||||
|
||||
install:
|
||||
-cp -n .env.dist .env
|
||||
if [ ! -d "${KEYS_DIR}" ]; then mkdir -p ${KEYS_DIR}; openssl genrsa -out ${KEYS_DIR}/private.pem 2048; openssl rsa -in ${KEYS_DIR}/private.pem -outform PEM -pubout -out ${KEYS_DIR}/public.pem; fi
|
||||
yarn
|
||||
node server/migrate.js
|
||||
|
||||
|
|
15
README.md
15
README.md
|
@ -4,27 +4,20 @@
|
|||
|
||||
```bash
|
||||
# install dependencies
|
||||
$ yarn install
|
||||
$ make install
|
||||
|
||||
# configure environment
|
||||
$ cp .env.dist .env
|
||||
$ nano .env
|
||||
$ make switch LANG=pl
|
||||
$ node server/initDb.js
|
||||
|
||||
# serve with hot reload at localhost:3000
|
||||
$ yarn dev
|
||||
$ make run
|
||||
|
||||
# build for production and launch server
|
||||
$ yarn build
|
||||
$ yarn start
|
||||
|
||||
# generate static project
|
||||
$ yarn generate
|
||||
$ make deploy
|
||||
$ nuxt start
|
||||
```
|
||||
|
||||
For detailed explanation on how things work, check out [Nuxt.js docs](https://nuxtjs.org).
|
||||
|
||||
## Copyright
|
||||
|
||||
* **Author:** Andrea [(Avris.it)](https://avris.it)
|
||||
|
|
|
@ -76,6 +76,10 @@
|
|||
links.push({ link: '/' + this.config.contact.route, icon: 'comment-alt-smile', text: this.$t('contact.header')});
|
||||
}
|
||||
|
||||
if (this.config.user.enabled) {
|
||||
links.push({ link: '/' + this.config.user.route, icon: 'user', text: this.$t('user.header'), textLong: this.$t('user.headerLong')});
|
||||
}
|
||||
|
||||
return {
|
||||
links,
|
||||
};
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
data() {
|
||||
return {
|
||||
preset: {
|
||||
url: process.env.baseUrl + this.$route.path,
|
||||
url: process.env.BASE_URL + this.$route.path,
|
||||
title: this.title,
|
||||
extra: {
|
||||
media: '',
|
||||
|
|
|
@ -73,3 +73,7 @@ contact:
|
|||
mail: 'zuzannagrzybowska@protonmail.com'
|
||||
areas:
|
||||
social_media: ~
|
||||
|
||||
user:
|
||||
enabled: true
|
||||
route: 'account'
|
||||
|
|
|
@ -202,3 +202,7 @@ support:
|
|||
iconSet: 'b'
|
||||
url: 'https://paypal.me/AndreAvris'
|
||||
headline: 'PayPal'
|
||||
|
||||
user:
|
||||
enabled: true
|
||||
route: 'konto'
|
||||
|
|
|
@ -518,6 +518,11 @@ support:
|
|||
Jeśli chcesz się zrzucić na serwer, domeny, wlepki itp., lub zwyczajnie postawić autorzom piwo,
|
||||
możesz skorzystać z poniższego linku (wspomnij o „zaimki.pl” w opisie transakcji):
|
||||
|
||||
user:
|
||||
header: 'Konto'
|
||||
headerLong: 'Twoje konto'
|
||||
|
||||
|
||||
share: 'Udostępnij'
|
||||
|
||||
crud:
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import translations from './server/translations';
|
||||
import config from './server/config';
|
||||
import fs from 'fs';
|
||||
|
||||
const title = translations.title;
|
||||
const description = translations.description;
|
||||
|
@ -78,17 +79,18 @@ export default {
|
|||
},
|
||||
},
|
||||
env: {
|
||||
baseUrl: process.env.BASE_URL,
|
||||
secret: process.env.SECRET,
|
||||
lang: process.env.LANG,
|
||||
BASE_URL: process.env.BASE_URL,
|
||||
SECRET: process.env.SECRET,
|
||||
PUBLIC_KEY: fs.readFileSync(__dirname + '/keys/public.pem').toString(),
|
||||
},
|
||||
serverMiddleware: {
|
||||
'/': bodyParser.json(),
|
||||
'/nouns': '~/server/nouns.js',
|
||||
'/banner': '~/server/banner.js',
|
||||
'/api/nouns': '~/server/nouns.js',
|
||||
'/api/user': '~/server/user.js',
|
||||
},
|
||||
axios: {
|
||||
baseURL: process.env.BASE_URL,
|
||||
baseURL: process.env.BASE_URL + '/api',
|
||||
},
|
||||
router: {
|
||||
extendRoutes(routes, resolve) {
|
||||
|
@ -124,6 +126,9 @@ export default {
|
|||
routes.push({ path: '/' + config.contact.route, component: resolve(__dirname, 'routes/contact.vue') });
|
||||
}
|
||||
|
||||
if (config.user.enabled) {
|
||||
routes.push({path: '/' + config.user.route, component: resolve(__dirname, 'routes/user.vue')});
|
||||
}
|
||||
routes.push({ path: '/' + config.template.any.route, component: resolve(__dirname, 'routes/any.vue') });
|
||||
|
||||
routes.push({ name: 'all', path: '*', component: resolve(__dirname, 'routes/template.vue') });
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
"body-parser": "^1.19.0",
|
||||
"canvas": "^2.6.1",
|
||||
"dotenv": "^8.2.0",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"mailer": "^0.6.7",
|
||||
"nuxt": "^2.13.0",
|
||||
"sql-template-strings": "^2.2.2",
|
||||
|
|
|
@ -242,14 +242,14 @@
|
|||
if (!this.selectedTemplate.pronoun()) {
|
||||
return null;
|
||||
}
|
||||
return this.addSlash(process.env.baseUrl + '/' + (this.usedBaseEquals ? this.usedBase : this.longLink));
|
||||
return this.addSlash(process.env.BASE_URL + '/' + (this.usedBaseEquals ? this.usedBase : this.longLink));
|
||||
},
|
||||
linkMultiple() {
|
||||
if (!this.multiple.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.addSlash(process.env.baseUrl + '/' + this.multiple.join('&'));
|
||||
return this.addSlash(process.env.BASE_URL + '/' + this.multiple.join('&'));
|
||||
},
|
||||
sources() {
|
||||
return getSources(this.selectedTemplate);
|
||||
|
|
|
@ -42,10 +42,8 @@
|
|||
|
||||
<script>
|
||||
import { head } from "../src/helpers";
|
||||
import Icon from "../components/Icon";
|
||||
|
||||
export default {
|
||||
components: {Icon},
|
||||
head() {
|
||||
return head({
|
||||
title: this.$t('contact.header'),
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
<template>
|
||||
<div class="container">
|
||||
<h2>
|
||||
<Icon v="user"/>
|
||||
<T>user.header</T>
|
||||
</h2>
|
||||
|
||||
<div v-if="token">
|
||||
<pre><code>{{JSON.stringify(token)}}</code></pre>
|
||||
<pre>{{JSON.stringify(payload, null, 4)}}</pre>
|
||||
</div>
|
||||
<button v-else class="btn btn-primary" @click="login">Zaloguj</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { head } from "../src/helpers";
|
||||
import jwt from 'jsonwebtoken';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
token: null,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
payload() {
|
||||
if (!this.token) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return jwt.verify(this.token, process.env.PUBLIC_KEY, {
|
||||
algorithm: 'RS256',
|
||||
audience: process.env.BASE_URL,
|
||||
issuer: process.env.BASE_URL,
|
||||
});
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async login() {
|
||||
this.token = await this.$axios.$post(`/user`);
|
||||
},
|
||||
},
|
||||
head() {
|
||||
return head({
|
||||
title: this.$t('user.headerLong'),
|
||||
});
|
||||
},
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,32 @@
|
|||
import jwt from 'jsonwebtoken';
|
||||
import fs from 'fs';
|
||||
|
||||
class Jwt {
|
||||
constructor(privateKey, publicKey) {
|
||||
this.privateKey = fs.readFileSync(privateKey);
|
||||
this.publicKey = fs.readFileSync(publicKey);
|
||||
}
|
||||
|
||||
sign(payload, expiresIn = '30d') {
|
||||
return jwt.sign(payload, this.privateKey, {
|
||||
expiresIn,
|
||||
algorithm: 'RS256',
|
||||
audience: process.env.BASE_URL,
|
||||
issuer: process.env.BASE_URL,
|
||||
});
|
||||
}
|
||||
|
||||
validate(token) {
|
||||
try {
|
||||
return jwt.verify(token, this.publicKey, {
|
||||
algorithm: 'RS256',
|
||||
audience: process.env.BASE_URL,
|
||||
issuer: process.env.BASE_URL,
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new Jwt(__dirname + '/../keys/private.pem', __dirname + '/../keys/public.pem');
|
|
@ -0,0 +1,19 @@
|
|||
import jwt from './jwt';
|
||||
import { makeId } from '../src/helpers';
|
||||
|
||||
export default async function (req, res, next) {
|
||||
const db = await dbConnection();
|
||||
|
||||
let result = {error: 'Not found'}
|
||||
if (req.method === 'GET' && req.url === '/all') {
|
||||
jwt.sign({
|
||||
username: 'andrea',
|
||||
email: 'andrea@avris.it',
|
||||
secret: makeId(6, '0123456789'),
|
||||
})
|
||||
}
|
||||
|
||||
res.setHeader('content-type', 'application/json');
|
||||
res.write(JSON.stringify(result));
|
||||
res.end();
|
||||
}
|
|
@ -31,7 +31,7 @@ export const head = ({title, description, banner}) => {
|
|||
}
|
||||
|
||||
if (banner) {
|
||||
banner = process.env.baseUrl + '/' + banner;
|
||||
banner = process.env.BASE_URL + '/' + banner;
|
||||
meta.meta.push({ hid: 'og:logo', property: 'og:logo', content: banner });
|
||||
meta.meta.push({ hid: 'twitter:image', property: 'twitter:image', content: banner });
|
||||
}
|
||||
|
@ -62,3 +62,13 @@ export const clearUrl = url => {
|
|||
|
||||
return decodeURIComponent(url);
|
||||
}
|
||||
|
||||
export const makeId = (length, characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789') => {
|
||||
let result = '';
|
||||
const charactersLength = characters.length;
|
||||
for (let i = 0; i < length; i++) {
|
||||
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
80
yarn.lock
80
yarn.lock
|
@ -2065,6 +2065,11 @@ browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.6.4, browserslist@^4.
|
|||
escalade "^3.0.1"
|
||||
node-releases "^1.1.58"
|
||||
|
||||
buffer-equal-constant-time@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819"
|
||||
integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=
|
||||
|
||||
buffer-from@^1.0.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
|
||||
|
@ -3226,6 +3231,13 @@ ecc-jsbn@~0.1.1:
|
|||
jsbn "~0.1.0"
|
||||
safer-buffer "^2.1.0"
|
||||
|
||||
ecdsa-sig-formatter@1.0.11:
|
||||
version "1.0.11"
|
||||
resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf"
|
||||
integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==
|
||||
dependencies:
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
ee-first@1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
|
||||
|
@ -4871,6 +4883,22 @@ jsonfile@^6.0.1:
|
|||
optionalDependencies:
|
||||
graceful-fs "^4.1.6"
|
||||
|
||||
jsonwebtoken@^8.5.1:
|
||||
version "8.5.1"
|
||||
resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d"
|
||||
integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==
|
||||
dependencies:
|
||||
jws "^3.2.2"
|
||||
lodash.includes "^4.3.0"
|
||||
lodash.isboolean "^3.0.3"
|
||||
lodash.isinteger "^4.0.4"
|
||||
lodash.isnumber "^3.0.3"
|
||||
lodash.isplainobject "^4.0.6"
|
||||
lodash.isstring "^4.0.1"
|
||||
lodash.once "^4.0.0"
|
||||
ms "^2.1.1"
|
||||
semver "^5.6.0"
|
||||
|
||||
jsprim@^1.2.2:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
|
||||
|
@ -4881,6 +4909,23 @@ jsprim@^1.2.2:
|
|||
json-schema "0.2.3"
|
||||
verror "1.10.0"
|
||||
|
||||
jwa@^1.4.1:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a"
|
||||
integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==
|
||||
dependencies:
|
||||
buffer-equal-constant-time "1.0.1"
|
||||
ecdsa-sig-formatter "1.0.11"
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
jws@^3.2.2:
|
||||
version "3.2.2"
|
||||
resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304"
|
||||
integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==
|
||||
dependencies:
|
||||
jwa "^1.4.1"
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0:
|
||||
version "3.2.2"
|
||||
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
|
||||
|
@ -5000,6 +5045,36 @@ lodash._reinterpolate@^3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
|
||||
integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=
|
||||
|
||||
lodash.includes@^4.3.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f"
|
||||
integrity sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=
|
||||
|
||||
lodash.isboolean@^3.0.3:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6"
|
||||
integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=
|
||||
|
||||
lodash.isinteger@^4.0.4:
|
||||
version "4.0.4"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343"
|
||||
integrity sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=
|
||||
|
||||
lodash.isnumber@^3.0.3:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc"
|
||||
integrity sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=
|
||||
|
||||
lodash.isplainobject@^4.0.6:
|
||||
version "4.0.6"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
|
||||
integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=
|
||||
|
||||
lodash.isstring@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451"
|
||||
integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=
|
||||
|
||||
lodash.kebabcase@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz#8489b1cb0d29ff88195cceca448ff6d6cc295c36"
|
||||
|
@ -5010,6 +5085,11 @@ lodash.memoize@^4.1.2:
|
|||
resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
|
||||
integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=
|
||||
|
||||
lodash.once@^4.0.0:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"
|
||||
integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=
|
||||
|
||||
lodash.template@^4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab"
|
||||
|
|
Reference in New Issue