require_relative '../spec_helper' require_relative 'user_shared_examples' require 'helpers/user_part_helper' describe User do include UserPartHelper include_context 'user spec configuration' it "should only allow legal usernames" do illegal_usernames = %w(si$mon 'sergio estella' j@vi sergio£££ simon_tokumine SIMON Simon jose.rilla -rilla rilla-) legal_usernames = %w(simon javier-de-la-torre sergio-leiva sergio99) illegal_usernames.each do |name| @user.username = name @user.valid?.should be_false @user.errors[:username].should be_present end legal_usernames.each do |name| @user.username = name @user.valid?.should be_true @user.errors[:username].should be_blank end end it "should not allow a username in use by an organization" do org = create_org('testusername', 10.megabytes, 1) @user.username = org.name @user.valid?.should be_false @user.username = 'wadus' @user.valid?.should be_true end it "should have a default dashboard_viewed? false" do user = ::User.new user.dashboard_viewed?.should be_false end it "should reset dashboard_viewed when dashboard gets viewed" do user = ::User.new user.view_dashboard user.dashboard_viewed?.should be_true end describe "avatar checks" do let(:user1) do User.where(username: 'u1').first&.destroy create_user(email: 'ewdewfref34r43r43d32f45g5@example.com', username: 'u1', password: 'foobar') end after(:each) do user1.destroy end it "should load a cartodb avatar url if no gravatar associated" do gravatar_url = %r{gravatar.com} Typhoeus.stub(gravatar_url, { method: :get }).and_return(Typhoeus::Response.new(code: 404)) user1.stubs(:gravatar_enabled?).returns(true) user1.avatar_url = nil user1.save user1.reload_avatar kind_regex = "(#{Cartodb.config[:avatars]['kinds'].join('|')})" color_regex = "(#{Cartodb.config[:avatars]['colors'].join('|')})" expected_url = /#{Cartodb.config[:avatars]['base_url']}\/avatar_#{kind_regex}_#{color_regex}\.png/ expect(user1.avatar_url).to match(expected_url) end it "should load a cartodb avatar url if gravatar disabled" do gravatar_url = %r{gravatar.com} Typhoeus.stub(gravatar_url, { method: :get }).and_return(Typhoeus::Response.new(code: 200)) user1.stubs(:gravatar_enabled?).returns(false) user1.avatar_url = nil user1.save user1.reload_avatar kind_regex = "(#{Cartodb.config[:avatars]['kinds'].join('|')})" color_regex = "(#{Cartodb.config[:avatars]['colors'].join('|')})" expected_url = /#{Cartodb.config[:avatars]['base_url']}\/avatar_#{kind_regex}_#{color_regex}\.png/ expect(user1.avatar_url).to match(expected_url) end it "should load a the user gravatar url" do gravatar_url = %r{gravatar.com} Typhoeus.stub(gravatar_url, { method: :get }).and_return(Typhoeus::Response.new(code: 200)) user1.stubs(:gravatar_enabled?).returns(true) user1.reload_avatar user1.avatar_url.should == "//#{user1.gravatar_user_url}" end describe '#gravatar_enabled?' do it 'should be enabled by default (every setting but false will enable it)' do user = ::User.new Cartodb.with_config(avatars: {}) { user.gravatar_enabled?.should be_true } Cartodb.with_config(avatars: { 'gravatar_enabled' => true }) { user.gravatar_enabled?.should be_true } Cartodb.with_config(avatars: { 'gravatar_enabled' => 'true' }) { user.gravatar_enabled?.should be_true } Cartodb.with_config(avatars: { 'gravatar_enabled' => 'wadus' }) { user.gravatar_enabled?.should be_true } end it 'can be disabled' do user = ::User.new Cartodb.with_config(avatars: { 'gravatar_enabled' => false }) { user.gravatar_enabled?.should be_false } Cartodb.with_config(avatars: { 'gravatar_enabled' => 'false' }) { user.gravatar_enabled?.should be_false } end end end describe '#private_maps_enabled?' do it 'should not have private maps enabled by default' do user_missing_private_maps = create_user email: 'user_mpm@example.com', username: 'usermpm', password: '000usermpm' user_missing_private_maps.private_maps_enabled?.should eq false user_missing_private_maps.destroy end it 'should have private maps if enabled' do user_with_private_maps = create_user email: 'user_wpm@example.com', username: 'userwpm', password: '000userwpm', private_maps_enabled: true user_with_private_maps.private_maps_enabled?.should eq true user_with_private_maps.destroy end it 'should not have private maps if disabled' do user_without_private_maps = create_user email: 'user_opm@example.com', username: 'useropm', password: '000useropm', private_maps_enabled: false user_without_private_maps.private_maps_enabled?.should eq false user_without_private_maps.destroy end end describe "#purge_redis_vizjson_cache" do it "shall iterate on the user's visualizations and purge their redis cache" do # Create a few tables with their default vizs (1..3).each do |i| t = Table.new t.user_id = @user.id t.save end collection = CartoDB::Visualization::Collection.new.fetch({user_id: @user.id}) redis_spy = RedisDoubles::RedisSpy.new redis_vizjson_cache = CartoDB::Visualization::RedisVizjsonCache.new() redis_embed_cache = EmbedRedisCache.new() CartoDB::Visualization::RedisVizjsonCache.any_instance.stubs(:redis).returns(redis_spy) EmbedRedisCache.any_instance.stubs(:redis).returns(redis_spy) redis_vizjson_keys = collection.map { |v| [ redis_vizjson_cache.key(v.id, false), redis_vizjson_cache.key(v.id, true), redis_vizjson_cache.key(v.id, false, 3), redis_vizjson_cache.key(v.id, true, 3), redis_vizjson_cache.key(v.id, false, '3n'), redis_vizjson_cache.key(v.id, true, '3n'), redis_vizjson_cache.key(v.id, false, '3a'), redis_vizjson_cache.key(v.id, true, '3a'), ] }.flatten redis_vizjson_keys.should_not be_empty redis_embed_keys = collection.map { |v| [redis_embed_cache.key(v.id, false), redis_embed_cache.key(v.id, true)] }.flatten redis_embed_keys.should_not be_empty @user.purge_redis_vizjson_cache redis_spy.deleted.should include(*redis_vizjson_keys) redis_spy.deleted.should include(*redis_embed_keys) redis_spy.deleted.count.should eq redis_vizjson_keys.count + redis_embed_keys.count redis_spy.invokes(:del).count.should eq 2 redis_spy.invokes(:del).map(&:sort).should include(redis_vizjson_keys.sort) redis_spy.invokes(:del).map(&:sort).should include(redis_embed_keys.sort) end it "shall not fail if the user does not have visualizations" do user = create_user collection = CartoDB::Visualization::Collection.new.fetch({user_id: user.id}) # 'http' keys redis_keys = collection.map(&:redis_vizjson_key) redis_keys.should be_empty # 'https' keys redis_keys = collection.map { |item| item.redis_vizjson_key(true) } redis_keys.should be_empty CartoDB::Visualization::Member.expects(:redis_cache).never user.purge_redis_vizjson_cache user.destroy end end describe '#visualization_count' do include_context 'organization with users helper' include TableSharing it 'filters by type if asked' do vis = FactoryGirl.create(:carto_visualization, user_id: @org_user_1.id, type: Carto::Visualization::TYPE_DERIVED) @org_user_1.visualization_count.should eq 1 @org_user_1.visualization_count(type: Carto::Visualization::TYPE_DERIVED).should eq 1 [Carto::Visualization::TYPE_CANONICAL, Carto::Visualization::TYPE_REMOTE].each do |type| @org_user_1.visualization_count(type: type).should eq 0 end vis.destroy end it 'filters by privacy if asked' do vis = FactoryGirl.create(:carto_visualization, user_id: @org_user_1.id, privacy: Carto::Visualization::PRIVACY_PUBLIC) @org_user_1.visualization_count.should eq 1 @org_user_1.visualization_count(privacy: Carto::Visualization::PRIVACY_PUBLIC).should eq 1 [ Carto::Visualization::PRIVACY_PRIVATE, Carto::Visualization::PRIVACY_LINK, Carto::Visualization::PRIVACY_PROTECTED ].each do |privacy| @org_user_1.visualization_count(privacy: privacy).should eq 0 end vis.destroy end it 'filters by shared exclusion if asked' do vis = FactoryGirl.create(:carto_visualization, user_id: @org_user_1.id, type: Carto::Visualization::TYPE_DERIVED) share_visualization_with_user(vis, @org_user_2) @org_user_2.visualization_count.should eq 1 @org_user_2.visualization_count(exclude_shared: true).should eq 0 vis.destroy end it 'filters by raster exclusion if asked' do vis = FactoryGirl.create(:carto_visualization, user_id: @org_user_1.id, kind: Carto::Visualization::KIND_RASTER) @org_user_1.visualization_count.should eq 1 @org_user_1.visualization_count(exclude_raster: true).should eq 0 vis.destroy end end describe 'viewer user' do def verify_viewer_quota(user) user.quota_in_bytes.should eq 0 user.geocoding_quota.should eq 0 user.soft_geocoding_limit.should eq false user.twitter_datasource_quota.should eq 0 user.soft_twitter_datasource_limit.should eq false user.here_isolines_quota.should eq 0 user.soft_here_isolines_limit.should eq false user.obs_snapshot_quota.should eq 0 user.soft_obs_snapshot_limit.should eq false user.obs_general_quota.should eq 0 user.soft_obs_general_limit.should eq false end describe 'creation' do it 'assigns 0 as quota and no soft limit no matter what is requested' do @user = create_user email: 'u_v@whatever.com', username: 'viewer', password: 'user11', viewer: true, geocoding_quota: 10, soft_geocoding_limit: true, twitter_datasource_quota: 100, soft_twitter_datasource_limit: 10, here_isolines_quota: 10, soft_here_isolines_limit: true, obs_snapshot_quota: 100, soft_obs_snapshot_limit: true, obs_general_quota: 100, soft_obs_general_limit: true verify_viewer_quota(@user) @user.destroy end end describe 'builder -> viewer' do it 'assigns 0 as quota and no soft limit no matter what is requested' do @user = create_user email: 'u_v@whatever.com', username: 'builder-to-viewer', password: 'user11', viewer: false, geocoding_quota: 10, soft_geocoding_limit: true, twitter_datasource_quota: 100, soft_twitter_datasource_limit: 10, here_isolines_quota: 10, soft_here_isolines_limit: true, obs_snapshot_quota: 100, soft_obs_snapshot_limit: true, obs_general_quota: 100, soft_obs_general_limit: true # Random check, but we can trust create_user @user.quota_in_bytes.should_not eq 0 @user.viewer = true @user.save @user.reload verify_viewer_quota(@user) @user.destroy end end describe 'quotas' do it "can't change for viewer users" do @user = create_user(viewer: true) verify_viewer_quota(@user) @user.quota_in_bytes = 666 @user.save @user.reload verify_viewer_quota(@user) @user.destroy end end end describe 'session' do before(:all) do Cartodb::Central.stubs(:sync_data_with_cartodb_central?).returns(true) @user = FactoryGirl.create(:valid_user) end after(:all) do Cartodb::Central.unstub(:sync_data_with_cartodb_central?) @user.destroy end it 'salt should be generated at creation' do @user.session_salt.should_not be_nil end it 'security token should include salt' do sec_token = Carto::Common::EncryptionService.encrypt(sha_class: Digest::SHA256, password: @user.crypted_password, salt: @user.session_salt) @user.security_token.should == sec_token end describe '#invalidate_all_sessions!' do before(:each) do Cartodb::Central.any_instance.stubs(:send_request) end after(:each) do Cartodb::Central.any_instance.unstub(:send_request) end context 'when everything succeeds' do it 'updates the session_salt' do initial_session_salt = @user.session_salt @user.invalidate_all_sessions! initial_session_salt.should_not == @user.reload.session_salt end it 'updates the user in Central' do Cartodb::Central.any_instance.expects(:send_request).once @user.invalidate_all_sessions! end end context 'when syncing to Central fails' do context 'due to a newtork error' do before do User.any_instance.stubs(:update_in_central).raises(CartoDB::CentralCommunicationFailure, 'Error') end it 'logs an error' do Rails.logger.expects(:error).once @user.invalidate_all_sessions! end end context 'due to anything else' do before do User.any_instance.stubs(:update_in_central).returns(false) end it 'logs an error' do Rails.logger.expects(:error).once @user.invalidate_all_sessions! end end end context 'when saving in local fails' do it 'logs an error' do @user.email = nil Rails.logger.expects(:error).once @user.invalidate_all_sessions! end end end end end