diff --git a/package-lock.json b/package-lock.json index a23a5b5..0263788 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "tether", - "version": "0.3.6", + "version": "0.3.7", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "tether", - "version": "0.3.6", + "version": "0.3.7", "license": "GPL-3.0-only", "dependencies": { "@fastify/cookie": "^11.0.2", diff --git a/package.json b/package.json index b2e0e89..1c1560d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tether", - "version": "0.3.6", + "version": "0.3.7", "description": "Communication server using the Nexlink protocol", "repository": { "type": "git", diff --git a/src/controllers/community/community.ts b/src/controllers/community/community.ts index 2de1ed6..08cb643 100644 --- a/src/controllers/community/community.ts +++ b/src/controllers/community/community.ts @@ -22,6 +22,9 @@ import type { IGetRolesParams, IGetRolesResponseError, IGetRolesResponseSuccess, + IGetInvitesParams, + IGetInvitesResponseError, + IGetInvitesResponseSuccess, IPostCreateInviteParams, IPostCreateInviteRequest, IPostCreateInviteResponseError, @@ -34,6 +37,7 @@ import { getCommunityChannelsByIdAuth, getCommunityMembersByIdAuth, getCommunityRolesByIdAuth, + getCommunityInvitesByIdAuth, createInviteAuth, deleteCommunityByIdAuth, } from "../../services/community/community.js"; @@ -243,6 +247,36 @@ const getRoles = async (request: FastifyRequest, reply: FastifyReply) => { } 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 ( request: FastifyRequest, reply: FastifyReply, @@ -292,5 +326,6 @@ export { getMembers, getChannels, getRoles, + getInvites, postCreateInvite, }; diff --git a/src/controllers/community/routes.ts b/src/controllers/community/routes.ts index 5a18b99..e35fe60 100644 --- a/src/controllers/community/routes.ts +++ b/src/controllers/community/routes.ts @@ -9,6 +9,7 @@ const communityRoutes = async (fastify: FastifyInstance) => { fastify.get(`/:id/members`, controller.getMembers); fastify.get(`/:id/channels`, controller.getChannels); fastify.get(`/:id/roles`, controller.getRoles); + fastify.get(`/:id/invites`, controller.getInvites); fastify.post(`/:id/invite`, controller.postCreateInvite); }; diff --git a/src/controllers/community/types.ts b/src/controllers/community/types.ts index d831387..b1e4972 100644 --- a/src/controllers/community/types.ts +++ b/src/controllers/community/types.ts @@ -72,10 +72,10 @@ interface IGetMembersResponseError { interface IGetMembersResponseSuccess { id: string; name: string; - members: IGetMembersResponseMembers[]; + members: IGetMembersResponseMember[]; } -interface IGetMembersResponseMembers { +interface IGetMembersResponseMember { id: string; username: string; } @@ -92,10 +92,10 @@ interface IGetChannelsResponseError { interface IGetChannelsResponseSuccess { id: string; name: string; - channels: IGetChannelsResponseChannels[]; + channels: IGetChannelsResponseChannel[]; } -interface IGetChannelsResponseChannels { +interface IGetChannelsResponseChannel { id: string; name: string; } @@ -112,14 +112,33 @@ interface IGetRolesResponseError { interface IGetRolesResponseSuccess { id: string; name: string; - roles: IGetRolesResponseRoles[]; + roles: IGetRolesResponseRole[]; } -interface IGetRolesResponseRoles { +interface IGetRolesResponseRole { id: 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 { id: string; } @@ -157,15 +176,19 @@ export { type IGetMembersParams, type IGetMembersResponseError, type IGetMembersResponseSuccess, - type IGetMembersResponseMembers, + type IGetMembersResponseMember, type IGetChannelsParams, type IGetChannelsResponseError, type IGetChannelsResponseSuccess, - type IGetChannelsResponseChannels, + type IGetChannelsResponseChannel, type IGetRolesParams, type IGetRolesResponseError, type IGetRolesResponseSuccess, - type IGetRolesResponseRoles, + type IGetRolesResponseRole, + type IGetInvitesParams, + type IGetInvitesResponseError, + type IGetInvitesResponseSuccess, + type IGetInvitesResponseInvite, type IPostCreateInviteParams, type IPostCreateInviteRequest, type IPostCreateInviteResponseError, diff --git a/src/services/auth/permission.ts b/src/services/auth/permission.ts index 0d9d217..de6fa1c 100644 --- a/src/services/auth/permission.ts +++ b/src/services/auth/permission.ts @@ -3,12 +3,12 @@ enum PERMISSION { CHANNELS_READ = "CHANNELS_READ", CHANNELS_MANAGE = "CHANNELS_MANAGE", ROLES_READ = "ROLES_READ", - INVITES_CREATE = "INVITES_CREATE", - INVITES_DELETE = "INVITES_DELETE", ROLES_MANAGE = "ROLES_MANAGE", MEMBERS_READ = "MEMBERS_READ", MEMBERS_KICK = "MEMBERS_KICK", MEMBERS_BAN = "MEMBERS_BAN", + INVITES_CREATE = "INVITES_CREATE", + INVITES_DELETE = "INVITES_DELETE", } export { PERMISSION }; diff --git a/src/services/community/community.ts b/src/services/community/community.ts index ebc4f97..cf14ea1 100644 --- a/src/services/community/community.ts +++ b/src/services/community/community.ts @@ -9,11 +9,12 @@ import { import { PERMISSION } from "../auth/permission.js"; import type { ICreateCommunity, + IUpdateCommunity, ICommunityChannel, ICommunityMember, ICommunityRole, + ICommunityInvite, ICreateInvite, - IUpdateCommunity, } from "./types.js"; const getCommunityById = async (id: string): Promise => { @@ -227,6 +228,42 @@ const getCommunityRolesByIdAuth = async ( return await getCommunityRolesById(id); }; +const getCommunityInvitesById = async ( + id: string, +): Promise => { + return await getDB().invite.findMany({ + where: { + communityId: id, + }, + select: { + id: true, + }, + }); +}; + +const getCommunityInvitesByIdAuth = async ( + id: string, + authHeader: string | undefined, +): Promise => { + 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 ( id: string, creatorId: string, @@ -280,6 +317,8 @@ export { getCommunityChannelsByIdAuth, getCommunityRolesById, getCommunityRolesByIdAuth, + getCommunityInvitesById, + getCommunityInvitesByIdAuth, createInvite, createInviteAuth, }; diff --git a/src/services/community/types.ts b/src/services/community/types.ts index 9096244..1fe3973 100644 --- a/src/services/community/types.ts +++ b/src/services/community/types.ts @@ -23,6 +23,10 @@ interface ICommunityRole { name: string; } +interface ICommunityInvite { + id: string; +} + interface ICreateInvite { totalInvites?: number; remainingInvites?: number; @@ -35,5 +39,6 @@ export { type ICommunityMember, type ICommunityChannel, type ICommunityRole, + type ICommunityInvite, type ICreateInvite, };