routing-controllers
routing-controllers copied to clipboard
Order of routes matters
Hello,
awesome project. I have an issue though. My JSON-Controller looks like this:
import {Router, Request, Response, NextFunction} from 'express';
import {getEntityManager, Repository} from "typeorm";
import {User} from "../models/user";
import {authService} from "../services/authservice";
import {getConnectionManager} from "typeorm";
import {JsonController} from "routing-controllers/decorator/JsonController";
import {Authorized, Body, Get, Post, Res} from "routing-controllers";
interface authData {
password: string;
username: string;
email?: string;
}
@JsonController("/users")
export class UsersController {
private userRepository: Repository<User>;
constructor() {
this.userRepository = getConnectionManager().get().getRepository(User);
}
@Post("/sign_up")
public async signUp(@Body() authData: authData, @Res() res: Response) {
if (authData.username && authData.email && authData.password) {
let user = await this.userRepository.findOneById(authData.username);
const count = await this.userRepository.count();
if (!user) {
user = new User();
user.username = authData.username;
user.email = authData.email;
user = await authService.setHashedPassword(user, authData.password);
user.admnin = count === 0;
this.userRepository.persist(user);
res.send(user);
}
else {
res.send("Already exists");
}
} else {
res.send("Incomplete");
}
}
@Post("/sign_in")
public async signIn(@Body() authData: authData, @Res() res: Response) {
if (authData.username && authData.password) {
let user = await this.userRepository.findOneById(authData.username);
if (user) {
console.log(user);
const valid = await authService.checkPassword(authData.password, user);
if (valid) {
authService.setTokenForUser(res, user).then(() => {
res.send("logged in");
});
} else {
res.send("Wrong information");
}
} else {
res.send("Not found");
}
} else {
res.send("Incomplete");
}
}
@Authorized()
@Get("/auto")
public async checkAuthentication(@Res() res: Response) {
res.send("Authorized");
}
}
This crashes on the sign_in route. Cannot POST /users/sign_in
. Funny enough if I change the order to have the GET route at the top of the class like this:
import {Router, Request, Response, NextFunction} from 'express';
import {getEntityManager, Repository} from "typeorm";
import {User} from "../models/user";
import {authService} from "../services/authservice";
import {getConnectionManager} from "typeorm";
import {JsonController} from "routing-controllers/decorator/JsonController";
import {Authorized, Body, Get, Post, Res} from "routing-controllers";
interface authData {
password: string;
username: string;
email?: string;
}
@JsonController("/users")
export class UsersController {
private userRepository: Repository<User>;
constructor() {
this.userRepository = getConnectionManager().get().getRepository(User);
}
@Authorized()
@Get("/auto")
public async checkAuthentication(@Res() res: Response) {
res.send("Authorized");
}
@Post("/sign_up")
public async signUp(@Body() authData: authData, @Res() res: Response) {
if (authData.username && authData.email && authData.password) {
let user = await this.userRepository.findOneById(authData.username);
const count = await this.userRepository.count();
if (!user) {
user = new User();
user.username = authData.username;
user.email = authData.email;
user = await authService.setHashedPassword(user, authData.password);
user.admnin = count === 0;
this.userRepository.persist(user);
res.send(user);
}
else {
res.send("Already exists");
}
} else {
res.send("Incomplete");
}
}
@Post("/sign_in")
public async signIn(@Body() authData: authData, @Res() res: Response) {
if (authData.username && authData.password) {
let user = await this.userRepository.findOneById(authData.username);
if (user) {
console.log(user);
const valid = await authService.checkPassword(authData.password, user);
if (valid) {
authService.setTokenForUser(res, user).then(() => {
res.send("logged in");
});
} else {
res.send("Wrong information");
}
} else {
res.send("Not found");
}
} else {
res.send("Incomplete");
}
}
}
everything works fine. Is there something I am missing or is this a bug?
Thanks a lot, Christian
sounds strange, does it work if you remove @Authorized()
decorator?
No, that doesn't solve it. Only the order seems to solve it. Interestingly enough it only seems to crash in signIn. SignIn is being called though.
setTokenForUser is defined like this:
setTokenForUser: (res: Response, user: User) => {
return new Promise((resolve, reject) => {
const jwtClaimSet: JWTClaimSet = { name: user.username, email: user.email };
jwt.sign(jwtClaimSet, config.authentication.secret, { algorithm: 'HS256' },
(err: Error, token: string) => {
if (err) {
reject('Could not create jwtToken!')
console.log(err);
} else {
console.log("Hello world");
res.cookie(config.authentication.cookiename, token);
console.log(token);
resolve();
}
});
});
}
It seems to crash on the cookie function call. The console.log is still being executed.
This should not be possible. Can you please setup a git repo with a minimal reproduction of your problem, then I can checkout, debug and solve your problem.
There you go: https://github.com/Christian24/routingcontrollersissue/tree/master
Thanks a lot.
@Christian24 Can you do a MINIMAL example? One simple controller with 2-3 simple routes, one service if needed, not the entire jungle which is hard to understand.
For me it looks like you've forgot to return promise somewhere in you hell and because of next
fallthrough the next route is catched as it also match to the pattern.
@pleerock @19majkel94 same problem here!!!
I have two endpoints on controller 'UserController'
@Get('/me')
@Get('/:userId')
both marked as @Authorized
some requests executes /:userId with 'me' as param
Stale issue message