crud documents

This commit is contained in:
2019-01-12 21:39:22 +03:00
parent 6d5de7bc49
commit c437d3269e
5 changed files with 329 additions and 1 deletions

View File

@@ -6,6 +6,7 @@ import * as bodyParser from "koa-body";
import * as jwt from "koa-jwt";
import * as logger from "koa-logger";
import { config } from "~config";
import { docsRouter } from "~routes/docs";
import { userRouter } from "~routes/users";
export const app = new Koa();
@@ -31,6 +32,7 @@ app.use(async (ctx, next) => {
});
app.use(userRouter.routes()).use(userRouter.allowedMethods());
app.use(docsRouter.routes()).use(docsRouter.allowedMethods());
app.on("error", (err, ctx) => {
ctx.body = {

View File

@@ -21,4 +21,11 @@ export class Document extends BaseEntity {
@Column({ type: "text" })
public content: string;
constructor(user: User, name: string, content: string) {
super();
this.user = user;
this.name = name;
this.content = content;
}
}

168
src/routes/docs.ts Normal file
View File

@@ -0,0 +1,168 @@
import * as Router from "koa-router";
import { Document } from "~entity/Document";
export const docsRouter = new Router();
export type IDocumentJSON = Pick<Document, "id" | "name" | "content">;
docsRouter.post("/docs/new", async ctx => {
if (!ctx.state.user) {
ctx.throw(401);
}
const { user } = ctx.state;
const { name, content } = ctx.request.body as {
name: string | null;
content: string | null;
};
if (!(name && content)) {
ctx.throw(400);
}
const document = new Document(user.id, name, content);
try {
await document.save();
} catch (e) {
ctx.throw(400);
}
ctx.body = {
error: false,
data: {
id: document.id,
name: document.name,
content: document.content,
},
};
});
docsRouter.patch("/docs/byID/:id", async ctx => {
if (!ctx.state.user) {
ctx.throw(401);
}
const { user } = ctx.state;
const { id } = ctx.params as {
id: number | null;
};
if (!id) {
ctx.throw(400);
}
const { name, content } = ctx.request.body as {
name: string | null;
content: string | null;
};
const document = await Document.findOne({ id, user: user.id });
if (!document) {
ctx.throw(404);
}
if (name) {
document.name = name;
}
if (content) {
document.content = content;
}
try {
await document.save();
} catch (e) {
ctx.throw(400);
}
ctx.body = {
error: false,
data: {
id: document.id,
name: document.name,
content: document.content,
},
};
});
docsRouter.get("/docs/list", async ctx => {
if (!ctx.state.user) {
ctx.throw(401);
}
const { user } = ctx.state;
const documents = await Document.find({ user: user.id });
ctx.body = {
error: false,
data: documents.map(document => ({
id: document.id,
name: document.name,
content: document.content,
})),
};
});
docsRouter.get("/docs/byID/:id", async ctx => {
if (!ctx.state.user) {
ctx.throw(401);
}
const { id } = ctx.params as {
id: number | null;
};
if (!id) {
ctx.throw(400);
}
const { user } = ctx.state;
const document = await Document.findOne({ id, user: user.id });
if (!document) {
ctx.throw(404);
}
ctx.body = {
error: false,
data: {
id: document.id,
name: document.name,
content: document.content,
},
};
});
docsRouter.delete("/docs/byID/:id", async ctx => {
if (!ctx.state.user) {
ctx.throw(401);
}
const { id } = ctx.params as {
id: number | null;
};
if (!id) {
ctx.throw(400);
}
const { user } = ctx.state;
const document = await Document.findOne({ id, user: user.id });
if (!document) {
ctx.throw(404);
}
await document.remove();
ctx.body = {
error: false,
data: true,
};
});

View File

@@ -0,0 +1,145 @@
import { expect } from "chai";
import { connect } from "config/database";
import * as request from "supertest";
import { getConnection } from "typeorm";
import { app } from "~app";
import { Document } from "~entity/Document";
import { IDocumentJSON } from "~routes/docs";
import { ISeed, seedDB } from "./util";
const callback = app.callback();
let seed: ISeed;
describe("users", () => {
before(async () => {
await connect();
});
after(async () => {
await getConnection().close();
});
beforeEach(async () => {
seed = await seedDB();
});
it("should create a document", async () => {
const response = await request(callback)
.post("/docs/new")
.set({
Authorization: `Bearer ${seed.user1.toJWT()}`,
"Content-Type": "application/json",
})
.send({ name: "Test1", content: "Test1" })
.expect(200);
expect(response.body.error).to.be.false;
const document = response.body.data as IDocumentJSON;
expect(document.name).to.be.equal("Test1");
const dbDocument = await Document.findOneOrFail({
id: document.id,
user: seed.user1.id as any,
});
expect(dbDocument.name).to.be.equal("Test1");
});
it("should update a document", async () => {
const response = await request(callback)
.patch(`/docs/byID/${seed.doc1.id}`)
.set({
Authorization: `Bearer ${seed.user1.toJWT()}`,
"Content-Type": "application/json",
})
.send({ name: "Test1", content: "Test1" })
.expect(200);
expect(response.body.error).to.be.false;
const document = response.body.data as IDocumentJSON;
expect(document.name).to.be.equal("Test1");
const dbDocument = await Document.findOne({
id: seed.doc1.id,
user: seed.user1.id as any,
});
expect(dbDocument.name).to.be.equal("Test1");
});
it("should list docs", async () => {
const response = await request(callback)
.get("/docs/list")
.set({
Authorization: `Bearer ${seed.user1.toJWT()}`,
})
.expect(200);
expect(response.body.error).to.be.false;
const documents = response.body.data as IDocumentJSON[];
const userDocs = [
{
id: seed.doc1.id,
name: seed.doc1.name,
content: seed.doc1.content,
},
];
expect(documents).to.deep.equal(userDocs);
});
it("should get a document", async () => {
const response = await request(callback)
.get(`/docs/byID/${seed.doc1.id}`)
.set({
Authorization: `Bearer ${seed.user1.toJWT()}`,
})
.expect(200);
expect(response.body.error).to.be.false;
const document = response.body.data as IDocumentJSON;
const usedDoc = {
id: seed.doc1.id,
name: seed.doc1.name,
content: seed.doc1.content,
};
expect(document).to.deep.equal(usedDoc);
});
it("should not get a document without jwt", async () => {
const response = await request(callback)
.get(`/docs/byID/${seed.doc1.id}`)
.set({
Authorization: `Bearer ${seed.user2.toJWT()}`,
})
.expect(404);
expect(response.body.error).to.be.equal("Not Found");
});
it("should delete a document", async () => {
const response = await request(callback)
.delete(`/docs/byID/${seed.doc1.id}`)
.set({
Authorization: `Bearer ${seed.user1.toJWT()}`,
})
.expect(200);
expect(response.body.error).to.be.false;
const dbDocument = await Document.findOne(seed.doc1.id);
expect(dbDocument).to.be.undefined;
});
});

View File

@@ -1,11 +1,14 @@
import { User } from "entity/User";
import { Document } from "~entity/Document";
export interface ISeed {
user1: User;
user2: User;
doc1: Document;
}
export async function seedDB(): Promise<ISeed> {
await Document.remove(await Document.find());
await User.remove(await User.find());
const user1 = new User("User1", "user1@users.com");
@@ -16,5 +19,8 @@ export async function seedDB(): Promise<ISeed> {
await user2.setPassword("User2");
await user2.save();
return { user1, user2 };
const doc1 = new Document(user1, "Doc1", "Doc1");
await doc1.save();
return { user1, user2, doc1 };
}