IPost/routes/api/userRoutes.js
2025-04-29 00:29:00 +02:00

294 lines
11 KiB
JavaScript

import sharp from 'sharp'
import { ensureExists } from '../../extra_modules/ensureExists.js'
import { SHA256 } from '../../extra_modules/SHA.js'
import getIP from '../../extra_modules/getip.js'
import { getunsigned } from '../../extra_modules/unsign.js'
export const setup = function (router, con, server) {
const config = server.config
const HASHES_DB = config.cookies.server_hashes
const HASHES_COOKIE = config.cookies.client_hashes
const HASHES_DIFF = HASHES_DB - HASHES_COOKIE
const __dirname = server.dirname
router.post('/api/setavatar', function (req, res) {
res.set('Access-Control-Allow-Origin', '')
if (!req.files || Object.keys(req.files).length === 0) {
return res.status(410).send('No files were uploaded. (req.files)')
}
let avatar = req.files.avatar
if (!avatar) {
return res.status(411).send('No files were uploaded. (req.files.)')
}
const avatars = __dirname + '/avatars/'
ensureExists(avatars, function (err) {
if (err) {
return res
.status(500)
.json({ error: "there's been an internal server error." })
}
if (res.locals.avatar) {
try {
unlinkSync(avatars + res.locals.avatar)
} catch (ignored) {}
}
let filename = genstring(95) + '.webp'
while (
existsSync(avatars + '/' + filename) ||
filename === '.webp'
) {
//generate new filename until it's unique
filename = genstring(95) + '.webp'
}
sharp(avatar.data)
.resize({
//resize avatar to 100x100 and convert it to a webp, then store it
width: 100,
height: 100,
})
.webp({
effort: 6,
mixed: true,
})
.toBuffer()
.then(function (data) {
writeFileSync(avatars + filename, data)
let sql = `update ipost.users set User_Avatar=? where User_Name=?`
con.query(
sql,
[filename, encodeURIComponent(res.locals.username)],
function (err) {
if (err) throw err
res.json({ success: 'updated avatar' })
}
)
})
})
/* #swagger.security = [{
"appTokenAuthHeader": []
}] */
})
router.get('/api/getuser', function (_req, res) {
res.json({
username: res.locals.username,
bio: res.locals.bio,
avatar: res.locals.avatar,
userid: res.locals.userid,
})
/* #swagger.security = [{
"appTokenAuthHeader": []
}] */
})
router.get('/api/getalluserinformation', function (req, res) {
res.set('Access-Control-Allow-Origin', '') //we don't want that here
let unsigned = getunsigned(req, res) //has to be asking for it via the cookie
if (!unsigned) return
unsigned = decodeURIComponent(unsigned)
let sql = `select * from ipost.users where User_Name=? and User_PW=?;`
let values = unsigned.split(' ')
values[1] = SHA256(values[1], values[0], HASHES_DIFF)
con.query(sql, values, function (err, result) {
if (err) throw err
if (result[0]) {
res.status(200)
res.json(result[0])
} else {
res.status(402)
res.json({
error: 'you cannot access the api without being logged in',
})
}
})
/* #swagger.security = [{
"appTokenAuthHeader": []
}] */
})
router.get('/api/getotheruser', function (req, res) {
res.set('Access-Control-Allow-Origin', '*')
let username = req.query.user
let sql = `select User_Name,User_Bio,User_Avatar from ipost.users where User_Name=?;`
con.query(sql, [username], function (err, result) {
if (err) throw err
if (result[0]) {
res.json({
username: username,
bio: result[0].User_Bio,
avatar: result[0].User_Avatar,
publicKey: result[0].User_PublicKey,
})
} else {
res.json({ error: 'there is no such user!' })
}
})
})
router.post('/api/setBio', function (req, res) {
res.set('Access-Control-Allow-Origin', '')
let bio = req.body.Bio
if (!bio) {
res.status(410)
res.json({ error: 'no bio set!' })
return
}
bio = encodeURIComponent(bio)
if (bio.length > 100) {
res.status(411)
res.json({ error: 'the bio is too long!' })
return
}
let sql = `update ipost.users set User_Bio=? where User_Name=?`
con.query(
sql,
[bio, encodeURIComponent(res.locals.username)],
function (err) {
if (err) throw err
res.json({ success: 'updated bio' })
}
)
/* #swagger.security = [{
"appTokenAuthHeader": []
}] */
})
router.post('/api/changePW', (req, res) => {
res.set('Access-Control-Allow-Origin', '')
if (typeof req.body.newPW !== 'string') {
res.json({ error: 'incorrect password' })
return
}
if (typeof req.body.currentPW !== 'string') {
res.json({ error: 'incorrect password' })
return
}
if (req.body.newPW.length < 10) {
res.status(410)
res.json({ error: 'password is too short' })
return
}
let hashed_pw = SHA256(
req.body.currentPW,
res.locals.username,
HASHES_DB
)
let hashed_new_pw = SHA256(
req.body.newPW,
res.locals.username,
HASHES_DB
)
let sql = `select * from ipost.users where User_Name=? and User_PW=?;`
let values = [res.locals.username, hashed_pw]
con.query(sql, values, function (err, result) {
if (err) throw err
if (result[0]) {
let sql = `update ipost.users set User_PW=? where User_Name=? and User_PW=?;`
let values = [hashed_new_pw, res.locals.username, hashed_pw]
con.query(sql, values, (err2) => {
if (err2) throw err2
let ip = getIP(req)
let setTo = `${res.locals.username} ${SHA256(req.body.newPW, res.locals.username, HASHES_COOKIE)}`
let cookiesigned = signature.sign(setTo, cookiesecret + ip)
res.cookie('AUTH_COOKIE', cookiesigned, {
maxAge: Math.pow(10, 10),
httpOnly: true,
secure: true,
})
res.json({ success: 'successfully changed password' })
})
} else {
res.json({ error: 'invalid password' })
}
})
/* #swagger.security = [{
"appTokenAuthHeader": []
}] */
})
router.post('/api/changeUsername', function (req, res) {
res.set('Access-Control-Allow-Origin', '')
if (typeof req.body.newUsername !== 'string') {
res.status(410)
res.json({ error: 'incorrect username' })
return
}
if (typeof req.body.currentPW !== 'string') {
res.status(411)
res.json({ error: 'incorrect password' })
return
}
if (req.body.newUsername.length > 100) {
res.status(412)
res.json({ error: 'username is too long' })
return
}
if (req.body.newUsername === res.locals.username) {
res.status(413)
res.json({ error: "username can't be the current one" })
return
}
let hashed_pw = SHA256(
req.body.currentPW,
res.locals.username,
HASHES_DB
)
let hashed_new_pw = SHA256(
req.body.currentPW,
req.body.newUsername,
HASHES_DB
)
let sql = `select * from ipost.users where User_Name=? and User_PW=?;` //check if pw is correct
let values = [res.locals.username, hashed_pw]
con.query(sql, values, function (err, result) {
if (err) throw err
if (result[0]) {
let sql = `select * from ipost.users where User_Name=?;` //check if newUsername isn't already used
let values = [req.body.newUsername]
con.query(sql, values, function (err, result) {
if (err) throw err
if (result[0]) {
res.json({
error: 'user with that username already exists',
})
return
}
let sql = `update ipost.users set User_PW=?,User_Name=? where User_Name=? and User_PW=?;` //change username in users
let values = [
hashed_new_pw,
req.body.newUsername,
res.locals.username,
hashed_pw,
]
con.query(sql, values, function (err) {
if (err) throw err
let ip = getIP(req)
let setTo = `${req.body.newUsername} ${SHA256(req.body.currentPW, req.body.newUsername, HASHES_COOKIE)}`
let cookiesigned = signature.sign(
setTo,
cookiesecret + ip
)
res.cookie('AUTH_COOKIE', cookiesigned, {
maxAge: Math.pow(10, 10),
httpOnly: true,
secure: true,
})
//updated username in the users table, but not yet on posts
//TODO: update username on dms
let sql = `update ipost.posts set post_user_name=? where post_user_name=?;` //change username of every past post sent
let values = [
req.body.newUsername,
res.locals.username,
hashed_pw,
]
con.query(sql, values, () => {
res.json({
success: 'successfully changed username',
}) //done
})
})
})
} else {
res.json({ error: 'invalid password' })
}
})
/* #swagger.security = [{
"appTokenAuthHeader": []
}] */
})
}