refactor: user agent parsing

This commit is contained in:
Sérgio Salgado 2020-10-26 16:03:02 +00:00 committed by Josh Harvey
parent 791b275cdf
commit 839e6aae47
8 changed files with 21 additions and 63 deletions

View file

@ -68,10 +68,12 @@ app.use('/front-camera-photo', serveStatic(frontCameraBasedir, { index: false })
app.get('/api/register', (req, res, next) => {
const otp = req.query.otp
const ua = req.headers['user-agent']
const ip = req.ip
if (!otp) return next()
return login.register(req)
return login.register(otp, ua, ip)
.then(r => {
if (r.expired) return res.status(401).send('OTP expired, generate new registration link')

View file

@ -160,6 +160,8 @@ const typeDefs = gql`
token: String!
name: String!
created: Date!
user_agent: String!
ip_address: String!
}
type Transaction {
@ -224,7 +226,7 @@ const typeDefs = gql`
transactionsCsv(from: Date, until: Date, limit: Int, offset: Int): String
accounts: JSONObject
config: JSONObject
userTokens(browser: String!, os: String!): [UserToken]
userTokens: [UserToken]
}
enum MachineAction {
@ -283,7 +285,7 @@ const resolvers = {
transactions.batch(from, until, limit, offset).then(parseAsync),
config: () => settingsLoader.loadLatestConfigOrNone(),
accounts: () => settingsLoader.loadAccounts(),
userTokens: (...[, { browser, os }]) => tokenManager.getTokenList(browser, os)
userTokens: () => tokenManager.getTokenList()
},
Mutation: {
machineAction: (...[, { deviceId, action, cassette1, cassette2, newName }]) => machineAction({ deviceId, action, cassette1, cassette2, newName }),

View file

@ -1,6 +1,5 @@
const crypto = require('crypto')
const browserOS = require('../../new-lamassu-admin/src/utils/browser-os')
const db = require('../db')
function generateOTP (name) {
@ -22,18 +21,15 @@ function validateOTP (otp) {
.catch(() => ({ success: false, expired: false }))
}
function register (req) {
const otp = req.query.otp
function register (otp, ua, ip) {
return validateOTP(otp)
.then(r => {
if (!r.success) return r
const deviceInfo = browserOS.getInformation(req.headers['user-agent'])
const token = crypto.randomBytes(32).toString('hex')
const sql = 'insert into user_tokens (token, name, browser_version, os_version, ip_address) values ($1, $2, $3, $4, $5)'
const sql = 'insert into user_tokens (token, name, user_agent, ip_address) values ($1, $2, $3, $4)'
return db.none(sql, [token, r.name, deviceInfo.browser, deviceInfo.OS, browserOS.getRequestIP(req)])
return db.none(sql, [token, r.name, ua, ip])
.then(() => ({ success: true, token: token }))
})
.catch(() => ({ success: false, expired: false }))

View file

@ -1,8 +1,8 @@
const db = require('./db')
function getTokenList (browser, os) {
const sql = `select * from user_tokens where browser_version=$1 and os_version=$2`
return db.any(sql, [browser, os])
function getTokenList () {
const sql = `select * from user_tokens`
return db.any(sql)
}
function revokeToken (token) {

View file

@ -2,8 +2,7 @@ const db = require('./db')
exports.up = function (next) {
var sql = [
'ALTER TABLE user_tokens ADD COLUMN browser_version text',
'ALTER TABLE user_tokens ADD COLUMN os_version text',
'ALTER TABLE user_tokens ADD COLUMN user_agent text',
'ALTER TABLE user_tokens ADD COLUMN ip_address inet',
]

View file

@ -1,26 +1,22 @@
import { useQuery, useMutation } from '@apollo/react-hooks'
import { makeStyles } from '@material-ui/core/styles'
import gql from 'graphql-tag'
import moment from 'moment'
import * as R from 'ramda'
import React from 'react'
import Title from 'src/components/Title'
import { IconButton } from 'src/components/buttons'
import TitleSection from 'src/components/layout/TitleSection'
import DataTable from 'src/components/tables/DataTable'
import { ReactComponent as DeleteIcon } from 'src/styling/icons/action/delete/enabled.svg'
import * as browserOS from 'src/utils/browser-os'
import { mainStyles } from './TokenManagement.styles'
const useStyles = makeStyles(mainStyles)
const GET_USER_TOKENS = gql`
query userTokens($browser: String!, $os: String!) {
userTokens(browser: $browser, os: $os) {
query userTokens {
userTokens {
token
name
created
user_agent
ip_address
}
}
`
@ -34,16 +30,7 @@ const REVOKE_USER_TOKEN = gql`
`
const Tokens = () => {
const classes = useStyles()
const userAgent = browserOS.getInformation(navigator.userAgent)
const { data: tknResponse } = useQuery(GET_USER_TOKENS, {
variables: {
browser: `${userAgent.browser}`,
os: `${userAgent.OS}`
}
})
const { data: tknResponse } = useQuery(GET_USER_TOKENS)
const [revokeToken] = useMutation(REVOKE_USER_TOKEN, {
refetchQueries: () => ['userTokens']
@ -96,11 +83,7 @@ const Tokens = () => {
return (
<>
<div className={classes.titleWrapper}>
<div className={classes.titleAndButtonsContainer}>
<Title>Token Management</Title>
</div>
</div>
<TitleSection title="Token Management" />
<DataTable
elements={elements}
data={R.path(['userTokens'])(tknResponse)}

View file

@ -1,10 +0,0 @@
import baseStyles from 'src/pages/Logs.styles'
const { titleWrapper, titleAndButtonsContainer } = baseStyles
const mainStyles = {
titleWrapper,
titleAndButtonsContainer
}
export { mainStyles }

View file

@ -1,14 +0,0 @@
const parser = require('ua-parser-js')
function getRequestIP(req) {
return req.ip
}
function getInformation(uaString) {
const userAgent = parser(uaString)
const browser = `${userAgent.browser.name} ${userAgent.browser.version}`
const OS = `${userAgent.os.name} ${userAgent.os.version}`
return { browser: browser, OS: OS }
}
module.exports = { getRequestIP, getInformation }