From 4eaa437c0a285c617e30a533d1ef369eaa8644a6 Mon Sep 17 00:00:00 2001 From: terminaldweller Date: Tue, 5 Jul 2022 20:19:16 +0430 Subject: WIP, adding rss to the blog --- Dockerfile | 4 ++-- docker-compose-test.yaml | 25 ++++++++++++---------- docker-compose.yaml | 39 ++++++++++++++++++++++++++++++---- model.js | 55 ++++++++++++++++++++++++++++++++++++------------ server.js | 34 ++++++++++++++++++++++-------- static/about.html | 6 ++++++ views/index.ejs | 8 ++++++- views/rss_feed.pug | 18 ++++++++-------- 8 files changed, 140 insertions(+), 49 deletions(-) diff --git a/Dockerfile b/Dockerfile index 23e5984..551946e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,7 +3,7 @@ RUN apk add openssl WORKDIR /certs RUN openssl req -nodes -new -x509 -subj="/C=US/ST=Denial/L=springfield/O=Dis/CN=localhost" -keyout server.key -out server.cert -FROM node:lts-alpine3.13 +FROM node:lts-alpine3.15 COPY --from=certbuilder /certs/ /certs COPY ./package.* /server/ RUN cd /server && npm install --production @@ -11,6 +11,6 @@ COPY ./css /server/css/ COPY ./views /server/views/ COPY ./static /server/static/ COPY ./mds /server/mds/ -COPY ./server.js /server/ +COPY ./*.js /server/ ENTRYPOINT ["/server/server.js"] EXPOSE 9000 diff --git a/docker-compose-test.yaml b/docker-compose-test.yaml index 243b282..fceb9b9 100644 --- a/docker-compose-test.yaml +++ b/docker-compose-test.yaml @@ -1,11 +1,11 @@ version: "3.7" services: - web: - image: web + blog: + image: blog build: - context: ./ + context: . networks: - - webnet + - blognet - dbnet ports: - "19009:9000" @@ -16,30 +16,33 @@ services: - SERVER_LISTEN_PORT=9000 depends_on: - mongo + secrets: + - mongo_user + - mongo_pass mongo: image: mongo:5.0 networks: - dbnet restart: on-failure ports: - - "27117:27017" + - "127.0.0.1:27117:27017" - "127.0.0.1:27118:27018" - "127.0.0.1:27119:27019" volumes: - - db-data:/data/db - env: + - blog-data:/data/db + environment: - MONGO_INITDB_ROOT_USERNAME_FILE=/run/secrets/mongo_user - MONGO_INITDB_ROOT_PASSWORD_FILE=/run/secrets/mongo_pass secrets: - mongo_user - mongo_pass networks: - webnet: + blognet: dbnet: volumes: - db-data: + blog-data: secrets: mongo_user: - file: ./mongo_user + file: ./mongo_secrets/mongo_user mongo_pass: - file: ./mongo_pass + file: ./mongo_secrets/mongo_pass diff --git a/docker-compose.yaml b/docker-compose.yaml index 5f3e217..79e5d0c 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,11 +1,12 @@ version: "3.7" services: - web: - image: web + blog: + image: blog build: context: ./ networks: - - webnet + - blognet + - dbnet restart: unless-stopped ports: - "9000:9000" @@ -16,5 +17,35 @@ services: environment: - SERVER_DEPLOYMENT_TYPE=deployment - SERVER_LISTEN_PORT=9000 + depends_on: + - mongo + secrets: + - mongo_user + - mongo_pass + mongo: + image: mongo:5.0 + networks: + - dbnet + restart: on-failure + ports: + - "127.0.0.1:27117:27017" + - "127.0.0.1:27118:27018" + - "127.0.0.1:27119:27019" + volumes: + - blog-data:/data/db + environment: + - MONGO_INITDB_ROOT_USERNAME_FILE=/run/secrets/mongo_user + - MONGO_INITDB_ROOT_PASSWORD_FILE=/run/secrets/mongo_pass + secrets: + - mongo_user + - mongo_pass networks: - webnet: + blognet: + dbnet: +volumes: + blog-data: +secrets: + mongo_user: + file: ./mongo_secrets/mongo_user + mongo_pass: + file: ./mongo_secrets/mongo_pass diff --git a/model.js b/model.js index 7eba2a4..d4bfc83 100644 --- a/model.js +++ b/model.js @@ -1,22 +1,30 @@ "use strict"; +const fs = require("fs"); +const path = require("path"); const mongoose = require("mongoose"); +const Schema = mongoose.Schema; mongoose.Promise = global.Promise; const db = {}; db.mongoose = mongoose; -db.url = "mongo:27017"; +const db_pass = fs.readFileSync("/run/secrets/mongo_pass").toString(); +const db_user = fs.readFileSync("/run/secrets/mongo_user").toString(); +db.url = "mongodb://" + db_user + ":" + db_pass + "@mongo:27017"; -const blogPostModel = mongoose.model( - "blogPost", - mongoose.Schema( - { - title: String, - description: String, - published: Boolean, - }, - { timestamps: true } - ) -); +const BlogPostSchema = new Schema({ + title: { type: String, required: true, trim: true }, + slug: { type: String, required: true, lowercase: true, trim: true }, + body: { type: String, required: true }, + teaser: { type: String, required: true }, + keywords: { type: Array, required: true }, + lastUpdatedAt: { type: Number }, +}); + +// a simple hook to update the timestamp(lastUpdatedAt) on update +BlogPostSchema.pre("save", function (next) { + this.lastUpdatedAt = Date.now(); + next(); +}); function dbInit() { db.mongoose @@ -29,4 +37,25 @@ function dbInit() { process.exit(1); }); } -module.exports = dbInit; + +function populateDB(model) { + let filePaths = fs.readdirSync(path.join(__dirname, "mds")); + filePaths.forEach((fileName) => { + let fileContent = fs + .readFileSync(path.join(__dirname, "mds", fileName), "utf-8") + .toString(); + let newBlogPost = new model({ + title: fileName, + slug: "slug", + body: fileContent, + teaser: "teaser", + keywords: ["kw1", "kw2"], + }); + newBlogPost.save(); + }); +} +module.exports = { + blogPost: mongoose.model("BlogPost", BlogPostSchema), + dbInit: dbInit, + populateDB: populateDB, +}; diff --git a/server.js b/server.js index a42072f..bd23a1f 100755 --- a/server.js +++ b/server.js @@ -22,15 +22,23 @@ const mit = require("markdown-it")({ html: true }) const spdy = require("spdy"); const helmet = require("helmet"); const morgan = require("morgan"); -const pug = require("pug"); +// const pug = require("pug"); +const model = require("./model"); + +model.dbInit(); +model.populateDB(model.blogPost); const app = express(); app.disable("x-powered-by"); app.use(express.static(path.join(__dirname, "css"))); app.use(express.static(path.join(__dirname, "static"))); app.set("views", path.join(__dirname, "views")); +// app.set("view engine", "ejs"); +// app.engine("ejs", require("ejs").__express); +// app.engine("pug", require("pug").renderFilej); +// app.engine("pug", "pug"); app.set("view engine", "ejs"); -app.engine("ejs", require("ejs").__express); +app.set("view engine", "pug"); app.use(helmet.crossOriginEmbedderPolicy()); app.use(helmet.crossOriginOpenerPolicy()); @@ -85,7 +93,7 @@ function renderAndSend(req, res) { ); //FIXME-this can obviously fail readStream.on("data", (chunk) => { - res.render("index", { + res.render("index.ejs", { cache: true, data: { blogHttp: mit.render(chunk), @@ -111,7 +119,7 @@ app.get("/about", (req, res) => { app.get("/archive", (req, res) => { res.type("text/html"); - res.render("archive", { + res.render("archive.ejs", { cache: true, data: { mds: fs.readdirSync(path.join(__dirname, "mds"), "utf-8"), @@ -129,11 +137,19 @@ app.get("/robots.txt", (req, res) => { }); app.get("/rss/feed", (req, res) => { - const compiledFunction = pug.compileFile("./views/rss_feed.pug"); - const files = fs.readdirSync(path.join(__dirname, "mds")); - for (const file of files) { - res.send(compiledFunction(file)); - } + model.blogPost + .find({}) + .sort("-lastUpdatedAt") + .select("title slug lastUpdatedAt teaser") + .exec(function (err, posts) { + if (err) return err; + return res.render("rss_feed.pug", { cache: true, posts: posts }); + }); + // const compiledFunction = pug.compileFile("./views/rss_feed.pug"); + // const files = fs.readdirSync(path.join(__dirname, "mds")); + // for (const file of files) { + // res.send(compiledFunction(file)); + // } }); app.get("/$", (req, res) => { diff --git a/static/about.html b/static/about.html index b6bdfa9..a56ad24 100644 --- a/static/about.html +++ b/static/about.html @@ -25,5 +25,11 @@ here .

+
+
+
+
+ Home +
diff --git a/views/index.ejs b/views/index.ejs index 6cc3a45..0e47f53 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -6,7 +6,7 @@ Blog - + @@ -15,6 +15,12 @@


+ Keywords: + <%- data.Keywords %> +
+
+
+
Archive About     diff --git a/views/rss_feed.pug b/views/rss_feed.pug index 9bdd9bd..0ae2b74 100644 --- a/views/rss_feed.pug +++ b/views/rss_feed.pug @@ -1,21 +1,21 @@ doctype xml rss(version='2.0', xmlns:atom='http://www.w3.org/2005/Atom') channel - title DevSmash - link http://devsmash.com - atom:link(href='http://devsmash.com/feed/rss', rel='self', type='application/rss+xml') - description Developers talking about stuff that developers like to talk about. + title deviblog + link https://blog.terminaldweller.com + atom:link(href='https://blog.terminaldweller.com/feed/rss', rel='self', type='application/rss+xml') + description I talk about software here. language en-US if posts.length - lastBuildDate= new Date(posts[0].publishedAt).toUTCString() + lastBuildDate= new Date(posts[0].lastUpdatedAt).toUTCString() each post in posts item title= post.title - link http://devsmash.com/blog/#{post.slug} + link https://terminaldweller.com/blog/#{post.slug} description | http://devsmash.com/blog/#{post.slug}')!= 'Read more »' + p: a(href='https://blog.terminaldweller.com/blog/#{post.slug}') 'Read more »' | ]]> - pubDate= new Date(post.publishedAt).toUTCString() - guid(isPermaLink='false')