diff --git a/README.md b/README.md index 2893d02..561a4a1 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,30 @@ A satirical blog with its own lightweight CMS, which all runs on [Sapper](https: Requires Node.js and MongoDB -Create a MongoDB database for howfeed +Create a MongoDB database for howfeed: + +```sh +$ mongo +> use howfeed; +``` Set up `.env.example` as `.env` +Then install dependencies and start a local server: + ```sh -npm i -npm run dev +$ npm i +$ npm run dev ``` + +## Usage + +Anyone can sign up for an account, but to designate a certain account as an author so they can publish articles, you will need to set the `author` field to `true` in Mongo: + +```sh +$ mongo +> use howfeed; +> db.users.updateOne({username: 'myuser1'}, {$set:{author: true}}) +``` + +Then the user should logout and log back in. diff --git a/src/client.js b/src/client.js index cec9172..7769029 100644 --- a/src/client.js +++ b/src/client.js @@ -1,5 +1,5 @@ import * as sapper from '@sapper/app'; sapper.start({ - target: document.querySelector('#sapper') -}); \ No newline at end of file + target: document.querySelector('#hydrate') +}); diff --git a/src/components/FakeTweet.svelte b/src/components/FakeTweet.svelte index 1f35fe9..f073135 100644 --- a/src/components/FakeTweet.svelte +++ b/src/components/FakeTweet.svelte @@ -3,7 +3,7 @@ export let author; export let handle; export let avatar; - export let media; + export let media = null; export let likes = 100; export let replies = 100; export let verified; @@ -20,7 +20,1708 @@
diff --git a/src/components/Nav.svelte b/src/components/Nav.svelte index 688ad7c..88e8415 100644 --- a/src/components/Nav.svelte +++ b/src/components/Nav.svelte @@ -56,6 +56,8 @@ {#if !$session.user} {:else} + +
{/if}
diff --git a/src/models/user.js b/src/models/user.js index 721bdb0..cad2bd3 100644 --- a/src/models/user.js +++ b/src/models/user.js @@ -8,7 +8,8 @@ const { Schema } = mongoose; const UserSchema = new Schema({ username: { type: String, required: true, index: { unique: true } }, password: { type: String, required: true }, - realname: { type: String, required: true } + realname: { type: String, required: true }, + author: { type: Boolean, default: false } }); diff --git a/src/routes/cms/index.svelte b/src/routes/cms/index.svelte index b6acdf7..2a9581b 100644 --- a/src/routes/cms/index.svelte +++ b/src/routes/cms/index.svelte @@ -12,9 +12,19 @@ Dashboard | HOWFEED.BIZ + +
-

HowFeed Publisher Dashboard

-

Publish a new article

-

Edit an existing article

-

Delete an article

+ {#if user.author} +

HowFeed Publisher Dashboard

+

Publish a new article

+

Edit an existing article

+

Delete an article

+ {:else} + + {/if}
diff --git a/src/server.js b/src/server.js index 52b3fa5..51c08ec 100644 --- a/src/server.js +++ b/src/server.js @@ -8,6 +8,7 @@ import mongoose from 'mongoose'; import passport from 'passport'; import { Strategy } from 'passport-local'; import sessionFileStore from 'session-file-store'; +import Article from './models/article.js'; import User from './models/user.js'; require('dotenv').config(); @@ -52,7 +53,6 @@ passport.use(new Strategy((username, password, done) => { })); express() - .use(passport.initialize()) .use(bodyParser.json()) .use(bodyParser.urlencoded({ extended: true })) .use(session({ @@ -67,9 +67,11 @@ express() path: '.sessions' }) })) + .use(passport.initialize()) + .use(passport.session()) .post('/cms/register', - (req, res, next) => { + function(req, res, next) { if (!req.user) { next(); } else { @@ -109,6 +111,15 @@ express() })); return false; } + if (!/^[a-z0-9.]+$/i.test(username)) { + res.writeHead(422, { + 'Content-Type': 'application/json' + }); + res.end(JSON.stringify({ + message: `The username can only contain letters, numbers, and periods.` + })); + return false; + } try { const user = await User.findOne({ username: req.body.username }); if (user) { @@ -167,7 +178,27 @@ express() }) .post('/cms/article', - passport.authenticate('local'), + function(req, res, next) { + if (req.user) { + if (req.user.author) { + next(); + } else { + res.writeHead(401, { + 'Content-Type': 'application/json' + }); + res.end(JSON.stringify({ + message: `You are not designated as an author.` + })); + } + } else { + res.writeHead(401, { + 'Content-Type': 'application/json' + }); + res.end(JSON.stringify({ + message: `You are not logged in` + })); + } + }, function(req, res, next) { res.writeHead(200, { 'Content-Type': 'application/json' @@ -175,15 +206,6 @@ express() res.end(JSON.stringify({ message: `ur a faget lol` })); - }, - function(err, req, res, next) { - // handle error - res.writeHead(err.status || 500, { - 'Content-Type': 'application/json' - }); - res.end(JSON.stringify({ - message: err.message - })); } ) diff --git a/src/template.html b/src/template.html index fbcfffb..b388f9d 100644 --- a/src/template.html +++ b/src/template.html @@ -3,7 +3,9 @@ - + + + %sapper.base% @@ -11,7 +13,7 @@ %sapper.head% -
%sapper.html%
+
%sapper.html%
%sapper.scripts% diff --git a/static/ct.jpg b/static/ct.jpg new file mode 100644 index 0000000..55dc0f5 Binary files /dev/null and b/static/ct.jpg differ diff --git a/webpack.config.js b/webpack.config.js index 9613292..1ccbda1 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -24,7 +24,7 @@ module.exports = { options: { dev, hydratable: true, - hotReload: false // pending https://github.com/sveltejs/svelte/issues/2377 + hotReload: true, } } } @@ -39,7 +39,7 @@ module.exports = { 'process.env.NODE_ENV': JSON.stringify(mode) }), ].filter(Boolean), - devtool: dev && 'inline-source-map' + devtool: dev && 'inline-source-map', }, server: { @@ -66,7 +66,7 @@ module.exports = { mode: process.env.NODE_ENV, performance: { hints: false // it doesn't matter if server.js is large - } + }, }, serviceworker: {