diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8f5e467 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +node_modules +package-lock.json +.env \ No newline at end of file diff --git a/app.js b/app.js new file mode 100644 index 0000000..43167b7 --- /dev/null +++ b/app.js @@ -0,0 +1,66 @@ +require("dotenv").config(); +const express = require("express"), + app = express(), + mongoose = require("mongoose"), + bodyParser = require("body-parser"); +(expressSantizer = require("express-sanitizer")), + (methodOverride = require("method-override")), + (passport = require("passport")), + (localStrategy = require("passport-local")), + (flash = require("connect-flash")); + +const blogRoutes = require("./routes/blog"), + authRoutes = require("./routes/auth"); + +const User = require("./models/user"); + +app.use( + bodyParser.urlencoded({ + extended: true, + }) +); +app.set("view engine", "ejs"); +app.use(express.static("public")); +app.use(expressSantizer()); +app.use(methodOverride("_method")); +app.use(flash()); + +// PASSPORT Configuration +app.use( + require("express-session")({ + secret: "Who knows what is this?!", + resave: false, + saveUninitialized: false, + }) +); +app.use(passport.initialize()); +app.use(passport.session()); +passport.use(new localStrategy(User.authenticate())); +passport.serializeUser(User.serializeUser()); +passport.deserializeUser(User.deserializeUser()); + +// FLASH Middleware +app.use((req, res, next) => { + res.locals.user = req.user; + res.locals.success = req.flash("success"); + res.locals.error = req.flash("error"); + next(); +}); + +app.use("/blogs", blogRoutes); +app.use("/", authRoutes); + +mongoose + .connect(process.env.DB_CONNECT, { + useNewUrlParser: true, + useUnifiedTopology: true, + useFindAndModify: false, + }) + .then(() => { + console.log("===DB Connected==="); + }) + .catch((err) => { + console.log(err); + }); + +app.listen(process.env.PORT || 3000); diff --git a/css/login.css b/css/login.css new file mode 100644 index 0000000..e530e62 --- /dev/null +++ b/css/login.css @@ -0,0 +1,18 @@ +.container { + width: 30%; + padding: 2rem 3rem; + -webkit-box-shadow: 0 0 8px 0 #aaa; + box-shadow: 0 0 8px 0 #aaa; + margin: auto; + text-align: center; + margin-top: 5em; +} + +.container input { + display: block; + margin: auto; + width: 70%; + height: 2rem; + padding: 1rem; +} +/*# sourceMappingURL=login.css.map */ \ No newline at end of file diff --git a/css/login.css.map b/css/login.css.map new file mode 100644 index 0000000..24184c3 --- /dev/null +++ b/css/login.css.map @@ -0,0 +1,9 @@ +{ + "version": 3, + "mappings": "AAAA,AAAA,UAAU,CAAC;EACT,KAAK,EAAE,GAAG;EACV,OAAO,EAAE,SAAS;EAClB,UAAU,EAAE,cAAc;EAC1B,MAAM,EAAE,IAAI;EACZ,UAAU,EAAE,MAAM;EAClB,UAAU,EAAE,GAAG;CAShB;;AAfD,AAQE,UARQ,CAQR,KAAK,CAAC;EACJ,OAAO,EAAE,KAAK;EACd,MAAM,EAAE,IAAI;EACZ,KAAK,EAAE,GAAG;EACV,MAAM,EAAE,IAAI;EACZ,OAAO,EAAE,IAAI;CACd", + "sources": [ + "login.scss" + ], + "names": [], + "file": "login.css" +} \ No newline at end of file diff --git a/css/login.scss b/css/login.scss new file mode 100644 index 0000000..20f7f13 --- /dev/null +++ b/css/login.scss @@ -0,0 +1,16 @@ +.container { + width: 30%; + padding: 2rem 3rem; + box-shadow: 0 0 8px 0 #aaa; + margin: auto; + text-align: center; + margin-top: 5em; + + input { + display: block; + margin: auto; + width: 70%; + height: 2rem; + padding: 1rem; + } +} diff --git a/middleware/index.js b/middleware/index.js new file mode 100644 index 0000000..39decf4 --- /dev/null +++ b/middleware/index.js @@ -0,0 +1,39 @@ +const Blog = require("../models/blog"), + User = require("../models/user"); +exports.isLoggedIn = function (req, res, next) { + if (req.isAuthenticated()) { + return next(); + } + + req.flash("error", "Please log in first"); + return res.redirect("/login"); +}; + +exports.checkBlogAuthor = function (req, res, next) { + Blog.findById(req.params.id, (err, blog) => { + if (err || !blog) { + console.log(err); + req.flash("error", "Sorry! This blog does not exist"); + return res.redirect("/blogs"); + } else if (blog.author.id.equals(req.user._id)) { + next(); + } else { + req.flash("error", "You do not have permission to do that"); + return res.redirect("back"); + } + }); +}; + +exports.checkLoginInfo = function (req, res, next) { + User.findOne({ username: req.body.username }, (err, user) => { + if (err || !user) { + req.flash( + "error", + "This username does not exist. Please register first." + ); + return res.redirect("/login"); + } + + next(); + }); +}; diff --git a/models/blog.js b/models/blog.js new file mode 100644 index 0000000..e7c5d62 --- /dev/null +++ b/models/blog.js @@ -0,0 +1,21 @@ +const mongoose = require("mongoose"); + +const blogSchema = new mongoose.Schema({ + title: String, + body: String, + image: String, + author: { + id: { + type: mongoose.Schema.Types.ObjectId, + ref: "User", + }, + + name: String, + }, + created: { + type: Date, + default: Date.now(), + }, +}); + +module.exports = mongoose.model("Blog", blogSchema); diff --git a/models/user.js b/models/user.js new file mode 100644 index 0000000..a7aba88 --- /dev/null +++ b/models/user.js @@ -0,0 +1,30 @@ +const mongoose = require("mongoose"); +const passportLocalMongoose = require("passport-local-mongoose"); + +const userSchema = new mongoose.Schema( + { + name: { + type: String, + required: true, + }, + username: { + type: String, + required: true, + unique: true, + }, + email: { + type: String, + required: true, + unique: true, + }, + password: { + type: String, + // required: true, + }, + }, + { timestamps: true } +); + +userSchema.plugin(passportLocalMongoose); + +module.exports = mongoose.model("User", userSchema); diff --git a/package.json b/package.json new file mode 100644 index 0000000..20b30a8 --- /dev/null +++ b/package.json @@ -0,0 +1,26 @@ +{ + "name": "ircblog", + "version": "1.0.0", + "description": "", + "main": "app.js", + "scripts": { + "start": "node app.js" + }, + "author": "", + "license": "ISC", + "dependencies": { + "@hapi/joi": "^17.1.1", + "body-parser": "^1.19.0", + "connect-flash": "^0.1.1", + "dotenv": "^8.2.0", + "ejs": "^3.1.2", + "express": "^4.17.1", + "express-sanitizer": "^1.0.5", + "express-session": "^1.17.1", + "method-override": "^3.0.0", + "mongoose": "^5.9.10", + "passport": "^0.4.1", + "passport-local": "^1.0.0", + "passport-local-mongoose": "^6.0.1" + } +} diff --git a/public/about.html b/public/about.html new file mode 100644 index 0000000..94640c6 --- /dev/null +++ b/public/about.html @@ -0,0 +1,109 @@ + + + + + + About Us | ITER ROBOTICS CLUB + + + + + +
+ +
+ +
+
+

About Us

+

+ The need for a technical club which would incorporate the principles + of all engineering branches onto a common platform was felt by the + dynamic students of the college, as a result of which the iter + robotics club was initiated in the year 2007. +

+ +

+ ​It is an open club, co-ordinated by the students, + functioning in the interest of students of the institution wishing to + have a practical application of their knowledge base, gained from the + classrooms. +

+

+ ​We at iter robotics club constantly have been working for the + spreading of technical awareness in the field of robotics . +

+

+ ​We beileve in creating local hotpots of technical knowledge for the + proper access to technology to the engineering fraternity. We believe + in putting theories into practice in day to day life making process + easier for humans +

+

+ ​The worldwide developments in the field of robotics today has + obviously encouraged whooping number of students taking ‘robotics’ + into something more than just a hobby. +

+ +

+ Presently, the IRC has more than 100+ registered + student members from various branches who have shown their excellence + by winning robotics competitions throughout the nation. +

+
+
+ + + + + + diff --git a/public/css/index.css b/public/css/index.css new file mode 100644 index 0000000..10b99e3 --- /dev/null +++ b/public/css/index.css @@ -0,0 +1,67 @@ +.container { + width: 70%; + margin: 5rem auto; +} + +.blog { + position: relative; + margin-bottom: 5rem; +} + +.blog-title { + font-size: 3.3rem; + font-weight: 700; +} + +.other { + display: flex; + width: 50%; + margin-bottom: 2rem; +} + +.other .blog-author { + margin-right: 1em; +} + +.image img { + width: 15%; + position: absolute; + right: 0; + top: 5%; + display: inline-block; + margin-left: 1em; +} + +.body { + width: 85%; + margin-bottom: 3rem; +} + +.blog-body { + font-size: 2.2rem; +} + +.blog-date, +.blog-author { + font-size: 1.8rem; + font-weight: 300; +} + +.btn { + width: 20%; + text-align: center; + border: 2px solid #ee8844; + border-radius: 3rem; + padding: 1rem 2em; + cursor: pointer; + color: #ee8844; + font-size: 1.8rem; + transition: 0.3s ease; +} + +.btn:hover { + color: white; + background: #ee8844; + border: none; + box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.5); +} diff --git a/public/css/login.css b/public/css/login.css new file mode 100644 index 0000000..d0b2a69 --- /dev/null +++ b/public/css/login.css @@ -0,0 +1,91 @@ +.container { + width: 30%; + padding: 2rem 3rem; + -webkit-box-shadow: 0 0 8px 0 #aaa; + box-shadow: 0 0 8px 0 #aaa; + margin: auto; + text-align: center; + margin-top: 5em; + border-radius: 1rem; + min-height: 50vh; + position: relative; +} + +.container .heading h2 { + font-size: 4rem; + margin: 4rem 0; +} + +.container input { + display: block; + margin: 1rem auto; + width: 80%; + height: 3.5rem; + padding: 1rem; + outline: none; + border: none; + background: #eee; + -webkit-transition: 0.3s ease-in; + transition: 0.3s ease-in; + border-radius: 0.5rem; +} + +.container input:focus { + border-color: dodgerblue; + -webkit-box-shadow: 0 0 6px 0 dodgerblue; + box-shadow: 0 0 6px 0 dodgerblue; +} + +.container button { + cursor: pointer; + padding: 0.5rem 2rem; + margin-top: 2.5rem; + background: dodgerblue; + color: white; + border: none; + font-size: 1.8rem; + border-radius: 2rem; + font-family: "Montserrat", sans-serif; +} + +.container button:hover { + background: #2475b0; +} + +.container .other { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-align: start; + -ms-flex-align: start; + align-items: flex-start; + -webkit-box-pack: end; + -ms-flex-pack: end; + justify-content: flex-end; + margin-top: 5.5rem; +} + +.container .other p { + font-size: 1.5rem; + margin-bottom: 0.5rem; + font-weight: 600; +} + +.container .other a { + padding: 0.5rem 1.5rem; + border: 2px solid dodgerblue; + border-radius: 1rem; + -webkit-transition: 0.3s; + transition: 0.3s; + font-size: 1.5rem; +} + +.container .other a:hover { + background: dodgerblue; + color: white; +} +/*# sourceMappingURL=login.css.map */ \ No newline at end of file diff --git a/public/css/login.css.map b/public/css/login.css.map new file mode 100644 index 0000000..215ac42 --- /dev/null +++ b/public/css/login.css.map @@ -0,0 +1,9 @@ +{ + "version": 3, + "mappings": "AAAA,AAAA,UAAU,CAAC;EACT,KAAK,EAAE,GAAG;EACV,OAAO,EAAE,SAAS;EAClB,UAAU,EAAE,cAAc;EAC1B,MAAM,EAAE,IAAI;EACZ,UAAU,EAAE,MAAM;EAClB,UAAU,EAAE,GAAG;EACf,aAAa,EAAE,IAAI;EACnB,UAAU,EAAE,IAAI;EAChB,QAAQ,EAAE,QAAQ;CAmEnB;;AA5ED,AAWE,UAXQ,CAWR,QAAQ,CAAC,EAAE,CAAC;EACV,SAAS,EAAE,IAAI;EACf,MAAM,EAAE,MAAM;CACf;;AAdH,AAgBE,UAhBQ,CAgBR,KAAK,CAAC;EACJ,OAAO,EAAE,KAAK;EACd,MAAM,EAAE,SAAS;EACjB,KAAK,EAAE,GAAG;EACV,MAAM,EAAE,MAAM;EACd,OAAO,EAAE,IAAI;EACb,OAAO,EAAE,IAAI;EACb,MAAM,EAAE,IAAI;EACZ,UAAU,EAAE,IAAI;EAChB,UAAU,EAAE,YAAY;EACxB,aAAa,EAAE,MAAM;CAMtB;;AAhCH,AA4BI,UA5BM,CAgBR,KAAK,AAYF,MAAM,CAAC;EACN,YAAY,EAAE,UAAU;EACxB,UAAU,EAAE,oBAAoB;CACjC;;AA/BL,AAkCE,UAlCQ,CAkCR,MAAM,CAAC;EACL,MAAM,EAAE,OAAO;EACf,OAAO,EAAE,WAAW;EACpB,UAAU,EAAE,MAAM;EAClB,UAAU,EAAE,UAAU;EACtB,KAAK,EAAE,KAAK;EACZ,MAAM,EAAE,IAAI;EACZ,SAAS,EAAE,MAAM;EACjB,aAAa,EAAE,IAAI;EACnB,WAAW,EAAE,wBAAwB;CAKtC;;AAhDH,AA6CI,UA7CM,CAkCR,MAAM,AAWH,MAAM,CAAC;EACN,UAAU,EAAE,OAAO;CACpB;;AA/CL,AAkDE,UAlDQ,CAkDR,MAAM,CAAC;EACL,OAAO,EAAE,IAAI;EACb,cAAc,EAAE,MAAM;EACtB,WAAW,EAAE,UAAU;EACvB,eAAe,EAAE,QAAQ;EACzB,UAAU,EAAE,MAAM;CACnB;;AAxDH,AA0DE,UA1DQ,CA0DR,MAAM,CAAC,CAAC,CAAC;EACP,SAAS,EAAE,MAAM;EACjB,aAAa,EAAE,MAAM;EACrB,WAAW,EAAE,GAAG;CACjB;;AA9DH,AAgEE,UAhEQ,CAgER,MAAM,CAAC,CAAC,CAAC;EACP,OAAO,EAAE,aAAa;EACtB,MAAM,EAAE,oBAAoB;EAC5B,aAAa,EAAE,IAAI;EACnB,UAAU,EAAE,IAAI;EAChB,SAAS,EAAE,MAAM;CAMlB;;AA3EH,AAuEI,UAvEM,CAgER,MAAM,CAAC,CAAC,AAOL,MAAM,CAAC;EACN,UAAU,EAAE,UAAU;EACtB,KAAK,EAAE,KAAK;CACb", + "sources": [ + "login.scss" + ], + "names": [], + "file": "login.css" +} \ No newline at end of file diff --git a/public/css/login.scss b/public/css/login.scss new file mode 100644 index 0000000..150e4d1 --- /dev/null +++ b/public/css/login.scss @@ -0,0 +1,77 @@ +.container { + width: 30%; + padding: 2rem 3rem; + box-shadow: 0 0 8px 0 #aaa; + margin: auto; + text-align: center; + margin-top: 5em; + border-radius: 1rem; + min-height: 50vh; + position: relative; + + .heading h2 { + font-size: 4rem; + margin: 4rem 0; + } + + input { + display: block; + margin: 1rem auto; + width: 80%; + height: 3.5rem; + padding: 1rem; + outline: none; + border: none; + background: #eee; + transition: 0.3s ease-in; + border-radius: 0.5rem; + + &:focus { + border-color: dodgerblue; + box-shadow: 0 0 6px 0 dodgerblue; + } + } + + button { + cursor: pointer; + padding: 0.5rem 2rem; + margin-top: 2.5rem; + background: dodgerblue; + color: white; + border: none; + font-size: 1.8rem; + border-radius: 2rem; + font-family: "Montserrat", sans-serif; + + &:hover { + background: #2475b0; + } + } + + .other { + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: flex-end; + margin-top: 5.5rem; + } + + .other p { + font-size: 1.5rem; + margin-bottom: 0.5rem; + font-weight: 600; + } + + .other a { + padding: 0.5rem 1.5rem; + border: 2px solid dodgerblue; + border-radius: 1rem; + transition: 0.3s; + font-size: 1.5rem; + + &:hover { + background: dodgerblue; + color: white; + } + } +} diff --git a/public/css/new.css b/public/css/new.css new file mode 100644 index 0000000..1ccc8ce --- /dev/null +++ b/public/css/new.css @@ -0,0 +1,57 @@ +.container { + width: 70%; + margin: 4em auto; + padding: 0 3em; +} + +.heading { + font-size: 3.5rem; + font-weight: 700; + text-align: center; + margin-bottom: 1em; +} + +.blog { + width: 80%; + height: 7vh; + margin: 0 auto; + margin-bottom: 2em; + display: flex; + justify-content: center; +} + +input, +textarea { + background: none; + border: none; + border: 1px solid #aaa; + width: 100%; + height: 90%; + font-size: 1.8rem; + padding: 1rem; + outline: none; + transition: 0.4s; +} + +input:focus, +textarea:focus { + border-color: dodgerblue; + box-shadow: 0 0 8px 0 dodgerblue; +} + +.body { + height: 80vh; +} + +textarea { + resize: none; + font-family: sans-serif; +} + +input[type="submit"] { + width: 40%; + background: #33b3f3; + color: white; + border: none; + cursor: pointer; +} diff --git a/public/css/register.css b/public/css/register.css new file mode 100644 index 0000000..4c3425a --- /dev/null +++ b/public/css/register.css @@ -0,0 +1,89 @@ +.container { + width: 30%; + padding: 2rem 3rem; + -webkit-box-shadow: 0 0 8px 0 #aaa; + box-shadow: 0 0 8px 0 #aaa; + margin: auto; + text-align: center; + margin-top: 5em; + border-radius: 1rem; +} + +.container .heading h2 { + font-size: 4rem; + margin: 4rem 0; +} + +.container input { + display: block; + margin: 1.5rem auto; + width: 80%; + height: 3.5rem; + padding: 1rem; + outline: none; + border: none; + -webkit-transition: 0.3s ease-in; + transition: 0.3s ease-in; + background: #eee; + border-radius: 0.5rem; +} + +.container input:focus { + border-color: dodgerblue; + -webkit-box-shadow: 0 0 6px 0 dodgerblue; + box-shadow: 0 0 6px 0 dodgerblue; +} + +.container button { + cursor: pointer; + padding: 0.5rem 2rem; + margin-top: 3rem; + background: dodgerblue; + color: white; + border: none; + font-size: 1.8rem; + border-radius: 2rem; + font-family: "Montserrat", sans-serif; +} + +.container button:hover { + background: #2475b0; +} + +.container .other { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-align: start; + -ms-flex-align: start; + align-items: flex-start; + -webkit-box-pack: end; + -ms-flex-pack: end; + justify-content: flex-end; + margin-top: 5rem; +} + +.container .other p { + font-size: 1.5rem; + margin-bottom: 0.5rem; + font-weight: 600; +} + +.container .other a { + padding: 0.5rem 1.5rem; + border: 2px solid dodgerblue; + border-radius: 1rem; + -webkit-transition: 0.3s; + transition: 0.3s; + font-size: 1.5rem; +} + +.container .other a:hover { + background: dodgerblue; + color: white; +} +/*# sourceMappingURL=register.css.map */ \ No newline at end of file diff --git a/public/css/register.css.map b/public/css/register.css.map new file mode 100644 index 0000000..44462e1 --- /dev/null +++ b/public/css/register.css.map @@ -0,0 +1,9 @@ +{ + "version": 3, + "mappings": "AAAA,AAAA,UAAU,CAAC;EACT,KAAK,EAAE,GAAG;EACV,OAAO,EAAE,SAAS;EAClB,UAAU,EAAE,cAAc;EAC1B,MAAM,EAAE,IAAI;EACZ,UAAU,EAAE,MAAM;EAClB,UAAU,EAAE,GAAG;EACf,aAAa,EAAE,IAAI;CAmEpB;;AA1ED,AASE,UATQ,CASR,QAAQ,CAAC,EAAE,CAAC;EACV,SAAS,EAAE,IAAI;EACf,MAAM,EAAE,MAAM;CACf;;AAZH,AAcE,UAdQ,CAcR,KAAK,CAAC;EACJ,OAAO,EAAE,KAAK;EACd,MAAM,EAAE,WAAW;EACnB,KAAK,EAAE,GAAG;EACV,MAAM,EAAE,MAAM;EACd,OAAO,EAAE,IAAI;EACb,OAAO,EAAE,IAAI;EACb,MAAM,EAAE,IAAI;EACZ,UAAU,EAAE,YAAY;EACxB,UAAU,EAAE,IAAI;EAChB,aAAa,EAAE,MAAM;CAMtB;;AA9BH,AA0BI,UA1BM,CAcR,KAAK,AAYF,MAAM,CAAC;EACN,YAAY,EAAE,UAAU;EACxB,UAAU,EAAE,oBAAoB;CACjC;;AA7BL,AAgCE,UAhCQ,CAgCR,MAAM,CAAC;EACL,MAAM,EAAE,OAAO;EACf,OAAO,EAAE,WAAW;EACpB,UAAU,EAAE,IAAI;EAChB,UAAU,EAAE,UAAU;EACtB,KAAK,EAAE,KAAK;EACZ,MAAM,EAAE,IAAI;EACZ,SAAS,EAAE,MAAM;EACjB,aAAa,EAAE,IAAI;EACnB,WAAW,EAAE,wBAAwB;CAKtC;;AA9CH,AA2CI,UA3CM,CAgCR,MAAM,AAWH,MAAM,CAAC;EACN,UAAU,EAAE,OAAO;CACpB;;AA7CL,AAgDE,UAhDQ,CAgDR,MAAM,CAAC;EACL,OAAO,EAAE,IAAI;EACb,cAAc,EAAE,MAAM;EACtB,WAAW,EAAE,UAAU;EACvB,eAAe,EAAE,QAAQ;EACzB,UAAU,EAAE,IAAI;CACjB;;AAtDH,AAwDE,UAxDQ,CAwDR,MAAM,CAAC,CAAC,CAAC;EACP,SAAS,EAAE,MAAM;EACjB,aAAa,EAAE,MAAM;EACrB,WAAW,EAAE,GAAG;CACjB;;AA5DH,AA8DE,UA9DQ,CA8DR,MAAM,CAAC,CAAC,CAAC;EACP,OAAO,EAAE,aAAa;EACtB,MAAM,EAAE,oBAAoB;EAC5B,aAAa,EAAE,IAAI;EACnB,UAAU,EAAE,IAAI;EAChB,SAAS,EAAE,MAAM;CAMlB;;AAzEH,AAqEI,UArEM,CA8DR,MAAM,CAAC,CAAC,AAOL,MAAM,CAAC;EACN,UAAU,EAAE,UAAU;EACtB,KAAK,EAAE,KAAK;CACb", + "sources": [ + "register.scss" + ], + "names": [], + "file": "register.css" +} \ No newline at end of file diff --git a/public/css/register.scss b/public/css/register.scss new file mode 100644 index 0000000..e8f65b8 --- /dev/null +++ b/public/css/register.scss @@ -0,0 +1,75 @@ +.container { + width: 30%; + padding: 2rem 3rem; + box-shadow: 0 0 8px 0 #aaa; + margin: auto; + text-align: center; + margin-top: 5em; + border-radius: 1rem; + + .heading h2 { + font-size: 4rem; + margin: 4rem 0; + } + + input { + display: block; + margin: 1.5rem auto; + width: 80%; + height: 3.5rem; + padding: 1rem; + outline: none; + border: none; + transition: 0.3s ease-in; + background: #eee; + border-radius: 0.5rem; + + &:focus { + border-color: dodgerblue; + box-shadow: 0 0 6px 0 dodgerblue; + } + } + + button { + cursor: pointer; + padding: 0.5rem 2rem; + margin-top: 3rem; + background: dodgerblue; + color: white; + border: none; + font-size: 1.8rem; + border-radius: 2rem; + font-family: "Montserrat", sans-serif; + + &:hover { + background: #2475b0; + } + } + + .other { + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: flex-end; + margin-top: 5rem; + } + + .other p { + font-size: 1.5rem; + margin-bottom: 0.5rem; + font-weight: 600; + } + + .other a { + padding: 0.5rem 1.5rem; + border: 2px solid dodgerblue; + border-radius: 1rem; + transition: 0.3s; + font-size: 1.5rem; + + &:hover { + background: dodgerblue; + color: white; + } + } +} diff --git a/public/css/show.css b/public/css/show.css new file mode 100644 index 0000000..da3570a --- /dev/null +++ b/public/css/show.css @@ -0,0 +1,51 @@ +.container { + width: 70%; + margin: 3em auto; +} + +.section { + margin-bottom: 2rem; +} + +.title h2 { + font-size: 4rem; +} + +.body { + font-size: 2rem; +} + +.author, +.date { + font-size: 1.7rem; +} + +.buttons { + width: 40%; + display: flex; + justify-content: space-evenly; +} + +.btn, +.delete { + border-radius: 0.8rem; + cursor: pointer; + border: none; +} + +.btn.edit { + background: #dfaf2b; + padding: 0.3em 3.5rem; +} + +.edit a { + color: white; + font-size: 1.8rem; +} + +.delete { + background-color: #d63031; + color: white; + padding: 1rem 4rem; + font-size: 1.8rem; +} diff --git a/public/css/style.css b/public/css/style.css new file mode 100644 index 0000000..91f90a8 --- /dev/null +++ b/public/css/style.css @@ -0,0 +1,94 @@ +@import url("https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700&display=swap"); + +/* defaults */ +html { + font-size: 56.25%; +} + +body { + max-width: 100%; + overflow-x: hidden; + font-family: "Montserrat", sans-serif; +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +a { + text-decoration: none; + color: black; +} + +li { + list-style: none; +} + +.btn { + text-decoration: none; + background: none; + border: none; +} + +/* navbar */ + +.navbar { + width: 100%; + height: 7em; + display: flex; + justify-content: space-between; + align-items: center; + background-color: rgba(0, 0, 0, 0.85); + color: white; +} + +.brand { + display: flex; + width: 30%; +} + +.brand-logo { + width: 4rem; + margin: 0 2em; +} + +.brand-title { + font-size: 3rem; + font-weight: 700; + margin-left: 1rem; +} + +.nav-links { + display: flex; + justify-content: space-evenly; + align-items: center; + color: white; + width: 40%; +} + +.nav-item a { + font-size: 2em; + color: white; +} + +/* MESSAGE */ + +.msg-box { + width: 70%; + margin: auto; + padding: 0.5rem 0; + font-size: 1.4rem; + border-radius: 0.7rem; +} + +.msg-box.success { + background: rgb(120, 206, 140); + color: rgb(76, 133, 89); +} + +.msg-box.error { + background: #f8d7da; + color: #b67b81; +} diff --git a/public/gallery.html b/public/gallery.html new file mode 100644 index 0000000..61ecbd6 --- /dev/null +++ b/public/gallery.html @@ -0,0 +1,122 @@ + + + + + + Gallery | ITER ROBOTICS CLUB + + + + + +
+ +
+ +
+
+
+ +
+ + + + + + + + + +
+
+ + + + + + diff --git a/public/images/arrow.svg b/public/images/arrow.svg new file mode 100644 index 0000000..0336ab4 --- /dev/null +++ b/public/images/arrow.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/images/logo.svg b/public/images/logo.svg new file mode 100644 index 0000000..39cdad4 --- /dev/null +++ b/public/images/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..b491c99 --- /dev/null +++ b/public/index.html @@ -0,0 +1,105 @@ + + + + + + Home | ITER ROBOTICS CLUB + + + + + +
+ +
+ +
+
+
+ +
+ +
+

Innovating + Simulating + Fabricating + Coding = ROBOTizing

+
+ +
+

Not a member yet ?

+ +
+ +
+ +
+
+
+ + + + + + diff --git a/public/js/script.js b/public/js/script.js new file mode 100644 index 0000000..207315a --- /dev/null +++ b/public/js/script.js @@ -0,0 +1,6 @@ +tinymce.init({ + selector: "#mytextarea", + menubar: "edit view format", + width: 1200, + height: 800, +}); diff --git a/public/mainCSS/about.css b/public/mainCSS/about.css new file mode 100644 index 0000000..6272ec2 --- /dev/null +++ b/public/mainCSS/about.css @@ -0,0 +1,23 @@ +.container { + width: 100vw; + padding: 2em; + background-color: #f6f6f6; +} + +.heading { + font-size: 3rem; + padding-bottom: 1.5rem; +} + +.container p { + font-size: 1.8rem; + padding-bottom: 2rem; +} + +@media (min-width: 900px) { + .container { + width: 80%; + margin: 0 auto; + height: 80vh; + } +} diff --git a/public/mainCSS/gallery.css b/public/mainCSS/gallery.css new file mode 100644 index 0000000..22c5699 --- /dev/null +++ b/public/mainCSS/gallery.css @@ -0,0 +1,52 @@ +.container { + width: 100%; + margin: 2em auto; + text-align: center; +} + +.container img { + width: 90vw; +} + +@media (min-width: 900px) { + .container { + width: 80%; + } + + .container img { + width: 30%; + cursor: pointer; + } + + .fade { + display: inline-block; + position: relative; + width: 30%; + height: auto; + } + + .fade img { + width: 100%; + } + + .fade::after { + content: "Senior instructing juniors"; + display: flex; + align-items: center; + justify-content: center; + color: white; + font-size: 2rem; + position: absolute; + top: 0; + left: 0; + height: 100%; + width: 100%; + background: #000; + opacity: 0; + transition: all 0.5s ease; + } + + .fade:hover::after { + opacity: 0.5; + } +} diff --git a/public/mainCSS/index.css b/public/mainCSS/index.css new file mode 100644 index 0000000..1fa4283 --- /dev/null +++ b/public/mainCSS/index.css @@ -0,0 +1,122 @@ +/* body */ + +.container { + max-width: 100%; + height: auto; + margin: 2em auto; + text-align: center; +} + +.back-image img { + width: 100vw; + margin-bottom: 2rem; +} + +.tagline { + margin-bottom: 2rem; +} + +.tagline h2 { + font-size: 1.6rem; + color: #2b2a29; +} + +.club-register { + margin-top: 6rem; +} + +.club-register h3 { + font-size: 1.8rem; + padding-bottom: 0.5rem; +} + +.btn.register { + padding: 0.5rem 4rem; + border-radius: 3em; + background-color: #0084ff; +} + +.btn.register a { + color: white; + font-size: 2.4rem; +} + +.other-info { + margin: 6rem auto; +} + +.other-info .btn { + border: 2px solid #0084ff; + padding: 1rem 3rem; + border-radius: 1.7rem; +} + +.other-info a { + font-size: 2.3rem; + font-weight: 600; +} + +.other-info p { + font-size: 1.8rem; +} + +.other-info .btn:hover { + cursor: pointer; + background-color: #0084ff; +} + +/* desktop version */ + +@media (min-width: 950px) { + .container { + width: 85%; + margin: 0 auto; + } + + .back-image img { + width: 100%; + margin: 2em auto; + } + + .tagline h2 { + font-size: 4rem; + color: rgba(30, 30, 30, 0.9); + } + + .club-register h3 { + font-size: 3rem; + } + + .btn.register { + width: 25%; + height: auto; + padding: 3em auto; + } + + .btn.register a { + letter-spacing: 0.2rem; + color: white; + font-size: 2.7rem; + } + + .btn.register:hover { + box-shadow: 0px 3px 5px #979797; + cursor: pointer; + } + + .other-info a { + font-size: 3rem; + font-weight: 600; + letter-spacing: 0.3rem; + } + + .other-info p { + font-size: 2.3rem; + letter-spacing: 0.2rem; + } + + .other-info .btn { + width: 30%; + margin: 3em auto; + } +} diff --git a/public/mainCSS/style.css b/public/mainCSS/style.css new file mode 100644 index 0000000..e985eb4 --- /dev/null +++ b/public/mainCSS/style.css @@ -0,0 +1,202 @@ +/* defaults */ +html { + font-size: 56.25%; +} + +body { + max-width: 100%; + overflow-x: hidden; + font-family: "Montserrat", sans-serif; +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +a { + text-decoration: none; + color: black; +} + +li { + list-style: none; +} + +.btn { + text-decoration: none; + background: none; + border: none; +} + +/* navbar */ + +nav { + width: 100%; + max-height: 13vh; + display: flex; + justify-content: space-between; + align-items: center; + border-bottom: 2px solid #f6f6f6; + box-shadow: 0px 2px 5px #f6f6f6; +} + +.brand, +.nav-items { + display: flex; + align-items: center; +} + +.brand a { + display: flex; +} + +.brand-title { + font-size: 2.7rem; +} + +.burger { + cursor: pointer; +} + +nav .logo { + height: 8vh; +} + +.hide-mobile { + display: none; +} + +.close-btn { + width: 20%; + position: absolute; + top: 0; + right: 0; + padding: 2rem; + cursor: pointer; +} + +.nav-links { + background-color: #f6f6f6; + position: absolute; + top: 0; + right: 0; + padding: 14em auto; + display: block; + text-align: center; + width: 60%; + height: 100vh; + transform: translateX(100%); + visibility: hidden; + transition: 800ms; +} + +.nav-links li a { + display: block; + font-size: 2em; + padding: 2em auto; + letter-spacing: 0.2rem; + margin: 2em auto; + opacity: 0; + transition: 800ms; +} + +.nav-links.nav-active { + transform: translateX(0%); + opacity: 1; + visibility: visible; +} + +.nav-links.nav-active li a { + opacity: 1; +} + +/* footer */ + +@media (min-height: 700px) { + footer { + position: absolute; + bottom: 0; + width: 100%; + border-top: 2px solid rgba(230, 228, 228, 0.5); + } +} + +footer { + width: 100%; + border-top: 2px solid rgba(230, 228, 228, 0.5); + height: 9vh; +} + +.social-icons { + display: flex; + margin-top: 2em; + justify-content: space-evenly; +} + +footer img { + width: 3em; +} + +/* desktop version */ + +@media (min-width: 950px) { + nav { + width: 100%; + display: flex; + height: 10vh; + } + + .brand-title { + font-size: 3.5rem; + } + + .burger { + display: none; + } + + .close-btn { + display: none; + } + + .nav-links { + display: flex; + justify-content: space-evenly; + width: 60%; + padding: 0 1em; + margin: 1em 0 0 0; + height: auto; + background: none; + transform: translateX(0%); + visibility: visible; + } + + .nav-links li a { + padding: 1em 1em; + margin: 0; + opacity: 1; + } + + .nav-links li:hover { + background-color: #f6f6f6; + } + + /* footer */ + + footer.footer { + width: 100%; + position: relative; + max-height: 10vh; + } + + .social-icons { + width: 60%; + margin: 2.5em auto; + justify-content: space-evenly; + } + + footer img { + width: 3.5rem; + } +} diff --git a/public/mainCSS/support.css b/public/mainCSS/support.css new file mode 100644 index 0000000..4d61f30 --- /dev/null +++ b/public/mainCSS/support.css @@ -0,0 +1,68 @@ +.container { + width: 100%; + background-color: #f6f6f6; + padding: 3rem 0; +} + +.intro, +.contact-info { + padding-left: 1.5em; +} + +.intro { + text-align: center; +} + +.heading { + padding-top: 3rem; +} + +.heading { + font-size: 2.7rem; + margin-bottom: 0.5rem; +} + +.sub-heading { + font-size: 2rem; + font-weight: 500; +} + +.title { + font-size: 2.4rem; + font-weight: 700; +} + +.sub-title { + font-size: 2.2rem; + font-weight: 600; +} + +p, +.number { + font-size: 2.1rem; + line-height: 1.5em; +} + +.faculty, +.coordinators { + margin: 4rem auto; +} + +@media (min-width: 900px) { + .container { + width: 90%; + min-height: 80vh; + margin: 0 auto; + text-align: justify; + padding: 3rem 2rem; + } + + .contact-info, + .parts { + display: flex; + } + + .part { + padding: 1em 2em 1em 0.2em; + } +} diff --git a/public/support.html b/public/support.html new file mode 100644 index 0000000..f8301e2 --- /dev/null +++ b/public/support.html @@ -0,0 +1,117 @@ + + + + + + Support | ITER ROBOTICS CLUB + + + + + + +
+ +
+ +
+
+
+

Contact Us

+

We are always here to listen to you

+
+
+
+

Faculty Incharge

+
+

Shaktijeet Mahapatra

+

Associate Professor

+

Room No.221,E-block

+

+ Department of Electronics and
+ Communication Engineering, ITER +

+

Bhubaneswar,Odisha-751030

+

+91- 993 7190 396

+
+
+ +
+

Overall Coordinators

+
+
+

Khitish Kumar Rout

+

+91-977 7619 991

+

Ankit Pattanayak

+

+91-700 8942 992

+

Tashmin Mishra

+

+91-966 8829 114

+
+
+

Subham Kumar

+

+91-903 1690 140

+

Binny Kumari

+

+91-809 3396 217

+

Mukund Mourya

+

+91-700 8197 552

+
+
+
+
+
+
+ + + + + + diff --git a/routes/auth.js b/routes/auth.js new file mode 100644 index 0000000..bd79d9f --- /dev/null +++ b/routes/auth.js @@ -0,0 +1,78 @@ +const express = require("express"), + router = express.Router(), + path = require("path"), + passport = require("passport"), + Joi = require("@hapi/joi"); + +const User = require("../models/user"); +const { checkLoginInfo } = require("../middleware"); + +const schema = Joi.object({ + name: Joi.string().min(3).max(30).required(), + username: Joi.string().min(10).max(12).required(), + email: Joi.string().required().email(), + password: Joi.string().min(8).required(), +}); + +router.get("/", (req, res) => { + res.sendFile(path.join(__dirname + "/../public/index.html")); +}); + +router.get("/register", (req, res) => { + res.render("auth/register"); +}); + +router.post("/register", (req, res) => { + // Validate the data + const { error } = schema.validate(req.body); + if (error) { + const msg = error.details[0].message; + req.flash("error", msg); + console.log(msg); + const { name, username, email } = req.body; + return res.redirect("/register"); + } + + User.register( + new User({ + username: req.body.username, + email: req.body.email, + name: req.body.name, + }), + req.body.password, + (err, user) => { + if (err || !user) { + console.log(err); + req.flash("error", err.message); + return res.render("auth/register"); + } + + passport.authenticate("local")(req, res, () => { + res.redirect("/blogs"); + }); + } + ); +}); + +router.get("/login", (req, res) => { + res.render("auth/login"); +}); + +router.post( + "/login", + checkLoginInfo, + passport.authenticate("local", { + successRedirect: "/blogs", + failureRedirect: "/login", + failureFlash: "Username and password do not match", + }), + (req, res) => {} +); + +router.get("/logout", (req, res) => { + req.logout(); + req.flash("success", "Successfully logged out!"); + res.redirect("/blogs"); +}); + +module.exports = router; diff --git a/routes/blog.js b/routes/blog.js new file mode 100644 index 0000000..a005713 --- /dev/null +++ b/routes/blog.js @@ -0,0 +1,113 @@ +const express = require("express"), + router = express.Router(); + +const Blog = require("../models/blog"); +const { isLoggedIn, checkBlogAuthor } = require("../middleware"); + +// RESTful ROUTES + +// INDEX Route +router.get("/", (req, res) => { + Blog.find({}, (err, blogs) => { + if (err) { + return res.status(404).json({ + error: "Could not get blog posts", + }); + } else { + res.render("blogs/index", { blogs }); + } + }); +}); + +// NEW Route +router.get("/new", isLoggedIn, (req, res) => { + res.render("blogs/new"); +}); + +// CREATE Route +router.post("/", isLoggedIn, (req, res) => { + req.body.blog.body = req.sanitize(req.body.blog.body); + + let title = req.body.blog.title, + body = req.body.blog.body, + image = req.body.blog.image, + author = { + id: req.user._id, + name: req.user.name, + }; + + const blog = new Blog({ + title, + image, + body, + author, + }); + + blog.save((err, blog) => { + if (err || !blog) { + console.log(err); + } else { + console.log("Blog is saved in DB"); + req.flash("Success", "Your blog has been submitted successfully!"); + res.redirect("/blogs"); + } + }); +}); + +// SHOW Route +router.get("/:id", (req, res) => { + Blog.findById(req.params.id, (err, blog) => { + if (err || !blog) { + console.log(err); + req.flash("error", "Sorry! This blog does not exist anymore"); + req.redirect("back"); + } + + res.render("blogs/show", { blog }); + }); +}); + +// EDIT Route +router.get("/:id/edit", isLoggedIn, checkBlogAuthor, (req, res) => { + Blog.findById(req.params.id, (err, blog) => { + if (err) { + res.status(404).json({ + error: "Could not find the blog", + }); + } + + res.render("blogs/edit", { blog }); + }); +}); + +// UPDATE Route +router.put("/:id", isLoggedIn, checkBlogAuthor, (req, res) => { + req.body.blog.body = req.sanitize(req.body.blog.body); + + Blog.findByIdAndUpdate(req.params.id, req.body.blog, (err, blog) => { + if (err || !blog) { + console.log(err); + req.flash("error", "Sorry! Something went wrong."); + return res.redirect("back"); + } + + req.flash("success", "Blog updated successfully!"); + res.redirect("/blogs/" + req.params.id); + }); +}); + +// DELETE Route +router.delete("/:id", isLoggedIn, checkBlogAuthor, (req, res) => { + Blog.findByIdAndRemove(req.params.id, (err) => { + if (err) { + console.log(err); + req.flash("error", "Sorry! Could not delete the blog"); + return res.redirect(`/blogs/${req.params.id}`); + } + + req.flash("error", "Blog deleted successfully"); + res.redirect("/blogs"); + }); +}); + +module.exports = router; diff --git a/views/auth/login.ejs b/views/auth/login.ejs new file mode 100644 index 0000000..64bed86 --- /dev/null +++ b/views/auth/login.ejs @@ -0,0 +1,35 @@ + + + + + + Login + + + + + + + <%- include("../partials/header") %> +
+
+

Login

+
+ <%- include("../partials/message") %> +
+ + + +
+ +
+

Do not have an account?

+ Register +
+
+ + diff --git a/views/auth/register.ejs b/views/auth/register.ejs new file mode 100644 index 0000000..f2da9f4 --- /dev/null +++ b/views/auth/register.ejs @@ -0,0 +1,57 @@ + + + + + + Register + + + + + + + <%- include("../partials/header") %> +
+
+

Create Account

+
+ + <%- include("../partials/message.ejs") %> +
+ + + + + +
+ +
+

Already registered?

+ Login +
+
+ + diff --git a/views/blogs/edit.ejs b/views/blogs/edit.ejs new file mode 100644 index 0000000..1ddc218 --- /dev/null +++ b/views/blogs/edit.ejs @@ -0,0 +1,57 @@ + + + + + + Edit + + + + + + + + + + <%- include("../partials/header") %> + + +
+

New Blog

+ +
+
+ +
+ +
+ +
+ +
+ +
+ +
+
+
+ + diff --git a/views/blogs/index.ejs b/views/blogs/index.ejs new file mode 100644 index 0000000..4915b31 --- /dev/null +++ b/views/blogs/index.ejs @@ -0,0 +1,42 @@ + + + + + + Blogs + + + + + + + <%- include("../partials/header") %> + + +
+ <% blogs.forEach((blog) => { %> +
+

<%= blog.title %>

+ +
+

By <%= blog.author.name %>

+

<%= blog.created.toDateString() %>

+
+ + + +
+ +
+ +
+ Read More + +
+
+ <% }) %> +
+ + diff --git a/views/blogs/new.ejs b/views/blogs/new.ejs new file mode 100644 index 0000000..07fd5a1 --- /dev/null +++ b/views/blogs/new.ejs @@ -0,0 +1,53 @@ + + + + + + New Blog + + + + + + + + + + <%- include("../partials/header") %> + + +
+

New Blog

+ +
+
+ +
+ +
+ +
+ +
+ +
+ +
+
+
+ + diff --git a/views/blogs/show.ejs b/views/blogs/show.ejs new file mode 100644 index 0000000..7b20174 --- /dev/null +++ b/views/blogs/show.ejs @@ -0,0 +1,41 @@ + + + + + + <%= blog.title %> + + + + + + + <%- include("../partials/header") %> + + +
+
+

<%= blog.title %>

+
+
+ <%- blog.body %> +
+
+ +
+

<%= blog.author.name %>

+

<%= blog.created.toDateString() %>

+ +
+ +
+ +
+
+
+ + diff --git a/views/partials/footer.ejs b/views/partials/footer.ejs new file mode 100644 index 0000000..e69de29 diff --git a/views/partials/header.ejs b/views/partials/header.ejs new file mode 100644 index 0000000..b7c818e --- /dev/null +++ b/views/partials/header.ejs @@ -0,0 +1,37 @@ +
+ +
diff --git a/views/partials/message.ejs b/views/partials/message.ejs new file mode 100644 index 0000000..d447812 --- /dev/null +++ b/views/partials/message.ejs @@ -0,0 +1,10 @@ +<% if(success && success.length > 0) { %> +
+

<%= success %>

+
+<% } %> <% if(error && error.length > 0) { %> +
+

<%= error %> +

+
+<% } %>