1
0
Fork 0
mirror of https://github.com/openstf/stf synced 2025-10-04 10:19:30 +02:00

refactoring swagger

This commit is contained in:
Vishal Banthia 2015-12-08 15:58:05 +09:00
parent 26ad95a36e
commit 9de5ba5fae
5 changed files with 234 additions and 148 deletions

View file

@ -1,31 +1,37 @@
var Promise = require('bluebird')
var _ = require('lodash') var _ = require('lodash')
var Promise = require('bluebird')
var dbapi = require('../../../db/api') var dbapi = require('../../../db/api')
var logger = require('../../../util/logger') var logger = require('../../../util/logger')
var datautil = require('../../../util/datautil') var datautil = require('../../../util/datautil')
var log = logger.createLogger('api:controllers:device') var log = logger.createLogger('api:controllers:devices')
module.exports = { module.exports = {
getDevices: getDevices getDevices: getDevices
, getDeviceBySerial: getDeviceBySerial , getDeviceBySerial: getDeviceBySerial
} }
var log = logger.createLogger('api:contoller:device')
function getDevices(req, res) { function getDevices(req, res) {
var fields = req.swagger.params.fields.value
dbapi.loadDevices() dbapi.loadDevices()
.then(function(cursor) { .then(function(cursor) {
return Promise.promisify(cursor.toArray, cursor)() return Promise.promisify(cursor.toArray, cursor)()
.then(function(list) { .then(function(list) {
var deviceList = []
list.forEach(function(device) { list.forEach(function(device) {
datautil.normalize(device, req.user) datautil.normalize(device, req.user)
if (fields) {
device = _.pick(device, fields.split(','))
}
deviceList.push(device)
}) })
res.json({ res.json({
success: true success: true
, devices: list , devices: deviceList
}) })
}) })
}) })
@ -58,6 +64,7 @@ function getDeviceBySerial(req, res) {
else { else {
res.status(404).json({ res.status(404).json({
success: false success: false
, description: 'Device not found'
}) })
} }
}) })

View file

@ -1,33 +0,0 @@
var Promise = require('bluebird')
var dbapi = require('../../../db/api')
var logger = require('../../../util/logger')
var log = logger.createLogger('api:controllers:token')
module.exports = {
getAccessTokens: getAccessTokens
}
function getAccessTokens(req, res) {
dbapi.loadAccessTokens(req.user.email)
.then(function(cursor) {
return Promise.promisify(cursor.toArray, cursor)()
.then(function(list) {
var titles = []
list.forEach(function(token) {
titles.push(token.title)
})
res.json({
success: true
, titles: titles
})
})
})
.catch(function(err) {
log.error('Failed to load tokens: ', err.stack)
res.status(500).json({
success: false
})
})
}

View file

@ -1,4 +1,7 @@
var util = require('util')
var Promise = require('bluebird') var Promise = require('bluebird')
var _ = require('lodash')
var dbapi = require('../../../db/api') var dbapi = require('../../../db/api')
var logger = require('../../../util/logger') var logger = require('../../../util/logger')
@ -9,45 +12,96 @@ var wireutil = require('../../../wire/util')
var log = logger.createLogger('api:controllers:user') var log = logger.createLogger('api:controllers:user')
module.exports = { module.exports = {
getCurrentUser: getCurrentUser getUser: getUser
, getCurrentUserDevices: getCurrentUserDevices , getUserDevices: getUserDevices
, addDeviceToUser: addDeviceToUser , addUserDevice: addUserDevice
, deleteDeviceFromUser: deleteDeviceFromUser
, getUserDeviceBySerial: getUserDeviceBySerial , getUserDeviceBySerial: getUserDeviceBySerial
, connectDeviceBySerial: connectDeviceBySerial , deleteUserDeviceBySerial: deleteUserDeviceBySerial
, disconnectDeviceBySerial: disconnectDeviceBySerial , remoteConnectUserDeviceBySerial: remoteConnectUserDeviceBySerial
, remoteDisconnectUserDeviceBySerial: remoteDisconnectUserDeviceBySerial
, getUserAccessTokens: getUserAccessTokens
} }
function getCurrentUser(req, res) { function getUser(req, res) {
res.json({ res.json({
success: true success: true
, user: req.user , user: req.user
}) })
} }
function getCurrentUserDevices(req, res) { function getUserDevices(req, res) {
var fields = req.swagger.params.fields.value
dbapi.loadUserDevices(req.user.email) dbapi.loadUserDevices(req.user.email)
.then(function(cursor) { .then(function(cursor) {
return Promise.promisify(cursor.toArray, cursor)() return Promise.promisify(cursor.toArray, cursor)()
.then(function(list) { .then(function(list) {
var deviceList = []
list.forEach(function(device) { list.forEach(function(device) {
datautil.normalize(device, req.user) datautil.normalize(device, req.user)
if (fields) {
device = _.pick(device, fields.split(','))
}
deviceList.push(device)
}) })
res.json({ res.json({
success: true success: true
, devices: list , devices: deviceList
}) })
}) })
}) })
.catch(function(err) { .catch(function(err) {
log.error('Failed to load group: ', err.stack) log.error('Failed to load device list: ', err.stack)
res.status(500).json({ res.status(500).json({
success: false success: false
}) })
}) })
} }
function addDeviceToUser(req, res) { function getUserDeviceBySerial(req, res) {
var serial = req.swagger.params.serial.value
var fields = req.swagger.params.fields.value
dbapi.loadDevice(serial)
.then(function(device) {
if (device) {
datautil.normalize(device, req.user)
if (device.owner && device.owner.email === req.user.email) {
if(fields) {
device = _.pick(device, fields.split(','))
}
res.json({
success: true
, device: device
})
}
else {
res.status(401).json({
success: false
, description: 'Device is not owned by you'
})
}
}
else {
res.status(404).json({
success: false
, description: 'Device not found'
})
}
})
.catch(function(err) {
log.error('Failed to load device "%s": ', req.params.serial, err.stack)
res.status(500).json({
success: false
})
})
}
function addUserDevice(req, res) {
var serial = req.body.serial var serial = req.body.serial
var timeout = req.body.timeout || null var timeout = req.body.timeout || null
@ -81,17 +135,23 @@ function addDeviceToUser(req, res) {
res.status(202).json({ res.status(202).json({
success: true success: true
, description: 'Device Add request is accepted' , description: 'Device Add request is accepted. Check if device is successfully added using pollingUrl'
, pollingUrl: util.format('%s://%s%s/user/devices/%s'
, req.protocol
, req.get('host')
, req.swagger.operation.api.basePath
, serial
)
}) })
} else { } else {
res.status(500).json({ res.status(401).json({
success: false success: false
, description: 'Device is being used or not available' , description: 'Device is being used or not available'
}) })
} }
} else { } else {
res.status(500).json({ res.status(404).json({
success: false success: false
, description: 'Bad device serial' , description: 'Bad device serial'
}) })
@ -99,7 +159,7 @@ function addDeviceToUser(req, res) {
}) })
} }
function deleteDeviceFromUser(req, res) { function deleteUserDeviceBySerial(req, res) {
var serial = req.swagger.params.serial.value var serial = req.swagger.params.serial.value
dbapi.loadDevice(serial) dbapi.loadDevice(serial)
@ -126,17 +186,23 @@ function deleteDeviceFromUser(req, res) {
res.status(202).json({ res.status(202).json({
success: true success: true
, description: 'Device Release request is accepted' , description: 'Device Release request is accepted. Check if device is successfully removed using pollingUrl'
, pollingUrl: util.format('%s://%s%s/user/devices/%s'
, req.protocol
, req.get('host')
, req.swagger.operation.api.basePath
, serial
)
}) })
} else { } else {
res.status(500).json({ res.status(401).json({
success: false success: false
, description: 'You cannot kick this device' , description: 'You cannot kick this device'
}) })
} }
} else { } else {
res.status(500).json({ res.status(404).json({
success: false success: false
, description: 'Bad device serial' , description: 'Bad device serial'
}) })
@ -144,47 +210,7 @@ function deleteDeviceFromUser(req, res) {
}) })
} }
function getUserDeviceBySerial(req, res) { function remoteConnectUserDeviceBySerial(req, res) {
var serial = req.swagger.params.serial.value
var fields = req.swagger.params.fields.value
dbapi.loadDevice(serial)
.then(function(device) {
if (device) {
datautil.normalize(device, req.user)
if (device.owner && device.owner === req.user.email) {
if(fields) {
device = _.pick(device, fields.split(','))
}
res.json({
success: true
, device: device
})
}
else {
res.status(404).json({
success: false
, description: 'device is not owned by you'
})
}
}
else {
res.status(404).json({
success: false
})
}
})
.catch(function(err) {
log.error('Failed to load device "%s": ', req.params.serial, err.stack)
res.status(500).json({
success: false
})
})
}
function connectDeviceBySerial(req, res) {
var serial = req.swagger.params.serial.value var serial = req.swagger.params.serial.value
dbapi.loadDevice(serial) dbapi.loadDevice(serial)
@ -192,7 +218,7 @@ function connectDeviceBySerial(req, res) {
if (device) { if (device) {
datautil.normalize(device, req.user) datautil.normalize(device, req.user)
if (device.present && device.ready && device.using && device.owner.email == req.user.email) { if (device.present && device.ready && device.using && device.owner.email === req.user.email) {
req.options.push.send([ req.options.push.send([
device.channel device.channel
, wireutil.envelope( , wireutil.envelope(
@ -202,11 +228,17 @@ function connectDeviceBySerial(req, res) {
res.status(202).json({ res.status(202).json({
success: true success: true
, description: 'Device Connect request is accepted' , description: 'Device Connect request is accepted. Check if device is successfully connected using pollingUrl'
, pollingUrl: util.format('%s://%s%s/user/devices/%s'
, req.protocol
, req.get('host')
, req.swagger.operation.api.basePath
, serial
)
}) })
} }
else { else {
res.status(500).json({ res.status(401).json({
success: false success: false
, description: 'Device is not owned by you or is not available' , description: 'Device is not owned by you or is not available'
}) })
@ -215,7 +247,7 @@ function connectDeviceBySerial(req, res) {
else { else {
res.status(404).json({ res.status(404).json({
success: false success: false
, description: 'Bad device serial' , description: 'Device not found'
}) })
} }
}) })
@ -227,7 +259,7 @@ function connectDeviceBySerial(req, res) {
}) })
} }
function disconnectDeviceBySerial(req, res) { function remoteDisconnectUserDeviceBySerial(req, res) {
var serial = req.swagger.params.serial.value var serial = req.swagger.params.serial.value
dbapi.loadDevice(serial) dbapi.loadDevice(serial)
@ -245,11 +277,17 @@ function disconnectDeviceBySerial(req, res) {
res.status(202).json({ res.status(202).json({
success: true success: true
, description: 'Device Disonnect request is accepted' , description: 'Device Disonnect request is accepted. Check if device is successfully disconnected using pollingUrl'
, pollingUrl: util.format('%s://%s%s/user/devices/%s'
, req.protocol
, req.get('host')
, req.swagger.operation.api.basePath
, serial
)
}) })
} }
else { else {
res.status(500).json({ res.status(401).json({
success: false success: false
, description: 'Device is not owned by you or is not available' , description: 'Device is not owned by you or is not available'
}) })
@ -258,7 +296,7 @@ function disconnectDeviceBySerial(req, res) {
else { else {
res.status(404).json({ res.status(404).json({
success: false success: false
, description: 'Bad device serial' , description: 'Device not found'
}) })
} }
}) })
@ -269,3 +307,26 @@ function disconnectDeviceBySerial(req, res) {
}) })
}) })
} }
function getUserAccessTokens(req, res) {
dbapi.loadAccessTokens(req.user.email)
.then(function(cursor) {
return Promise.promisify(cursor.toArray, cursor)()
.then(function(list) {
var titles = []
list.forEach(function(token) {
titles.push(token.title)
})
res.json({
success: true
, titles: titles
})
})
})
.catch(function(err) {
log.error('Failed to load tokens: ', err.stack)
res.status(500).json({
success: false
})
})
}

View file

@ -1,7 +1,7 @@
var dbapi = require('../../../db/api')
var jwtutil = require('../../../util/jwtutil') var jwtutil = require('../../../util/jwtutil')
var urlutil = require('../../../util/urlutil') var urlutil = require('../../../util/urlutil')
var logger = require('../../../util/logger') var logger = require('../../../util/logger')
var dbapi = require('../../../db/api')
var log = logger.createLogger('api:helpers:securityHandlers') var log = logger.createLogger('api:helpers:securityHandlers')
@ -11,7 +11,16 @@ module.exports = {
function accessTokenAuth(req, res, next) { function accessTokenAuth(req, res, next) {
if (req.headers.authorization) { if (req.headers.authorization) {
var tokenId = req.headers.authorization.split(" ")[1] var authHeader = req.headers.authorization.split(' ')
, format = authHeader[0]
, tokenId = authHeader[1]
if (format !== 'bearer') {
res.status(401).json({
success: false
, description: 'Authorization header should be in "bearer $AUTH_TOKEN" format'
})
}
if (tokenId) { if (tokenId) {
dbapi.loadAccessToken(tokenId) dbapi.loadAccessToken(tokenId)
@ -28,23 +37,23 @@ function accessTokenAuth(req, res, next) {
} }
}) })
} else { } else {
res.json(500, { res.status(500).json({
success: false success: false
}) })
} }
}) })
.catch(function(err) { .catch(function(err) {
log.error('Failed to load token: ', err.stack) log.error('Failed to load token: ', err.stack)
res.json(401, { res.status(401).json({
success: false, success: false,
description: 'Bad credentials' description: 'Bad Credentials'
}) })
}) })
} else { } else {
log.error('Bad Access Token Header') log.error('Bad Access Token Header')
res.json(401, { res.status(401).json({
success: false, success: false,
description: 'Bad credentials' description: 'Bad Credentials'
}) })
} }
} }
@ -67,9 +76,9 @@ function accessTokenAuth(req, res, next) {
.catch(next) .catch(next)
} }
else { else {
res.json(401, { res.status(401).json({
success: false, success: false,
description: 'Requires authentication' description: 'Requires Authentication'
}) })
} }
} }

View file

@ -2,12 +2,12 @@ swagger: "2.0"
info: info:
version: "2.0.0" version: "2.0.0"
title: Smartphone Test Farm title: Smartphone Test Farm
description: Control and manager real Smartphone devices from browser and restful apis description: Control and manages real Smartphone devices from browser and restful apis
license: license:
name: Apache-2.0 name: Apache-2.0
url: http://www.apache.org/licenses/LICENSE-2.0 url: http://www.apache.org/licenses/LICENSE-2.0
contact: contact:
name: STF Support name: STF Team
email: contact@openstf.io email: contact@openstf.io
url: http://openstf.io/ url: http://openstf.io/
basePath: /api/v1 basePath: /api/v1
@ -21,15 +21,15 @@ produces:
tags: tags:
- name: user - name: user
description: User Operations description: User Operations
- name: device - name: devices
description: Device Operations description: Device Operations
paths: paths:
/user: /user:
x-swagger-router-controller: user x-swagger-router-controller: user
get: get:
summary: User Profile summary: User Profile
description: The User Profile endpoint returns information about current authorized user. description: The User Profile endpoint returns information about current authorized user
operationId: getCurrentUser operationId: getUser
tags: tags:
- user - user
responses: responses:
@ -47,13 +47,19 @@ paths:
x-swagger-router-controller: user x-swagger-router-controller: user
get: get:
summary: List devices owned by current user summary: List devices owned by current user
description: The User Devices endpoint returns information about user group of current authorized user. description: The User Devices endpoint returns device list owner by current authorized user
operationId: getCurrentUserDevices operationId: getUserDevices
tags: tags:
- user - user
parameters:
- name: fields
in: query
description: Fields query parameter takes a comma seperated list of fields. Only listed field will be return in response
required: false
type: string
responses: responses:
"200": "200":
description: Current User Devices information description: Current User Devices List
schema: schema:
$ref: "#/definitions/DeviceListResponse" $ref: "#/definitions/DeviceListResponse"
default: default:
@ -63,21 +69,23 @@ paths:
security: security:
- accessTokenAuth: [] - accessTokenAuth: []
post: post:
summary: Add device to a user summary: Add a device to a user
description: The User Devices endpoint will request stf server for a new device. It will return request accepted if device is usable. description: The User Devices endpoint will request stf server for a new device. It will return request accepted if device is usable
operationId: addDeviceToUser operationId: addUserDevice
tags: tags:
- user - user
parameters: parameters:
- name: device - name: devices
in: body in: body
description: Device to add description: Device to add
required: true required: true
schema: schema:
$ref: "#/definitions/DeviceAddPayload" $ref: "#/definitions/AddUserDevicePayload"
responses: responses:
"202": "202":
description: Device Add Request Status description: Add User Device Request Status and polling Url
schema:
$ref: "#/definitions/AddUserDeviceResponse"
default: default:
description: Unexpected Error description: Unexpected Error
schema: schema:
@ -88,7 +96,7 @@ paths:
x-swagger-router-controller: user x-swagger-router-controller: user
get: get:
summary: Device Information summary: Device Information
description: The device enpoint return information about a single device. description: The device enpoint return information about device owned by user
operationId: getUserDeviceBySerial operationId: getUserDeviceBySerial
tags: tags:
- user - user
@ -105,9 +113,9 @@ paths:
type: string type: string
responses: responses:
"200": "200":
description: Device Information description: Delete User Device Request Status and polling Url
schema: schema:
$ref: "#/definitions/DeviceResponse" $ref: "#/definitions/DeleteUserDeviceBySerialResponse"
default: default:
description: Unexpected Error description: Unexpected Error
schema: schema:
@ -116,8 +124,8 @@ paths:
- accessTokenAuth: [] - accessTokenAuth: []
delete: delete:
summary: Release device from user summary: Release device from user
description: The User Devices endpoint will request for device release from stf server. description: The User Devices endpoint will request for device release from stf server. It will return request accepted if device is being used by current user
operationId: deleteDeviceFromUser operationId: deleteUserDeviceBySerial
tags: tags:
- user - user
parameters: parameters:
@ -142,7 +150,7 @@ paths:
post: post:
summary: Remote Connect summary: Remote Connect
description: The device connect endpoint will request stf server to connect remotely description: The device connect endpoint will request stf server to connect remotely
operationId: connectDeviceBySerial operationId: remoteConnectUserDeviceBySerial
tags: tags:
- user - user
parameters: parameters:
@ -153,7 +161,9 @@ paths:
type: string type: string
responses: responses:
"202": "202":
description: Device Connect Request Status description: Remote Connect User Device Request Status
schema:
$ref: "#/definitions/RemoteConnectUserDeviceResponse"
default: default:
description: Unexpected Error description: Unexpected Error
schema: schema:
@ -163,7 +173,7 @@ paths:
delete: delete:
summary: Remote Disconnect summary: Remote Disconnect
description: The device connect endpoint will request stf server to disconnect remotely description: The device connect endpoint will request stf server to disconnect remotely
operationId: disconnectDeviceBySerial operationId: remoteDisconnectUserDeviceBySerial
tags: tags:
- user - user
parameters: parameters:
@ -174,7 +184,9 @@ paths:
type: string type: string
responses: responses:
"202": "202":
description: Device Disconnect Request Status description: Remote Disonnect User Device Request Status
schema:
$ref: "#/definitions/RemoteDisconnectUserDeviceResponse"
default: default:
description: Unexpected Error description: Unexpected Error
schema: schema:
@ -185,8 +197,8 @@ paths:
x-swagger-router-controller: token x-swagger-router-controller: token
get: get:
summary: Access Tokens summary: Access Tokens
description: The Access Tokens endpoints returns titles of all the valid access tokens. description: The Access Tokens endpoints returns titles of all the valid access tokens
operationId: getAccessTokens operationId: getUserAccessTokens
tags: tags:
- user - user
responses: responses:
@ -201,13 +213,19 @@ paths:
security: security:
- accessTokenAuth: [] - accessTokenAuth: []
/devices: /devices:
x-swagger-router-controller: device x-swagger-router-controller: devices
get: get:
summary: Device List summary: Device List
description: The devices enpoint return list of all the STF devices including Disconnected and Offline description: The devices endpoint return list of all the STF devices including Disconnected and Offline
operationId: getDevices operationId: getDevices
tags: tags:
- device - devices
parameters:
- name: fields
in: query
description: Fields query parameter takes a comma seperated list of fields. Only listed field will be return in response
required: false
type: string
responses: responses:
"200": "200":
description: List of Devices description: List of Devices
@ -220,13 +238,13 @@ paths:
security: security:
- accessTokenAuth: [] - accessTokenAuth: []
/devices/{serial}: /devices/{serial}:
x-swagger-router-controller: device x-swagger-router-controller: devices
get: get:
summary: Device Information summary: Device Information
description: The device enpoint return information about a single device. description: The device enpoint return information about a single device
operationId: getDeviceBySerial operationId: getDeviceBySerial
tags: tags:
- device - devices
parameters: parameters:
- name: serial - name: serial
in: path in: path
@ -280,13 +298,37 @@ definitions:
properties: properties:
device: device:
type: object type: object
AddUserDeviceResponse:
required:
- pollingUrl
properties:
pollingUrl:
type: string
DeleteUserDeviceBySerialResponse:
required:
- pollingUrl
properties:
pollingUrl:
type: string
RemoteDisconnectUserDeviceResponse:
required:
- pollingUrl
properties:
pollingUrl:
type: string
RemoteConnectUserDeviceResponse:
required:
- pollingUrl
properties:
pollingUrl:
type: string
ErrorResponse: ErrorResponse:
required: required:
- message - message
properties: properties:
message: message:
type: string type: string
DeviceAddPayload: AddUserDevicePayload:
description: payload object for adding device to user description: payload object for adding device to user
required: required:
- serial - serial
@ -295,11 +337,11 @@ definitions:
description: Device Serial description: Device Serial
type: string type: string
timeout: timeout:
description: Device timeout in ms. If device is kept idle for this period, it will be automatically disconnected. Default is provider group timeout. description: Device timeout in ms. If device is kept idle for this period, it will be automatically disconnected. Default is provider group timeout
type: integer type: integer
securityDefinitions: securityDefinitions:
accessTokenAuth: accessTokenAuth:
type: apiKey type: apiKey
name: accessTokenAuth name: authorization
in: header in: header