You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
212 lines
4.4 KiB
212 lines
4.4 KiB
3 years ago
|
import fastifySession from '@fastify/session'
|
||
|
import fastifyCookie from 'fastify-cookie'
|
||
|
|
||
|
import PouchDB from 'pouchdb'
|
||
|
import PouchDBfind from 'pouchdb-find'
|
||
|
|
||
|
|
||
|
/**
|
||
|
* pouchdb storage
|
||
|
*
|
||
|
*
|
||
|
* @extends Store
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
class PouchdbStore extends Store
|
||
|
{
|
||
|
/**
|
||
|
*
|
||
|
*
|
||
|
* @param {Object}
|
||
|
*
|
||
|
*/
|
||
|
constructor()
|
||
|
{
|
||
|
super()
|
||
|
|
||
|
PouchDB.plugin(PouchDBfind)
|
||
|
|
||
|
// create db if not already exists
|
||
|
this.db = new PouchDB('./../../storage/session', {
|
||
|
revs_limit: 0
|
||
|
})
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
* @param {[type]} sessionId [description]
|
||
|
* @param {Function} callback [description]
|
||
|
*/
|
||
|
async set(sessionId, session, callback)
|
||
|
{
|
||
|
const result = await this.db.find({
|
||
|
'selector': {
|
||
|
'_id': sessionId
|
||
|
}
|
||
|
})
|
||
|
|
||
|
if (result.docs.length === 0) {
|
||
|
session._id = sessionId
|
||
|
await this.db.post(session)
|
||
|
}
|
||
|
|
||
|
callback()
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
* @param {[type]} sessionId [description]
|
||
|
* @param {Function} callback [description]
|
||
|
* @return {[type]} [description]
|
||
|
*/
|
||
|
async get(sessionId, callback)
|
||
|
{
|
||
|
const result = await this.db.find({
|
||
|
'selector': {
|
||
|
'_id': sessionId
|
||
|
}
|
||
|
})
|
||
|
|
||
|
let session = null
|
||
|
|
||
|
if (result.docs.length > 0) {
|
||
|
session = result.docs[0]
|
||
|
}
|
||
|
|
||
|
callback(null, session)
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
* @param {[type]} sessionId [description]
|
||
|
* @param {Function} callback [description]
|
||
|
* @return {[type]} [description]
|
||
|
*/
|
||
|
async destroy(sessionId, callback)
|
||
|
{
|
||
|
const result = await this.db.find({
|
||
|
'selector': {
|
||
|
'_id': sessionId
|
||
|
}
|
||
|
})
|
||
|
|
||
|
if (result.docs.length > 0) {
|
||
|
await this.db.remove(result.docs[0])
|
||
|
}
|
||
|
|
||
|
callback()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
*
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
const loginSchema = {
|
||
|
schema: {
|
||
|
body: {
|
||
|
username: { type: 'string' },
|
||
|
password: { type: 'string' }
|
||
|
},
|
||
|
response: {
|
||
|
200: {
|
||
|
type: 'object',
|
||
|
properties: {
|
||
|
token: { type: 'string' }
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* create Plugin
|
||
|
*
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
function plugin(fastify, options, next) {
|
||
|
{
|
||
|
// create cookie
|
||
|
fastify
|
||
|
.register(fastifyCookie)
|
||
|
.register(fastifySession, {
|
||
|
secret: options.secret,
|
||
|
cookieName: 'session',
|
||
|
cookie: {
|
||
|
path: '/',
|
||
|
maxAge: options.secret,
|
||
|
secure: true,
|
||
|
httpOnly: true,
|
||
|
sameSite: 'Strict'
|
||
|
},
|
||
|
store: new PouchdbStore()
|
||
|
})
|
||
|
|
||
|
/**
|
||
|
* route: logout user and destroy session
|
||
|
*
|
||
|
*
|
||
|
*/
|
||
|
fastify.get('/logout', async function(request, response)
|
||
|
{
|
||
|
request.destroySession(() => {
|
||
|
response.redirect('/')
|
||
|
})
|
||
|
})
|
||
|
|
||
|
/**
|
||
|
* route: auth
|
||
|
*
|
||
|
* @param {object} request
|
||
|
* @param {object} response
|
||
|
*
|
||
|
*/
|
||
|
fastify.post('/auth', loginSchema, async function (request, reply)
|
||
|
{
|
||
|
let { username, password } = request.body
|
||
|
|
||
|
// strip crap from strings
|
||
|
username = DOMPurify.sanitize(username)
|
||
|
password = DOMPurify.sanitize(password)
|
||
|
|
||
|
const userRepository = new UserRepository()
|
||
|
const user = await userRepository.findOneByUsername(username)
|
||
|
|
||
|
// add header for json
|
||
|
reply.header('Content-Type', 'application/json; charset=utf-8')
|
||
|
|
||
|
// user not found
|
||
|
if (!user) {
|
||
|
return reply
|
||
|
.code(404)
|
||
|
.send()
|
||
|
}
|
||
|
|
||
|
// password wrong
|
||
|
if (!bcrypt.compareSync(password, user.password)) {
|
||
|
return reply
|
||
|
.code(401)
|
||
|
.send()
|
||
|
}
|
||
|
|
||
|
// setting session to store and set cookie
|
||
|
request.sessionStore.set(request.session.sessionId, request.session, async function() {
|
||
|
user.sessionId = request.session.sessionId
|
||
|
|
||
|
await userRepository.update(user)
|
||
|
|
||
|
// send 200 and send set-token
|
||
|
reply
|
||
|
.code(200)
|
||
|
.send()
|
||
|
})
|
||
|
})
|
||
|
|
||
|
done()
|
||
|
}
|
||
|
|
||
|
module.exports = plugin
|