Profile Pictures!
2
index.js
|
@ -11,6 +11,8 @@ const passport = require('passport')
|
||||||
const fetch = require('node-fetch')
|
const fetch = require('node-fetch')
|
||||||
const express = require('express')
|
const express = require('express')
|
||||||
|
|
||||||
|
_CC._ = require('lodash')
|
||||||
|
|
||||||
const config = require('./config')
|
const config = require('./config')
|
||||||
_CC.config = config
|
_CC.config = config
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
"express-session": "^1.17.2",
|
"express-session": "^1.17.2",
|
||||||
"get-product-name": "1",
|
"get-product-name": "1",
|
||||||
"jsdom": "^17.0.0",
|
"jsdom": "^17.0.0",
|
||||||
|
"lodash": "^4.17.20",
|
||||||
"marked": "^3.0.3",
|
"marked": "^3.0.3",
|
||||||
"memdown": "^6.0.0",
|
"memdown": "^6.0.0",
|
||||||
"mkdirp": "^1.0.4",
|
"mkdirp": "^1.0.4",
|
||||||
|
|
|
@ -11,7 +11,7 @@ const SECRET_TOKEN_LIFETIME =
|
||||||
24 * // hours
|
24 * // hours
|
||||||
7 // days
|
7 // days
|
||||||
|
|
||||||
module.exports = (db) => {
|
module.exports = ({ db, ensurePfp }) => {
|
||||||
const router = express.Router()
|
const router = express.Router()
|
||||||
|
|
||||||
router.get('/', verifyAuth(), (req, res) => {
|
router.get('/', verifyAuth(), (req, res) => {
|
||||||
|
@ -25,15 +25,16 @@ module.exports = (db) => {
|
||||||
|
|
||||||
router.post('/add', verifyAuth(), async (req, res) => {
|
router.post('/add', verifyAuth(), async (req, res) => {
|
||||||
if (!req.user.admin) return res.redirect('/')
|
if (!req.user.admin) return res.redirect('/')
|
||||||
|
const username = req.body.newUserUsername.trim()
|
||||||
await db.put({
|
await db.put({
|
||||||
_id: req.body.newUserUsername.trim(),
|
_id: username,
|
||||||
admin: false,
|
admin: false,
|
||||||
wishlist: [],
|
wishlist: [],
|
||||||
|
|
||||||
signupToken: nanoid(SECRET_TOKEN_LENGTH),
|
signupToken: nanoid(SECRET_TOKEN_LENGTH),
|
||||||
expiry: new Date().getTime() + SECRET_TOKEN_LIFETIME
|
expiry: new Date().getTime() + SECRET_TOKEN_LIFETIME
|
||||||
|
|
||||||
})
|
})
|
||||||
|
await ensurePfp(username)
|
||||||
res.redirect(`/admin-settings/edit/${req.body.newUserUsername.trim()}`)
|
res.redirect(`/admin-settings/edit/${req.body.newUserUsername.trim()}`)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,24 @@
|
||||||
const publicRoute = require('../middlewares/publicRoute')
|
const publicRoute = require('../middlewares/publicRoute')
|
||||||
const express = require('express')
|
const express = require('express')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
|
const fs = require('fs/promises')
|
||||||
|
|
||||||
module.exports = ({ db, config }) => {
|
module.exports = ({ db, config }) => {
|
||||||
|
async function ensurePfp (username) {
|
||||||
|
const user = await db.get(username)
|
||||||
|
console.log(user)
|
||||||
|
if (user.pfp) return
|
||||||
|
|
||||||
|
const { rows } = await db.allDocs({ include_docs: true })
|
||||||
|
|
||||||
|
const unfilteredPool = await fs.readdir('static/img/default-pfps')
|
||||||
|
const filteredPool = unfilteredPool.filter(file => !rows.find(row => row.doc.pfp === `${_CC.config.base}img/default-pfps/${file}`))
|
||||||
|
const pool = filteredPool.length ? filteredPool : unfilteredPool
|
||||||
|
|
||||||
|
user.pfp = `${_CC.config.base}img/default-pfps/${_CC._.sample(pool)}`
|
||||||
|
await db.put(user)
|
||||||
|
}
|
||||||
|
|
||||||
const router = express.Router()
|
const router = express.Router()
|
||||||
|
|
||||||
router.use('/', express.static(path.join(__dirname, '../static')))
|
router.use('/', express.static(path.join(__dirname, '../static')))
|
||||||
|
@ -26,7 +42,7 @@ module.exports = ({ db, config }) => {
|
||||||
|
|
||||||
router.use('/setup', require('./setup')(db))
|
router.use('/setup', require('./setup')(db))
|
||||||
|
|
||||||
router.use('/login', require('./login')())
|
router.use('/login', require('./login')({ ensurePfp }))
|
||||||
router.use('/logout', require('./logout')())
|
router.use('/logout', require('./logout')())
|
||||||
router.use('/resetpw', require('./resetpw')(db))
|
router.use('/resetpw', require('./resetpw')(db))
|
||||||
router.use('/confirm-account', require('./confirm-account')(db))
|
router.use('/confirm-account', require('./confirm-account')(db))
|
||||||
|
@ -34,9 +50,9 @@ module.exports = ({ db, config }) => {
|
||||||
router.use('/wishlist', require('./wishlist')(db))
|
router.use('/wishlist', require('./wishlist')(db))
|
||||||
router.use('/supported-sites', require('./supported-sites')())
|
router.use('/supported-sites', require('./supported-sites')())
|
||||||
|
|
||||||
router.use('/profile', require('./profile')(db))
|
router.use('/profile', require('./profile')({ db, ensurePfp }))
|
||||||
|
|
||||||
router.use('/admin-settings', require('./adminSettings')(db))
|
router.use('/admin-settings', require('./adminSettings')({ db, ensurePfp }))
|
||||||
|
|
||||||
router.use('/manifest.json', require('./manifest.json')({ config }))
|
router.use('/manifest.json', require('./manifest.json')({ config }))
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,20 @@ const verifyAuth = require('../../middlewares/verifyAuth')
|
||||||
const bcrypt = require('bcrypt-nodejs')
|
const bcrypt = require('bcrypt-nodejs')
|
||||||
const express = require('express')
|
const express = require('express')
|
||||||
|
|
||||||
module.exports = (db) => {
|
module.exports = ({ db, ensurePfp }) => {
|
||||||
const router = express.Router()
|
const router = express.Router()
|
||||||
|
|
||||||
router.get('/', verifyAuth(), (req, res) => res.render('profile', { title: `Profile Settings - ${req.user._id}` }))
|
router.get('/', verifyAuth(), async (req, res) => {
|
||||||
|
await ensurePfp(req.user._id)
|
||||||
|
res.render('profile', { title: `Profile Settings - ${req.user._id}` })
|
||||||
|
})
|
||||||
|
router.post('/pfp', verifyAuth(), async (req, res) => {
|
||||||
|
req.user.pfp = req.body.image
|
||||||
|
await db.put(req.user)
|
||||||
|
if (!req.user.pfp) await ensurePfp(req.user._id)
|
||||||
|
req.flash('success', 'Saved profile picture!')
|
||||||
|
res.redirect(`${_CC.config.base}profile`)
|
||||||
|
})
|
||||||
router.post('/', verifyAuth(), (req, res) => {
|
router.post('/', verifyAuth(), (req, res) => {
|
||||||
if (req.body.oldPassword && req.body.newPassword) {
|
if (req.body.oldPassword && req.body.newPassword) {
|
||||||
bcrypt.compare(req.body.oldPassword, req.user.password, (err, correct) => {
|
bcrypt.compare(req.body.oldPassword, req.user.password, (err, correct) => {
|
||||||
|
|
BIN
static/img/default-pfps/1.jpg
Normal file
After Width: | Height: | Size: 120 KiB |
BIN
static/img/default-pfps/10.jpg
Normal file
After Width: | Height: | Size: 612 KiB |
BIN
static/img/default-pfps/2.jpg
Normal file
After Width: | Height: | Size: 616 KiB |
BIN
static/img/default-pfps/3.jpg
Normal file
After Width: | Height: | Size: 282 KiB |
BIN
static/img/default-pfps/4.png
Normal file
After Width: | Height: | Size: 258 KiB |
BIN
static/img/default-pfps/5.png
Normal file
After Width: | Height: | Size: 206 KiB |
BIN
static/img/default-pfps/6.jpg
Normal file
After Width: | Height: | Size: 464 KiB |
BIN
static/img/default-pfps/7.jpg
Normal file
After Width: | Height: | Size: 705 KiB |
BIN
static/img/default-pfps/8.jpg
Normal file
After Width: | Height: | Size: 414 KiB |
BIN
static/img/default-pfps/9.jpg
Normal file
After Width: | Height: | Size: 366 KiB |
20
views/profile-password.pug
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
extends layout.pug
|
||||||
|
|
||||||
|
block content
|
||||||
|
form(method='POST')
|
||||||
|
.field
|
||||||
|
label.label Old Password (Required if changing password)
|
||||||
|
.control.has-icons-left
|
||||||
|
input.input(type='password', name='oldPassword', placeholder='pa$$word!')
|
||||||
|
span.icon.is-small.is-left
|
||||||
|
i.fas.fa-lock
|
||||||
|
.field
|
||||||
|
label.label New Password (Leave blank if not changing password)
|
||||||
|
.control.has-icons-left
|
||||||
|
input.input(type='password', name='newPassword', placeholder='pa$$word!')
|
||||||
|
span.icon.is-small.is-left
|
||||||
|
i.fas.fa-lock
|
||||||
|
.field
|
||||||
|
.control
|
||||||
|
input.button.is-primary(type='submit' value='Save')
|
||||||
|
|
|
@ -1,20 +1,31 @@
|
||||||
extends layout.pug
|
extends layout.pug
|
||||||
|
|
||||||
block content
|
block content
|
||||||
form(method='POST')
|
h2 Profile
|
||||||
.field
|
div(style='margin-top: 1em;')
|
||||||
label.label Old Password (Required if changing password)
|
.columns(style='margin-top: 1em;')
|
||||||
.control.has-icons-left
|
.column.is-narrow
|
||||||
input.input(type='password', name='oldPassword', placeholder='pa$$word!')
|
.box
|
||||||
span.icon.is-small.is-left
|
.columns
|
||||||
i.fas.fa-lock
|
.column
|
||||||
.field
|
figure.image.is-square(style='display: inline-block; width: 90%;')
|
||||||
label.label New Password (Leave blank if not changing password)
|
img.is-rounded(src=req.user.pfp, style='object-fit: cover;')
|
||||||
.control.has-icons-left
|
.column.is-narrow
|
||||||
input.input(type='password', name='newPassword', placeholder='pa$$word!')
|
.column
|
||||||
span.icon.is-small.is-left
|
span.is-size-3= req.user._id
|
||||||
i.fas.fa-lock
|
br
|
||||||
.field
|
br
|
||||||
|
form(action=`${_CC.config.base}profile/pfp`, method='POST')
|
||||||
|
label.label Image URL
|
||||||
|
.field.has-addons
|
||||||
.control
|
.control
|
||||||
input.button.is-primary(type='submit' value='Save')
|
input.input(name='image', value=req.user.pfp)
|
||||||
|
.control
|
||||||
|
button.button.is-primary(type='submit')
|
||||||
|
span.icon
|
||||||
|
i.fas.fa-save
|
||||||
|
h2 Security
|
||||||
|
a.button.is-primary(href=`${_CC.config.base}profile/password`)
|
||||||
|
span.icon
|
||||||
|
i.fas.fa-shield-alt
|
||||||
|
span Change Password
|
||||||
|
|
|
@ -6,6 +6,11 @@ block content
|
||||||
li
|
li
|
||||||
a(href=`${_CC.config.base}wishlist/${req.user._id}`)
|
a(href=`${_CC.config.base}wishlist/${req.user._id}`)
|
||||||
.box
|
.box
|
||||||
|
.columns
|
||||||
|
.column.is-1(style='overflow: hidden;')
|
||||||
|
figure.image.is-square.is-fullwidth.is-marginless(style='display: inline-block;')
|
||||||
|
img.is-rounded.is-fullwidth(src=req.user.pfp, style='object-fit: cover;')
|
||||||
|
.column
|
||||||
span=req.user._id
|
span=req.user._id
|
||||||
span : ???/???
|
span : ???/???
|
||||||
progress.progress(value=1, max=1)
|
progress.progress(value=1, max=1)
|
||||||
|
@ -14,6 +19,11 @@ block content
|
||||||
li
|
li
|
||||||
a(href=`${_CC.config.base}wishlist/${user.id}`)
|
a(href=`${_CC.config.base}wishlist/${user.id}`)
|
||||||
.box
|
.box
|
||||||
|
.columns
|
||||||
|
.column.is-1(style='overflow: hidden;')
|
||||||
|
figure.image.is-square.is-fullwidth.is-marginless(style='display: inline-block;')
|
||||||
|
img.is-rounded.is-fullwidth(src=user.doc.pfp, style='object-fit: cover;')
|
||||||
|
.column
|
||||||
span= user.id
|
span= user.id
|
||||||
span : #{totals(user.doc.wishlist).pledged}/#{user.doc.wishlist.length}
|
span : #{totals(user.doc.wishlist).pledged}/#{user.doc.wishlist.length}
|
||||||
progress.progress.is-info(value=totals(user.doc.wishlist).pledged, max=user.doc.wishlist.length)
|
progress.progress.is-info(value=totals(user.doc.wishlist).pledged, max=user.doc.wishlist.length)
|
|
@ -2700,7 +2700,7 @@
|
||||||
"resolved" "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz"
|
"resolved" "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz"
|
||||||
"version" "4.4.2"
|
"version" "4.4.2"
|
||||||
|
|
||||||
"lodash@^4.15.0", "lodash@^4.17.19":
|
"lodash@^4.15.0", "lodash@^4.17.19", "lodash@^4.17.20":
|
||||||
"integrity" "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
|
"integrity" "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
|
||||||
"resolved" "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz"
|
"resolved" "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz"
|
||||||
"version" "4.17.20"
|
"version" "4.17.20"
|
||||||
|
|