forked from noxious/server
my 13th reason
This commit is contained in:
@ -1,11 +1,11 @@
|
||||
import {User} from "@prisma/client";
|
||||
|
||||
interface ILoggedInUsers {
|
||||
type TLoggedInUsers = {
|
||||
users: User[];
|
||||
}
|
||||
|
||||
class UserManager {
|
||||
private loggedInUsers: ILoggedInUsers[] = [];
|
||||
private loggedInUsers: TLoggedInUsers[] = [];
|
||||
|
||||
// Method to initialize user manager
|
||||
public async boot() {
|
||||
|
@ -1,14 +1,14 @@
|
||||
import {Character, Zone} from "@prisma/client";
|
||||
import ZoneRepository from "./repositories/zone.repository";
|
||||
import ZoneService from "./services/zone.service";
|
||||
import ZoneRepository from "./repositories/ZoneRepository";
|
||||
import ZoneService from "./services/ZoneService";
|
||||
|
||||
interface ILoadedZone {
|
||||
type TLoadedZone = {
|
||||
zone: Zone;
|
||||
characters: Character[];
|
||||
}
|
||||
|
||||
class ZoneManager {
|
||||
private loadedZones: ILoadedZone[] = [];
|
||||
private loadedZones: TLoadedZone[] = [];
|
||||
|
||||
// Method to initialize zone manager
|
||||
public async boot() {
|
||||
|
8
src/app/events/CharacterConnect.ts
Normal file
8
src/app/events/CharacterConnect.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { Socket, Server } from "socket.io";
|
||||
import {TSocket} from "../types/TSocket";
|
||||
|
||||
export default function CharacterConnect(socket: TSocket, io: Server) {
|
||||
socket.on('character:connect', (data: any) => {
|
||||
console.log(`---User ${socket.user?.id} has joined.`);
|
||||
});
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import { Socket, Server } from "socket.io";
|
||||
import ZoneRepository from "../repositories/zone.repository";
|
||||
import ZoneRepository from "../repositories/ZoneRepository";
|
||||
import ZoneManager from "../ZoneManager";
|
||||
import {Zone} from "@prisma/client";
|
||||
|
||||
@ -14,7 +14,7 @@ interface IZoneLoad {
|
||||
* @param socket
|
||||
* @param io
|
||||
*/
|
||||
export default function characterZoneLoad(socket: Socket, io: Server) {
|
||||
export default function CharacterZoneLoad(socket: Socket, io: Server) {
|
||||
socket.on('character:zone:load', async (data: IZoneLoad) => {
|
||||
console.log(`---User ${socket.id} has requested zone.`);
|
||||
|
8
src/app/events/CharactersGet.ts
Normal file
8
src/app/events/CharactersGet.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { Socket, Server } from "socket.io";
|
||||
import {TSocket} from "../types/TSocket";
|
||||
|
||||
export default function CharactersGet(socket: TSocket, io: Server) {
|
||||
socket.on('characters:get', async (data: any) => {
|
||||
console.log(socket.user);
|
||||
});
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import { Socket, Server } from "socket.io";
|
||||
|
||||
export default function user_connect(socket: Socket, io: Server) {
|
||||
socket.on('disconnect', (data) => {
|
||||
export default function Disconnect(socket: Socket, io: Server) {
|
||||
socket.on('disconnect', (data: any) => {
|
||||
console.log(`---User ${socket.id} has disconnected.`);
|
||||
});
|
||||
}
|
7
src/app/events/Login.ts
Normal file
7
src/app/events/Login.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { Socket, Server } from "socket.io";
|
||||
|
||||
export default function Login(socket: Socket, io: Server) {
|
||||
socket.on('login', (data: any) => {
|
||||
console.log(`---User ${socket.id} has logged in.`);
|
||||
});
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
import { Socket, Server } from "socket.io";
|
||||
import {ISocket} from "../interfaces/socket";
|
||||
|
||||
export default function characterConnect(socket: ISocket, io: Server) {
|
||||
socket.on('character:connect', (data) => {
|
||||
socket.user.username = 'hello'
|
||||
console.log(`---User ${socket.id} has joined.`);
|
||||
});
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
import { Socket, Server } from "socket.io";
|
||||
import {ISocket} from "../interfaces/socket";
|
||||
|
||||
export default function characterConnect(socket: ISocket, io: Server) {
|
||||
socket.on('characters:get', async (data) => {
|
||||
console.log(socket.user.username)
|
||||
console.log(`---characters requested.`);
|
||||
});
|
||||
}
|
17
src/app/index.d.ts
vendored
Normal file
17
src/app/index.d.ts
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
import "socket.io";
|
||||
|
||||
declare module "socket.io" {
|
||||
interface Socket {
|
||||
data: {
|
||||
user: {
|
||||
id: string;
|
||||
username: string;
|
||||
};
|
||||
};
|
||||
handshake: {
|
||||
headers: {
|
||||
cookie: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
import {Socket} from "socket.io";
|
||||
|
||||
export interface ISocket extends Socket {
|
||||
user?: any;
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
import {Character} from "@prisma/client";
|
||||
|
||||
interface zoneCharacters extends Character
|
||||
{
|
||||
|
||||
}
|
37
src/app/middleware/Authentication.ts
Normal file
37
src/app/middleware/Authentication.ts
Normal file
@ -0,0 +1,37 @@
|
||||
// socket io jwt auth middleware
|
||||
import { verify } from 'jsonwebtoken';
|
||||
import { TSocket } from '../types/TSocket';
|
||||
import config from "../utilities/Config";
|
||||
import UserRepository from "../repositories/UserRepository";
|
||||
import {User} from "@prisma/client";
|
||||
|
||||
export async function Authentication (socket: TSocket, next: any) {
|
||||
|
||||
if (!socket.request.headers.cookie) {
|
||||
console.log('No cookie provided');
|
||||
return next(new Error('Authentication error'));
|
||||
}
|
||||
|
||||
const cookies = socket.request.headers.cookie.split('; ').reduce((prev: any, current: any) => {
|
||||
const [name, value] = current.split('=');
|
||||
prev[name] = value;
|
||||
return prev;
|
||||
}, {});
|
||||
|
||||
const token = cookies['token'];
|
||||
|
||||
if (token) {
|
||||
verify(token, config.JWT_SECRET, async (err: any, decoded: any) => {
|
||||
if (err) {
|
||||
console.log('err');
|
||||
return next(new Error('Authentication error'));
|
||||
}
|
||||
|
||||
socket.user = await UserRepository.getById(decoded.id) as User;
|
||||
next();
|
||||
});
|
||||
} else {
|
||||
console.log('No token provided');
|
||||
next(new Error('Authentication error'));
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
import prisma from '../utilities/prisma'; // Import the global Prisma instance
|
||||
import prisma from '../utilities/Prisma'; // Import the global Prisma instance
|
||||
import {Character} from '@prisma/client';
|
||||
import CharacterService from "../services/character.service";
|
||||
import CharacterService from "../services/CharacterService";
|
||||
|
||||
class CharacterRepository {
|
||||
async getByUserId(userId: number): Promise<Character[] | null> {
|
@ -1,7 +1,19 @@
|
||||
import prisma from '../utilities/prisma'; // Import the global Prisma instance
|
||||
import prisma from '../utilities/Prisma'; // Import the global Prisma instance
|
||||
import { User } from '@prisma/client';
|
||||
|
||||
class UserRepository {
|
||||
async getById(id: number): Promise<User | null> {
|
||||
try {
|
||||
return await prisma.user.findUnique({
|
||||
where: {
|
||||
id,
|
||||
},
|
||||
});
|
||||
} catch (error: any) {
|
||||
// Handle error
|
||||
throw new Error(`Failed to get user by ID: ${error.message}`);
|
||||
}
|
||||
}
|
||||
async getByUsername(username: string): Promise<User | null> {
|
||||
try {
|
||||
return await prisma.user.findUnique({
|
||||
@ -14,7 +26,6 @@ class UserRepository {
|
||||
throw new Error(`Failed to get user by username: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
async create(username: string, password: string): Promise<User> {
|
||||
try {
|
||||
return await prisma.user.create({
|
@ -1,5 +1,5 @@
|
||||
import { Zone } from '@prisma/client';
|
||||
import prisma from '../utilities/prisma'; // Import the global Prisma instance
|
||||
import prisma from '../utilities/Prisma'; // Import the global Prisma instance
|
||||
|
||||
class ZoneRepository {
|
||||
async getFirst(): Promise<Zone | null> {
|
@ -1,6 +1,6 @@
|
||||
import bcrypt from "bcryptjs";
|
||||
import UserRepository from "../repositories/user.repository";
|
||||
import CharacterRepository from "../repositories/character.repository";
|
||||
import UserRepository from "../repositories/UserRepository";
|
||||
import CharacterRepository from "../repositories/CharacterRepository";
|
||||
|
||||
class UserService {
|
||||
async login(username: string, password: string): Promise<boolean | any> {
|
@ -1,5 +1,5 @@
|
||||
import {Zone} from "@prisma/client";
|
||||
import ZoneRepository from "../repositories/zone.repository";
|
||||
import ZoneRepository from "../repositories/ZoneRepository";
|
||||
|
||||
class ZoneService
|
||||
{
|
@ -1,8 +1,7 @@
|
||||
import { Socket } from 'socket.io';
|
||||
import {Character as ICharacter, User} from "@prisma/client";
|
||||
|
||||
interface Character extends Socket
|
||||
{
|
||||
export type TCharacter = Socket & {
|
||||
user?: User,
|
||||
character?: ICharacter
|
||||
}
|
16
src/app/types/TSocket.ts
Normal file
16
src/app/types/TSocket.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import {Socket} from "socket.io";
|
||||
import { User } from '@prisma/client';
|
||||
|
||||
export type TSocket = Socket & {
|
||||
user?: User
|
||||
handshake?: {
|
||||
query?: {
|
||||
token?: any
|
||||
}
|
||||
}
|
||||
request?: {
|
||||
headers?: {
|
||||
cookie?: any
|
||||
}
|
||||
}
|
||||
}
|
5
src/app/types/TZoneCharacter.ts
Normal file
5
src/app/types/TZoneCharacter.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import {Character} from "@prisma/client";
|
||||
|
||||
export type TZoneCharacter = Character & {
|
||||
|
||||
}
|
@ -5,6 +5,7 @@ dotenv.config();
|
||||
class config {
|
||||
static ENV: string = process.env.ENV || "prod";
|
||||
static PORT: number = process.env.PORT ? parseInt(process.env.PORT) : 5000;
|
||||
static JWT_SECRET: string = process.env.JWT_SECRET || "secret";
|
||||
}
|
||||
|
||||
export default config;
|
@ -1,7 +1,15 @@
|
||||
import { Request, Response } from 'express';
|
||||
import UserService from '../services/user.service';
|
||||
/**
|
||||
* Resources:
|
||||
* https://stackoverflow.com/questions/76131891/what-is-the-best-method-for-socket-io-authentication
|
||||
*
|
||||
*/
|
||||
|
||||
async function addAuthRoutes(app: any) {
|
||||
import {Application, Request, Response} from 'express';
|
||||
import UserService from '../services/UserService';
|
||||
import jwt from "jsonwebtoken";
|
||||
import config from "./Config";
|
||||
|
||||
async function addAuthRoutes(app: Application) {
|
||||
app.post('/login', async (req: Request, res: Response) => {
|
||||
const { username, password } = req.body;
|
||||
|
||||
@ -9,7 +17,8 @@ async function addAuthRoutes(app: any) {
|
||||
const user = await userService.login(username, password);
|
||||
|
||||
if (user) {
|
||||
return res.status(200).json(user);
|
||||
const token = jwt.sign({ id: user.id }, config.JWT_SECRET, { expiresIn: '1h' });
|
||||
return res.status(200).json({ token });
|
||||
}
|
||||
return res.status(401).json({ message: 'Invalid credentials' });
|
||||
});
|
||||
@ -21,7 +30,8 @@ async function addAuthRoutes(app: any) {
|
||||
const user = await userService.register(username, password);
|
||||
|
||||
if (user) {
|
||||
return res.status(201).json(user);
|
||||
const token = jwt.sign({ id: user.id }, config.JWT_SECRET, { expiresIn: '1h' });
|
||||
return res.status(201).json({ token });
|
||||
}
|
||||
return res.status(400).json({ message: 'Failed to register user' });
|
||||
});
|
||||
@ -29,4 +39,4 @@ async function addAuthRoutes(app: any) {
|
||||
console.log('[✅] Auth routes added');
|
||||
}
|
||||
|
||||
export default { addAuthRoutes };
|
||||
export { addAuthRoutes };
|
Reference in New Issue
Block a user