Created some user endpoints ; Pretty code
This commit is contained in:
10
concord-server/.editorconfig
Normal file
10
concord-server/.editorconfig
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# EditorConfig helps maintain consistent coding styles
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
end_of_line = lf
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
To install dependencies:
|
To install dependencies:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
bun install
|
bun install
|
||||||
```
|
```
|
||||||
|
|
||||||
To run:
|
To run:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
bun run dev
|
bun run dev
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
import { getUserInformation } from "../services/actions";
|
|
||||||
|
|
||||||
|
|
||||||
export async function fetchUserData(id: string) {
|
|
||||||
return await getUserInformation(id);
|
|
||||||
}
|
|
||||||
9
concord-server/src/controller/userController.ts
Normal file
9
concord-server/src/controller/userController.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { getAllUsersFrom, getUserInformation } from "../services/userService";
|
||||||
|
|
||||||
|
export async function fetchUserData(id: string) {
|
||||||
|
return await getUserInformation(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function fetchAllUsers(instanceId: string) {
|
||||||
|
return await getAllUsersFrom(instanceId);
|
||||||
|
}
|
||||||
@@ -1,50 +1,53 @@
|
|||||||
import { Hono } from 'hono'
|
import { Hono } from "hono";
|
||||||
import { cors } from 'hono/cors'
|
import { cors } from "hono/cors";
|
||||||
import { Server as Engine } from '@socket.io/bun-engine'
|
import { Server as Engine } from "@socket.io/bun-engine";
|
||||||
import { Server } from 'socket.io'
|
import { Server } from "socket.io";
|
||||||
import routes from './routes/index'
|
import routes from "./routes/index";
|
||||||
|
|
||||||
//initialize socket.io server
|
//initialize socket.io server
|
||||||
const io = new Server()
|
const io = new Server();
|
||||||
|
|
||||||
//initialize bun engine
|
//initialize bun engine
|
||||||
//then bind to socket.io server
|
//then bind to socket.io server
|
||||||
const engine = new Engine()
|
const engine = new Engine();
|
||||||
io.bind(engine)
|
io.bind(engine);
|
||||||
|
|
||||||
io.on('connection', (socket) => {
|
io.on("connection", (socket) => {
|
||||||
|
//get userId and clientId from query params
|
||||||
|
const userId = socket.handshake.query.userId;
|
||||||
|
const clientId = socket.handshake.query.clientId;
|
||||||
|
if (!userId || Array.isArray(userId)) {
|
||||||
|
socket.disconnect();
|
||||||
|
throw new Error("Invalid user ID");
|
||||||
|
}
|
||||||
|
|
||||||
//get userId and clientId from query params
|
if (!clientId || Array.isArray(clientId)) {
|
||||||
const userId = socket.handshake.query.userId;
|
socket.disconnect();
|
||||||
const clientId = socket.handshake.query.clientId;
|
throw new Error("Invalid client ID");
|
||||||
if(!userId || Array.isArray(userId)){
|
}
|
||||||
socket.disconnect();
|
|
||||||
throw new Error('Invalid user ID');
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!clientId || Array.isArray(clientId)){
|
socket.join(userId);
|
||||||
socket.disconnect()
|
console.log(
|
||||||
throw new Error('Invalid client ID')
|
`User ${userId} connected. Client ID ${clientId} on socket ${socket.id}`,
|
||||||
}
|
);
|
||||||
|
|
||||||
socket.join(userId)
|
socket.on("disconnect", () => {
|
||||||
console.log(`User ${userId} connected. Client ID ${clientId} on socket ${socket.id}`);
|
console.log(`User ${userId} disconnected from socket ${socket.id}`);
|
||||||
|
});
|
||||||
socket.on('disconnect', () => {
|
|
||||||
console.log(`User ${userId} disconnected from socket ${socket.id}`);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const app = new Hono()
|
const app = new Hono();
|
||||||
|
|
||||||
app.use('*', cors({
|
app.use(
|
||||||
origin: 'http://localhost:5173',
|
"*",
|
||||||
allowHeaders: ['Content-Type', 'Authorization'],
|
cors({
|
||||||
allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
|
origin: "http://localhost:5173",
|
||||||
credentials: true
|
allowHeaders: ["Content-Type", "Authorization"],
|
||||||
}))
|
allowMethods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
|
||||||
|
credentials: true,
|
||||||
app.route('/api', routes)
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
app.route("/api", routes);
|
||||||
|
|
||||||
export default app;
|
export default app;
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
import { Hono } from "hono"
|
|
||||||
import { fetchUserData } from "../controller/actions"
|
|
||||||
const actions = new Hono()
|
|
||||||
|
|
||||||
/*
|
|
||||||
actions.post("actions/message/:id", (c) => {
|
|
||||||
//todo: pass service function to send a message to user id
|
|
||||||
})
|
|
||||||
|
|
||||||
actions.delete("actions/message/delete/:id", (c) => {
|
|
||||||
//todo: pass service function to delete a message by user id
|
|
||||||
})
|
|
||||||
|
|
||||||
actions.get("actions/message/all/:userId", (c) => {
|
|
||||||
//todo: pass service function to fetch all messages f a user
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
actions.get("actions/userChannels/:id", (c) => {
|
|
||||||
//todo: pass service function to fetch all channels the id is part of
|
|
||||||
})
|
|
||||||
*/
|
|
||||||
|
|
||||||
actions.get("actions/:id", async (c) => {
|
|
||||||
const id = c.req.param("id");
|
|
||||||
const userData = await fetchUserData(id);
|
|
||||||
if (userData) {
|
|
||||||
return c.json(userData);
|
|
||||||
} else {
|
|
||||||
return c.json({ error: "User not found" }, 404);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
export default actions
|
|
||||||
@@ -1,11 +1,9 @@
|
|||||||
//place exported routes below this line
|
//place exported routes below this line
|
||||||
import { Hono } from 'hono';
|
import { Hono } from "hono";
|
||||||
import actions from './actions';
|
import actions from "./userRoutes";
|
||||||
|
|
||||||
|
|
||||||
const routes = new Hono();
|
const routes = new Hono();
|
||||||
|
|
||||||
routes.route("/", actions)
|
routes.route("/", actions);
|
||||||
|
|
||||||
|
|
||||||
export default routes;
|
export default routes;
|
||||||
25
concord-server/src/routes/userRoutes.ts
Normal file
25
concord-server/src/routes/userRoutes.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import { Hono } from "hono";
|
||||||
|
import { fetchAllUsers, fetchUserData } from "../controller/userController";
|
||||||
|
const actions = new Hono();
|
||||||
|
|
||||||
|
actions.get("user/:id", async (c) => {
|
||||||
|
const id = c.req.param("id");
|
||||||
|
const userData = await fetchUserData(id);
|
||||||
|
if (userData) {
|
||||||
|
return c.json(userData);
|
||||||
|
} else {
|
||||||
|
return c.json({ error: "User not found" }, 404);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
actions.get("instance/:id/users", async (c) => {
|
||||||
|
const instanceId = c.req.param("id");
|
||||||
|
const userData = await fetchAllUsers(instanceId);
|
||||||
|
if (userData) {
|
||||||
|
return c.json(userData);
|
||||||
|
} else {
|
||||||
|
return c.json({ error: "Error getting all users from instance" }, 500);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default actions;
|
||||||
@@ -1,153 +0,0 @@
|
|||||||
import { Message, MessagePing, PrismaClient, Role, UserAuth } from "@prisma/client";
|
|
||||||
|
|
||||||
const prisma = new PrismaClient();
|
|
||||||
|
|
||||||
export async function getUserChannels(userId: string): Promise<string[] | null> {
|
|
||||||
try{
|
|
||||||
if(!userId){
|
|
||||||
throw new Error('missing userId');
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: add some prisma code here
|
|
||||||
//to fetch all the channels a user is part of
|
|
||||||
|
|
||||||
|
|
||||||
return ["test1","test2"];
|
|
||||||
}catch(err){
|
|
||||||
const errMessage = err as Error
|
|
||||||
|
|
||||||
if(errMessage.message === 'missing userId'){
|
|
||||||
console.log('services::actions::getUserChannels - missing userId');
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('services::actions::getUserChannels - unknown error', errMessage);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getUserInformation(userId: string):
|
|
||||||
Promise<{
|
|
||||||
id: string,
|
|
||||||
userName: string,
|
|
||||||
nickName: string | null,
|
|
||||||
bio: string | null,
|
|
||||||
picture: string | null,
|
|
||||||
banner: string | null,
|
|
||||||
admin: boolean,
|
|
||||||
status: 'online' | 'offline' | 'dnd' | 'idle' | 'invis',
|
|
||||||
role: Role[],
|
|
||||||
userAuth?: UserAuth,
|
|
||||||
} | null> {
|
|
||||||
try{
|
|
||||||
if(!userId){
|
|
||||||
throw new Error('missing userId');
|
|
||||||
}
|
|
||||||
|
|
||||||
const user = await prisma.user.findUnique({
|
|
||||||
where: {
|
|
||||||
id: userId
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!user) {
|
|
||||||
throw new Error('could not find user');
|
|
||||||
}
|
|
||||||
|
|
||||||
const userRoles = await prisma.role.findMany({
|
|
||||||
where: {
|
|
||||||
userId: userId
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return {
|
|
||||||
id: userId,
|
|
||||||
userName: user.username,
|
|
||||||
nickName: user.nickname,
|
|
||||||
bio: user.bio,
|
|
||||||
picture: user.picture,
|
|
||||||
banner: user.banner,
|
|
||||||
admin: user.admin,
|
|
||||||
status: (["online", "offline", "dnd", "idle", "invis"] as const).includes(user.status as any) ? user.status as 'online' | 'offline' | 'dnd' | 'idle' | 'invis' : 'offline',
|
|
||||||
role: userRoles,
|
|
||||||
};
|
|
||||||
|
|
||||||
}catch(err){
|
|
||||||
const errMessage = err as Error
|
|
||||||
|
|
||||||
if(errMessage.message === 'missing userId'){
|
|
||||||
console.log('services::actions::getUserInformation - missing userId');
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(errMessage.message === 'could not find user'){
|
|
||||||
console.log('services::actions::getUserInformation - unable to find user');
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('services::actions::getUserInformation - unknown error', errMessage);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getAllMessage(userId: string): Promise<{id: string, content: string, senderId: string, receiverId: string}[] | null> {
|
|
||||||
try{
|
|
||||||
if(!userId){
|
|
||||||
throw new Error('missing userId');
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: add some prisma code here
|
|
||||||
//to fetch all messages for a user
|
|
||||||
|
|
||||||
return [
|
|
||||||
{id: "1", content: "Hello", senderId: userId, receiverId: "2"},
|
|
||||||
{id: "2", content: "Hi", senderId: "2", receiverId: userId}
|
|
||||||
];
|
|
||||||
}catch(err){
|
|
||||||
const errMessage = err as Error
|
|
||||||
|
|
||||||
if(errMessage.message === 'missing userId'){
|
|
||||||
console.log('services::actions::getAllMessage - missing userId');
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('services::actions::getAllMessage - unknown error', errMessage);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export async function sendMessage(userId: string, content: string): Promise<boolean> {
|
|
||||||
try{
|
|
||||||
if(!userId){
|
|
||||||
throw new Error('missing userId');
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!content){
|
|
||||||
throw new Error('missing content');
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: add some prisma code here
|
|
||||||
//to save a message
|
|
||||||
|
|
||||||
//todo: add some socketio code to
|
|
||||||
//emit the message to the receiver
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}catch(err){
|
|
||||||
const errMessage = err as Error
|
|
||||||
|
|
||||||
if(errMessage.message === 'missing userId'){
|
|
||||||
console.log('services::actions::sendMessage - missing userId');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(errMessage.message === 'missing content'){
|
|
||||||
console.log('services::actions::sendMessage - missing content');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('services::actions::sendMessage - unknown error', errMessage);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
151
concord-server/src/services/userService.ts
Normal file
151
concord-server/src/services/userService.ts
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
import {
|
||||||
|
Message,
|
||||||
|
MessagePing,
|
||||||
|
PrismaClient,
|
||||||
|
Role,
|
||||||
|
UserAuth,
|
||||||
|
} from "@prisma/client";
|
||||||
|
|
||||||
|
const prisma = new PrismaClient();
|
||||||
|
|
||||||
|
export async function getUserInformation(userId: string): Promise<{
|
||||||
|
id: string;
|
||||||
|
userName: string;
|
||||||
|
nickName: string | null;
|
||||||
|
bio: string | null;
|
||||||
|
picture: string | null;
|
||||||
|
banner: string | null;
|
||||||
|
admin: boolean;
|
||||||
|
status: "online" | "offline" | "dnd" | "idle" | "invis";
|
||||||
|
role: Role[];
|
||||||
|
} | null> {
|
||||||
|
try {
|
||||||
|
if (!userId) {
|
||||||
|
throw new Error("missing userId");
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = await prisma.user.findUnique({
|
||||||
|
where: {
|
||||||
|
id: userId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
throw new Error("could not find user");
|
||||||
|
}
|
||||||
|
|
||||||
|
const userRoles = await prisma.role.findMany({
|
||||||
|
where: {
|
||||||
|
userId: userId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: userId,
|
||||||
|
userName: user.username,
|
||||||
|
nickName: user.nickname,
|
||||||
|
bio: user.bio,
|
||||||
|
picture: user.picture,
|
||||||
|
banner: user.banner,
|
||||||
|
admin: user.admin,
|
||||||
|
status: (["online", "offline", "dnd", "idle", "invis"] as const).includes(
|
||||||
|
user.status as any,
|
||||||
|
)
|
||||||
|
? (user.status as "online" | "offline" | "dnd" | "idle" | "invis")
|
||||||
|
: "offline",
|
||||||
|
role: userRoles,
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
const errMessage = err as Error;
|
||||||
|
|
||||||
|
if (errMessage.message === "missing userId") {
|
||||||
|
console.log("services::actions::getUserInformation - missing userId");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errMessage.message === "could not find user") {
|
||||||
|
console.log(
|
||||||
|
"services::actions::getUserInformation - unable to find user",
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
"services::actions::getUserInformation - unknown error",
|
||||||
|
errMessage,
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getAllUsersFrom(instanceId: string): Promise<
|
||||||
|
| {
|
||||||
|
id: string;
|
||||||
|
userName: string;
|
||||||
|
nickName: string | null;
|
||||||
|
bio: string | null;
|
||||||
|
picture: string | null;
|
||||||
|
banner: string | null;
|
||||||
|
admin: boolean;
|
||||||
|
status: "online" | "offline" | "dnd" | "idle" | "invis";
|
||||||
|
role: {
|
||||||
|
userId: string;
|
||||||
|
instanceId: string;
|
||||||
|
}[];
|
||||||
|
}[]
|
||||||
|
| null
|
||||||
|
> {
|
||||||
|
try {
|
||||||
|
const instances = await prisma.instance.findMany();
|
||||||
|
if (!instances) {
|
||||||
|
throw new Error("could not get all instances");
|
||||||
|
}
|
||||||
|
|
||||||
|
const users = await prisma.user.findMany({
|
||||||
|
where: {
|
||||||
|
Role: {
|
||||||
|
some: {
|
||||||
|
instanceId: instanceId,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (!users) {
|
||||||
|
throw new Error("could not get all users in instance");
|
||||||
|
}
|
||||||
|
|
||||||
|
const userData = await Promise.all(
|
||||||
|
users.map(async (u) => {
|
||||||
|
const userRoles = await prisma.role.findMany({
|
||||||
|
where: {
|
||||||
|
userId: u.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (!userRoles) {
|
||||||
|
throw new Error("could not get user roles for user " + u.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: u.id,
|
||||||
|
userName: u.username,
|
||||||
|
nickName: u.nickname,
|
||||||
|
bio: u.bio,
|
||||||
|
picture: u.picture,
|
||||||
|
banner: u.banner,
|
||||||
|
admin: u.admin,
|
||||||
|
status: (
|
||||||
|
["online", "offline", "dnd", "idle", "invis"] as const
|
||||||
|
).includes(u.status as any)
|
||||||
|
? (u.status as "online" | "offline" | "dnd" | "idle" | "invis")
|
||||||
|
: "offline",
|
||||||
|
role: userRoles,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
return userData;
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
import { zValidator } from "@hono/zod-validator"
|
|
||||||
|
|
||||||
export const
|
|
||||||
Reference in New Issue
Block a user