Create dummy users for new api tokens

openid
Marcin Kulik 11 years ago
parent 74d7bb0156
commit 2ceea32cc4

@ -24,10 +24,10 @@ class UserDecorator < ApplicationDecorator
private
def wrap_with_link(html)
if id
h.link_to html, h.profile_path(model), title: nickname
else
if dummy
html
else
h.link_to html, h.profile_path(model), title: nickname
end
end

@ -4,43 +4,31 @@ class AsciicastParams
meta = JSON.parse(params[:meta].read)
attributes = {
stdout_data: params[:stdout],
stdout_timing: params[:stdout_timing],
stdin_data: params[:stdin],
stdin_timing: params[:stdin_timing],
username: meta['username'],
duration: meta['duration'],
title: meta['title'],
command: meta['command'],
duration: meta['duration'],
shell: meta['shell'],
terminal_lines: meta['term']['lines'],
stdin_data: params[:stdin],
stdin_timing: params[:stdin_timing],
stdout_data: params[:stdout],
stdout_timing: params[:stdout_timing],
terminal_columns: meta['term']['columns'],
terminal_lines: meta['term']['lines'],
terminal_type: meta['term']['type'],
title: meta['title'],
user: get_user(meta)
}
if meta['uname']
if meta['uname'] # old client, with useless, random user_agent
attributes[:uname] = meta['uname']
else
attributes[:user_agent] = user_agent
end
assign_user_or_token(attributes, meta)
attributes
end
def self.assign_user_or_token(attributes, meta)
token = meta['user_token']
if token.present?
api_token = ApiToken.find_by_token(token)
if api_token
attributes[:user_id] = api_token.user_id
else
attributes[:api_token] = token
end
end
def self.get_user(attributes)
User.for_api_token(attributes['user_token'], attributes['username'])
end
end

@ -10,7 +10,9 @@ class User < ActiveRecord::Base
attr_accessible :nickname, :email, :name
validates :nickname, :email, presence: true, uniqueness: true
validates :nickname, presence: true
validates :nickname, uniqueness: { scope: :dummy }, unless: :dummy
validates :email, presence: true, uniqueness: true, unless: :dummy
before_create :generate_auth_token
@ -22,6 +24,26 @@ class User < ActiveRecord::Base
where(email: email).first
end
def self.for_api_token(token, username)
return nil if token.blank?
user = User.joins(:api_tokens).where('api_tokens.token' => token).first
user ? user : create_user_with_token(token, username)
end
def self.create_user_with_token(token, username)
username = 'anonymous' if username.blank?
transaction do |tx|
user = User.new
user.dummy = true
user.nickname = username
user.save!
user.add_api_token(token)
user
end
end
def self.generate_auth_token
SecureRandom.urlsafe_base64
end

@ -0,0 +1,6 @@
class AddDummyToUsers < ActiveRecord::Migration
def change
add_column :users, :dummy, :boolean, default: false, null: false
add_index :users, :dummy
end
end

@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20140210153648) do
ActiveRecord::Schema.define(version: 20140211152727) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@ -91,13 +91,15 @@ ActiveRecord::Schema.define(version: 20140210153648) do
t.string "email"
t.string "name"
t.string "avatar_url"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "nickname", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "nickname", null: false
t.string "auth_token"
t.boolean "dummy", default: false, null: false
end
add_index "users", ["auth_token"], name: "index_users_on_auth_token", using: :btree
add_index "users", ["dummy"], name: "index_users_on_dummy", using: :btree
add_index "users", ["email"], name: "index_users_on_email", using: :btree
add_index "users", ["nickname"], name: "index_users_on_nickname", using: :btree
add_index "users", ["provider", "uid"], name: "index_users_on_provider_and_uid", unique: true, using: :btree

@ -13,9 +13,9 @@ describe UserDecorator do
allow(h).to receive(:profile_path).with(user) { '/path' }
end
context "when user has id" do
context "when user is real" do
before do
user.id = 1
user.dummy = false
end
it "is a nickname link to user's profile" do
@ -23,9 +23,9 @@ describe UserDecorator do
end
end
context "when user has no id" do
context "when user is dummy" do
before do
user.id = nil
user.dummy = true
end
it "is user's nickname" do
@ -44,9 +44,9 @@ describe UserDecorator do
allow(decorator).to receive(:avatar_image_tag) { '<img ...>'.html_safe }
end
context "when user has id" do
context "when user is real" do
before do
user.id = 1
user.dummy = false
end
it "is an avatar link to user's profile" do
@ -54,9 +54,9 @@ describe UserDecorator do
end
end
context "when user has no id" do
context "when user is dummy" do
before do
user.id = nil
user.dummy = true
end
it "is user's avatar image" do

@ -1,4 +1,5 @@
require 'spec_helper'
require 'stringio'
describe AsciicastParams do
@ -6,86 +7,60 @@ describe AsciicastParams do
subject { described_class.build(input, user_agent) }
let(:input) { {
meta: meta_file,
meta: StringIO.new(meta.to_json),
stdout: stdout_data_file,
stdout_timing: stdout_timing_file
stdout_timing: stdout_timing_file,
} }
let(:user_agent) { 'asciinema/0.9.7' }
let(:stdout_data_file) { double('stdout_data_file') }
let(:stdout_timing_file) { double('stdout_timing_file') }
let(:now) { DateTime.new(2014) }
let(:required_attrs) { {
stdout_data: stdout_data_file,
stdout_timing: stdout_timing_file,
stdin_data: nil,
stdin_timing: nil,
username: 'kill',
duration: 11.146430015563965,
title: 'bashing :)',
let(:meta) { {
command: '/bin/bash',
duration: 11.146430015563965,
shell: '/bin/zsh',
term: { lines: 26, columns: 96, type: 'screen-256color' },
title: 'bashing :)',
user_token: 'f33e6188-f53c-11e2-abf4-84a6c827e88b',
username: 'kill',
} }
let(:user) { double('user') }
let(:expected_attrs) { {
command: '/bin/bash',
duration: 11.146430015563965,
shell: '/bin/zsh',
stdin_data: nil,
stdin_timing: nil,
stdout_data: stdout_data_file,
stdout_timing: stdout_timing_file,
terminal_columns: 96,
terminal_lines: 26,
terminal_type: 'screen-256color',
title: 'bashing :)',
user: user,
user_agent: 'asciinema/0.9.7',
} }
let(:token) { 'f33e6188-f53c-11e2-abf4-84a6c827e88b' }
before do
allow(DateTime).to receive(:now) { now }
allow(User).to receive(:for_api_token).
with('f33e6188-f53c-11e2-abf4-84a6c827e88b', 'kill') { user }
end
context "when uname given" do
let(:meta_file) {
fixture_file_upload(
'spec/fixtures/meta-with-uname.json', 'application/json'
)
}
let(:expected_attrs) {
required_attrs.merge(
api_token: token,
uname: 'Linux 3.9.9-302.fc19.x86_64 #1 SMP Sat Jul 6 13:41:07' +
' UTC 2013 x86_64'
)
}
it { should eq(expected_attrs) }
context "when uname given" do
before do
meta[:uname] = 'Linux 3.9.9-302.fc19.x86_64'
expected_attrs[:uname] = 'Linux 3.9.9-302.fc19.x86_64'
expected_attrs.delete(:user_agent)
end
it { should eq(expected_attrs) }
end
context "when no api_token given" do
let(:meta_file) { fixture_file_upload('spec/fixtures/meta-no-token.json',
'application/json') }
let(:expected_attrs) { required_attrs }
it { should eq(expected_attrs) }
end
context "when api_token given" do
let(:meta_file) { fixture_file_upload('spec/fixtures/meta.json',
'application/json') }
context "and user with this token exists" do
let(:user) { create(:user) }
let!(:api_token) { create(:api_token, token: token, user: user) }
let(:expected_attrs) { required_attrs.merge(user_id: user.id) }
it { should eq(expected_attrs) }
end
context "and user with this token doesn't exist" do
let(:expected_attrs) { required_attrs.merge(api_token: token) }
it { should eq(expected_attrs) }
end
end
end
end

@ -2,6 +2,10 @@ require 'spec_helper'
describe User do
it "is not dummy by default" do
expect(described_class.new).to_not be_dummy
end
it 'gets an auth_token upon creation' do
attrs = attributes_for(:user)
attrs.delete(:auth_token)
@ -11,12 +15,58 @@ describe User do
end
describe "#valid?" do
before do
create(:user)
let!(:existing_user) { create(:user) }
let(:user) { described_class.new }
it { should validate_presence_of(:nickname) }
context "when user is dummy" do
before do
user.dummy = true
end
it "doesn't check for nickname uniqueness" do
user.nickname = existing_user.nickname
user.valid?
expect(user.errors[:nickname]).to be_empty
end
it "doesn't check for email presence" do
user.email = nil
user.valid?
expect(user.errors[:email]).to be_empty
end
it "doesn't check for email uniqueness" do
user.email = existing_user.email
user.valid?
expect(user.errors[:email]).to be_empty
end
end
it { should validate_uniqueness_of(:nickname) }
it { should validate_uniqueness_of(:email) }
context "when user is real" do
before do
user.dummy = false
end
it "checks for nickname uniqueness" do
user.nickname = existing_user.nickname
user.valid?
expect(user.errors[:nickname]).to_not be_empty
end
it "checks for email presence" do
user.email = nil
user.valid?
expect(user.errors[:email]).to_not be_empty
end
it "checks for email uniqueness" do
user.email = existing_user.email
user.valid?
expect(user.errors[:email]).to_not be_empty
end
end
end
describe '.generate_auth_token' do
@ -70,9 +120,74 @@ describe User do
end
end
describe '.for_api_token' do
subject { described_class.for_api_token(token, username) }
let(:token) { 'f33e6188-f53c-11e2-abf4-84a6c827e88b' }
let(:username) { 'somerandomguy' }
context "when token doesn't exist" do
it "returns a persisted user record" do
expect(subject.id).not_to be(nil)
end
it "assigns given username to the user" do
expect(subject.nickname).to eq(username)
end
it "assigns given api token to the user" do
expect(subject.api_tokens.first.token).to eq(token)
end
context "and username is nil" do
let(:username) { nil }
it "returns a persisted user record" do
expect(subject.id).not_to be(nil)
end
it "assigns 'anonymous' as username to the user" do
expect(subject.nickname).to eq('anonymous')
end
end
context "and username is an empty string" do
let(:username) { nil }
it "returns a persisted user record" do
expect(subject.id).not_to be(nil)
end
it "assigns 'anonymous' as username to the user" do
expect(subject.nickname).to eq('anonymous')
end
end
end
context "when token already exists" do
let!(:existing_token) { create(:api_token, token: token) }
it "returns a persisted user record" do
expect(subject).to eq(existing_token.user)
end
end
context "when token is nil" do
let(:token) { nil }
it { should be(nil) }
end
context "when token is an empty string" do
let(:token) { '' }
it { should be(nil) }
end
end
describe '#nickname=' do
it 'strips the whitespace' do
user = User.new(nickname: ' sickill ')
user = described_class.new(nickname: ' sickill ')
expect(user.nickname).to eq('sickill')
end
@ -80,7 +195,7 @@ describe User do
describe '#email=' do
it 'strips the whitespace' do
user = User.new(email: ' foo@bar.com ')
user = described_class.new(email: ' foo@bar.com ')
expect(user.email).to eq('foo@bar.com')
end

@ -1,13 +1,36 @@
require 'spec_helper'
describe "Asciicast upload" do
it 'returns the URL to the uploaded asciicast' do
post '/api/asciicasts', :asciicast => {
:meta => fixture_file('meta.json', 'application/json'),
:stdout => fixture_file('stdout', 'application/octet-stream'),
:stdout_timing => fixture_file('stdout.time', 'application/octet-stream')
subject { response.body }
before do
post '/api/asciicasts', asciicast: {
meta: fixture_file(meta_filename, 'application/json'),
stdout: fixture_file('stdout', 'application/octet-stream'),
stdout_timing: fixture_file('stdout.time', 'application/octet-stream')
}
end
let(:meta_filename) { 'meta.json' }
it 'returns the URL to the uploaded asciicast' do
expect(response.body).to eq(asciicast_url(Asciicast.last))
end
context "when json includes uname (legacy)" do
let(:meta_filename) { 'meta-with-uname.json' }
it 'returns the URL to the uploaded asciicast' do
expect(response.body).to eq(asciicast_url(Asciicast.last))
end
end
context "when json doesn't include user_token (anonymous?)" do
let(:meta_filename) { 'meta-no-token.json' }
it 'returns the URL to the uploaded asciicast' do
expect(response.body).to eq(asciicast_url(Asciicast.last))
end
end
end

Loading…
Cancel
Save