Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hw06 email #5486

Open
wants to merge 37 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
f8cea9d
first commit
zetdou Aug 12, 2024
2e2a716
contacts.js
zetdou Aug 12, 2024
c5dd792
contacts.js
zetdou Aug 13, 2024
e8d960b
contacts.js
zetdou Aug 13, 2024
65fc903
Merge pull request #1 from zetdou/hw02-express
zetdou Aug 13, 2024
e1d2990
Final commit
zetdou Aug 13, 2024
06e2f4d
Merge pull request #2 from zetdou/hw02-express
zetdou Aug 13, 2024
38b0c14
Fix routes
zetdou Aug 13, 2024
a649d63
Merge pull request #3 from zetdou/hw02-express
zetdou Aug 13, 2024
d9ea879
Routes and global middleware
zetdou Aug 25, 2024
ffc43eb
Merge pull request #4 from zetdou/hw02-express
zetdou Aug 25, 2024
725999f
Split code
zetdou Aug 25, 2024
dd533c4
Merge pull request #5 from zetdou/hw02-express
zetdou Aug 25, 2024
b11e704
server.js
zetdou Aug 26, 2024
923ec92
Merge pull request #6 from zetdou/hw03-mongodb
zetdou Aug 26, 2024
61bffd2
update server.js
zetdou Aug 26, 2024
f1975ba
Merge pull request #7 from zetdou/hw03-mongodb
zetdou Aug 26, 2024
e2bf876
contactSchema.js
zetdou Aug 26, 2024
1f595f4
Merge pull request #8 from zetdou/hw03-mongodb
zetdou Aug 26, 2024
fda5350
contactController.js
zetdou Aug 27, 2024
ec82401
Merge pull request #9 from zetdou/hw03-mongodb
zetdou Aug 27, 2024
0ae5161
Update contactController.js
zetdou Aug 29, 2024
c493fc1
Merge pull request #10 from zetdou/hw03-mongodb
zetdou Aug 29, 2024
06c5b97
contactController.js
zetdou Aug 30, 2024
3a25685
Merge pull request #11 from zetdou/hw03-mongodb
zetdou Aug 30, 2024
d73573d
userSchema.js
zetdou Aug 31, 2024
f1c59c4
Merge pull request #12 from zetdou/hw04-auth
zetdou Aug 31, 2024
8b9097a
auth.js
zetdou Sep 2, 2024
2885b76
Merge pull request #13 from zetdou/hw04-auth
zetdou Sep 2, 2024
4c5f5c5
authController, authService
zetdou Sep 5, 2024
693a3a3
Merge pull request #14 from zetdou/hw04-auth
zetdou Sep 5, 2024
cc74fc2
app.js
zetdou Sep 13, 2024
a1fa462
Merge pull request #15 from zetdou/hw05-avatars
zetdou Sep 13, 2024
e374004
formatting code
zetdou Sep 13, 2024
940d02d
Merge pull request #16 from zetdou/hw05-avatars
zetdou Sep 13, 2024
770e7f1
emailService.js
zetdou Sep 15, 2024
dec5dc7
authController and Service
zetdou Sep 15, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
4 changes: 2 additions & 2 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ module.exports = {
es2021: true,
node: true,
},
extends: ['standard', 'prettier'],
extends: ["standard", "prettier"],
parserOptions: {
ecmaVersion: 12,
},
rules: {},
}
};
41 changes: 25 additions & 16 deletions app.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,34 @@
const express = require('express')
const logger = require('morgan')
const cors = require('cors')
const express = require("express");
const logger = require("morgan");
const cors = require("cors");
const { jwtStrategy } = require("./config/jwt");
const { errorMiddleware } = require("./middleware/errorMiddleware");
const path = require("path");

const contactsRouter = require('./routes/api/contacts')
const contactsRouter = require("./routes/api/contacts");
const authRouter = require("./routes/api/auth");

const app = express()
const app = express();

const formatsLogger = app.get('env') === 'development' ? 'dev' : 'short'
const formatsLogger = app.get("env") === "development" ? "dev" : "short";

app.use(logger(formatsLogger))
app.use(cors())
app.use(express.json())
app.use(logger(formatsLogger));
app.use(cors());
app.use(express.json());

app.use('/api/contacts', contactsRouter)
jwtStrategy();

app.use(express.static(path.join(__dirname, "public")));

app.use("/api/contacts", contactsRouter);
app.use("/api/users", authRouter);

app.use((req, res) => {
res.status(404).json({ message: 'Not found' })
})
res.status(404).json({
message: `Not found - ${req.path}`,
});
});

app.use((err, req, res, next) => {
res.status(500).json({ message: err.message })
})
app.use(errorMiddleware);

module.exports = app
module.exports = app;
31 changes: 31 additions & 0 deletions config/jwt.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
const passport = require("passport");
const { ExtractJwt, Strategy } = require("passport-jwt");
const User = require("../services/schemas/userSchema");

const jwtStrategy = () => {
const secret = process.env.SECRET;

const params = {
secretOrKey: secret,
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
};

passport.use(
new Strategy(params, async function (payload, done) {
try {
const user = await User.findOne({ _id: payload.id }).lean();

if (!user) {
return done(new Error("User not found!"));
}
return done(null, user);
} catch (err) {
return done(err);
}
}),
);
};

module.exports = {
jwtStrategy,
};
109 changes: 109 additions & 0 deletions controllers/authController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
const gravatar = require("gravatar");
const {
registerUser,
loginUser,
logoutUser,
verifyUser,
resendVerificationEmail,
} = require("../services/authService");
const User = require("../services/schemas/userSchema");

const signup = async (req, res, next) => {
const { username, email, password } = req.body;
try {
const avatarURL = gravatar.url(email, { s: "200", d: "retro" }, true);
const newUser = await registerUser({
username,
email,
password,
avatarURL,
});
return res.status(201).json({
message: "User created",
user: {
email: newUser.email,
subscription: newUser.subscription,
avatarURL: newUser.avatarURL,
},
});
} catch (err) {
next(err);
}
};

const login = async (req, res, next) => {
const { email, password } = req.body;
try {
const { token, user } = await loginUser({ email, password });
return res.json({ token, user });
} catch (err) {
if (err.message === "Email has not been verified! Please check your inbox.") {
return res.status(401).json({ message: err.message });
}
next(err);
}
};

const logout = async (req, res, next) => {
try {
const userId = req.user._id;
await logoutUser(userId);
res.status(204).send();
} catch (error) {
next(error);
}
};

const getCurrentUser = async (req, res, next) => {
try {
const { email, subscription } = req.user;
res.status(200).json({ email, subscription });
} catch (error) {
next(error);
}
};

const verifyEmail = async (req, res, next) => {
const { verificationToken } = req.params;

try {
const user = await verifyUser(verificationToken);
if (!user) {
const alreadyVerifiedUser = await User.findOne({ verificationToken: null, verify: true, email: req.body.email });

if (alreadyVerifiedUser) {
return res.status(400).json({ message: "Email has already been verified!" });
}
return res.status(404).json({ message: "User not found!" });
}
res.status(200).json({ message: "Verification succesful!" });
} catch (err) {
next(err);
}
};

const resendVerificationEmailHandler = async (req, res, next) => {
const { email } = req.body;

if(!email) {
return res.status(400).json({ message: "Missing required field email!" });
}
try {
const result = await resendVerificationEmail(email);
if (result === "alreadyVerified") {
return res.status(400).json({ message: "Verification has already been passed!" });
}
res.status(200).json({ message: "Verification email sent!" });
} catch (err) {
next(err);
}
}

module.exports = {
signup,
login,
logout,
getCurrentUser,
verifyEmail,
resendVerificationEmailHandler,
};
98 changes: 98 additions & 0 deletions controllers/contactController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
const {
getAllContacts,
createContact,
updateExistingContact,
deleteContact,
getContactById,
} = require("../services/contactService");

const fetchAll = async (req, res, next) => {
try {
const contacts = await getAllContacts();
res.json(contacts);
} catch (err) {
next(err);
}
};

const fetchById = async (req, res, next) => {
try {
const contacts = await getContactById(req.params.id);
if (contacts) {
res.json(contacts);
} else {
next();
}
} catch (err) {
next(err);
}
};

const insertContact = async (req, res, next) => {
const { name, email, phone } = req.body;
try {
const newContact = await createContact({
name,
email,
phone,
});
res.status(201).json(newContact);
} catch (err) {
next(err);
}
};

const updateContactDetails = async (req, res, next) => {
const { id } = req.params;
const { name, email, phone } = req.body;
try {
const updatedContact = await updateExistingContact(id, {
name,
email,
phone,
});
if (!updatedContact) {
next();
} else {
res.json(updatedContact);
}
} catch (err) {
next(err);
}
};

const updateContactStatus = async (req, res, next) => {
const { id } = req.params;
const { favorite = false } = req.body;
try {
const updatedStatus = await updateExistingContact(id, { favorite });
if (!updatedStatus) {
next();
} else {
res.json(updatedStatus);
}
} catch (err) {
next(err);
}
};

const removeContact = async (req, res, next) => {
const { id } = req.params;
try {
await deleteContact(id);
res.status(204).send({
message: "Contact deleted!",
});
} catch (err) {
next(err);
}
};

module.exports = {
fetchAll,
fetchById,
insertContact,
updateContactDetails,
removeContact,
updateContactStatus,
};
60 changes: 60 additions & 0 deletions controllers/uploadController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
const fs = require("fs/promises");
const path = require("path");
const Jimp = require("jimp");
const { v4: uuidv4 } = require("uuid");
const User = require("../services/schemas/userSchema");
const { setupFolder } = require("../utils/folderUtils"); // Import funkcji pomocniczej

const avatarsDir = path.join(process.cwd(), "public/avatars");
const MAX_AVATAR_WIDTH = 250;
const MAX_AVATAR_HEIGHT = 250;

// Funkcja aktualizacji awatara
const updateAvatar = async (req, res, next) => {
try {
// Sprawdzenie, czy folder "avatars" istnieje
await setupFolder(avatarsDir); // Wywołanie funkcji, która sprawdza i tworzy folder

if (!req.file) {
return res.status(400).json({ message: "No file uploaded" });
}

const { path: tmpPath, originalname } = req.file;
const ext = path.extname(originalname).toLowerCase();
const uniqueName = `${uuidv4()}${ext}`;
const avatarPath = path.join(avatarsDir, uniqueName);

// Przeniesienie pliku z tmp do folderu avatars
await fs.rename(tmpPath, avatarPath);

// Przetwarzanie obrazu za pomocą Jimp (kadrowanie)
const image = await Jimp.read(avatarPath);
const w = image.bitmap.width;
const h = image.bitmap.height;

// Przycięcie obrazu do maksymalnych wymiarów 250x250
const cropWidth = w > MAX_AVATAR_WIDTH ? MAX_AVATAR_WIDTH : w;
const cropHeight = h > MAX_AVATAR_HEIGHT ? MAX_AVATAR_HEIGHT : h;

const centerX = Math.round(w / 2 - cropWidth / 2);
const centerY = Math.round(h / 2 - cropHeight / 2);

await image
.crop(centerX, centerY, cropWidth, cropHeight)
.resize(250, 250) // Zmiana rozmiaru na 250x250
.writeAsync(avatarPath); // Zapis przetworzonego obrazu

// Aktualizacja URL-a awatara w bazie danych użytkownika
const avatarURL = `/avatars/${uniqueName}`;
await User.findByIdAndUpdate(req.user._id, { avatarURL });

res.json({ avatarURL });
} catch (err) {
console.error(err);
next(err);
}
};

module.exports = {
updateAvatar,
};
30 changes: 30 additions & 0 deletions middleware/authMiddleware.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const passport = require("passport");
const User = require("../services/schemas/userSchema");

const authMiddleware = (req, res, next) => {
passport.authenticate(
"jwt",
{
session: false,
},
async (err, user) => {
if (!user || err) {
return res.status(401).json({ message: "Unauthorized!" });
}

const foundUser = await User.findById(user._id);
if (
!foundUser ||
foundUser.token !== req.headers.authorization.split(" ")[1]
) {
return res.status(401).json({ message: "Unauthorized!" });
}
req.user = foundUser;
next();
},
)(req, res, next);
};

module.exports = {
authMiddleware,
};
Loading