mirror of
https://github.com/zyphlar/doorlock.git
synced 2024-04-03 21:36:03 +00:00
Add Cobot card fetching, cleanup config setup.
This commit is contained in:
parent
a076724f83
commit
bf358756e1
11
.env.example
Normal file
11
.env.example
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
COBOT_CLIENT_ID='...'
|
||||||
|
COBOT_CLIENT_SECRET='...'
|
||||||
|
COBOT_REDIRECT_URL='http://10.0.1.48:8080/success'
|
||||||
|
COBOT_AUTHORIZE_URL='https://www.cobot.me/oauth/authorize'
|
||||||
|
COBOT_TOKEN_URL='https://www.cobot.me/oauth/access_token'
|
||||||
|
COBOT_SCOPE='checkin_tokens'
|
||||||
|
COBOT_USER_EMAIL='...'
|
||||||
|
COBOT_USER_PASSWORD='...'
|
||||||
|
COBOT_CARDS_API='https://chimera.cobot.me/api/check_in_tokens'
|
||||||
|
DOOR_OPEN_DELAY=6000
|
||||||
|
PORT=8080
|
11
.env.test
Normal file
11
.env.test
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
COBOT_CLIENT_ID='fake-id'
|
||||||
|
COBOT_CLIENT_SECRET='fake-secret'
|
||||||
|
COBOT_REDIRECT_URL='http://localhost:8080/success'
|
||||||
|
COBOT_AUTHORIZE_URL='https://www.cobot.me/oauth/authorize'
|
||||||
|
COBOT_TOKEN_URL='https://www.cobot.me/oauth/access_token'
|
||||||
|
COBOT_SCOPE='checkin_tokens'
|
||||||
|
COBOT_USER_EMAIL='info@chimeraarts.org'
|
||||||
|
COBOT_USER_PASSWORD='somepassword'
|
||||||
|
COBOT_CARDS_API='https://chimera.cobot.me/api/check_in_tokens'
|
||||||
|
DOOR_OPEN_DELAY=1
|
||||||
|
PORT=8080
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,3 +1,4 @@
|
||||||
|
|
||||||
|
.env
|
||||||
node_modules
|
node_modules
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
|
@ -4,4 +4,4 @@
|
||||||
# .tesselinclude works the same as .npminclude
|
# .tesselinclude works the same as .npminclude
|
||||||
# You DO NOT need to list node_modules or package.json
|
# You DO NOT need to list node_modules or package.json
|
||||||
# For more information, visit: https://tessel.io/docs/cli#usage
|
# For more information, visit: https://tessel.io/docs/cli#usage
|
||||||
index.html
|
.env
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
module.exports = {
|
|
||||||
env: 'ENV',
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
module.exports = {
|
|
||||||
cardApi: 'https://chimera.cobot.me/api/check_in_tokens',
|
|
||||||
env: 'development',
|
|
||||||
openDelay: 6000,
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
module.exports = {
|
|
||||||
env: 'test',
|
|
||||||
openDelay: 1,
|
|
||||||
}
|
|
5
package-lock.json
generated
5
package-lock.json
generated
|
@ -355,6 +355,11 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"dotenv": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-4As8uPrjfwb7VXC+WnLCbXK7y+Ueb2B3zgNCePYfhxS1PYeaO1YTeplffTEcbfLhvFNGLAz90VvJs9yomG7bow=="
|
||||||
|
},
|
||||||
"eslint": {
|
"eslint": {
|
||||||
"version": "4.17.0",
|
"version": "4.17.0",
|
||||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-4.17.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint/-/eslint-4.17.0.tgz",
|
||||||
|
|
|
@ -8,15 +8,11 @@
|
||||||
"watch-test": "npm test -- --watch"
|
"watch-test": "npm test -- --watch"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "0.17.1",
|
"axios": "0.18.0",
|
||||||
"chalk": "2.3.1",
|
"chalk": "2.3.1",
|
||||||
"config": "1.30.0",
|
"dotenv": "5.0.1",
|
||||||
"consolidate": "0.15.0",
|
|
||||||
"eslint": "4.17.0",
|
"eslint": "4.17.0",
|
||||||
"express": "4.16.2",
|
|
||||||
"node-hid": "0.7.2",
|
"node-hid": "0.7.2",
|
||||||
"pug": "2.0.0-rc.4",
|
|
||||||
"serialport": "6.0.5",
|
|
||||||
"tessel": "0.3.25"
|
"tessel": "0.3.25"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
@ -66,6 +66,10 @@ t2 erase
|
||||||
t2 ap -n doorlock
|
t2 ap -n doorlock
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Networking
|
||||||
|
|
||||||
|
To find the IP address of your Tessel, download the iOS app Fing and look for a device on your network called `doorlock`.
|
||||||
|
|
||||||
### USB Storage
|
### USB Storage
|
||||||
|
|
||||||
* Make sure to format USB to be FAT32!
|
* Make sure to format USB to be FAT32!
|
||||||
|
|
17
src/boot.js
17
src/boot.js
|
@ -1,6 +1,19 @@
|
||||||
const Door = require('./models/door')
|
const Cobot = require('./models/cobot')
|
||||||
|
|
||||||
Door.open()
|
Cobot.authorize().then(cobot => {
|
||||||
|
cobot.cards().then(resp => console.log('RESP:', resp))
|
||||||
|
})
|
||||||
|
|
||||||
|
// const server = require('./server')
|
||||||
|
|
||||||
|
// server()
|
||||||
|
|
||||||
|
// const Cards = require('./models/cards')
|
||||||
|
// const Door = require('./models/door')
|
||||||
|
|
||||||
|
// Door.open()
|
||||||
|
|
||||||
|
// Cards.update()
|
||||||
|
|
||||||
// const server = require('./server')
|
// const server = require('./server')
|
||||||
|
|
||||||
|
|
14
src/constants.js
Normal file
14
src/constants.js
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
require('dotenv').config()
|
||||||
|
|
||||||
|
const ENV = process.env.NODE_ENV || 'development'
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
COBOT_CARDS_API: process.env.COBOT_CARDS_API,
|
||||||
|
COBOT_CLIENT_ID: process.env.COBOT_CLIENT_ID,
|
||||||
|
COBOT_CLIENT_SECRET: process.env.COBOT_CLIENT_SECRET,
|
||||||
|
COBOT_SCOPE: process.env.COBOT_SCOPE,
|
||||||
|
COBOT_USER_EMAIL: process.env.COBOT_USER_EMAIL,
|
||||||
|
COBOT_USER_PASSWORD: process.env.COBOT_USER_PASSWORD,
|
||||||
|
DOOR_OPEN_DELAY: process.env.DOOR_OPEN_DELAY,
|
||||||
|
ENV,
|
||||||
|
}
|
|
@ -1,9 +1,9 @@
|
||||||
const axios = require('axios')
|
const axios = require('axios')
|
||||||
const config = require('config')
|
const { COBOT_CARDS_API } = require('../constants')
|
||||||
|
|
||||||
class Cards {
|
class Cards {
|
||||||
static update() {
|
static update() {
|
||||||
return axios.get(config.get('cardApi'))
|
return axios.get(COBOT_CARDS_API)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
64
src/models/cobot.js
Normal file
64
src/models/cobot.js
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
const axios = require('axios')
|
||||||
|
const {
|
||||||
|
COBOT_CARDS_API,
|
||||||
|
COBOT_CLIENT_ID,
|
||||||
|
COBOT_CLIENT_SECRET,
|
||||||
|
COBOT_SCOPE,
|
||||||
|
COBOT_USER_EMAIL,
|
||||||
|
COBOT_USER_PASSWORD,
|
||||||
|
} = require('../constants')
|
||||||
|
|
||||||
|
class Cobot {
|
||||||
|
constructor(token) {
|
||||||
|
this.token = token
|
||||||
|
}
|
||||||
|
|
||||||
|
cards() {
|
||||||
|
if (!COBOT_CARDS_API)
|
||||||
|
throw new Error('missing "COBOT_CARDS_API" env variable!')
|
||||||
|
return axios
|
||||||
|
.get(COBOT_CARDS_API, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${this.token}`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then(resp =>
|
||||||
|
resp.data.map(card => ({
|
||||||
|
name: card.membership.name,
|
||||||
|
number: card.token,
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
static authorize() {
|
||||||
|
if (!COBOT_SCOPE) throw new Error('missing "COBOT_SCOPE" env variable!')
|
||||||
|
if (!COBOT_USER_EMAIL)
|
||||||
|
throw new Error('missing "COBOT_USER_EMAIL" env variable!')
|
||||||
|
if (!COBOT_USER_PASSWORD)
|
||||||
|
throw new Error('missing "COBOT_USER_PASSWORD" env variable!')
|
||||||
|
if (!COBOT_CLIENT_ID)
|
||||||
|
throw new Error('missing "COBOT_CLIENT_ID" env variable!')
|
||||||
|
if (!COBOT_CLIENT_SECRET)
|
||||||
|
throw new Error('missing "COBOT_CLIENT_SECRET" env variable!')
|
||||||
|
console.log(
|
||||||
|
COBOT_SCOPE,
|
||||||
|
COBOT_USER_EMAIL,
|
||||||
|
COBOT_USER_PASSWORD,
|
||||||
|
COBOT_CLIENT_ID,
|
||||||
|
COBOT_CLIENT_SECRET
|
||||||
|
)
|
||||||
|
const qs = [
|
||||||
|
`scope=${COBOT_SCOPE}`,
|
||||||
|
`grant_type=password`,
|
||||||
|
`username=${COBOT_USER_EMAIL}`,
|
||||||
|
`password=${COBOT_USER_PASSWORD}`,
|
||||||
|
`client_id=${COBOT_CLIENT_ID}`,
|
||||||
|
`client_secret=${COBOT_CLIENT_SECRET}`,
|
||||||
|
].join('&')
|
||||||
|
return axios
|
||||||
|
.post(`https://www.cobot.me/oauth/access_token?${qs}`)
|
||||||
|
.then(resp => new Cobot(resp.data.access_token))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Cobot
|
41
src/models/cobot.test.js
Normal file
41
src/models/cobot.test.js
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
const axios = require('axios')
|
||||||
|
const Cobot = require('./cobot')
|
||||||
|
|
||||||
|
jest.mock('axios')
|
||||||
|
|
||||||
|
describe('models/cobot', () => {
|
||||||
|
describe('.authorize', () => {
|
||||||
|
test('should fetch a new token', () => {
|
||||||
|
const resp = { data: { access_token: 'meow' } }
|
||||||
|
jest.spyOn(axios, 'post').mockResolvedValue(resp)
|
||||||
|
return Cobot.authorize().then(cobot => {
|
||||||
|
expect(axios.post).toBeCalled()
|
||||||
|
expect(cobot).toBeInstanceOf(Cobot)
|
||||||
|
expect(cobot.token).toBe('meow')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('.cards', () => {
|
||||||
|
test('returns a structured list of cards', () => {
|
||||||
|
const resp = {
|
||||||
|
data: [
|
||||||
|
{ membership: { id: 'foo', name: 'John' }, token: '001' },
|
||||||
|
{ membership: { id: 'bar', name: 'Jane' }, token: '002' },
|
||||||
|
],
|
||||||
|
}
|
||||||
|
const expected = [
|
||||||
|
{ name: 'John', number: '001' },
|
||||||
|
{ name: 'Jane', number: '002' },
|
||||||
|
]
|
||||||
|
jest.spyOn(axios, 'get').mockResolvedValue(resp)
|
||||||
|
|
||||||
|
// TODO: why doesnt this work? It should...
|
||||||
|
// axios.get.mockResolvedValue(resp)
|
||||||
|
|
||||||
|
return new Cobot('fake-value')
|
||||||
|
.cards()
|
||||||
|
.then(actual => expect(actual).toEqual(expected))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
|
@ -1,9 +1,7 @@
|
||||||
const config = require('config')
|
const { DOOR_OPEN_DELAY } = require('../constants')
|
||||||
const logger = require('../utils/logger')
|
const logger = require('../utils/logger')
|
||||||
const tessel = require('tessel')
|
const tessel = require('tessel')
|
||||||
|
|
||||||
const DOOR_OPEN_DELAY = config.get('openDelay')
|
|
||||||
|
|
||||||
// const fs = require('fs')
|
// const fs = require('fs')
|
||||||
// const path = require('path')
|
// const path = require('path')
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
const config = require('config')
|
const { ENV } = require('../constants')
|
||||||
const ENV = config.get('env')
|
|
||||||
|
|
||||||
class Logger {
|
class Logger {
|
||||||
log() {
|
log() {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user