fediglam/src/api/methods/invites.zig

108 lines
2.9 KiB
Zig

const std = @import("std");
const util = @import("util");
const services = @import("../services.zig");
const pkg = @import("../lib.zig");
const Uuid = util.Uuid;
const DateTime = util.DateTime;
const ApiContext = pkg.ApiContext;
const CreateOptions = pkg.invites.CreateOptions;
const Invite = pkg.invites.Invite;
pub fn create(
alloc: std.mem.Allocator,
ctx: ApiContext,
svcs: anytype,
options: CreateOptions,
) !Uuid {
// Only logged in users can make invites
const user_id = ctx.userId() orelse return error.TokenRequired;
const community_id = if (options.to_community) |id| blk: {
// Only admins can send invites for other communities
if (!ctx.isAdmin()) return error.PermissionDenied;
break :blk id;
} else ctx.community.id;
// Users can only make user invites
if (options.kind != .user and !ctx.isAdmin()) return error.PermissionDenied;
return try svcs.createInvite(alloc, .{
.created_by = user_id,
.community_id = community_id,
.name = options.name,
.lifespan = options.lifespan,
.max_uses = options.max_uses,
.kind = options.kind,
});
}
pub fn isValid(invite: services.invites.Invite) bool {
if (invite.max_uses != null and invite.times_used >= invite.max_uses.?) return false;
if (invite.expires_at != null and DateTime.now().isAfter(invite.expires_at.?)) return false;
return true;
}
fn getInviteImpl(
alloc: std.mem.Allocator,
ctx: ApiContext,
svcs: anytype,
invite: services.invites.Invite,
) !Invite {
errdefer util.deepFree(alloc, invite);
if (!Uuid.eql(invite.community_id, ctx.community.id) and !ctx.isAdmin()) return error.NotFound;
if (!isValid(invite)) return error.NotFound;
const community = try svcs.getCommunity(alloc, invite.community_id);
defer util.deepFree(alloc, community);
const url = try std.fmt.allocPrint(
alloc,
"{s}://{s}/invite/{s}",
.{ @tagName(community.scheme), community.host, invite.code },
);
errdefer util.deepFree(alloc, url);
return Invite{
.id = invite.id,
.created_by = invite.created_by,
.community_id = invite.community_id,
.name = invite.name,
.code = invite.code,
.url = url,
.created_at = invite.created_at,
.times_used = invite.times_used,
.expires_at = invite.expires_at,
.max_uses = invite.max_uses,
.kind = invite.kind,
};
}
pub fn get(
alloc: std.mem.Allocator,
ctx: ApiContext,
svcs: anytype,
id: Uuid,
) !Invite {
const invite = try svcs.getInvite(alloc, id);
return getInviteImpl(alloc, ctx, svcs, invite);
}
pub fn getByCode(
alloc: std.mem.Allocator,
ctx: ApiContext,
svcs: anytype,
code: []const u8,
) !Invite {
const invite = try svcs.getInviteByCode(alloc, code, ctx.community.id);
return getInviteImpl(alloc, ctx, svcs, invite);
}