IPost/routes/api/userRoutes.js
Mystikfluu 0ea07f9ec8 update api documentation
add authentication
2023-04-21 00:17:05 +02:00

234 lines
10 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;
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": []
}] */
});
}