Compare commits
7 commits
25630bba41
...
6dcb5a4963
| Author | SHA1 | Date | |
|---|---|---|---|
| 6dcb5a4963 | |||
| cbc27f1706 | |||
| d4358479f6 | |||
| 0f7176999b | |||
| 0d604ef320 | |||
| e64f5dbabf | |||
| e6bfa62381 |
18 changed files with 113 additions and 287 deletions
|
|
@ -99,14 +99,13 @@ class FFTCGDB
|
|||
stmt.finalize()
|
||||
if err
|
||||
logger.warn "reg: FAIL db '#{err.code}' for '#{login}'"
|
||||
reject messages.exists # user already exists
|
||||
# user already exists
|
||||
reject messages.exists
|
||||
|
||||
else
|
||||
logger.info "reg: OK '#{login}'"
|
||||
# registration successful
|
||||
resolve
|
||||
user: @lastID
|
||||
login: login
|
||||
resolve null
|
||||
|
||||
.catch ->
|
||||
reject messages.empty
|
||||
|
|
@ -117,7 +116,7 @@ class FFTCGDB
|
|||
@validate login, password
|
||||
.then =>
|
||||
# get users table row
|
||||
stmt = @db.prepare 'SELECT user, login, pwdhash FROM users WHERE login = ?'
|
||||
stmt = @db.prepare 'SELECT * FROM users WHERE login = ?'
|
||||
stmt.get [login], (err, row) =>
|
||||
stmt.finalize()
|
||||
if err
|
||||
|
|
@ -139,9 +138,7 @@ class FFTCGDB
|
|||
if res == true
|
||||
logger.debug "login: OK '#{row.login}'"
|
||||
# login successful
|
||||
resolve
|
||||
user: row.user
|
||||
login: row.login
|
||||
resolve row.user
|
||||
|
||||
else
|
||||
logger.debug "login: FAIL password for '#{login}'"
|
||||
|
|
@ -150,6 +147,26 @@ class FFTCGDB
|
|||
.catch ->
|
||||
reject messages.empty
|
||||
|
||||
get: (user) ->
|
||||
new Promise (resolve, reject) =>
|
||||
# get users table row
|
||||
stmt = @db.prepare 'SELECT * FROM users WHERE user = ?'
|
||||
stmt.get [user], (err, row) =>
|
||||
stmt.finalize()
|
||||
if err
|
||||
logger.warn "get: FAIL db '#{err.code}' for '#{user}'"
|
||||
reject messages.db
|
||||
|
||||
else if not row
|
||||
logger.debug "get: FAIL nonexistent '#{user}'"
|
||||
reject messages.noexists # user doesnt exist
|
||||
|
||||
else
|
||||
resolve
|
||||
user: row.user
|
||||
login: row.login
|
||||
settings: row.settings
|
||||
|
||||
addDeck: (user, deckCards) ->
|
||||
new Promise (resolve, reject) =>
|
||||
# try creating row in decks table
|
||||
|
|
|
|||
34
backend/routes/user/info.coffee
Normal file
34
backend/routes/user/info.coffee
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
logger = (require 'logging').default '/user/info'
|
||||
|
||||
# session storage (volatile data)
|
||||
session = (require '../../session')
|
||||
# fftcg.db (persistent data)
|
||||
fftcgdb = (require '../../db')
|
||||
|
||||
module.exports =
|
||||
url: '/user/info'
|
||||
method: 'POST'
|
||||
schema: (require './info.schema')
|
||||
|
||||
handler: (request, reply) ->
|
||||
session.check request.body.session ? ""
|
||||
.then (userid) ->
|
||||
# active session found, get associated user
|
||||
fftcgdb.get (userid)
|
||||
.then (user) ->
|
||||
logger.debug "OK '#{user.login}' got info"
|
||||
reply.send
|
||||
success: true
|
||||
user: user
|
||||
|
||||
.catch (err) ->
|
||||
# couldnt get user details
|
||||
logger.warn "FAIL '#{err}' for user id '#{userid}'"
|
||||
reply.send
|
||||
success: false
|
||||
|
||||
.catch ->
|
||||
# no session found
|
||||
logger.info "FAIL '#{request.body.session}' session not found"
|
||||
reply.send
|
||||
success: false
|
||||
24
backend/routes/user/info.schema.coffee
Normal file
24
backend/routes/user/info.schema.coffee
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
module.exports =
|
||||
body:
|
||||
session: type: 'string'
|
||||
response:
|
||||
200:
|
||||
type: 'object'
|
||||
required: ['success']
|
||||
properties:
|
||||
success: type: 'boolean'
|
||||
user:
|
||||
type: 'object'
|
||||
required: ['user', 'login', 'settings']
|
||||
properties:
|
||||
user: type: 'integer'
|
||||
login: type: 'string'
|
||||
settings: type: 'string'
|
||||
# user is required iff success
|
||||
if:
|
||||
properties:
|
||||
success:
|
||||
const: true
|
||||
then:
|
||||
required: ['user']
|
||||
else: true
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
logger = (require 'logging').default 'login'
|
||||
logger = (require 'logging').default '/user/login'
|
||||
|
||||
# session storage (volatile data)
|
||||
session = (require '../../session')
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
logger = (require 'logging').default 'logout'
|
||||
logger = (require 'logging').default '/user/logout'
|
||||
|
||||
# session storage (volatile data)
|
||||
session = (require '../../session')
|
||||
|
|
@ -6,17 +6,7 @@ session = (require '../../session')
|
|||
module.exports =
|
||||
url: '/user/logout'
|
||||
method: 'POST'
|
||||
schema:
|
||||
body:
|
||||
session: type: 'string'
|
||||
response:
|
||||
200:
|
||||
type: 'object'
|
||||
required: ['success']
|
||||
properties:
|
||||
success:
|
||||
type: 'boolean'
|
||||
const: true
|
||||
schema: (require './logout.schema')
|
||||
|
||||
handler: (request, reply) ->
|
||||
new Promise (resolve) ->
|
||||
|
|
|
|||
11
backend/routes/user/logout.schema.coffee
Normal file
11
backend/routes/user/logout.schema.coffee
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
module.exports =
|
||||
body:
|
||||
session: type: 'string'
|
||||
response:
|
||||
200:
|
||||
type: 'object'
|
||||
required: ['success']
|
||||
properties:
|
||||
success:
|
||||
type: 'boolean'
|
||||
const: true
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
logger = (require 'logging').default 'register'
|
||||
logger = (require 'logging').default '/user/register'
|
||||
|
||||
# fftcg.db (persistent data)
|
||||
fftcgdb = (require '../../db')
|
||||
|
|
@ -10,7 +10,7 @@ module.exports =
|
|||
|
||||
handler: (request, reply) ->
|
||||
fftcgdb.register(request.body.login, request.body.password)
|
||||
.then (user) ->
|
||||
.then ->
|
||||
logger.info "OK '#{request.body.login}'"
|
||||
reply.send
|
||||
success: true
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ fastify.route (require "./routes/#{route}") for route in [
|
|||
'test'
|
||||
# log in user
|
||||
'user/login'
|
||||
# user info
|
||||
'user/info'
|
||||
# log out user
|
||||
'user/logout'
|
||||
# register user
|
||||
|
|
|
|||
|
|
@ -57,6 +57,6 @@ class FFTCGSESSION
|
|||
else
|
||||
@db.get digest, (err, res) ->
|
||||
logger.info "OK '#{digest}' resumed"
|
||||
resolve digest
|
||||
resolve (JSON.parse res)
|
||||
|
||||
module.exports = new FFTCGSESSION
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ export default {
|
|||
let cookie_data = JSON.parse(response.data.message)
|
||||
Cookies.set('session', cookie_data.value, cookie_data.properties)
|
||||
this.$refs.main.showSnackbar('Login successful!', 'success')
|
||||
this.$router.push('about')
|
||||
this.$router.push('usercp')
|
||||
} else {
|
||||
this.$refs.main.showSnackbar(response.data.message, 'error')
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,13 +14,13 @@ export default new Router({
|
|||
component: Home
|
||||
},
|
||||
{
|
||||
path: '/about',
|
||||
name: 'about',
|
||||
path: '/usercp',
|
||||
name: 'usercp',
|
||||
// route level code-splitting
|
||||
// this generates a separate chunk (about.[hash].js) for this route
|
||||
// this generates a separate chunk (usercp.[hash].js) for this route
|
||||
// which is lazy-loaded when the route is visited.
|
||||
component: () =>
|
||||
import(/* webpackChunkName: "about" */ './views/About.vue')
|
||||
import(/* webpackChunkName: "usercp" */ './views/UserCP.vue')
|
||||
},
|
||||
{
|
||||
path: '/game',
|
||||
|
|
|
|||
|
|
@ -18,12 +18,6 @@ import RegisterForm from '@/components/forms/Register.vue'
|
|||
export default {
|
||||
name: 'Home',
|
||||
|
||||
data() {
|
||||
return {
|
||||
dialog: false
|
||||
}
|
||||
},
|
||||
|
||||
components: {
|
||||
Header,
|
||||
LoginForm,
|
||||
|
|
@ -38,7 +32,7 @@ export default {
|
|||
})
|
||||
.then(response => {
|
||||
if (response.data.success) {
|
||||
this.$router.push({ name: 'about' })
|
||||
this.$router.push({ name: 'usercp' })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<v-container>
|
||||
<Header />
|
||||
|
||||
<p>user session: {{ sessionID }}</p>
|
||||
<p>user logged in: {{ user.login }}</p>
|
||||
<v-btn @click.native="logout">Logout</v-btn>
|
||||
</v-container>
|
||||
</template>
|
||||
|
|
@ -14,14 +14,14 @@ import axios from '@/plugins/axios'
|
|||
import Header from '@/components/Header.vue'
|
||||
|
||||
export default {
|
||||
name: 'About',
|
||||
name: 'UserCP',
|
||||
|
||||
components: {
|
||||
Header
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
sessionID: ''
|
||||
user: ''
|
||||
}),
|
||||
|
||||
methods: {
|
||||
|
|
@ -45,12 +45,12 @@ export default {
|
|||
|
||||
mounted() {
|
||||
axios
|
||||
.post('/user/login', {
|
||||
.post('/user/info', {
|
||||
session: Cookies.get('session')
|
||||
})
|
||||
.then(response => {
|
||||
if (response.data.success) {
|
||||
this.sessionID = response.data.message
|
||||
this.user = response.data.user
|
||||
} else {
|
||||
this.goHome()
|
||||
}
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
# libs
|
||||
window.$ = require('jquery')
|
||||
|
||||
# on load
|
||||
$ ->
|
||||
# libs requiring full DOM
|
||||
require 'craftyjs/dist/crafty'
|
||||
io = require 'socket.io-client'
|
||||
|
||||
# style sheet
|
||||
require './style/custom.scss'
|
||||
|
||||
# fftcg libs
|
||||
require './game/config.coffee'
|
||||
require './game/components/Card.coffee'
|
||||
require './game/scenes/Battle.coffee'
|
||||
|
||||
# init Socket.IO
|
||||
socket = io()
|
||||
|
||||
# init CraftyJS framework
|
||||
Crafty.init()
|
||||
|
||||
# Load base scene
|
||||
Crafty.scene "Battle"
|
||||
|
||||
# Testing some entities
|
||||
Crafty.sprite 480, 670, '//www.fftcgmognet.com/images/cards/hd/1/1/107.jpg',
|
||||
shantotto: [
|
||||
0
|
||||
0
|
||||
]
|
||||
|
||||
backups = [
|
||||
|
||||
Crafty.e 'shantotto, AllyCard'
|
||||
.attr {
|
||||
card:
|
||||
type: 'backup'
|
||||
}
|
||||
|
||||
Crafty.e 'shantotto, AllyCard'
|
||||
.attr {
|
||||
card:
|
||||
type: 'backup'
|
||||
}
|
||||
|
||||
Crafty.e 'shantotto, AllyCard'
|
||||
.attr {
|
||||
card:
|
||||
type: 'backup'
|
||||
}
|
||||
|
||||
]
|
||||
|
||||
Crafty 'AllyCard'
|
||||
.each (index) ->
|
||||
switch @card.type
|
||||
when 'backup'
|
||||
@trigger 'Place',
|
||||
x: CONF.coord.x.main + index * CONF.coord.x.step
|
||||
y: CONF.coord.y.bkup
|
||||
return
|
||||
|
||||
|
||||
Crafty.e 'shantotto, EnemyCard'
|
||||
.trigger 'Place',
|
||||
x: 900
|
||||
y: 0
|
||||
|
||||
return
|
||||
105
src/index.coffee
105
src/index.coffee
|
|
@ -1,105 +0,0 @@
|
|||
# libs
|
||||
window.$ = require('jquery')
|
||||
|
||||
# import bootstrap
|
||||
require './style/custom.scss'
|
||||
require 'bootstrap/js/dist/alert'
|
||||
|
||||
window.showAlert = (level, content) ->
|
||||
($ '.alert').alert 'close'
|
||||
|
||||
($ '#alert-area').append ($ '<div>',
|
||||
class: "alert alert-#{level} alert-dismissible fade show"
|
||||
role: 'alert'
|
||||
.append content, ($ '<button>',
|
||||
type: 'button'
|
||||
class: 'close'
|
||||
'data-dismiss': 'alert',
|
||||
'aria-label': 'Close'
|
||||
.append ($ '<span>',
|
||||
'aria-hidden': 'true'
|
||||
.append '×'
|
||||
)))
|
||||
|
||||
# on load
|
||||
$ ->
|
||||
# reset forms
|
||||
$('form').each ->
|
||||
@fullReset = ->
|
||||
$('input', @).each ->
|
||||
$(@).removeClass 'is-invalid'
|
||||
$(@).removeClass 'is-valid'
|
||||
@reset()
|
||||
|
||||
# login form
|
||||
$('form[name="login"]').submit (event) ->
|
||||
that = @
|
||||
# inhibit normal form submission
|
||||
event.preventDefault()
|
||||
|
||||
# gather form data
|
||||
login = $('input[name="login"]', @)
|
||||
password = $('input[name="password"]', @)
|
||||
|
||||
# transmit form data
|
||||
$.post '/login',
|
||||
login: login.val()
|
||||
password: password.val()
|
||||
.done (data) ->
|
||||
if data.status == 'ok'
|
||||
that.fullReset()
|
||||
showAlert 'success', "successfully logged in '#{data.login}'"
|
||||
location.reload()
|
||||
|
||||
else
|
||||
switch data.text
|
||||
when 'login'
|
||||
showAlert 'warning', 'Invalid username and/or password.'
|
||||
login.addClass 'is-invalid'
|
||||
password.addClass 'is-invalid'
|
||||
when 'db' or 'hash'
|
||||
showAlert 'danger', 'Internal failure, try again later.'
|
||||
else
|
||||
showAlert 'danger', 'Unknown failure. Can you reproduce this?'
|
||||
|
||||
# registration form
|
||||
$('form[name="register"]').submit (event) ->
|
||||
that = @
|
||||
# inhibit normal form submission
|
||||
event.preventDefault()
|
||||
|
||||
# gather form data
|
||||
login = $('input[name="login"]', @)
|
||||
password = $('input[name="password"]', @)
|
||||
confirm = $('input[name="confirm"]', @)
|
||||
|
||||
# check form data
|
||||
if password.val() != confirm.val()
|
||||
confirm.addClass 'is-invalid'
|
||||
confirm.focus()
|
||||
|
||||
else
|
||||
# transmit form data
|
||||
$.post '/register',
|
||||
login: login.val()
|
||||
password: password.val()
|
||||
.done (data) ->
|
||||
if data.status == 'ok'
|
||||
that.fullReset()
|
||||
showAlert 'success', "successfully registered '#{data.login}'"
|
||||
|
||||
else
|
||||
switch data.text
|
||||
when 'invalid'
|
||||
showAlert 'warning', 'Invalid user input. Please provide username AND password.'
|
||||
login.addClass 'is-invalid'
|
||||
password.addClass 'is-invalid'
|
||||
login.focus()
|
||||
when 'hash'
|
||||
showAlert 'danger', 'Internal failure, try again later.'
|
||||
when 'db'
|
||||
showAlert 'danger', 'Internal failure or user name already taken.'
|
||||
login.addClass 'is-invalid'
|
||||
login.focus()
|
||||
else
|
||||
showAlert 'danger', 'Unknown failure. Can you reproduce this?'
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
# libs
|
||||
window.$ = require('jquery')
|
||||
|
||||
# import bootstrap
|
||||
require './style/custom.scss'
|
||||
require 'bootstrap/js/dist/alert'
|
||||
require 'bootstrap/js/dist/collapse'
|
||||
|
||||
# on load
|
||||
$ ->
|
||||
return
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
doctype html
|
||||
html
|
||||
head
|
||||
title Crafty Things
|
||||
script(src='/game.bundle.js')
|
||||
body
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
doctype html
|
||||
html
|
||||
|
||||
head
|
||||
title Crafty Things
|
||||
script(src='/index.bundle.js')
|
||||
|
||||
body
|
||||
|
||||
header.jumbotron.jumbotron-fluid.py-4.bg-primary.text-light.text-center
|
||||
div.container
|
||||
h1 Hello World!
|
||||
h2 App under development, please don't submit any valuable data!
|
||||
|
||||
div.container.bg-light
|
||||
div#alert-area
|
||||
div.row
|
||||
|
||||
div.col-md-6
|
||||
h3 Yavook!FFTCG
|
||||
p Lorem ipsum dolor sit amet
|
||||
|
||||
div.col-md-3
|
||||
h3 Login
|
||||
form(name="login")
|
||||
div.form-group
|
||||
label(for="login") User name:
|
||||
input.form-control(name="login" required)
|
||||
|
||||
div.form-group
|
||||
label(for="password") Password:
|
||||
input.form-control(name="password" type="password" required)
|
||||
|
||||
div.form-group
|
||||
button.btn.btn-primary.w-100(type="submit") Login
|
||||
|
||||
div.col-md-3
|
||||
h3 Register
|
||||
form(name="register")
|
||||
div.form-group
|
||||
label(for="login") User name:
|
||||
input.form-control(name="login" required)
|
||||
div.invalid-feedback User name invalid or taken.
|
||||
|
||||
div.form-group
|
||||
label(for="password") Password:
|
||||
input.form-control(name="password" type="password" required)
|
||||
|
||||
label(for="confirm") Confirm password:
|
||||
input.form-control(name="confirm" type="password")
|
||||
div.invalid-feedback Passwords do not match.
|
||||
|
||||
button.btn.btn-primary.w-100(type="submit") Register
|
||||
Reference in a new issue