67 lines
1.7 KiB
Zig
67 lines
1.7 KiB
Zig
|
const std = @import("std");
|
||
|
const util = @import("util");
|
||
|
|
||
|
const Uuid = util.Uuid;
|
||
|
const DateTime = util.DateTime;
|
||
|
|
||
|
pub const Role = enum {
|
||
|
user,
|
||
|
admin,
|
||
|
};
|
||
|
pub const CreateOptions = struct {
|
||
|
invite_id: ?Uuid = null,
|
||
|
email: ?[]const u8 = null,
|
||
|
role: Role = .user,
|
||
|
};
|
||
|
|
||
|
/// Creates a local account with the given information
|
||
|
pub fn create(
|
||
|
db: anytype,
|
||
|
for_actor: Uuid,
|
||
|
password_hash: []const u8,
|
||
|
options: CreateOptions,
|
||
|
alloc: std.mem.Allocator,
|
||
|
) !void {
|
||
|
const tx = try db.beginOrSavepoint();
|
||
|
errdefer tx.rollback();
|
||
|
|
||
|
tx.insert("account", .{
|
||
|
.id = for_actor,
|
||
|
.invite_id = options.invite_id,
|
||
|
.email = options.email,
|
||
|
.kind = options.role,
|
||
|
}, alloc) catch return error.DatabaseFailure;
|
||
|
tx.insert("password", .{
|
||
|
.account_id = for_actor,
|
||
|
.hash = password_hash,
|
||
|
.changed_at = DateTime.now(),
|
||
|
}, alloc) catch return error.DatabaseFailure;
|
||
|
|
||
|
tx.commitOrRelease() catch return error.DatabaseFailure;
|
||
|
}
|
||
|
|
||
|
pub const Credentials = struct {
|
||
|
account_id: Uuid,
|
||
|
password_hash: []const u8,
|
||
|
};
|
||
|
|
||
|
pub fn getCredentialsByUsername(db: anytype, username: []const u8, community_id: Uuid, alloc: std.mem.Allocator) !Credentials {
|
||
|
return db.queryRow(
|
||
|
Credentials,
|
||
|
\\SELECT account.id as account_id, password.hash as password_hash
|
||
|
\\FROM password
|
||
|
\\ JOIN account
|
||
|
\\ JOIN actor
|
||
|
\\ ON password.account_id = account.id AND account.id = actor.id
|
||
|
\\WHERE actor.username = $1
|
||
|
\\ AND actor.community_id = $2
|
||
|
\\LIMIT 1
|
||
|
,
|
||
|
.{ username, community_id },
|
||
|
alloc,
|
||
|
) catch |err| return switch (err) {
|
||
|
error.NoRows => error.InvalidLogin,
|
||
|
else => |e| return e,
|
||
|
};
|
||
|
}
|