From 45bd31fad0cbc03a7ee293aaf022c95bbf26c7f5 Mon Sep 17 00:00:00 2001 From: Henne Vogelsang Date: Mon, 2 May 2016 17:39:06 +0200 Subject: [PATCH 1/5] Escape HTML some factory strings --- spec/factories/conferences.rb | 2 +- spec/factories/events.rb | 1 - spec/factories/lodgings.rb | 2 +- spec/factories/sponsors.rb | 2 +- spec/factories/sponsorship_levels.rb | 2 +- spec/features/lodgings_spec.rb | 8 ++++---- spec/views/admin/conference/index.html.haml_spec.rb | 2 +- spec/views/admin/conference/new.html.haml_spec.rb | 2 +- spec/views/admin/lodgings/index.html.haml_spec.rb | 2 +- spec/views/admin/sponsors/index.html.haml_spec.rb | 6 +++--- .../admin/sponsorship_levels/index.html.haml_spec.rb | 2 +- spec/views/conference/show.html.haml_spec.rb | 12 ++++++------ 12 files changed, 21 insertions(+), 22 deletions(-) diff --git a/spec/factories/conferences.rb b/spec/factories/conferences.rb index 3bd59f64..c7c07bb8 100644 --- a/spec/factories/conferences.rb +++ b/spec/factories/conferences.rb @@ -8,7 +8,7 @@ FactoryGirl.define do start_date { Date.today } end_date { 6.days.from_now } registration_limit 0 - description { CGI.escapeHTML(Faker::Hipster.paragraph) } + description { Faker::Hipster.paragraph } after(:create) do |conference| Role.where(name: 'organizer', resource: conference).first_or_create(description: 'For the organizers of the conference (who shall have full access)') diff --git a/spec/factories/events.rb b/spec/factories/events.rb index e4cf19df..8cbf2293 100644 --- a/spec/factories/events.rb +++ b/spec/factories/events.rb @@ -30,6 +30,5 @@ FactoryGirl.define do event.comment_threads << build(:comment, commentable: event) end end - end end diff --git a/spec/factories/lodgings.rb b/spec/factories/lodgings.rb index 73ceeefa..636d9060 100644 --- a/spec/factories/lodgings.rb +++ b/spec/factories/lodgings.rb @@ -3,7 +3,7 @@ FactoryGirl.define do factory :lodging do name { "#{Faker::App.name} Hotel" } - description { CGI.escapeHTML(Faker::Lorem.paragraph) } + description { Faker::Lorem.paragraph } website_link { Faker::Internet.url } end end diff --git a/spec/factories/sponsors.rb b/spec/factories/sponsors.rb index edf1bf16..dd074ab3 100644 --- a/spec/factories/sponsors.rb +++ b/spec/factories/sponsors.rb @@ -4,7 +4,7 @@ FactoryGirl.define do factory :sponsor do name { Faker::Company.name } website_url { Faker::Internet.url } - description { CGI.escapeHTML(Faker::Lorem.paragraph) } + description { Faker::Lorem.paragraph } sponsorship_level diff --git a/spec/factories/sponsorship_levels.rb b/spec/factories/sponsorship_levels.rb index df2e3b6d..72db7493 100644 --- a/spec/factories/sponsorship_levels.rb +++ b/spec/factories/sponsorship_levels.rb @@ -2,7 +2,7 @@ FactoryGirl.define do factory :sponsorship_level do - title { Faker::Hipster.word } + title { Faker::Lorem.word } conference end diff --git a/spec/features/lodgings_spec.rb b/spec/features/lodgings_spec.rb index 6d1d72ff..1e6b491d 100644 --- a/spec/features/lodgings_spec.rb +++ b/spec/features/lodgings_spec.rb @@ -15,7 +15,7 @@ feature Lodging do click_link 'Add Lodging' fill_in 'lodging_name', with: 'New lodging' - fill_in 'lodging_website_link', with: 'http:\\www.google.com' + fill_in 'lodging_website_link', with: 'http://www.google.com' attach_file 'Picture', path click_button 'Create Lodging' @@ -35,7 +35,7 @@ feature Lodging do visit admin_conference_lodgings_path( conference_id: conference.short_title) - expect(page.has_content?(lodging.name)).to be true + expect(page.has_content?(CGI.escapeHTML(lodging.name))).to be true # Add lodging click_link 'Edit' @@ -51,7 +51,7 @@ feature Lodging do expect(page.has_content?('New lodging')).to be true lodging.reload expect(lodging.name).to eq('New lodging') - expect(lodging.description).to eq(lodging.description) + expect(lodging.description).to eq(CGI.escapeHTML(lodging.description)) expect(lodging.website_link).to eq('http://www.google.com') expect(Lodging.count).to eq(1) end @@ -70,7 +70,7 @@ feature Lodging do # Validations expect(flash).to eq('Lodging successfully deleted.') - expect(page.has_content?(lodging.name)).to be false + expect(page.has_content?(CGI.escapeHTML(lodging.name))).to be false expect(Lodging.count).to eq(0) end end diff --git a/spec/views/admin/conference/index.html.haml_spec.rb b/spec/views/admin/conference/index.html.haml_spec.rb index b2c285cb..d1f2eef1 100644 --- a/spec/views/admin/conference/index.html.haml_spec.rb +++ b/spec/views/admin/conference/index.html.haml_spec.rb @@ -8,6 +8,6 @@ describe 'admin/conference/index' do assign(:conferences, [conference, second_conference]) render expect(rendered).to include('openSUSE Conference 2016') - expect(rendered).to include(second_conference.title) + expect(rendered).to include(CGI.escapeHTML(second_conference.title)) end end diff --git a/spec/views/admin/conference/new.html.haml_spec.rb b/spec/views/admin/conference/new.html.haml_spec.rb index e19ab1d3..983526f8 100644 --- a/spec/views/admin/conference/new.html.haml_spec.rb +++ b/spec/views/admin/conference/new.html.haml_spec.rb @@ -9,6 +9,6 @@ describe 'admin/conference/new' do expect(rendered).to include('Basic Information') assign(:conference, conference) render - expect(rendered).to include(conference.title) + expect(rendered).to include(CGI.escapeHTML(conference.title)) end end diff --git a/spec/views/admin/lodgings/index.html.haml_spec.rb b/spec/views/admin/lodgings/index.html.haml_spec.rb index 30fdaece..95f16be4 100644 --- a/spec/views/admin/lodgings/index.html.haml_spec.rb +++ b/spec/views/admin/lodgings/index.html.haml_spec.rb @@ -7,6 +7,6 @@ describe 'admin/lodgings/index' do @conference.lodgings << create(:lodging) assign :venue, @conference.venue render - expect(rendered).to include(@conference.lodgings.first.name) + expect(rendered).to include(CGI.escapeHTML(@conference.lodgings.first.name)) end end diff --git a/spec/views/admin/sponsors/index.html.haml_spec.rb b/spec/views/admin/sponsors/index.html.haml_spec.rb index 6311c5d1..3f0988e6 100644 --- a/spec/views/admin/sponsors/index.html.haml_spec.rb +++ b/spec/views/admin/sponsors/index.html.haml_spec.rb @@ -9,9 +9,9 @@ describe 'admin/sponsors/index' do ) assign :conference, @conference render - expect(rendered).to include(@conference.sponsors.first.name) + expect(rendered).to include(CGI.escapeHTML(@conference.sponsors.first.name)) expect(rendered).to include(@conference.sponsors.first.website_url) - expect(rendered).to include(truncate(@conference.sponsors.first.description)) - expect(rendered).to include(@conference.sponsorship_levels.first.title) + expect(rendered).to include(truncate(CGI.escapeHTML(@conference.sponsors.first.description))) + expect(rendered).to include(CGI.escapeHTML(@conference.sponsorship_levels.first.title)) end end diff --git a/spec/views/admin/sponsorship_levels/index.html.haml_spec.rb b/spec/views/admin/sponsorship_levels/index.html.haml_spec.rb index d3abb41e..d599b1a3 100644 --- a/spec/views/admin/sponsorship_levels/index.html.haml_spec.rb +++ b/spec/views/admin/sponsorship_levels/index.html.haml_spec.rb @@ -5,6 +5,6 @@ describe 'admin/sponsorship_levels/index' do @sponsorship_level = create(:sponsorship_level) assign :conference, @sponsorship_level.conference render - expect(rendered).to include(@sponsorship_level.title) + expect(rendered).to include(CGI.escapeHTML(@sponsorship_level.title)) end end diff --git a/spec/views/conference/show.html.haml_spec.rb b/spec/views/conference/show.html.haml_spec.rb index 46205267..80f6c85b 100644 --- a/spec/views/conference/show.html.haml_spec.rb +++ b/spec/views/conference/show.html.haml_spec.rb @@ -9,7 +9,7 @@ describe 'conference/show.html.haml' do end it 'renders banner component' do - expect(rendered).to match(conference.description) + expect(rendered).to match(CGI.escapeHTML(conference.description)) end it 'renders program partial' do @@ -28,7 +28,7 @@ describe 'conference/show.html.haml' do expect(view).to render_template(partial: 'conference/_sponsors') expect(rendered).to match(conference.contact.email) expect(rendered).to match(conference.sponsors.first.website_url) - expect(rendered).to match(conference.sponsors.first.description) + expect(rendered).to match(CGI.escapeHTML(conference.sponsors.first.description)) expect(rendered).to match(conference.sponsors.first.logo_file_name) end @@ -42,16 +42,16 @@ describe 'conference/show.html.haml' do it 'renders venue partial' do expect(view).to render_template(partial: 'conference/_venue') - expect(rendered).to match(conference.venue.name) + expect(rendered).to match(CGI.escapeHTML(conference.venue.name)) expect(rendered).to match(conference.venue.street) expect(rendered).to match(conference.venue.website) - expect(rendered).to match(conference.venue.description) + expect(rendered).to match(CGI.escapeHTML(conference.venue.description)) end it 'renders lodging partial' do expect(view).to render_template(partial: 'conference/_lodging') - expect(rendered).to match(conference.lodgings.first.name) - expect(rendered).to match(conference.lodgings.first.description) + expect(rendered).to match(CGI.escapeHTML(conference.lodgings.first.name)) + expect(rendered).to match(CGI.escapeHTML(conference.lodgings.first.description)) # FIXME: Lodging without image doesn't show link # expect(rendered).to match(conference.lodgings.first.website_link) end From 4c4918a7a7358f58a3e0ccb26a9fc089df77f3d7 Mon Sep 17 00:00:00 2001 From: Henne Vogelsang Date: Mon, 2 May 2016 17:57:35 +0200 Subject: [PATCH 2/5] Somehow the :venues factory creates a dangling Conference disabling for now --- spec/factories/venues.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/spec/factories/venues.rb b/spec/factories/venues.rb index 11f27035..92c149cc 100644 --- a/spec/factories/venues.rb +++ b/spec/factories/venues.rb @@ -8,7 +8,5 @@ FactoryGirl.define do country { Faker::Address.country_code } website { Faker::Internet.url } description { Faker::Lorem.sentence } - - conference end end From c876a2d1cfe9e0c765546f1864d15a07e1919f52 Mon Sep 17 00:00:00 2001 From: Henne Vogelsang Date: Mon, 2 May 2016 18:06:24 +0200 Subject: [PATCH 3/5] Assign a public id based on the picture name --- app/uploaders/picture_uploader.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/uploaders/picture_uploader.rb b/app/uploaders/picture_uploader.rb index 171c2d23..39b81f3f 100644 --- a/app/uploaders/picture_uploader.rb +++ b/app/uploaders/picture_uploader.rb @@ -8,6 +8,10 @@ class PictureUploader < CarrierWave::Uploader::Base # use cloudinary if it's configured if Cloudinary.config.cloud_name include Cloudinary::CarrierWave + + def public_id + return model.try(:photo_file_name) || model.try(:logo_file_name) + end end def paperclip_path From 5b20c992ae55a0fa5f5361c41c14ef4634dbcd15 Mon Sep 17 00:00:00 2001 From: Henne Vogelsang Date: Tue, 3 May 2016 12:13:23 +0200 Subject: [PATCH 4/5] Let activerecord handle the picture upload in factories --- spec/factories/conferences.rb | 8 ++++---- spec/factories/sponsors.rb | 9 ++++----- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/spec/factories/conferences.rb b/spec/factories/conferences.rb index c7c07bb8..93089cce 100644 --- a/spec/factories/conferences.rb +++ b/spec/factories/conferences.rb @@ -46,10 +46,10 @@ FactoryGirl.define do create(:question, conferences: [conference]) # Logo... - uploader = PictureUploader.new(conference, :picture) - File.open('app/assets/images/rails.png') { |f| uploader.store!(f) } - conference.logo_file_name = 'rails.png' - conference.save + File.open("spec/support/logos/#{1 + rand(13)}.png") do |file| + conference.picture = file + end + conference.save! end end end diff --git a/spec/factories/sponsors.rb b/spec/factories/sponsors.rb index dd074ab3..5d531991 100644 --- a/spec/factories/sponsors.rb +++ b/spec/factories/sponsors.rb @@ -9,11 +9,10 @@ FactoryGirl.define do sponsorship_level after(:create) do |sponsor| - logo = "#{1 + rand(13)}.png" - uploader = PictureUploader.new(sponsor, :picture) - File.open("spec/support/logos/#{logo}") { |f| uploader.store!(f) } - sponsor.logo_file_name = logo.to_s - sponsor.save + File.open("spec/support/logos/#{1 + rand(13)}.png") do |file| + sponsor.picture = file + end + sponsor.save! end end end From 084ee7ef43d42440b314f1e12cbda9a1c5e4a3b8 Mon Sep 17 00:00:00 2001 From: Henne Vogelsang Date: Tue, 3 May 2016 14:13:45 +0200 Subject: [PATCH 5/5] Give a bit more demo info in the conference description --- app/uploaders/picture_uploader.rb | 5 ++++- lib/tasks/data_demo.rake | 6 ++++-- spec/factories/conferences.rb | 2 +- spec/support/logos/OSEM.jpg | Bin 0 -> 14699 bytes 4 files changed, 9 insertions(+), 4 deletions(-) create mode 100644 spec/support/logos/OSEM.jpg diff --git a/app/uploaders/picture_uploader.rb b/app/uploaders/picture_uploader.rb index 39b81f3f..af3c2227 100644 --- a/app/uploaders/picture_uploader.rb +++ b/app/uploaders/picture_uploader.rb @@ -7,10 +7,13 @@ class PictureUploader < CarrierWave::Uploader::Base # use cloudinary if it's configured if Cloudinary.config.cloud_name + # use https by default + Cloudinary.config.secure = true + include Cloudinary::CarrierWave def public_id - return model.try(:photo_file_name) || model.try(:logo_file_name) + model.try(:photo_file_name) || model.try(:logo_file_name) end end diff --git a/lib/tasks/data_demo.rake b/lib/tasks/data_demo.rake index dc209c1d..8debfe49 100644 --- a/lib/tasks/data_demo.rake +++ b/lib/tasks/data_demo.rake @@ -2,7 +2,9 @@ namespace :data do desc 'Create demo data using our factories' task demo: :environment do include FactoryGirl::Syntax::Methods - create(:full_conference) - create(:admin, email: 'admin@osem.io', username: 'admin', password: 'password', password_confirmation: 'password') + + conference = create(:full_conference, title: 'Open Source Event Manager Demo', short_title: 'osemdemo' ,description: "This is a [Open Source Event Manager](http://osem.io/) demo instance. You can log in as **admin** with the password **password123** or just you just [sign up](/accounts/sign_up) with your own user. We hope you enjoy checking out all the functionality, if you have questions don't hesitate to [contact us](http://osem.io/#contact)!\r\n\r\n## Data will be destroyed every thirty minutes or whenever someone updates the [OSEM source code on github](https://github.com/openSUSE/osem/commits/master).") + conference.contact.update_attributes(email: 'osemdemo@osem.io', sponsor_email: 'osemdemo@osem.io') + create(:admin, email: 'admin@osem.io', username: 'admin', password: 'password123', password_confirmation: 'password123') end end diff --git a/spec/factories/conferences.rb b/spec/factories/conferences.rb index 93089cce..d92a7e88 100644 --- a/spec/factories/conferences.rb +++ b/spec/factories/conferences.rb @@ -46,7 +46,7 @@ FactoryGirl.define do create(:question, conferences: [conference]) # Logo... - File.open("spec/support/logos/#{1 + rand(13)}.png") do |file| + File.open('spec/support/logos/OSEM.jpg') do |file| conference.picture = file end conference.save! diff --git a/spec/support/logos/OSEM.jpg b/spec/support/logos/OSEM.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9e4dc4a392007a83ce384e2bddb9d8ea585e7604 GIT binary patch literal 14699 zcmd^mbyOTpwCCUff?IG1LkODS1PvBoa2Z^JB^h7_cMZV_?hu&Z?(Xgq+-88_1h?R_ ze0$FB`*zRSeQ*EX+kLvayX01#uDW&a@7{i#fBX#~1btBW06;-O1<*VlfJX#C8i0oS z5B+mRdm?m9^nd6XCME_Z_A?wD>}S~6IL`^5f zC;X=olz(cXp+9@7NQjG#`}Fqzksdn$M9%=*C>&@gF9E1TC}>0|k39fd015!@pA!Y} zKL``+83r0UHVW!fwiY4ai81OE=ck@wU_TW?d3pd~U}6ywGjcy8ku-g&Zcj?VBc=T{ zCSj6{`~{PSlYeF)ZZ+@3i8izfgb z0}~Au1?wr3kLZadDk|nP%>U6T6u=WtA`C`i5^hQLO0t(4ruJVmJ4u=NVkVAxrB-=> zkBflkPlG@uLL&l504i8P+C;V*@wr5-Aa&w@CC05?UW$g;6z|4@vSlHv!c~H+QXe)> z_Xf0hURA8CRDB)`wF`u52Id{&K;C@d!Y?hfDKy31B0#MZA!^q@pdkifn=4dp0#9V# zd-^q{Pk%ZpNN!EN>JxdnHj(^WW0~gTOJ0bAx@M7R+<*hE%6gL6E_d{9EDx!4AK%2B zrLnDQ$i#}FD>XF7%T-eU!!6#8Z9VU5WwKr~t7$z!Bi@KsV-+K3|Dgu?s%kUR1pCf( z#VLo-1$%qsPyso;Ya`kMQMO-deP7tar}CX#RAuvd<1QC8K_>Yyel7NsROn9G&KVA4 zuWdap=U0m4%_P0Wfx%OQ?d;!U3L94mb`lm zV?y2tzCO4LXQ)(K9P)RL;H3mr9hdz_d_xgFk-7^+R{XR1IjDYMqCk|B#7~cmkOy4l z^n8l5y5O*ffH>{SiN3y_TDY?gv%&HKi^9dAMH<(eGLDTS<1!&*NK9u)?F;$D#oxJB zSQE}l?B1#bVk*sgepH0WGP0FfFj{xfx9R#~%y z7aO+DxlH@bSsz4GYpCzC!Uucj7mTW{nkslPBU#kMy0AQF|6B|W808&56&Fs9A)m&| zk-a)-V1;idKmeudWfrxTjnPRA0B!7NSSvY(PA9F z{kh6mH`c)tt)Rnz#aL_1FAotgF|XdzJl+HM4)-=~Y^aHmh0hm8!cNl7D{G0=|=5QSufNx6&pFL9WR&L{uye#gtGFU*ey*Bf=! zD^Q=U{3CmH3A?Chd8ni6^fJZ^xS&(YF8rfq5agTtK)4pLVo;J1*Lw1fp)YL)| z-Y?DwV1we6(pMa-Zkvqo<&TRrxWqtK)=TDs2Dq#wtDMIr{=L*YI_Gngyj0Vix7`qE z-6UZEgH3#n0{~?l{KFn41ze?M$XV%VUt&Pr4ShauuSiNQ+a$EmFg~v+Pv;4AWa-KH z+}D(_yTpa34~;!6uVmg@t=I^xB@1jj?IPCFKzzYaR7ZS__g9$58I9!-e3-fpyx^bG zsusncGSz$?6($vSP`19r$r5CkD-2f>%4zH%CXEk>G&PiJF2lJTJD)H+}jRF<3b+Fo9F zJN6%oan24e!@JTg6K{;Y_Y8Mn3{8m{dityKzeO{k(g7IG^3-;BR7u)lp$mfYFQy<= zKKG%8#CgExmk)Jum&%UVYnN)iFks1>WO-2r4-rC@YoD9%;R=T)9>Vps1H_be)x;Nh zVbIGD{hiMEccdKoW;w6@3F@k^a&d=iC$@X+9sy(z6ows3N-1^{&2#z*l+~8x=lZ$J zT=mI+f;RgU)#>be_G_5C;&Vm3xFFgHnEYZ6;g(#3EX+bqXu-*zQI=UG%5+<++&rb$ zsOm$DMay(9d)GyL?(0yHM#z7bm<-JZMd#C~fe3Npvs?i9dF@4;mQuu(X+Qw!(mA=^B z0a4LV(XUKXJ3`7Zd3B>u*e6DN+C3;b>z5CM?1)r<1<`usLHjQ~&8iEyWQ{xU@F?1f1e@Xj)3ZW@Iqq1IY|hHw@zyN}B;xotG|E&*p>*?*vyOE{McdIMer zRgwR0Wn9ysaevM{XZU;NqgElU$9~LM*@1D36-L^#=)

P8EP4Y@#)R#g)9<~ia( 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 E0jTFlT>t<8 literal 0 HcmV?d00001