77 lines
2.7 KiB
D
77 lines
2.7 KiB
D
|
/// API endpoints for authentication-related functions, like registration and login.
|
||
|
module auth.api;
|
||
|
|
||
|
import handy_httpd;
|
||
|
import handy_httpd.components.optional;
|
||
|
import slf4d;
|
||
|
|
||
|
import auth.model;
|
||
|
import auth.dao;
|
||
|
import auth.dto;
|
||
|
import auth.service;
|
||
|
|
||
|
void postLogin(ref HttpRequestContext ctx) {
|
||
|
LoginCredentials loginCredentials;
|
||
|
try {
|
||
|
loginCredentials = LoginCredentials.parse(ctx.request.readBodyAsJson());
|
||
|
} catch (Exception e) {
|
||
|
ctx.response.status = HttpStatus.BAD_REQUEST;
|
||
|
}
|
||
|
if (!validateUsername(loginCredentials.username)) {
|
||
|
ctx.response.status = HttpStatus.UNAUTHORIZED;
|
||
|
return;
|
||
|
}
|
||
|
UserRepository userRepo = new FileSystemUserRepository();
|
||
|
Optional!User optionalUser = userRepo.findByUsername(loginCredentials.username);
|
||
|
if (optionalUser.isNull) {
|
||
|
ctx.response.status = HttpStatus.UNAUTHORIZED;
|
||
|
return;
|
||
|
}
|
||
|
import botan.passhash.bcrypt : checkBcrypt;
|
||
|
if (!checkBcrypt(loginCredentials.password, optionalUser.value.passwordHash)) {
|
||
|
ctx.response.status = HttpStatus.UNAUTHORIZED;
|
||
|
return;
|
||
|
}
|
||
|
string token = generateAccessToken(optionalUser.value);
|
||
|
ctx.response.status = HttpStatus.OK;
|
||
|
ctx.response.writeBodyString(TokenResponse(token).toJson(), "application/json");
|
||
|
}
|
||
|
|
||
|
void postRegister(ref HttpRequestContext ctx) {
|
||
|
RegistrationData registrationData;
|
||
|
try {
|
||
|
registrationData = RegistrationData.parse(ctx.request.readBodyAsJson());
|
||
|
} catch (Exception e) {
|
||
|
ctx.response.status = HttpStatus.BAD_REQUEST;
|
||
|
return;
|
||
|
}
|
||
|
if (!validateUsername(registrationData.username)) {
|
||
|
ctx.response.status = HttpStatus.BAD_REQUEST;
|
||
|
ctx.response.writeBodyString("Invalid username.");
|
||
|
return;
|
||
|
}
|
||
|
if (!validatePassword(registrationData.password)) {
|
||
|
ctx.response.status = HttpStatus.BAD_REQUEST;
|
||
|
ctx.response.writeBodyString("Invalid password.");
|
||
|
return;
|
||
|
}
|
||
|
UserRepository userRepo = new FileSystemUserRepository();
|
||
|
if (!userRepo.findByUsername(registrationData.username).isNull) {
|
||
|
ctx.response.status = HttpStatus.BAD_REQUEST;
|
||
|
ctx.response.writeBodyString("Username is taken.");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
import botan.passhash.bcrypt : generateBcrypt;
|
||
|
import botan.rng.auto_rng;
|
||
|
RandomNumberGenerator rng = new AutoSeededRNG();
|
||
|
string passwordHash = generateBcrypt(registrationData.password, rng, 12);
|
||
|
userRepo.createUser(registrationData.username, passwordHash);
|
||
|
infoF!"Created user: %s"(registrationData.username);
|
||
|
}
|
||
|
|
||
|
void getMyUser(ref HttpRequestContext ctx) {
|
||
|
AuthContext auth = getAuthContext(ctx);
|
||
|
ctx.response.writeBodyString(auth.user.username);
|
||
|
}
|