Add community invites api

This commit is contained in:
Aslan 2026-01-10 19:40:44 -05:00
parent e120a12eaa
commit 23128f25e1
8 changed files with 118 additions and 15 deletions

4
package-lock.json generated
View file

@ -1,12 +1,12 @@
{ {
"name": "tether", "name": "tether",
"version": "0.3.6", "version": "0.3.7",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "tether", "name": "tether",
"version": "0.3.6", "version": "0.3.7",
"license": "GPL-3.0-only", "license": "GPL-3.0-only",
"dependencies": { "dependencies": {
"@fastify/cookie": "^11.0.2", "@fastify/cookie": "^11.0.2",

View file

@ -1,6 +1,6 @@
{ {
"name": "tether", "name": "tether",
"version": "0.3.6", "version": "0.3.7",
"description": "Communication server using the Nexlink protocol", "description": "Communication server using the Nexlink protocol",
"repository": { "repository": {
"type": "git", "type": "git",

View file

@ -22,6 +22,9 @@ import type {
IGetRolesParams, IGetRolesParams,
IGetRolesResponseError, IGetRolesResponseError,
IGetRolesResponseSuccess, IGetRolesResponseSuccess,
IGetInvitesParams,
IGetInvitesResponseError,
IGetInvitesResponseSuccess,
IPostCreateInviteParams, IPostCreateInviteParams,
IPostCreateInviteRequest, IPostCreateInviteRequest,
IPostCreateInviteResponseError, IPostCreateInviteResponseError,
@ -34,6 +37,7 @@ import {
getCommunityChannelsByIdAuth, getCommunityChannelsByIdAuth,
getCommunityMembersByIdAuth, getCommunityMembersByIdAuth,
getCommunityRolesByIdAuth, getCommunityRolesByIdAuth,
getCommunityInvitesByIdAuth,
createInviteAuth, createInviteAuth,
deleteCommunityByIdAuth, deleteCommunityByIdAuth,
} from "../../services/community/community.js"; } from "../../services/community/community.js";
@ -243,6 +247,36 @@ const getRoles = async (request: FastifyRequest, reply: FastifyReply) => {
} as IGetRolesResponseSuccess; } as IGetRolesResponseSuccess;
}; };
const getInvites = async (request: FastifyRequest, reply: FastifyReply) => {
const { id } = request.params as IGetInvitesParams;
const authHeader = request.headers["authorization"];
const community = await getCommunityById(id);
const invites = await getCommunityInvitesByIdAuth(id, authHeader);
if (!invites || !community) {
reply.status(404);
return {
id: id,
error: API_ERROR.NOT_FOUND,
} as IGetInvitesResponseError;
}
if (invites === API_ERROR.ACCESS_DENIED) {
reply.status(403);
return {
id: id,
error: API_ERROR.ACCESS_DENIED,
} as IGetInvitesResponseError;
}
return {
id: community.id,
name: community.name,
invites: invites.map((invite) => ({
id: invite.id,
})),
} as IGetInvitesResponseSuccess;
};
const postCreateInvite = async ( const postCreateInvite = async (
request: FastifyRequest, request: FastifyRequest,
reply: FastifyReply, reply: FastifyReply,
@ -292,5 +326,6 @@ export {
getMembers, getMembers,
getChannels, getChannels,
getRoles, getRoles,
getInvites,
postCreateInvite, postCreateInvite,
}; };

View file

@ -9,6 +9,7 @@ const communityRoutes = async (fastify: FastifyInstance) => {
fastify.get(`/:id/members`, controller.getMembers); fastify.get(`/:id/members`, controller.getMembers);
fastify.get(`/:id/channels`, controller.getChannels); fastify.get(`/:id/channels`, controller.getChannels);
fastify.get(`/:id/roles`, controller.getRoles); fastify.get(`/:id/roles`, controller.getRoles);
fastify.get(`/:id/invites`, controller.getInvites);
fastify.post(`/:id/invite`, controller.postCreateInvite); fastify.post(`/:id/invite`, controller.postCreateInvite);
}; };

View file

@ -72,10 +72,10 @@ interface IGetMembersResponseError {
interface IGetMembersResponseSuccess { interface IGetMembersResponseSuccess {
id: string; id: string;
name: string; name: string;
members: IGetMembersResponseMembers[]; members: IGetMembersResponseMember[];
} }
interface IGetMembersResponseMembers { interface IGetMembersResponseMember {
id: string; id: string;
username: string; username: string;
} }
@ -92,10 +92,10 @@ interface IGetChannelsResponseError {
interface IGetChannelsResponseSuccess { interface IGetChannelsResponseSuccess {
id: string; id: string;
name: string; name: string;
channels: IGetChannelsResponseChannels[]; channels: IGetChannelsResponseChannel[];
} }
interface IGetChannelsResponseChannels { interface IGetChannelsResponseChannel {
id: string; id: string;
name: string; name: string;
} }
@ -112,14 +112,33 @@ interface IGetRolesResponseError {
interface IGetRolesResponseSuccess { interface IGetRolesResponseSuccess {
id: string; id: string;
name: string; name: string;
roles: IGetRolesResponseRoles[]; roles: IGetRolesResponseRole[];
} }
interface IGetRolesResponseRoles { interface IGetRolesResponseRole {
id: string; id: string;
name: string; name: string;
} }
interface IGetInvitesParams {
id: string;
}
interface IGetInvitesResponseError {
id: string;
error: API_ERROR;
}
interface IGetInvitesResponseSuccess {
id: string;
name: string;
invites: IGetInvitesResponseInvite[];
}
interface IGetInvitesResponseInvite {
id: string;
}
interface IPostCreateInviteParams { interface IPostCreateInviteParams {
id: string; id: string;
} }
@ -157,15 +176,19 @@ export {
type IGetMembersParams, type IGetMembersParams,
type IGetMembersResponseError, type IGetMembersResponseError,
type IGetMembersResponseSuccess, type IGetMembersResponseSuccess,
type IGetMembersResponseMembers, type IGetMembersResponseMember,
type IGetChannelsParams, type IGetChannelsParams,
type IGetChannelsResponseError, type IGetChannelsResponseError,
type IGetChannelsResponseSuccess, type IGetChannelsResponseSuccess,
type IGetChannelsResponseChannels, type IGetChannelsResponseChannel,
type IGetRolesParams, type IGetRolesParams,
type IGetRolesResponseError, type IGetRolesResponseError,
type IGetRolesResponseSuccess, type IGetRolesResponseSuccess,
type IGetRolesResponseRoles, type IGetRolesResponseRole,
type IGetInvitesParams,
type IGetInvitesResponseError,
type IGetInvitesResponseSuccess,
type IGetInvitesResponseInvite,
type IPostCreateInviteParams, type IPostCreateInviteParams,
type IPostCreateInviteRequest, type IPostCreateInviteRequest,
type IPostCreateInviteResponseError, type IPostCreateInviteResponseError,

View file

@ -3,12 +3,12 @@ enum PERMISSION {
CHANNELS_READ = "CHANNELS_READ", CHANNELS_READ = "CHANNELS_READ",
CHANNELS_MANAGE = "CHANNELS_MANAGE", CHANNELS_MANAGE = "CHANNELS_MANAGE",
ROLES_READ = "ROLES_READ", ROLES_READ = "ROLES_READ",
INVITES_CREATE = "INVITES_CREATE",
INVITES_DELETE = "INVITES_DELETE",
ROLES_MANAGE = "ROLES_MANAGE", ROLES_MANAGE = "ROLES_MANAGE",
MEMBERS_READ = "MEMBERS_READ", MEMBERS_READ = "MEMBERS_READ",
MEMBERS_KICK = "MEMBERS_KICK", MEMBERS_KICK = "MEMBERS_KICK",
MEMBERS_BAN = "MEMBERS_BAN", MEMBERS_BAN = "MEMBERS_BAN",
INVITES_CREATE = "INVITES_CREATE",
INVITES_DELETE = "INVITES_DELETE",
} }
export { PERMISSION }; export { PERMISSION };

View file

@ -9,11 +9,12 @@ import {
import { PERMISSION } from "../auth/permission.js"; import { PERMISSION } from "../auth/permission.js";
import type { import type {
ICreateCommunity, ICreateCommunity,
IUpdateCommunity,
ICommunityChannel, ICommunityChannel,
ICommunityMember, ICommunityMember,
ICommunityRole, ICommunityRole,
ICommunityInvite,
ICreateInvite, ICreateInvite,
IUpdateCommunity,
} from "./types.js"; } from "./types.js";
const getCommunityById = async (id: string): Promise<Community | null> => { const getCommunityById = async (id: string): Promise<Community | null> => {
@ -227,6 +228,42 @@ const getCommunityRolesByIdAuth = async (
return await getCommunityRolesById(id); return await getCommunityRolesById(id);
}; };
const getCommunityInvitesById = async (
id: string,
): Promise<ICommunityInvite[]> => {
return await getDB().invite.findMany({
where: {
communityId: id,
},
select: {
id: true,
},
});
};
const getCommunityInvitesByIdAuth = async (
id: string,
authHeader: string | undefined,
): Promise<ICommunityInvite[] | API_ERROR.ACCESS_DENIED> => {
const authUser = await getUserFromAuth(authHeader);
const community = await getCommunityById(id);
if (
!(await isUserAllowed(
authUser,
{
community: community,
},
community,
[PERMISSION.INVITES_CREATE],
))
) {
return API_ERROR.ACCESS_DENIED;
}
return await getCommunityInvitesById(id);
};
const createInvite = async ( const createInvite = async (
id: string, id: string,
creatorId: string, creatorId: string,
@ -280,6 +317,8 @@ export {
getCommunityChannelsByIdAuth, getCommunityChannelsByIdAuth,
getCommunityRolesById, getCommunityRolesById,
getCommunityRolesByIdAuth, getCommunityRolesByIdAuth,
getCommunityInvitesById,
getCommunityInvitesByIdAuth,
createInvite, createInvite,
createInviteAuth, createInviteAuth,
}; };

View file

@ -23,6 +23,10 @@ interface ICommunityRole {
name: string; name: string;
} }
interface ICommunityInvite {
id: string;
}
interface ICreateInvite { interface ICreateInvite {
totalInvites?: number; totalInvites?: number;
remainingInvites?: number; remainingInvites?: number;
@ -35,5 +39,6 @@ export {
type ICommunityMember, type ICommunityMember,
type ICommunityChannel, type ICommunityChannel,
type ICommunityRole, type ICommunityRole,
type ICommunityInvite,
type ICreateInvite, type ICreateInvite,
}; };