cubash-archive/routes/user.js

232 lines
6.4 KiB
JavaScript

/*
@swagger
components:
schemas:
Book:
type: object
required:
- title
- author
- finished
properties:
id:
type: integer
description: The auto-generated id of the book.
title:
type: string
description: The title of your book.
author:
type: string
description: Who wrote the book?
finished:
type: boolean
description: Have you finished reading it?
createdAt:
type: string
format: date
description: The date of the record creation.
example:
title: The Pragmatic Programmer
author: Andy Hunt / Dave Thomas
finished: true
*/
let bcrypt = require('bcryptjs')
let multer = require('multer')
let express = require('express')
let router = express.Router()
const auth = require('../lib/auth')
var Recaptcha = require('express-recaptcha').RecaptchaV3;
var recaptcha = new Recaptcha('6LdlbrwZAAAAAKvtcVQhVl_QaNOqmQ4PgyW3SKHy', '6LdlbrwZAAAAAMAWPVDrL8eNPxrws6AMDtLf1bgd');
var reCAPTCHASecret = "6LdlbrwZAAAAAKvtcVQhVl_QaNOqmQ4PgyW3SKHy";
const Errors = require('../lib/errors.js')
var format = require('date-format');
let {
User, Post, ProfilePicture, Item, userWall, StaffApplications, Inventory, AdminToken, PassKey, Thread, Category, Sequelize, Ip, Ban, sequelize
} = require('../models')
let pagination = require('../lib/pagination.js')
const sgMail = require('@sendgrid/mail');
const MailGen = require('mailgen')
const crypto = require("crypto")
const cryptoRandomString = require("crypto-random-string")
const rateLimit = require("express-rate-limit");
const emailLimiter = rateLimit({
windowMs: 60000,
max: 1, // limit each IP to 100 requests per windowMs
message: "{\"errors\":[{\"name\":\"rateLimit\",\"message\":\"You may only make 1 request to this endpoint per minute.\",\"status\":429}]}"
});
function setUserSession(req, res, username, UserId, admin) {
req.userData.loggedIn = true
req.userData.username = username
req.userData.UserId = UserId
res.cookie('username', username)
if(admin) { req.userData.admin = true }
}
router.get('/:username', async(req, res, next) => {
try {
let queryObj = {
attributes: {exclude: ['hash', 'email', 'emailVerified', 'koins', 'currency2', 'emailToken', 'passwordResetExpiry', 'passwordResetToken', 'experimentMode', 'developerMode', 'cookieOptOut', 'deleteCode', 'jwtOffset']},
where: {username: req.params.username}
}
if (req.query.posts) {
let {from, limit} = pagination.getPaginationProps(req.query, true)
let postInclude = {
model: Post,
include: Post.includeOptions(),
limit,
order: [['id', 'DESC']]
}
if (from !== null) {
postInclude.where = {id: {$lte: from}}
}
queryObj.include = [postInclude]
let user = await User.findOne(queryObj)
if (!user) throw Errors.accountDoesNotExist
let meta = await user.getMeta(limit)
res.json(Object.assign(user.toJSON(limit), {meta}))
} else if (req.query.wall) {
let {from, limit} = pagination.getPaginationProps(req.query, true)
let postInclude = {
model: userWall,
include: userWall.includeOptions(),
limit,
order: [['id', 'DESC']],
}
if (from !== null) {
postInclude.where = {id: {$lte: from}}
}
queryObj.include = [postInclude]
let user = await User.findOne(queryObj)
if (!user) throw Errors.accountDoesNotExist
if (user.userWallOptOut) {
res.status(200)
res.json({userWalls: []})
}
res.json(Object.assign(user.toJSON(limit)))
} else if (req.query.threads) {
let queryString = ''
Object.keys(req.query).forEach(query => {
queryString += `&${query}=${req.query[query]}`
})
res.redirect('/api/v1/forums/category/ALL?username=' + req.params.username + queryString)
} else if(req.query.marketplace) {
let {from, limit} = pagination.getPaginationProps(req.query, true)
let UserId = await User.findOne({
where: {
username: req.params.username
}
})
if(!UserId) throw Errors.accountDoesNotExist
let marketplace = await Item.findAll({
where: {
UserId: UserId.id
}
})
let postInclude = {
model: Item,
include: { model: User, attributes: ['username', 'createdAt', 'id', 'color', 'picture', 'locked', 'admin', 'booster', 'executive', 'bot'] },
limit,
order: [['id', 'DESC']],
}
queryObj.include = [postInclude]
let user = await User.findOne(queryObj)
res.status(200)
let meta = await user.getMeta(limit)
res.json(Object.assign(user.toJSON(limit), {meta}))
} else if(req.query.inventory) {
let {from, limit} = pagination.getPaginationProps(req.query, true)
let userLookup = await User.findOne({
where: {
username: req.params.username
}
})
let marketplace = await Inventory.findAll({
where: {
UserId: userLookup.id
}
})
let postInclude = {
model: Inventory,
include: { model: Item, include: { model: User, attributes: ['username', 'createdAt', 'id', 'color', 'picture', 'locked', 'admin', 'booster', 'executive', 'bot'] } },
limit,
order: [['id', 'DESC']],
}
queryObj.include = [postInclude]
let user = await User.findOne(queryObj)
res.status(200)
let meta = await user.getMeta(limit)
res.json(Object.assign(user.toJSON(limit), {meta}))
} else {
let user = await User.findOne(queryObj)
if(!user) throw Errors.accountDoesNotExist
res.json(user.toJSON())
}
} catch (err) { next(err) }
})
router.get('/', async(req, res, next) => {
try {
let sortFields = {
createdAt: 'X.id',
username: 'X.username',
threadCount: 'threadCount',
postCount: 'postCount'
};
let offset = Number.isInteger(+req.query.offset) ? +req.query.offset : 0;
let havingClause = '';
if(req.query.search) {
//I.e. if there is not already a HAVING clause
if(!havingClause.length) {
havingClause = 'HAVING ';
} else {
havingClause += ' AND ';
}
havingClause += 'Users.username LIKE $search';
}
let sql = `
SELECT X.username, X.postCount, COUNT(Threads.id) as threadCount
FROM (
SELECT Users.*, COUNT(Posts.id) as postCount
FROM Users
LEFT OUTER JOIN Posts
ON Users.id = Posts.UserUsername
GROUP BY Users.username
${havingClause}
) as X
LEFT OUTER JOIN threads
ON X.username = Threads.UserUsername
GROUP BY X.id
ORDER BY ${sortFields[req.query.sort] || 'X.id'} ${req.query.order === 'asc' ? 'DESC' : 'ASC'}
LIMIT 30
OFFSET ${offset}
`;
let users = await sequelize.query(sql, {
model: User,
bind: { search: req.query.search + '%' }
});
res.json(users)
} catch (e) { next(e) }
})
module.exports = router;