-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
41 changed files
with
5,269 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,8 @@ | ||
# e-buddy | ||
# React + Vite | ||
|
||
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. | ||
|
||
Currently, two official plugins are available: | ||
|
||
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh | ||
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
const io = require("socket.io")(server); | ||
|
||
io.on("connection", (socket) => { | ||
console.log("User connected: " + socket.id); | ||
|
||
socket.on("send_message", (data) => { | ||
io.to(data.receiverId).emit("receive_message", data); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"_id": "64b9c27f4e", | ||
"senderId": "123", | ||
"receiverId": "456", | ||
"content": "Hello, how are you?", | ||
"timestamp": "2025-01-21T14:30:00Z" | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"_id": "64b9c25d2f", | ||
"username": "john_doe", | ||
"email": "[email protected]", | ||
"password": "$2b$10$hashedPassword" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
id | group_name | member_id | created_at |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
id | sender_id | receiver_id | content | timestamp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
id | username | email password_hash | status |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
mongoose.connect("mongodb+srv://<username>:<password>@cluster0.mongodb.net/ebuddy"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
const express = require("express"); | ||
const bodyParser = require("body-parser"); | ||
const jwt = require("jsonwebtoken"); | ||
const bcrypt = require("bcrypt"); | ||
const mongoose = require("mongoose"); | ||
|
||
const app = express(); | ||
const PORT = 3000; | ||
|
||
// Middleware | ||
app.use(bodyParser.json()); | ||
|
||
// MongoDB Connection | ||
mongoose.connect("mongodb://localhost:27017/ebuddy", { useNewUrlParser: true, useUnifiedTopology: true }); | ||
|
||
// User Schema | ||
const UserSchema = new mongoose.Schema({ | ||
username: String, | ||
email: String, | ||
password: String, | ||
}); | ||
const User = mongoose.model("User", UserSchema); | ||
|
||
// Routes | ||
// Register User | ||
app.post("/api/register", async (req, res) => { | ||
const { username, email, password } = req.body; | ||
const hashedPassword = await bcrypt.hash(password, 10); | ||
const user = new User({ username, email, password: hashedPassword }); | ||
await user.save(); | ||
res.status(201).json({ message: "User registered successfully" }); | ||
}); | ||
|
||
// Login User | ||
app.post("/api/login", async (req, res) => { | ||
const { email, password } = req.body; | ||
const user = await User.findOne({ email }); | ||
if (user && (await bcrypt.compare(password, user.password))) { | ||
const token = jwt.sign({ id: user._id, email: user.email }, "SECRET_KEY", { expiresIn: "1h" }); | ||
res.json({ message: "Login successful", token }); | ||
} else { | ||
res.status(401).json({ message: "Invalid email or password" }); | ||
} | ||
}); | ||
|
||
app.listen(PORT, () => { | ||
console.log(`Server running on http://localhost:${PORT}`); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
io.on("connection", (socket) => { | ||
console.log("User connected: " + socket.id); | ||
|
||
// Bergabung ke grup | ||
socket.on("join_group", (groupId) => { | ||
socket.join(groupId); | ||
console.log(`User ${socket.id} joined group: ${groupId}`); | ||
}); | ||
|
||
// Kirim pesan ke grup | ||
socket.on("send_group_message", (data) => { | ||
const { groupId, senderId, content } = data; | ||
io.to(groupId).emit("receive_group_message", { senderId, content }); | ||
}); | ||
}); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
const http = require("http"); | ||
const socketIo = require("socket.io"); | ||
|
||
// Create HTTP server | ||
const server = http.createServer(app); | ||
|
||
// Setup Socket.IO | ||
const io = socketIo(server); | ||
|
||
io.on("connection", (socket) => { | ||
console.log("User connected: " + socket.id); | ||
|
||
// Event: Send message | ||
socket.on("send_message", (data) => { | ||
console.log("Message received:", data); | ||
// Emit message to specific user | ||
io.to(data.receiverId).emit("receive_message", { | ||
senderId: data.senderId, | ||
content: data.content, | ||
}); | ||
}); | ||
|
||
socket.on("disconnect", () => { | ||
console.log("User disconnected: " + socket.id); | ||
}); | ||
}); | ||
|
||
// Start Server | ||
server.listen(3001, () => { | ||
console.log("Real-time server running on http://localhost:3001"); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
const CryptoJS = require("crypto-js"); | ||
|
||
const encryptMessage = (message, key) => { | ||
return CryptoJS.AES.encrypt(message, key).toString(); | ||
}; | ||
|
||
const decryptMessage = (encryptedMessage, key) => { | ||
const bytes = CryptoJS.AES.decrypt(encryptedMessage, key); | ||
return bytes.toString(CryptoJS.enc.Utf8); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
const express = require("express"); | ||
const router = express.Router(); | ||
const Group = require("./models/Group"); // Model Grup | ||
const User = require("./models/User"); // Model Pengguna | ||
|
||
// Buat grup baru | ||
router.post("/api/groups", async (req, res) => { | ||
const { groupName, members } = req.body; | ||
try { | ||
const group = new Group({ groupName, members }); | ||
await group.save(); | ||
res.status(201).json({ message: "Group created successfully", group }); | ||
} catch (error) { | ||
res.status(500).json({ error: "Failed to create group" }); | ||
} | ||
}); | ||
|
||
// Tambahkan pesan ke grup | ||
router.post("/api/groups/:groupId/messages", async (req, res) => { | ||
const { groupId } = req.params; | ||
const { sender, content } = req.body; | ||
try { | ||
const group = await Group.findById(groupId); | ||
group.messages.push({ sender, content }); | ||
await group.save(); | ||
res.status(200).json({ message: "Message sent", group }); | ||
} catch (error) { | ||
res.status(500).json({ error: "Failed to send message" }); | ||
} | ||
}); | ||
|
||
// Ambil pesan grup | ||
router.get("/api/groups/:groupId/messages", async (req, res) => { | ||
const { groupId } = req.params; | ||
try { | ||
const group = await Group.findById(groupId).populate("messages.sender", "username"); | ||
res.status(200).json({ messages: group.messages }); | ||
} catch (error) { | ||
res.status(500).json({ error: "Failed to fetch messages" }); | ||
} | ||
}); | ||
|
||
module.exports = router; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
const mongoose = require("mongoose"); | ||
|
||
const GroupSchema = new mongoose.Schema({ | ||
groupName: { type: String, required: true }, | ||
members: [{ type: mongoose.Schema.Types.ObjectId, ref: "User" }], // User IDs | ||
messages: [ | ||
{ | ||
sender: { type: mongoose.Schema.Types.ObjectId, ref: "User" }, | ||
content: String, | ||
timestamp: { type: Date, default: Date.now }, | ||
}, | ||
], | ||
}); | ||
|
||
const Group = mongoose.model("Group", GroupSchema); | ||
module.exports = Group; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
router.get("/api/groups/:groupId/messages", async (req, res) => { | ||
const { groupId } = req.params; | ||
const { page = 1, limit = 10 } = req.query; // Default 10 pesan per halaman | ||
try { | ||
const group = await Group.findById(groupId) | ||
.populate("messages.sender", "username") | ||
.skip((page - 1) * limit) | ||
.limit(parseInt(limit)); | ||
res.status(200).json({ messages: group.messages }); | ||
} catch (error) { | ||
res.status(500).json({ error: "Failed to fetch messages" }); | ||
} | ||
}); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
const authenticateToken = (req, res, next) => { | ||
const token = req.header("Authorization"); | ||
if (!token) return res.status(401).json({ error: "Access denied" }); | ||
try { | ||
const verified = jwt.verify(token, process.env.JWT_SECRET); | ||
req.user = verified; | ||
next(); | ||
} catch (error) { | ||
res.status(400).json({ error: "Invalid token" }); | ||
} | ||
}; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
io.on("connection", (socket) => { | ||
console.log("User connected for WebRTC: " + socket.id); | ||
|
||
// Meneruskan pesan signaling | ||
socket.on("signal", (data) => { | ||
const { to, from, signal } = data; | ||
io.to(to).emit("signal", { from, signal }); | ||
}); | ||
|
||
socket.on("join_call", (room) => { | ||
socket.join(room); | ||
socket.broadcast.to(room).emit("user-joined", socket.id); | ||
}); | ||
}); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
const winston = require("winston"); | ||
|
||
const logger = winston.createLogger({ | ||
level: "info", | ||
format: winston.format.json(), | ||
transports: [ | ||
new winston.transports.File({ filename: "error.log", level: "error" }), | ||
new winston.transports.File({ filename: "combined.log" }), | ||
], | ||
}); | ||
|
||
logger.info("This is an informational message"); | ||
logger.error("This is an error message"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
const client = require("prom-client"); | ||
const collectDefaultMetrics = client.collectDefaultMetrics; | ||
|
||
collectDefaultMetrics(); // Metrik default | ||
|
||
app.get("/metrics", async (req, res) => { | ||
res.set("Content-Type", client.register.contentType); | ||
res.end(await client.register.metrics()); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
const mongoose = require("mongoose"); | ||
|
||
mongoose.connect(process.env.MONGO_URI, { | ||
useNewUrlParser: true, | ||
useUnifiedTopology: true, | ||
}).then(() => { | ||
console.log("Connected to MongoDB Atlas"); | ||
}).catch((err) => { | ||
console.error("Database connection error:", err); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
const request = require("supertest"); | ||
const app = require("./app"); // Import aplikasi Express.js | ||
|
||
describe("User Authentication API", () => { | ||
test("Should register a new user", async () => { | ||
const response = await request(app).post("/api/register").send({ | ||
username: "testuser", | ||
email: "[email protected]", | ||
password: "password123", | ||
}); | ||
expect(response.statusCode).toBe(201); | ||
expect(response.body.message).toBe("User registered successfully"); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
describe("Chat Application", () => { | ||
it("Should allow user to send and receive messages", () => { | ||
cy.visit("http://localhost:3000"); | ||
cy.get("input[name='email']").type("[email protected]"); | ||
cy.get("input[name='password']").type("password123"); | ||
cy.get("button[type='submit']").click(); | ||
|
||
cy.get("input[name='message']").type("Hello, World!"); | ||
cy.get("button[type='send']").click(); | ||
|
||
cy.contains("Hello, World!"); | ||
}); | ||
}); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import http from "k6/http"; | ||
import { sleep } from "k6"; | ||
|
||
export default function () { | ||
http.get("http://localhost:3000/api/messages"); | ||
sleep(1); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
const peer = new Peer({ | ||
initiator: true, | ||
trickle: false, | ||
config: { | ||
iceServers: [ | ||
{ urls: "stun:stun.l.google.com:19302" }, // STUN Server | ||
{ urls: "turn:your-turn-server.com:3478", username: "user", credential: "password" }, // TURN Server | ||
], | ||
}, | ||
stream, | ||
}); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import js from '@eslint/js' | ||
import globals from 'globals' | ||
import react from 'eslint-plugin-react' | ||
import reactHooks from 'eslint-plugin-react-hooks' | ||
import reactRefresh from 'eslint-plugin-react-refresh' | ||
|
||
export default [ | ||
{ ignores: ['dist'] }, | ||
{ | ||
files: ['**/*.{js,jsx}'], | ||
languageOptions: { | ||
ecmaVersion: 2020, | ||
globals: globals.browser, | ||
parserOptions: { | ||
ecmaVersion: 'latest', | ||
ecmaFeatures: { jsx: true }, | ||
sourceType: 'module', | ||
}, | ||
}, | ||
settings: { react: { version: '18.3' } }, | ||
plugins: { | ||
react, | ||
'react-hooks': reactHooks, | ||
'react-refresh': reactRefresh, | ||
}, | ||
rules: { | ||
...js.configs.recommended.rules, | ||
...react.configs.recommended.rules, | ||
...react.configs['jsx-runtime'].rules, | ||
...reactHooks.configs.recommended.rules, | ||
'react/jsx-no-target-blank': 'off', | ||
'react-refresh/only-export-components': [ | ||
'warn', | ||
{ allowConstantExport: true }, | ||
], | ||
}, | ||
}, | ||
] |
Oops, something went wrong.