various improvements

This commit is contained in:
Zoe
2023-04-20 21:19:22 -05:00
parent b6d3b045aa
commit 3ea8167569
60 changed files with 12369 additions and 7625 deletions

51
server/api/channels/[id]/index.get.ts Normal file → Executable file
View File

@@ -1,20 +1,20 @@
import { IChannel, IServer, SafeUser } from '../../../../types'
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
import { IChannel, IServer, SafeUser } from '~/types';
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
export default defineEventHandler(async (event) => {
if (!event.context.user.authenticated) {
event.node.res.statusCode = 401;
return {
message: 'You must be logged in to view a channel.'
}
throw createError({
statusCode: 401,
statusMessage: 'You must be logged in to view a channel.',
});
}
if (!event.context.params.id) {
event.node.res.statusCode = 400;
return {
message: 'A channelId is required'
}
if (!event.context.params?.id) {
throw createError({
statusCode: 400,
statusMessage: 'A channelId is required',
});
}
const channel = await prisma.channel.findFirst({
@@ -58,7 +58,7 @@ export default defineEventHandler(async (event) => {
name: true,
participants: {
select: {
id: true
id: true,
}
}
}
@@ -69,7 +69,6 @@ export default defineEventHandler(async (event) => {
select: {
id: true,
emoji: true,
count: true,
users: {
select: {
id: true,
@@ -114,7 +113,6 @@ export default defineEventHandler(async (event) => {
select: {
id: true,
emoji: true,
count: true,
users: {
select: {
id: true,
@@ -137,10 +135,10 @@ export default defineEventHandler(async (event) => {
}) as IChannel | null;
if (!channel) {
event.node.res.statusCode = 404;
return {
message: `Channel with id "${event.context.params.id}" not found`
}
throw createError({
statusCode: 404,
statusMessage: `Channel with id "${event.context.params.id}" not found`,
});
}
if (channel.serverId && !channel.DM) {
@@ -156,15 +154,16 @@ export default defineEventHandler(async (event) => {
if (!server) return;
const userInServer: Array<SafeUser> | undefined = server?.participants.filter((e: SafeUser) => e.id === event.context.user.id)
const userInServer: Array<SafeUser> | undefined = server.participants.filter((e: SafeUser) => e.id === event.context.user.id);
if (!userInServer) {
event.node.res.statusCode = 401;
return {
message: `You must be in the server to access a channel in that server`
}
throw createError({
statusCode: 401,
statusMessage: 'You must be in the server to access a channel in that server',
});
}
}
return channel
})
return channel;
});

View File

@@ -0,0 +1,49 @@
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
export default defineEventHandler(async (event) => {
if (!event.context.user.authenticated) {
throw createError({
statusCode: 401,
statusMessage: 'You must be logged in to send a message.',
});
}
const { id: channelId, messageId } = event.context.params;
const message = await prisma.message.findFirst({
where: {
id: messageId,
channelId: channelId,
},
include: {
creator: true
}
});
if (!message) {
throw createError({
statusCode: 404,
statusMessage: `message in channel ${channelId} with id ${messageId} is not found.`,
});
}
if (event.context.user.id !== message.creator.id) {
throw createError({
statusCode: 401,
statusMessage: 'you are not allowed to delete that message.',
});
}
await prisma.message.delete({
where: {
id: message.id
}
});
global.io.emit(`message-${event.context.params?.id}`, { message: { id: message.id }, deleted: true });
return {
message: 'message successfully deleted.'
};
});

View File

@@ -1,52 +0,0 @@
import { IChannel, IServer, SafeUser } from '~/types'
import emojiRegex from 'emoji-regex'
import { PrismaClient } from '@prisma/client'
import parseBody from '~~/utils/parseMessageBody'
const prisma = new PrismaClient()
export default defineEventHandler(async (event) => {
if (!event.context.user.authenticated) {
event.node.res.statusCode = 401;
return {
message: 'You must be logged in to send a message.'
}
}
const { id: channelId, messageId } = event.context.params
const message = await prisma.message.findFirst({
where: {
id: messageId,
channelId: channelId,
},
include: {
creator: true
}
})
if (!message) {
event.node.res.statusCode = 404;
return {
message: `message in channel ${channelId} with id ${messageId} is not found.`
}
}
if (event.context.user.id !== message.creator.id) {
event.node.res.statusCode = 401;
return {
message: 'you are not allowed to delete that message.'
}
}
await prisma.message.delete({
where: {
id: message.id
}
})
global.io.emit(`message-${event.context.params.id}`, { message: { id: message.id }, deleted: true });
return {
message: 'message successfully deleted.'
}
})

View File

@@ -1,23 +1,29 @@
import { IChannel, IServer, SafeUser } from '~/types'
import emojiRegex from 'emoji-regex'
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
import emojiRegex from 'emoji-regex';
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
export default defineEventHandler(async (event) => {
if (!event.context.user.authenticated) {
event.node.res.statusCode = 401;
return {
message: 'You must be logged in to send a message.'
}
throw createError({
statusCode: 401,
statusMessage: 'You must be logged in to send a message.',
});
}
const emoji = decodeURIComponent(event.context.params.name)
if (!event.context.params?.name) {
throw createError({
statusCode: 400,
statusMessage: 'Reaction must be defined.',
});
}
const emoji = decodeURIComponent(event.context.params.name);
const match = emoji.match(emojiRegex());
if (!match || match.length !== 1) {
event.node.res.statusCode = 400;
return {
message: 'reaction is not an emoji or more than one emoji.'
}
throw createError({
statusCode: 400,
statusMessage: 'reaction is not an emoji or more than one emoji.',
});
}
@@ -30,27 +36,10 @@ export default defineEventHandler(async (event) => {
username: true
}
},
invites: {
select: {
id: true,
server: {
select: {
id: true,
name: true,
participants: {
select: {
id: true
}
}
}
}
}
},
reactions: {
select: {
id: true,
emoji: true,
count: true,
users: {
select: {
id: true,
@@ -59,31 +48,23 @@ export default defineEventHandler(async (event) => {
}
}
}
}
};
const message = await prisma.message.findFirst({
where: {
id: event.context.params.messageId
},
select: messageSelect
})
});
if (!message.id) {
event.node.res.statusCode = 404;
return {
message: `message with id "${event.context.params.messageId}" not found.`
}
if (!message || !message.id) {
throw createError({
statusCode: 404,
statusMessage: `message with id "${event.context.params.messageId}" not found.`,
});
}
const reactionInMessage = message.reactions.find((e) => e.emoji.name === emoji)
let count;
if (reactionInMessage?.count) {
count = reactionInMessage.count + 1;
} else {
count = 1;
}
const reactionInMessage = message.reactions.find((e) => e.emoji === emoji);
if (reactionInMessage && reactionInMessage.users.find((e) => e.id === event.context.user.id)) {
// remove reaction
@@ -92,23 +73,22 @@ export default defineEventHandler(async (event) => {
id: reactionInMessage.id
},
data: {
count: reactionInMessage.count - 1,
users: {
disconnect: [{ id: event.context.user.id }]
}
}
})
});
const updatedMessage = await prisma.message.findFirst({
where: {
id: event.context.params.messageId
},
select: messageSelect
})
});
global.io.emit(`message-${event.context.params.id}`, { message: updatedMessage });
return { message: updatedMessage }
return { message: updatedMessage };
}
let reaction;
@@ -119,22 +99,17 @@ export default defineEventHandler(async (event) => {
id: reactionInMessage.id
},
data: {
count,
users: {
connect: [{
id: event.context.user.id,
}]
},
}
})
});
} else {
reaction = await prisma.reaction.create({
data: {
emoji: {
name: emoji,
id: null
},
count: count,
emoji,
users: {
connect: [{
id: event.context.user.id,
@@ -146,7 +121,7 @@ export default defineEventHandler(async (event) => {
}
}
}
})
});
}
if (!reaction.messageId) return;
@@ -156,9 +131,9 @@ export default defineEventHandler(async (event) => {
id: reaction.messageId,
},
select: messageSelect
})
});
global.io.emit(`message-${event.context.params.id}`, { message: updatedMessage });
return { message: updatedMessage }
})
return { message: updatedMessage };
});

View File

@@ -1,28 +1,40 @@
import { IChannel, IServer, SafeUser, IMessage } from '~/types'
import { Server } from 'socket.io'
import { PrismaClient } from '@prisma/client'
import { registerRuntimeHelpers } from '@vue/compiler-core'
const prisma = new PrismaClient()
import { IChannel, IServer, SafeUser, IMessage } from '~/types';
import { Server } from 'socket.io';
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
declare global {
var io: Server
let io: Server;
}
export default defineEventHandler(async (event) => {
if (!event.context.user.authenticated) {
event.node.res.statusCode = 401;
return {
message: 'You must be logged in to send a message.'
}
throw createError({
statusCode: 401,
statusMessage: 'You must be logged in to send a message.',
});
}
let { body, channelId } = await readBody(event)
if (!event.context.params?.id) return;
if (!body || !channelId) {
event.node.res.statusCode = 400;
return {
message: 'A body or channelId is required to send a message.'
}
const req = await readBody(event);
const channelId = event.context.params.id;
if (!req || !channelId) {
throw createError({
statusCode: 400,
statusMessage: 'A body is required to send a message.',
});
}
let { body } = req;
if (body.length > 5000) {
throw createError({
statusCode: 400,
statusMessage: 'Message is larger than 5000 characters.'
});
}
const channel = await prisma.channel.findFirst({
@@ -34,6 +46,7 @@ export default defineEventHandler(async (event) => {
name: true,
messages: false,
DM: true,
serverId: true,
dmParticipants: {
select: {
id: true,
@@ -44,10 +57,10 @@ export default defineEventHandler(async (event) => {
}) as IChannel | null;
if (!channel) {
event.node.res.statusCode = 404;
return {
message: `Channel with id "${channelId}" not found.`
}
throw createError({
statusCode: 404,
statusMessage: `Channel with id "${channelId}" not found.`,
});
}
if (!channel.DM) {
@@ -88,43 +101,44 @@ export default defineEventHandler(async (event) => {
}) as IServer | null;
if (!server) {
throw new Error(`server with id "${channel.serverId}" is not found but channel with id "${channel.id}" is not a dm?`)
throw new Error(`server with id "${channel.serverId}" is not found but channel with id "${channel.id}" is not a dm?`);
}
const userInServer: SafeUser | undefined = server.participants.find((e: SafeUser) => e.id === event.context.user.id)
const userInServer: SafeUser | undefined = server.participants.find((e: SafeUser) => e.id === event.context.user.id);
if (!userInServer) {
event.node.res.statusCode = 401;
return {
message: 'You must be in the server to send a message.'
}
throw createError({
statusCode: 401,
statusMessage: 'You must be in the server to send a message.',
});
}
if (!server) {
event.node.res.statusCode = 404;
return {
message: 'Server not found'
}
throw createError({
statusCode: 404,
statusMessage: 'Server not found',
});
}
} else {
const userInDM: SafeUser | undefined = channel.dmParticipants?.find((e) => e.id === event.context.user.id)
const userInDM: SafeUser | undefined = channel.dmParticipants?.find((e) => e.id === event.context.user.id);
if (!userInDM) {
event.node.res.statusCode = 401;
return {
message: 'You must be in the DM to send a message.'
}
throw createError({
statusCode: 401,
statusMessage: 'You must be in the DM to send a message.',
});
}
}
// TODO: make this client side or something because it's bug ridden right now lmao
const inviteCodes = body.match(/<&([a-z]|[0-9]){25}>/g);
let invites: { id: string; }[] = [];
const invites: { id: string; }[] = [];
if (inviteCodes) {
inviteCodes.forEach((e: string) => {
if (!e) return
if (!e) return;
const opBody = body;
body = body.split(e).join('')
body = body.split(e).join('');
if (opBody === body) return;
const id = e.split('<&')[1]?.split('>')[0];
if (!id) return;
@@ -174,10 +188,10 @@ export default defineEventHandler(async (event) => {
}
}
}
}) as unknown as IMessage
}) as unknown as IMessage;
global.io.emit(`message-${channel.id}`, { message });
return message
})
return message;
});

42
server/api/channels/create.post.ts Normal file → Executable file
View File

@@ -1,35 +1,37 @@
import { IServer } from '~/types'
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
import { IServer } from '~/types';
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
export default defineEventHandler(async (event) => {
if (!event.context.user.authenticated) {
event.node.res.statusCode = 401;
return {
message: 'You must be logged in to view a channel.'
}
throw createError({
statusCode: 401,
statusMessage: 'You must be logged in to view a channel.',
});
}
const { serverName } = await readBody(event)
const body = await readBody(event);
if (!serverName) {
event.node.res.statusCode = 400;
return {
message: 'channel name is required to create a channel.'
}
if (!body) {
throw createError({
statusCode: 400,
statusMessage: 'Server name is required to create a Server.',
});
}
const { serverName } = body;
const preExistingServer = await prisma.server.findFirst({
where: {
name: serverName
}
}) as IServer
}) as IServer | null;
if (preExistingServer) {
event.node.res.statusCode = 409;
return {
message: `Server with name ${serverName} already exists.`
}
throw createError({
statusCode: 409,
statusMessage: `Server with name ${serverName} already exists.`,
});
}
const server = await prisma.server.create({
@@ -87,5 +89,5 @@ export default defineEventHandler(async (event) => {
}
}) as unknown as IServer;
return server
})
return server;
});

50
server/api/channels/createDM.post.ts Normal file → Executable file
View File

@@ -1,22 +1,22 @@
import { IChannel, SafeUser } from '~/types'
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
import { IChannel, SafeUser } from '~/types';
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
export default defineEventHandler(async (event) => {
if (!event.context.user.authenticated) {
event.node.res.statusCode = 401;
return {
message: 'You must be logged in to view a channel.'
}
throw createError({
statusCode: 401,
statusMessage: 'You must be logged in to view a channel.',
});
}
const { partnerId } = await readBody(event)
const { partnerId } = await readBody(event);
if (!partnerId) {
event.node.res.statusCode = 400;
return {
message: 'A friend is required to create a DM.'
}
throw createError({
statusCode: 400,
statusMessage: 'A friend is required to create a DM.',
});
}
const partner = await prisma.user.findFirst({
@@ -32,14 +32,14 @@ export default defineEventHandler(async (event) => {
}) as SafeUser | null;
if (!partner) {
event.node.res.statusCode = 400;
return {
message: 'No partner found'
}
throw createError({
statusCode: 400,
statusMessage: 'No partner found',
});
}
if (!user) {
throw new Error('user not found?')
throw new Error('user not found?');
}
const preExistingServer = await prisma.channel.findFirst({
@@ -47,13 +47,13 @@ export default defineEventHandler(async (event) => {
name: `${user.id}-${partner.id}`,
DM: true
}
}) as IChannel
}) as IChannel;
if (preExistingServer) {
event.node.res.statusCode = 409;
return {
message: `DM already exists.`
}
throw createError({
statusCode: 409,
statusMessage: 'DM already exists.',
});
}
const server = await prisma.channel.create({
@@ -74,7 +74,7 @@ export default defineEventHandler(async (event) => {
}
}
}
}) as IChannel
}) as IChannel;
return server
})
return server;
});

18
server/api/getCurrentUser.get.ts Normal file → Executable file
View File

@@ -1,13 +1,13 @@
import { PrismaClient } from '@prisma/client'
import { SafeUser } from '../../types'
const prisma = new PrismaClient()
import { PrismaClient } from '@prisma/client';
import { SafeUser } from '~/types';
const prisma = new PrismaClient();
export default defineEventHandler(async (event) => {
if (!event.context.user.authenticated) {
event.node.res.statusCode = 401;
return {
message: "Unauthenticated"
}
throw createError({
statusCode: 401,
statusMessage: 'Unauthenticated',
});
}
const user = await prisma.user.findFirst({
@@ -26,5 +26,5 @@ export default defineEventHandler(async (event) => {
}
}) as SafeUser | null;
return user
})
return user;
});

60
server/api/guilds/[id]/addChannel.post.ts Normal file → Executable file
View File

@@ -1,23 +1,23 @@
import { IChannel, IServer, SafeUser } from '~/types'
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
import { IChannel, IServer, SafeUser } from '~/types';
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
export default defineEventHandler(async (event) => {
if (!event.context.user.authenticated) {
event.node.res.statusCode = 401;
return {
message: 'You must be logged in to view a channel.'
}
throw createError({
statusCode: 401,
statusMessage: 'You must be logged in to view a channel.',
});
}
if (!event.context.params.id) {
event.node.res.statusCode = 400;
return {
message: 'A serverId is required'
}
if (!event.context.params?.id) {
throw createError({
statusCode: 400,
statusMessage: 'A serverId is required',
});
}
const { channelName } = await readBody(event)
const { channelName } = await readBody(event);
const server = await prisma.server.findFirst({
where: {
@@ -31,26 +31,26 @@ export default defineEventHandler(async (event) => {
}) as IServer | null;
if (!server) {
event.node.res.statusCode = 404;
return {
message: `Server with id "${event.context.params.id}" not found`
}
throw createError({
statusCode: 404,
statusMessage: `Server with id "${event.context.params.id}" not found`,
});
}
const userInServer: Array<SafeUser> = server.participants.filter((e: SafeUser) => e.id === event.context.user.id)
const userInServer: Array<SafeUser> = server.participants.filter((e: SafeUser) => e.id === event.context.user.id);
if (!userInServer) {
event.node.res.statusCode = 401;
return {
message: `You must be in the server to access a channel in that server`
}
throw createError({
statusCode: 401,
statusMessage: 'You must be in the server to access a channel in that server',
});
}
if (server.channels?.find((e) => e.name === channelName)) {
event.node.res.statusCode = 409;
return {
message: `Channel with name "${channelName}" already exists in server with id "event.context.user.id"`
}
throw createError({
statusCode: 409,
statusMessage: `Channel with name "${channelName}" already exists in server with id "event.context.user.id"`,
});
}
const channel = await prisma.channel.create({
@@ -121,9 +121,9 @@ export default defineEventHandler(async (event) => {
},
serverId: true,
}
}) as IChannel
}) as IChannel;
global.io.emit(`addChannel-${server.id}`, channel)
global.io.emit(`addChannel-${server.id}`, channel);
return channel
})
return channel;
});

52
server/api/guilds/[id]/createInvite.post.ts Normal file → Executable file
View File

@@ -1,25 +1,25 @@
import { IChannel, IInviteCode, IServer, SafeUser } from '~/types'
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
import { IInviteCode, IServer, SafeUser } from '~/types';
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
export default defineEventHandler(async (event) => {
if (!event.context.user.authenticated) {
event.node.res.statusCode = 401;
return {
message: 'You must be logged in to view a channel.'
}
throw createError({
statusCode: 401,
statusMessage: 'You must be logged in to view a channel.',
});
}
if (!event.context.params.id) {
event.node.res.statusCode = 400;
return {
message: 'A serverId is required'
}
if (!event.context.params?.id) {
throw createError({
statusCode: 400,
statusMessage: 'A serverId is required',
});
}
let body = await readBody(event)
// const body = await readBody(event);
let expires = false;
// let expires = false;
// if (body.expiryDate) {
// expires = true;
// body.expiryDate = new Date(body.expiryDate).getUTCDate()
@@ -37,19 +37,19 @@ export default defineEventHandler(async (event) => {
}) as IServer | null;
if (!server) {
event.node.res.statusCode = 404;
return {
message: `Server with id "${event.context.params.id}" not found`
}
throw createError({
statusCode: 404,
statusMessage: `Server with id "${event.context.params.id}" not found`,
});
}
const userInServerAndPermited: Array<SafeUser> = server.participants.filter((e: SafeUser) => e.id === event.context.user.id && e.roles?.some((el) => el.administer === true || el.owner === false))
const userInServerAndPermited: Array<SafeUser> = server.participants.filter((e: SafeUser) => e.id === event.context.user.id && e.roles?.some((el) => el.administer === true || el.owner === false));
if (!userInServerAndPermited) {
event.node.res.statusCode = 401;
return {
message: `You must be in the server or an admin/owner of that server to make an invite code`
}
throw createError({
statusCode: 401,
statusMessage: 'You must be in the server or an admin/owner of that server to make an invite code',
});
}
const inviteCode = await prisma.inviteCode.create({
@@ -61,7 +61,7 @@ export default defineEventHandler(async (event) => {
},
maxUses: 0
}
}) as IInviteCode
}) as IInviteCode;
return inviteCode
})
return inviteCode;
});

88
server/api/guilds/[id]/index.get.ts Normal file → Executable file
View File

@@ -1,20 +1,20 @@
import { IServer } from '~/types'
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
import { IServer } from '~/types';
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
export default defineEventHandler(async (event) => {
if (!event.context.user.authenticated) {
event.node.res.statusCode = 401;
return {
message: 'You must be logged in to view a channel.'
}
throw createError({
statusCode: 401,
statusMessage: 'You must be logged in to view a channel.',
});
}
if (!event.context.params.id) {
event.node.res.statusCode = 400;
return {
message: 'A channelId is required'
}
if (!event.context.params?.id) {
throw createError({
statusCode: 400,
statusMessage: 'A channelId is required',
});
}
const server = await prisma.server.findFirst({
@@ -35,60 +35,30 @@ export default defineEventHandler(async (event) => {
id: true,
DM: true,
name: true,
messages: {
}
},
roles: {
select: {
id: true,
name: true,
administrator: true,
owner: true,
users: {
select: {
id: true,
body: true,
creator: {
select: {
id: true,
username: true
}
},
invites: {
select: {
id: true,
server: {
select: {
id: true,
name: true,
participants: {
select: {
id: true
}
}
}
}
}
},
reactions: {
select: {
id: true,
emoji: true,
count: true,
users: {
select: {
id: true,
username: true
}
}
}
}
id: true
}
}
}
},
}
}
}) as IServer | null;
if (!server) {
event.node.res.statusCode = 404;
return {
message: `Channel with id "${event.context.params.id}" not found`
}
throw createError({
statusCode: 404,
statusMessage: `Channel with id "${event.context.params.id}" not found`,
});
}
return {
server
}
})
return server;
});

52
server/api/guilds/joinGuild.post.ts Normal file → Executable file
View File

@@ -1,22 +1,22 @@
import { IInviteCode, IServer } from '~/types'
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
import { IInviteCode, IServer } from '~/types';
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
export default defineEventHandler(async (event) => {
if (!event.context.user.authenticated) {
event.node.res.statusCode = 401;
return {
message: 'You must be logged in to view a channel.'
}
throw createError({
statusCode: 401,
statusMessage: 'You must be logged in to view a channel.',
});
}
const { inviteId } = await readBody(event);
if (!inviteId) {
event.node.res.statusCode = 400;
return {
message: 'A inviteId is required'
}
throw createError({
statusCode: 400,
statusMessage: 'A inviteId is required',
});
}
const invite = await prisma.inviteCode.findFirst({
@@ -43,19 +43,19 @@ export default defineEventHandler(async (event) => {
}) as IInviteCode | null;
if (!invite) {
event.node.res.statusCode = 404;
return {
message: `Invite with id "${inviteId}" not found`
}
throw createError({
statusCode: 404,
statusMessage: `Invite with id "${inviteId}" not found`,
});
}
const userInServer = invite.server.participants.find((e) => e.id === event.context.user.id);
if (userInServer) {
event.node.res.statusCode = 409;
return {
message: `You are already in that server.`
}
throw createError({
statusCode: 409,
statusMessage: 'You are already in that server.',
});
}
// TODO: check if invite is valid
@@ -101,16 +101,16 @@ export default defineEventHandler(async (event) => {
}
}
}
}) as unknown as IServer
}) as unknown as IServer;
if (!server) {
event.node.res.statusCode = 404;
return {
message: `Channel with id "${event.context.params.id}" not found`
}
throw createError({
statusCode: 404,
statusMessage: `Channel with id "${event.context.params?.id}" not found`,
});
}
return {
server
}
})
};
});

49
server/api/login.post.ts Normal file → Executable file
View File

@@ -1,17 +1,22 @@
import bcryptjs from "bcryptjs";
import { v4 as uuidv4 } from "uuid";
import { PrismaClient } from '@prisma/client'
import { IUser, SafeUser } from "../../types";
const prisma = new PrismaClient()
import bcryptjs from 'bcryptjs';
import { v4 as uuidv4 } from 'uuid';
import * as dotenv from 'dotenv';
import crypto from 'node:crypto';
import { PrismaClient } from '@prisma/client';
import { IUser, SafeUser } from '~/types';
const prisma = new PrismaClient();
dotenv.config();
export default defineEventHandler(async (event) => {
const body = await readBody(event)
if (!process.env.SESSION_SECRET_KEY) throw new Error('Session secret missing');
const body = await readBody(event);
if (!body.username || !body.password) {
event.node.res.statusCode = 400;
return {
message: 'A username, and a password are required to login'
}
throw createError({
statusCode: 400,
statusMessage: 'A username, and a password are required to login',
});
}
let user = await prisma.user.findFirst({
@@ -24,31 +29,33 @@ export default defineEventHandler(async (event) => {
passwordhash: true,
email: true,
},
}) as unknown as IUser
}) as unknown as IUser;
const isCorrect = await bcryptjs.compare(body.password, user.passwordhash)
const isCorrect = await bcryptjs.compare(body.password, user.passwordhash);
if (!isCorrect) {
event.node.res.statusCode = 401;
return {
message: 'Incorrect username or password'
}
throw createError({
statusCode: 401,
statusMessage: 'Incorrect username or password',
});
}
const token = uuidv4()
const token = crypto.createHmac('sha1', process.env.SESSION_SECRET_KEY)
.update(uuidv4())
.digest('hex');
await prisma.session.create({
data: {
token,
userId: user.id
}
})
});
user = user as SafeUser
user = user as SafeUser;
return {
token,
userId: user.id,
user
}
})
};
});

77
server/api/signup.post.ts Normal file → Executable file
View File

@@ -1,17 +1,22 @@
import bcryptjs from "bcryptjs";
import { v4 as uuidv4 } from "uuid";
import { PrismaClient } from '@prisma/client'
import { IUser, SafeUser } from "~/types";
const prisma = new PrismaClient()
import bcryptjs from 'bcryptjs';
import { v4 as uuidv4 } from 'uuid';
import * as dotenv from 'dotenv';
import crypto from 'node:crypto';
import { PrismaClient } from '@prisma/client';
import { IUser, SafeUser } from '~/types';
const prisma = new PrismaClient();
dotenv.config();
export default defineEventHandler(async (event) => {
const body = await readBody(event)
if (!process.env.SESSION_SECRET_KEY) throw new Error('Session secret missing');
const body = await readBody(event);
if (!body.username || !body.password || !body.email) {
event.node.res.statusCode = 400;
return {
message: 'A username, a password, and an email address are required to singup'
}
throw createError({
statusCode: 400,
statusMessage: 'A username, a password, and an email address are required to singup',
});
}
const preExistingUser = await prisma.user.findFirst({
@@ -25,16 +30,16 @@ export default defineEventHandler(async (event) => {
}
]
}
}) as SafeUser
}) as SafeUser;
if (preExistingUser) {
event.node.res.statusCode = 409;
return {
message: `User with username ${body.username} or email ${body.email} already exists`
}
throw createError({
statusCode: 409,
statusMessage: `User with username ${body.username} or email ${body.email} already exists`,
});
}
const passwordhash = await bcryptjs.hash(body.password, 10)
const passwordhash = await bcryptjs.hash(body.password, 10);
const user = await prisma.user.create({
data: {
@@ -46,35 +51,39 @@ export default defineEventHandler(async (event) => {
id: true,
username: true,
servers: {
participants: {
select: {
id: true,
username: true
}
},
channels: {
select: {
id: true,
DM: true,
name: true,
}
},
select: {
participants: {
select: {
id: true,
username: true
}
},
channels: {
select: {
id: true,
DM: true,
name: true,
}
},
}
}
},
}) as unknown as IUser
}) as unknown as IUser;
const token = uuidv4()
const token = crypto.createHmac('sha1', process.env.SESSION_SECRET_KEY)
.update(uuidv4())
.digest('hex');
await prisma.session.create({
data: {
token,
userId: user.id
}
})
});
return {
token,
userId: user.id,
user
}
})
};
});

100
server/api/user/getServers.get.ts Normal file → Executable file
View File

@@ -1,13 +1,13 @@
import { PrismaClient } from '@prisma/client'
import { IChannel, IServer, IUser } from '~/types'
const prisma = new PrismaClient()
import { PrismaClient } from '@prisma/client';
import { IChannel, IServer } from '~/types';
const prisma = new PrismaClient();
export default defineEventHandler(async (event) => {
if (!event.context.user.authenticated) {
event.node.res.statusCode = 401;
return {
message: "Unauthenticated"
}
throw createError({
statusCode: 401,
statusMessage: 'Unauthenticated',
});
}
const servers = await prisma.server.findMany({
@@ -24,89 +24,8 @@ export default defineEventHandler(async (event) => {
channels: {
select: {
id: true,
DM: true,
name: true,
server: {
select: {
id: true,
name: true,
participants: {
select: {
id: true,
username: true
}
},
channels: {
select: {
id: true,
DM: true,
name: true,
messages: {
select: {
id: true,
body: true,
creator: {
select: {
id: true,
username: true
}
},
invites: {
select: {
id: true,
server: {
select: {
id: true,
name: true,
participants: {
select: {
id: true
}
}
}
}
}
},
reactions: {
select: {
id: true,
emoji: true,
count: true,
users: {
select: {
id: true,
username: true
}
}
}
}
}
}
}
},
}
},
},
},
participants: {
select: {
id: true,
username: true
}
},
roles: {
select: {
id: true,
name: true,
administrator: true,
owner: true,
users: {
select: {
id: true
}
}
}
}
}
}) as unknown as IServer[] | null;
@@ -122,7 +41,6 @@ export default defineEventHandler(async (event) => {
select: {
id: true,
name: true,
messages: false,
DM: true,
dmParticipants: {
select: {
@@ -135,5 +53,5 @@ export default defineEventHandler(async (event) => {
return {
servers, dms
}
})
};
});

22
server/api/user/logout.ts Normal file → Executable file
View File

@@ -1,23 +1,23 @@
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
export default defineEventHandler(async (event) => {
const { sessionToken } = parseCookies(event)
const { sessionToken } = parseCookies(event);
if (!sessionToken) {
event.node.res.statusCode = 400;
return {
message: 'A session token is required to logout duh'
}
throw createError({
statusCode: 400,
statusMessage: 'A session token is required to logout duh',
});
}
await prisma.session.delete({
where: {
token: sessionToken
},
})
});
return {
message: `successfully logged out`
}
})
message: 'successfully logged out'
};
});