diff options
-rw-r--r-- | Dockerfile | 4 | ||||
-rw-r--r-- | docker-compose-test.yaml | 25 | ||||
-rw-r--r-- | docker-compose.yaml | 39 | ||||
-rw-r--r-- | model.js | 55 | ||||
-rwxr-xr-x | server.js | 34 | ||||
-rw-r--r-- | static/about.html | 6 | ||||
-rw-r--r-- | views/index.ejs | 8 | ||||
-rw-r--r-- | views/rss_feed.pug | 18 |
8 files changed, 140 insertions, 49 deletions
@@ -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 @@ -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, +}; @@ -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 @@ <a href="https://github.com/terminaldweller/web">here</a> . </p> + <br /> + <br /> + <hr /> + <br /> + <a href="/" class="left-footer">Home</a> + <br /> </body> </html> 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 @@ <title>Blog</title> <link rel="stylesheet" href="/master.css" type="text/css" media="screen" title="no title" charset="utf-8"> <link rel="alternate" type="application/rss+xml" title="RSS" href="/rss/feed"> - <!-- <link rel="alternate" type="application/atom+xml" title="RSS" href="/rss/feed"> --> + <!-- <link rel="alternate" type="application/atom+xml" title="RSS" href="/feed/rss"> --> </head> <body> <!-- <script>0</script> --> @@ -15,6 +15,12 @@ <br/> <hr/> <br/> + <a class="left-footer">Keywords:</a> + <%- data.Keywords %> + <br/> + <br/> + <hr/> + <br/> <a href="/archive" class="left-footer">Archive</a> <a href="/about" class="right-footer">About</a> <a class="right-footer">   </a> 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='<a href="http://www.w3.org/2005/Atom" rel="nofollow">http://www.w3.org/2005/Atom</a>') channel - title DevSmash - link <a href="http://devsmash.com" rel="nofollow">http://devsmash.com</a> - atom:link(href='<a href="http://devsmash.com/feed/rss" rel="nofollow">http://devsmash.com/feed/rss</a>', rel='self', type='application/rss+xml') - description Developers talking about stuff that developers like to talk about. + title deviblog + link <a href="https://blog.terminaldweller.com" rel="nofollow">https://blog.terminaldweller.com</a> + atom:link(href='<a href="https://blog.terminaldweller.com/feed/rss" rel="nofollow">https://blog.terminaldweller.com/feed/rss</a>', 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 <a href="http://devsmash.com/blog/#{post.slug}" rel="nofollow">http://devsmash.com/blog/#{post.slug}</a> + link <a href="https://blog.terminaldweller.com/blog/#{post.slug}" rel="nofollow">https://terminaldweller.com/blog/#{post.slug}</a> description | <![CDATA[ | !{post.teaser} - p: a(href='<a href="http://devsmash.com/blog/#{post.slug}')!=" rel="nofollow">http://devsmash.com/blog/#{post.slug}')!=</a> 'Read more »' + p: a(href='<a href="https://blog.terminaldweller.com/blog/#{post.slug} rel="nofollow">https://blog.terminaldweller.com/blog/#{post.slug}</a>') 'Read more »' | ]]> - pubDate= new Date(post.publishedAt).toUTCString() - guid(isPermaLink='false') <a href="http://devsmash.com/blog/#{post.slug}" + pubDate= new Date(post.lastUpdatedAt).toUTCString() + guid(isPermaLink='false') <a href="https://blog.terminaldweller.com/blog/#{post.slug}" |