add register and login endpoints
This commit is contained in:
Generated
+965
File diff suppressed because it is too large
Load Diff
@@ -14,11 +14,13 @@
|
||||
"license": "MIT",
|
||||
"description": "",
|
||||
"dependencies": {
|
||||
"@types/bcrypt": "^5.0.2",
|
||||
"@types/express": "^4.17.21",
|
||||
"@types/jsonwebtoken": "^9.0.5",
|
||||
"@types/node": "^20.11.19",
|
||||
"@types/ws": "^8.5.10",
|
||||
"axios": "^1.7.7",
|
||||
"bcrypt": "^5.1.1",
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^16.4.4",
|
||||
"express": "5.0.0",
|
||||
|
||||
+7
-16
@@ -6,11 +6,12 @@ import mongoose from "mongoose";
|
||||
|
||||
export interface IUser {
|
||||
name: string,
|
||||
password?: string,
|
||||
uuid: string,
|
||||
id: ObjectId,
|
||||
config: UserConfig,
|
||||
lastState: MatrixState,
|
||||
spotifyConfig: SpotifyConfig,
|
||||
lastState?: MatrixState,
|
||||
spotifyConfig?: SpotifyConfig,
|
||||
timezone: string
|
||||
location: string
|
||||
}
|
||||
@@ -56,6 +57,10 @@ const userSchema = new mongoose.Schema<IUser>({
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
password: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
uuid: {
|
||||
type: String,
|
||||
required: true,
|
||||
@@ -78,70 +83,56 @@ const userSchema = new mongoose.Schema<IUser>({
|
||||
global: {
|
||||
mode: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
brightness: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
text: {
|
||||
text: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
align: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
speed: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
size: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
color: {
|
||||
type: [Number],
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
image: {
|
||||
image: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
clock: {
|
||||
color: {
|
||||
type: [Number],
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
music: {
|
||||
fullscreen: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
}
|
||||
}
|
||||
},
|
||||
spotifyConfig: {
|
||||
accessToken: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
refreshToken: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
expirationDate: {
|
||||
type: Date,
|
||||
required: true,
|
||||
},
|
||||
scope: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
timezone: {
|
||||
|
||||
@@ -35,4 +35,12 @@ export class UserService {
|
||||
public async getUserByUUID(uuid: string): Promise<IUser | null> {
|
||||
return await UserModel.findOne({uuid}).exec();
|
||||
}
|
||||
|
||||
public async getUserByName(name: string): Promise<IUser | null> {
|
||||
return await UserModel.findOne({name}).exec();
|
||||
}
|
||||
|
||||
public async createUser(user: IUser): Promise<IUser> {
|
||||
return await UserModel.create(user);
|
||||
}
|
||||
}
|
||||
|
||||
+4
-2
@@ -6,10 +6,10 @@ import {authenticateJwt} from "./rest/middleware/authenticateJwt";
|
||||
import {JwtTokenPropertiesExtractor} from "./rest/jwtTokenPropertiesExtractor";
|
||||
import cors from "cors";
|
||||
import {SpotifyTokenGenerator} from "./rest/spotifyTokenGenerator";
|
||||
import {RestAuth} from "./rest/auth";
|
||||
|
||||
const app = express();
|
||||
const port = process.env.PORT || 3000;
|
||||
console.log("server startet");
|
||||
const server = app.listen(port, () => {
|
||||
console.log(`Server is running on port ${port}`);
|
||||
});
|
||||
@@ -26,6 +26,7 @@ app.use(express.json({limit: "15mb"}));
|
||||
const webSocketServer = new ExtendedWebSocketServer(server);
|
||||
const restWebSocket = new RestWebSocket(webSocketServer);
|
||||
const restUser = new RestUser();
|
||||
const auth = new RestAuth();
|
||||
const jwtTokenPropertiesExtractor = new JwtTokenPropertiesExtractor();
|
||||
const spotify = new SpotifyTokenGenerator();
|
||||
|
||||
@@ -36,5 +37,6 @@ app.use(
|
||||
authenticateJwt,
|
||||
jwtTokenPropertiesExtractor.createRouter(),
|
||||
);
|
||||
|
||||
app.use("/api/spotify", authenticateJwt, spotify.createRouter());
|
||||
|
||||
app.use("/api/auth", auth.createRouter());
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
import express from "express";
|
||||
import {UserService} from "../db/services/db/UserService";
|
||||
import {IUser} from "../db/models/user";
|
||||
import {ObjectId} from "mongodb";
|
||||
import {JwtAuthenticator} from "../utils/jwtAuthenticator";
|
||||
import bcrypt from "bcrypt";
|
||||
|
||||
export class RestAuth {
|
||||
public createRouter() {
|
||||
const router = express.Router();
|
||||
|
||||
router.put("/register", async (req, res) => {
|
||||
const username = req.body.username;
|
||||
const timezone = req.body.timezone;
|
||||
const location = req.body.location;
|
||||
const password = req.body.password;
|
||||
const userService = await UserService.create();
|
||||
const user = await userService.getUserByName(username);
|
||||
|
||||
if (user) {
|
||||
res.status(409).send({message: "Username already exists"});
|
||||
} else {
|
||||
const hashedPassword = await bcrypt.hash(password, 10);
|
||||
const newUser: IUser = {
|
||||
name: username,
|
||||
password: hashedPassword,
|
||||
uuid: crypto.randomUUID(),
|
||||
id: ObjectId.createFromTime(Date.now()),
|
||||
config: {
|
||||
isVisible: false,
|
||||
isAdmin: false,
|
||||
canBeModified: false
|
||||
},
|
||||
timezone,
|
||||
location
|
||||
};
|
||||
const result = await userService.createUser(newUser);
|
||||
result.password = undefined;
|
||||
res.status(201).send({success: true, user: result});
|
||||
}
|
||||
});
|
||||
|
||||
router.post("/login", async (req, res) => {
|
||||
const username = req.body.username;
|
||||
const password = req.body.password;
|
||||
const userService = await UserService.create();
|
||||
const user = await userService.getUserByName(username);
|
||||
|
||||
if (!user) {
|
||||
res.status(404).send({success: false, message: "User not found"});
|
||||
return;
|
||||
}
|
||||
|
||||
const isValid = await bcrypt.compare(password, user.password!);
|
||||
|
||||
if (!isValid) {
|
||||
res.status(401).send({success: false, message: "Invalid password"});
|
||||
return;
|
||||
}
|
||||
|
||||
// generate JWT token here
|
||||
const jwtToken = new JwtAuthenticator(
|
||||
process.env.SECRET_KEY!,
|
||||
).generateToken({username: user.name, id: user.id, uuid: user.uuid});
|
||||
|
||||
res.status(200).send({success: true, token: jwtToken});
|
||||
});
|
||||
|
||||
|
||||
return router;
|
||||
}
|
||||
}
|
||||
@@ -17,4 +17,8 @@ export class JwtAuthenticator {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public generateToken(payload: object): string {
|
||||
return jwt.sign(payload, this.secret);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,13 +97,17 @@ export class WebsocketEventHandler {
|
||||
console.log("Checking Spotify")
|
||||
const user = this.webSocket.user;
|
||||
const spotifyConfig = user.spotifyConfig;
|
||||
if (!spotifyConfig) {
|
||||
console.log("No Spotify config found");
|
||||
return;
|
||||
}
|
||||
if (Date.now() > spotifyConfig.expirationDate.getTime()) {
|
||||
console.log("Token expired");
|
||||
|
||||
const token = await new SpotifyTokenService().refreshToken(spotifyConfig.refreshToken);
|
||||
user.spotifyConfig = {
|
||||
// use old refresh token because you don't get a new one
|
||||
refreshToken: user.spotifyConfig.refreshToken,
|
||||
refreshToken: user.spotifyConfig!.refreshToken,
|
||||
accessToken: token.access_token,
|
||||
expirationDate: new Date(Date.now() + token.expires_in * 1000),
|
||||
scope: token.scope,
|
||||
@@ -112,7 +116,7 @@ export class WebsocketEventHandler {
|
||||
await userService.updateUser(user);
|
||||
console.log("Token refreshed and database updated");
|
||||
}
|
||||
const musicData = await getCurrentlyPlaying(user.spotifyConfig.accessToken);
|
||||
const musicData = await getCurrentlyPlaying(user.spotifyConfig!.accessToken);
|
||||
|
||||
this.webSocket.send(JSON.stringify({
|
||||
type: "SPOTIFY_UPDATE",
|
||||
|
||||
Reference in New Issue
Block a user