Store client's user agent on Asciicast record
This commit is contained in:
parent
e4cb9c0657
commit
d74ead2263
@ -3,7 +3,7 @@ class Api::AsciicastsController < ApplicationController
|
|||||||
skip_before_filter :verify_authenticity_token
|
skip_before_filter :verify_authenticity_token
|
||||||
|
|
||||||
def create
|
def create
|
||||||
asciicast = AsciicastCreator.new.create(params[:asciicast])
|
asciicast = AsciicastCreator.new.create(params[:asciicast], request.headers)
|
||||||
render :text => asciicast_url(asciicast), :status => :created,
|
render :text => asciicast_url(asciicast), :status => :created,
|
||||||
:location => asciicast
|
:location => asciicast
|
||||||
rescue ActiveRecord::RecordInvalid => e
|
rescue ActiveRecord::RecordInvalid => e
|
||||||
|
@ -5,14 +5,12 @@ class AsciicastDecorator < ApplicationDecorator
|
|||||||
THUMBNAIL_HEIGHT = 10
|
THUMBNAIL_HEIGHT = 10
|
||||||
|
|
||||||
def os
|
def os
|
||||||
return 'unknown' if uname.blank?
|
if user_agent.present?
|
||||||
|
os_from_user_agent
|
||||||
if uname =~ /Linux/
|
elsif uname.present?
|
||||||
'Linux'
|
os_from_uname
|
||||||
elsif uname =~ /Darwin/
|
|
||||||
'OSX'
|
|
||||||
else
|
else
|
||||||
uname.split(' ', 2)[0]
|
'unknown'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -99,4 +97,27 @@ class AsciicastDecorator < ApplicationDecorator
|
|||||||
"%02d:%02d" % [minutes, seconds]
|
"%02d:%02d" % [minutes, seconds]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def os_from_user_agent
|
||||||
|
match = user_agent.match(/^[^\s]+\s+\(([^\)]+)\)/)
|
||||||
|
os = match[1].split(/(\s|-)/).first
|
||||||
|
|
||||||
|
guess_os(os)
|
||||||
|
end
|
||||||
|
|
||||||
|
def os_from_uname
|
||||||
|
guess_os(uname)
|
||||||
|
end
|
||||||
|
|
||||||
|
def guess_os(text)
|
||||||
|
if text =~ /Linux/
|
||||||
|
'Linux'
|
||||||
|
elsif text =~ /Darwin/
|
||||||
|
'OSX'
|
||||||
|
else
|
||||||
|
text.split(' ', 2)[0]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -1,21 +1,23 @@
|
|||||||
class AsciicastParams
|
class AsciicastParams
|
||||||
|
|
||||||
def initialize(input)
|
def initialize(params, headers)
|
||||||
@input = input
|
@params = params
|
||||||
|
@headers = headers
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_h
|
def to_h
|
||||||
attributes = {
|
attributes = {
|
||||||
:stdout_data => input[:stdout],
|
:stdout_data => params[:stdout],
|
||||||
:stdout_timing => input[:stdout_timing],
|
:stdout_timing => params[:stdout_timing],
|
||||||
:stdin_data => input[:stdin],
|
:stdin_data => params[:stdin],
|
||||||
:stdin_timing => input[:stdin_timing],
|
:stdin_timing => params[:stdin_timing],
|
||||||
:username => meta['username'],
|
:username => meta['username'],
|
||||||
:duration => meta['duration'],
|
:duration => meta['duration'],
|
||||||
:recorded_at => meta['recorded_at'],
|
:recorded_at => meta['recorded_at'],
|
||||||
:title => meta['title'],
|
:title => meta['title'],
|
||||||
:command => meta['command'],
|
:command => meta['command'],
|
||||||
:shell => meta['shell'],
|
:shell => meta['shell'],
|
||||||
|
:user_agent => headers['User-Agent'],
|
||||||
:uname => meta['uname'],
|
:uname => meta['uname'],
|
||||||
:terminal_lines => meta['term']['lines'],
|
:terminal_lines => meta['term']['lines'],
|
||||||
:terminal_columns => meta['term']['columns'],
|
:terminal_columns => meta['term']['columns'],
|
||||||
@ -29,10 +31,10 @@ class AsciicastParams
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
attr_reader :input
|
attr_reader :params, :headers
|
||||||
|
|
||||||
def meta
|
def meta
|
||||||
@meta ||= JSON.parse(input[:meta].read)
|
@meta ||= JSON.parse(params[:meta].read)
|
||||||
end
|
end
|
||||||
|
|
||||||
def assign_user_or_token(attributes, meta)
|
def assign_user_or_token(attributes, meta)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
class AsciicastCreator
|
class AsciicastCreator
|
||||||
|
|
||||||
def create(attributes)
|
def create(attributes, headers)
|
||||||
attributes = AsciicastParams.new(attributes).to_h
|
attributes = AsciicastParams.new(attributes, headers).to_h
|
||||||
asciicast = Asciicast.create!(attributes, without_protection: true)
|
asciicast = Asciicast.create!(attributes, without_protection: true)
|
||||||
AsciicastWorker.perform_async(asciicast.id)
|
AsciicastWorker.perform_async(asciicast.id)
|
||||||
|
|
||||||
|
5
db/migrate/20131011181418_add_user_agent_to_asciicast.rb
Normal file
5
db/migrate/20131011181418_add_user_agent_to_asciicast.rb
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
class AddUserAgentToAsciicast < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
add_column :asciicasts, :user_agent, :string
|
||||||
|
end
|
||||||
|
end
|
@ -11,7 +11,7 @@
|
|||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema.define(version: 20130828162232) do
|
ActiveRecord::Schema.define(version: 20131011181418) do
|
||||||
|
|
||||||
create_table "asciicasts", force: true do |t|
|
create_table "asciicasts", force: true do |t|
|
||||||
t.integer "user_id"
|
t.integer "user_id"
|
||||||
@ -40,6 +40,7 @@ ActiveRecord::Schema.define(version: 20130828162232) do
|
|||||||
t.boolean "time_compression", default: true, null: false
|
t.boolean "time_compression", default: true, null: false
|
||||||
t.integer "views_count", default: 0, null: false
|
t.integer "views_count", default: 0, null: false
|
||||||
t.string "stdout_frames"
|
t.string "stdout_frames"
|
||||||
|
t.string "user_agent"
|
||||||
end
|
end
|
||||||
|
|
||||||
add_index "asciicasts", ["created_at"], name: "index_asciicasts_on_created_at", using: :btree
|
add_index "asciicasts", ["created_at"], name: "index_asciicasts_on_created_at", using: :btree
|
||||||
|
@ -14,7 +14,8 @@ describe Api::AsciicastsController do
|
|||||||
let(:asciicast) { stub_model(Asciicast, :id => 666) }
|
let(:asciicast) { stub_model(Asciicast, :id => 666) }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
allow(creator).to receive(:create).with(attributes) { asciicast }
|
allow(creator).to receive(:create).
|
||||||
|
with(attributes, kind_of(ActionDispatch::Http::Headers)) { asciicast }
|
||||||
post :create, :asciicast => attributes
|
post :create, :asciicast => attributes
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -33,7 +34,8 @@ describe Api::AsciicastsController do
|
|||||||
let(:full_messages) { ['This is invalid'] }
|
let(:full_messages) { ['This is invalid'] }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
allow(creator).to receive(:create).with(attributes).
|
allow(creator).to receive(:create).
|
||||||
|
with(attributes, kind_of(ActionDispatch::Http::Headers)).
|
||||||
and_raise(ActiveRecord::RecordInvalid.new(asciicast))
|
and_raise(ActiveRecord::RecordInvalid.new(asciicast))
|
||||||
post :create, :asciicast => attributes
|
post :create, :asciicast => attributes
|
||||||
end
|
end
|
||||||
@ -42,7 +44,7 @@ describe Api::AsciicastsController do
|
|||||||
expect(response.status).to eq(422)
|
expect(response.status).to eq(422)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns the full error messages as the content body' do
|
it 'returns nothing as the content body' do
|
||||||
expect(response.body).to be_blank
|
expect(response.body).to be_blank
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -11,7 +11,38 @@ describe AsciicastDecorator do
|
|||||||
describe '#os' do
|
describe '#os' do
|
||||||
let(:method) { :os }
|
let(:method) { :os }
|
||||||
|
|
||||||
context 'for Linux-like uname' do
|
context 'when user_agent is present' do
|
||||||
|
context 'and the OS is Linux' do
|
||||||
|
before do
|
||||||
|
asciicast.user_agent =
|
||||||
|
"asciinema/0.9.7 " \
|
||||||
|
"(Linux-3.8.0-30-generic-x86_64-with-Ubuntu-13.04-raring)"
|
||||||
|
end
|
||||||
|
|
||||||
|
it { should == 'Linux' }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'and the OS is OSX' do
|
||||||
|
before do
|
||||||
|
asciicast.user_agent = "asciinema/0.9.7 (Darwin-10.0.0-i386-64bit)"
|
||||||
|
end
|
||||||
|
|
||||||
|
it { should == 'OSX' }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'and the OS is other' do
|
||||||
|
before do
|
||||||
|
asciicast.user_agent = "asciinema/0.9.7 (Jola Misio Foo)"
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should return first token' do
|
||||||
|
should == 'Jola'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when uname is present' do
|
||||||
|
context "and it's Linux-like" do
|
||||||
before do
|
before do
|
||||||
asciicast.uname = "Linux t430u 3.5.0-18-generic #29-Ubuntu SMP"
|
asciicast.uname = "Linux t430u 3.5.0-18-generic #29-Ubuntu SMP"
|
||||||
end
|
end
|
||||||
@ -19,7 +50,7 @@ describe AsciicastDecorator do
|
|||||||
it { should == 'Linux' }
|
it { should == 'Linux' }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'for Darwin-like uname' do
|
context "and it's Darwin-like" do
|
||||||
before do
|
before do
|
||||||
asciicast.uname = "Darwin local 10.3.0 Darwin Kernel Version 10.3.0"
|
asciicast.uname = "Darwin local 10.3.0 Darwin Kernel Version 10.3.0"
|
||||||
end
|
end
|
||||||
@ -27,7 +58,7 @@ describe AsciicastDecorator do
|
|||||||
it { should == 'OSX' }
|
it { should == 'OSX' }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'for other systems' do
|
context "and it's other" do
|
||||||
before do
|
before do
|
||||||
asciicast.uname = "Jola Misio Foo"
|
asciicast.uname = "Jola Misio Foo"
|
||||||
end
|
end
|
||||||
@ -36,17 +67,20 @@ describe AsciicastDecorator do
|
|||||||
should == 'Jola'
|
should == 'Jola'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context 'when uname is nil' do
|
context 'when user_agent and uname are nil' do
|
||||||
before do
|
before do
|
||||||
|
asciicast.user_agent = nil
|
||||||
asciicast.uname = nil
|
asciicast.uname = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
it { should == 'unknown' }
|
it { should == 'unknown' }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when uname is blank string' do
|
context 'when user_agent and uname are a blank string' do
|
||||||
before do
|
before do
|
||||||
|
asciicast.user_agent = ' '
|
||||||
asciicast.uname = ' '
|
asciicast.uname = ' '
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -2,13 +2,14 @@ require 'spec_helper'
|
|||||||
|
|
||||||
describe AsciicastParams do
|
describe AsciicastParams do
|
||||||
|
|
||||||
let(:asciicast_params) { described_class.new(input) }
|
let(:asciicast_params) { described_class.new(input, headers) }
|
||||||
|
|
||||||
let(:input) { {
|
let(:input) { {
|
||||||
:meta => meta_file,
|
:meta => meta_file,
|
||||||
:stdout => stdout_data_file,
|
:stdout => stdout_data_file,
|
||||||
:stdout_timing => stdout_timing_file
|
:stdout_timing => stdout_timing_file
|
||||||
} }
|
} }
|
||||||
|
let(:headers) { { 'User-Agent' => 'asciinema/0.9.7' } }
|
||||||
|
|
||||||
let(:stdout_data_file) { double('stdout_data_file') }
|
let(:stdout_data_file) { double('stdout_data_file') }
|
||||||
let(:stdout_timing_file) { double('stdout_timing_file') }
|
let(:stdout_timing_file) { double('stdout_timing_file') }
|
||||||
@ -25,6 +26,7 @@ describe AsciicastParams do
|
|||||||
:title => 'bashing :)',
|
:title => 'bashing :)',
|
||||||
:command => '/bin/bash',
|
:command => '/bin/bash',
|
||||||
:shell => '/bin/zsh',
|
:shell => '/bin/zsh',
|
||||||
|
:user_agent => 'asciinema/0.9.7',
|
||||||
:uname => 'Linux 3.9.9-302.fc19.x86_64 #1 SMP ' +
|
:uname => 'Linux 3.9.9-302.fc19.x86_64 #1 SMP ' +
|
||||||
'Sat Jul 6 13:41:07 UTC 2013 x86_64',
|
'Sat Jul 6 13:41:07 UTC 2013 x86_64',
|
||||||
:terminal_columns => 96,
|
:terminal_columns => 96,
|
||||||
|
@ -7,13 +7,14 @@ describe AsciicastCreator do
|
|||||||
describe '#create' do
|
describe '#create' do
|
||||||
let(:asciicast) { stub_model(Asciicast, id: 666) }
|
let(:asciicast) { stub_model(Asciicast, id: 666) }
|
||||||
let(:input_attrs) { { a: 'A' } }
|
let(:input_attrs) { { a: 'A' } }
|
||||||
|
let(:headers) { { 'User-Agent' => 'asciinema/0.9.7' } }
|
||||||
let(:prepared_attrs) { { b: 'B' } }
|
let(:prepared_attrs) { { b: 'B' } }
|
||||||
|
|
||||||
subject { creator.create(input_attrs) }
|
subject { creator.create(input_attrs, headers) }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
allow(AsciicastParams).to receive(:new).
|
allow(AsciicastParams).to receive(:new).
|
||||||
with(input_attrs) { prepared_attrs }
|
with(input_attrs, headers) { prepared_attrs }
|
||||||
allow(Asciicast).to receive(:create!) { asciicast }
|
allow(Asciicast).to receive(:create!) { asciicast }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user