Track invite uses and handle properly

This commit is contained in:
jaina heartles 2022-07-26 23:03:27 -07:00
parent 76f2b818ab
commit ae9a062caf
4 changed files with 13 additions and 12 deletions

View file

@ -86,6 +86,12 @@ pub const LoginResult = struct {
issued_at: DateTime,
};
pub const InviteOptions = struct {
name: []const u8 = "",
max_uses: ?i64 = null,
lifetime: ?i64 = null, // unix seconds, TODO make a TimeSpan type
};
threadlocal var prng: std.rand.DefaultPrng = undefined;
pub fn initThreadPrng(seed: u64) void {
@ -225,7 +231,8 @@ fn ApiConn(comptime DbConn: type) type {
const now = DateTime.now();
const invite_id = if (info.invite_code) |invite_code| blk: {
const invite = (try self.db.getBy(models.Invite, .invite_code, invite_code, self.arena.allocator())) orelse return error.InvalidInvite;
const uses_left = if (invite.max_uses) |max_uses| invite.uses < max_uses else true;
const uses = try self.db.countWhereEq(models.LocalUser, .invite_id, invite.id);
const uses_left = if (invite.max_uses) |max_uses| uses < max_uses else true;
const expired = if (invite.expires_at) |expires_at| now.seconds_since_epoch > expires_at.seconds_since_epoch else false;
if (!uses_left or expired) return error.InvalidInvite;
@ -306,11 +313,6 @@ fn ApiConn(comptime DbConn: type) type {
};
}
const InviteOptions = struct {
name: []const u8 = "",
max_uses: ?i64 = null,
lifetime: ?i64 = null, // unix seconds, TODO make a TimeSpan type
};
pub fn createInvite(self: *Self, options: InviteOptions) !models.Invite {
const id = Uuid.randV4(prng.random());
@ -334,7 +336,6 @@ fn ApiConn(comptime DbConn: type) type {
.created_by = user_id,
.invite_code = code_str,
.uses = 0,
.max_uses = options.max_uses,
.created_at = now,

View file

@ -3,16 +3,19 @@ const http = @import("http");
const Uuid = @import("util").Uuid;
const utils = @import("../../controllers.zig").utils;
const NoteCreateInfo = @import("../../api.zig").NoteCreateInfo;
const InviteOptions = @import("../../api.zig").InviteOptions;
const RequestServer = root.RequestServer;
const RouteArgs = http.RouteArgs;
pub fn create(srv: *RequestServer, ctx: *http.server.Context, _: RouteArgs) !void {
const opt = try utils.parseRequestBody(InviteOptions, ctx);
defer utils.freeRequestBody(opt, ctx.alloc);
var api = try utils.getApiConn(srv, ctx);
defer api.close();
const invite = try api.createInvite(.{});
const invite = try api.createInvite(opt);
try utils.respondJson(ctx, .created, invite);
}

View file

@ -155,7 +155,6 @@ pub const Database = struct {
\\
\\ username TEXT NOT NULL,
\\ email TEXT,
\\ invite_id TEXT,
\\
\\ hashed_password TEXT NOT NULL,
\\ password_changed_at INTEGER NOT NULL,
@ -215,7 +214,6 @@ pub const Database = struct {
\\ invite_code TEXT NOT NULL,
\\ created_by TEXT NOT NULL REFERENCES local_user(id),
\\
\\ uses INTEGER NOT NULL,
\\ max_uses INTEGER,
\\
\\ created_at INTEGER NOT NULL,

View file

@ -111,7 +111,6 @@ pub const Invite = struct {
invite_code: []const u8,
created_by: Ref(LocalUser),
uses: i64,
max_uses: ?i64,
created_at: DateTime,