Bladeren bron

Use raw sql in user route

sbkwgh 7 jaren geleden
bovenliggende
commit
dc0d7da29b
2 gewijzigde bestanden met toevoegingen van 161 en 75 verwijderingen
  1. 69 12
      routes/user.js
  2. 92 63
      test/adminUser.js

+ 69 - 12
routes/user.js

@@ -5,7 +5,7 @@ let router = express.Router()
 
 const Errors = require('../lib/errors.js')
 let {
-	User, Post, ProfilePicture, AdminToken, Thread, Category, Sequelize, Ip, Ban
+	User, Post, ProfilePicture, AdminToken, Thread, Category, Sequelize, Ip, Ban, sequelize
 } = require('../models')
 let pagination = require('../lib/pagination.js')
 
@@ -294,19 +294,76 @@ router.all('*', (req, res, next) => {
 
 router.get('/', async (req, res, next) => {
 	try {
-		if(req.query.admin) {
-			let admins = await User.findAll({
-				where: { admin: true },
-				attributes: {
-					exclude: ['hash']
-				}
-			})
-
-			res.json(admins)
+		let sortFields = {
+			id: 'id',
+			username: 'username',
+			date: 'createdAt'
+		};
+		let offset = Number.isInteger(+req.query.offset) ? +req.query.offset : 0;
+		let havingClause;
+		if(req.query.role === 'admin') {
+			havingClause = 'HAVING Users.admin = true';
+		} else if(req.query.role === 'user') {
+			havingClause = 'HAVING Users.admin = false';
 		} else {
-			res.json({})
+			havingClause = '';
 		}
+
+		let sql = `
+			SELECT X.username, X.admin, X.createdAt, 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.UserId
+				GROUP BY Users.id
+				${havingClause}
+				ORDER BY Users.${sortFields[req.query.sort] || 'id'} ${req.query.order === 'asc' ? 'ASC' : 'DESC'}
+				LIMIT 30
+				OFFSET ${offset}
+			) as X
+			LEFT OUTER JOIN threads
+			ON X.id = Threads.UserId
+			GROUP BY X.id
+		`;
+
+		let users = await sequelize.query(sql, {
+			model: User
+		});
+
+		res.json(users)
 	} catch (e) { next(e) }
 })
 
-module.exports = router
+module.exports = router
+
+/*
+router.get('/', async (req, res, next) => {
+	try {
+		let sortOptions = {
+			'username': 'username',
+			'date': 'createdAt',
+			'threads': '',
+			'posts': ''
+		};
+		let sort = sortOptions[req.query.sort];
+		let order = req.query.order === 'asc' ? 'ASC' : 'DESC';
+
+		let users = await User.findAll({
+			include: [Post, Thread],
+			attributes: [
+				'username',
+				'id',
+				'createdAt',
+				[Sequelize.fn('COUNT', Sequelize.col('Posts.id')), 'postsCount'],
+			//	[Sequelize.fn('COUNT', Sequelize.col('Threads.id')), 'threadsCount']
+			],
+			limit: 30,
+		//	offset: req.query.offset || 0,
+			logging: console.log
+		})
+
+		res.json(users);
+	} catch (err) { next(err) }
+});
+*/

+ 92 - 63
test/adminUser.js

@@ -20,92 +20,113 @@ describe('GET /user', () => {
 		const NumThreads = 5;
 		const NumPosts = 30;
 
-		function createCategory  () {
-			return Category.create({
-				name: 'category-name'
-			});
-		}
-
-		async function createUsers (category) {
+		async function createUsers () {
 			let userPromises = [];
+
+			userPromises.push(
+				adminAgent
+					.post('/api/v1/user')
+					.set('content-type', 'application/json')
+					.send({
+						username: 'adminuser',
+						password: 'password',
+						admin: true
+					})
+			)
+
 			for(let i = 0; i < NumUsers; i++) {
-				userPromises.push(
-					User.create({
-						username: i === 1 ? 'admin123' : 'username' + i,
-						hash: 'password',
-						admin: i === 1
+				let promise = chai.request(server)
+					.post('/api/v1/user')
+					.set('content-type', 'application/json')
+					.send({
+						username: 'username' + i,
+						password: 'password',
+						admin: false
 					})
-				)
+
+				userPromises.push(promise)
 			}
+
 			let users = await Promise.all(userPromises);
 
-			return { category, users };
+			return users;
 		}
 
-		async function createThreads (params) {
-			let { category, users } = params;
+		function createCategory  () {
+			return adminAgent
+				.post('/api/v1/category')
+				.set('content-type', 'application/json')
+				.send({ name: 'category-name' })
+		}
+
+		async function getUserAgents () {
+			let agents = [];
+			for(let i = 0; i < 5; i++) {
+				agents.push(chai.request.agent(server))
+			}
+
+			let agentPromises = agents.map((agent, i) => {
+				let username = 'username' + i;
+
+				return agent
+					.post('/api/v1/user/' + username + '/login')
+					.set('content-type', 'application/json')
+					.send({
+						username: username,
+						password: 'password',
+					});
+			});
+			await Promise.all(agentPromises);
 
+			return agents;
+		}
+
+		async function createThreads (agents) {
 			let threadPromises = [];
+
 			for(let i = 0; i < NumThreads; i++) {
+				let agent = agents[i % agents.length];
+
 				threadPromises.push(
-					Thread.create({
-						name: 'thread' + i
-					})
+					agent
+						.post('/api/v1/thread')
+						.set('content-type', 'application/json')
+						.send({ name: 'thread' + i, category: 'category-name' })
 				);
 			}
-			let threads = await Promise.all(threadPromises);
+			await Promise.all(threadPromises);
 
-			threads.map(async (thread, i) => {
-				await thread.setCategory(category);
-				await thread.setUser(users[i]);
-			})
-
-			return { threads, category, users };
+			return agents;
 		}
 
-		async function createPosts (params) {
-			let { threads, category, users } = params;
-
+		async function createPosts (agents) {
 			let postPromises = [];
 			for(let i = 0; i < NumPosts; i++) {
 				postPromises.push(
-					Post.create({
-						content: 'post' + i,
-						postNumber: 1
-					})
+					agents[i%agents.length]
+						.post('/api/v1/post')
+						.set('content-type', 'application/json')
+						.send({ content: 'post', threadId: i%NumThreads+1 })
 				);
 			}
-			let posts = await Promise.all(postPromises);
-
-
-			posts.map(async (post, i) => {
-				await post.setUser(users[i % NumUsers]);
-				await post.setThread(threads[i % NumThreads]);
-			});
+			await Promise.all(postPromises);
 
-			return posts;
-		}
-
-		function login () {
-			return adminAgent
-				.post('/api/v1/user/admin123/login')
-				.set('content-type', 'application/json')
-				.send({
-					password: 'password'
-				});
+			return agents;
 		}
 
 		function createMockData () {
-			createCategory()
-				.then(createUsers)
+			createUsers()
+				.then(createCategory)
+				.then(getUserAgents)
 				.then(createThreads)
 				.then(createPosts)
-				.then(login)
 				.then(_ => {
+					console.log('Completed');
 					done();
 				})
 				.catch(err => {
-					console.log(err)
+				console.log(err);
+					done(err);
 				})
 		}
 
@@ -120,22 +141,30 @@ describe('GET /user', () => {
 	after(() => sequelize.sync({ force: true }) )
 
 	it('should get first 30 users, by default ordered by username descending', (done) => {
-		adminAgent.get('/api/v1/user').end((err, res) => {
+		adminAgent.get('/api/v1/user?role=admin').end((err, res) => {
 			if(err) done(err);
 
+			console.log(res.body)
+
 			res.body.should.have.length(30);
-			res.body[0].username.should.equal('admin123');
-			res.body[29].username.should.equal('username28');
+			res.body[0].id.should.equal(65);
+			//res.body[0].postsCount.should.equal(2);
+			//res.body[0].threadsCount.should.equal(1);
+
+			res.body[29].id.should.equal(36);
 
 			done();
 		});
 	})
-	it('should paginate correctly', (done) => {
+	/*it('should paginate correctly', (done) => {
 		adminAgent.get('/api/v1/user?offset=60').end((err, res) => {
 			if(err) done(err);
 
 			res.body.should.have.length(30);
 			res.body[0].username.should.equal('username60');
+			res.body[0].postsCount.should.equal(0);
+			res.body[0].threadsCount.should.equal(0);
+
 			res.body[29].username.should.equal('username64');
 
 			done();
@@ -152,11 +181,11 @@ describe('GET /user', () => {
 			done();
 		});
 	})
-	/*it('should enable filtering by username', (done) => {
+	it('should enable filtering by username', (done) => {
 		adminAgent.get('/api/v1/user', (err, res) => {
 			res.body.should.contain
 		});
-	})*/
+	})
 	it('should enable filtering by role (admin or user)', (done) => {
 		adminAgent.get('/api/v1/user?role=admin').end((err, res) => {
 			if(err) done(err);
@@ -167,11 +196,11 @@ describe('GET /user', () => {
 			done();
 		});
 	})
-	/*it('should enable sorting by date joined', (done) => {
+	it('should enable sorting by date joined', (done) => {
 		adminAgent.get('/api/v1/user', (err, res) => {
 			res.body.should.contain
 		});
-	})*/
+	})
 	it('should enable sorting by number of posts', (done) => {
 		adminAgent.get('/api/v1/user?sort=posts&order=asc').end((err, res) => {
 			if(err) done(err);
@@ -201,5 +230,5 @@ describe('GET /user', () => {
 
 			done();
 		});
-	})
+	})*/
 })