isundil 6 년 전
부모
커밋
03361b806b
17개의 변경된 파일267개의 추가작업 그리고 5개의 파일을 삭제
  1. 4 1
      .gitignore
  2. 1 1
      Makefile
  3. 51 0
      app.js
  4. 1 1
      config.js.sample
  5. 12 0
      models/users.js
  6. 12 2
      package.json
  7. 1 0
      public/images/home.svg
  8. 48 0
      public/stylesheets/style.css
  9. 12 0
      routes/index.js
  10. 37 0
      routes/login.js
  11. 10 0
      src/sequelize.js
  12. 22 0
      src/templateArgs.js
  13. 6 0
      views/error.pug
  14. 19 0
      views/include/headbar.pug
  15. 9 0
      views/include/layout.pug
  16. 5 0
      views/index.pug
  17. 17 0
      views/login.pug

+ 4 - 1
.gitignore

@@ -1,2 +1,5 @@
-/src/config.js
+/config.js
 /node_modules
+/bin
+/package-lock.json
+

+ 1 - 1
Makefile

@@ -2,7 +2,7 @@
 SRC=	src/cli/resources.js	\
 		src/cli/ui.js
 
-OUTPUT=	public/script.min.js
+OUTPUT=	public/javascripts/scripts.js
 
 MAPFILE=	${OUTPUT}.map
 

+ 51 - 0
app.js

@@ -0,0 +1,51 @@
+var createError = require('http-errors');
+var express = require('express');
+var path = require('path');
+var cookieParser = require('cookie-parser');
+var logger = require('morgan');
+
+var indexRouter = require('./routes/index');
+var loginRouter = require('./routes/login');
+
+var app = express();
+
+// view engine setup
+app.set('views', path.join(__dirname, 'views'));
+app.set('view engine', 'pug');
+app.set('trust proxy', 1);
+
+app.use(logger('dev'));
+app.use(express.json());
+app.use(express.urlencoded({ extended: false }));
+app.use(cookieParser());
+app.use(require('express-session')({
+    secret: require("./config.js").sessionHash,
+    name: "sessionId",
+    saveUninitialized: false,
+    resave: true
+}));
+app.use(express.static(path.join(__dirname, 'public')));
+
+app.use('/', indexRouter);
+app.use('/login', loginRouter);
+
+// catch 404 and forward to error handler
+app.use(function(req, res, next) {
+  next(createError(404));
+});
+
+// error handler
+app.use(function(err, req, res, next) {
+  // set locals, only providing error in development
+  res.locals.message = err.message;
+  res.locals.error = req.app.get('env') === 'development' ? err : {};
+
+  // render the error page
+  require('./src/templateArgs.js').generate(req).then(args => {
+    res.status(err.status || 500);
+    res.render('error', args);
+  });
+});
+
+module.exports = app;
+

+ 1 - 1
src/config.js.sample → config.js.sample

@@ -1,5 +1,5 @@
 
-modules.EXPORT = {
+module.exports = {
     db: {
         username: "totorobook",
         password: "HackMe",

+ 12 - 0
models/users.js

@@ -0,0 +1,12 @@
+
+module.exports = (sequelize, DataTypes) => {
+    var User = sequelize.define("user", {
+        username: { type: DataTypes.STRING, unique: true },
+        password: { type: DataTypes.STRING }
+    }, {
+        timestamps: true,
+        sequelize });
+    User.sync();
+    return User;
+};
+

+ 12 - 2
package.json

@@ -4,7 +4,7 @@
   "description": "Numeric Book Shelf",
   "main": "index.js",
   "scripts": {
-    "test": "echo \"Error: no test specified\" && exit 1"
+    "start": "node ./bin/www"
   },
   "repository": {
     "type": "git",
@@ -13,6 +13,16 @@
   "author": "isundil",
   "license": "GPL-3.0-or-later",
   "dependencies": {
-    "express": "^4.16.4"
+    "cookie-parser": "~1.4.3",
+    "debug": "~2.6.9",
+    "express": "~4.16.0",
+    "express-session": "^1.16.1",
+    "http-errors": "~1.6.2",
+    "mariadb": "^2.0.3",
+    "morgan": "~1.9.0",
+    "mysql2": "^1.6.5",
+    "pug": "2.0.0-beta11",
+    "sequelize": "^5.7.3",
+    "sha256": "^0.2.0"
   }
 }

+ 1 - 0
public/images/home.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 32 40" x="0px" y="0px"><title>book</title><path d="M28 4v26h-21c-1.657 0-3-1.343-3-3s1.343-3 3-3h19v-24h-20c-2.2 0-4 1.8-4 4v24c0 2.2 1.8 4 4 4h24v-28h-2z"/><path d="M7.002 26v0c-0.001 0-0.001 0-0.002 0-0.552 0-1 0.448-1 1s0.448 1 1 1c0.001 0 0.001-0 0.002-0v0h18.997v-2h-18.997z"/><text x="0" y="47" fill="#000000" font-size="5px" font-weight="bold" font-family="'Helvetica Neue', Helvetica, Arial-Unicode, Arial, Sans-serif">Created by DIVYA A</text><text x="0" y="52" fill="#000000" font-size="5px" font-weight="bold" font-family="'Helvetica Neue', Helvetica, Arial-Unicode, Arial, Sans-serif">from the Noun Project</text></svg>

+ 48 - 0
public/stylesheets/style.css

@@ -0,0 +1,48 @@
+body {
+  padding: 0;
+  margin: 0;
+  font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
+}
+
+a {
+  color: #00B7FF;
+}
+
+#warning-container {
+
+}
+
+nav.menubar {
+  display: flex;
+  padding: .7em 15px;
+  background-color: #707070;
+  font-size: 1.5em;
+}
+
+.menubar ul {
+  padding: 0;
+  margin: 0;
+  display: inline-block;
+}
+
+.menubar .left {
+  flex: 1;
+}
+.menubar .right {
+  flex: 0;
+}
+
+.menubar li {
+  display: inline;
+  list-style-type: none;
+}
+
+.menubar img {
+  height: 1em;
+  vertical-align: middle;
+}
+
+.page {
+  margin: 0 20px;
+}
+

+ 12 - 0
routes/index.js

@@ -0,0 +1,12 @@
+var express = require('express');
+var router = express.Router();
+var templateArgs = require('../src/templateArgs.js');
+
+/* GET home page. */
+router.get('/', function(req, res, next) {
+  templateArgs.generate(req).then(args => {
+    res.render("index", args);
+  });
+});
+
+module.exports = router;

+ 37 - 0
routes/login.js

@@ -0,0 +1,37 @@
+var express = require('express');
+var router = express.Router();
+var templateArgs = require('../src/templateArgs.js');
+var User = require("../src/sequelize.js").User();
+
+function renderLogin(req, res, loginFailure) {
+  templateArgs.generate(req).then(args => {
+    args.title = "Totoro Book - Login";
+    args.failure = !!loginFailure;
+    res.render('login', args);
+  });
+}
+
+router.get('/', (req, res, next) => {
+  if (req.session.userId)
+    res.redirect("/");
+  else
+    renderLogin(req, res);
+});
+
+router.post('/', (req, res) => {
+  User.findAll({
+    where: {
+      username: req.body.username,
+      password: require('sha256')(req.body.password)
+    }
+  }).then(val => {
+    if (val && val[0]) {
+      req.session.userId = val[0].id;
+      res.redirect("/");
+    } else {
+      renderLogin(req, res, true);
+    }
+  });
+});
+
+module.exports = router;

+ 10 - 0
src/sequelize.js

@@ -0,0 +1,10 @@
+
+const config = require("../config.js").db,
+    Sequelize = require("sequelize"),
+    sequelize = new Sequelize(config.database, config.username, config.password, { dialect: "mysql", host: config.server });
+
+module.exports = {
+    sequelize: sequelize,
+    User: function() { return sequelize.import(__dirname + "/../models/users.js"); }
+};
+

+ 22 - 0
src/templateArgs.js

@@ -0,0 +1,22 @@
+
+const User = require("./sequelize.js").User();
+
+module.exports.generate = function(req) {
+  var args = {
+    title: "Totoro Book",
+  };
+  return new Promise((res, rej) => {
+    if (req && req.session && req.session.userId) {
+        User.findAll({ where: { id: req.session.userId }}).then(users => {
+          if (users && users[0]) {
+            args.user = users[0];
+            args.username = args.user.username;
+          }
+          res(args);
+        });
+    } else {
+      res(args);
+    }
+  });
+}
+

+ 6 - 0
views/error.pug

@@ -0,0 +1,6 @@
+extends include/layout
+
+block content
+  h1= message
+  h2= error.status
+  pre #{error.stack}

+ 19 - 0
views/include/headbar.pug

@@ -0,0 +1,19 @@
+block header
+  nav(role='navigation' class='menubar')
+    span(class='left')
+      ul
+        li
+          a(href='/')
+            img(src='images/home.svg')
+    span(class='right')
+      ul
+        if username
+          li
+            input(type='text')
+            a(href='/settings')
+              img(src='images/settings.svg')
+        else
+          li
+            a(href='/login')
+              img(src='images/login.svg')
+

+ 9 - 0
views/include/layout.pug

@@ -0,0 +1,9 @@
+doctype html
+html
+  head
+    title= title
+    link(rel='stylesheet', href='/stylesheets/style.css')
+  body
+    include headbar
+    div(class='page')
+      block content

+ 5 - 0
views/index.pug

@@ -0,0 +1,5 @@
+extends include/layout
+
+block content
+  h1= title
+  p Welcome to #{username}

+ 17 - 0
views/login.pug

@@ -0,0 +1,17 @@
+extends include/layout
+
+block content
+  h1= title
+  p Welcome to #{title}
+
+  form(method='POST')
+    if failure
+      p(class='error') Incorrect Login or Password
+    label
+      span Login
+      input(type='text' name='username')
+    label
+      span Password
+      input(type='password' name='password')
+    input(type='submit')
+