Accept version 1 asciicasts

private-asciicasts
Marcin Kulik 9 years ago
parent 78a2ba9ea9
commit c6cc9fbdbc

@ -30,6 +30,8 @@ gem 'warden', '~> 1.2.3'
gem 'pundit', '~> 0.3.0'
gem 'rack-robustness', '~> 1.1.0'
gem 'rack-rewrite', '~> 1.5.0'
gem 'oj'
gem 'oj_mimic_json'
group :development do
gem 'quiet_assets', '~> 1.0.1'

@ -167,6 +167,8 @@ GEM
net-ssh (>= 2.6.5)
newrelic_rpm (3.7.1.182)
nokogiri (1.5.11)
oj (2.11.5)
oj_mimic_json (1.0.1)
open4 (1.3.0)
parallel (0.7.1)
pg (0.17.0)
@ -354,6 +356,8 @@ DEPENDENCIES
jquery-rails (~> 3.0.4)
kaminari (~> 0.14.1)
newrelic_rpm
oj
oj_mimic_json
open4 (~> 1.3.0)
pg (~> 0.14)
poltergeist (~> 1.5.0)

@ -30,22 +30,42 @@ module Api
private
def parse_request
attrs, username, token = parse_format_0_request
if legacy_format?
attrs, username, token = parse_format_0_request
else
attrs, username, token = parse_format_1_request
end
user = User.for_api_token!(token, username)
[attrs, user]
end
def legacy_format?
!params[:asciicast].try(:respond_to?, :read)
end
def parse_format_0_request
meta = JSON.parse(params[:asciicast][:meta].read)
username, token = authenticate_with_http_basic { |username, password| [username, password] }
username, token = basic_auth_credentials
token ||= meta.delete('user_token')
username ||= meta.delete('username')
attrs = AsciicastParams.build(params[:asciicast].merge(meta: meta), request.user_agent)
attrs = AsciicastParams.from_format_0_request(params[:asciicast].merge(meta: meta), request.user_agent)
[attrs, username, token]
end
def parse_format_1_request
username, token = basic_auth_credentials
attrs = AsciicastParams.from_format_1_request(params[:asciicast], request.user_agent)
[attrs, username, token]
end
def basic_auth_credentials
authenticate_with_http_basic { |username, password| [username, password] }
end
def asciicast_creator
AsciicastCreator.new
end

@ -7,10 +7,12 @@ class Asciicast < ActiveRecord::Base
mount_uploader :stdout_data, StdoutDataUploader
mount_uploader :stdout_timing, StdoutTimingUploader
mount_uploader :stdout_frames, StdoutFramesUploader
mount_uploader :file, AsciicastUploader
serialize :snapshot, ActiveSupportJsonProxy
validates :stdout_data, :stdout_timing, :presence => true
validates :stdout_data, :stdout_timing, presence: true, unless: :file
validates :file, presence: true, unless: :stdout_data
validates :terminal_columns, :terminal_lines, :duration, :presence => true
validates :snapshot_at, numericality: { greater_than: 0, allow_blank: true }

@ -1,9 +1,10 @@
class AsciicastParams
def self.build(params, user_agent)
def self.from_format_0_request(params, user_agent)
meta = params[:meta]
attributes = {
version: 0,
command: meta['command'],
duration: meta['duration'],
shell: meta['shell'],
@ -17,7 +18,7 @@ class AsciicastParams
title: meta['title'],
}
if meta['uname'] # old client, with useless, random user_agent
if meta['uname'] # old client, with useless user_agent
attributes[:uname] = meta['uname']
else
attributes[:user_agent] = user_agent
@ -26,4 +27,36 @@ class AsciicastParams
attributes
end
def self.from_format_1_request(asciicast_file, user_agent)
asciicast = Oj.sc_parse(AsciicastHandler.new, asciicast_file)
env = asciicast['env']
{
version: 1,
terminal_columns: asciicast['width'],
terminal_lines: asciicast['height'],
duration: asciicast['duration'],
command: asciicast['command'],
title: asciicast['title'],
shell: env && env['SHELL'],
terminal_type: env && env['TERM'],
file: asciicast_file,
user_agent: user_agent,
}
end
class AsciicastHandler < ::Oj::ScHandler
META_ATTRIBUTES = %w[width height duration command title env SHELL TERM]
def hash_start
{}
end
def hash_set(h, k, v)
if META_ATTRIBUTES.include?(k)
h[k] = v
end
end
end
end

@ -0,0 +1,3 @@
class AsciicastUploader < BaseUploader
end

@ -0,0 +1,5 @@
class AddVersionToAsciicasts < ActiveRecord::Migration
def change
add_column :asciicasts, :version, :integer, default: 0, null: false
end
end

@ -0,0 +1,5 @@
class AddFileToAsciicast < ActiveRecord::Migration
def change
add_column :asciicasts, :file, :string
end
end

@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20141129115837) do
ActiveRecord::Schema.define(version: 20150227112949) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@ -53,6 +53,8 @@ ActiveRecord::Schema.define(version: 20141129115837) do
t.string "user_agent"
t.string "theme_name"
t.float "snapshot_at"
t.integer "version", default: 0, null: false
t.string "file"
end
add_index "asciicasts", ["created_at"], name: "index_asciicasts_on_created_at", using: :btree

@ -37,6 +37,18 @@ describe "Asciicast creation" do
before { subject }
it 'creates asciicast version 0' do
expect(created_asciicast.version).to eq(0)
end
it 'creates asciicast with given stdout data file' do
expect(created_asciicast.stdout_data).to_not be(nil)
end
it 'creates asciicast with given stdout timing file' do
expect(created_asciicast.stdout_timing).to_not be(nil)
end
it 'creates asciicast with given command' do
expect(created_asciicast.command).to eq('/bin/bash')
end
@ -120,6 +132,18 @@ describe "Asciicast creation" do
before { subject }
it 'creates asciicast version 0' do
expect(created_asciicast.version).to eq(0)
end
it 'creates asciicast with given stdout data file' do
expect(created_asciicast.stdout_data).to_not be(nil)
end
it 'creates asciicast with given stdout timing file' do
expect(created_asciicast.stdout_timing).to_not be(nil)
end
it 'creates asciicast with given command' do
expect(created_asciicast.command).to eq('/bin/bash')
end
@ -148,7 +172,7 @@ describe "Asciicast creation" do
expect(created_asciicast.title).to eq('bashing :)')
end
it 'creates asciicast with given uname' do
it 'creates asciicast with nil uname' do
expect(created_asciicast.uname).to be(nil)
end
@ -203,6 +227,18 @@ describe "Asciicast creation" do
before { subject }
it 'creates asciicast version 0' do
expect(created_asciicast.version).to eq(0)
end
it 'creates asciicast with given stdout data file' do
expect(created_asciicast.stdout_data).to_not be(nil)
end
it 'creates asciicast with given stdout timing file' do
expect(created_asciicast.stdout_timing).to_not be(nil)
end
it 'creates asciicast with given command' do
expect(created_asciicast.command).to eq('/bin/bash')
end
@ -231,7 +267,7 @@ describe "Asciicast creation" do
expect(created_asciicast.title).to eq('bashing :)')
end
it 'creates asciicast with given uname' do
it 'creates asciicast with nil uname' do
expect(created_asciicast.uname).to be(nil)
end
@ -270,4 +306,90 @@ describe "Asciicast creation" do
end
end
context 'format 1' do
subject { make_request }
def make_request
post '/api/asciicasts',
{ asciicast: fixture_file('1/asciicast.json', 'application/json') },
headers('kill', 'f33e6188-f53c-11e2-abf4-84a6c827e88b', 'asciinema/1.0.0 gc/go1.3 jola-amd64')
end
before { subject }
it 'creates asciicast version 1' do
expect(created_asciicast.version).to eq(1)
end
it 'creates asciicast with given file' do
expect(created_asciicast.file).to_not be(nil)
end
it 'creates asciicast with given command' do
expect(created_asciicast.command).to eq('/bin/bash')
end
it 'creates asciicast with given duration' do
expect(created_asciicast.duration).to eq(11.146430015564)
end
it 'creates asciicast with given shell' do
expect(created_asciicast.shell).to eq('/bin/zsh')
end
it 'creates asciicast with given terminal type' do
expect(created_asciicast.terminal_type).to eq('screen-256color')
end
it 'creates asciicast with given terminal width' do
expect(created_asciicast.terminal_columns).to eq(96)
end
it 'creates asciicast with given terminal height' do
expect(created_asciicast.terminal_lines).to eq(26)
end
it 'creates asciicast with given title' do
expect(created_asciicast.title).to eq('bashing :)')
end
it 'creates asciicast with nil uname' do
expect(created_asciicast.uname).to be(nil)
end
it 'creates asciicast with given user agent' do
expect(created_asciicast.user_agent).to eq('asciinema/1.0.0 gc/go1.3 jola-amd64')
end
context 'when a user with given token does not exist' do
let(:created_user) { User.last }
it 'creates new user with given username and token' do
expect(created_user.temporary_username).to eq('kill')
expect(created_user.api_tokens.first.token).to eq('f33e6188-f53c-11e2-abf4-84a6c827e88b')
end
it 'creates asciicast assigned to newly created user' do
expect(created_asciicast.user).to eq(created_user)
end
end
context 'when a user with given token exists' do
let(:user) { User.create_with_token('f33e6188-f53c-11e2-abf4-84a6c827e88b', 'kill') }
subject do
user
make_request
end
it 'creates asciicast assigned to a user with given token' do
expect(created_asciicast.user).to eq(user)
end
end
it 'returns the URL to the uploaded asciicast' do
expect(response.body).to eq(asciicast_url(created_asciicast))
end
end
end

@ -0,0 +1,16 @@
{
"version": 1,
"width": 96,
"height": 26,
"duration": 11.146430015564,
"command": "/bin/bash",
"title": "bashing :)",
"env": {
"TERM": "screen-256color",
"SHELL": "/bin/zsh"
},
"stdout": [
[1.234567, "foo bar"],
[5.678987, "baz qux"]
]
}
Loading…
Cancel
Save