forked from noxious/server
my 13th reason
This commit is contained in:
parent
4157ff5b5c
commit
80ec470fd4
@ -2,3 +2,4 @@
|
|||||||
ENV=development
|
ENV=development
|
||||||
PORT=4000
|
PORT=4000
|
||||||
DATABASE_URL="mysql://root@localhost:3306/nq"
|
DATABASE_URL="mysql://root@localhost:3306/nq"
|
||||||
|
JWT_SECRET="secret"
|
119
package-lock.json
generated
119
package-lock.json
generated
@ -10,6 +10,7 @@
|
|||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
"express": "^4.19.2",
|
"express": "^4.19.2",
|
||||||
|
"jsonwebtoken": "^9.0.2",
|
||||||
"prisma": "^5.13.0",
|
"prisma": "^5.13.0",
|
||||||
"socket.io": "^4.7.5",
|
"socket.io": "^4.7.5",
|
||||||
"ts-node": "^10.9.2",
|
"ts-node": "^10.9.2",
|
||||||
@ -18,6 +19,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bcryptjs": "^2.4.6",
|
"@types/bcryptjs": "^2.4.6",
|
||||||
"@types/express": "^4.17.21",
|
"@types/express": "^4.17.21",
|
||||||
|
"@types/jsonwebtoken": "^9.0.6",
|
||||||
"@types/node": "^20.12.11",
|
"@types/node": "^20.12.11",
|
||||||
"@types/socket.io": "^3.0.2",
|
"@types/socket.io": "^3.0.2",
|
||||||
"nodemon": "^3.1.0"
|
"nodemon": "^3.1.0"
|
||||||
@ -229,6 +231,16 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/jsonwebtoken": {
|
||||||
|
"version": "9.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.6.tgz",
|
||||||
|
"integrity": "sha512-/5hndP5dCjloafCXns6SZyESp3Ldq7YjH3zwzwczYnjxIT0Fqzk5ROSYVGfFyczIue7IUEj8hkvLbPoLQ18vQw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/mime": {
|
"node_modules/@types/mime": {
|
||||||
"version": "1.3.5",
|
"version": "1.3.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz",
|
||||||
@ -436,6 +448,12 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/buffer-equal-constant-time": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
|
||||||
|
"license": "BSD-3-Clause"
|
||||||
|
},
|
||||||
"node_modules/bytes": {
|
"node_modules/bytes": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
|
||||||
@ -617,6 +635,15 @@
|
|||||||
"url": "https://dotenvx.com"
|
"url": "https://dotenvx.com"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ecdsa-sig-formatter": {
|
||||||
|
"version": "1.0.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
|
||||||
|
"integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"safe-buffer": "^5.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ee-first": {
|
"node_modules/ee-first": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||||
@ -1043,6 +1070,97 @@
|
|||||||
"node": ">=0.12.0"
|
"node": ">=0.12.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/jsonwebtoken": {
|
||||||
|
"version": "9.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz",
|
||||||
|
"integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"jws": "^3.2.2",
|
||||||
|
"lodash.includes": "^4.3.0",
|
||||||
|
"lodash.isboolean": "^3.0.3",
|
||||||
|
"lodash.isinteger": "^4.0.4",
|
||||||
|
"lodash.isnumber": "^3.0.3",
|
||||||
|
"lodash.isplainobject": "^4.0.6",
|
||||||
|
"lodash.isstring": "^4.0.1",
|
||||||
|
"lodash.once": "^4.0.0",
|
||||||
|
"ms": "^2.1.1",
|
||||||
|
"semver": "^7.5.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12",
|
||||||
|
"npm": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/jsonwebtoken/node_modules/ms": {
|
||||||
|
"version": "2.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
|
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/jwa": {
|
||||||
|
"version": "1.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
|
||||||
|
"integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"buffer-equal-constant-time": "1.0.1",
|
||||||
|
"ecdsa-sig-formatter": "1.0.11",
|
||||||
|
"safe-buffer": "^5.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/jws": {
|
||||||
|
"version": "3.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
|
||||||
|
"integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"jwa": "^1.4.1",
|
||||||
|
"safe-buffer": "^5.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/lodash.includes": {
|
||||||
|
"version": "4.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
|
||||||
|
"integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/lodash.isboolean": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/lodash.isinteger": {
|
||||||
|
"version": "4.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
|
||||||
|
"integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/lodash.isnumber": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/lodash.isplainobject": {
|
||||||
|
"version": "4.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
|
||||||
|
"integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/lodash.isstring": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/lodash.once": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
|
||||||
|
"integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/make-error": {
|
"node_modules/make-error": {
|
||||||
"version": "1.3.6",
|
"version": "1.3.6",
|
||||||
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
|
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
|
||||||
@ -1374,7 +1492,6 @@
|
|||||||
"version": "7.6.2",
|
"version": "7.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz",
|
||||||
"integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==",
|
"integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==",
|
||||||
"dev": true,
|
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"bin": {
|
"bin": {
|
||||||
"semver": "bin/semver.js"
|
"semver": "bin/semver.js"
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
"express": "^4.19.2",
|
"express": "^4.19.2",
|
||||||
|
"jsonwebtoken": "^9.0.2",
|
||||||
"prisma": "^5.13.0",
|
"prisma": "^5.13.0",
|
||||||
"socket.io": "^4.7.5",
|
"socket.io": "^4.7.5",
|
||||||
"ts-node": "^10.9.2",
|
"ts-node": "^10.9.2",
|
||||||
@ -18,6 +19,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bcryptjs": "^2.4.6",
|
"@types/bcryptjs": "^2.4.6",
|
||||||
"@types/express": "^4.17.21",
|
"@types/express": "^4.17.21",
|
||||||
|
"@types/jsonwebtoken": "^9.0.6",
|
||||||
"@types/node": "^20.12.11",
|
"@types/node": "^20.12.11",
|
||||||
"@types/socket.io": "^3.0.2",
|
"@types/socket.io": "^3.0.2",
|
||||||
"nodemon": "^3.1.0"
|
"nodemon": "^3.1.0"
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import {User} from "@prisma/client";
|
import {User} from "@prisma/client";
|
||||||
|
|
||||||
interface ILoggedInUsers {
|
type TLoggedInUsers = {
|
||||||
users: User[];
|
users: User[];
|
||||||
}
|
}
|
||||||
|
|
||||||
class UserManager {
|
class UserManager {
|
||||||
private loggedInUsers: ILoggedInUsers[] = [];
|
private loggedInUsers: TLoggedInUsers[] = [];
|
||||||
|
|
||||||
// Method to initialize user manager
|
// Method to initialize user manager
|
||||||
public async boot() {
|
public async boot() {
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import {Character, Zone} from "@prisma/client";
|
import {Character, Zone} from "@prisma/client";
|
||||||
import ZoneRepository from "./repositories/zone.repository";
|
import ZoneRepository from "./repositories/ZoneRepository";
|
||||||
import ZoneService from "./services/zone.service";
|
import ZoneService from "./services/ZoneService";
|
||||||
|
|
||||||
interface ILoadedZone {
|
type TLoadedZone = {
|
||||||
zone: Zone;
|
zone: Zone;
|
||||||
characters: Character[];
|
characters: Character[];
|
||||||
}
|
}
|
||||||
|
|
||||||
class ZoneManager {
|
class ZoneManager {
|
||||||
private loadedZones: ILoadedZone[] = [];
|
private loadedZones: TLoadedZone[] = [];
|
||||||
|
|
||||||
// Method to initialize zone manager
|
// Method to initialize zone manager
|
||||||
public async boot() {
|
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 { Socket, Server } from "socket.io";
|
||||||
import ZoneRepository from "../repositories/zone.repository";
|
import ZoneRepository from "../repositories/ZoneRepository";
|
||||||
import ZoneManager from "../ZoneManager";
|
import ZoneManager from "../ZoneManager";
|
||||||
import {Zone} from "@prisma/client";
|
import {Zone} from "@prisma/client";
|
||||||
|
|
||||||
@ -14,7 +14,7 @@ interface IZoneLoad {
|
|||||||
* @param socket
|
* @param socket
|
||||||
* @param io
|
* @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) => {
|
socket.on('character:zone:load', async (data: IZoneLoad) => {
|
||||||
console.log(`---User ${socket.id} has requested zone.`);
|
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";
|
import { Socket, Server } from "socket.io";
|
||||||
|
|
||||||
export default function user_connect(socket: Socket, io: Server) {
|
export default function Disconnect(socket: Socket, io: Server) {
|
||||||
socket.on('disconnect', (data) => {
|
socket.on('disconnect', (data: any) => {
|
||||||
console.log(`---User ${socket.id} has disconnected.`);
|
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 {Character} from '@prisma/client';
|
||||||
import CharacterService from "../services/character.service";
|
import CharacterService from "../services/CharacterService";
|
||||||
|
|
||||||
class CharacterRepository {
|
class CharacterRepository {
|
||||||
async getByUserId(userId: number): Promise<Character[] | null> {
|
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';
|
import { User } from '@prisma/client';
|
||||||
|
|
||||||
class UserRepository {
|
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> {
|
async getByUsername(username: string): Promise<User | null> {
|
||||||
try {
|
try {
|
||||||
return await prisma.user.findUnique({
|
return await prisma.user.findUnique({
|
||||||
@ -14,7 +26,6 @@ class UserRepository {
|
|||||||
throw new Error(`Failed to get user by username: ${error.message}`);
|
throw new Error(`Failed to get user by username: ${error.message}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async create(username: string, password: string): Promise<User> {
|
async create(username: string, password: string): Promise<User> {
|
||||||
try {
|
try {
|
||||||
return await prisma.user.create({
|
return await prisma.user.create({
|
@ -1,5 +1,5 @@
|
|||||||
import { Zone } from '@prisma/client';
|
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 {
|
class ZoneRepository {
|
||||||
async getFirst(): Promise<Zone | null> {
|
async getFirst(): Promise<Zone | null> {
|
@ -1,6 +1,6 @@
|
|||||||
import bcrypt from "bcryptjs";
|
import bcrypt from "bcryptjs";
|
||||||
import UserRepository from "../repositories/user.repository";
|
import UserRepository from "../repositories/UserRepository";
|
||||||
import CharacterRepository from "../repositories/character.repository";
|
import CharacterRepository from "../repositories/CharacterRepository";
|
||||||
|
|
||||||
class UserService {
|
class UserService {
|
||||||
async login(username: string, password: string): Promise<boolean | any> {
|
async login(username: string, password: string): Promise<boolean | any> {
|
@ -1,5 +1,5 @@
|
|||||||
import {Zone} from "@prisma/client";
|
import {Zone} from "@prisma/client";
|
||||||
import ZoneRepository from "../repositories/zone.repository";
|
import ZoneRepository from "../repositories/ZoneRepository";
|
||||||
|
|
||||||
class ZoneService
|
class ZoneService
|
||||||
{
|
{
|
@ -1,8 +1,7 @@
|
|||||||
import { Socket } from 'socket.io';
|
import { Socket } from 'socket.io';
|
||||||
import {Character as ICharacter, User} from "@prisma/client";
|
import {Character as ICharacter, User} from "@prisma/client";
|
||||||
|
|
||||||
interface Character extends Socket
|
export type TCharacter = Socket & {
|
||||||
{
|
|
||||||
user?: User,
|
user?: User,
|
||||||
character?: ICharacter
|
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 {
|
class config {
|
||||||
static ENV: string = process.env.ENV || "prod";
|
static ENV: string = process.env.ENV || "prod";
|
||||||
static PORT: number = process.env.PORT ? parseInt(process.env.PORT) : 5000;
|
static PORT: number = process.env.PORT ? parseInt(process.env.PORT) : 5000;
|
||||||
|
static JWT_SECRET: string = process.env.JWT_SECRET || "secret";
|
||||||
}
|
}
|
||||||
|
|
||||||
export default config;
|
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) => {
|
app.post('/login', async (req: Request, res: Response) => {
|
||||||
const { username, password } = req.body;
|
const { username, password } = req.body;
|
||||||
|
|
||||||
@ -9,7 +17,8 @@ async function addAuthRoutes(app: any) {
|
|||||||
const user = await userService.login(username, password);
|
const user = await userService.login(username, password);
|
||||||
|
|
||||||
if (user) {
|
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' });
|
return res.status(401).json({ message: 'Invalid credentials' });
|
||||||
});
|
});
|
||||||
@ -21,7 +30,8 @@ async function addAuthRoutes(app: any) {
|
|||||||
const user = await userService.register(username, password);
|
const user = await userService.register(username, password);
|
||||||
|
|
||||||
if (user) {
|
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' });
|
return res.status(400).json({ message: 'Failed to register user' });
|
||||||
});
|
});
|
||||||
@ -29,4 +39,4 @@ async function addAuthRoutes(app: any) {
|
|||||||
console.log('[✅] Auth routes added');
|
console.log('[✅] Auth routes added');
|
||||||
}
|
}
|
||||||
|
|
||||||
export default { addAuthRoutes };
|
export { addAuthRoutes };
|
@ -1,19 +1,21 @@
|
|||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import express, {Application} from 'express';
|
import express, {Application} from 'express';
|
||||||
import http from 'http';
|
import {createServer as httpServer} from 'http';
|
||||||
|
import {addAuthRoutes} from './app/utilities/Http';
|
||||||
import cors from 'cors';
|
import cors from 'cors';
|
||||||
import {Server as SocketServer, Socket} from 'socket.io';
|
import {Server as SocketServer} from 'socket.io';
|
||||||
import config from './app/utilities/config';
|
import {TSocket} from "./app/types/TSocket";
|
||||||
import prisma from './app/utilities/prisma';
|
import config from './app/utilities/Config';
|
||||||
import api from "./app/utilities/api";
|
import prisma from './app/utilities/Prisma';
|
||||||
import ZoneManager from "./app/ZoneManager";
|
import ZoneManager from "./app/ZoneManager";
|
||||||
import UserManager from "./app/UserManager";
|
import UserManager from "./app/UserManager";
|
||||||
|
import {Authentication} from "./app/middleware/Authentication";
|
||||||
|
|
||||||
export class Server
|
export class Server
|
||||||
{
|
{
|
||||||
private readonly app: Application;
|
private readonly app: Application;
|
||||||
private readonly server: any;
|
private readonly http: any;
|
||||||
private readonly io: SocketServer;
|
private readonly io: SocketServer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -24,8 +26,9 @@ export class Server
|
|||||||
this.app.use(cors());
|
this.app.use(cors());
|
||||||
this.app.use(express.json());
|
this.app.use(express.json());
|
||||||
this.app.use(express.urlencoded({ extended: true }));
|
this.app.use(express.urlencoded({ extended: true }));
|
||||||
this.server = http.createServer(this.app)
|
this.http = httpServer(this.app)
|
||||||
this.io = new SocketServer(this.server);
|
this.io = new SocketServer(this.http);
|
||||||
|
this.io.use(Authentication)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -46,14 +49,14 @@ export class Server
|
|||||||
|
|
||||||
// Start the server
|
// Start the server
|
||||||
try {
|
try {
|
||||||
await this.server.listen(config.PORT);
|
await this.http.listen(config.PORT);
|
||||||
console.log('[✅] Socket.IO running on port', config.PORT);
|
console.log('[✅] Socket.IO running on port', config.PORT);
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
throw new Error(`[❌] Socket.IO failed to start: ${error.message}`);
|
throw new Error(`[❌] Socket.IO failed to start: ${error.message}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add API routes
|
// Add http API routes
|
||||||
await api.addAuthRoutes(this.app);
|
await addAuthRoutes(this.app);
|
||||||
|
|
||||||
// Load user manager
|
// Load user manager
|
||||||
await UserManager.boot();
|
await UserManager.boot();
|
||||||
@ -70,7 +73,7 @@ export class Server
|
|||||||
* @param socket
|
* @param socket
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
private async handleConnection(socket: Socket) {
|
private async handleConnection(socket: TSocket) {
|
||||||
const eventsPath = path.join(__dirname, 'app', 'events');
|
const eventsPath = path.join(__dirname, 'app', 'events');
|
||||||
try {
|
try {
|
||||||
const files: string[] = await fs.promises.readdir(eventsPath);
|
const files: string[] = await fs.promises.readdir(eventsPath);
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
|
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
|
||||||
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
|
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
|
||||||
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
|
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
|
||||||
// "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
|
"typeRoots": ["./node_modules/@types", "./src/app"], /* Specify multiple folders that act like './node_modules/@types'. */
|
||||||
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
|
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
|
||||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||||
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
|
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user