require_relative '../spec_helper' require_relative '../factories/organizations_contexts' describe Carto::Api::UserPresenter do before(:each) do CartoDB::UserModule::DBService.any_instance.stubs(:enable_remote_db_user).returns(true) end describe '#current_viewer' do include_context 'organization with users helper' it 'displays full data for user administrator' do presentation = Carto::Api::UserPresenter.new(@carto_org_user_1, current_viewer: @carto_org_user_owner).to_poro expect(presentation.keys).to include :email end it 'displays full data for own user' do presentation = Carto::Api::UserPresenter.new(@carto_org_user_1, current_viewer: @carto_org_user_1).to_poro expect(presentation.keys).to include :email end it 'displays filtered data for other users' do presentation = Carto::Api::UserPresenter.new(@carto_org_user_1, current_viewer: @carto_org_user_2).to_poro expect(presentation.keys).to_not include :email end it 'displays filtered data for public' do presentation = Carto::Api::UserPresenter.new(@carto_org_user_1).to_poro expect(presentation.keys).to_not include :email end end it "Compares old and new ways of 'presenting' user data" do Delorean.time_travel_to('2018-01-15') bypass_named_maps # Non-org user user = create_user({ email: 'example@carto.com', username: 'example', password: 'example123', name: "my example name", sync_tables_enabled: true, private_tables_enabled: true, twitter_datasource_enabled: true, twitter_datasource_block_size: 1000, twitter_datasource_block_price: 10, twitter_datasource_quota: 70000, soft_twitter_datasource_limit: true, public_visualization_count: 1, all_visualization_count: 2, job_role: "Developer", company: "test", phone: "123", industry: "Academic and Education", period_end_date: Time.parse('2018-01-01'), account_type: 'ENTERPRISE LUMP-SUM' }) # Some sample data data_import_id = '11111111-1111-1111-1111-111111111111' SequelRails.connection.run(%Q{ INSERT INTO data_imports("data_source","data_type","table_name","state","success","logger","updated_at", "created_at","tables_created_count", "table_names","append","id","table_id","user_id", "service_name","service_item_id","stats","type_guessing","quoted_fields_guessing","content_guessing","server","host", "resque_ppid","upload_host","create_visualization","user_defined_limits") VALUES('test','url','test','complete','t','11111111-1111-1111-1111-111111111112', '2015-03-17 00:00:00.94006+00','2015-03-17 00:00:00.810581+00','1', 'test','f','#{data_import_id}','11111111-1111-1111-1111-111111111113', '#{user.id}','public_url', 'test', '[{"type":".csv","size":5015}]','t','f','t','test','0.0.0.0','13204','test','f','{"twitter_credits_limit":0}'); }) SequelRails.connection.run(%Q{ INSERT INTO geocodings("table_name","processed_rows","created_at","updated_at","formatter","state", "id","user_id", "cache_hits","kind","geometry_type","processable_rows","real_rows","used_credits", "data_import_id" ) VALUES('importer_123456','197','2015-03-17 00:00:00.279934+00','2015-03-17 00:00:00.536383+00','field_1','finished', '11111111-1111-1111-1111-111111111114','#{user.id}','0','admin0','polygon','195','0','0', '#{data_import_id}'); }) create_table( { user_id: user.id, name: 'table1' } ) create_table( { user_id: user.id, name: 'table2', privacy: Carto::UserTable::PRIVACY_PUBLIC } ) feature_flag1 = FactoryGirl.create(:feature_flag, id: 1, name: 'ff1') feature_flag2 = FactoryGirl.create(:feature_flag, id: 2, name: 'ff2') user.update_feature_flags([ feature_flag1.id.to_s, feature_flag2.id.to_s ]) user.save.reload compare_data(user.data, Carto::Api::UserPresenter.new(Carto::User.find(user.id)).data, false, false) # Now org user, organization and another member owner = create_user({ email: 'owner@carto.com', username: 'owner', password: 'owner123', name: "owner name", sync_tables_enabled: true, private_tables_enabled: true, twitter_datasource_enabled: true, twitter_datasource_block_size: 1000, twitter_datasource_block_price: 10, twitter_datasource_quota: 70000, soft_twitter_datasource_limit: true, public_visualization_count: 1, all_visualization_count: 2, job_role: "Developer", company: "test", phone: "123", industry: "Academic and Education", period_end_date: Time.parse('2018-01-01'), account_type: 'ENTERPRISE LUMP-SUM' }) organization = ::Organization.new(quota_in_bytes: 200.megabytes, name: 'testorg', seats: 5).save user_org = CartoDB::UserOrganization.new(organization.id, owner.id) user_org.promote_user_to_admin organization.reload owner.reload user2 = create_user({ email: 'example2@carto.com', username: 'example2', password: 'example123', account_type: 'ORGANIZATION USER' }) user2.organization = organization user2.save user2.reload organization.reload compare_data(owner.data, Carto::Api::UserPresenter.new(Carto::User.find(owner.id)).data, true) SequelRails.connection.run( %Q{ DELETE FROM geocodings } ) SequelRails.connection.run( %Q{ DELETE FROM data_imports } ) user.destroy organization.destroy Delorean.back_to_the_present end protected def compare_data(original_old_data, new_data, org_user = false, mobile_sdk_enabled = false) old_data = add_new_keys(original_old_data) # INFO: new organization presenter now doesn't contain users old_data[:organization].delete(:users) if old_data[:organization] # TODO: This fails at CI server, until there's time to research... #new_data.should eq old_data # To detect deltas not migrated to new presenter new_data.keys.sort.should == old_data.keys.sort new_data[:id].should == old_data[:id] new_data[:email].should == old_data[:email] new_data[:name].should == old_data[:name] new_data[:username].should == old_data[:username] new_data[:account_type].should == old_data[:account_type] new_data[:table_quota].should == old_data[:table_quota] new_data[:public_map_quota].should == old_data[:public_map_quota] new_data[:public_dataset_quota].should == old_data[:public_dataset_quota] new_data[:private_map_quota].should == old_data[:private_map_quota] new_data[:regular_api_key_quota].should == old_data[:regular_api_key_quota] new_data[:table_count].should == old_data[:table_count] new_data[:public_visualization_count].should == old_data[:public_visualization_count] new_data[:public_privacy_visualization_count].should == old_data[:public_privacy_visualization_count] new_data[:link_privacy_visualization_count].should == old_data[:link_privacy_visualization_count] new_data[:password_privacy_visualization_count].should == old_data[:password_privacy_visualization_count] new_data[:private_privacy_visualization_count].should == old_data[:private_privacy_visualization_count] new_data[:all_visualization_count].should == old_data[:all_visualization_count] new_data[:visualization_count].should == old_data[:visualization_count] new_data[:failed_import_count].should == old_data[:failed_import_count] new_data[:success_import_count].should == old_data[:success_import_count] new_data[:import_count].should == old_data[:import_count] new_viz_date = new_data[:last_visualization_created_at].to_s old_viz_date = old_data[:last_visualization_created_at].to_s Time.parse(new_viz_date).should eq Time.parse(old_viz_date) unless old_viz_date.blank? && new_viz_date.blank? new_data[:quota_in_bytes].should == old_data[:quota_in_bytes] new_data[:db_size_in_bytes].should == old_data[:db_size_in_bytes] new_data[:db_size_in_megabytes].should == old_data[:db_size_in_megabytes] new_data[:remaining_table_quota].should == old_data[:remaining_table_quota] new_data[:remaining_byte_quota].should == old_data[:remaining_byte_quota] new_data[:api_calls].should == old_data[:api_calls] new_data[:api_calls_quota].should == old_data[:api_calls_quota] new_data[:api_calls_block_price].should == old_data[:api_calls_block_price] new_data[:geocoding].should == old_data[:geocoding] new_data[:here_isolines].should == old_data[:here_isolines] new_data[:obs_snapshot].should == old_data[:obs_snapshot] new_data[:obs_general].should == old_data[:obs_general] new_data[:twitter].should == old_data[:twitter] new_data[:billing_period].should == old_data[:billing_period] new_data[:next_billing_period].should == old_data[:next_billing_period] new_data[:max_layers].should == old_data[:max_layers] new_data[:api_key].should == old_data[:api_key] new_data[:layers].should == old_data[:layers] new_data[:trial_ends_at].should == old_data[:trial_ends_at] new_data[:upgraded_at].should == old_data[:upgraded_at] new_data[:show_trial_reminder].should == old_data[:show_trial_reminder] new_data[:show_upgraded_message].should == old_data[:show_upgraded_message] new_data[:actions].should == old_data[:actions] new_data[:notification].should == old_data[:notification] new_data[:avatar_url].should == old_data[:avatar_url] new_data[:new_dashboard_enabled].should == old_data[:new_dashboard_enabled] new_data[:feature_flags].should == old_data[:feature_flags] new_data[:base_url].should == old_data[:base_url] new_data[:geocoder_provider].should == old_data[:geocoder_provider] new_data[:isolines_provider].should == old_data[:isolines_provider] new_data[:routing_provider].should == old_data[:routing_provider] new_data[:mfa_configured].should == old_data[:mfa_configured] new_data[:is_enterprise].should == old_data[:is_enterprise] new_data[:unverified].should == old_data[:unverified] if org_user new_data[:organization].keys.sort.should == old_data[:organization].keys.sort # This is an implicit test of OrganizationPresenter... # INFO: we have a weird error sometimes running builds that fails comparing dates despite having equal value... # > Diff:2015-06-23 17:27:02 +0200.==(2015-06-23 17:27:02 +0200) returned false even though the diff between # 2015-06-23 17:27:02 +0200 and 2015-06-23 17:27:02 +0200 is empty. Check the implementation of # 2015-06-23 17:27:02 +0200.==. new_data[:organization][:created_at].should == old_data[:organization][:created_at] new_data[:organization][:description].should == old_data[:organization][:description] new_data[:organization][:discus_shortname].should == old_data[:organization][:discus_shortname] new_data[:organization][:display_name].should == old_data[:organization][:display_name] new_data[:organization][:id].should == old_data[:organization][:id] new_data[:organization][:name].should == old_data[:organization][:name] new_data[:organization][:owner][:id].should == old_data[:organization][:owner][:id] new_data[:organization][:owner][:username].should == old_data[:organization][:owner][:username] new_data[:organization][:owner][:avatar_url].should == old_data[:organization][:owner][:avatar_url] new_data[:organization][:owner][:email].should == old_data[:organization][:owner][:email] new_data[:organization][:quota_in_bytes].should == old_data[:organization][:quota_in_bytes] new_data[:organization][:geocoding_quota].should == old_data[:organization][:geocoding_quota] new_data[:organization][:here_isolines_quota].should == old_data[:organization][:here_isolines_quota] new_data[:organization][:obs_snapshot_quota].should == old_data[:organization][:obs_snapshot_quota] new_data[:organization][:obs_general_quota].should == old_data[:organization][:obs_general_quota] new_data[:organization][:mapzen_routing_quota].should == old_data[:organization][:mapzen_routing_quota] new_data[:organization][:map_view_quota].should == old_data[:organization][:map_view_quota] new_data[:organization][:twitter_datasource_quota].should == old_data[:organization][:twitter_datasource_quota] new_data[:organization][:map_view_block_price].should == old_data[:organization][:map_view_block_price] new_data[:organization][:geocoding_block_price].should == old_data[:organization][:geocoding_block_price] new_data[:organization][:here_isolines_block_price].should == old_data[:organization][:here_isolines_block_price] new_data[:organization][:obs_snapshot_block_price].should == old_data[:organization][:obs_snapshot_block_price] new_data[:organization][:obs_general_block_price].should == old_data[:organization][:obs_general_block_price] new_data[:organization][:mapzen_routing_block_price].should == old_data[:organization][:mapzen_routing_block_price] new_data[:organization][:seats].should == old_data[:organization][:seats] new_data[:organization][:twitter_username].should == old_data[:organization][:twitter_username] new_data[:organization][:location].should == old_data[:organization][:location] # Same as [:organization][:created_at] issue above # TODO Skipped organization.created_at due to Rails 4 TZ issues # new_data[:organization][:updated_at].to_s.should == old_data[:organization][:updated_at].to_s #owner is excluded from the users list new_data[:organization][:website].should == old_data[:organization][:website] new_data[:organization][:avatar_url].should == old_data[:organization][:avatar_url] new_data[:geocoder_provider].should == old_data[:geocoder_provider] new_data[:isolines_provider].should == old_data[:isolines_provider] new_data[:routing_provider].should == old_data[:routing_provider] end if mobile_sdk_enabled new_data[:mobile_apps].keys.sort.should == old_data[:mobile_apps].keys.sort new_data[:mobile_apps][:mobile_xamarin].should = new_data[:mobile_apps].mobile_xamarin new_data[:mobile_apps][:mobile_custom_watermark].should = new_data[:mobile_apps].mobile_custom_watermark new_data[:mobile_apps][:mobile_offline_maps].should = new_data[:mobile_apps].mobile_offline_maps new_data[:mobile_apps][:mobile_gis_extension].should = new_data[:mobile_apps].mobile_gis_extension new_data[:mobile_apps][:mobile_max_open_users].should = new_data[:mobile_apps].mobile_max_open_users new_data[:mobile_apps][:mobile_max_private_users].should = new_data[:mobile_apps].mobile_max_private_users end # TODO: Pending migration and testing of :real_table_count & :last_active_time end def add_new_keys(user_poro) new_poro = user_poro.dup.deep_merge(viewer: false) new_poro[:organization] = user_poro[:organization].deep_merge(viewer_seats: 0) if user_poro[:organization].present? new_poro[:mfa_configured] = false new_poro[:next_billing_period] = Time.parse('2018-02-01') new_poro[:is_enterprise] = true new_poro[:do_enabled] = false new_poro end def create_org(org_name, org_quota, org_seats) organization = Organization.new organization.name = org_name organization.quota_in_bytes = org_quota organization.seats = org_seats organization.save! organization end end