瀏覽代碼

started server

Tomi Cvetic 7 年之前
父節點
當前提交
62f9c55e3d
共有 8 個文件被更改,包括 699 次插入27 次删除
  1. 4 0
      .babelrc
  2. 14 1
      package.json
  3. 100 0
      src/restServer/api.js
  4. 4 0
      src/restServer/config/database.js
  5. 23 0
      src/restServer/config/passport.js
  6. 46 0
      src/restServer/models/user.js
  7. 5 0
      src/server.js
  8. 503 26
      yarn.lock

+ 4 - 0
.babelrc

@@ -0,0 +1,4 @@
+{
+  "plugins": [["transform-object-rest-spread", {"useBuiltIns": true}]],
+  "presets": ["latest"]
+}

+ 14 - 1
package.json

@@ -3,12 +3,24 @@
   "version": "0.1.0",
   "private": true,
   "dependencies": {
+    "babel-core": "^6.25.0",
+    "babel-polyfill": "^6.23.0",
+    "babel-preset-latest": "^6.24.1",
+    "babel-register": "^6.24.1",
+    "bcrypt": "^1.0.2",
     "blob": "^0.0.4",
+    "body-parser": "^1.17.2",
     "bootstrap": "3",
     "debug": "^2.6.8",
     "dotenv": "^4.0.0",
+    "express": "^4.15.3",
     "file-saver": "^1.3.3",
+    "jwt-simple": "^0.5.1",
     "moment": "^2.18.1",
+    "mongoose": "^4.11.3",
+    "morgan": "^1.8.2",
+    "passport": "^0.3.2",
+    "passport-jwt": "^2.2.1",
     "react": "^15.5.4",
     "react-dom": "^15.5.4",
     "react-redux": "^5.0.5",
@@ -28,6 +40,7 @@
     "build": "react-scripts build",
     "inline": "node node_modules/html-inline/bin/cmd.js build/index.html -o build/index_inline.html",
     "test": "react-scripts test --env=jsdom",
-    "eject": "react-scripts eject"
+    "eject": "react-scripts eject",
+    "server": "node src/server.js"
   }
 }

+ 100 - 0
src/restServer/api.js

@@ -0,0 +1,100 @@
+import express from 'express'
+import bodyParser from 'body-parser'
+import morgan from 'morgan'
+import mongoose from 'mongoose'
+import passport from 'passport'
+import jwt from 'jwt-simple'
+
+import config from './config/database'
+import { configPassport } from './config/passport'
+import User from './models/user'
+
+const port = process.env.PORT || 8080
+const app = express()
+
+app.use(bodyParser.urlencoded({ extended: false }))
+app.use(bodyParser.json())
+app.use(morgan('dev'))
+app.use(passport.initialize())
+
+app.get('/', (req, res) => {
+  res.send(`Express API at http://localhost:${port}/api`)
+})
+
+mongoose.connect(config.database)
+configPassport(passport)
+const apiRoutes = express.Router()
+
+apiRoutes.post('/signup', (req, res) => {
+  if (!req.body.name || !req.body.password) {
+    res.json({ success: false, msg: 'Please pass name and password.' })
+  } else {
+    const newUser = new User({
+      name: req.body.name,
+      password: req.body.password
+    })
+    newUser.save(err => {
+      if (err) {
+        return res.json({ success: false, msg: 'Username already exists.' })
+      }
+      res.json({ success: true, msg: 'Successfully created user.' })
+    })
+  }
+})
+
+apiRoutes.post('/authenticate', (req, res) => {
+  User.findOne({ name: req.body.name }, (err, user) => {
+    if (err) {
+      throw err
+    }
+    if (!user) {
+      res.send({ success: false, msg: 'Authentication failed. User not found.' })
+    } else {
+      user.comparePassword(req.body.password, (err, isMatch) => {
+        if (isMatch && !err) {
+          const token = jwt.encode(user, config.secret)
+          res.json({ success: true, token: `JWT ${token}` })
+        } else {
+          res.send({ soccess: false, msg: 'Authentication failed. Wrong password.' })
+        }
+      })
+    }
+  })
+})
+
+apiRoutes.get('/memberinfo', passport.authenticate('jwt', { session: false }), (req, res) => {
+  const token = getToken(req.headers)
+  if (token) {
+    const decoded = jwt.decode(token, config.secret)
+    User.findOne({ name: decoded.name }, (err, user) => {
+      if (err) {
+        throw err
+      }
+      if (!user) {
+        return res.status(403).send({ success: false, msg: 'Authentication failed. User not found.' })
+      } else {
+        res.json({ success: true, msg: `Welcome in the member area, ${user.name}!` })
+      }
+    })
+  } else {
+    return res.status(403).send({ success: false, msg: 'No token provided.' })
+  }
+})
+
+function getToken (headers) {
+  if (headers && headers.authorization) {
+    const parted = headers.authorization.split(' ')
+    if (parted.length === 2) {
+      return parted[1]
+    } else {
+      return null
+    }
+  } else {
+    return null
+  }
+}
+
+app.use('/api', apiRoutes)
+
+app.listen(port)
+console.log('Server running.')

+ 4 - 0
src/restServer/config/database.js

@@ -0,0 +1,4 @@
+export default {
+  secret: 'CNXSp8Zc7LpTTdpJ',
+  database: 'mongodb://localhost/sztm'
+}

+ 23 - 0
src/restServer/config/passport.js

@@ -0,0 +1,23 @@
+import { Strategy, ExtractJwt } from 'passport-jwt'
+import User from '../models/user'
+import config from '../config/database'
+
+function configPassport (passport) {
+  const opts = {}
+  opts.secretOrKey = config.secret
+  opts.jwtFromRequest = ExtractJwt.fromAuthHeader()
+  passport.use(new Strategy(opts, (jwtPayload, done) => {
+    User.findOne({ id: jwtPayload.id }, (err, user) => {
+      if (err) {
+        return done(err, false)
+      }
+      if (user) {
+        done(null, user)
+      } else {
+        done(null, false)
+      }
+    })
+  }))
+}
+
+export { configPassport }

+ 46 - 0
src/restServer/models/user.js

@@ -0,0 +1,46 @@
+import mongoose from 'mongoose'
+import bcrypt from 'bcrypt'
+
+const UserSchema = new mongoose.Schema({
+  name: {
+    type: String,
+    unique: true,
+    required: true
+  },
+  password: {
+    type: String,
+    required: true
+  }
+})
+
+UserSchema.pre('save', function (next) {
+  if (this.isModified('password') || this.isNew) {
+    bcrypt.genSalt(10, (err, salt) => {
+      if (err) {
+        return next(err)
+      }
+      bcrypt.hash(this.password, salt, (err, hash) => {
+        if (err) {
+          return next(err)
+        }
+        this.password = hash
+        next()
+      })
+    })
+  } else {
+    return next()
+  }
+})
+
+UserSchema.methods.comparePassword = function (passwd, cb) {
+  bcrypt.compare(passwd, this.password, (err, isMatch) => {
+    if (err) {
+      return cb(err)
+    }
+    cb(null, isMatch)
+  })
+}
+
+const User = mongoose.model('User', UserSchema)
+
+export default User

+ 5 - 0
src/server.js

@@ -0,0 +1,5 @@
+'use strict'
+require('babel-register')
+require('babel-polyfill')
+require('dotenv').config()
+require('./restServer/api.js')

文件差異過大導致無法顯示
+ 503 - 26
yarn.lock


部分文件因文件數量過多而無法顯示