decoupled backend
This commit is contained in:
parent
e538eab674
commit
ffb7dd8da6
23 changed files with 3053 additions and 221 deletions
|
@ -1,19 +0,0 @@
|
||||||
# node stuff
|
|
||||||
node_modules
|
|
||||||
npm-debug.log
|
|
||||||
|
|
||||||
# big files
|
|
||||||
**/*.xcf
|
|
||||||
**/*.bundle.js
|
|
||||||
|
|
||||||
# docker stuff
|
|
||||||
Dockerfile
|
|
||||||
.dockerignore
|
|
||||||
docker-compose.yml
|
|
||||||
|
|
||||||
# container volumes
|
|
||||||
src
|
|
||||||
views
|
|
||||||
public_html
|
|
||||||
inc
|
|
||||||
server.coffee
|
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1 +1 @@
|
||||||
**/*.bundle.js
|
**/node_modules
|
||||||
|
|
16
Dockerfile
16
Dockerfile
|
@ -1,16 +0,0 @@
|
||||||
FROM node:latest
|
|
||||||
|
|
||||||
# some dir for our code
|
|
||||||
WORKDIR /app
|
|
||||||
# container port
|
|
||||||
EXPOSE 3000
|
|
||||||
|
|
||||||
# install dependencies
|
|
||||||
COPY package*.json .
|
|
||||||
RUN yarn
|
|
||||||
|
|
||||||
# copy code
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
# this is how we start
|
|
||||||
CMD ["yarn", "start"]
|
|
30
Makefile
Normal file
30
Makefile
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
COMPOSE:=sudo docker-compose
|
||||||
|
|
||||||
|
.PHONY: all
|
||||||
|
all: develop
|
||||||
|
|
||||||
|
%/node_modules/.yarn-integrity:
|
||||||
|
$(eval image:=$(patsubst %/node_modules/.yarn-integrity,%,$@))
|
||||||
|
$(COMPOSE) build $(image)
|
||||||
|
$(COMPOSE) run --rm $(image) yarn install --production=false
|
||||||
|
|
||||||
|
DFILES:=$(wildcard */Dockerfile)
|
||||||
|
IMAGES:=$(patsubst %/Dockerfile,%,$(DFILES))
|
||||||
|
|
||||||
|
.PHONY: develop
|
||||||
|
develop: $(patsubst %,%/node_modules/.yarn-integrity,$(IMAGES))
|
||||||
|
$(COMPOSE) up
|
||||||
|
|
||||||
|
.PHONY: production
|
||||||
|
production:
|
||||||
|
$(COMPOSE) -f docker-compose.yml -f docker-compose.prod.yml build
|
||||||
|
$(COMPOSE) -f docker-compose.yml -f docker-compose.prod.yml up -d
|
||||||
|
|
||||||
|
.PHONY: fe-init fe-init-simple
|
||||||
|
fe-init:
|
||||||
|
$(COMPOSE) build frontend
|
||||||
|
$(COMPOSE) run --rm frontend vue init bootstrap-vue/webpack .
|
||||||
|
|
||||||
|
fe-init-simple:
|
||||||
|
$(COMPOSE) build frontend
|
||||||
|
$(COMPOSE) run --rm frontend vue init bootstrap-vue/webpack-simple .
|
7
backend/.dockerignore
Normal file
7
backend/.dockerignore
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# node stuff
|
||||||
|
node_modules
|
||||||
|
npm-debug.log
|
||||||
|
|
||||||
|
# Docker stuff
|
||||||
|
Dockerfile
|
||||||
|
.dockerignore
|
22
backend/Dockerfile
Normal file
22
backend/Dockerfile
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
FROM node:lts AS dev
|
||||||
|
ENV NODE_ENV development
|
||||||
|
# some dir for our code
|
||||||
|
WORKDIR /app
|
||||||
|
# mount code
|
||||||
|
VOLUME ["/app"]
|
||||||
|
# this is how we start
|
||||||
|
CMD [ "yarn", "dev" ]
|
||||||
|
|
||||||
|
|
||||||
|
FROM node:lts-alpine AS prod
|
||||||
|
ENV NODE_ENV production
|
||||||
|
# some dir for our code
|
||||||
|
WORKDIR /app
|
||||||
|
# install dependencies
|
||||||
|
COPY package*.json yarn*.lock ./
|
||||||
|
RUN yarn --production
|
||||||
|
# copy code
|
||||||
|
COPY . .
|
||||||
|
USER node
|
||||||
|
# this is how we start
|
||||||
|
CMD [ "yarn", "start" ]
|
|
@ -1,7 +1,7 @@
|
||||||
# libraries
|
# libraries
|
||||||
bcrypt = (require 'bcrypt')
|
bcrypt = (require 'bcrypt')
|
||||||
sqlite3 = (require 'sqlite3').verbose()
|
sqlite3 = (require 'sqlite3').verbose()
|
||||||
FFTCGLOG = new (require './console')('FFTCGDB')
|
logger = (require 'logging').default 'db'
|
||||||
|
|
||||||
# bruteforce countermeasure
|
# bruteforce countermeasure
|
||||||
saltRounds = 13
|
saltRounds = 13
|
||||||
|
@ -12,17 +12,17 @@ FFTCGDB = (filename, truncate) ->
|
||||||
|
|
||||||
@db = new sqlite3.Database @filename, (err) ->
|
@db = new sqlite3.Database @filename, (err) ->
|
||||||
if err
|
if err
|
||||||
FFTCGLOG.error err.message
|
logger.error err.message
|
||||||
|
|
||||||
else
|
else
|
||||||
FFTCGLOG.log "Connected to '#{that.filename}'"
|
logger.info "Connected to '#{that.filename}'"
|
||||||
|
|
||||||
that.db.run 'PRAGMA foreign_keys = ON;', (err) ->
|
that.db.run 'PRAGMA foreign_keys = ON;', (err) ->
|
||||||
FFTCGLOG.error err.message if err
|
logger.error err.message if err
|
||||||
|
|
||||||
if truncate == true
|
if truncate == true
|
||||||
that.db.run 'DROP TABLE IF EXISTS users;', (err) ->
|
that.db.run 'DROP TABLE IF EXISTS users;', (err) ->
|
||||||
FFTCGLOG.error err.message if err
|
logger.error err.message if err
|
||||||
that.db.run '''
|
that.db.run '''
|
||||||
CREATE TABLE users (
|
CREATE TABLE users (
|
||||||
user integer PRIMARY KEY,
|
user integer PRIMARY KEY,
|
||||||
|
@ -34,7 +34,7 @@ FFTCGDB = (filename, truncate) ->
|
||||||
FFTCGLOG.error err.message if err
|
FFTCGLOG.error err.message if err
|
||||||
|
|
||||||
that.db.run 'DROP TABLE IF EXISTS decks;', (err) ->
|
that.db.run 'DROP TABLE IF EXISTS decks;', (err) ->
|
||||||
FFTCGLOG.error err.message if err
|
logger.error err.message if err
|
||||||
that.db.run '''
|
that.db.run '''
|
||||||
CREATE TABLE decks (
|
CREATE TABLE decks (
|
||||||
deck integer PRIMARY KEY,
|
deck integer PRIMARY KEY,
|
||||||
|
@ -44,20 +44,21 @@ FFTCGDB = (filename, truncate) ->
|
||||||
ON DELETE CASCADE
|
ON DELETE CASCADE
|
||||||
);
|
);
|
||||||
''', (err) ->
|
''', (err) ->
|
||||||
FFTCGLOG.error err.message if err
|
logger.error err.message if err
|
||||||
|
|
||||||
FFTCGLOG.log 'recreated DB'
|
logger.info 'recreated DB'
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
FFTCGDB::close = ->
|
FFTCGDB::close = ->
|
||||||
|
logger.info 'shutting down'
|
||||||
new Promise (resolve, reject) ->
|
new Promise (resolve, reject) ->
|
||||||
@db.close (err) ->
|
@db.close (err) ->
|
||||||
if err
|
if err
|
||||||
FFTCGLOG.log "Error closing: '#{err.message}'"
|
logger.error "Error closing: '#{err.message}'"
|
||||||
resolve 'ok'
|
resolve 'ok'
|
||||||
else
|
else
|
||||||
FFTCGLOG.error "Closed '#{@filename}'"
|
logger.warn "Closed '#{@filename}'"
|
||||||
reject 'db'
|
reject 'db'
|
||||||
|
|
||||||
FFTCGDB::register = (login, password) ->
|
FFTCGDB::register = (login, password) ->
|
||||||
|
@ -67,26 +68,26 @@ FFTCGDB::register = (login, password) ->
|
||||||
# validate user input
|
# validate user input
|
||||||
if login == '' or password == ''
|
if login == '' or password == ''
|
||||||
# no user name or password given
|
# no user name or password given
|
||||||
FFTCGLOG.log "reg: user name '#{login}' or password empty"
|
logger.info "reg: user name '#{login}' or password empty"
|
||||||
reject 'invalid'
|
reject 'invalid'
|
||||||
|
|
||||||
# hash password
|
# hash password
|
||||||
bcrypt.hash password, saltRounds, (err, hash) ->
|
bcrypt.hash password, saltRounds, (err, hash) ->
|
||||||
if err
|
if err
|
||||||
FFTCGLOG.log "reg: hash fail for name '#{login}'"
|
logger.info "reg: hash fail for name '#{login}'"
|
||||||
reject 'hash'
|
reject 'hash'
|
||||||
|
|
||||||
# try creating row in users table
|
# try creating row in users table
|
||||||
stmt = that.db.prepare 'INSERT INTO users (login, pwdhash) VALUES (?, ?)'
|
stmt = that.db.prepare 'INSERT INTO users (login, pwdhash) VALUES (?, ?)'
|
||||||
stmt.run [login, hash], (err) ->
|
stmt.run [login, hash], (err) ->
|
||||||
if err
|
if err
|
||||||
FFTCGLOG.log "reg: DB fail '#{err.code}' for name '#{login}'"
|
logger.warn "reg: DB fail '#{err.code}' for name '#{login}'"
|
||||||
stmt.finalize()
|
stmt.finalize()
|
||||||
# reduce attack surface, don't disclose user names
|
# reduce attack surface, don't disclose user names
|
||||||
reject 'db' # user already exists
|
reject 'db' # user already exists
|
||||||
|
|
||||||
else
|
else
|
||||||
FFTCGLOG.log "reg: OK '#{login}'"
|
logger.info "reg: OK '#{login}'"
|
||||||
stmt.finalize()
|
stmt.finalize()
|
||||||
# registration successful
|
# registration successful
|
||||||
resolve
|
resolve
|
||||||
|
@ -101,14 +102,14 @@ FFTCGDB::login = (login, password) ->
|
||||||
stmt = that.db.prepare 'SELECT user, login, pwdhash FROM users WHERE login = ?'
|
stmt = that.db.prepare 'SELECT user, login, pwdhash FROM users WHERE login = ?'
|
||||||
stmt.get [login], (err, row) ->
|
stmt.get [login], (err, row) ->
|
||||||
if err
|
if err
|
||||||
FFTCGLOG.log "login: DB fail '#{err.code}' for name '#{login}'"
|
logger.warn "login: DB fail '#{err.code}' for name '#{login}'"
|
||||||
stmt.finalize()
|
stmt.finalize()
|
||||||
reject 'db'
|
reject 'db'
|
||||||
|
|
||||||
else if not row
|
else if not row
|
||||||
# hash the password for timing attack reasons
|
# hash the password for timing attack reasons
|
||||||
bcrypt.hash password, saltRounds, (err, hash) ->
|
bcrypt.hash password, saltRounds, (err, hash) ->
|
||||||
FFTCGLOG.log "login: nonexistent '#{login}'"
|
logger.debug "login: nonexistent '#{login}'"
|
||||||
stmt.finalize()
|
stmt.finalize()
|
||||||
# reduce attack surface, don't disclose user names
|
# reduce attack surface, don't disclose user names
|
||||||
reject 'login' # user doesnt exist
|
reject 'login' # user doesnt exist
|
||||||
|
@ -116,11 +117,11 @@ FFTCGDB::login = (login, password) ->
|
||||||
else
|
else
|
||||||
bcrypt.compare password, row.pwdhash, (err, res) ->
|
bcrypt.compare password, row.pwdhash, (err, res) ->
|
||||||
if err
|
if err
|
||||||
FFTCGLOG.log "login: hash fail for name '#{login}'"
|
logger.info "login: hash fail for name '#{login}'"
|
||||||
reject 'hash'
|
reject 'hash'
|
||||||
|
|
||||||
if res == true
|
if res == true
|
||||||
FFTCGLOG.log "login: OK '#{row.login}'"
|
logger.debug "login: OK '#{row.login}'"
|
||||||
stmt.finalize()
|
stmt.finalize()
|
||||||
# login successful
|
# login successful
|
||||||
resolve
|
resolve
|
||||||
|
@ -128,7 +129,7 @@ FFTCGDB::login = (login, password) ->
|
||||||
login: row.login
|
login: row.login
|
||||||
|
|
||||||
else
|
else
|
||||||
FFTCGLOG.log "login: wrong password for '#{login}'"
|
logger.debug "login: wrong password for '#{login}'"
|
||||||
stmt.finalize()
|
stmt.finalize()
|
||||||
# login failed
|
# login failed
|
||||||
reject 'login'
|
reject 'login'
|
||||||
|
@ -141,7 +142,7 @@ FFTCGDB::addDeck = (user, deckCards) ->
|
||||||
stmt = that.db.prepare 'INSERT INTO decks (user, json) VALUES (?, ?)'
|
stmt = that.db.prepare 'INSERT INTO decks (user, json) VALUES (?, ?)'
|
||||||
stmt.run [user, JSON.stringify deckCards], (err) ->
|
stmt.run [user, JSON.stringify deckCards], (err) ->
|
||||||
if err
|
if err
|
||||||
FFTCGLOG.log "addDeck: DB fail '#{err.code}' for id '#{user}'"
|
logger.warn "addDeck: DB fail '#{err.code}' for id '#{user}'"
|
||||||
stmt.finalize()
|
stmt.finalize()
|
||||||
reject 'db'
|
reject 'db'
|
||||||
|
|
||||||
|
@ -163,7 +164,7 @@ FFTCGDB::modDeck = (deckID, deckCards) ->
|
||||||
stmt.run [deckID], (err) ->
|
stmt.run [deckID], (err) ->
|
||||||
stmt.finalize()
|
stmt.finalize()
|
||||||
if err
|
if err
|
||||||
FFTCGLOG.log "modDeck: DB fail '#{err.code}' for deck '#{deckID}'"
|
logger.warn "modDeck: DB fail '#{err.code}' for deck '#{deckID}'"
|
||||||
reject 'db'
|
reject 'db'
|
||||||
else
|
else
|
||||||
stmt = that.db.prepare 'INSERT INTO decks_cards (deck, card, quant) VALUES (?, ?, ?)'
|
stmt = that.db.prepare 'INSERT INTO decks_cards (deck, card, quant) VALUES (?, ?, ?)'
|
||||||
|
@ -174,14 +175,14 @@ FFTCGDB::modDeck = (deckID, deckCards) ->
|
||||||
deckCards.forEach (card) ->
|
deckCards.forEach (card) ->
|
||||||
stmt.run [deckID, card.id, card.quant], (err) ->
|
stmt.run [deckID, card.id, card.quant], (err) ->
|
||||||
if err
|
if err
|
||||||
FFTCGLOG.log "modDeck: DB fail '#{err.code}' for card '#{deckID}', '#{card.id}', '#{card.quant}'"
|
logger.warn "modDeck: DB fail '#{err.code}' for card '#{deckID}', '#{card.id}', '#{card.quant}'"
|
||||||
stmt.finalize()
|
stmt.finalize()
|
||||||
reject 'db'
|
reject 'db'
|
||||||
else
|
else
|
||||||
# check if all queries are done
|
# check if all queries are done
|
||||||
promiseCount -= 1
|
promiseCount -= 1
|
||||||
if promiseCount == 0
|
if promiseCount == 0
|
||||||
FFTCGLOG.log "modDeck: OK '#{deckID}'"
|
logger.debug "modDeck: OK '#{deckID}'"
|
||||||
stmt.finalize()
|
stmt.finalize()
|
||||||
resolve deckID
|
resolve deckID
|
||||||
|
|
||||||
|
@ -195,10 +196,10 @@ FFTCGDB::getDecks = (user) ->
|
||||||
stmt.all [user], (err, rows) ->
|
stmt.all [user], (err, rows) ->
|
||||||
stmt.finalize()
|
stmt.finalize()
|
||||||
if err
|
if err
|
||||||
FFTCGLOG.log "getDeck: DB fail '#{err.code}' for deck '#{deckID}'"
|
logger.warn "getDeck: DB fail '#{err.code}' for deck '#{deckID}'"
|
||||||
reject 'db'
|
reject 'db'
|
||||||
else
|
else
|
||||||
FFTCGLOG.log "getDeck: OK '#{deckID}'"
|
logger.debug "getDeck: OK '#{deckID}'"
|
||||||
for row in rows
|
for row in rows
|
||||||
decks[row.deck] = JSON.parse row.json
|
decks[row.deck] = JSON.parse row.json
|
||||||
resolve decks
|
resolve decks
|
||||||
|
@ -212,10 +213,10 @@ FFTCGDB::delDeck = (deckID) ->
|
||||||
stmt.run [deckID], (err) ->
|
stmt.run [deckID], (err) ->
|
||||||
stmt.finalize()
|
stmt.finalize()
|
||||||
if err
|
if err
|
||||||
FFTCGLOG.log "delDeck: DB fail '#{err.code}' for deck '#{deckID}'"
|
logger.warn "delDeck: DB fail '#{err.code}' for deck '#{deckID}'"
|
||||||
reject 'db'
|
reject 'db'
|
||||||
else
|
else
|
||||||
FFTCGLOG.log "delDeck: OK '#{deckID}'"
|
logger.debug "delDeck: OK '#{deckID}'"
|
||||||
resolve deckID
|
resolve deckID
|
||||||
|
|
||||||
|
|
0
backend/fftcg.db
Normal file
0
backend/fftcg.db
Normal file
31
backend/package.json
Normal file
31
backend/package.json
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
{
|
||||||
|
"name": "node-fftcg",
|
||||||
|
"version": "0.0.3",
|
||||||
|
"description": "FFTCG online using Socket.IO and CraftyJS on Node.js on Docker",
|
||||||
|
"author": "JMM <jmm@yavook.de>",
|
||||||
|
"main": "server.coffee",
|
||||||
|
"private": true,
|
||||||
|
"license": "UNLICENSED",
|
||||||
|
"scripts": {
|
||||||
|
"start": "coffee server.coffee",
|
||||||
|
"dev": "nodemon",
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"nodemon": "^1.18.9"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"bcrypt": "^3.0.4",
|
||||||
|
"coffeescript": "^2.3.2",
|
||||||
|
"connect-redis": "^3.4.0",
|
||||||
|
"cors": "^2.8.5",
|
||||||
|
"express": "^4.16.4",
|
||||||
|
"express-session": "^1.15.6",
|
||||||
|
"express-socket.io-session": "^1.3.5",
|
||||||
|
"helmet": "^3.15.0",
|
||||||
|
"logging": "^3.2.0",
|
||||||
|
"socket.io": "^2.2.0",
|
||||||
|
"socket.io-client": "^2.2.0",
|
||||||
|
"sqlite3": "^4.0.4"
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,10 +4,10 @@ path = (require 'path')
|
||||||
|
|
||||||
# my libraries
|
# my libraries
|
||||||
FFTCGDB = (require './db')
|
FFTCGDB = (require './db')
|
||||||
FFTCGLOG = new (require './console')('FFTCGROUTER')
|
logger = (require 'logging').default 'router'
|
||||||
|
|
||||||
# open fftcg db
|
# open fftcg db
|
||||||
fftcgdb = new FFTCGDB path.resolve(__dirname, '../fftcg.db')
|
fftcgdb = new FFTCGDB path.resolve(__dirname, 'fftcg.db')
|
||||||
|
|
||||||
# create router
|
# create router
|
||||||
FFTCGROUTER = express.Router()
|
FFTCGROUTER = express.Router()
|
||||||
|
@ -15,15 +15,12 @@ FFTCGROUTER = express.Router()
|
||||||
# request logging
|
# request logging
|
||||||
FFTCGROUTER.use (req, res, next) ->
|
FFTCGROUTER.use (req, res, next) ->
|
||||||
if req.session.user
|
if req.session.user
|
||||||
FFTCGLOG.log "user '#{req.session.user.login}' requested '#{req.url}'"
|
logger.debug "user '#{req.session.user.login}' requested '#{req.url}'"
|
||||||
else
|
else
|
||||||
FFTCGLOG.log "requested '#{req.url}'"
|
logger.debug "requested '#{req.url}'"
|
||||||
|
|
||||||
next()
|
next()
|
||||||
|
|
||||||
# static content
|
|
||||||
FFTCGROUTER.use express.static path.resolve(__dirname, '../public_html')
|
|
||||||
|
|
||||||
# register user
|
# register user
|
||||||
FFTCGROUTER.post '/register', (req, res) ->
|
FFTCGROUTER.post '/register', (req, res) ->
|
||||||
fftcgdb.register req.body.login, req.body.password
|
fftcgdb.register req.body.login, req.body.password
|
||||||
|
@ -60,23 +57,4 @@ FFTCGROUTER.post '/login', (req, res) ->
|
||||||
status: 'fail'
|
status: 'fail'
|
||||||
text: err
|
text: err
|
||||||
|
|
||||||
# Templates
|
|
||||||
FFTCGROUTER.get '/:template.html', (req, res) ->
|
|
||||||
# redirect logged-in users to user cp
|
|
||||||
if req.session.user and req.params.template == 'index'
|
|
||||||
return res.redirect '/usercp.html'
|
|
||||||
|
|
||||||
# render requested template
|
|
||||||
res.render (req.params.template + '.pug'), (err, html) ->
|
|
||||||
# redirect invalid requests to index
|
|
||||||
if err
|
|
||||||
return res.redirect '/index.html'
|
|
||||||
|
|
||||||
# actual response
|
|
||||||
res.send html
|
|
||||||
|
|
||||||
# default route
|
|
||||||
FFTCGROUTER.use (req, res) ->
|
|
||||||
return res.redirect '/index.html'
|
|
||||||
|
|
||||||
module.exports = FFTCGROUTER
|
module.exports = FFTCGROUTER
|
|
@ -5,12 +5,12 @@ sharedSession = (require 'express-socket.io-session')
|
||||||
helmet = (require 'helmet')
|
helmet = (require 'helmet')
|
||||||
http = (require 'http')
|
http = (require 'http')
|
||||||
path = (require 'path')
|
path = (require 'path')
|
||||||
|
logger = (require 'logging').default 'FFTCG'
|
||||||
|
|
||||||
# my libraries
|
# my libraries
|
||||||
FFTCGSOCKET = (require './inc/socket')
|
FFTCGSOCKET = (require './socket')
|
||||||
FFTCGSESSION = (require './inc/session')
|
FFTCGSESSION = (require './session')
|
||||||
FFTCGROUTER = (require './inc/router')
|
FFTCGROUTER = (require './router')
|
||||||
FFTCGLOG = new (require './inc/console')('FFTCG')
|
|
||||||
|
|
||||||
# express framework
|
# express framework
|
||||||
app = express()
|
app = express()
|
||||||
|
@ -30,11 +30,11 @@ web = http.Server app
|
||||||
socket = new FFTCGSOCKET web, sharedSession sessionMiddleware
|
socket = new FFTCGSOCKET web, sharedSession sessionMiddleware
|
||||||
|
|
||||||
# Create server
|
# Create server
|
||||||
web.listen 3000, ->
|
web.listen 3001, ->
|
||||||
FFTCGLOG.log 'Listening on port 3000 ...'
|
logger.info 'Listening on port 3001 ...'
|
||||||
|
|
||||||
# Handle termination
|
# Handle termination
|
||||||
process.on 'SIGINT', ->
|
process.on 'SIGINT', ->
|
||||||
socket.close()
|
socket.close()
|
||||||
FFTCGLOG.log 'shutting down after SIGINT'
|
logger.info 'shutting down after SIGINT'
|
||||||
process.exit()
|
process.exit()
|
32
backend/socket.coffee
Normal file
32
backend/socket.coffee
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
# node libraries
|
||||||
|
socketio = (require 'socket.io')
|
||||||
|
path = (require 'path')
|
||||||
|
logger = (require 'logging').default 'socket'
|
||||||
|
|
||||||
|
# my libraries
|
||||||
|
|
||||||
|
FFTCGSOCKET = (http, session) ->
|
||||||
|
that = @
|
||||||
|
|
||||||
|
# create server socket
|
||||||
|
@io = socketio http
|
||||||
|
@io.use session
|
||||||
|
|
||||||
|
# on new connection
|
||||||
|
@io.on 'connection', (socket) ->
|
||||||
|
@session = socket.handshake.session
|
||||||
|
logger.debug "session '#{@session.id}' connected"
|
||||||
|
logger.debug "is user '#{@session.userID}'" if @session.userID
|
||||||
|
|
||||||
|
socket.on 'disconnect', ->
|
||||||
|
logger.debug "session '#{that.session.id}' disconnected"
|
||||||
|
logger.debug "is user '#{that.session.userID}'" if that.session.userID
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
FFTCGSOCKET::close = ->
|
||||||
|
logger.info 'shutting down'
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = FFTCGSOCKET
|
2860
backend/yarn.lock
Normal file
2860
backend/yarn.lock
Normal file
File diff suppressed because it is too large
Load diff
13
docker-compose.override.yml
Normal file
13
docker-compose.override.yml
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
version: "2.3"
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
redis:
|
||||||
|
restart: "no"
|
||||||
|
|
||||||
|
backend:
|
||||||
|
build:
|
||||||
|
target: dev
|
||||||
|
restart: "no"
|
||||||
|
volumes:
|
||||||
|
- "./backend:/app"
|
11
docker-compose.prod.yml
Normal file
11
docker-compose.prod.yml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
version: "2.3"
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
redis:
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
backend:
|
||||||
|
build:
|
||||||
|
target: prod
|
||||||
|
restart: unless-stopped
|
|
@ -1,20 +1,12 @@
|
||||||
version: "2"
|
version: "2.3"
|
||||||
|
|
||||||
services:
|
services:
|
||||||
fftcg:
|
|
||||||
build: .
|
|
||||||
command: "yarn debug"
|
|
||||||
restart: "no"
|
|
||||||
volumes:
|
|
||||||
- "${PWD}/src:/app/src"
|
|
||||||
- "${PWD}/views:/app/views:ro"
|
|
||||||
- "${PWD}/public_html:/app/public_html"
|
|
||||||
- "${PWD}/inc:/app/inc:ro"
|
|
||||||
- "${PWD}/server.coffee:/app/server.coffee:ro"
|
|
||||||
# - "${PWD}/fftcg.db:/app/fftcg.db"
|
|
||||||
ports:
|
|
||||||
- "3000:3000"
|
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
image: redis:alpine
|
image: redis:alpine
|
||||||
restart: "no"
|
|
||||||
|
backend:
|
||||||
|
build:
|
||||||
|
context: ./backend
|
||||||
|
ports:
|
||||||
|
- "3001:3000"
|
||||||
|
|
BIN
fftcg.db
BIN
fftcg.db
Binary file not shown.
|
@ -1,11 +0,0 @@
|
||||||
FFTCGLOG = (unit) ->
|
|
||||||
@unit = unit
|
|
||||||
return
|
|
||||||
|
|
||||||
FFTCGLOG::log = (msg) ->
|
|
||||||
console.log "[#{@unit}] #{msg}"
|
|
||||||
|
|
||||||
FFTCGLOG::error = (msg) ->
|
|
||||||
console.error "[#{@unit}] #{msg}"
|
|
||||||
|
|
||||||
module.exports = FFTCGLOG
|
|
|
@ -1,38 +0,0 @@
|
||||||
# node libraries
|
|
||||||
socketio = (require 'socket.io')
|
|
||||||
path = (require 'path')
|
|
||||||
FFTCGLOG = new (require './console')('FFTCGSOCKET')
|
|
||||||
|
|
||||||
# my libraries
|
|
||||||
|
|
||||||
FFTCGSOCKET = (http, session) ->
|
|
||||||
that = @
|
|
||||||
|
|
||||||
# create server socket
|
|
||||||
@io = socketio http
|
|
||||||
@io.use session
|
|
||||||
|
|
||||||
# on new connection
|
|
||||||
@io.on 'connection', (socket) ->
|
|
||||||
@session = socket.handshake.session
|
|
||||||
FFTCGLOG.log "session '#{@session.id}' connected"
|
|
||||||
FFTCGLOG.log "is user '#{@session.userID}'" if @session.userID
|
|
||||||
|
|
||||||
socket.on 'disconnect', ->
|
|
||||||
FFTCGLOG.log "session '#{that.session.id}' disconnected"
|
|
||||||
FFTCGLOG.log "is user '#{that.session.userID}'" if that.session.userID
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
FFTCGSOCKET::close = ->
|
|
||||||
FFTCGLOG.log 'shutting down'
|
|
||||||
if @db
|
|
||||||
@db.close()
|
|
||||||
.then (msg) ->
|
|
||||||
console.log msg
|
|
||||||
.catch (err) ->
|
|
||||||
console.error err
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = FFTCGSOCKET
|
|
|
@ -1,4 +0,0 @@
|
||||||
{
|
|
||||||
"verbose": true,
|
|
||||||
"watch": ["server.coffee", "inc/*"]
|
|
||||||
}
|
|
57
package.json
57
package.json
|
@ -1,57 +0,0 @@
|
||||||
{
|
|
||||||
"name": "node-fftcg",
|
|
||||||
"version": "0.0.3",
|
|
||||||
|
|
||||||
"description": "FFTCG online using Socket.IO and CraftyJS on Node.js on Docker",
|
|
||||||
"author": "JMM <jmm@yavook.de>",
|
|
||||||
|
|
||||||
"main": "server.coffee",
|
|
||||||
"private": true,
|
|
||||||
"license": "UNLICENSED",
|
|
||||||
|
|
||||||
"scripts": {
|
|
||||||
"build": "webpack",
|
|
||||||
"watch": "webpack --watch",
|
|
||||||
"start": "webpack && coffee server.coffee",
|
|
||||||
"debug": "webpack --watch & nodemon server.coffee",
|
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
|
||||||
},
|
|
||||||
|
|
||||||
"devDependencies": {
|
|
||||||
"@babel/core": "^7.1.6",
|
|
||||||
"@babel/preset-env": "^7.1.6",
|
|
||||||
"coffee-loader": "^0.9.0",
|
|
||||||
|
|
||||||
"autoprefixer": "^9.3.1",
|
|
||||||
"css-loader": "^1.0.1",
|
|
||||||
"postcss-loader": "^3.0.0",
|
|
||||||
"node-sass": "^4.10.0",
|
|
||||||
"precss": "^3.1.2",
|
|
||||||
"sass-loader": "^7.1.0",
|
|
||||||
"style-loader": "^0.23.1",
|
|
||||||
|
|
||||||
"nodemon": "^1.18.9",
|
|
||||||
"webpack": "^4.25.1",
|
|
||||||
"webpack-cli": "^3.1.2",
|
|
||||||
|
|
||||||
"bootstrap": "^4.1.3",
|
|
||||||
"craftyjs": "^0.9.0",
|
|
||||||
"jquery": "^3.3.1",
|
|
||||||
"popper.js": "^1.14.5"
|
|
||||||
},
|
|
||||||
|
|
||||||
"dependencies": {
|
|
||||||
"bcrypt": "^3.0.2",
|
|
||||||
"body-parser": "^1.18.3",
|
|
||||||
"coffeescript": "^2.3.2",
|
|
||||||
"connect-redis": "^3.4.0",
|
|
||||||
"express": "^4.16.4",
|
|
||||||
"express-session": "^1.15.6",
|
|
||||||
"express-socket.io-session": "^1.3.5",
|
|
||||||
"helmet": "^3.15.0",
|
|
||||||
"pug": "^2.0.3",
|
|
||||||
"socket.io": "^2.2.0",
|
|
||||||
"socket.io-client": "^2.2.0",
|
|
||||||
"sqlite3": "^4.0.4"
|
|
||||||
}
|
|
||||||
}
|
|
Reference in a new issue