Rename some API object and add update user to UserPoint. However, it seems to be broken somehow
This commit is contained in:
parent
81f1c3668b
commit
a9bd803112
12 changed files with 143 additions and 41 deletions
|
|
@ -5,7 +5,7 @@ meta {
|
|||
}
|
||||
|
||||
post {
|
||||
url: http://localhost:4000/user
|
||||
url: http://localhost:4000/user/create
|
||||
body: json
|
||||
auth: bearer
|
||||
}
|
||||
|
|
|
|||
30
bruno/recipe-backend/updateUser.bru
Normal file
30
bruno/recipe-backend/updateUser.bru
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
meta {
|
||||
name: updateUser
|
||||
type: http
|
||||
seq: 8
|
||||
}
|
||||
|
||||
post {
|
||||
url: https://localhost:4000/user/update
|
||||
body: json
|
||||
auth: bearer
|
||||
}
|
||||
|
||||
auth:bearer {
|
||||
token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImE0NDdlNDM0LTQyMWYtNDJiYS04MGRlLTM0ZDE1YzJmNWE2YyIsImlhdCI6MTc2MzA2NTI0MCwiZXhwIjoxNzYzMTUxNjQwfQ.e7v1JnlNHm7zwSzumlZIy2Dxfojqsxk55aYC9UA7BkE
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"id": "a447e434-421f-42ba-80de-34d15c2f5a6c",
|
||||
"userName": "admin",
|
||||
"email": "anika@raemer.net",
|
||||
"firstName": "Anika",
|
||||
"lastName": "Rämer",
|
||||
"role": "admin"
|
||||
}
|
||||
}
|
||||
|
||||
settings {
|
||||
encodeUrl: true
|
||||
}
|
||||
7
src/dtos/ChangeUserPasswordRequest.ts
Normal file
7
src/dtos/ChangeUserPasswordRequest.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
/**
|
||||
* DTO for changing user password
|
||||
*/
|
||||
export class ChangeUserPasswordRequest {
|
||||
userId?: string;
|
||||
password?: string;
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@ import { UserDto } from "./UserDto.js";
|
|||
/**
|
||||
* DTO used for user creation
|
||||
*/
|
||||
export class CreateUserRequestDto {
|
||||
export class CreateUserRequest {
|
||||
userData?: UserDto;
|
||||
password?: string;
|
||||
}
|
||||
5
src/dtos/CreateUserResponse.ts
Normal file
5
src/dtos/CreateUserResponse.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
import { UserDto } from "./UserDto.js";
|
||||
|
||||
export class CreateUserResponse{
|
||||
userData?: UserDto;
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
* Defines a login request
|
||||
*/
|
||||
export class LoginRequestDto {
|
||||
export class LoginRequest {
|
||||
userName?: string;
|
||||
password?: string;
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@ import { UserDto } from "./UserDto.js";
|
|||
/**
|
||||
* Response to a successful login
|
||||
*/
|
||||
export class LoginResponseDto {
|
||||
export class LoginResponse {
|
||||
userData?: UserDto;
|
||||
token?: string;
|
||||
expiryDate? : Date;
|
||||
|
|
@ -7,7 +7,7 @@ import {
|
|||
UnauthorizedError,
|
||||
InternalServerError,
|
||||
} from "../errors/httpErrors.js";
|
||||
import { LoginRequestDto } from "../dtos/LoginRequestDto.js";
|
||||
import { LoginRequest } from "../dtos/LoginRequest.js";
|
||||
|
||||
export const authBasicRoute = "/auth"
|
||||
|
||||
|
|
@ -18,13 +18,13 @@ const authController = new AuthHandler(userRepository, mapper);
|
|||
|
||||
/**
|
||||
* Login using username and password
|
||||
* Consumes LoginRequestDto
|
||||
* Responds with LoginResponseDto
|
||||
* Consumes LoginRequest
|
||||
* Responds with LoginResponse
|
||||
*/
|
||||
router.post("/login", async (req, res) => {
|
||||
console.log("login point called")
|
||||
try {
|
||||
const requestDto: LoginRequestDto = req.body;
|
||||
const requestDto: LoginRequest = req.body;
|
||||
const responseDto = await authController.login(requestDto);
|
||||
res.json(responseDto);
|
||||
} catch (err: any) {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ const recipeIngredientMapper = new RecipeIngredientDtoEntityMapper();
|
|||
const recipeIngredientGroupMapper = new RecipeIngredientGroupDtoEntityMapper(recipeIngredientMapper);
|
||||
const recipeInstructionStepMapper = new RecipeInstructionStepDtoEntityMapper();
|
||||
const recipeMapper = new RecipeDtoEntityMapper(recipeInstructionStepMapper, recipeIngredientGroupMapper);
|
||||
const recipeController = new RecipeHandler(recipeRepository, recipeMapper);
|
||||
const recipeHandler = new RecipeHandler(recipeRepository, recipeMapper);
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -34,7 +34,7 @@ router.post(
|
|||
"/create-or-update",
|
||||
asyncHandler(async(req, res) => {
|
||||
const requestDto: RecipeDto = req.body;
|
||||
const responseDto = await recipeController.createOrUpdateRecipe(requestDto);
|
||||
const responseDto = await recipeHandler.createOrUpdateRecipe(requestDto);
|
||||
res.status(201).json(responseDto);
|
||||
})
|
||||
)
|
||||
|
|
@ -47,7 +47,7 @@ router.get(
|
|||
"/:id",
|
||||
asyncHandler(async(req, res) => {
|
||||
const id = req.params.id;
|
||||
const responseDto = await recipeController.getRecipeById(id);
|
||||
const responseDto = await recipeHandler.getRecipeById(id);
|
||||
res.status(201).json(responseDto);
|
||||
})
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
import { Router } from "express";
|
||||
import { UserHandler } from "../handlers/UserHandler.js";
|
||||
import { CreateUserRequestDto } from "../dtos/CreateUserRequestDto.js";
|
||||
import { CreateUserRequest } from "../dtos/CreateUserRequest.js";
|
||||
import { UserRepository } from "../repositories/UserRepository.js";
|
||||
import { UserDtoEntityMapper } from "../mappers/UserDtoEntityMapper.js";
|
||||
import { asyncHandler } from "../utils/asyncHandler.js";
|
||||
import {CreateUserResponse} from "../dtos/CreateUserResponse.js";
|
||||
import {UserDto} from "../dtos/UserDto.js";
|
||||
|
||||
/**
|
||||
* Handles all user related routes
|
||||
|
|
@ -11,24 +13,51 @@ import { asyncHandler } from "../utils/asyncHandler.js";
|
|||
const router = Router();
|
||||
|
||||
// Inject repo + mapper here
|
||||
const userRepository = new UserRepository();
|
||||
const userMapper = new UserDtoEntityMapper();
|
||||
const userController = new UserHandler(userRepository, userMapper);
|
||||
const handler
|
||||
= new UserHandler(new UserRepository(), new UserDtoEntityMapper());
|
||||
|
||||
/**
|
||||
* Create a new user
|
||||
* Consumes CreateUserRequestDto
|
||||
* Consumes CreateUserRequest
|
||||
* Responds with UserDto
|
||||
*/
|
||||
router.post(
|
||||
"/",
|
||||
"/create",
|
||||
asyncHandler(async (req, res) => {
|
||||
const requestDto: CreateUserRequestDto = req.body;
|
||||
const responseDto = await userController.createUser(requestDto);
|
||||
res.status(201).json(responseDto);
|
||||
const request: CreateUserRequest = req.body;
|
||||
const user : UserDto = await handler.createUser(request);
|
||||
const response : CreateUserResponse = { userData: user };
|
||||
res.status(201).json(response);
|
||||
})
|
||||
);
|
||||
|
||||
/**
|
||||
* Update existing user
|
||||
* Consumes UserDto
|
||||
* Responds with UserDto
|
||||
* Does not allow for password change. Use change-password instead
|
||||
*/
|
||||
router.post(
|
||||
"/update",
|
||||
asyncHandler(async (req, res) => {
|
||||
const dto : UserDto = req.body;
|
||||
const response = await handler.updateUserData(dto);
|
||||
res.status(201).json(response);
|
||||
})
|
||||
)
|
||||
|
||||
/**
|
||||
* Update password of existing user
|
||||
* Consumes ChangeUserPasswordRequest
|
||||
* Responds with code 201 indicating success
|
||||
*/
|
||||
router.post(
|
||||
"/change-password",
|
||||
asyncHandler(async (req, res) => {
|
||||
throw Error("not implemented!");
|
||||
})
|
||||
)
|
||||
|
||||
/**
|
||||
* Get user data for current user
|
||||
* Responds with UserDto
|
||||
|
|
@ -39,7 +68,7 @@ router.get("/me",
|
|||
const id = req.currentUser?.id;
|
||||
if(id){
|
||||
// it breaks here because id is no longer a uuid
|
||||
const responseDto = await userController.getUserById(id);
|
||||
const responseDto = await handler.getUserById(id);
|
||||
res.status(201).json(responseDto);
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ import { UserRepository } from "../repositories/UserRepository.js";
|
|||
import { encrypt } from "../utils/encryptionUtils.js";
|
||||
import { ValidationError, UnauthorizedError } from "../errors/httpErrors.js";
|
||||
import { UserDtoEntityMapper } from "../mappers/UserDtoEntityMapper.js";
|
||||
import { LoginResponseDto } from "../dtos/LoginResponseDto.js";
|
||||
import { LoginRequestDto } from "../dtos/LoginRequestDto.js";
|
||||
import { LoginResponse } from "../dtos/LoginResponse.js";
|
||||
import { LoginRequest } from "../dtos/LoginRequest.js";
|
||||
|
||||
/**
|
||||
* Controller responsible for authentication, e.g., login or issueing a token with extended
|
||||
|
|
@ -17,10 +17,10 @@ export class AuthHandler {
|
|||
|
||||
/**
|
||||
* Login: Check user and password and generate token
|
||||
* @param loginRequest LoginRequestDto containing userName and password for login
|
||||
* @param loginRequest LoginRequest containing userName and password for login
|
||||
* @returns LoginResponse containing token and user data for the user who just logged in
|
||||
*/
|
||||
async login(loginRequest : LoginRequestDto): Promise<LoginResponseDto> {
|
||||
async login(loginRequest : LoginRequest): Promise<LoginResponse> {
|
||||
const userName :string|undefined = loginRequest.userName;
|
||||
const password :string|undefined = loginRequest.password;
|
||||
console.log("user", userName, " is trying to log in")
|
||||
|
|
@ -50,7 +50,7 @@ export class AuthHandler {
|
|||
id: userId!, // ! to indicate that we've definitely checked for userId being defined
|
||||
});
|
||||
|
||||
const responseDto = new LoginResponseDto();
|
||||
const responseDto = new LoginResponse();
|
||||
responseDto.userData = this.mapper.toDto(user);
|
||||
responseDto.token = tokenInfo.token;
|
||||
responseDto.expiryDate = tokenInfo.expiryDate;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { ValidationError, ConflictError, NotFoundError } from "../errors/httpErrors.js";
|
||||
import { CreateUserRequestDto } from "../dtos/CreateUserRequestDto.js";
|
||||
import { CreateUserRequest } from "../dtos/CreateUserRequest.js";
|
||||
import { UserDto } from "../dtos/UserDto.js";
|
||||
import { encrypt } from "../utils/encryptionUtils.js";
|
||||
import { UserRepository } from "../repositories/UserRepository.js";
|
||||
|
|
@ -17,26 +17,21 @@ export class UserHandler {
|
|||
|
||||
/**
|
||||
* Create a new user
|
||||
* @param dto CreateUserRequestDto containing data for the user to add
|
||||
* @param dto CreateUserRequest containing data for the user to add
|
||||
* @returns UserDto Data of the user as stored in the database
|
||||
*/
|
||||
async createUser(dto: CreateUserRequestDto): Promise<UserDto> {
|
||||
async createUser(dto: CreateUserRequest): Promise<UserDto> {
|
||||
// check mandatory fields
|
||||
if(!dto.userData){
|
||||
throw new ValidationError("User data is required")
|
||||
}
|
||||
const email = dto.userData.email;
|
||||
if (!email || (email && email.length == 0)) {
|
||||
throw new ValidationError("Email is required");
|
||||
}
|
||||
this.validateUserData(dto.userData);
|
||||
const userName = dto.userData.userName;
|
||||
const password = dto.password;
|
||||
if(!password || (password && password.length == 0)){
|
||||
throw new ValidationError("Password is required");
|
||||
}
|
||||
const userName = dto.userData.userName;
|
||||
if (!userName|| (userName && userName.length == 0)){
|
||||
throw new ValidationError("Username is required");
|
||||
}
|
||||
|
||||
|
||||
// user name must be unique
|
||||
const existingUser = await this.userRepository.findByUserName(userName);
|
||||
|
|
@ -52,6 +47,42 @@ export class UserHandler {
|
|||
return this.mapper.toDto(savedUser);
|
||||
}
|
||||
|
||||
private validateUserData(dto: UserDto) : void {
|
||||
const email = dto.email;
|
||||
if (!email || (email && email.length == 0)) {
|
||||
throw new ValidationError("Email is required");
|
||||
}
|
||||
const userName = dto.userName;
|
||||
if (!userName || (userName && userName.length == 0)) {
|
||||
throw new ValidationError("Username is required");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update user data
|
||||
* @param dto UserDto containing updates userData
|
||||
*/
|
||||
async updateUserData(dto: UserDto) : Promise<UserDto> {
|
||||
// Ensure that user data is complete
|
||||
this.validateUserData(dto);
|
||||
const userId = dto.id
|
||||
if(userId === undefined || userId.length === 0){
|
||||
// user does not exist yet -> Wrong method is used
|
||||
throw new ValidationError("Cannot save user without valid userId. Use user/create to create a new user");
|
||||
}
|
||||
// First: Load current version of user from database
|
||||
const entity = await this.userRepository.findById(userId);
|
||||
if (!entity) {
|
||||
throw new ValidationError("No user with ID " + userId + " found in database!")
|
||||
}
|
||||
// merge changes into entity
|
||||
this.mapper.mergeDtoIntoEntity(dto, entity);
|
||||
// persist changes
|
||||
const savedEntity = await this.userRepository.update(entity);
|
||||
return this.mapper.toDto(savedEntity);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Load data of a specific user
|
||||
* @param userId Id of user to load
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue