general code improvements
This commit is contained in:
@@ -4,21 +4,20 @@ import { ProjectService } from "../service/project.service";
|
|||||||
|
|
||||||
const router = Router();
|
const router = Router();
|
||||||
|
|
||||||
const BASE_PATH = "/projects";
|
export const apiNamespace = "/projects";
|
||||||
|
|
||||||
export const getAllPath = BASE_PATH;
|
router.get(apiNamespace, async (req, res) => {
|
||||||
router.get(getAllPath, async (req, res) => {
|
|
||||||
const projects = await ProjectService.listAllByUserId(req.userId)
|
const projects = await ProjectService.listAllByUserId(req.userId)
|
||||||
|
|
||||||
const response: ProjectDto[] = projects.map<ProjectDto>(project => ({
|
const response: ProjectDto[] = projects.map<ProjectDto>(project => ({
|
||||||
|
id: project.id,
|
||||||
name: project.name
|
name: project.name
|
||||||
}))
|
}))
|
||||||
|
|
||||||
res.json(response)
|
res.json(response)
|
||||||
});
|
});
|
||||||
|
|
||||||
export const createPath = BASE_PATH;
|
router.post(apiNamespace, (req, res) => {
|
||||||
router.post(createPath, (req, res) => {
|
|
||||||
const { name } = req.body;
|
const { name } = req.body;
|
||||||
|
|
||||||
ProjectService.create({
|
ProjectService.create({
|
||||||
@@ -26,6 +25,7 @@ router.post(createPath, (req, res) => {
|
|||||||
userId: req.userId
|
userId: req.userId
|
||||||
}).then(project => {
|
}).then(project => {
|
||||||
const respose: ProjectDto = {
|
const respose: ProjectDto = {
|
||||||
|
id: project.id,
|
||||||
name: project.name
|
name: project.name
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,4 +37,28 @@ router.post(createPath, (req, res) => {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.delete(`${apiNamespace}/:id`, async (req, res, next) => {
|
||||||
|
const { id } = req.params;
|
||||||
|
const projectId = parseInt(id)
|
||||||
|
|
||||||
|
const userProjects = await ProjectService.listAllByUserId(req.userId)
|
||||||
|
const projecToBeDeleted = userProjects.find(project => project.id === projectId)
|
||||||
|
|
||||||
|
if (projecToBeDeleted) {
|
||||||
|
const success = await ProjectService.destroyProject(projecToBeDeleted)
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
res.json({ success })
|
||||||
|
} else {
|
||||||
|
res.status(422).json({
|
||||||
|
error: "Could not delete project"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res.status(404).json({
|
||||||
|
error: "Project not found"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
export const ProjectRoutes = router;
|
export const ProjectRoutes = router;
|
||||||
|
|||||||
@@ -2,15 +2,12 @@ import { Router } from 'express';
|
|||||||
import { UserDto } from '../dto/user.dto';
|
import { UserDto } from '../dto/user.dto';
|
||||||
import { AuthService } from '../service/auth.service';
|
import { AuthService } from '../service/auth.service';
|
||||||
import { UserService } from '../service/user.service';
|
import { UserService } from '../service/user.service';
|
||||||
import { createPath as buildPath } from '../utils/createPath';
|
|
||||||
|
|
||||||
const router = Router();
|
const router = Router();
|
||||||
|
|
||||||
const BASE_PATH = '/users'
|
export const apiNamespace = '/users'
|
||||||
|
|
||||||
export const createPath = BASE_PATH
|
router.post(apiNamespace, (req, res) => {
|
||||||
|
|
||||||
router.post(createPath, (req, res) => {
|
|
||||||
const { email, password } = req.body;
|
const { email, password } = req.body;
|
||||||
|
|
||||||
UserService.create({
|
UserService.create({
|
||||||
@@ -30,8 +27,7 @@ router.post(createPath, (req, res) => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
export const signInPath = buildPath(BASE_PATH, 'sign_in')
|
router.post(`${apiNamespace}/sign_in`, async (req, res) => {
|
||||||
router.post(signInPath, async (req, res) => {
|
|
||||||
const { email, password } = req.body;
|
const { email, password } = req.body;
|
||||||
|
|
||||||
const user = await UserService.findByEmail(email)
|
const user = await UserService.findByEmail(email)
|
||||||
@@ -53,8 +49,7 @@ router.post(signInPath, async (req, res) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export const signOutPath = buildPath(BASE_PATH, 'sign_out')
|
router.delete(`${apiNamespace}/sign_out`, async (req, res) => {
|
||||||
router.delete(signOutPath, async (req, res) => {
|
|
||||||
const token = req.headers['x-access-token']
|
const token = req.headers['x-access-token']
|
||||||
|
|
||||||
if (typeof token === 'string') {
|
if (typeof token === 'string') {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
export type ProjectDto = {
|
export type ProjectDto = {
|
||||||
|
id: number
|
||||||
name: string
|
name: string
|
||||||
}
|
}
|
||||||
@@ -6,8 +6,12 @@ import { cleanDataSource } from "../../utils/cleanDataSource";
|
|||||||
describe("Project", () => {
|
describe("Project", () => {
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await AppDataSource.initialize();
|
await AppDataSource.initialize();
|
||||||
await cleanDataSource(AppDataSource, ["project", "user"]);
|
await cleanDataSource(AppDataSource);
|
||||||
});
|
});
|
||||||
|
afterAll(async () => {
|
||||||
|
await cleanDataSource(AppDataSource);
|
||||||
|
await AppDataSource.destroy()
|
||||||
|
})
|
||||||
|
|
||||||
describe("relations", () => {
|
describe("relations", () => {
|
||||||
it("should have many projects", async () => {
|
it("should have many projects", async () => {
|
||||||
|
|||||||
@@ -7,8 +7,12 @@ import { User } from "../user.entity";
|
|||||||
describe("User", () => {
|
describe("User", () => {
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await AppDataSource.initialize();
|
await AppDataSource.initialize();
|
||||||
await cleanDataSource(AppDataSource, ["project", "user"]);
|
await cleanDataSource(AppDataSource);
|
||||||
});
|
});
|
||||||
|
afterAll(async () => {
|
||||||
|
await cleanDataSource(AppDataSource);
|
||||||
|
await AppDataSource.destroy()
|
||||||
|
})
|
||||||
|
|
||||||
describe("relations", () => {
|
describe("relations", () => {
|
||||||
it("should have many projects", async () => {
|
it("should have many projects", async () => {
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { signInPath, createPath } from '../../controller/users.controller';
|
import {isRouteUnprotected} from '../session.middleware'
|
||||||
import { UNPROTECTED_ROUTES } from '../session.middleware'
|
describe('isRouteUnprotected', () => {
|
||||||
|
it('validate unprotected routes', () => {
|
||||||
describe('Unprotected Routes', () => {
|
expect(isRouteUnprotected('/users')).toBeTruthy()
|
||||||
it('check content', () => {
|
expect(isRouteUnprotected('/users/sign_in')).toBeTruthy()
|
||||||
expect(UNPROTECTED_ROUTES.sort()).toEqual([createPath, signInPath].sort());
|
expect(isRouteUnprotected('/users/sign_out')).toBeTruthy()
|
||||||
|
expect(isRouteUnprotected('/projects')).toBeFalsy()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -1,14 +1,16 @@
|
|||||||
import { Handler, Request, Response } from 'express';
|
import { RequestHandler } from 'express';
|
||||||
import { verify } from 'jsonwebtoken';
|
import { verify } from 'jsonwebtoken';
|
||||||
import { signInPath, createPath } from '../controller/user.controller';
|
import { apiNamespace as userControllerNamespace } from '../controller/user.controller';
|
||||||
import { AuthService } from '../service/auth.service';
|
import { AuthService } from '../service/auth.service';
|
||||||
|
|
||||||
export const UNPROTECTED_ROUTES = [signInPath, createPath];
|
export const isRouteUnprotected = (path: string) => {
|
||||||
|
return path.startsWith(userControllerNamespace)
|
||||||
|
}
|
||||||
|
|
||||||
export const sessionMiddleware: Handler = (req: Request, res: Response, next) => {
|
export const sessionMiddleware: RequestHandler = (req, res, next) => {
|
||||||
const token = req.headers['x-access-token'];
|
const token = req.headers['x-access-token'];
|
||||||
|
|
||||||
if (UNPROTECTED_ROUTES.includes(req.url)) {
|
if (isRouteUnprotected(req.url)) {
|
||||||
next();
|
next();
|
||||||
} else if (typeof token === 'string') {
|
} else if (typeof token === 'string') {
|
||||||
AuthService.isSessionValid(token).then(valid => {
|
AuthService.isSessionValid(token).then(valid => {
|
||||||
|
|||||||
@@ -44,8 +44,6 @@ describe('AuthService', () => {
|
|||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|
||||||
const currentUserEncryptedPassowrd = user.encryptedPassword
|
|
||||||
|
|
||||||
const result = await AuthService.isUserPasswordValid(user, 'example');
|
const result = await AuthService.isUserPasswordValid(user, 'example');
|
||||||
|
|
||||||
expect(result).toBeTruthy()
|
expect(result).toBeTruthy()
|
||||||
@@ -66,8 +64,6 @@ describe('AuthService', () => {
|
|||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|
||||||
const currentUserEncryptedPassowrd = user.encryptedPassword
|
|
||||||
|
|
||||||
const result = await AuthService.isUserPasswordValid(user, 'example2');
|
const result = await AuthService.isUserPasswordValid(user, 'example2');
|
||||||
|
|
||||||
expect(result).toBeFalsy()
|
expect(result).toBeFalsy()
|
||||||
|
|||||||
@@ -28,7 +28,17 @@ async function listAllByUserId(userId: User["id"]): Promise<Project[]> {
|
|||||||
return query.getMany();
|
return query.getMany();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function destroyProject(project: Project): Promise<boolean>{
|
||||||
|
const query = projectRepository.createQueryBuilder();
|
||||||
|
query.where('"id" = :projectId', { projectId: project.id });
|
||||||
|
|
||||||
|
const result = await query.delete().execute()
|
||||||
|
|
||||||
|
return result.affected > 0;
|
||||||
|
}
|
||||||
|
|
||||||
export const ProjectService = {
|
export const ProjectService = {
|
||||||
create,
|
create,
|
||||||
listAllByUserId,
|
listAllByUserId,
|
||||||
|
destroyProject
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { DataSource } from "typeorm";
|
|||||||
|
|
||||||
export const cleanDataSource = async (
|
export const cleanDataSource = async (
|
||||||
dataSource: DataSource,
|
dataSource: DataSource,
|
||||||
entityNames: string[]
|
entityNames: string[] = ["project", "user"]
|
||||||
) => {
|
) => {
|
||||||
if (process.env.NODE_ENV !== "test") {
|
if (process.env.NODE_ENV !== "test") {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
export const createPath = (...args: string[]): string => {
|
|
||||||
return args.join('/')
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user