67 lines
2.0 KiB
D
67 lines
2.0 KiB
D
|
module auth.dao;
|
||
|
|
||
|
import handy_httpd.components.optional;
|
||
|
import auth.model;
|
||
|
|
||
|
interface UserRepository {
|
||
|
Optional!User findByUsername(string username);
|
||
|
User createUser(string username, string passwordHash);
|
||
|
void deleteByUsername(string username);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* User implementation that stores each user's data in a separate directory.
|
||
|
*/
|
||
|
class FileSystemUserRepository : UserRepository {
|
||
|
import std.path;
|
||
|
import std.file;
|
||
|
import std.json;
|
||
|
|
||
|
private string usersDir;
|
||
|
|
||
|
this(string usersDir = "users") {
|
||
|
this.usersDir = usersDir;
|
||
|
}
|
||
|
|
||
|
Optional!User findByUsername(string username) {
|
||
|
if (
|
||
|
!validateUsername(username) ||
|
||
|
!exists(getUserDir(username)) ||
|
||
|
!exists(getUserDataFile(username))
|
||
|
) {
|
||
|
return Optional!User.empty;
|
||
|
}
|
||
|
JSONValue userObj = parseJSON(readText(getUserDataFile(username)));
|
||
|
return Optional!User.of(User(
|
||
|
username,
|
||
|
userObj.object["passwordHash"].str
|
||
|
));
|
||
|
}
|
||
|
|
||
|
User createUser(string username, string passwordHash) {
|
||
|
if (!validateUsername(username)) throw new Exception("Invalid username");
|
||
|
if (exists(getUserDir(username))) throw new Exception("User already exists.");
|
||
|
JSONValue userObj = JSONValue.emptyObject;
|
||
|
userObj.object["passwordHash"] = JSONValue(passwordHash);
|
||
|
string jsonStr = userObj.toPrettyString();
|
||
|
if (!exists(this.usersDir)) mkdir(this.usersDir);
|
||
|
mkdir(getUserDir(username));
|
||
|
std.file.write(getUserDataFile(username), cast(ubyte[]) jsonStr);
|
||
|
return User(username, passwordHash);
|
||
|
}
|
||
|
|
||
|
void deleteByUsername(string username) {
|
||
|
if (validateUsername(username) && exists(getUserDir(username))) {
|
||
|
rmdirRecurse(getUserDir(username));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private string getUserDir(string username) {
|
||
|
return buildPath(this.usersDir, username);
|
||
|
}
|
||
|
|
||
|
private string getUserDataFile(string username) {
|
||
|
return buildPath(this.usersDir, username, "user-data.json");
|
||
|
}
|
||
|
}
|