Skip to content

Instantly share code, notes, and snippets.

@zmajstor
Last active August 29, 2015 14:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zmajstor/2587f9ff72c0ddfacff1 to your computer and use it in GitHub Desktop.
Save zmajstor/2587f9ff72c0ddfacff1 to your computer and use it in GitHub Desktop.
Simple API sample (responds with json or xml)
class API::V1::DevicesController < ApplicationController
before_filter :authenticate!
before_filter :find_device, only: [:update, :destroy, :capability, :push_mdm_commands]
skip_before_filter :verify_authenticity_token
respond_to :json, :xml
rescue_from ActiveRecord::RecordNotFound, with: :record_not_found_error
# curl -v -k -X GET -H "Content-Type: application/json" -H "Accept: application/json" -H 'Authorization: Token token=justesting' https://localhost:8443/api/v1/devices
# default response format is json, append .xml for XML output: https://localhost:8443/api/v1/devices.xml
# TODO implement page-ing and remove limit
def index
devices = Device.api_select.order(:id).limit(300)
respond_with devices
end
# curl -v -k -X GET -H "Content-Type: application/json" -H "Accept: application/json" -H 'Authorization: Token token=justesting' https://localhost:8443/api/v1/devices/filter_by/username/zm
# https://localhost:8443/api/v1/devices/filter_by/username/zm.xml
def filter_devices
if Device.api_attrs.include?(params[:field])
@devices = Device.api_filter_by(params[:field] => params[:value]).limit(300) if params[:value]
respond_with @devices
else
respond_with_error "Invalid filter"
end
end
# https://localhost:8443/api/v1/devices/3
# https://localhost:8443/api/v1/devices/3.xml
def show
if (@device = Device.api_filter_by({ id: params[:id].to_i }, { all: true }).first)
respond_with @device
else
respond_with_error "Invalid device"
end
end
# https://localhost:8443/api/v1/devices/3/capability
# https://localhost:8443/api/v1/devices/3/capability.xml
def capability
if (device_mdm_commands = @device.capable_for_mdm_commands)
respond_with({ mdm_commands: device_mdm_commands })
else
respond_with_error "Device capability error"
end
end
# show array of editable attrs
def editable
respond_with(Device.api_attrs(update: true))
end
# curl -v -k -X POST -H "Content-Type: application/json" -H "Accept: application/json" -H 'Authorization: Basic encoded==' -d '{"device": {"serial":"12345"}}' https://localhost:8443/api/v1/devices/
# curl -v -k -X POST -H "Content-Type: application/json" -H "Accept: application/json" -H 'Authorization: Token token=justesting' -d '{"device": {"serial":"12345"}}' https://localhost:8443/api/v1/devices/
def create
serial = params[:device][:serial].to_s.upcase
if (@device = Device.find_or_create_by_serial(serial))
respond_with(@device, only: :id, status: :created, location: api_v1_device_path(@device))
else
respond_with_error "Device create failed for serial #{serial}"
end
end
# curl -v -k -X PUT -H "Content-Type: application/json" -H "Accept: application/json" -H 'Authorization: Token token=justesting' -d '{"device": {"note":"12345"}}' https://localhost:8443/api/v1/devices/8
def update
valid_keys = Device.api_attrs(update: true).map(&:to_sym)
if @device.update_attributes(params[:device].slice(*valid_keys))
respond_with(@device, only: :id, status: :ok, location: api_v1_device_path(@device))
else
respond_with_error @device.errors
end
end
# Push MDM Commands to Device curl sample:
# curl -v -k -X POST -H "Content-Type: application/json" -H "Accept: application/json" -H 'Authorization: Basic encoded==' -d '{"mdm_commands": [{"request_type":"DeviceInformation"}, {"request_type":"RemoveProfile", "identifier":"net.promdm.profile4", "force":"true"} ]}' https://localhost:8443/api/v1/devices/3/push_mdm_commands
def push_mdm_commands
if params['mdm_commands'].respond_to? :each
params['mdm_commands'].each do |cmd|
if cmd['request_type'].present?
queued, msg = @device.queue_deduplicated_command(cmd.symbolize_keys)
@device.errors.add(:base, "#{msg} on MDM Command #{cmd} for device id #{@device.id}") unless queued
end
@device.errors.add(:base, "push_notification failed for device id #{@device.id}") unless @device.push_notification
end
else
@device.errors.add(:base, "invalid mdm_commands")
end
if @device.errors.empty?
head :no_content, status: :ok, nothing: true
else
respond_with_error @device.errors.full_messages
end
rescue => e
logger.error "push_mdm_commands: #{e.message}"
respond_with_error e.message
end
# curl -v -k -X DELETE -H "Content-Type: application/json" -H "Accept: application/json" -H 'Authorization: Token token=justesting' https://localhost:8443/api/v1/devices/1
def destroy
if @device.destroy
head :no_content, status: :ok, nothing: true
else
respond_with_error "Device delete failed"
end
end
protected
def authenticate!
authenticate_token || render_unauthorized
end
def authenticate_token
authenticate_with_http_token do |token, options|
token == API_TOKEN if defined?(API_TOKEN)
end
end
def render_unauthorized
self.headers['WWW-Authenticate'] = 'Token realm="Application"'
respond_with({ error: 'Bad credentials' }, status: 401, location: nil)
end
def respond_with_error(msg)
respond_with({ error: msg }, status: :unprocessable_entity, location: nil)
end
def record_not_found_error
# head :not_found, nothing: true
respond_with({ error: 'Resource not found' }, status: 404, location: nil)
end
private
def find_device
@device = Device.find(params[:id])
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment