fediglam/src/main/api/invites.zig

102 lines
2.4 KiB
Zig
Raw Normal View History

2022-09-08 05:10:58 +00:00
const std = @import("std");
const builtin = @import("builtin");
const util = @import("util");
const models = @import("../db/models.zig");
const DbError = @import("../db.zig").ExecError;
const getRandom = @import("../api.zig").getRandom;
const Uuid = util.Uuid;
const DateTime = util.DateTime;
// 9 random bytes = 12 random b64
const rand_len = 8;
const code_len = 12;
const Encoder = std.base64.url_safe.Encoder;
const Decoder = std.base64.url_safe.Decoder;
pub const InviteType = enum {
system,
community_owner,
user,
pub const jsonStringify = defaultJsonStringify(@This());
};
fn defaultJsonStringify(comptime T: type) fn (T, std.json.StringifyOptions, anytype) anyerror!void {
return struct {
pub fn jsonStringify(s: T, _: std.json.StringifyOptions, writer: anytype) !void {
return std.fmt.format(writer, "\"{s}\"", .{@tagName(s)});
}
}.jsonStringify;
}
pub const Invite = struct {
id: Uuid,
created_by: Uuid, // User ID
to_community: ?Uuid,
name: []const u8,
code: []const u8,
created_at: DateTime,
times_used: usize,
expires_at: ?DateTime,
max_uses: ?usize,
invite_type: InviteType,
};
fn cloneStr(str: []const u8, alloc: std.mem.Allocator) ![]const u8 {
const new = try alloc.alloc(u8, str.len);
std.mem.copy(u8, new, str);
return new;
}
pub const InviteOptions = struct {
name: ?[]const u8 = null,
max_uses: ?usize = null,
expires_at: ?DateTime = null,
invite_type: InviteType = .user,
};
pub fn create(db: anytype, created_by: Uuid, to_community: ?Uuid, options: InviteOptions, alloc: std.mem.Allocator) !Invite {
var code_bytes: [rand_len]u8 = undefined;
getRandom().bytes(&code_bytes);
const code = try alloc.alloc(u8, code_len);
errdefer alloc.free(code);
_ = Encoder.encode(code, &code_bytes);
const name = if (options.name) |name|
try cloneStr(name, alloc)
else
try cloneStr(code, alloc);
const id = Uuid.randV4(getRandom());
const created_at = DateTime.now();
const invite = Invite{
.id = id,
.created_by = created_by,
.to_community = to_community,
.name = name,
.code = code,
.created_at = created_at,
.times_used = 0,
.expires_at = options.expires_at,
.max_uses = options.max_uses,
.invite_type = options.invite_type,
};
try db.insert("invite", invite);
return invite;
}