Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
bjorkypie committed Jun 1, 2021
0 parents commit 598cba5
Show file tree
Hide file tree
Showing 35 changed files with 3,106 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
*.env
*.DS_Store
4 changes: 4 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"editor.fontSize": 24,
"terminal.integrated.fontSize": 20
}
1 change: 1 addition & 0 deletions Procfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
web: node server.js
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Install

`npm install`

---

# Things to add

- Create a .env file and add the following as key = value
- PORT = 2121 (can be any port example: 3000)
- DB_STRING = your database URI
- CLOUD_NAME = your cloudinary cloud name
- API_KEY = your cloudinary api key
- API_SECRET = your cloudinary api secret
- logo
- adapt pages
---

# Run

`npm start`
19 changes: 19 additions & 0 deletions config/database.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const mongoose = require("mongoose");

const connectDB = async () => {
try {
const conn = await mongoose.connect(process.env.DB_STRING, {
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: false,
useCreateIndex: true,
});

console.log(`MongoDB Connected: ${conn.connection.host}`);
} catch (err) {
console.error(err);
process.exit(1);
}
};

module.exports = connectDB;
41 changes: 41 additions & 0 deletions config/passport.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
const LocalStrategy = require("passport-local").Strategy;
const mongoose = require("mongoose");
const User = require("../models/User");

module.exports = function (passport) {
passport.use(
new LocalStrategy({ usernameField: "email" }, (email, password, done) => {
User.findOne({ email: email.toLowerCase() }, (err, user) => {
if (err) {
return done(err);
}
if (!user) {
return done(null, false, { msg: `Email ${email} not found.` });
}
if (!user.password) {
return done(null, false, {
msg:
"Your account was registered using a sign-in provider. To enable password login, sign in using a provider, and then set a password under your user profile.",
});
}
user.comparePassword(password, (err, isMatch) => {
if (err) {
return done(err);
}
if (isMatch) {
return done(null, user);
}
return done(null, false, { msg: "Invalid email or password." });
});
});
})
);

passport.serializeUser((user, done) => {
done(null, user.id);
});

passport.deserializeUser((id, done) => {
User.findById(id, (err, user) => done(err, user));
});
};
116 changes: 116 additions & 0 deletions controllers/auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
const passport = require("passport");
const validator = require("validator");
const User = require("../models/User");

exports.getLogin = (req, res) => {
if (req.user) {
return res.redirect("/profile");
}
res.render("login", {
title: "Login",
});
};

exports.postLogin = (req, res, next) => {
const validationErrors = [];
if (!validator.isEmail(req.body.email))
validationErrors.push({ msg: "Please enter a valid email address." });
if (validator.isEmpty(req.body.password))
validationErrors.push({ msg: "Password cannot be blank." });

if (validationErrors.length) {
req.flash("errors", validationErrors);
return res.redirect("/login");
}
req.body.email = validator.normalizeEmail(req.body.email, {
gmail_remove_dots: false,
});

passport.authenticate("local", (err, user, info) => {
if (err) {
return next(err);
}
if (!user) {
req.flash("errors", info);
return res.redirect("/login");
}
req.logIn(user, (err) => {
if (err) {
return next(err);
}
req.flash("success", { msg: "Success! You are logged in." });
res.redirect(req.session.returnTo || "/profile");
});
})(req, res, next);
};

exports.logout = (req, res) => {
req.logout();
req.session.destroy((err) => {
if (err)
console.log("Error : Failed to destroy the session during logout.", err);
req.user = null;
res.redirect("/");
});
};

exports.getSignup = (req, res) => {
if (req.user) {
return res.redirect("/profile");
}
res.render("signup", {
title: "Create Account",
});
};

exports.postSignup = (req, res, next) => {
const validationErrors = [];
if (!validator.isEmail(req.body.email))
validationErrors.push({ msg: "Please enter a valid email address." });
if (!validator.isLength(req.body.password, { min: 8 }))
validationErrors.push({
msg: "Password must be at least 8 characters long",
});
if (req.body.password !== req.body.confirmPassword)
validationErrors.push({ msg: "Passwords do not match" });

if (validationErrors.length) {
req.flash("errors", validationErrors);
return res.redirect("../signup");
}
req.body.email = validator.normalizeEmail(req.body.email, {
gmail_remove_dots: false,
});

const user = new User({
userName: req.body.userName,
email: req.body.email,
password: req.body.password,
});

User.findOne(
{ $or: [{ email: req.body.email }, { userName: req.body.userName }] },
(err, existingUser) => {
if (err) {
return next(err);
}
if (existingUser) {
req.flash("errors", {
msg: "Account with that email address or username already exists.",
});
return res.redirect("../signup");
}
user.save((err) => {
if (err) {
return next(err);
}
req.logIn(user, (err) => {
if (err) {
return next(err);
}
res.redirect("/profile");
});
});
}
);
};
5 changes: 5 additions & 0 deletions controllers/home.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = {
getIndex: (req, res) => {
res.render("index.ejs");
},
};
76 changes: 76 additions & 0 deletions controllers/posts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
const cloudinary = require("../middleware/cloudinary");
const Post = require("../models/Post");

module.exports = {
getProfile: async (req, res) => {
try {
const posts = await Post.find({ user: req.user.id });
res.render("profile.ejs", { posts: posts, user: req.user });
} catch (err) {
console.log(err);
}
},
getFeed: async (req, res) => {
try {
const posts = await Post.find().sort({ createdAt: "desc" }).lean();
res.render("feed.ejs", { posts: posts });
} catch (err) {
console.log(err);
}
},
getPost: async (req, res) => {
try {
const post = await Post.findById(req.params.id);
res.render("post.ejs", { post: post, user: req.user });
} catch (err) {
console.log(err);
}
},
createPost: async (req, res) => {
try {
// Upload image to cloudinary
const result = await cloudinary.uploader.upload(req.file.path);

await Post.create({
title: req.body.title,
image: result.secure_url,
cloudinaryId: result.public_id,
caption: req.body.caption,
likes: 0,
user: req.user.id,
});
console.log("Post has been added!");
res.redirect("/profile");
} catch (err) {
console.log(err);
}
},
likePost: async (req, res) => {
try {
await Post.findOneAndUpdate(
{ _id: req.params.id }, //_id: req.params.zebra, how we find our matching ID
{
$inc: { likes: 1 },
}
);
console.log("Likes +1");
res.redirect(`/post/${req.params.id}`);
} catch (err) {
console.log(err);
}
},
deletePost: async (req, res) => {
try {
// Find post by id
let post = await Post.findById({ _id: req.params.id });
// Delete image from cloudinary
await cloudinary.uploader.destroy(post.cloudinaryId);
// Delete post from db
await Post.remove({ _id: req.params.id });
console.log("Deleted Post");
res.redirect("/profile");
} catch (err) {
res.redirect("/profile");
}
},
};
5 changes: 5 additions & 0 deletions controllers/team.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = {
getTeam: (req, res) => {
res.render("team.ejs");
},
};
16 changes: 16 additions & 0 deletions middleware/auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module.exports = {
ensureAuth: function (req, res, next) {
if (req.isAuthenticated()) {
return next();
} else {
res.redirect("/");
}
},
ensureGuest: function (req, res, next) {
if (!req.isAuthenticated()) {
return next();
} else {
res.redirect("/dashboard");
}
},
};
11 changes: 11 additions & 0 deletions middleware/cloudinary.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const cloudinary = require("cloudinary").v2;

require("dotenv").config({ path: "./config/.env" });

cloudinary.config({
cloud_name: process.env.CLOUD_NAME,
api_key: process.env.API_KEY,
api_secret: process.env.API_SECRET,
});

module.exports = cloudinary;
14 changes: 14 additions & 0 deletions middleware/multer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const multer = require("multer");
const path = require("path");

module.exports = multer({
storage: multer.diskStorage({}),
fileFilter: (req, file, cb) => {
let ext = path.extname(file.originalname);
if (ext !== ".jpg" && ext !== ".jpeg" && ext !== ".png") {
cb(new Error("File type is not supported"), false);
return;
}
cb(null, true);
},
});
34 changes: 34 additions & 0 deletions models/Post.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
const mongoose = require("mongoose");

const PostSchema = new mongoose.Schema({
title: {
type: String,
required: true,
},
image: {
type: String,
require: true,
},
cloudinaryId: {
type: String,
require: true,
},
caption: {
type: String,
required: true,
},
likes: {
type: Number,
required: true,
},
user: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
createdAt: {
type: Date,
default: Date.now,
},
});

module.exports = mongoose.model("Post", PostSchema);
Loading

0 comments on commit 598cba5

Please sign in to comment.