From b24a191b95f56a0f2e03bdf09c79876ffc0484a0 Mon Sep 17 00:00:00 2001 From: Andreas Maierhofer Date: Wed, 2 Jul 2014 10:30:22 +0200 Subject: [PATCH 01/11] created_at must be present on update, fixes #7262 --- app/models/pbs/role.rb | 3 +++ spec/models/role_spec.rb | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/models/pbs/role.rb b/app/models/pbs/role.rb index b5d96a92c..33196df0c 100644 --- a/app/models/pbs/role.rb +++ b/app/models/pbs/role.rb @@ -25,10 +25,13 @@ module Pbs::Role included do self.used_attributes += [:created_at, :deleted_at] + validates_presence_of :created_at, on: :update + validates :created_at, timeliness: { type: :datetime, on_or_before: :now, allow_blank: true } + validates :deleted_at, timeliness: { type: :datetime, on_or_before: :now, diff --git a/spec/models/role_spec.rb b/spec/models/role_spec.rb index 6303c700c..1d50fb198 100644 --- a/spec/models/role_spec.rb +++ b/spec/models/role_spec.rb @@ -64,7 +64,7 @@ it 'created_at has illegal format' do role.created_at = '303030' role.should_not be_valid - role.should have(1).error_on(:created_at) + role.should have(2).error_on(:created_at) role.created_at.should be_nil end From 2455cf31c5e373bacc3257583caf435a402449c9 Mon Sep 17 00:00:00 2001 From: Pascal Zumkehr Date: Tue, 8 Jul 2014 17:11:11 +0200 Subject: [PATCH 02/11] add json extensions for group and people --- app/views/groups/_attrs_pbs.json.jbuilder | 8 ++++++++ app/views/people/_details_pbs.json.jbuilder | 9 +++++++++ 2 files changed, 17 insertions(+) create mode 100644 app/views/groups/_attrs_pbs.json.jbuilder create mode 100644 app/views/people/_details_pbs.json.jbuilder diff --git a/app/views/groups/_attrs_pbs.json.jbuilder b/app/views/groups/_attrs_pbs.json.jbuilder new file mode 100644 index 000000000..6e245228f --- /dev/null +++ b/app/views/groups/_attrs_pbs.json.jbuilder @@ -0,0 +1,8 @@ +# Copyright (c) 2014, Pfadibewegung Schweiz. This file is part of +# hitobito_cevi and licensed under the Affero General Public License version 3 +# or later. See the COPYING file at the top-level directory or at +# https://github.com/hitobito/hitobito_cevi. + +json.extract!(entry, + *entry.used_attributes(:pbs_shortname, :website, :bank_account, :pta, :vkp, + :pbs_material_insurance, :description)) diff --git a/app/views/people/_details_pbs.json.jbuilder b/app/views/people/_details_pbs.json.jbuilder new file mode 100644 index 000000000..468b87238 --- /dev/null +++ b/app/views/people/_details_pbs.json.jbuilder @@ -0,0 +1,9 @@ +# Copyright (c) 2014, Pfadibewegung Schweiz. This file is part of +# hitobito_cevi and licensed under the Affero General Public License version 3 +# or later. See the COPYING file at the top-level directory or at +# https://github.com/hitobito/hitobito_cevi. + +json.extract!(entry, + :pbs_number, :j_s_number, :salutation_value, :correspondence_language, + :grade_of_school, :brother_and_sisters, :entry_date, :leaving_date) + From f26e2753039bed734a419b58bbe409a18f7dd056 Mon Sep 17 00:00:00 2001 From: Pascal Zumkehr Date: Wed, 9 Jul 2014 17:32:21 +0200 Subject: [PATCH 03/11] replace jbuilder with oat --- app/serializers/pbs/group_serializer.rb | 11 +++++++++++ app/serializers/pbs/person_serializer.rb | 11 +++++++++++ app/views/groups/_attrs_pbs.json.jbuilder | 8 -------- app/views/people/_details_pbs.json.jbuilder | 9 --------- lib/hitobito_pbs/wagon.rb | 4 ++++ 5 files changed, 26 insertions(+), 17 deletions(-) create mode 100644 app/serializers/pbs/group_serializer.rb create mode 100644 app/serializers/pbs/person_serializer.rb delete mode 100644 app/views/groups/_attrs_pbs.json.jbuilder delete mode 100644 app/views/people/_details_pbs.json.jbuilder diff --git a/app/serializers/pbs/group_serializer.rb b/app/serializers/pbs/group_serializer.rb new file mode 100644 index 000000000..2a3d0dc9c --- /dev/null +++ b/app/serializers/pbs/group_serializer.rb @@ -0,0 +1,11 @@ +module Pbs::GroupSerializer + extend ActiveSupport::Concern + + included do + extension(:attrs) do |_| + map_properties(*item.used_attributes(:pbs_shortname, :website, :bank_account, :pta, :vkp, + :pbs_material_insurance, :description)) + end + end + +end \ No newline at end of file diff --git a/app/serializers/pbs/person_serializer.rb b/app/serializers/pbs/person_serializer.rb new file mode 100644 index 000000000..0b4309875 --- /dev/null +++ b/app/serializers/pbs/person_serializer.rb @@ -0,0 +1,11 @@ +module Pbs::PersonSerializer + extend ActiveSupport::Concern + + included do + extension(:details) do |_| + map_properties :pbs_number, :j_s_number, :salutation_value, :correspondence_language, + :grade_of_school, :brother_and_sisters, :entry_date, :leaving_date + end + end + +end \ No newline at end of file diff --git a/app/views/groups/_attrs_pbs.json.jbuilder b/app/views/groups/_attrs_pbs.json.jbuilder deleted file mode 100644 index 6e245228f..000000000 --- a/app/views/groups/_attrs_pbs.json.jbuilder +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright (c) 2014, Pfadibewegung Schweiz. This file is part of -# hitobito_cevi and licensed under the Affero General Public License version 3 -# or later. See the COPYING file at the top-level directory or at -# https://github.com/hitobito/hitobito_cevi. - -json.extract!(entry, - *entry.used_attributes(:pbs_shortname, :website, :bank_account, :pta, :vkp, - :pbs_material_insurance, :description)) diff --git a/app/views/people/_details_pbs.json.jbuilder b/app/views/people/_details_pbs.json.jbuilder deleted file mode 100644 index 468b87238..000000000 --- a/app/views/people/_details_pbs.json.jbuilder +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2014, Pfadibewegung Schweiz. This file is part of -# hitobito_cevi and licensed under the Affero General Public License version 3 -# or later. See the COPYING file at the top-level directory or at -# https://github.com/hitobito/hitobito_cevi. - -json.extract!(entry, - :pbs_number, :j_s_number, :salutation_value, :correspondence_language, - :grade_of_school, :brother_and_sisters, :entry_date, :leaving_date) - diff --git a/lib/hitobito_pbs/wagon.rb b/lib/hitobito_pbs/wagon.rb index 028ab2a59..164fbcf84 100644 --- a/lib/hitobito_pbs/wagon.rb +++ b/lib/hitobito_pbs/wagon.rb @@ -19,6 +19,7 @@ class Wagon < Rails::Engine config.autoload_paths += %W( #{config.root}/app/abilities #{config.root}/app/domain #{config.root}/app/jobs + #{config.root}/app/serializers ) config.to_prepare do @@ -31,6 +32,9 @@ class Wagon < Rails::Engine GroupAbility.send :include, Pbs::GroupAbility VariousAbility.send :include, Pbs::VariousAbility + PersonSerializer.send :include, Pbs::PersonSerializer + GroupSerializer.send :include, Pbs::GroupSerializer + PeopleController.permitted_attrs += [:salutation, :title, :grade_of_school, :entry_date, :leaving_date, :j_s_number, :correspondence_language, :brother_and_sisters] From d94b9d87d92ccca53b58e614095e6b66d1f8d852 Mon Sep 17 00:00:00 2001 From: Andreas Maierhofer Date: Mon, 11 Aug 2014 16:36:24 +0200 Subject: [PATCH 04/11] info on login and people edit page, refs #6345 --- config/locales/views.pbs.de.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/config/locales/views.pbs.de.yml b/config/locales/views.pbs.de.yml index 4e5fff5c2..a9755973d 100644 --- a/config/locales/views.pbs.de.yml +++ b/config/locales/views.pbs.de.yml @@ -55,6 +55,8 @@ de: membercounts: people: + fields: + no_sensitive_information: In diesem Feld keine besonders schützenswerte Personendaten erfassen. fields_pbs: non_automatic_field: Dies ist kein automatisches Feld und muss manuell angepasst werden. in_abteilung: (in der Abteilung) @@ -67,3 +69,7 @@ de: please_confirm_census_data: 'Bitte ergänze das Geschlecht aller Mitglieder und bestätige den Bestand deiner Abteilung mit "Bestand bestätigen".' missing_gender_information: Um den Bestand bestätigen zu können, muss bei allen Mitgliedern das Geschlecht ausgefüllt sein. + devise: + sessions: + new: + usage_advise: Die Daten in der Mitgliederdatenbank dürfen nur im Zusammenhang mit Aktivitäten der Pfadi verwendet werden, sie dürfen z.B. nicht an Drittpersonen oder Organisationen weiter gegeben werden. Die Bearbeitung und Nutzung hat nach Treu und Glauben zu erfolgen und muss verhältnismässig sein. From 0ffd37edad9dce84c696cd801adedf6981fd3ae9 Mon Sep 17 00:00:00 2001 From: Mathis Hofer Date: Mon, 18 Aug 2014 09:33:31 +0200 Subject: [PATCH 05/11] add mho and bs to seed data --- db/seeds/development/1_people.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/db/seeds/development/1_people.rb b/db/seeds/development/1_people.rb index 3fbeaf779..4cfa8fe1b 100644 --- a/db/seeds/development/1_people.rb +++ b/db/seeds/development/1_people.rb @@ -22,7 +22,9 @@ def amount(role_type) 'Pierre Fritsch', 'Andreas Maierhofer', 'Andre Kunz', - 'Roland Studer'] + 'Roland Studer', + 'Mathis Hofer', + 'Bruno Santschi'] devs = {'Olivier Brian' => 'olivier.brian@bfh.ch'} puzzlers.each do |puz| From 09dd48001ddc51fe57768b056e91e5762c620870 Mon Sep 17 00:00:00 2001 From: Mathis Hofer Date: Mon, 18 Aug 2014 09:30:52 +0200 Subject: [PATCH 06/11] notify users after role change if actuator gains access to person data (#7603) --- app/jobs/group_membership_job.rb | 35 +++++++++++ app/mailers/group_membership_mailer.rb | 34 +++++++++++ app/models/pbs/role.rb | 28 +++++++++ app/views/roles/_fields_pbs.html.haml | 3 + config/locales/views.pbs.de.yml | 5 ++ db/seeds/custom_contents.rb | 36 ++++++++++++ spec/controllers/roles_controller_spec.rb | 62 +++++++++++++++++++- spec/domain/import/person_importer_spec.rb | 44 ++++++++++++++ spec/jobs/group_membership_job_spec.rb | 52 ++++++++++++++++ spec/mailers/group_membership_mailer_spec.rb | 45 ++++++++++++++ spec/models/role_spec.rb | 51 ++++++++++++++++ 11 files changed, 394 insertions(+), 1 deletion(-) create mode 100644 app/jobs/group_membership_job.rb create mode 100644 app/mailers/group_membership_mailer.rb create mode 100644 db/seeds/custom_contents.rb create mode 100644 spec/domain/import/person_importer_spec.rb create mode 100644 spec/jobs/group_membership_job_spec.rb create mode 100644 spec/mailers/group_membership_mailer_spec.rb diff --git a/app/jobs/group_membership_job.rb b/app/jobs/group_membership_job.rb new file mode 100644 index 000000000..18503e54a --- /dev/null +++ b/app/jobs/group_membership_job.rb @@ -0,0 +1,35 @@ +# encoding: utf-8 + +# Copyright (c) 2012-2014, Pfadibewegung Schweiz. This file is part of +# hitobito_pbs and licensed under the Affero General Public License version 3 +# or later. See the COPYING file at the top-level directory or at +# https://github.com/hitobito/hitobito_pbs. + +class GroupMembershipJob < BaseJob + + self.parameters = [:recipient_id, :actuator_id, :group_id, :locale] + + def initialize(recipient, actuator, group) + super() + @recipient_id = recipient.id + @actuator_id = actuator.id + @group_id = group.id + end + + def perform + set_locale + GroupMembershipMailer.added_to_group(recipient, actuator, group).deliver + end + + def recipient + @recipient ||= Person.find(@recipient_id) + end + + def actuator + @actuator ||= Person.find(@actuator_id) + end + + def group + @group ||= Group.find(@group_id) + end +end diff --git a/app/mailers/group_membership_mailer.rb b/app/mailers/group_membership_mailer.rb new file mode 100644 index 000000000..9438fa7e2 --- /dev/null +++ b/app/mailers/group_membership_mailer.rb @@ -0,0 +1,34 @@ +# encoding: utf-8 + +# Copyright (c) 2012-2014, Pfadibewegung Schweiz. This file is part of +# hitobito_pbs and licensed under the Affero General Public License version 3 +# or later. See the COPYING file at the top-level directory or at +# https://github.com/hitobito/hitobito_pbs. + +class GroupMembershipMailer < ActionMailer::Base + + CONTENT_GROUP_MEMBERSHIP = 'group_membership' + + def added_to_group(recipient, actuator, group) + content = CustomContent.get(CONTENT_GROUP_MEMBERSHIP) + values = { + 'recipient-name' => recipient.greeting_name, + 'actuator-name' => actuator.to_s, + 'group-link' => group_link_with_layer(group) + } + + # This email is only sent to the main email address. + mail(to: recipient.email, subject: content.subject) do |format| + format.html { render text: content.body_with_values(values) } + end + end + + private + + def group_link_with_layer(group) + group_links = group.with_layer.map do |g| + "#{g}" + end + group_links.join(' / ') + end +end diff --git a/app/models/pbs/role.rb b/app/models/pbs/role.rb index 33196df0c..76545b39f 100644 --- a/app/models/pbs/role.rb +++ b/app/models/pbs/role.rb @@ -37,6 +37,9 @@ module Pbs::Role on_or_before: :now, after: ->(role) { role.created_at }, allow_blank: true } + + before_create :detect_group_membership_notification + after_create :send_group_membership_notification end def created_at=(value) @@ -52,4 +55,29 @@ def deleted_at=(value) # could not set value super(nil) end + + def detect_group_membership_notification + @send_notification = false; + + return unless Person.stamper + @current_user = Person.find(Person.stamper) + + # don't notify newly created users without roles + p = Person.find(person.id) + return unless p.roles.exists? + + # manually initialize ability (this is not very beautiful but + # must be done to detect change in access to person data) + @send_notification = Ability.new(@current_user).cannot?(:update, p) + + true + end + + def send_group_membership_notification + if @send_notification && @current_user + GroupMembershipJob.new(person, @current_user, group).enqueue! + end + + true + end end diff --git a/app/views/roles/_fields_pbs.html.haml b/app/views/roles/_fields_pbs.html.haml index f8a334755..5ed987ff0 100644 --- a/app/views/roles/_fields_pbs.html.haml +++ b/app/views/roles/_fields_pbs.html.haml @@ -4,3 +4,6 @@ = f.labeled(:deleted_at) do = f.date_field(:deleted_at, class: 'date span6', value: f(@role.deleted_at.try(:to_date))) + += field_set_tag t('.notification') do + %p= t('.notification_hint') diff --git a/config/locales/views.pbs.de.yml b/config/locales/views.pbs.de.yml index a9755973d..2034ff6a0 100644 --- a/config/locales/views.pbs.de.yml +++ b/config/locales/views.pbs.de.yml @@ -69,6 +69,11 @@ de: please_confirm_census_data: 'Bitte ergänze das Geschlecht aller Mitglieder und bestätige den Bestand deiner Abteilung mit "Bestand bestätigen".' missing_gender_information: Um den Bestand bestätigen zu können, muss bei allen Mitgliedern das Geschlecht ausgefüllt sein. + roles: + fields_pbs: + notification: Benachrichtigung + notification_hint: Bestehende Personen werden per E-Mail über die Änderung informiert, sofern Du dadurch mehr Personendaten einsehen kannst. + devise: sessions: new: diff --git a/db/seeds/custom_contents.rb b/db/seeds/custom_contents.rb new file mode 100644 index 000000000..576574efe --- /dev/null +++ b/db/seeds/custom_contents.rb @@ -0,0 +1,36 @@ +# encoding: utf-8 + +# Copyright (c) 2012-2014, Pfadibewegung Schweiz. This file is part of +# hitobito_pbs and licensed under the Affero General Public License version 3 +# or later. See the COPYING file at the top-level directory or at +# https://github.com/hitobito/hitobito_pbs. + +CustomContent.seed_once(:key, + { key: GroupMembershipMailer::CONTENT_GROUP_MEMBERSHIP, + placeholders_required: 'actuator-name, group-link', + placeholders_optional: 'recipient-name' } +) + +group_membership_id = CustomContent.where(key: GroupMembershipMailer::CONTENT_GROUP_MEMBERSHIP).first.id + +CustomContent::Translation.seed_once(:custom_content_id, :locale, + { custom_content_id: group_membership_id, + locale: 'de', + label: 'Information bei neuer Gruppenzugehörigkeit', + subject: "Aufnahme in Gruppe", + body: "Hallo {recipient-name}

" \ + "{actuator-name} hat dich zur Gruppe {group-link} hinzugefügt.

" \ + "Bis bald!" }, + + { custom_content_id: group_membership_id, + locale: 'fr', + label: 'Informations pour les nouveau membres du groupe', + subject: 'Admission dans le groupe', + body: "Salut {recipient-name}

" \ + "{actuator-name} t\'as ajouté au groupe {group-link}.

" \ + "A bientôt!"}, + + { custom_content_id: group_membership_id, + locale: 'it', + label: 'Informazioni per la nuova appartenenza al gruppo' } +) diff --git a/spec/controllers/roles_controller_spec.rb b/spec/controllers/roles_controller_spec.rb index 16542a1b3..86e31137d 100644 --- a/spec/controllers/roles_controller_spec.rb +++ b/spec/controllers/roles_controller_spec.rb @@ -33,7 +33,6 @@ end describe 'POST #create' do - context 'with valid params' do let(:role_params) do role_defaults.merge(created_at: Date.new(2014, 3, 4), @@ -82,6 +81,67 @@ end end + context 'notification when gaining access to more person data' do + let(:actuator) { people(:al_schekka) } + let(:home_group) { groups(:schekka) } + let(:foreign_group) { groups(:chaeib) } + let(:person) { Fabricate(:person, first_name: 'Asdf') } + + before do + sign_in(actuator) + Person.stamper = actuator + end + + after { Person.reset_stamper } + + it 'is sent on role creation with more access' do + Fabricate(Group::Abteilung::Sekretariat.name.to_sym, group: foreign_group, person: person) + + role_params = { group_id: home_group.id, + person_id: person.id, + type: Group::Abteilung::Sekretariat.sti_name } + expect { post :create, group_id: home_group.id, role: role_params }. + to change { Delayed::Job.count }.by(1) + Delayed::Job.first.handler.should include('GroupMembershipJob') + end + + it 'is not sent on role creation with equal access' do + Fabricate(Group::Abteilung::Sekretariat.name.to_sym, group: home_group, person: person) + + role_params = { group_id: home_group.id, + person_id: person.id, + type: Group::Abteilung::Revisor.sti_name } + expect { post :create, group_id: home_group.id, role: role_params }. + not_to change { Delayed::Job.count } + end + + it 'is not sent on role creation for new person' do + role_params = { group_id: home_group.id, + person_id: nil, + type: Group::Abteilung::Sekretariat.sti_name, + new_person: { first_name: 'Asdf', last_name: 'Asdf' } } + expect { post :create, group_id: home_group.id, role: role_params }. + not_to change { Delayed::Job.count } + end + + it 'is not sent on role update (not possible to gain access via update)' do + child_group = groups(:sunnewirbu) + role = Fabricate(Group::Abteilung::Revisor.name.to_sym, group: home_group, person: person) + + role_params = { group_id: child_group.id, + type: Group::Woelfe::Wolf.sti_name } + expect { put :update, group_id: home_group.id, id: role.id, role: role_params }. + not_to change { Delayed::Job.count } + end + + it 'is not sent on role destruction' do + role = Fabricate(Group::Abteilung::Sekretariat.name.to_sym, group: home_group, person: person) + + expect { delete :destroy, group_id: home_group.id, id: role.id }. + not_to change { Delayed::Job.count } + end + end + end end diff --git a/spec/domain/import/person_importer_spec.rb b/spec/domain/import/person_importer_spec.rb new file mode 100644 index 000000000..06143e50f --- /dev/null +++ b/spec/domain/import/person_importer_spec.rb @@ -0,0 +1,44 @@ +# encoding: utf-8 + +# Copyright (c) 2012-2013, Jungwacht Blauring Schweiz. This file is part of +# hitobito and licensed under the Affero General Public License version 3 +# or later. See the COPYING file at the top-level directory or at +# https://github.com/hitobito/hitobito. + +require 'spec_helper' +describe Import::PersonImporter do + include CsvImportMacros + + let(:importer) do + Import::PersonImporter.new(group: groups(:schekka), + role_type: Group::Abteilung::Sekretariat, + data: data) + end + subject { importer } + + context 'notification when gaining access to more person data' do + let(:parser) { Import::CsvParser.new(File.read(path(:list))) } + let(:mapping) { headers_mapping(parser) } + let(:data) { parser.map_data(mapping) } + let(:actuator) { people(:al_schekka) } + let(:foreign_group) { groups(:chaeib) } + + before do + parser.parse + Person.stamper = actuator + end + + it 'is sent on role creation with more access' do + person = Fabricate(:person, first_name: 'Ramiro', last_name: 'Brown', + email: 'ramiro_brown@example.com') + Fabricate(Group::Abteilung::Sekretariat.name.to_sym, group: foreign_group, person: person) + + expect { importer.import }.to change { Delayed::Job.count }.by(1) + Delayed::Job.first.handler.should include('GroupMembershipJob') + end + + it 'is not sent on role creation for new person' do + expect { importer.import }.not_to change { Delayed::Job.count } + end + end +end diff --git a/spec/jobs/group_membership_job_spec.rb b/spec/jobs/group_membership_job_spec.rb new file mode 100644 index 000000000..89c210e57 --- /dev/null +++ b/spec/jobs/group_membership_job_spec.rb @@ -0,0 +1,52 @@ +# encoding: utf-8 + +# Copyright (c) 2012-2013, Jungwacht Blauring Schweiz. This file is part of +# hitobito and licensed under the Affero General Public License version 3 +# or later. See the COPYING file at the top-level directory or at +# https://github.com/hitobito/hitobito. + +require 'spec_helper' + +describe GroupMembershipJob do + + let(:recipient) { people(:child) } + let(:actuator) { people(:al_schekka) } + let(:group) { groups(:schekka) } + + before do + SeedFu.quiet = true + SeedFu.seed [Rails.root.join('db', 'seeds')] + end + + subject { GroupMembershipJob.new(recipient, actuator, group) } + + its(:parameters) do + should == { recipient_id: recipient.id, + actuator_id: actuator.id, + group_id: group.id, + locale: I18n.locale.to_s } + end + + it 'sends email' do + subject.perform + last_email.should be_present + last_email.body.should =~ /Hallo #{recipient.greeting_name}.*#{group.to_s}/ + end + + context 'with locale' do + after { I18n.locale = I18n.default_locale } + + subject do + I18n.locale = :fr + GroupMembershipJob.new(recipient, actuator, group) + end + + it 'sends localized email' do + I18n.locale = :de + subject.perform + last_email.should be_present + last_email.body.should =~ /Salut #{recipient.greeting_name}.*#{group.to_s}/ + end + end + +end diff --git a/spec/mailers/group_membership_mailer_spec.rb b/spec/mailers/group_membership_mailer_spec.rb new file mode 100644 index 000000000..1e37fd50b --- /dev/null +++ b/spec/mailers/group_membership_mailer_spec.rb @@ -0,0 +1,45 @@ +# encoding: utf-8 + +# Copyright (c) 2012-2014, Pfadibewegung Schweiz. This file is part of +# hitobito_pbs and licensed under the Affero General Public License version 3 +# or later. See the COPYING file at the top-level directory or at +# https://github.com/hitobito/hitobito_pbs. + +require 'spec_helper' + +describe GroupMembershipMailer do + + before do + SeedFu.quiet = true + SeedFu.seed [Rails.root.join('db', 'seeds')] + end + + let(:recipient) { people(:child) } + let(:actuator) { people(:al_schekka) } + let(:group) { groups(:schekka) } + let(:mail) { GroupMembershipMailer.added_to_group(recipient, actuator, group) } + + context 'headers' do + subject { mail } + its(:subject) { should eq 'Aufnahme in Gruppe' } + its(:to) { should eq ['child1@hitobito.example.com'] } + its(:from) { should eq ['noreply@localhost'] } + end + + context 'body' do + subject { mail.body } + + it 'renders placeholders' do + should =~ /Hallo My/ + should =~ /AL Schekka hat dich zur Gruppe.*Schekka.*hinzugefügt/ + end + end + + context 'with additional emails' do + it 'does not send to them' do + Fabricate(:additional_email, contactable: recipient) + mail.to.should eq [recipient.email] + end + end + +end diff --git a/spec/models/role_spec.rb b/spec/models/role_spec.rb index 1d50fb198..149bfe77f 100644 --- a/spec/models/role_spec.rb +++ b/spec/models/role_spec.rb @@ -77,4 +77,55 @@ end end + context 'notification when gaining access to more person data' do + let(:actuator) { people(:al_schekka) } + let(:home_group) { groups(:schekka) } + let(:foreign_group) { groups(:chaeib) } + let(:person) { Fabricate(:person, first_name: 'Asdf') } + + before { Person.stamper = actuator } + after { Person.reset_stamper } + + it 'is sent on role creation with more access' do + Fabricate(Group::Abteilung::Sekretariat.name.to_sym, group: foreign_group, person: person) + + role = Role.new(group_id: home_group.id, + person_id: person.id, + type: Group::Abteilung::Sekretariat.sti_name) + expect { role.save! }.to change { Delayed::Job.count }.by(1) + Delayed::Job.first.handler.should include('GroupMembershipJob') + end + + it 'is not sent on role creation with equal access' do + Fabricate(Group::Abteilung::Sekretariat.name.to_sym, group: home_group, person: person) + + role = Role.new(group_id: home_group.id, + person_id: person.id, + type: Group::Abteilung::Revisor.sti_name) + expect { role.save! }.not_to change { Delayed::Job.count } + end + + it 'is not sent on role creation for new person' do + role = Role.new(group_id: home_group.id, + person_id: person.id, + type: Group::Abteilung::Sekretariat.sti_name) + expect { role.save! }.not_to change { Delayed::Job.count } + end + + it 'is not sent on role update (not possible to gain access via update)' do + child_group = groups(:sunnewirbu) + role = Fabricate(Group::Abteilung::Revisor.name.to_sym, group: home_group, person: person) + + role.type = Group::Woelfe::Wolf.sti_name + expect { role.save! }.not_to change { Delayed::Job.count } + end + + it 'is not sent on role destruction' do + role = Fabricate(Group::Abteilung::Sekretariat.name.to_sym, group: home_group, person: person) + + expect { role.destroy! }.not_to change { Delayed::Job.count } + end + + end + end From b366a9f9d8ac8cec9cbfb8a29cd60a19934d5ab1 Mon Sep 17 00:00:00 2001 From: Pascal Zumkehr Date: Wed, 20 Aug 2014 15:39:58 +0200 Subject: [PATCH 07/11] add people relations for siblings --- config/locales/models.pbs.de.yml | 5 +++++ config/settings.yml | 4 ++-- lib/hitobito_pbs/wagon.rb | 2 ++ spec/models/people_relation_spec.rb | 13 +++++++++++++ 4 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 spec/models/people_relation_spec.rb diff --git a/config/locales/models.pbs.de.yml b/config/locales/models.pbs.de.yml index 54004f1f0..5eb975c83 100644 --- a/config/locales/models.pbs.de.yml +++ b/config/locales/models.pbs.de.yml @@ -661,6 +661,7 @@ de: j_s_number: J+S Personennummer correspondence_language: Korrespondenzsprache brother_and_sisters: Geschwister + relations_to_tails: Geschwister group: pta: PTA @@ -671,6 +672,10 @@ de: bank_account: Bank-/Postverbindung description: Beschreibung + people_relation: + kinds: + sibling: Geschwister + census: year: Jahr start_at: Ab diff --git a/config/settings.yml b/config/settings.yml index b3255edb8..8301aafb8 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -6,7 +6,6 @@ # Settings relevant for the jubla wagon # Overrides settings from the main application application: - #name: Pfadi languages: de: Deutsch @@ -16,4 +15,5 @@ application: # The person with this email has root access to everything # This person should only be used by the operators of the application, not the customers. # Initially, a password reset token may be mailed from the application to this address to set a password. -root_email: hitobito-pbs@puzzle.ch \ No newline at end of file +root_email: hitobito-pbs@puzzle.ch + diff --git a/lib/hitobito_pbs/wagon.rb b/lib/hitobito_pbs/wagon.rb index 164fbcf84..fb2c688a7 100644 --- a/lib/hitobito_pbs/wagon.rb +++ b/lib/hitobito_pbs/wagon.rb @@ -29,6 +29,8 @@ class Wagon < Rails::Engine Person.send :include, Pbs::Person Role.send :include, Pbs::Role + PeopleRelation.kind_opposites['sibling'] = 'sibling' + GroupAbility.send :include, Pbs::GroupAbility VariousAbility.send :include, Pbs::VariousAbility diff --git a/spec/models/people_relation_spec.rb b/spec/models/people_relation_spec.rb new file mode 100644 index 000000000..f826399e0 --- /dev/null +++ b/spec/models/people_relation_spec.rb @@ -0,0 +1,13 @@ +# encoding: utf-8 + +# Copyright (c) 2014, Pfadibewegung Schweiz. This file is part of +# hitobito_pbs and licensed under the Affero General Public License version 3 +# or later. See the COPYING file at the top-level directory or at +# https://github.com/hitobito/hitobito_pbs. + + +require 'spec_helper' + +describe PeopleRelation do + include_examples 'people relation kinds' +end \ No newline at end of file From ba70f2a6d561fe8ce1b913ca025aa61609028251 Mon Sep 17 00:00:00 2001 From: Pascal Zumkehr Date: Wed, 20 Aug 2014 17:58:56 +0200 Subject: [PATCH 08/11] add missing copyrights --- Gemfile | 7 +++++++ Rakefile | 7 +++++++ app/serializers/pbs/group_serializer.rb | 7 +++++++ app/serializers/pbs/person_serializer.rb | 7 +++++++ 4 files changed, 28 insertions(+) diff --git a/Gemfile b/Gemfile index a4641c9b8..19ec68e44 100644 --- a/Gemfile +++ b/Gemfile @@ -1,3 +1,10 @@ +# encoding: utf-8 + +# Copyright (c) 2014, Pfadibewegung Schweiz. This file is part of +# hitobito and licensed under the Affero General Public License version 3 +# or later. See the COPYING file at the top-level directory or at +# https://github.com/hitobito/hitobito. + require File.expand_path('../app_root', __FILE__) source 'https://rubygems.org' diff --git a/Rakefile b/Rakefile index 44af0ca9c..e3a43bf41 100644 --- a/Rakefile +++ b/Rakefile @@ -1,5 +1,12 @@ +# encoding: utf-8 #!/usr/bin/env rake +# Copyright (c) 2014, Pfadibewegung Schweiz. This file is part of +# hitobito and licensed under the Affero General Public License version 3 +# or later. See the COPYING file at the top-level directory or at +# https://github.com/hitobito/hitobito. + + begin require 'bundler/setup' rescue LoadError diff --git a/app/serializers/pbs/group_serializer.rb b/app/serializers/pbs/group_serializer.rb index 2a3d0dc9c..27c3a3e78 100644 --- a/app/serializers/pbs/group_serializer.rb +++ b/app/serializers/pbs/group_serializer.rb @@ -1,3 +1,10 @@ +# encoding: utf-8 + +# Copyright (c) 2014, Pfadibewegung Schweiz. This file is part of +# hitobito and licensed under the Affero General Public License version 3 +# or later. See the COPYING file at the top-level directory or at +# https://github.com/hitobito/hitobito. + module Pbs::GroupSerializer extend ActiveSupport::Concern diff --git a/app/serializers/pbs/person_serializer.rb b/app/serializers/pbs/person_serializer.rb index 0b4309875..f2a8ddd2a 100644 --- a/app/serializers/pbs/person_serializer.rb +++ b/app/serializers/pbs/person_serializer.rb @@ -1,3 +1,10 @@ +# encoding: utf-8 + +# Copyright (c) 2014, Pfadibewegung Schweiz. This file is part of +# hitobito and licensed under the Affero General Public License version 3 +# or later. See the COPYING file at the top-level directory or at +# https://github.com/hitobito/hitobito. + module Pbs::PersonSerializer extend ActiveSupport::Concern From cc1879f458c273786414c843fcbe77b2d7dd228c Mon Sep 17 00:00:00 2001 From: Pascal Zumkehr Date: Mon, 1 Sep 2014 13:26:56 +0200 Subject: [PATCH 09/11] upgrade to rails 4.1 --- spec/models/role_spec.rb | 2 +- spec/spec_helper.rb | 33 ++++++++------------------------- 2 files changed, 9 insertions(+), 26 deletions(-) diff --git a/spec/models/role_spec.rb b/spec/models/role_spec.rb index 149bfe77f..1a8ace841 100644 --- a/spec/models/role_spec.rb +++ b/spec/models/role_spec.rb @@ -123,7 +123,7 @@ it 'is not sent on role destruction' do role = Fabricate(Group::Abteilung::Sekretariat.name.to_sym, group: home_group, person: person) - expect { role.destroy! }.not_to change { Delayed::Job.count } + expect { role.really_destroy! }.not_to change { Delayed::Job.count } end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 4cf90bb7a..1577d17e6 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -5,33 +5,16 @@ # or later. See the COPYING file at the top-level directory or at # https://github.com/hitobito/hitobito_pbs. -def init_wagon - init_app_helper - config_rspec -end - -def init_app_helper - load File.expand_path('../../app_root.rb', __FILE__) - ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) +load File.expand_path('../../app_root.rb', __FILE__) +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) - require File.join(ENV['APP_ROOT'], 'spec', 'spec_helper.rb') +require File.join(ENV['APP_ROOT'], 'spec', 'spec_helper.rb') - # Requires supporting ruby files with custom matchers and macros, etc, - # in spec/support/ and its subdirectories. - Dir[HitobitoPbs::Wagon.root.join('spec/support/**/*.rb')].sort.each { |f| require f } -end +# Requires supporting ruby files with custom matchers and macros, etc, +# in spec/support/ and its subdirectories. +Dir[HitobitoPbs::Wagon.root.join('spec/support/**/*.rb')].sort.each { |f| require f } -def config_rspec - RSpec.configure do |config| - config.fixture_path = File.expand_path('../fixtures', __FILE__) - end +RSpec.configure do |config| + config.fixture_path = File.expand_path('../fixtures', __FILE__) end - -if /spork/i =~ $PROGRAM_NAME || (RSpec.respond_to?(:configuration) && RSpec.configuration.drb?) - require 'spork' - Spork.prefork { init_wagon } - Spork.each_run {} -else - init_wagon -end From cde3ee5e997c8d98d2f1c0f9a7ee1625f25f3cc6 Mon Sep 17 00:00:00 2001 From: Mathis Hofer Date: Wed, 3 Sep 2014 11:37:43 +0200 Subject: [PATCH 10/11] add editor/IDE-agnostic coding styles configuration (see http://editorconfig.org/) --- .editorconfig | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..c2cdfb8ad --- /dev/null +++ b/.editorconfig @@ -0,0 +1,21 @@ +# EditorConfig helps developers define and maintain consistent +# coding styles between different editors and IDEs +# editorconfig.org + +root = true + + +[*] + +# Change these settings to your own preference +indent_style = space +indent_size = 2 + +# We recommend you to keep these unchanged +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false From 91ea219e7ce2aa4318d8b0c8402a498603277b31 Mon Sep 17 00:00:00 2001 From: Pascal Zumkehr Date: Thu, 11 Sep 2014 09:55:16 +0200 Subject: [PATCH 11/11] centralize tarantula config in core --- lib/tasks/tarantula.rake | 2 +- test/tarantula/tarantula_test.rb | 65 ++++++-------------------------- 2 files changed, 12 insertions(+), 55 deletions(-) diff --git a/lib/tasks/tarantula.rake b/lib/tasks/tarantula.rake index 23cee62ad..19b46e230 100644 --- a/lib/tasks/tarantula.rake +++ b/lib/tasks/tarantula.rake @@ -9,5 +9,5 @@ desc "Crawl app with tarantula" task :tarantula do sh 'rm -rf ../../../tmp/tarantula' sh 'rm -rf ../hitobito/tmp/tarantula' - sh "bash -c \"RAILS_ENV=test #{ENV['APP_ROOT']}/bin/with_mysql rake db:test:prepare app:tarantula:test\"" + sh "bash -c \"RAILS_ENV=test #{ENV['APP_ROOT']}/bin/with_mysql rake app:tarantula:test\"" end \ No newline at end of file diff --git a/test/tarantula/tarantula_test.rb b/test/tarantula/tarantula_test.rb index 91c2ba39f..eaabf1ffa 100644 --- a/test/tarantula/tarantula_test.rb +++ b/test/tarantula/tarantula_test.rb @@ -7,6 +7,7 @@ require 'test_helper' require 'relevance/tarantula' +require 'tarantula/tarantula_config' class TarantulaTest < ActionDispatch::IntegrationTest # Load enough test data to ensure that there's a link to every page in your @@ -16,6 +17,7 @@ class TarantulaTest < ActionDispatch::IntegrationTest reset_fixture_path File.expand_path('../../../spec/fixtures', __FILE__) + include TarantulaConfig def test_tarantula_as_bundesleitung crawl_as(people(:bulei)) @@ -29,64 +31,19 @@ def test_tarantula_as_child crawl_as(people(:child)) end - def crawl_as(person) - person.password = 'foobar' - person.save! - post '/users/sign_in', person: { email: person.email, password: 'foobar' } - follow_redirect! + private - t = tarantula_crawler(self) - # t.handlers << Relevance::Tarantula::TidyHandler.new + def configure_urls_with_pbs(t, person) + configure_urls_without_pbs(t, person) - # some links use example.com as a domain, allow them - t.skip_uri_patterns.delete(/^http/) - t.skip_uri_patterns << /^http(?!:\/\/www\.example\.com)/ - t.skip_uri_patterns << /year=201[0-15-9]/ # only 2012 - 2014 - t.skip_uri_patterns << /year=200[0-9]/ - t.skip_uri_patterns << /year=202[0-9]/ - t.skip_uri_patterns << /users\/sign_out/ - # no modifications of user roles (and thereof its permissions) - t.skip_uri_patterns << /groups\/\d+\/roles\/(#{person.roles.collect(&:id).join("|")})$/ - # no ajax links in application market - t.skip_uri_patterns << /groups\/\d+\/events\/\d+\/application_market\/\d+\/participant$/ + # The parent entry may already have been deleted, thus producing 404s. + t.allow_404_for(/groups\/\d+\/member_counts$/) - # The type or merge_group_id tarantula generates is not from the - # given selection, thus producing 404s. - t.allow_404_for /groups$/ - t.allow_404_for /groups\/\d+\/roles$/ - t.allow_404_for /groups\/\d+\/roles\/\d+$/ - t.allow_404_for /groups\/\d+\/people$/ - t.allow_404_for /groups\/\d+\/merge$/ - t.allow_404_for /groups\/\d+\/move$/ - t.allow_404_for /groups\/\d+\/events$/ - t.allow_404_for /groups\/\d+\/events\/\d+$/ - t.allow_404_for /groups\/\d+\/events\/\d+\/roles$/ - t.allow_404_for /groups\/\d+\/events\/\d+\/roles\/\d+$/ - t.allow_404_for /groups\/\d+\/mailing_lists\/\d+\/subscriptions\/person$/ - t.allow_404_for /groups\/\d+\/mailing_lists\/\d+\/subscriptions\/event$/ - t.allow_404_for /groups\/\d+\/mailing_lists\/\d+\/subscriptions\/exclude_person$/ - t.allow_404_for /groups\/\d+\/mailing_lists\/\d+\/subscriptions\/\d+$/ - t.allow_404_for /event_kinds\/\d+$/ - t.allow_404_for /event_kinds$/ - t.allow_404_for /groups\/\d+\/member_counts$/ - # kind already deleted in another language - t.allow_404_for /qualification_kinds\/\d+$/ - # groups already deleted in another language - t.allow_404_for /it\/groups\/\d+$/ - # custom return_urls end up like that. - t.allow_404_for /^\-?\d+$/ - - # sphinx not running - t.allow_500_for /full$/ - # delete qualification is not allowed after role was removed from person - t.allow_500_for /groups\/\d+\/people\/\d+\/qualifications\/\d+$/ # delete not allowed - not completely clarified - investigate later - t.allow_500_for /groups\/\d+\/events\/\d+\/roles\/\d+$/ + t.allow_500_for(/groups\/\d+\/events\/\d+\/roles\/\d+$/) # roles with invalid created_at and deleted_at values may generate 500 :( - t.allow_500_for /groups\/\d+\/roles(\/\d+)?$/ - - - t.crawl_timeout = 20.minutes - t.crawl + t.allow_500_for(/groups\/\d+\/roles(\/\d+)?$/) end + alias_method_chain :configure_urls, :pbs + end