diff --git a/CHANGELOG.md b/CHANGELOG.md index c354f63139ca6e4b3c72bd00e7a1392a8869f293..f06253a64b547aaf57b9299835ebf0d115b7a204 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 1.1.10 - 03-02-2020 +### Added +- Route to list forms #61 (Richard Heise) +## Changed +- List from FormQUeryBuilder now lists an user's forms + ## 1.1.9 - 03-02-2020 ### Added - Route to change an user's password #63 (Richard Heise) diff --git a/package.json b/package.json index 492508044d4aece1b6b977b568c07a5dc980b057..c70479850c6d066bb460ec2ee119f60b7428445a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "form-creator-api", - "version": "1.1.9", + "version": "1.1.10", "description": "RESTful API used to manage and answer forms.", "main": "index.js", "scripts": { diff --git a/src/api/controllers/form.spec.ts b/src/api/controllers/form.spec.ts index a413be6dbf3104ad7417a34b87c6bf673df72b11..fa1d93805dc4c8b9ead163a1b06db69d79c5e3ef 100644 --- a/src/api/controllers/form.spec.ts +++ b/src/api/controllers/form.spec.ts @@ -93,28 +93,6 @@ describe("Initial test User", () => { describe("API data controller - form", () => { - it("should respond 200 when getting a list of forms", (done) => { - request(server) - .get("/form") - .expect(200) - .expect((res: any) => { - expect(res.body).to.be.an("array"); - expect(res.body[0].id).to.be.equal(1); - expect(res.body[0].title).to.be.equal("Form Title 1"); - expect(res.body[0].description).to.be.equal("Form Description 1"); - - expect(res.body[1].id).to.be.equal(2); - expect(res.body[1].title).to.be.equal("Form Title 2"); - expect(res.body[1].description).to.be.equal("Form Description 2"); - - expect(res.body[2].id).to.be.equal(3); - expect(res.body[2].title).to.be.equal("Form Title 3"); - expect(res.body[2].description).to.be.equal("Form Description 3"); - - }) - .end(done); - }); - it("should respond 200 when getting valid form", (done) => { request(server) diff --git a/src/api/controllers/form.ts b/src/api/controllers/form.ts index 6a359205625f47e27603686293a780cc1e8737f3..7a45d10546bc53de4272e2011de3cc2b55357c1f 100644 --- a/src/api/controllers/form.ts +++ b/src/api/controllers/form.ts @@ -29,27 +29,6 @@ import { Request } from "../apiTypes"; export class FormCtrl { - public static list(req: Request, res: Response, next: NextFunction) { - - req.db.form.list((err: Error, forms?: Form[]) => { - if (err){ - res.status(500).json({ - message: "Could not list forms. Some error has occurred. Check error property for details.", - error: err - }); - return; - } - - const mappedForms = forms.map(form => ({ - id: form.id - , title: form.title - , description: form.description - })); - res.json(mappedForms); - return; - }); - } - public static read(req: Request, res: Response, next: NextFunction) { req.db.form.read(req.params.id, (err: Error, form?: Form) => { diff --git a/src/api/controllers/user.spec.ts b/src/api/controllers/user.spec.ts index 3787cd1a042cb26b7684099eeca18059049e8334..1f7145862fb8c82bd782e074a7dc17f3eda8134b 100644 --- a/src/api/controllers/user.spec.ts +++ b/src/api/controllers/user.spec.ts @@ -183,6 +183,21 @@ describe ("API data controller", () => { }) .end(done); }); + + it("Should respond 200 when listing forms from an user", (done) => { + + request(server) + .get("/user/list/1") + .expect(200) + .expect((res: any) => { + expect(res.body).to.be.an("array"); + let j: number = 4; + for (const i of res.body) { + expect(i.id).to.be.eql(j++); + } + }) + .end(done); + }); it("Should respond 200 when deleting an user from the database", (done) => { diff --git a/src/api/controllers/user.ts b/src/api/controllers/user.ts index 8c3585cff8aa701e7bbb96ddca47fb02f8b16b03..0a33425b16f44cf9be2cd65f7f0482c7bbdaa30c 100644 --- a/src/api/controllers/user.ts +++ b/src/api/controllers/user.ts @@ -26,6 +26,7 @@ import { OptHandler } from "../../utils/optHandler"; import { waterfall } from "async"; import * as bcrypt from "bcrypt"; import * as jwt from "jsonwebtoken"; +import { Form } from "../../core/form"; export class UserCtrl { @@ -228,6 +229,27 @@ export class UserCtrl { }); return; } + }); + } + + public static listForms (req: Request, res: Response, next: NextFunction) { + + req.db.form.list(req.params.id, (err: Error, forms?: Form[]) => { + if (err){ + res.status(500).json({ + message: "Could not list forms. Some error has occurred. Check error property for details.", + error: err + }); + return; + } + + const mappedForms = forms.map(form => ({ + id: form.id + , title: form.title + , description: form.description + })); + + res.json(mappedForms); return; }); } diff --git a/src/core/user.ts b/src/core/user.ts index afa28b6aec8cd3d03b0293a4c69910c350e7d8e1..de97d8c184d15207b41e9786e3f4e79985ef82da 100644 --- a/src/core/user.ts +++ b/src/core/user.ts @@ -31,6 +31,8 @@ export interface UserOptions { hash: string; /** Determine either an user is electable or not */ enabled?: boolean; + /** User forms */ + forms?: number[]; } /** @@ -47,6 +49,8 @@ export class User { public readonly hash: string; /** Determine either an user is electable or not */ public readonly enabled: boolean; + /** User forms */ + public readonly forms: number[]; /** * Creates a new instance of User class. @@ -61,5 +65,6 @@ export class User { if ((options.enabled === undefined) || (options.enabled === null) ) { this.enabled = true; } + this.forms = options.forms ? options.forms : null; } } diff --git a/src/main.ts b/src/main.ts index 67b1f27cde6c0b1f9d59ba953462256d5d6963cc..12b35c189fdc30ba5e17372a09ff47f2e6d40787 100755 --- a/src/main.ts +++ b/src/main.ts @@ -50,7 +50,6 @@ app.use("/", DbHandlerMw()); // Setup routes -app.get("/form/", FormCtrl.list); app.get("/form/:id", FormCtrl.read); app.put("/form/:id", tokenValidation(), FormCtrl.update); app.post("/form", tokenValidation(), FormCtrl.write); @@ -59,6 +58,7 @@ app.post("/user/signUp", UserCtrl.signUp); app.post("/user/signIn", UserCtrl.signIn); app.delete("/user/deleteData/:id", tokenValidation(), UserCtrl.deleteData); app.put("/user/changePassword", tokenValidation(), UserCtrl.changePassword); +app.get("/user/list/:id", UserCtrl.listForms); // Listening diff --git a/src/utils/dbHandler.spec.ts b/src/utils/dbHandler.spec.ts index e79563421d08500297748b982efbeeaa2e3335e1..026fb3d417147c6609cca572c2f07a20db8cb8b4 100644 --- a/src/utils/dbHandler.spec.ts +++ b/src/utils/dbHandler.spec.ts @@ -290,18 +290,6 @@ describe("Database Handler", () => { describe("Read and Write on Database", () => { const dbhandler = new DbHandler(configs.poolconfig); - it("should list all forms", (done) => { - dbhandler.form.list((err: Error, forms?: Form[]) => { - expect(err).to.be.a("null"); - expect(forms.length).to.be.equal(4); - for (let i = 0; i < forms.length; i++){ - expect(forms[i].id).to.be.equal(i + 1); - expect(forms[i].title).to.be.equal("Form Title " + (i + 1)); - expect(forms[i].description).to.be.equal("Form Description " + (i + 1)); - } - done(); - }); - }); it("should read an existent form", (done) => { dbhandler.form.read(1, (err: Error, form: Form) => { diff --git a/src/utils/formQueryBuilder.ts b/src/utils/formQueryBuilder.ts index 2150629450f698402ce22e0d4a83a83bcd496995..578cc5e6e59240e17143151db067f28ffebda33c 100644 --- a/src/utils/formQueryBuilder.ts +++ b/src/utils/formQueryBuilder.ts @@ -53,13 +53,12 @@ export class FormQueryBuilder extends QueryBuilder { } /** - * Asynchronously list all forms using a transaction. - * @param cb - Callback function which contains the data read. + * Asynchronously lists all forms from an user. + * @param userId - User ID who owns the form list. + * @param cb - Callback function which contains information about method's execution. * @param cb.err - Error information when the method fails. - * @param cb.form - list of form or a empty list if there is no form on database. */ - public list(cb: (err: Error, result?: Form[]) => void) { - + public list(userId: number, cb: (err: Error, forms?: Form[]) => void) { waterfall([ (callback: (err: Error, result?: QueryResult) => void) => { this.begin((error: Error, results?: QueryResult) => { @@ -68,7 +67,7 @@ export class FormQueryBuilder extends QueryBuilder { }, (callback: (err: Error, result?: Form[]) => void) => { - this.executeListForms((error: Error, results?: Form[]) => { + this.executeListForms(userId, (error: Error, results?: Form[]) => { callback(error, results); }); }, @@ -90,16 +89,20 @@ export class FormQueryBuilder extends QueryBuilder { } /** - * Asynchronously get all forms from database without transactions. - * @param cb - Callback function which contains the data read. + * Asynchronously lists all forms from an user in the database. + * @param userId - User ID who owns the forms. + * @param cb - Callback function. * @param cb.err - Error information when the method fails. - * @param cb.form - list of form or a empty list if there is no form on database. */ - private executeListForms(cb: (err: Error, result?: Form[]) => void) { - const queryString: string = "SELECT id, title, description FROM form;"; + private executeListForms(userId: number, cb: (err: Error, forms?: Form[]) => void) { + const queryString: string = "SELECT t1.id,t1.title,t1.description FROM form t1 \ + INNER JOIN form_owner t2 ON (t1.id=t2.id_form \ + AND t2.id_user=$1)"; const query: QueryOptions = { query: queryString - , parameters: [] + , parameters: [ + userId + ] }; const forms: Form[] = []; @@ -125,7 +128,6 @@ export class FormQueryBuilder extends QueryBuilder { cb(null, forms); }); - } /** diff --git a/src/utils/optHandler.ts b/src/utils/optHandler.ts index 32b30309d687b6f61785ac08614da6197394a8f2..cd97a10263a3db8c9886ab4907db168094442832 100644 --- a/src/utils/optHandler.ts +++ b/src/utils/optHandler.ts @@ -269,6 +269,7 @@ export class OptHandler { , email: obj.email , id: obj.id , hash: hashedPw + , forms: obj.forms }; return option; diff --git a/src/utils/userQueryBuilder.ts b/src/utils/userQueryBuilder.ts index ba3d9e788bd497b77f9c01b627b7e8e3d1c88329..1fd8a0973d275d73ddc829ad163e6f4b5e625311 100644 --- a/src/utils/userQueryBuilder.ts +++ b/src/utils/userQueryBuilder.ts @@ -20,7 +20,6 @@ */ import { eachSeries, map, waterfall } from "async"; -import { SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION } from "constants"; import { Pool, PoolConfig, QueryResult } from "pg"; import { User, UserOptions } from "../core/user"; import { ErrorHandler} from "./errorHandler"; @@ -94,6 +93,7 @@ export class UserQueryBuilder extends QueryBuilder { , email: result.rows[0]["email"] , hash: result.rows[0]["hash"] , enabled: result.rows[0]["enabled"] + , forms: null }; cb(error, userTmp);