Create user contexts

This commit is contained in:
jaina heartles 2022-07-17 16:21:03 -07:00
parent 52003f5e4f
commit 87903ca17b
6 changed files with 45 additions and 10 deletions

View file

@ -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

View file

@ -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);
}

View file

@ -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)))),
};
}

View file

@ -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),

View file

@ -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 {

View file

@ -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),