Create user contexts
This commit is contained in:
parent
52003f5e4f
commit
87903ca17b
6 changed files with 45 additions and 10 deletions
|
@ -49,6 +49,10 @@ fn reify(comptime T: type, id: Uuid, val: CreateInfo(T)) T {
|
|||
return result;
|
||||
}
|
||||
|
||||
pub const UserContext = struct {
|
||||
user: models.User,
|
||||
};
|
||||
|
||||
pub const ApiServer = struct {
|
||||
prng: std.rand.DefaultPrng,
|
||||
db: db.Database,
|
||||
|
@ -60,6 +64,18 @@ pub const ApiServer = struct {
|
|||
};
|
||||
}
|
||||
|
||||
pub fn makeUserContext(self: *ApiServer, token: []const u8, alloc: std.mem.Allocator) !UserContext {
|
||||
if (token.len == 0) return error.InvalidToken;
|
||||
|
||||
const user_handle = token;
|
||||
|
||||
const user = (try self.db.getBy(models.User, .handle, user_handle, alloc)) orelse return error.InvalidToken;
|
||||
|
||||
return UserContext{
|
||||
.user = user,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn createNote(self: *ApiServer, info: CreateInfo(models.Note)) !models.Note {
|
||||
const id = Uuid.randV4(self.prng.random());
|
||||
// TODO: check for dupes
|
||||
|
|
|
@ -91,6 +91,16 @@ pub fn getUser(srv: *RequestServer, ctx: *http.server.Context, args: RouteArgs)
|
|||
try utils.respondJson(ctx, .ok, user, srv.alloc);
|
||||
}
|
||||
|
||||
pub fn authenticate(srv: *RequestServer, ctx: *http.server.Context, _: RouteArgs) !void {
|
||||
const header = ctx.request.headers.get("authorization") orelse "(null)";
|
||||
|
||||
const token = header[("bearer ").len..];
|
||||
|
||||
const user_ctx = try srv.api.makeUserContext(token, srv.alloc);
|
||||
|
||||
try utils.respondJson(ctx, .ok, user_ctx, srv.alloc);
|
||||
}
|
||||
|
||||
pub fn healthcheck(srv: *RequestServer, ctx: *http.server.Context, _: RouteArgs) !void {
|
||||
try utils.respondJson(ctx, .ok, .{ .status = "ok" }, srv.alloc);
|
||||
}
|
||||
|
|
|
@ -153,7 +153,8 @@ pub const Database = struct {
|
|||
@field(result, f) = switch (@TypeOf(@field(result, f))) {
|
||||
// TODO: Handle allocation failures gracefully
|
||||
[]const u8 => row.getTextAlloc(i, alloc) catch unreachable,
|
||||
else => @compileError("unknown type"),
|
||||
Uuid => row.getUuid(i) catch unreachable,
|
||||
else => @compileError("unknown type " ++ @typeName(@TypeOf(@field(result, f)))),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,8 @@ const router = Router{
|
|||
.routes = &[_]Route{
|
||||
Route.new(.GET, "/healthcheck", c.healthcheck),
|
||||
|
||||
Route.new(.GET, "/auth/authenticate", c.authenticate),
|
||||
|
||||
Route.new(.GET, "/notes/:id", c.getNote),
|
||||
Route.new(.POST, "/notes", c.createNote),
|
||||
Route.new(.GET, "/users/:id", c.getUser),
|
||||
|
|
|
@ -60,6 +60,12 @@ pub const Row = struct {
|
|||
|
||||
return self.getText(idx, buf);
|
||||
}
|
||||
|
||||
pub fn getUuid(self: Row, idx: u15) !Uuid {
|
||||
var buf: [Uuid.string_len + 1]u8 = undefined;
|
||||
_ = try self.getText(idx, &buf);
|
||||
return try Uuid.parse(buf[0..Uuid.string_len]);
|
||||
}
|
||||
};
|
||||
|
||||
pub const PreparedStmt = struct {
|
||||
|
|
|
@ -4,21 +4,21 @@ const std = @import("std");
|
|||
|
||||
data: u128,
|
||||
|
||||
pub const Nil = Uuid{ .data = @as(u128, 0) };
|
||||
pub const StringLen = 36;
|
||||
pub const nil = Uuid{ .data = @as(u128, 0) };
|
||||
pub const string_len = 36;
|
||||
|
||||
pub fn eql(lhs: Uuid, rhs: Uuid) bool {
|
||||
return lhs.data == rhs.data;
|
||||
}
|
||||
|
||||
pub fn toCharArray(value: Uuid) [StringLen]u8 {
|
||||
var buf: [StringLen]u8 = undefined;
|
||||
pub fn toCharArray(value: Uuid) [string_len]u8 {
|
||||
var buf: [string_len]u8 = undefined;
|
||||
_ = std.fmt.bufPrint(&buf, "{}", .{value}) catch unreachable;
|
||||
return buf;
|
||||
}
|
||||
|
||||
pub fn toCharArrayZ(value: Uuid) [StringLen + 1:0]u8 {
|
||||
var buf: [StringLen + 1:0]u8 = undefined;
|
||||
pub fn toCharArrayZ(value: Uuid) [string_len + 1:0]u8 {
|
||||
var buf: [string_len + 1:0]u8 = undefined;
|
||||
_ = std.fmt.bufPrintZ(&buf, "{}", .{value}) catch unreachable;
|
||||
return buf;
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ pub const ParseError = error{
|
|||
};
|
||||
|
||||
pub fn parse(str: []const u8) ParseError!Uuid {
|
||||
if (str.len != StringLen) return error.InvalidLength;
|
||||
if (str.len != string_len) return error.InvalidLength;
|
||||
|
||||
var data: [16]u8 = undefined;
|
||||
var str_i: usize = 0;
|
||||
|
@ -91,7 +91,7 @@ pub fn randV4(rand: std.rand.Random) Uuid {
|
|||
|
||||
test "parse uuid" {
|
||||
try std.testing.expectEqual(
|
||||
Uuid.Nil,
|
||||
Uuid.nil,
|
||||
try Uuid.parse("00000000-0000-0000-0000-000000000000"),
|
||||
);
|
||||
|
||||
|
@ -104,7 +104,7 @@ test "parse uuid" {
|
|||
}
|
||||
|
||||
test "format uuid" {
|
||||
try std.testing.expectFmt("00000000-0000-0000-0000-000000000000", "{}", .{Uuid.Nil});
|
||||
try std.testing.expectFmt("00000000-0000-0000-0000-000000000000", "{}", .{Uuid.nil});
|
||||
|
||||
const uuid = Uuid{
|
||||
.data = @as(u128, 0x4ba7b74522ad_1da8_c242_d312_60515ff7),
|
||||
|
|
Loading…
Reference in a new issue