Skip to content

Commit

Permalink
COMMENT ON THE CODE (#10)
Browse files Browse the repository at this point in the history
  • Loading branch information
covenantebube authored Feb 1, 2025
1 parent 2095750 commit f48c2f8
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 17 deletions.
30 changes: 22 additions & 8 deletions controllers/auth.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,44 +6,54 @@ class AuthController {
this.authService = new AuthService();
}

// Asynchronous function to check if a wallet address exists
async checkWallet(req, res) {
try {
// Extract the `walletAddress` from the request parameters
const { walletAddress } = req.params;
// Check if the wallet address exists using the `authService.walletExists` method
const exists = await this.authService.walletExists(walletAddress);
res.json({ exists });
} catch (error) {
// If an error occurs, handle it using the `handleError` method
this.handleError(res, error);
}
}

// Asynchronous function to handle user registration (signup)
async signup(req, res) {
try {
// Validate the registration data from the request body
const { error } = validateRegistration(req.body);
// If there's a validation error, return a 400 Bad Request response with the error message
if (error) return res.status(400).json({ error: error.details[0].message });

const { user, token } = await this.authService.register(req.body);

// If registration is successful, return a 201 Created response with the user details and token
res.status(201).json({
success: true,
success: true, // Indicates the registration was successful
user: {
id: user.id,
role: user.role,
walletAddress: user.walletAddress
id: user.id, // Include the user's ID
role: user.role, // Include the user's role
walletAddress: user.walletAddress // Include the user's wallet address
},
token
});
} catch (error) {
// handles error during the process
this.handleError(res, error);
}
}

async signin(req, res) {
try {
// Extract the wallet address from the request body and validate it
const { walletAddress } = req.body;
if (!walletAddress) return res.status(400).json({ error: 'Wallet address required' });

const { user, token } = await this.authService.login(walletAddress);

// Authenticate the user using the wallet address and retrieve the user details and token
const { user, token } = await this.authService.login(walletAddress);
// Respond with the authenticated user's details and generated token
res.json({
success: true,
user: {
Expand All @@ -54,15 +64,19 @@ class AuthController {
token
});
} catch (error) {
// Handle any errors that occur during the sign-in process
this.handleError(res, error);
}
}

handleError(res, error) {
// Log the error details for debugging purposes
console.error('Auth Error:', error);
// Determine the appropriate HTTP status code based on the error message
const statusCode = error.message.includes('not found') ? 404 :
error.message.includes('conflict') ? 409 : 400;
res.status(statusCode).json({
// Send a JSON response with the error message and appropriate status code
res.status(statusCode).json({
success: false,
error: error.message
});
Expand Down
19 changes: 19 additions & 0 deletions controllers/job.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,61 +7,80 @@ class JobController {

async create(req, res) {
try {
// Call the job service to create a new job using request body and uploaded file
const job = await this.jobService.create(req.body, req.file);
// Respond with the created job data and a 201 status for successful creation
res.status(201).json(job);
} catch (error) {
// Handle errors and return a 400 status with the error message
res.status(400).json({ error: error.message });
}
}

async findAll(req, res) {
try {
// Retrieve all job records from the job service
const jobs = await this.jobService.findAll();
// Send the retrieved jobs as a JSON response
res.json(jobs);
} catch (error) {
// Handle any errors and respond with a 500 status code
res.status(500).json({ error: error.message });
}
}

async findById(req, res) {
try {
// Retrieve the job by its ID from the jobService
const job = await this.jobService.findById(req.params.id);
// If no job is found, return a 404 Not Found response
if (!job) {
return res.status(404).json({ error: "Job not found" });
}
// Send the found job as a JSON response
res.json(job);
} catch (error) {
// Handle any server errors and return a 500 Internal Server
res.status(500).json({ error: error.message });
}
}

async update(req, res) {
try {
// Call the job service to update the job using the provided ID, request body, and optional file
const job = await this.jobService.update(
req.params.id,
req.body,
req.file
);
// Respond with the updated job details
res.json(job);
} catch (error) {
// Handle errors and return a 400 status with the error message
res.status(400).json({ error: error.message });
}
}

async delete(req, res) {
try {
// Call the job service to delete the job using the provided ID
await this.jobService.delete(req.params.id);
// Respond with a 204 status to indicate successful deletion with no content
res.status(204).send();
} catch (error) {
// Handle errors and return a 400 status with the error message
res.status(500).json({ error: error.message });
}
}

async deleteBanner(req, res) {
try {
// Call the job service to delete the banner using the provided job ID
const job = await this.jobService.deleteBanner(req.params.id);
// Respond with the result of the deletion operation
res.json(job);
} catch (error) {
// Handle any errors and return a 400 status with the error message
res.status(400).json({ error: error.message });
}
}
Expand Down
11 changes: 7 additions & 4 deletions routes/jobRoutes.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@ const storage = multer.diskStorage({
});

const upload = multer({
storage: storage,
storage: storage, // Configure the storage destination and filename for uploaded files
limits: {
fileSize: 5 * 1024 * 1024 // 5MB limit
},
fileFilter: (req, file, cb) => {
// Allow only image files by checking the MIME type
if (file.mimetype.startsWith("image/")) {
cb(null, true);
} else {
Expand All @@ -39,18 +40,20 @@ router.post(
upload.single("banner"),
(req, res) => JobController.create(req, res)
);

// Route to get all job listings
router.get("/", (req, res) => JobController.findAll(req, res));
// Route to get a specific job by its ID
router.get("/:id", (req, res) => JobController.findById(req, res));

// Route to update a job, including uploading a banner image
router.put(
"/:id",
upload.single("banner"),
(req, res) => JobController.update(req, res)
);

// Route to delete a specific job by its ID
router.delete("/:id", (req, res) => JobController.delete(req, res));

// Route to delete only the banner image of a specific job
router.delete("/:id/banner", (req, res) =>
JobController.deleteBanner(req, res)
);
Expand Down
3 changes: 3 additions & 0 deletions server.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,14 @@ AppDataSource.initialize()
res.status(500).json({ error: 'Internal server error' });
});

// Start the server and listen on the specified port
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
})
// Catch and handle database connection erro
.catch((error) => {
console.error('Database connection failed:', error);
// Exit the process with a failure status code
process.exit(1);
});
28 changes: 27 additions & 1 deletion services/auth.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,17 @@ class AuthService {
}

async walletExists(walletAddress) {
// Query the database to check if a user with the given wallet address exists
const user = await this.userRepository.findOne({
where: { walletAddress },
select: ['id']
});
// Return true if the user exists, otherwise return false
return !!user;
}

async checkExistingUser(walletAddress, email) {
// Query the database to find a user with the given wallet address or email
const existingUser = await this.userRepository.findOne({
where: [
{ walletAddress },
Expand All @@ -25,28 +28,45 @@ class AuthService {

if (existingUser) {
const conflicts = [];
// Check if the wallet address already exists and add it to conflicts
if (existingUser.walletAddress === walletAddress) conflicts.push('wallet');

// Check if the email already exists and add it to conflicts
if (existingUser.email === email) conflicts.push('email');

// Return the list of conflicts if any exist
return conflicts;
}
// Return null if no conflicts are found
return null;
}

async createUser(userData) {
// Create a new user instance using the provided user data
const user = this.userRepository.create(userData);

// Save the newly created user to the database
await this.userRepository.save(user);

// Return the saved user object
return user;
}

generateToken(user) {
// Generate a JWT token containing the user's ID and wallet address
return sign(
{ userId: user.id, walletAddress: user.walletAddress },

// Use the secret key from environment variables to sign the token
process.env.JWT_SECRET,

// Set the token expiration time to 24 hours
{ expiresIn: '24h' }
);
}

async register(userData) {
// Check if a user with the same wallet address or email already exists
const conflicts = await this.checkExistingUser(
userData.walletAddress,
userData.email
Expand All @@ -57,22 +77,28 @@ class AuthService {
}

const user = await this.createUser(userData);
// Generate an authentication token for the newly created user
const token = this.generateToken(user);

// Return the sanitized user object (excluding sensitive fields) along with the generated authentication token.
return {
user: this.sanitizeUser(user),
token
};
}

async login(walletAddress) {
// Find a user in the database by their wallet address
const user = await this.userRepository.findOne({ where: { walletAddress } });

// Throw an error if no user is found with the provided wallet address
if (!user) {
throw new Error('User not found');
}

// Generate a token for the authenticated user
const token = this.generateToken(user);

// Return the sanitized user data (e.g., excluding sensitive fields) and the generated token
return {
user: this.sanitizeUser(user),
token
Expand Down
19 changes: 15 additions & 4 deletions services/jobServices.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@ class JobService {
}

async create(jobData, banner) {
// Validate the job data against the JobValidation schema
const { error } = JobValidation.validate(jobData);
if (error) {
// Throw an error if validation fails
throw new Error(`Validation Error: ${error.details[0].message}`);
}

// Check if a job with the same title and company already exists in the repository
const existingJob = await this.jobRepository.findOne({
where: {
title: jobData.title,
Expand All @@ -25,35 +28,40 @@ class JobService {
throw new Error("Job with this title and company already exists");
}

// If a banner is provided, upload it using the UploadService and store the URL and public ID
if (banner) {
const uploadResult = await UploadService.uploadFile(banner);
jobData.banner = uploadResult.url;
jobData.bannerPublicId = uploadResult.publicId;
}

// Create a new job entity and save it to the repository
const job = this.jobRepository.create(jobData);
return await this.jobRepository.save(job);
}

// This method asynchronously retrieves all job records from the job repository.
async findAll() {
return await this.jobRepository.find();
}

// This method asynchronously retrieves a job record by its unique ID from the job repository.
async findById(id) {
return await this.jobRepository.findOne({ where: { id } });
}

// This method asynchronously updates an existing job record by its ID with new data and a banner (if provided).
async update(id, jobData, banner) {
const { error } = JobValidation.validate(jobData);
if (error) {
throw new Error(`Validation Error: ${error.details[0].message}`);
}

// Check if the job exists; if not, throw an error
const existingJob = await this.findById(id);
if (!existingJob) {
throw new Error("Job not found");
}

// If a new banner is provided, delete the old one and upload the new banner
if (banner) {
// Delete old banner if exists
if (existingJob.bannerPublicId) {
Expand Down Expand Up @@ -85,22 +93,25 @@ class JobService {
}

async deleteBanner(id) {
// Retrieve the job record by ID
const job = await this.findById(id);
if (!job) {
throw new Error("Job not found");
}

// Check if the job has a banner before attempting to delete
if (!job.bannerPublicId) {
throw new Error("No banner exists for this job");
}

// Delete the banner file from the storage service
await UploadService.deleteFile(job.bannerPublicId);

// Update the job record to remove banner details
await this.jobRepository.update(id, {
banner: null,
bannerPublicId: null
});

// Return the updated job record
return this.findById(id);
}
}
Expand Down
Loading

0 comments on commit f48c2f8

Please sign in to comment.