add prettifier

This commit is contained in:
philipredstone
2025-04-15 14:46:06 +02:00
parent c078610c4d
commit eceacf2117
43 changed files with 10946 additions and 6173 deletions

View File

@ -1,42 +1,42 @@
import express, { Application } from 'express';
import cors from 'cors';
import cookieParser from 'cookie-parser';
import dotenv from 'dotenv';
import authRoutes from './routes/auth.routes';
import networkRoutes from './routes/network.routes';
import peopleRoutes from './routes/people.routes';
import relationshipRoutes from './routes/relationship.routes';
import path from "node:path";
dotenv.config();
const app: Application = express();
// Middleware
app.use(express.json());
app.use(cookieParser());
app.use(cors({
origin: process.env.CLIENT_URL || 'http://localhost:3000',
credentials: true
}));
// Routes
app.use('/api/auth', authRoutes);
app.use('/api/networks', networkRoutes);
app.use('/api/networks', peopleRoutes);
app.use('/api/networks', relationshipRoutes);
// Base route
/*app.get('/', (req, res) => {
res.send('Friendship Network API is running');
});*/
app.use(express.static(path.join(__dirname, '../frontend/dist/')));
app.use((req,res,next) => {
res.sendFile(path.join(__dirname, '..', 'frontend/dist/index.html'));
})
export default app;
import express, { Application } from 'express';
import cors from 'cors';
import cookieParser from 'cookie-parser';
import dotenv from 'dotenv';
import authRoutes from './routes/auth.routes';
import networkRoutes from './routes/network.routes';
import peopleRoutes from './routes/people.routes';
import relationshipRoutes from './routes/relationship.routes';
import path from 'node:path';
dotenv.config();
const app: Application = express();
// Middleware
app.use(express.json());
app.use(cookieParser());
app.use(
cors({
origin: process.env.CLIENT_URL || 'http://localhost:3000',
credentials: true,
})
);
// Routes
app.use('/api/auth', authRoutes);
app.use('/api/networks', networkRoutes);
app.use('/api/networks', peopleRoutes);
app.use('/api/networks', relationshipRoutes);
// Base route
/*app.get('/', (req, res) => {
res.send('Friendship Network API is running');
});*/
app.use(express.static(path.join(__dirname, '../frontend/dist/')));
app.use((req, res, next) => {
res.sendFile(path.join(__dirname, '..', 'frontend/dist/index.html'));
});
export default app;

View File

@ -1,18 +1,18 @@
import mongoose from 'mongoose';
import dotenv from 'dotenv';
dotenv.config();
const MONGODB_URI = process.env.MONGODB_URI || 'mongodb://localhost:27017/friendship-network';
const connectDB = async (): Promise<void> => {
try {
await mongoose.connect(MONGODB_URI);
console.log('MongoDB connected successfully');
} catch (error) {
console.error('MongoDB connection error:', error);
process.exit(1);
}
};
export default connectDB;
import mongoose from 'mongoose';
import dotenv from 'dotenv';
dotenv.config();
const MONGODB_URI = process.env.MONGODB_URI || 'mongodb://localhost:27017/friendship-network';
const connectDB = async (): Promise<void> => {
try {
await mongoose.connect(MONGODB_URI);
console.log('MongoDB connected successfully');
} catch (error) {
console.error('MongoDB connection error:', error);
process.exit(1);
}
};
export default connectDB;

View File

@ -1,166 +1,165 @@
import { Request, Response } from 'express';
import jwt from 'jsonwebtoken';
import User, { IUser } from '../models/user.model';
import { UserRequest } from '../types/express';
import { validationResult } from 'express-validator';
// JWT secret from environment variables
const JWT_SECRET = process.env.JWT_SECRET || 'your_jwt_secret_key_change_this';
// Token expiration (1 day)
const TOKEN_EXPIRY = '1d';
// Generate JWT token
const generateToken = (user: IUser): string => {
return jwt.sign({ id: user._id }, JWT_SECRET, {
expiresIn: TOKEN_EXPIRY,
});
};
// Set cookie with JWT token
const setTokenCookie = (res: Response, token: string): void => {
// Cookie options
const options = {
expires: new Date(Date.now() + 24 * 60 * 60 * 1000), // 1 day
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
};
res.cookie('token', token, options);
};
// Register a new user
export const register = async (req: Request, res: Response): Promise<void> => {
try {
// Validate request
const errors = validationResult(req);
if (!errors.isEmpty()) {
res.status(400).json({ errors: errors.array() });
return;
}
if(!process.env.ENABLE_REGISTRATION)
{
res.status(403).json({errors: ["Registration is disabled"]});
return;
}
const { email, password, username } = req.body;
// Check if user already exists
let user = await User.findOne({ email });
if (user) {
res.status(400).json({ message: 'User already exists' });
return;
}
// Create new user
user = new User({
email,
password,
username,
});
// Save user to database
await user.save();
// Generate JWT token
const token = generateToken(user);
// Set token cookie
setTokenCookie(res, token);
// Send response
res.status(201).json({
success: true,
user: {
id: user._id,
email: user.email,
username: user.username,
},
});
} catch (error) {
console.error('Registration error:', error);
res.status(500).json({ message: 'Server error' });
}
};
// Login user
export const login = async (req: Request, res: Response): Promise<void> => {
try {
// Validate request
const errors = validationResult(req);
if (!errors.isEmpty()) {
res.status(400).json({ errors: errors.array() });
return;
}
const { email, password } = req.body;
// Check if user exists
const user = await User.findOne({ email });
if (!user) {
res.status(400).json({ message: 'Invalid credentials' });
return;
}
// Check if password is correct
const isMatch = await user.comparePassword(password);
if (!isMatch) {
res.status(400).json({ message: 'Invalid credentials' });
return;
}
// Generate JWT token
const token = generateToken(user);
// Set token cookie
setTokenCookie(res, token);
// Send response
res.json({
success: true,
user: {
id: user._id,
email: user.email,
username: user.username,
},
});
} catch (error) {
console.error('Login error:', error);
res.status(500).json({ message: 'Server error' });
}
};
// Logout user
export const logout = (req: Request, res: Response): void => {
res.cookie('token', 'none', {
expires: new Date(Date.now() + 10 * 1000), // 10 seconds
httpOnly: true,
});
res.json({ success: true, message: 'Logged out successfully' });
};
// Get current user
export const getCurrentUser = async (req: UserRequest, res: Response): Promise<void> => {
try {
const user = req.user;
if (!user) {
res.status(401).json({ message: 'Not authorized' });
return;
}
res.json({
success: true,
user: {
id: user._id,
email: user.email,
username: user.username,
},
});
} catch (error) {
console.error('Get current user error:', error);
res.status(500).json({ message: 'Server error' });
}
};
import { Request, Response } from 'express';
import jwt from 'jsonwebtoken';
import User, { IUser } from '../models/user.model';
import { UserRequest } from '../types/express';
import { validationResult } from 'express-validator';
// JWT secret from environment variables
const JWT_SECRET = process.env.JWT_SECRET || 'your_jwt_secret_key_change_this';
// Token expiration (1 day)
const TOKEN_EXPIRY = '1d';
// Generate JWT token
const generateToken = (user: IUser): string => {
return jwt.sign({ id: user._id }, JWT_SECRET, {
expiresIn: TOKEN_EXPIRY,
});
};
// Set cookie with JWT token
const setTokenCookie = (res: Response, token: string): void => {
// Cookie options
const options = {
expires: new Date(Date.now() + 24 * 60 * 60 * 1000), // 1 day
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
};
res.cookie('token', token, options);
};
// Register a new user
export const register = async (req: Request, res: Response): Promise<void> => {
try {
// Validate request
const errors = validationResult(req);
if (!errors.isEmpty()) {
res.status(400).json({ errors: errors.array() });
return;
}
if (!process.env.ENABLE_REGISTRATION) {
res.status(403).json({ errors: ['Registration is disabled'] });
return;
}
const { email, password, username } = req.body;
// Check if user already exists
let user = await User.findOne({ email });
if (user) {
res.status(400).json({ message: 'User already exists' });
return;
}
// Create new user
user = new User({
email,
password,
username,
});
// Save user to database
await user.save();
// Generate JWT token
const token = generateToken(user);
// Set token cookie
setTokenCookie(res, token);
// Send response
res.status(201).json({
success: true,
user: {
id: user._id,
email: user.email,
username: user.username,
},
});
} catch (error) {
console.error('Registration error:', error);
res.status(500).json({ message: 'Server error' });
}
};
// Login user
export const login = async (req: Request, res: Response): Promise<void> => {
try {
// Validate request
const errors = validationResult(req);
if (!errors.isEmpty()) {
res.status(400).json({ errors: errors.array() });
return;
}
const { email, password } = req.body;
// Check if user exists
const user = await User.findOne({ email });
if (!user) {
res.status(400).json({ message: 'Invalid credentials' });
return;
}
// Check if password is correct
const isMatch = await user.comparePassword(password);
if (!isMatch) {
res.status(400).json({ message: 'Invalid credentials' });
return;
}
// Generate JWT token
const token = generateToken(user);
// Set token cookie
setTokenCookie(res, token);
// Send response
res.json({
success: true,
user: {
id: user._id,
email: user.email,
username: user.username,
},
});
} catch (error) {
console.error('Login error:', error);
res.status(500).json({ message: 'Server error' });
}
};
// Logout user
export const logout = (req: Request, res: Response): void => {
res.cookie('token', 'none', {
expires: new Date(Date.now() + 10 * 1000), // 10 seconds
httpOnly: true,
});
res.json({ success: true, message: 'Logged out successfully' });
};
// Get current user
export const getCurrentUser = async (req: UserRequest, res: Response): Promise<void> => {
try {
const user = req.user;
if (!user) {
res.status(401).json({ message: 'Not authorized' });
return;
}
res.json({
success: true,
user: {
id: user._id,
email: user.email,
username: user.username,
},
});
} catch (error) {
console.error('Get current user error:', error);
res.status(500).json({ message: 'Server error' });
}
};

View File

@ -1,169 +1,166 @@
import { Response } from 'express';
import Network from '../models/network.model';
import { UserRequest } from '../types/express';
import { validationResult } from 'express-validator';
// Get all networks for current user and all public networks
export const getUserNetworks = async (req: UserRequest, res: Response): Promise<void> => {
try {
if (!req.user) {
res.status(401).json({ message: 'Not authorized' });
return;
}
// Find networks that either:
// 1. Belong to the current user, OR
// 2. Are public networks (created by any user)
const networks = await Network.find({
$or: [
{ owner: req.user._id },
{ isPublic: true }
]
}).populate('owner', 'username _id'); // Populate owner field with username
res.json({ success: true, data: networks });
} catch (error) {
console.error('Get networks error:', error);
res.status(500).json({ message: 'Server error' });
}
};
// Create a new network
export const createNetwork = async (req: UserRequest, res: Response): Promise<void> => {
try {
// Validate request
const errors = validationResult(req);
if (!errors.isEmpty()) {
res.status(400).json({ errors: errors.array() });
return;
}
if (!req.user) {
res.status(401).json({ message: 'Not authorized' });
return;
}
const { name, description, isPublic } = req.body;
const network = new Network({
name,
description,
owner: req.user._id,
isPublic: isPublic || false,
});
await network.save();
res.status(201).json({ success: true, data: network });
} catch (error) {
console.error('Create network error:', error);
res.status(500).json({ message: 'Server error' });
}
};
// Get a specific network
export const getNetwork = async (req: UserRequest, res: Response): Promise<void> => {
try {
const networkId = req.params.id;
if (!req.user) {
res.status(401).json({ message: 'Not authorized' });
return;
}
const network = await Network.findById(networkId).populate('owner', 'username _id');
if (!network) {
res.status(404).json({ message: 'Network not found' });
return;
}
// Check if user is owner or network is public
if (network.owner._id.toString() !== req.user._id.toString() && !network.isPublic) {
res.status(403).json({ message: 'You do not have permission to access this network' });
return;
}
res.json({ success: true, data: network });
} catch (error) {
console.error('Get network error:', error);
res.status(500).json({ message: 'Server error' });
}
};
// Update a network
export const updateNetwork = async (req: UserRequest, res: Response): Promise<void> => {
try {
// Validate request
const errors = validationResult(req);
if (!errors.isEmpty()) {
res.status(400).json({ errors: errors.array() });
return;
}
const networkId = req.params.id;
if (!req.user) {
res.status(401).json({ message: 'Not authorized' });
return;
}
const network = await Network.findById(networkId);
if (!network) {
res.status(404).json({ message: 'Network not found' });
return;
}
// Check if user is owner
if (network.owner.toString() !== req.user._id.toString()) {
res.status(403).json({ message: 'You do not have permission to update this network' });
return;
}
const { name, description, isPublic } = req.body;
network.name = name || network.name;
network.description = description !== undefined ? description : network.description;
network.isPublic = isPublic !== undefined ? isPublic : network.isPublic;
await network.save();
res.json({ success: true, data: network });
} catch (error) {
console.error('Update network error:', error);
res.status(500).json({ message: 'Server error' });
}
};
// Delete a network
export const deleteNetwork = async (req: UserRequest, res: Response): Promise<void> => {
try {
const networkId = req.params.id;
if (!req.user) {
res.status(401).json({ message: 'Not authorized' });
return;
}
const network = await Network.findById(networkId);
if (!network) {
res.status(404).json({ message: 'Network not found' });
return;
}
// Check if user is owner
if (network.owner.toString() !== req.user._id.toString()) {
res.status(403).json({ message: 'You do not have permission to delete this network' });
return;
}
await network.deleteOne(); // Changed from remove() to deleteOne()
res.json({ success: true, message: 'Network deleted successfully' });
} catch (error) {
console.error('Delete network error:', error);
res.status(500).json({ message: 'Server error' });
}
};
import { Response } from 'express';
import Network from '../models/network.model';
import { UserRequest } from '../types/express';
import { validationResult } from 'express-validator';
// Get all networks for current user and all public networks
export const getUserNetworks = async (req: UserRequest, res: Response): Promise<void> => {
try {
if (!req.user) {
res.status(401).json({ message: 'Not authorized' });
return;
}
// Find networks that either:
// 1. Belong to the current user, OR
// 2. Are public networks (created by any user)
const networks = await Network.find({
$or: [{ owner: req.user._id }, { isPublic: true }],
}).populate('owner', 'username _id'); // Populate owner field with username
res.json({ success: true, data: networks });
} catch (error) {
console.error('Get networks error:', error);
res.status(500).json({ message: 'Server error' });
}
};
// Create a new network
export const createNetwork = async (req: UserRequest, res: Response): Promise<void> => {
try {
// Validate request
const errors = validationResult(req);
if (!errors.isEmpty()) {
res.status(400).json({ errors: errors.array() });
return;
}
if (!req.user) {
res.status(401).json({ message: 'Not authorized' });
return;
}
const { name, description, isPublic } = req.body;
const network = new Network({
name,
description,
owner: req.user._id,
isPublic: isPublic || false,
});
await network.save();
res.status(201).json({ success: true, data: network });
} catch (error) {
console.error('Create network error:', error);
res.status(500).json({ message: 'Server error' });
}
};
// Get a specific network
export const getNetwork = async (req: UserRequest, res: Response): Promise<void> => {
try {
const networkId = req.params.id;
if (!req.user) {
res.status(401).json({ message: 'Not authorized' });
return;
}
const network = await Network.findById(networkId).populate('owner', 'username _id');
if (!network) {
res.status(404).json({ message: 'Network not found' });
return;
}
// Check if user is owner or network is public
if (network.owner._id.toString() !== req.user._id.toString() && !network.isPublic) {
res.status(403).json({ message: 'You do not have permission to access this network' });
return;
}
res.json({ success: true, data: network });
} catch (error) {
console.error('Get network error:', error);
res.status(500).json({ message: 'Server error' });
}
};
// Update a network
export const updateNetwork = async (req: UserRequest, res: Response): Promise<void> => {
try {
// Validate request
const errors = validationResult(req);
if (!errors.isEmpty()) {
res.status(400).json({ errors: errors.array() });
return;
}
const networkId = req.params.id;
if (!req.user) {
res.status(401).json({ message: 'Not authorized' });
return;
}
const network = await Network.findById(networkId);
if (!network) {
res.status(404).json({ message: 'Network not found' });
return;
}
// Check if user is owner
if (network.owner.toString() !== req.user._id.toString()) {
res.status(403).json({ message: 'You do not have permission to update this network' });
return;
}
const { name, description, isPublic } = req.body;
network.name = name || network.name;
network.description = description !== undefined ? description : network.description;
network.isPublic = isPublic !== undefined ? isPublic : network.isPublic;
await network.save();
res.json({ success: true, data: network });
} catch (error) {
console.error('Update network error:', error);
res.status(500).json({ message: 'Server error' });
}
};
// Delete a network
export const deleteNetwork = async (req: UserRequest, res: Response): Promise<void> => {
try {
const networkId = req.params.id;
if (!req.user) {
res.status(401).json({ message: 'Not authorized' });
return;
}
const network = await Network.findById(networkId);
if (!network) {
res.status(404).json({ message: 'Network not found' });
return;
}
// Check if user is owner
if (network.owner.toString() !== req.user._id.toString()) {
res.status(403).json({ message: 'You do not have permission to delete this network' });
return;
}
await network.deleteOne(); // Changed from remove() to deleteOne()
res.json({ success: true, message: 'Network deleted successfully' });
} catch (error) {
console.error('Delete network error:', error);
res.status(500).json({ message: 'Server error' });
}
};

View File

@ -1,174 +1,176 @@
import { Response } from 'express';
import Person from '../models/person.model';
import Relationship from '../models/relationship.model';
import { UserRequest } from '../types/express';
import { validationResult } from 'express-validator';
import mongoose from 'mongoose';
// Get all people in a network
export const getPeople = async (req: UserRequest, res: Response): Promise<void> => {
try {
const networkId = req.params.networkId;
if (!req.user || !req.network) {
res.status(401).json({ message: 'Not authorized' });
return;
}
const people = await Person.find({ network: networkId });
res.json({ success: true, data: people });
} catch (error) {
console.error('Get people error:', error);
res.status(500).json({ message: 'Server error' });
}
};
// Add a person to the network
export const addPerson = async (req: UserRequest, res: Response): Promise<void> => {
try {
// Validate request
const errors = validationResult(req);
if (!errors.isEmpty()) {
res.status(400).json({ errors: errors.array() });
return;
}
const networkId = req.params.networkId;
if (!req.user || !req.network) {
res.status(401).json({ message: 'Not authorized' });
return;
}
// Check if user is the owner (only owners can add people)
if (req.network.owner.toString() !== req.user._id.toString()) {
res.status(403).json({ message: 'Only the network owner can add people' });
return;
}
const { firstName, lastName, birthday, position } = req.body;
// Check if person already exists in this network
const existingPerson = await Person.findOne({
firstName,
lastName,
network: networkId,
});
if (existingPerson) {
res.status(400).json({ message: 'This person already exists in the network' });
return;
}
const person = new Person({
firstName,
lastName,
birthday: birthday || undefined,
network: networkId,
position: position || { x: 100 + Math.random() * 500, y: 100 + Math.random() * 400 },
});
await person.save();
res.status(201).json({ success: true, data: person });
} catch (error) {
console.error('Add person error:', error);
res.status(500).json({ message: 'Server error' });
}
};
// Update a person
export const updatePerson = async (req: UserRequest, res: Response): Promise<void> => {
try {
// Validate request
const errors = validationResult(req);
if (!errors.isEmpty()) {
res.status(400).json({ errors: errors.array() });
return;
}
const networkId = req.params.networkId;
const personId = req.params.id;
if (!req.user || !req.network) {
res.status(401).json({ message: 'Not authorized' });
return;
}
// Check if user is the owner (only owners can update people)
if (req.network.owner.toString() !== req.user._id.toString()) {
res.status(403).json({ message: 'Only the network owner can update people' });
return;
}
const person = await Person.findOne({
_id: personId,
network: networkId,
});
if (!person) {
res.status(404).json({ message: 'Person not found' });
return;
}
const { firstName, lastName, birthday, position } = req.body;
// Update person
if (firstName) person.firstName = firstName;
if (lastName) person.lastName = lastName;
if (birthday !== undefined) person.birthday = birthday || undefined;
if (position) person.position = position;
await person.save();
res.json({ success: true, data: person });
} catch (error) {
console.error('Update person error:', error);
res.status(500).json({ message: 'Server error' });
}
};
// Remove a person from the network
export const removePerson = async (req: UserRequest, res: Response): Promise<void> => {
try {
const networkId = req.params.networkId;
const personId = req.params.id;
if (!req.user || !req.network) {
res.status(401).json({ message: 'Not authorized' });
return;
}
// Check if user is the owner (only owners can remove people)
if (req.network.owner.toString() !== req.user._id.toString()) {
res.status(403).json({ message: 'Only the network owner can remove people' });
return;
}
const person = await Person.findOne({
_id: personId,
network: networkId,
});
if (!person) {
res.status(404).json({ message: 'Person not found' });
return;
}
// Remove all relationships involving this person
await Relationship.deleteMany({
network: networkId,
$or: [{ source: personId }, { target: personId }],
});
// Remove the person
await person.deleteOne(); // Changed from remove() to deleteOne()
res.json({ success: true, message: 'Person and associated relationships removed successfully' });
} catch (error) {
console.error('Remove person error:', error);
res.status(500).json({ message: 'Server error' });
}
};
import { Response } from 'express';
import Person from '../models/person.model';
import Relationship from '../models/relationship.model';
import { UserRequest } from '../types/express';
import { validationResult } from 'express-validator';
import mongoose from 'mongoose';
// Get all people in a network
export const getPeople = async (req: UserRequest, res: Response): Promise<void> => {
try {
const networkId = req.params.networkId;
if (!req.user || !req.network) {
res.status(401).json({ message: 'Not authorized' });
return;
}
const people = await Person.find({ network: networkId });
res.json({ success: true, data: people });
} catch (error) {
console.error('Get people error:', error);
res.status(500).json({ message: 'Server error' });
}
};
// Add a person to the network
export const addPerson = async (req: UserRequest, res: Response): Promise<void> => {
try {
// Validate request
const errors = validationResult(req);
if (!errors.isEmpty()) {
res.status(400).json({ errors: errors.array() });
return;
}
const networkId = req.params.networkId;
if (!req.user || !req.network) {
res.status(401).json({ message: 'Not authorized' });
return;
}
// Check if user is the owner (only owners can add people)
if (req.network.owner.toString() !== req.user._id.toString()) {
res.status(403).json({ message: 'Only the network owner can add people' });
return;
}
const { firstName, lastName, birthday, position } = req.body;
// Check if person already exists in this network
const existingPerson = await Person.findOne({
firstName,
lastName,
network: networkId,
});
if (existingPerson) {
res.status(400).json({ message: 'This person already exists in the network' });
return;
}
const person = new Person({
firstName,
lastName,
birthday: birthday || undefined,
network: networkId,
position: position || { x: 100 + Math.random() * 500, y: 100 + Math.random() * 400 },
});
await person.save();
res.status(201).json({ success: true, data: person });
} catch (error) {
console.error('Add person error:', error);
res.status(500).json({ message: 'Server error' });
}
};
// Update a person
export const updatePerson = async (req: UserRequest, res: Response): Promise<void> => {
try {
// Validate request
const errors = validationResult(req);
if (!errors.isEmpty()) {
res.status(400).json({ errors: errors.array() });
return;
}
const networkId = req.params.networkId;
const personId = req.params.id;
if (!req.user || !req.network) {
res.status(401).json({ message: 'Not authorized' });
return;
}
// Check if user is the owner (only owners can update people)
if (req.network.owner.toString() !== req.user._id.toString()) {
res.status(403).json({ message: 'Only the network owner can update people' });
return;
}
const person = await Person.findOne({
_id: personId,
network: networkId,
});
if (!person) {
res.status(404).json({ message: 'Person not found' });
return;
}
const { firstName, lastName, birthday, position } = req.body;
// Update person
if (firstName) person.firstName = firstName;
if (lastName) person.lastName = lastName;
if (birthday !== undefined) person.birthday = birthday || undefined;
if (position) person.position = position;
await person.save();
res.json({ success: true, data: person });
} catch (error) {
console.error('Update person error:', error);
res.status(500).json({ message: 'Server error' });
}
};
// Remove a person from the network
export const removePerson = async (req: UserRequest, res: Response): Promise<void> => {
try {
const networkId = req.params.networkId;
const personId = req.params.id;
if (!req.user || !req.network) {
res.status(401).json({ message: 'Not authorized' });
return;
}
// Check if user is the owner (only owners can remove people)
if (req.network.owner.toString() !== req.user._id.toString()) {
res.status(403).json({ message: 'Only the network owner can remove people' });
return;
}
const person = await Person.findOne({
_id: personId,
network: networkId,
});
if (!person) {
res.status(404).json({ message: 'Person not found' });
return;
}
// Remove all relationships involving this person
await Relationship.deleteMany({
network: networkId,
$or: [{ source: personId }, { target: personId }],
});
// Remove the person
await person.deleteOne(); // Changed from remove() to deleteOne()
res.json({
success: true,
message: 'Person and associated relationships removed successfully',
});
} catch (error) {
console.error('Remove person error:', error);
res.status(500).json({ message: 'Server error' });
}
};

View File

@ -1,180 +1,180 @@
import { Response } from 'express';
import Relationship from '../models/relationship.model';
import Person from '../models/person.model';
import { UserRequest } from '../types/express';
import { validationResult } from 'express-validator';
// Get all relationships in a network
export const getRelationships = async (req: UserRequest, res: Response): Promise<void> => {
try {
const networkId = req.params.networkId;
if (!req.user || !req.network) {
res.status(401).json({ message: 'Not authorized' });
return;
}
const relationships = await Relationship.find({ network: networkId });
res.json({ success: true, data: relationships });
} catch (error) {
console.error('Get relationships error:', error);
res.status(500).json({ message: 'Server error' });
}
};
// Add a relationship to the network
export const addRelationship = async (req: UserRequest, res: Response): Promise<void> => {
try {
// Validate request
const errors = validationResult(req);
if (!errors.isEmpty()) {
res.status(400).json({ errors: errors.array() });
return;
}
const networkId = req.params.networkId;
if (!req.user || !req.network) {
res.status(401).json({ message: 'Not authorized' });
return;
}
// Check if user is the owner (only owners can add relationships)
if (req.network.owner.toString() !== req.user._id.toString()) {
res.status(403).json({ message: 'Only the network owner can add relationships' });
return;
}
const { source, target, type, customType } = req.body;
// Check if source and target exist and belong to the network
const sourcePerson = await Person.findOne({
_id: source,
network: networkId,
});
const targetPerson = await Person.findOne({
_id: target,
network: networkId,
});
if (!sourcePerson || !targetPerson) {
res.status(400).json({ message: 'Source or target person not found in this network' });
return;
}
// Check if relationship already exists
const existingRelationship = await Relationship.findOne({
$or: [
{ source, target, network: networkId },
{ source: target, target: source, network: networkId },
],
});
if (existingRelationship) {
res.status(400).json({ message: 'A relationship already exists between these people' });
return;
}
const relationship = new Relationship({
source,
target,
type,
customType: type === 'custom' ? customType : undefined,
network: networkId,
});
await relationship.save();
res.status(201).json({ success: true, data: relationship });
} catch (error) {
console.error('Add relationship error:', error);
res.status(500).json({ message: 'Server error' });
}
};
// Update a relationship
export const updateRelationship = async (req: UserRequest, res: Response): Promise<void> => {
try {
// Validate request
const errors = validationResult(req);
if (!errors.isEmpty()) {
res.status(400).json({ errors: errors.array() });
return;
}
const networkId = req.params.networkId;
const relationshipId = req.params.id;
if (!req.user || !req.network) {
res.status(401).json({ message: 'Not authorized' });
return;
}
// Check if user is the owner (only owners can update relationships)
if (req.network.owner.toString() !== req.user._id.toString()) {
res.status(403).json({ message: 'Only the network owner can update relationships' });
return;
}
const relationship = await Relationship.findOne({
_id: relationshipId,
network: networkId,
});
if (!relationship) {
res.status(404).json({ message: 'Relationship not found' });
return;
}
const { type, customType } = req.body;
// Update relationship
if (type) relationship.type = type;
if (type === 'custom' && customType) relationship.customType = customType;
await relationship.save();
res.json({ success: true, data: relationship });
} catch (error) {
console.error('Update relationship error:', error);
res.status(500).json({ message: 'Server error' });
}
};
// Remove a relationship
export const removeRelationship = async (req: UserRequest, res: Response): Promise<void> => {
try {
const networkId = req.params.networkId;
const relationshipId = req.params.id;
if (!req.user || !req.network) {
res.status(401).json({ message: 'Not authorized' });
return;
}
// Check if user is the owner (only owners can remove relationships)
if (req.network.owner.toString() !== req.user._id.toString()) {
res.status(403).json({ message: 'Only the network owner can remove relationships' });
return;
}
const relationship = await Relationship.findOne({
_id: relationshipId,
network: networkId,
});
if (!relationship) {
res.status(404).json({ message: 'Relationship not found' });
return;
}
await relationship.deleteOne(); // Changed from remove() to deleteOne()
res.json({ success: true, message: 'Relationship removed successfully' });
} catch (error) {
console.error('Remove relationship error:', error);
res.status(500).json({ message: 'Server error' });
}
};
import { Response } from 'express';
import Relationship from '../models/relationship.model';
import Person from '../models/person.model';
import { UserRequest } from '../types/express';
import { validationResult } from 'express-validator';
// Get all relationships in a network
export const getRelationships = async (req: UserRequest, res: Response): Promise<void> => {
try {
const networkId = req.params.networkId;
if (!req.user || !req.network) {
res.status(401).json({ message: 'Not authorized' });
return;
}
const relationships = await Relationship.find({ network: networkId });
res.json({ success: true, data: relationships });
} catch (error) {
console.error('Get relationships error:', error);
res.status(500).json({ message: 'Server error' });
}
};
// Add a relationship to the network
export const addRelationship = async (req: UserRequest, res: Response): Promise<void> => {
try {
// Validate request
const errors = validationResult(req);
if (!errors.isEmpty()) {
res.status(400).json({ errors: errors.array() });
return;
}
const networkId = req.params.networkId;
if (!req.user || !req.network) {
res.status(401).json({ message: 'Not authorized' });
return;
}
// Check if user is the owner (only owners can add relationships)
if (req.network.owner.toString() !== req.user._id.toString()) {
res.status(403).json({ message: 'Only the network owner can add relationships' });
return;
}
const { source, target, type, customType } = req.body;
// Check if source and target exist and belong to the network
const sourcePerson = await Person.findOne({
_id: source,
network: networkId,
});
const targetPerson = await Person.findOne({
_id: target,
network: networkId,
});
if (!sourcePerson || !targetPerson) {
res.status(400).json({ message: 'Source or target person not found in this network' });
return;
}
// Check if relationship already exists
const existingRelationship = await Relationship.findOne({
$or: [
{ source, target, network: networkId },
{ source: target, target: source, network: networkId },
],
});
if (existingRelationship) {
res.status(400).json({ message: 'A relationship already exists between these people' });
return;
}
const relationship = new Relationship({
source,
target,
type,
customType: type === 'custom' ? customType : undefined,
network: networkId,
});
await relationship.save();
res.status(201).json({ success: true, data: relationship });
} catch (error) {
console.error('Add relationship error:', error);
res.status(500).json({ message: 'Server error' });
}
};
// Update a relationship
export const updateRelationship = async (req: UserRequest, res: Response): Promise<void> => {
try {
// Validate request
const errors = validationResult(req);
if (!errors.isEmpty()) {
res.status(400).json({ errors: errors.array() });
return;
}
const networkId = req.params.networkId;
const relationshipId = req.params.id;
if (!req.user || !req.network) {
res.status(401).json({ message: 'Not authorized' });
return;
}
// Check if user is the owner (only owners can update relationships)
if (req.network.owner.toString() !== req.user._id.toString()) {
res.status(403).json({ message: 'Only the network owner can update relationships' });
return;
}
const relationship = await Relationship.findOne({
_id: relationshipId,
network: networkId,
});
if (!relationship) {
res.status(404).json({ message: 'Relationship not found' });
return;
}
const { type, customType } = req.body;
// Update relationship
if (type) relationship.type = type;
if (type === 'custom' && customType) relationship.customType = customType;
await relationship.save();
res.json({ success: true, data: relationship });
} catch (error) {
console.error('Update relationship error:', error);
res.status(500).json({ message: 'Server error' });
}
};
// Remove a relationship
export const removeRelationship = async (req: UserRequest, res: Response): Promise<void> => {
try {
const networkId = req.params.networkId;
const relationshipId = req.params.id;
if (!req.user || !req.network) {
res.status(401).json({ message: 'Not authorized' });
return;
}
// Check if user is the owner (only owners can remove relationships)
if (req.network.owner.toString() !== req.user._id.toString()) {
res.status(403).json({ message: 'Only the network owner can remove relationships' });
return;
}
const relationship = await Relationship.findOne({
_id: relationshipId,
network: networkId,
});
if (!relationship) {
res.status(404).json({ message: 'Relationship not found' });
return;
}
await relationship.deleteOne(); // Changed from remove() to deleteOne()
res.json({ success: true, message: 'Relationship removed successfully' });
} catch (error) {
console.error('Remove relationship error:', error);
res.status(500).json({ message: 'Server error' });
}
};

View File

@ -1,39 +1,40 @@
import { Request, Response, NextFunction } from 'express';
import jwt from 'jsonwebtoken';
import User from '../models/user.model';
import { UserRequest } from '../types/express';
// JWT secret from environment variables
const JWT_SECRET = process.env.JWT_SECRET || 'your_jwt_secret_key_change_this';
export const auth = async (req: UserRequest, res: Response, next: NextFunction): Promise<void> => {
try {
// Get token from cookie or authorization header
const token = req.cookies.token ||
(req.headers.authorization && req.headers.authorization.startsWith('Bearer')
? req.headers.authorization.split(' ')[1]
: null);
if (!token) {
res.status(401).json({ message: 'No token, authorization denied' });
return;
}
// Verify token
const decoded = jwt.verify(token, JWT_SECRET) as { id: string };
// Find user by id
const user = await User.findById(decoded.id).select('-password');
if (!user) {
res.status(401).json({ message: 'User not found' });
return;
}
// Set user in request object
req.user = user;
next();
} catch (error) {
res.status(401).json({ message: 'Token is not valid' });
}
};
import { Request, Response, NextFunction } from 'express';
import jwt from 'jsonwebtoken';
import User from '../models/user.model';
import { UserRequest } from '../types/express';
// JWT secret from environment variables
const JWT_SECRET = process.env.JWT_SECRET || 'your_jwt_secret_key_change_this';
export const auth = async (req: UserRequest, res: Response, next: NextFunction): Promise<void> => {
try {
// Get token from cookie or authorization header
const token =
req.cookies.token ||
(req.headers.authorization && req.headers.authorization.startsWith('Bearer')
? req.headers.authorization.split(' ')[1]
: null);
if (!token) {
res.status(401).json({ message: 'No token, authorization denied' });
return;
}
// Verify token
const decoded = jwt.verify(token, JWT_SECRET) as { id: string };
// Find user by id
const user = await User.findById(decoded.id).select('-password');
if (!user) {
res.status(401).json({ message: 'User not found' });
return;
}
// Set user in request object
req.user = user;
next();
} catch (error) {
res.status(401).json({ message: 'Token is not valid' });
}
};

View File

@ -1,33 +1,37 @@
import { Response, NextFunction } from 'express';
import Network from '../models/network.model';
import { UserRequest } from '../types/express';
export const checkNetworkAccess = async (req: UserRequest, res: Response, next: NextFunction): Promise<void> => {
try {
const networkId = req.params.networkId;
if (!networkId) {
res.status(400).json({ message: 'Network ID is required' });
return;
}
const network = await Network.findById(networkId);
if (!network) {
res.status(404).json({ message: 'Network not found' });
return;
}
// Check if user is the owner or the network is public
if (network.owner.toString() !== req.user?._id.toString() && !network.isPublic) {
res.status(403).json({ message: 'You do not have permission to access this network' });
return;
}
// Add network to the request
req.network = network;
next();
} catch (error) {
res.status(500).json({ message: 'Server error' });
}
};
import { Response, NextFunction } from 'express';
import Network from '../models/network.model';
import { UserRequest } from '../types/express';
export const checkNetworkAccess = async (
req: UserRequest,
res: Response,
next: NextFunction
): Promise<void> => {
try {
const networkId = req.params.networkId;
if (!networkId) {
res.status(400).json({ message: 'Network ID is required' });
return;
}
const network = await Network.findById(networkId);
if (!network) {
res.status(404).json({ message: 'Network not found' });
return;
}
// Check if user is the owner or the network is public
if (network.owner.toString() !== req.user?._id.toString() && !network.isPublic) {
res.status(403).json({ message: 'You do not have permission to access this network' });
return;
}
// Add network to the request
req.network = network;
next();
} catch (error) {
res.status(500).json({ message: 'Server error' });
}
};

View File

@ -1,36 +1,35 @@
import mongoose, { Document, Schema } from 'mongoose';
export interface INetwork extends Document {
_id: string;
name: string;
description?: string;
owner: mongoose.Types.ObjectId;
isPublic: boolean;
}
const NetworkSchema = new Schema(
{
name: {
type: String,
required: [true, 'Network name is required'],
trim: true,
},
description: {
type: String,
trim: true,
},
owner: {
type: Schema.Types.ObjectId,
ref: 'User',
required: true,
},
isPublic: {
type: Boolean,
default: false,
},
},
{ timestamps: true }
);
export default mongoose.model<INetwork>('Network', NetworkSchema);
import mongoose, { Document, Schema } from 'mongoose';
export interface INetwork extends Document {
_id: string;
name: string;
description?: string;
owner: mongoose.Types.ObjectId;
isPublic: boolean;
}
const NetworkSchema = new Schema(
{
name: {
type: String,
required: [true, 'Network name is required'],
trim: true,
},
description: {
type: String,
trim: true,
},
owner: {
type: Schema.Types.ObjectId,
ref: 'User',
required: true,
},
isPublic: {
type: Boolean,
default: false,
},
},
{ timestamps: true }
);
export default mongoose.model<INetwork>('Network', NetworkSchema);

View File

@ -1,52 +1,52 @@
import mongoose, { Document, Schema } from 'mongoose';
export interface IPerson extends Document {
_id: string;
firstName: string;
lastName: string;
birthday?: Date;
network: mongoose.Types.ObjectId;
position: {
x: number;
y: number;
};
}
const PersonSchema = new Schema(
{
firstName: {
type: String,
required: [true, 'First name is required'],
trim: true,
},
lastName: {
type: String,
required: [true, 'Last name is required'],
trim: true,
},
birthday: {
type: Date,
},
network: {
type: Schema.Types.ObjectId,
ref: 'Network',
required: true,
},
position: {
x: {
type: Number,
default: 0,
},
y: {
type: Number,
default: 0,
},
},
},
{ timestamps: true }
);
// Create compound index to ensure uniqueness within a network
PersonSchema.index({ firstName: 1, lastName: 1, network: 1 }, { unique: true });
export default mongoose.model<IPerson>('Person', PersonSchema);
import mongoose, { Document, Schema } from 'mongoose';
export interface IPerson extends Document {
_id: string;
firstName: string;
lastName: string;
birthday?: Date;
network: mongoose.Types.ObjectId;
position: {
x: number;
y: number;
};
}
const PersonSchema = new Schema(
{
firstName: {
type: String,
required: [true, 'First name is required'],
trim: true,
},
lastName: {
type: String,
required: [true, 'Last name is required'],
trim: true,
},
birthday: {
type: Date,
},
network: {
type: Schema.Types.ObjectId,
ref: 'Network',
required: true,
},
position: {
x: {
type: Number,
default: 0,
},
y: {
type: Number,
default: 0,
},
},
},
{ timestamps: true }
);
// Create compound index to ensure uniqueness within a network
PersonSchema.index({ firstName: 1, lastName: 1, network: 1 }, { unique: true });
export default mongoose.model<IPerson>('Person', PersonSchema);

View File

@ -1,48 +1,45 @@
import mongoose, { Document, Schema } from 'mongoose';
export interface IRelationship extends Document {
_id: string;
source: mongoose.Types.ObjectId;
target: mongoose.Types.ObjectId;
type: string;
customType?: string;
network: mongoose.Types.ObjectId;
}
const RelationshipSchema = new Schema(
{
source: {
type: Schema.Types.ObjectId,
ref: 'Person',
required: true,
},
target: {
type: Schema.Types.ObjectId,
ref: 'Person',
required: true,
},
type: {
type: String,
required: [true, 'Relationship type is required'],
enum: ['freund', 'partner', 'familie', 'arbeitskolleg', 'custom'],
},
customType: {
type: String,
trim: true,
},
network: {
type: Schema.Types.ObjectId,
ref: 'Network',
required: true,
},
},
{ timestamps: true }
);
// Create compound index to ensure unique relationships in a network
RelationshipSchema.index(
{ source: 1, target: 1, network: 1 },
{ unique: true }
);
export default mongoose.model<IRelationship>('Relationship', RelationshipSchema);
import mongoose, { Document, Schema } from 'mongoose';
export interface IRelationship extends Document {
_id: string;
source: mongoose.Types.ObjectId;
target: mongoose.Types.ObjectId;
type: string;
customType?: string;
network: mongoose.Types.ObjectId;
}
const RelationshipSchema = new Schema(
{
source: {
type: Schema.Types.ObjectId,
ref: 'Person',
required: true,
},
target: {
type: Schema.Types.ObjectId,
ref: 'Person',
required: true,
},
type: {
type: String,
required: [true, 'Relationship type is required'],
enum: ['freund', 'partner', 'familie', 'arbeitskolleg', 'custom'],
},
customType: {
type: String,
trim: true,
},
network: {
type: Schema.Types.ObjectId,
ref: 'Network',
required: true,
},
},
{ timestamps: true }
);
// Create compound index to ensure unique relationships in a network
RelationshipSchema.index({ source: 1, target: 1, network: 1 }, { unique: true });
export default mongoose.model<IRelationship>('Relationship', RelationshipSchema);

View File

@ -1,54 +1,54 @@
import mongoose, { Document, Schema } from 'mongoose';
import bcrypt from 'bcryptjs';
export interface IUser extends Document {
_id: string;
email: string;
password: string;
username: string;
comparePassword(candidatePassword: string): Promise<boolean>;
}
const UserSchema = new Schema(
{
email: {
type: String,
required: [true, 'Email is required'],
unique: true,
trim: true,
lowercase: true,
},
password: {
type: String,
required: [true, 'Password is required'],
minlength: 6,
},
username: {
type: String,
required: [true, 'Username is required'],
trim: true,
},
},
{ timestamps: true }
);
// Hash password before saving
UserSchema.pre('save', async function(next) {
const user = this;
if (!user.isModified('password')) return next();
try {
const salt = await bcrypt.genSalt(10);
user.password = await bcrypt.hash(user.password, salt);
next();
} catch (error: any) {
next(error);
}
});
// Compare password method
UserSchema.methods.comparePassword = async function(candidatePassword: string): Promise<boolean> {
return bcrypt.compare(candidatePassword, this.password);
};
export default mongoose.model<IUser>('User', UserSchema);
import mongoose, { Document, Schema } from 'mongoose';
import bcrypt from 'bcryptjs';
export interface IUser extends Document {
_id: string;
email: string;
password: string;
username: string;
comparePassword(candidatePassword: string): Promise<boolean>;
}
const UserSchema = new Schema(
{
email: {
type: String,
required: [true, 'Email is required'],
unique: true,
trim: true,
lowercase: true,
},
password: {
type: String,
required: [true, 'Password is required'],
minlength: 6,
},
username: {
type: String,
required: [true, 'Username is required'],
trim: true,
},
},
{ timestamps: true }
);
// Hash password before saving
UserSchema.pre('save', async function (next) {
const user = this;
if (!user.isModified('password')) return next();
try {
const salt = await bcrypt.genSalt(10);
user.password = await bcrypt.hash(user.password, salt);
next();
} catch (error: any) {
next(error);
}
});
// Compare password method
UserSchema.methods.comparePassword = async function (candidatePassword: string): Promise<boolean> {
return bcrypt.compare(candidatePassword, this.password);
};
export default mongoose.model<IUser>('User', UserSchema);

View File

@ -1,43 +1,43 @@
import express from 'express';
import { check } from 'express-validator';
import * as authController from '../controllers/auth.controller';
import { auth } from '../middleware/auth.middleware';
const router = express.Router();
// @route POST /api/auth/register
// @desc Register a new user
// @access Public
router.post(
'/register',
[
check('email', 'Please include a valid email').isEmail(),
check('password', 'Password must be at least 6 characters').isLength({ min: 6 }),
check('username', 'Username is required').not().isEmpty(),
],
authController.register
);
// @route POST /api/auth/login
// @desc Login user
// @access Public
router.post(
'/login',
[
check('email', 'Please include a valid email').isEmail(),
check('password', 'Password is required').exists(),
],
authController.login
);
// @route POST /api/auth/logout
// @desc Logout user
// @access Private
router.post('/logout', authController.logout);
// @route GET /api/auth/me
// @desc Get current user
// @access Private
router.get('/me', auth, authController.getCurrentUser);
export default router;
import express from 'express';
import { check } from 'express-validator';
import * as authController from '../controllers/auth.controller';
import { auth } from '../middleware/auth.middleware';
const router = express.Router();
// @route POST /api/auth/register
// @desc Register a new user
// @access Public
router.post(
'/register',
[
check('email', 'Please include a valid email').isEmail(),
check('password', 'Password must be at least 6 characters').isLength({ min: 6 }),
check('username', 'Username is required').not().isEmpty(),
],
authController.register
);
// @route POST /api/auth/login
// @desc Login user
// @access Public
router.post(
'/login',
[
check('email', 'Please include a valid email').isEmail(),
check('password', 'Password is required').exists(),
],
authController.login
);
// @route POST /api/auth/logout
// @desc Logout user
// @access Private
router.post('/logout', authController.logout);
// @route GET /api/auth/me
// @desc Get current user
// @access Private
router.get('/me', auth, authController.getCurrentUser);
export default router;

View File

@ -1,48 +1,44 @@
import express from 'express';
import { check } from 'express-validator';
import * as networkController from '../controllers/network.controller';
import { auth } from '../middleware/auth.middleware';
const router = express.Router();
// All routes require authentication
router.use(auth);
// @route GET /api/networks
// @desc Get all networks for current user
// @access Private
router.get('/', networkController.getUserNetworks);
// @route POST /api/networks
// @desc Create a new network
// @access Private
router.post(
'/',
[
check('name', 'Network name is required').not().isEmpty(),
],
networkController.createNetwork
);
// @route GET /api/networks/:id
// @desc Get a specific network
// @access Private
router.get('/:id', networkController.getNetwork);
// @route PUT /api/networks/:id
// @desc Update a network
// @access Private
router.put(
'/:id',
[
check('name', 'Network name is required if provided').optional().not().isEmpty(),
],
networkController.updateNetwork
);
// @route DELETE /api/networks/:id
// @desc Delete a network
// @access Private
router.delete('/:id', networkController.deleteNetwork);
export default router;
import express from 'express';
import { check } from 'express-validator';
import * as networkController from '../controllers/network.controller';
import { auth } from '../middleware/auth.middleware';
const router = express.Router();
// All routes require authentication
router.use(auth);
// @route GET /api/networks
// @desc Get all networks for current user
// @access Private
router.get('/', networkController.getUserNetworks);
// @route POST /api/networks
// @desc Create a new network
// @access Private
router.post(
'/',
[check('name', 'Network name is required').not().isEmpty()],
networkController.createNetwork
);
// @route GET /api/networks/:id
// @desc Get a specific network
// @access Private
router.get('/:id', networkController.getNetwork);
// @route PUT /api/networks/:id
// @desc Update a network
// @access Private
router.put(
'/:id',
[check('name', 'Network name is required if provided').optional().not().isEmpty()],
networkController.updateNetwork
);
// @route DELETE /api/networks/:id
// @desc Delete a network
// @access Private
router.delete('/:id', networkController.deleteNetwork);
export default router;

View File

@ -1,48 +1,48 @@
import express from 'express';
import { check } from 'express-validator';
import * as peopleController from '../controllers/people.controller';
import { auth } from '../middleware/auth.middleware';
import { checkNetworkAccess } from '../middleware/network-access.middleware';
const router = express.Router();
// All routes require authentication and network access check
router.use('/:networkId/people', auth, checkNetworkAccess);
// @route GET /api/networks/:networkId/people
// @desc Get all people in a network
// @access Private
router.get('/:networkId/people', peopleController.getPeople);
// @route POST /api/networks/:networkId/people
// @desc Add a person to the network
// @access Private
router.post(
'/:networkId/people',
[
check('firstName', 'First name is required').not().isEmpty(),
check('lastName', 'Last name is required').not().isEmpty(),
check('birthday', 'Birthday must be a valid date if provided').optional().isISO8601().toDate(),
],
peopleController.addPerson
);
// @route PUT /api/networks/:networkId/people/:id
// @desc Update a person
// @access Private
router.put(
'/:networkId/people/:id',
[
check('firstName', 'First name must not be empty if provided').optional().not().isEmpty(),
check('lastName', 'Last name must not be empty if provided').optional().not().isEmpty(),
check('birthday', 'Birthday must be a valid date if provided').optional().isISO8601().toDate(),
],
peopleController.updatePerson
);
// @route DELETE /api/networks/:networkId/people/:id
// @desc Remove a person from the network
// @access Private
router.delete('/:networkId/people/:id', peopleController.removePerson);
export default router;
import express from 'express';
import { check } from 'express-validator';
import * as peopleController from '../controllers/people.controller';
import { auth } from '../middleware/auth.middleware';
import { checkNetworkAccess } from '../middleware/network-access.middleware';
const router = express.Router();
// All routes require authentication and network access check
router.use('/:networkId/people', auth, checkNetworkAccess);
// @route GET /api/networks/:networkId/people
// @desc Get all people in a network
// @access Private
router.get('/:networkId/people', peopleController.getPeople);
// @route POST /api/networks/:networkId/people
// @desc Add a person to the network
// @access Private
router.post(
'/:networkId/people',
[
check('firstName', 'First name is required').not().isEmpty(),
check('lastName', 'Last name is required').not().isEmpty(),
check('birthday', 'Birthday must be a valid date if provided').optional().isISO8601().toDate(),
],
peopleController.addPerson
);
// @route PUT /api/networks/:networkId/people/:id
// @desc Update a person
// @access Private
router.put(
'/:networkId/people/:id',
[
check('firstName', 'First name must not be empty if provided').optional().not().isEmpty(),
check('lastName', 'Last name must not be empty if provided').optional().not().isEmpty(),
check('birthday', 'Birthday must be a valid date if provided').optional().isISO8601().toDate(),
],
peopleController.updatePerson
);
// @route DELETE /api/networks/:networkId/people/:id
// @desc Remove a person from the network
// @access Private
router.delete('/:networkId/people/:id', peopleController.removePerson);
export default router;

View File

@ -1,56 +1,62 @@
import express from 'express';
import { check } from 'express-validator';
import * as relationshipController from '../controllers/relationship.controller';
import { auth } from '../middleware/auth.middleware';
import { checkNetworkAccess } from '../middleware/network-access.middleware';
const router = express.Router();
// All routes require authentication and network access check
router.use('/:networkId/relationships', auth, checkNetworkAccess);
// @route GET /api/networks/:networkId/relationships
// @desc Get all relationships in a network
// @access Private
router.get('/:networkId/relationships', relationshipController.getRelationships);
// @route POST /api/networks/:networkId/relationships
// @desc Add a relationship to the network
// @access Private
router.post(
'/:networkId/relationships',
[
check('source', 'Source person ID is required').not().isEmpty().isMongoId(),
check('target', 'Target person ID is required').not().isEmpty().isMongoId(),
check('type', 'Relationship type is required').isIn(['freund', 'partner', 'familie', 'arbeitskolleg', 'custom']),
check('customType', 'Custom type is required when type is custom')
.if(check('type').equals('custom'))
.not()
.isEmpty(),
],
relationshipController.addRelationship
);
// @route PUT /api/networks/:networkId/relationships/:id
// @desc Update a relationship
// @access Private
router.put(
'/:networkId/relationships/:id',
[
check('type', 'Relationship type must be valid if provided')
.optional()
.isIn(['freund', 'partner', 'familie', 'arbeitskolleg', 'custom']),
check('customType', 'Custom type is required when type is custom')
.if(check('type').equals('custom'))
.not()
.isEmpty(),
],
relationshipController.updateRelationship
);
// @route DELETE /api/networks/:networkId/relationships/:id
// @desc Remove a relationship
// @access Private
router.delete('/:networkId/relationships/:id', relationshipController.removeRelationship);
export default router;
import express from 'express';
import { check } from 'express-validator';
import * as relationshipController from '../controllers/relationship.controller';
import { auth } from '../middleware/auth.middleware';
import { checkNetworkAccess } from '../middleware/network-access.middleware';
const router = express.Router();
// All routes require authentication and network access check
router.use('/:networkId/relationships', auth, checkNetworkAccess);
// @route GET /api/networks/:networkId/relationships
// @desc Get all relationships in a network
// @access Private
router.get('/:networkId/relationships', relationshipController.getRelationships);
// @route POST /api/networks/:networkId/relationships
// @desc Add a relationship to the network
// @access Private
router.post(
'/:networkId/relationships',
[
check('source', 'Source person ID is required').not().isEmpty().isMongoId(),
check('target', 'Target person ID is required').not().isEmpty().isMongoId(),
check('type', 'Relationship type is required').isIn([
'freund',
'partner',
'familie',
'arbeitskolleg',
'custom',
]),
check('customType', 'Custom type is required when type is custom')
.if(check('type').equals('custom'))
.not()
.isEmpty(),
],
relationshipController.addRelationship
);
// @route PUT /api/networks/:networkId/relationships/:id
// @desc Update a relationship
// @access Private
router.put(
'/:networkId/relationships/:id',
[
check('type', 'Relationship type must be valid if provided')
.optional()
.isIn(['freund', 'partner', 'familie', 'arbeitskolleg', 'custom']),
check('customType', 'Custom type is required when type is custom')
.if(check('type').equals('custom'))
.not()
.isEmpty(),
],
relationshipController.updateRelationship
);
// @route DELETE /api/networks/:networkId/relationships/:id
// @desc Remove a relationship
// @access Private
router.delete('/:networkId/relationships/:id', relationshipController.removeRelationship);
export default router;

View File

@ -1,15 +1,15 @@
import app from './app';
import connectDB from './config/db';
import dotenv from 'dotenv';
dotenv.config();
const PORT = process.env.PORT || 5000;
// Connect to MongoDB
connectDB();
// Start server
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
import app from './app';
import connectDB from './config/db';
import dotenv from 'dotenv';
dotenv.config();
const PORT = process.env.PORT || 5000;
// Connect to MongoDB
connectDB();
// Start server
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});

View File

@ -1,9 +1,9 @@
import { Request } from 'express';
import { IUser } from '../models/user.model';
import { INetwork } from '../models/network.model';
import { Document } from 'mongoose';
export interface UserRequest extends Request {
user?: IUser;
network?: INetwork;
}
import { Request } from 'express';
import { IUser } from '../models/user.model';
import { INetwork } from '../models/network.model';
import { Document } from 'mongoose';
export interface UserRequest extends Request {
user?: IUser;
network?: INetwork;
}