From b4adca05592179b9065c9dafda1f56e254763940 Mon Sep 17 00:00:00 2001 From: rgarcia Date: Sun, 11 Oct 2015 13:40:31 +0200 Subject: [PATCH 01/24] refactors concern's polymorphic helpers --- .../concerns/commentable_actions.rb | 28 ++++--------------- app/controllers/concerns/polymorphic.rb | 24 ++++++++++++++++ 2 files changed, 29 insertions(+), 23 deletions(-) create mode 100644 app/controllers/concerns/polymorphic.rb diff --git a/app/controllers/concerns/commentable_actions.rb b/app/controllers/concerns/commentable_actions.rb index d59c67906..f0610de6c 100644 --- a/app/controllers/concerns/commentable_actions.rb +++ b/app/controllers/concerns/commentable_actions.rb @@ -1,5 +1,6 @@ module CommentableActions extend ActiveSupport::Concern + include Polymorphic def index @resources = @search_terms.present? ? resource_model.search(@search_terms) : resource_model.all @@ -58,29 +59,6 @@ module CommentableActions end private - def resource - @resource ||= instance_variable_get("@#{resource_name}") - end - - def resource_name - @resource_name ||= resource_model.to_s.downcase - end - - def set_resource_instance - instance_variable_set("@#{resource_name}", @resource) - end - - def set_resources_instance - instance_variable_set("@#{resource_name.pluralize}", @resources) - end - - def set_resource_votes(instance) - send("set_#{resource_name}_votes", instance) - end - - def strong_params - send("#{resource_name}_params") - end def track_event ahoy.track "#{resource_name}_created".to_sym, "#{resource_name}_id": resource.id @@ -103,4 +81,8 @@ module CommentableActions def parse_search_terms @search_terms = params[:search] if params[:search].present? end + + def set_resource_votes(instance) + send("set_#{resource_name}_votes", instance) + end end \ No newline at end of file diff --git a/app/controllers/concerns/polymorphic.rb b/app/controllers/concerns/polymorphic.rb new file mode 100644 index 000000000..51c5768c9 --- /dev/null +++ b/app/controllers/concerns/polymorphic.rb @@ -0,0 +1,24 @@ +module Polymorphic + + private + def resource + @resource ||= instance_variable_get("@#{resource_name}") + end + + def resource_name + @resource_name ||= resource_model.to_s.downcase + end + + def set_resource_instance + instance_variable_set("@#{resource_name}", @resource) + end + + def set_resources_instance + instance_variable_set("@#{resource_name.pluralize}", @resources) + end + + def strong_params + send("#{resource_name}_params") + end + +end \ No newline at end of file From 3edc23abe53c01c481b8c4408bdff86f263e4dd7 Mon Sep 17 00:00:00 2001 From: rgarcia Date: Sun, 11 Oct 2015 13:40:58 +0200 Subject: [PATCH 02/24] refactors moderator actions --- app/controllers/concerns/moderate_actions.rb | 60 +++++++++++++++++++ .../moderation/comments_controller.rb | 47 +++------------ .../moderation/debates_controller.rb | 46 ++------------ .../moderation/proposals_controller.rb | 46 ++------------ 4 files changed, 76 insertions(+), 123 deletions(-) create mode 100644 app/controllers/concerns/moderate_actions.rb diff --git a/app/controllers/concerns/moderate_actions.rb b/app/controllers/concerns/moderate_actions.rb new file mode 100644 index 000000000..792dacde0 --- /dev/null +++ b/app/controllers/concerns/moderate_actions.rb @@ -0,0 +1,60 @@ +module ModerateActions + extend ActiveSupport::Concern + include Polymorphic + + def index + @resources = @resources.send(@current_filter) + .send("sort_by_#{@current_order}") + .page(params[:page]) + .per(50) + set_resources_instance + end + + def hide + hide_resource resource + end + + def moderate + set_resource_params + @resources = @resources.where(id: params[:resource_ids]) + + if params[:hide_resources].present? + @resources.accessible_by(current_ability, :hide).each {|resource| hide_resource resource} + + elsif params[:ignore_flags].present? + @resources.accessible_by(current_ability, :ignore_flag).each(&:ignore_flag) + + elsif params[:block_authors].present? + author_ids = @resources.pluck(author_id).uniq + User.where(id: author_ids).accessible_by(current_ability, :block).each {|user| block_user user} + end + + redirect_to request.query_parameters.merge(action: :index) + end + + private + + def load_resources + @resources = resource_model.accessible_by(current_ability, :moderate) + end + + def hide_resource(resource) + resource.hide + Activity.log(current_user, :hide, resource) + end + + def block_user(user) + user.block + Activity.log(current_user, :block, user) + end + + def set_resource_params + params[:resource_ids] = params["#{resource_name}_ids"] + params[:hide_resources] = params["hide_#{resource_name.pluralize}"] + end + + def author_id + :author_id + end + +end \ No newline at end of file diff --git a/app/controllers/moderation/comments_controller.rb b/app/controllers/moderation/comments_controller.rb index 7177911e8..cf3197383 100644 --- a/app/controllers/moderation/comments_controller.rb +++ b/app/controllers/moderation/comments_controller.rb @@ -1,53 +1,20 @@ class Moderation::CommentsController < Moderation::BaseController + include ModerateActions + has_filters %w{pending_flag_review all with_ignored_flag}, only: :index has_orders %w{flags created_at}, only: :index - before_action :load_comments, only: [:index, :moderate] + before_action :load_resources, only: [:index, :moderate] load_and_authorize_resource - def index - @comments = @comments.send(@current_filter) - .send("sort_by_#{@current_order}") - .page(params[:page]) - .per(50) - end - - def hide - hide_comment @comment - end - - def moderate - @comments = @comments.where(id: params[:comment_ids]) - - if params[:hide_comments].present? - @comments.accessible_by(current_ability, :hide).each {|comment| hide_comment comment} - - elsif params[:ignore_flags].present? - @comments.accessible_by(current_ability, :ignore_flag).each(&:ignore_flag) - - elsif params[:block_authors].present? - author_ids = @comments.pluck(:user_id).uniq - User.where(id: author_ids).accessible_by(current_ability, :block).each {|user| block_user user} - end - - redirect_to request.query_parameters.merge(action: :index) - end - private - def load_comments - @comments = Comment.accessible_by(current_ability, :moderate) + def resource_model + Comment end - def hide_comment(comment) - comment.hide - Activity.log(current_user, :hide, comment) + def author_id + :user_id end - - def block_user(user) - user.block - Activity.log(current_user, :block, user) - end - end diff --git a/app/controllers/moderation/debates_controller.rb b/app/controllers/moderation/debates_controller.rb index 57c6a0e05..e2a6ba2a0 100644 --- a/app/controllers/moderation/debates_controller.rb +++ b/app/controllers/moderation/debates_controller.rb @@ -1,53 +1,17 @@ class Moderation::DebatesController < Moderation::BaseController + include ModerateActions + has_filters %w{pending_flag_review all with_ignored_flag}, only: :index has_orders %w{flags created_at}, only: :index - before_action :load_debates, only: [:index, :moderate] + before_action :load_resources, only: [:index, :moderate] load_and_authorize_resource - def index - @debates = @debates.send(@current_filter) - .send("sort_by_#{@current_order}") - .page(params[:page]) - .per(50) - end - - def hide - hide_debate @debate - end - - def moderate - @debates = @debates.where(id: params[:debate_ids]) - - if params[:hide_debates].present? - @debates.accessible_by(current_ability, :hide).each {|debate| hide_debate debate} - - elsif params[:ignore_flags].present? - @debates.accessible_by(current_ability, :ignore_flag).each(&:ignore_flag) - - elsif params[:block_authors].present? - author_ids = @debates.pluck(:author_id).uniq - User.where(id: author_ids).accessible_by(current_ability, :block).each {|user| block_user user} - end - - redirect_to request.query_parameters.merge(action: :index) - end - private - def load_debates - @debates = Debate.accessible_by(current_ability, :moderate) - end - - def hide_debate(debate) - debate.hide - Activity.log(current_user, :hide, debate) - end - - def block_user(user) - user.block - Activity.log(current_user, :block, user) + def resource_model + Debate end end diff --git a/app/controllers/moderation/proposals_controller.rb b/app/controllers/moderation/proposals_controller.rb index e59f3c79f..7d48a7c07 100644 --- a/app/controllers/moderation/proposals_controller.rb +++ b/app/controllers/moderation/proposals_controller.rb @@ -1,54 +1,16 @@ class Moderation::ProposalsController < Moderation::BaseController + include ModerateActions has_filters %w{pending_flag_review all with_ignored_flag}, only: :index has_orders %w{flags created_at}, only: :index - before_filter :load_proposals, only: [:index, :moderate] + before_filter :load_resources, only: [:index, :moderate] load_and_authorize_resource - def index - @proposals = @proposals.send(@current_filter) - .send("sort_by_#{@current_order}") - .page(params[:page]) - .per(50) - end - - def hide - hide_proposal @proposal - end - - def moderate - @proposals = @proposals.where(id: params[:proposal_ids]) - - if params[:hide_proposals].present? - @proposals.accessible_by(current_ability, :hide).each {|proposal| hide_proposal proposal} - - elsif params[:ignore_flags].present? - @proposals.accessible_by(current_ability, :ignore_flag).each(&:ignore_flag) - - elsif params[:block_authors].present? - author_ids = @proposals.pluck(:author_id).uniq - User.where(id: author_ids).accessible_by(current_ability, :block).each {|user| block_user user} - end - - redirect_to request.query_parameters.merge(action: :index) - end - private - def load_proposals - @proposals = Proposal.accessible_by(current_ability, :moderate) + def resource_model + Proposal end - - def hide_proposal(proposal) - proposal.hide - Activity.log(current_user, :hide, proposal) - end - - def block_user(user) - user.block - Activity.log(current_user, :block, user) - end - end From fdd777174c9e4649dfd8a21853e777c1db6a6186 Mon Sep 17 00:00:00 2001 From: rgarcia Date: Mon, 12 Oct 2015 22:38:18 +0200 Subject: [PATCH 03/24] allows updates of cached_votes --- app/models/concerns/taggable.rb | 2 +- spec/models/proposal_spec.rb | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/app/models/concerns/taggable.rb b/app/models/concerns/taggable.rb index 52efc04a7..9126e271a 100644 --- a/app/models/concerns/taggable.rb +++ b/app/models/concerns/taggable.rb @@ -3,7 +3,7 @@ module Taggable included do acts_as_taggable - validate :max_number_of_tags + validate :max_number_of_tags, on: :create end def tag_list_with_limit(limit = nil) diff --git a/spec/models/proposal_spec.rb b/spec/models/proposal_spec.rb index ac7c1edfb..c228962e1 100644 --- a/spec/models/proposal_spec.rb +++ b/spec/models/proposal_spec.rb @@ -194,6 +194,22 @@ describe Proposal do end end + describe '#cached_votes_up' do + + describe "with deprecated long tag list" do + + it "should increase number of cached_total_votes" do + proposal = create(:proposal) + + tag_list = ["tag1", "tag2", "tag3", "tag4", "tag5", "tag6", "tag7"] + proposal.update_attribute(:tag_list, tag_list) + + expect(proposal.update_cached_votes).to eq(true) + end + + end + end + describe '#hot_score' do let(:now) { Time.now } From db67eb5b23f9351d482de36817cf8f5809cdd986 Mon Sep 17 00:00:00 2001 From: rgarcia Date: Wed, 14 Oct 2015 17:53:49 +0200 Subject: [PATCH 04/24] redirects to managed user sign in path unless verified --- app/controllers/management/proposals_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/management/proposals_controller.rb b/app/controllers/management/proposals_controller.rb index 3e9e7541f..c529601c8 100644 --- a/app/controllers/management/proposals_controller.rb +++ b/app/controllers/management/proposals_controller.rb @@ -34,7 +34,7 @@ class Management::ProposalsController < Management::BaseController def check_verified_user unless current_user.level_two_or_three_verified? - redirect_to management_root_path, alert: t("management.proposals.alert.unverified_user") + redirect_to management_document_verifications_path, alert: t("management.proposals.alert.unverified_user") end end From e601374676348df7c5b2eff08fef2294b07bbbaa Mon Sep 17 00:00:00 2001 From: kikito Date: Wed, 14 Oct 2015 18:02:27 +0200 Subject: [PATCH 05/24] renames logout managed user to change user --- app/views/management/_account_info.html.erb | 2 +- config/locales/management.en.yml | 2 +- config/locales/management.es.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/management/_account_info.html.erb b/app/views/management/_account_info.html.erb index ba016c244..6d6bb044d 100644 --- a/app/views/management/_account_info.html.erb +++ b/app/views/management/_account_info.html.erb @@ -2,7 +2,7 @@
<% end %> - diff --git a/app/views/management/proposals/print.html.erb b/app/views/management/proposals/print.html.erb index 748092096..ddd36be14 100644 --- a/app/views/management/proposals/print.html.erb +++ b/app/views/management/proposals/print.html.erb @@ -1,7 +1,7 @@ -
+
- + <%= t('management.proposals.print.print_button') %> From 9cc6dcbfab4a7875940c7f6648fc7c5f9f8530ab Mon Sep 17 00:00:00 2001 From: rgarcia Date: Wed, 14 Oct 2015 18:36:58 +0200 Subject: [PATCH 07/24] fixes spec --- spec/features/management/managed_users_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/features/management/managed_users_spec.rb b/spec/features/management/managed_users_spec.rb index 83a36047e..dc0c3f3e0 100644 --- a/spec/features/management/managed_users_spec.rb +++ b/spec/features/management/managed_users_spec.rb @@ -111,7 +111,7 @@ feature 'Managed User' do expect(page).to have_content "Identified as" expect(page).to have_content "#{user.username}" - click_link "Logout" + click_link "Change user" end expect(page).to have_content "Signed out successfully." From c163d63813085f0a864316ac9b0c29754000e7c6 Mon Sep 17 00:00:00 2001 From: Alberto Garcia Cabeza Date: Wed, 14 Oct 2015 22:12:21 +0200 Subject: [PATCH 08/24] Improves styles for management UI --- app/assets/fonts/icons.eot | Bin 9412 -> 10544 bytes app/assets/fonts/icons.svg | 3 +- app/assets/fonts/icons.ttf | Bin 9256 -> 10388 bytes app/assets/fonts/icons.woff | Bin 7080 -> 8084 bytes app/assets/stylesheets/print.css | 58 ++++++++++++++++------------ app/views/management/_menu.html.erb | 4 +- 6 files changed, 36 insertions(+), 29 deletions(-) diff --git a/app/assets/fonts/icons.eot b/app/assets/fonts/icons.eot index 9bb4f6a688a2005b7278ca8f12f50e137d2db744..fed38cb4b73b91b2adc9fd5f288de42bdce9660e 100644 GIT binary patch delta 1614 zcmYjRTZkJ~82CflxyyU9+{buV4*MccJjS}m;>>})cdO*_e? z$;9p!C89!+rNuU)NUIdu2N5Y1LHi=2?SoH+N*{!RPy~IEJ_v#jvh_^1g>o|IpYQv> z^Pm3`=GLC;2ZV_&03VH>7xLWw$$`t~7plb@7q0@0t^z>f`JKCV!>b@re3;_F{Rf}U z?!R~R2LN>Op<>mj-+1xvb^wM@?o!!k)*n6umg--oep0s9md|{5_6`91FTl{z71Jp3 zpHAQD1Tfj2XTPLpu2bD%%PtxhX3zXeb@XmHP&HQT&|=O}|2B#TYev-!&z-#qF!BoJ zYIVEmEEa_i0MfT8UI(Nq`dl8Ey#IzW`ww^-N&x&a_txpKWc9g&JA%PJ zJ~5b(!5AYuJ(DHRU zhp7xrEhP$}&ID20xuI;h5K=`!8%kx;b4aV9R3wZAffx6Ryzt0emB>boND{#dMCuiI zvay#?C+ER$J)D3+7w|+BcwU&_c+eFF>At$BONpC?4gU7Q1rR@(Ji!sr!hxCq5nF1A+PP(mRNjI%|<=4?2TmI!=CUt zrAHE#dWGeX5q#ComDJzjG>pR}Omr@3!`$@vQH)_66PUz)9Kb;w!W3#aj3bg!D_iDx$v#zk^lF*Q zj(3x7RLUz3*?e!+Nzrast7gqGx{lb&drj#H_Xn>?kQrl;Pp={L@>ntr=cHfojAhEuU?O&ZTK9kawb zMwvC&Om5jS%D$Ribt=o1Vpk&;?QSxB!>n6tWZ5X1OSXN&TefYtpt{v+5{stZGRmgV zG>t}ag_x@}>6&5jZ&pgCO-gpL<<`U38FEm?M%U9wljHM`}smQ3ipGn~Xs=kwvX I_lfW8|I%YPQ2+n{ delta 506 zcmYk3JxE(o6vuz>!}L)LI%pM4V$}CE+6FO0sNi757_A>^V{5Hd$|HV4V&cb;xO8w5 zK`OU&a?s781;L>>6+v(k!A%OC6dW9M=&UDc2k+(HbN~PIzvrBL?q1@k&vRr$(BAY! zOu8=fo1N+8T4e{=PXKSMJK9464>Vj04#bCB!|~tazd#!mJd#Yi*&o{nRiK-~eVcKY zvUhhFqQ4NoHIvFutDmRaU|fMeFgxW=mdx$XsdCNt`MEJEclJb=NM(}lqBr+cbX$T4 z(rzwGM&A(s3&DYTH$7DrSv!Y%OSt)LW@*_xF^?rrPW&k}*=6M~yZBVr@t0Cv2sm>N zA`h)jk+%v)eb+)Ij=qki{%D621)0=cT;5_l_#&tf*^9}tSWD)=z`d-7xxR7WD5WQ diff --git a/app/assets/fonts/icons.svg b/app/assets/fonts/icons.svg index 31e98dac3..602058baf 100644 --- a/app/assets/fonts/icons.svg +++ b/app/assets/fonts/icons.svg @@ -7,7 +7,6 @@ - @@ -44,5 +43,5 @@ -icons.eot + diff --git a/app/assets/fonts/icons.ttf b/app/assets/fonts/icons.ttf index 3524044cf9df754627c0e02cd69c22b397ae919e..96e94423136a4d546cf33e396661d0ab27ad8889 100644 GIT binary patch delta 1706 zcmYLJU5Fc16h3GECqFaU>?GOz>|e5*Y`d23COb*j{ps4DwYJvQww6{4b~c$!vQ08+ zGO@c$C87@^ON;D^AXN~pP<$wgpnVak^}z>Gls*Xcr3mVS^g$2=Ve6Uf7IQQA%=evp z&pqEc$-Qytt!LYS0N{mJfQ94p^QVs1Z(X|%FtSW+?8yTM=ixaJ2%jN5aO~vn^s#&A zz5+l8pUzi}`mLw$?gd~Z;@&M9&HBTK6bVL-lV2)URu*6X;>wQz>^}g5=Srqg;NO`f z48PEmEtSl+!R=;v+N=>VRI1v`@+|u?;ZF#ksaSbqefssEDF7t}C#uGB9a_v)^6w!$ zP&2A#aOTP#fZHzxLe(`0NjMu&>S0 z?lAs_zrzkl!xYQ`bkAZY9ZHG{hJpc2P%)L%Cvw>-)Dr=61p84;Wjk0*j-n9If*}lw zf;fx%go?p*Zlbrk@8o{JzlVtdbt#kG+8)cxR}xXg>Mx`2qcuGKHrGqfx(e8*P|B? z&Ru;|6rB?KVHh9aJ?J9&I@M(&MXAL_N-h+f!gMa1>(Ye8U_7aJO=L5J>0mCPiA1#H zspJfjI^se>%n7`BSmcFmbKNCv)+Cop!ga~jE%4IjVTqiajGxP#fPM$?k|^-JFuVDn zv(QiT@>3m3+%nW0a68?`yVObf~h)M6IDyNc(xaj!xV8+p=Cmb>H8O&_^gkE&k=CXR0)hFVF(ji*n z3=-@NlI)DO(@pc+;%c6i`hK;GK4Chll;jmZnaf}f`M)qbTm)7l(WYVl;4}_7EX(r*QE zk8O-3F1AOg?FbAq$RdY43Mit4GP=->9`vGuD*CVs{n(8f1~3ROU11?y66`?X>&+U_m3Q7)EjY3sdJm-1G-S~Y8SQ?xIYZQE=} zd81<13PwXLm6z`OX?KZ*`L48)m(- zA}tzubHTDMxQmwM2&z|FO{qeuw~V4GG)<$CFG=PyC0#Qr{7dD6X-Neu-*WWu^+vg7 za|;!#$SzpR;)>O>TMMT17el%fna+i%5b8-gT!&yGMKsqz4(HsN@ZHP@KREXPJNoj{ Ee-p<*O#lD@ delta 514 zcmX|;JxE(o6vuz>BR0hr7yAK?X=2`s>4%6J9tw6)OiXKR;#ah-QXZNbB_FRfLv&Ga zl0qrHrBeq-p%e-ZB~$6tsT8`Ec2wx#&_!^wCsDkY!@2+epL6c{-}`oaH?@HVTxJu4 zY%)1D=51dY0PB*lfsx@vk_lQMaws^Ine2&Ye$RaYZB}q@q2ziWck0(bH-&q*!@!sx!RgFF$wWWh5Hw}{@$p|U#^MEvCJS0PwarvAnrWqy246{t~h{rr(j(IF> ZqQtmG7q_{ivat@$Qsvl<)^qQ5=RZ;VW1s*4 diff --git a/app/assets/fonts/icons.woff b/app/assets/fonts/icons.woff index f9944c81211865fa32af8e017ebfdcdfd09067c0..fb76f3b26da124fdec35092e214c4a0d5c186e59 100644 GIT binary patch delta 7984 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 +
  • <%= link_to t("management.menu.title"), management_root_path %> @@ -34,4 +34,4 @@ <% end %>
- +
From 3e9dc458bc3a194c5fe999f884f02d22e7b5cfbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baz=C3=A1n?= Date: Thu, 15 Oct 2015 13:43:15 +0200 Subject: [PATCH 09/24] adds manager_authenticator for UWeb Web Services --- lib/manager_authenticator.rb | 44 ++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 lib/manager_authenticator.rb diff --git a/lib/manager_authenticator.rb b/lib/manager_authenticator.rb new file mode 100644 index 000000000..a5b9921cc --- /dev/null +++ b/lib/manager_authenticator.rb @@ -0,0 +1,44 @@ +class ManagerAuthenticator + + def initialize(data={}) + @manager = {login: data[:login], user_key: data[:user_key], date: data[:date]} + end + + def auth + return false unless [@manager[:login], @manager[:user_key], @manager[:date]].all? {|_| _.present?} + return @manager if manager_exists? && application_authorized? + false + end + + private + + def manager_exists? + response = client.call(:get_status_user_data, message: { ub: {user_key: @manager[:user_key], date: @manager[:date]} }).body + parsed_response = parser.parse((response[:get_status_user_data_response][:get_status_user_data_return])) + @manager[:login] == parsed_response["USUARIO"]["LOGIN"] + rescue + false + end + + def application_authorized? + response = client.call(:get_applications_user_list, message: { ub: {user_key: @manager[:user_key]} }).body + parsed_response = parser.parse((response[:get_applications_user_list_response][:get_applications_user_list_return])) + aplication_value = parsed_response["APLICACIONES"]["APLICACION"] + # aplication_value from UWEB can be an array of hashes or a hash + aplication_value.include?( {"CLAVE_APLICACION" => application_key}) || aplication_value["CLAVE_APLICACION"] == application_key + rescue + false + end + + def client + @client ||= Savon.client(wsdl: Rails.application.secrets.managers_url) + end + + def parser + @parser ||= Nori.new + end + + def application_key + Rails.application.secrets.managers_application_key.to_s + end +end \ No newline at end of file From 89cc26c261f97b9cdcc2b0f56184c5d6d33688b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baz=C3=A1n?= Date: Thu, 15 Oct 2015 15:57:53 +0200 Subject: [PATCH 10/24] adds managers login via ManagerAuthenticators --- app/controllers/management/base_controller.rb | 2 +- .../management/sessions_controller.rb | 8 +++--- lib/manager_authenticator.rb | 2 +- .../management/sessions_controller_spec.rb | 26 +++++++------------ .../management/document_verifications_spec.rb | 2 +- .../management/email_verifications_spec.rb | 2 +- .../features/management/managed_users_spec.rb | 6 ++--- spec/features/management/proposals_spec.rb | 3 +-- spec/features/management/users_spec.rb | 2 +- spec/support/common_actions.rb | 6 +++-- 10 files changed, 27 insertions(+), 32 deletions(-) diff --git a/app/controllers/management/base_controller.rb b/app/controllers/management/base_controller.rb index 7d6c89b5f..144a28bfe 100644 --- a/app/controllers/management/base_controller.rb +++ b/app/controllers/management/base_controller.rb @@ -12,7 +12,7 @@ class Management::BaseController < ActionController::Base end def current_manager - @current_manager ||= Manager.find(session["manager_id"]) if session["manager_id"] + session["manager"] end def managed_user diff --git a/app/controllers/management/sessions_controller.rb b/app/controllers/management/sessions_controller.rb index 78f5a14c8..72bfdda14 100644 --- a/app/controllers/management/sessions_controller.rb +++ b/app/controllers/management/sessions_controller.rb @@ -1,9 +1,11 @@ +require "manager_authenticator" + class Management::SessionsController < ActionController::Base def create destroy_session - if manager = Manager.valid_manager(params[:login], params[:clave_usuario]) - session["manager_id"] = manager.id + if manager = ManagerAuthenticator.new(params).auth + session["manager"] = manager redirect_to management_root_path else raise ActionController::RoutingError.new('Not Found') @@ -18,7 +20,7 @@ class Management::SessionsController < ActionController::Base private def destroy_session - session["manager_id"] = nil + session["manager"] = nil end end \ No newline at end of file diff --git a/lib/manager_authenticator.rb b/lib/manager_authenticator.rb index a5b9921cc..3f0d58357 100644 --- a/lib/manager_authenticator.rb +++ b/lib/manager_authenticator.rb @@ -1,7 +1,7 @@ class ManagerAuthenticator def initialize(data={}) - @manager = {login: data[:login], user_key: data[:user_key], date: data[:date]} + @manager = {login: data[:login], user_key: data[:clave_usuario], date: data[:fecha_conexion]} end def auth diff --git a/spec/controllers/management/sessions_controller_spec.rb b/spec/controllers/management/sessions_controller_spec.rb index a1ac98279..f63cd3a56 100644 --- a/spec/controllers/management/sessions_controller_spec.rb +++ b/spec/controllers/management/sessions_controller_spec.rb @@ -2,36 +2,28 @@ require 'rails_helper' describe Management::SessionsController do - before(:all) do - create(:manager, username: "supermanager" , password: "secret") - end - describe 'Sign in' do - it "should return 404 if not username/password" do - expect { get :create }.to raise_error "Not Found" - end - - it "should return 404 if wrong username" do - expect { get :create, login: "nonexistent" , clave_usuario: "secret" }.to raise_error "Not Found" - end - - it "should return 404 if wrong password" do - expect { get :create, login: "supermanager" , clave_usuario: "wrong" }.to raise_error "Not Found" + it "should return 404 if wrong credentials" do + allow_any_instance_of(ManagerAuthenticator).to receive(:auth).and_return(false) + expect { get :create, login: "nonexistent" , clave_usuario: "wrong"}.to raise_error "Not Found" end it "should redirect to management root path if right credentials" do - get :create, login: "supermanager" , clave_usuario: "secret" + manager = {login: "JJB033", user_key: "31415926" , date: "20151031135905"} + allow_any_instance_of(ManagerAuthenticator).to receive(:auth).and_return(manager) + + get :create, login: "JJB033" , clave_usuario: "31415926", fecha_conexion: "20151031135905" expect(response).to be_redirect end end describe 'Sign out' do it "should destroy the session and redirect" do - session[:manager_id] = 1 + session[:manager] = {user_key: "31415926" , date: "20151031135905", login: "JJB033"} delete :destroy - expect(session[:manager_id]).to be_nil + expect(session[:manager]).to be_nil expect(response).to be_redirect end end diff --git a/spec/features/management/document_verifications_spec.rb b/spec/features/management/document_verifications_spec.rb index 4a9f8c44e..6e43dc1cf 100644 --- a/spec/features/management/document_verifications_spec.rb +++ b/spec/features/management/document_verifications_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' feature 'DocumentVerifications' do background do - login_as_manager(create(:manager)) + login_as_manager end scenario 'Verifying a level 3 user shows an "already verified" page' do diff --git a/spec/features/management/email_verifications_spec.rb b/spec/features/management/email_verifications_spec.rb index 96c0c78ed..cb695a0f7 100644 --- a/spec/features/management/email_verifications_spec.rb +++ b/spec/features/management/email_verifications_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' feature 'EmailVerifications' do scenario 'Verifying a level 1 user via email' do - login_as_manager(create(:manager)) + login_as_manager user = create(:user) diff --git a/spec/features/management/managed_users_spec.rb b/spec/features/management/managed_users_spec.rb index dc0c3f3e0..48b1809af 100644 --- a/spec/features/management/managed_users_spec.rb +++ b/spec/features/management/managed_users_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' feature 'Managed User' do background do - login_as_manager(create(:manager)) + login_as_manager end context "Currently managed user" do @@ -47,7 +47,7 @@ feature 'Managed User' do end scenario "User becomes verified as level two (pending email confirmation for level three)" do - login_as_manager(create(:manager)) + login_as_manager user = create(:user) @@ -71,7 +71,7 @@ feature 'Managed User' do end scenario "User is created as level three from scratch" do - login_as_manager(create(:manager)) + login_as_manager visit management_document_verifications_path fill_in 'document_verification_document_number', with: '1234' diff --git a/spec/features/management/proposals_spec.rb b/spec/features/management/proposals_spec.rb index 6c54dc04d..a035c600d 100644 --- a/spec/features/management/proposals_spec.rb +++ b/spec/features/management/proposals_spec.rb @@ -3,8 +3,7 @@ require 'rails_helper' feature 'Proposals' do background do - manager = create(:manager) - login_as_manager(manager) + login_as_manager end context "Create" do diff --git a/spec/features/management/users_spec.rb b/spec/features/management/users_spec.rb index bb2ffe7b4..2e2564df8 100644 --- a/spec/features/management/users_spec.rb +++ b/spec/features/management/users_spec.rb @@ -4,7 +4,7 @@ feature 'users' do scenario 'Creating a level 3 user from scratch' do - login_as_manager(create(:manager)) + login_as_manager visit management_document_verifications_path fill_in 'document_verification_document_number', with: '1234' diff --git a/spec/support/common_actions.rb b/spec/support/common_actions.rb index d57a5eaac..b53ff2816 100644 --- a/spec/support/common_actions.rb +++ b/spec/support/common_actions.rb @@ -24,8 +24,10 @@ module CommonActions click_button 'Log in' end - def login_as_manager(manager) - visit management_sign_in_path(login: manager.username, clave_usuario: manager.password) + def login_as_manager + login, user_key, date = "JJB042", "31415926", Time.now.strftime("%Y%m%d%H%M%S") + allow_any_instance_of(ManagerAuthenticator).to receive(:auth).and_return({login: login, user_key: user_key, date: date}) + visit management_sign_in_path(login: login, clave_usuario: user_key, fecha_conexion: date) end def login_managed_user(user) From 113ac9dc6737e0aa249693c83cecdfcf3962822f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baz=C3=A1n?= Date: Thu, 15 Oct 2015 15:58:48 +0200 Subject: [PATCH 11/24] removes unnecessary factory --- spec/factories.rb | 5 ----- 1 file changed, 5 deletions(-) diff --git a/spec/factories.rb b/spec/factories.rb index 6b665e884..83bc79af1 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -223,11 +223,6 @@ FactoryGirl.define do user end - factory :manager do - sequence(:username) { |n| "manager#{n}" } - password 'supersecret' - end - factory :organization do user responsible_name "Johnny Utah" From 855763267ff13a9ce351754c3a10b6a5c305effa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baz=C3=A1n?= Date: Thu, 15 Oct 2015 15:59:14 +0200 Subject: [PATCH 12/24] adds spec for lib/manager_authenticator --- spec/lib/manager_authenticator_spec.rb | 48 ++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 spec/lib/manager_authenticator_spec.rb diff --git a/spec/lib/manager_authenticator_spec.rb b/spec/lib/manager_authenticator_spec.rb new file mode 100644 index 000000000..f9f09acce --- /dev/null +++ b/spec/lib/manager_authenticator_spec.rb @@ -0,0 +1,48 @@ +require 'rails_helper' + +describe ManagerAuthenticator do + describe 'initialization params' do + it 'should cause auth to return false if blank login' do + authenticator = ManagerAuthenticator.new({login: "", clave_usuario: "31415926", fecha_conexion: "20151031135905"}) + expect(authenticator.auth).to be false + end + + it 'should cause auth to return false if blank user_key' do + authenticator = ManagerAuthenticator.new({login: "JJB033", clave_usuario: "", fecha_conexion: "20151031135905"}) + expect(authenticator.auth).to be false + end + + it 'should cause auth to return false if blank date' do + authenticator = ManagerAuthenticator.new({login: "JJB033", clave_usuario: "31415926", fecha_conexion: ""}) + expect(authenticator.auth).to be false + end + end + + describe '#auth' do + before(:all) do + @authenticator = ManagerAuthenticator.new({login: "JJB033", clave_usuario: "31415926", fecha_conexion: "20151031135905"}) + end + + it 'should return false if not manager_exists' do + allow(@authenticator).to receive(:manager_exists?).and_return(false) + allow(@authenticator).to receive(:application_authorized?).and_return(true) + + expect(@authenticator.auth).to be false + end + + it 'should return false if not application_authorized' do + allow(@authenticator).to receive(:manager_exists?).and_return(true) + allow(@authenticator).to receive(:application_authorized?).and_return(false) + + expect(@authenticator.auth).to be false + end + + it 'should return ok if manager_exists and application_authorized' do + allow(@authenticator).to receive(:manager_exists?).and_return(true) + allow(@authenticator).to receive(:application_authorized?).and_return(true) + + expect(@authenticator.auth).to be_truthy + end + + end +end \ No newline at end of file From df14e979ca5dfdfb9c3f5f52655150a444cf918c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baza=CC=81n?= Date: Thu, 15 Oct 2015 15:59:38 +0200 Subject: [PATCH 13/24] deletes Manager --- app/models/manager.rb | 12 ----- db/migrate/20151015135154_destroy_manager.rb | 16 +++++++ db/schema.rb | 12 +---- spec/models/manager_spec.rb | 46 -------------------- 4 files changed, 17 insertions(+), 69 deletions(-) delete mode 100644 app/models/manager.rb create mode 100644 db/migrate/20151015135154_destroy_manager.rb delete mode 100644 spec/models/manager_spec.rb diff --git a/app/models/manager.rb b/app/models/manager.rb deleted file mode 100644 index 6dc5cceea..000000000 --- a/app/models/manager.rb +++ /dev/null @@ -1,12 +0,0 @@ -class Manager < ActiveRecord::Base - validates :username, presence: true, uniqueness: true - validates :password_digest, presence: true - - has_secure_password - - def self.valid_manager(username = nil, password = nil) - return false unless username.present? && password.present? - Manager.find_by(username: username).try(:authenticate, password) - end - -end \ No newline at end of file diff --git a/db/migrate/20151015135154_destroy_manager.rb b/db/migrate/20151015135154_destroy_manager.rb new file mode 100644 index 000000000..41e16f0e3 --- /dev/null +++ b/db/migrate/20151015135154_destroy_manager.rb @@ -0,0 +1,16 @@ +class DestroyManager < ActiveRecord::Migration + def self.up + drop_table :managers + end + + def self.down + create_table :managers do |t| + t.string :username, null: false + t.string :password_digest, null: false + t.timestamp :last_login_at + t.timestamps + end + + add_index :managers, [:username] + end +end diff --git a/db/schema.rb b/db/schema.rb index 3dbea57a8..56d5a4a9f 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20151013145757) do +ActiveRecord::Schema.define(version: 20151015135154) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -168,16 +168,6 @@ ActiveRecord::Schema.define(version: 20151013145757) do add_index "locks", ["user_id"], name: "index_locks_on_user_id", using: :btree - create_table "managers", force: :cascade do |t| - t.string "username", null: false - t.string "password_digest", null: false - t.datetime "last_login_at" - t.datetime "created_at" - t.datetime "updated_at" - end - - add_index "managers", ["username"], name: "index_managers_on_username", using: :btree - create_table "moderators", force: :cascade do |t| t.integer "user_id" end diff --git a/spec/models/manager_spec.rb b/spec/models/manager_spec.rb deleted file mode 100644 index a6a89427c..000000000 --- a/spec/models/manager_spec.rb +++ /dev/null @@ -1,46 +0,0 @@ -require 'rails_helper' - -describe Manager do - - describe "valid?" do - - let(:manager) { create(:manager) } - - it "is false when username is blank" do - manager.username = nil - expect(manager).to_not be_valid - end - it "is false when password is blank" do - manager.password_digest = nil - expect(manager).to_not be_valid - end - - it "is true if username and password present" do - expect(manager).to be_valid - end - end - - describe "self.valid_manager" do - before(:all) { create(:manager, username: "Silvia" ,password: "supersecret") } - - it "is false when username is blank" do - expect(Manager.valid_manager(nil, "supersecret")).to be_blank - end - it "is false when password is blank" do - expect(Manager.valid_manager("Silvia", nil)).to be_blank - end - - it "is false if manager unexistent" do - expect(Manager.valid_manager("Manager", "supersecret")).to be_blank - end - - it "is false if wrong password unexistent" do - expect(Manager.valid_manager("Silvia", "wrong")).to be_blank - end - - it "is true if right username/password combination" do - expect(Manager.valid_manager("Silvia", "supersecret")).to be_present - end - end - -end \ No newline at end of file From 31788ff7eb7a990ccb51d0e1288a2da47925b704 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baz=C3=A1n?= Date: Thu, 15 Oct 2015 16:40:34 +0200 Subject: [PATCH 14/24] changes capistrano task description --- lib/capistrano/tasks/upload_secrets.cap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/capistrano/tasks/upload_secrets.cap b/lib/capistrano/tasks/upload_secrets.cap index 525bcc85d..e8b75bfcf 100644 --- a/lib/capistrano/tasks/upload_secrets.cap +++ b/lib/capistrano/tasks/upload_secrets.cap @@ -1,5 +1,5 @@ namespace :deploy do - desc "compiles assets locally then rsyncs" + desc "rsyncs local config/secrets.yml file" task :upload_secrets do on roles(:app) do |role| run_locally do From 5203f5c9834b065f74e65b4782709358216768bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baz=C3=A1n?= Date: Thu, 15 Oct 2015 17:05:34 +0200 Subject: [PATCH 15/24] adds specs for SOAP calls --- spec/lib/manager_authenticator_spec.rb | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/spec/lib/manager_authenticator_spec.rb b/spec/lib/manager_authenticator_spec.rb index f9f09acce..256303fdd 100644 --- a/spec/lib/manager_authenticator_spec.rb +++ b/spec/lib/manager_authenticator_spec.rb @@ -43,6 +43,23 @@ describe ManagerAuthenticator do expect(@authenticator.auth).to be_truthy end + end + describe 'SOAP' do + before(:all) do + @authenticator = ManagerAuthenticator.new({login: "JJB033", clave_usuario: "31415926", fecha_conexion: "20151031135905"}) + end + + it 'should call the verification user method' do + allow(@authenticator).to receive(:application_authorized?).and_return(true) + expect(@authenticator.send(:client)).to receive(:call).with(:get_status_user_data, message: { ub: {user_key: "31415926", date: "20151031135905"} }) + @authenticator.auth + end + + it 'should call the permissions check method' do + allow(@authenticator).to receive(:manager_exists?).and_return(true) + expect(@authenticator.send(:client)).to receive(:call).with(:get_applications_user_list, message: { ub: {user_key: "31415926"} }) + @authenticator.auth + end end end \ No newline at end of file From 1744769af22e069eefdf185ad776150717df1fd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baz=C3=A1n?= Date: Sat, 17 Oct 2015 13:17:47 +0200 Subject: [PATCH 16/24] cleans document number in management verification --- .../management/document_verifications_controller.rb | 5 +++++ config/locales/management.en.yml | 8 ++++---- spec/features/management/document_verifications_spec.rb | 9 +++++++++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/app/controllers/management/document_verifications_controller.rb b/app/controllers/management/document_verifications_controller.rb index 32d38c748..1b8fabcc2 100644 --- a/app/controllers/management/document_verifications_controller.rb +++ b/app/controllers/management/document_verifications_controller.rb @@ -1,5 +1,6 @@ class Management::DocumentVerificationsController < Management::BaseController + before_action :clean_document_number, only: :check before_action :set_document, only: :check def index @@ -41,4 +42,8 @@ class Management::DocumentVerificationsController < Management::BaseController session[:document_number] = params[:document_verification][:document_number] end + def clean_document_number + params[:document_verification][:document_number] = params[:document_verification][:document_number].gsub(/[^a-z0-9]+/i, "").upcase unless params[:document_verification][:document_number].blank? + end + end \ No newline at end of file diff --git a/config/locales/management.en.yml b/config/locales/management.en.yml index 1718c80d5..73b7ed608 100644 --- a/config/locales/management.en.yml +++ b/config/locales/management.en.yml @@ -17,10 +17,10 @@ en: title: "Management" account_info: identified_label: "Identified as:" - username_label: "Username" - email_label: "Email" - document_number_label: "Document number" - document_type_label: "Document type" + username_label: "Username:" + email_label: "Email:" + document_number_label: "Document number:" + document_type_label: "Document type:" change_user: "Change user" sessions: signed_out: "Signed out successfully." diff --git a/spec/features/management/document_verifications_spec.rb b/spec/features/management/document_verifications_spec.rb index 6e43dc1cf..4a437a661 100644 --- a/spec/features/management/document_verifications_spec.rb +++ b/spec/features/management/document_verifications_spec.rb @@ -53,4 +53,13 @@ feature 'DocumentVerifications' do expect(page).to have_content "Please introduce the email used on the account" end + scenario 'Document number is format-standarized' do + + visit management_document_verifications_path + fill_in 'document_verification_document_number', with: '12345 - h' + click_button 'Check' + + expect(page).to have_content "Document number: 12345H" + end + end \ No newline at end of file From c54341dd070283e828ebbc31e1fb049e88889d70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baz=C3=A1n?= Date: Sat, 17 Oct 2015 13:18:42 +0200 Subject: [PATCH 17/24] changes link to root in management layout --- app/views/layouts/management.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/layouts/management.html.erb b/app/views/layouts/management.html.erb index 0f641ad13..354fae1a1 100644 --- a/app/views/layouts/management.html.erb +++ b/app/views/layouts/management.html.erb @@ -27,7 +27,7 @@
+ +<%= render '/shared/print' %> \ No newline at end of file diff --git a/app/views/management/proposals/show.html.erb b/app/views/management/proposals/show.html.erb index 3b1f441f7..7d8e22804 100644 --- a/app/views/management/proposals/show.html.erb +++ b/app/views/management/proposals/show.html.erb @@ -1 +1,3 @@ -<%= render template: 'proposals/show' %> \ No newline at end of file +<%= render template: 'proposals/show' %> + +<%= render '/shared/print' %> \ No newline at end of file diff --git a/app/views/pages/conditions.html.erb b/app/views/pages/conditions.html.erb index 81245849e..2893830c5 100644 --- a/app/views/pages/conditions.html.erb +++ b/app/views/pages/conditions.html.erb @@ -95,3 +95,5 @@ + +<%= render '/shared/print' %> \ No newline at end of file diff --git a/app/views/pages/privacy.html.erb b/app/views/pages/privacy.html.erb index a79000ac8..093e68c28 100644 --- a/app/views/pages/privacy.html.erb +++ b/app/views/pages/privacy.html.erb @@ -21,3 +21,5 @@ + +<%= render '/shared/print' %> \ No newline at end of file diff --git a/app/views/shared/_print.html.erb b/app/views/shared/_print.html.erb new file mode 100644 index 000000000..652c26832 --- /dev/null +++ b/app/views/shared/_print.html.erb @@ -0,0 +1,3 @@ + + <%= t("shared.print.print_button") %> + \ No newline at end of file diff --git a/config/locales/en.yml b/config/locales/en.yml index 14ca26510..8e56cd69e 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -310,6 +310,8 @@ en: shared: tags_cloud: tags: Trend + print: + print_button: "Print this info" flag: Flag as inappropriate unflag: Undo flag collective: Collective diff --git a/config/locales/es.yml b/config/locales/es.yml index 866b2179e..18763a895 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -310,6 +310,8 @@ es: shared: tags_cloud: tags: Tendencias + print: + print_button: "Imprimir esta información" flag: Denunciar como inapropiado unflag: Deshacer denuncia collective: Colectivo From 07117f4a493e0a7d83df71e017eb54530e609d1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baz=C3=A1n?= Date: Mon, 19 Oct 2015 12:18:42 +0200 Subject: [PATCH 22/24] includes all date in document age verification --- .../verification/management/document.rb | 3 +- .../verification/management/document_spec.rb | 37 +++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 spec/models/verification/management/document_spec.rb diff --git a/app/models/verification/management/document.rb b/app/models/verification/management/document.rb index fb23528b8..ee9e5462d 100644 --- a/app/models/verification/management/document.rb +++ b/app/models/verification/management/document.rb @@ -1,5 +1,6 @@ class Verification::Management::Document include ActiveModel::Model + include ActiveModel::Dates attr_accessor :document_type attr_accessor :document_number @@ -31,7 +32,7 @@ class Verification::Management::Document end def under_sixteen?(response) - 16.years.ago.year < response.date_of_birth.to_date.year + 16.years.ago < string_to_date(response.date_of_birth) end def verified? diff --git a/spec/models/verification/management/document_spec.rb b/spec/models/verification/management/document_spec.rb new file mode 100644 index 000000000..b4140f7ed --- /dev/null +++ b/spec/models/verification/management/document_spec.rb @@ -0,0 +1,37 @@ +require 'rails_helper' + +describe Verification::Management::Document do + describe "#valid_age?" do + it "returns false when the user is younger than sixteen years old" do + census_response = double(date_of_birth: "31-12-#{16.years.ago.year}") + expect(Verification::Management::Document.new.valid_age?(census_response)).to be false + end + + it "returns true when the user is sixteen years old" do + census_response = double(date_of_birth: 16.years.ago.strftime("%d-%m-%Y")) + expect(Verification::Management::Document.new.valid_age?(census_response)).to be true + end + + it "returns true when the user is older than sixteen years old" do + census_response = double(date_of_birth: "31-12-#{33.years.ago.year}") + expect(Verification::Management::Document.new.valid_age?(census_response)).to be true + end + end + + describe "#under_sixteen?" do + it "returns true when the user is younger than sixteen years old" do + census_response = double(date_of_birth: "31-12-#{16.years.ago.year}") + expect(Verification::Management::Document.new.under_sixteen?(census_response)).to be true + end + + it "returns false when the user is sixteen years old" do + census_response = double(date_of_birth: 16.years.ago.strftime("%d-%m-%Y")) + expect(Verification::Management::Document.new.under_sixteen?(census_response)).to be false + end + + it "returns false when the user is older than sixteen years old" do + census_response = double(date_of_birth: "31-12-#{33.years.ago.year}") + expect(Verification::Management::Document.new.under_sixteen?(census_response)).to be false + end + end +end \ No newline at end of file From 8c339b54fc625b6cd97c5556970e1690da68f5b8 Mon Sep 17 00:00:00 2001 From: Alberto Garcia Cabeza Date: Mon, 19 Oct 2015 13:27:34 +0200 Subject: [PATCH 23/24] Adds new styles for print buttons --- app/assets/stylesheets/admin.scss | 13 ++++++++----- app/assets/stylesheets/layout.scss | 7 +++---- app/assets/stylesheets/print.css | 6 ++++++ app/views/management/proposals/new.html.erb | 6 +++--- app/views/management/proposals/show.html.erb | 4 ++-- app/views/pages/conditions.html.erb | 5 +++-- app/views/pages/privacy.html.erb | 5 +++-- app/views/shared/_print.html.erb | 2 +- config/locales/management.en.yml | 1 + config/locales/management.es.yml | 1 + 10 files changed, 31 insertions(+), 19 deletions(-) diff --git a/app/assets/stylesheets/admin.scss b/app/assets/stylesheets/admin.scss index 51161d55f..85423df75 100644 --- a/app/assets/stylesheets/admin.scss +++ b/app/assets/stylesheets/admin.scss @@ -68,6 +68,14 @@ body.admin { .filters h2 { margin-top: 0; } + + .proposal-new, .proposal-edit { + padding-top: 0; + } + + .proposal-show { + padding-top: rem-calc(54); + } } .is-featured { @@ -293,11 +301,6 @@ body.admin { // 05. Management // - - - - - - - - - - - - - - - - - - - - - - - - - -.postfix { - height: rem-calc(48); - line-height: rem-calc(48); -} - .user-permissions { ul { diff --git a/app/assets/stylesheets/layout.scss b/app/assets/stylesheets/layout.scss index 866daf600..5e7c189bb 100644 --- a/app/assets/stylesheets/layout.scss +++ b/app/assets/stylesheets/layout.scss @@ -958,8 +958,7 @@ form { em { background: white; - display: inline-block; - padding-left: rem-calc(6); + display: block; } } @@ -1147,9 +1146,9 @@ img.avatar, img.admin-avatar, img.moderator-avatar, img.initialjs-avatar { background-color: rgba(255,255,255,.5); color: rgba(0,0,0,.4); font-size: rem-calc(40); - left: 11px; + left: rem-calc(11); position: absolute; - top: 63px; + top: rem-calc(72); } .user-deleted { diff --git a/app/assets/stylesheets/print.css b/app/assets/stylesheets/print.css index 77b51c441..9418d5ee0 100644 --- a/app/assets/stylesheets/print.css +++ b/app/assets/stylesheets/print.css @@ -22,12 +22,18 @@ img.left { display: none !important; } .icon-proposals { display: none !important; } +.captcha { display: none !important; } + li.name span { display: none !important; } p.proposal-info span:nth-child(3) { display: none !important; } .top-links { display: none !important; } +.button { display: none !important; } + +input[type="submit"] { display: none !important; } + .select-order { border: 0; font-size: 24px; diff --git a/app/views/management/proposals/new.html.erb b/app/views/management/proposals/new.html.erb index d79197ca7..28c150e86 100644 --- a/app/views/management/proposals/new.html.erb +++ b/app/views/management/proposals/new.html.erb @@ -1,9 +1,9 @@ -
+<%= render '/shared/print' %> +
+

<%= t("management.proposals.create_proposal") %>

<%= render "proposals/form", form_url: management_proposals_url %>
- -<%= render '/shared/print' %> \ No newline at end of file diff --git a/app/views/management/proposals/show.html.erb b/app/views/management/proposals/show.html.erb index 7d8e22804..cc20459d4 100644 --- a/app/views/management/proposals/show.html.erb +++ b/app/views/management/proposals/show.html.erb @@ -1,3 +1,3 @@ -<%= render template: 'proposals/show' %> +<%= render '/shared/print' %> -<%= render '/shared/print' %> \ No newline at end of file +<%= render template: 'proposals/show' %> diff --git a/app/views/pages/conditions.html.erb b/app/views/pages/conditions.html.erb index 2893830c5..8cf4d5bf0 100644 --- a/app/views/pages/conditions.html.erb +++ b/app/views/pages/conditions.html.erb @@ -2,6 +2,9 @@
+ + <%= render '/shared/print' %> +

<%= t("pages.conditions") %>

AVISO LEGAL SOBRE LAS CONDICIONES DE USO, PRIVACIDAD Y PROTECCIÓN DE DATOS PERSONALES DEL PORTAL DE GOBIERNO ABIERTO DEL AYUNTAMIENTO DE MADRID

@@ -95,5 +98,3 @@
- -<%= render '/shared/print' %> \ No newline at end of file diff --git a/app/views/pages/privacy.html.erb b/app/views/pages/privacy.html.erb index 093e68c28..895fdbc76 100644 --- a/app/views/pages/privacy.html.erb +++ b/app/views/pages/privacy.html.erb @@ -2,6 +2,9 @@
+ + <%= render '/shared/print' %> +

<%= t("pages.privacy") %>

AVISO DE PROTECCIÓN DE DATOS

@@ -21,5 +24,3 @@
- -<%= render '/shared/print' %> \ No newline at end of file diff --git a/app/views/shared/_print.html.erb b/app/views/shared/_print.html.erb index 652c26832..471cf6692 100644 --- a/app/views/shared/_print.html.erb +++ b/app/views/shared/_print.html.erb @@ -1,3 +1,3 @@ - + <%= t("shared.print.print_button") %> \ No newline at end of file diff --git a/config/locales/management.en.yml b/config/locales/management.en.yml index 34a30a832..d4eb2e262 100644 --- a/config/locales/management.en.yml +++ b/config/locales/management.en.yml @@ -26,6 +26,7 @@ en: signed_out: "Signed out successfully." signed_out_managed_user: "User session signed out successfully." proposals: + create_proposal: "Create proposal" print: print_button: Print alert: diff --git a/config/locales/management.es.yml b/config/locales/management.es.yml index d56fb625d..dde24a2c6 100644 --- a/config/locales/management.es.yml +++ b/config/locales/management.es.yml @@ -26,6 +26,7 @@ es: signed_out: "Has cerrado la sesión correctamente." signed_out_managed_user: "Se ha cerrado correctamente la sesión del usuario." proposals: + create_proposal: "Crear propuesta" print: print_button: Imprimir alert: From b24de9eaff2e4b9c671daedf6238489898b259f7 Mon Sep 17 00:00:00 2001 From: Alberto Garcia Cabeza Date: Mon, 19 Oct 2015 13:36:32 +0200 Subject: [PATCH 24/24] Adds initial text on management index page --- app/views/management/dashboard/index.html.erb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app/views/management/dashboard/index.html.erb b/app/views/management/dashboard/index.html.erb index 8fc1b6100..4145592d8 100644 --- a/app/views/management/dashboard/index.html.erb +++ b/app/views/management/dashboard/index.html.erb @@ -1,3 +1,14 @@

<%= t("management.dashboard.index.title") %>

+ +

Desde aquí puedes gestionar usuarios a través de las siguientes acciones:

+ +

Usuarios

+ +

Crear propuesta

+ +

Apoyar propuesta

+ +

Imprimir propuestas

+