diff --git a/lib/diaspora_federation/entities.rb b/lib/diaspora_federation/entities.rb index e2748cc..7ab98e9 100644 --- a/lib/diaspora_federation/entities.rb +++ b/lib/diaspora_federation/entities.rb @@ -14,3 +14,4 @@ require "diaspora_federation/entities/location" require "diaspora_federation/entities/photo" require "diaspora_federation/entities/status_message" require "diaspora_federation/entities/request" +require "diaspora_federation/entities/participation" diff --git a/lib/diaspora_federation/entities/participation.rb b/lib/diaspora_federation/entities/participation.rb new file mode 100644 index 0000000..a7f99ce --- /dev/null +++ b/lib/diaspora_federation/entities/participation.rb @@ -0,0 +1,12 @@ +module DiasporaFederation + module Entities + class Participation < Entity + property :guid + property :target_type + property :parent_guid + property :parent_author_signature + property :author_signature + property :diaspora_id, xml_name: :diaspora_handle + end + end +end diff --git a/lib/diaspora_federation/validators.rb b/lib/diaspora_federation/validators.rb index a84f349..5f4c7f3 100644 --- a/lib/diaspora_federation/validators.rb +++ b/lib/diaspora_federation/validators.rb @@ -3,6 +3,7 @@ require "validation/rule/regular_expression" require "validation/rule/length" require "validation/rule/not_empty" require "validation/rule/uri" +require "validation/rule/numeric" # +valid+ gem namespace module Validation @@ -37,3 +38,7 @@ require "diaspora_federation/validators/person_validator" require "diaspora_federation/validators/profile_validator" require "diaspora_federation/validators/web_finger_validator" require "diaspora_federation/validators/request_validator" +require "diaspora_federation/validators/photo_validator" +require "diaspora_federation/validators/location_validator" +require "diaspora_federation/validators/status_message_validator" +require "diaspora_federation/validators/participation_validator" diff --git a/lib/diaspora_federation/validators/location_validator.rb b/lib/diaspora_federation/validators/location_validator.rb new file mode 100644 index 0000000..4a2e91d --- /dev/null +++ b/lib/diaspora_federation/validators/location_validator.rb @@ -0,0 +1,10 @@ +module DiasporaFederation + module Validators + class LocationValidator < Validation::Validator + include Validation + + rule :lat, :not_empty + rule :lng, :not_empty + end + end +end diff --git a/lib/diaspora_federation/validators/participation_validator.rb b/lib/diaspora_federation/validators/participation_validator.rb new file mode 100644 index 0000000..e51739b --- /dev/null +++ b/lib/diaspora_federation/validators/participation_validator.rb @@ -0,0 +1,19 @@ +module DiasporaFederation + module Validators + class ParticipationValidator < Validation::Validator + include Validation + + rule :guid, :guid + + rule :target_type, :not_empty + + rule :parent_guid, :guid + + rule :parent_author_signature, :not_empty + + rule :author_signature, :not_empty + + rule :diaspora_id, %i(not_empty diaspora_id) + end + end +end diff --git a/lib/diaspora_federation/validators/photo_validator.rb b/lib/diaspora_federation/validators/photo_validator.rb new file mode 100644 index 0000000..ffc0680 --- /dev/null +++ b/lib/diaspora_federation/validators/photo_validator.rb @@ -0,0 +1,23 @@ +module DiasporaFederation + module Validators + class PhotoValidator < Validation::Validator + include Validation + + rule :guid, :guid + + rule :diaspora_id, %i(not_empty diaspora_id) + + rule :public, :boolean + + rule :remote_photo_path, :not_empty + + rule :remote_photo_name, :not_empty + + rule :status_message_guid, :guid + + rule :height, :numeric + + rule :width, :numeric + end + end +end diff --git a/lib/diaspora_federation/validators/request_validator.rb b/lib/diaspora_federation/validators/request_validator.rb index 2bd7ec3..fecb7ea 100644 --- a/lib/diaspora_federation/validators/request_validator.rb +++ b/lib/diaspora_federation/validators/request_validator.rb @@ -3,8 +3,8 @@ module DiasporaFederation class RequestValidator < Validation::Validator include Validation - rule :sender_id, %i(not_nil diaspora_id) - rule :recipient_id, %i(not_nil diaspora_id) + rule :sender_id, %i(not_empty diaspora_id) + rule :recipient_id, %i(not_empty diaspora_id) end end end diff --git a/lib/diaspora_federation/validators/status_message_validator.rb b/lib/diaspora_federation/validators/status_message_validator.rb new file mode 100644 index 0000000..04dbb36 --- /dev/null +++ b/lib/diaspora_federation/validators/status_message_validator.rb @@ -0,0 +1,13 @@ +module DiasporaFederation + module Validators + class StatusMessageValidator < Validation::Validator + include Validation + + rule :guid, :guid + + rule :diaspora_id, %i(not_empty diaspora_id) + + rule :public, :boolean + end + end +end diff --git a/spec/factories.rb b/spec/factories.rb index 25fce9b..d68b25d 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -8,6 +8,11 @@ FactoryGirl.define do sequence(:guid) { UUID.generate :compact } sequence(:diaspora_id) {|n| "person-#{n}-#{r_str}@localhost:3000" } sequence(:public_key) { OpenSSL::PKey::RSA.generate(1024).public_key.export } + sequence(:signature) do |i| + abc = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + ltr = abc[i % abc.length] + "#{ltr * 6}==" + end factory :person do diaspora_id @@ -83,8 +88,30 @@ FactoryGirl.define do remote_photo_path "https://diaspora.example.tld/uploads/images/" remote_photo_name "f2a41e9d2db4d9a199c8.jpg" text "what you see here..." - status_message_guid { guid } + status_message_guid { generate(:guid) } height 480 width 800 end + + factory :participation_entity, class: DiasporaFederation::Entities::Participation do + guid + target_type "StatusMessage" + parent_guid { generate(:guid) } + diaspora_id + parent_author_signature { generate(:signature) } + author_signature { generate(:signature) } + end + + factory :status_message_entity, class: DiasporaFederation::Entities::StatusMessage do + raw_message "i am a very interesting status update" + guid + diaspora_id + public(true) + created_at { Time.zone.now } + end + + factory :request_entity, class: DiasporaFederation::Entities::Request do + sender_id { generate(:diaspora_id) } + recipient_id { generate(:diaspora_id) } + end end diff --git a/spec/lib/diaspora_federation/entities/participation_spec.rb b/spec/lib/diaspora_federation/entities/participation_spec.rb new file mode 100644 index 0000000..5653c41 --- /dev/null +++ b/spec/lib/diaspora_federation/entities/participation_spec.rb @@ -0,0 +1,29 @@ +module DiasporaFederation + describe Entities::Participation do + let(:data) { + {guid: "0123456789abcdef", + target_type: "Post", + parent_guid: "fedcba9876543210", + parent_author_signature: "BBBBBB==", + author_signature: "AAAAAA==", + diaspora_id: "luke@diaspora.example.tld"} + } + + let(:xml) { + <<-XML + + #{data[:guid]} + #{data[:target_type]} + #{data[:parent_guid]} + #{data[:parent_author_signature]} + #{data[:author_signature]} + #{data[:diaspora_id]} + +XML + } + + it_behaves_like "an Entity subclass" + + it_behaves_like "an XML Entity" + end +end diff --git a/spec/lib/diaspora_federation/validators/location_validator_spec.rb b/spec/lib/diaspora_federation/validators/location_validator_spec.rb new file mode 100644 index 0000000..0577d63 --- /dev/null +++ b/spec/lib/diaspora_federation/validators/location_validator_spec.rb @@ -0,0 +1,19 @@ +module DiasporaFederation + describe Validators::LocationValidator do + let(:entity) { :location_entity } + it_behaves_like "a common validator" + + context "#lat and #lng" do + %i(lat lng).each do |prop| + it "must not be empty" do + entity = OpenStruct.new(FactoryGirl.attributes_for(:location_entity)) + entity.public_send("#{prop}=", "") + + validator = Validators::LocationValidator.new(entity) + expect(validator).not_to be_valid + expect(validator.errors).to include(prop) + end + end + end + end +end diff --git a/spec/lib/diaspora_federation/validators/participation_validator_spec.rb b/spec/lib/diaspora_federation/validators/participation_validator_spec.rb new file mode 100644 index 0000000..9bb8bff --- /dev/null +++ b/spec/lib/diaspora_federation/validators/participation_validator_spec.rb @@ -0,0 +1,42 @@ +module DiasporaFederation + describe Validators::ParticipationValidator do + let(:entity) { :participation_entity } + + it_behaves_like "a common validator" + + it_behaves_like "a diaspora id validator" do + let(:property) { :diaspora_id } + let(:mandatory) { true } + end + + context "#target_type" do + it "must not be empty" do + entity = OpenStruct.new(FactoryGirl.attributes_for(:participation_entity, target_type: "")) + validator = Validators::ParticipationValidator.new(entity) + expect(validator).not_to be_valid + expect(validator.errors).to include(:target_type) + end + end + + context "#guid, #parent_guid" do + %i(guid parent_guid).each do |prop| + it_behaves_like "a guid validator" do + let(:property) { prop } + end + end + end + + context "#author_signature and #parent_author_signature" do + %i(author_signature parent_author_signature).each do |prop| + it "must not be empty" do + p = OpenStruct.new(FactoryGirl.attributes_for(:participation_entity)) + p.public_send("#{prop}=", "") + + v = Validators::ParticipationValidator.new(p) + expect(v).not_to be_valid + expect(v.errors).to include(prop) + end + end + end + end +end diff --git a/spec/lib/diaspora_federation/validators/person_validator_spec.rb b/spec/lib/diaspora_federation/validators/person_validator_spec.rb index 753cd9c..b973472 100644 --- a/spec/lib/diaspora_federation/validators/person_validator_spec.rb +++ b/spec/lib/diaspora_federation/validators/person_validator_spec.rb @@ -2,13 +2,7 @@ module DiasporaFederation describe Validators::PersonValidator do let(:entity) { :person_entity } - it "validates a well-formed instance" do - instance = OpenStruct.new(FactoryGirl.attributes_for(:person_entity)) - validator = Validators::PersonValidator.new(instance) - - expect(validator).to be_valid - expect(validator.errors).to be_empty - end + it_behaves_like "a common validator" it_behaves_like "a diaspora id validator" do let(:property) { :diaspora_id } diff --git a/spec/lib/diaspora_federation/validators/photo_validator_spec.rb b/spec/lib/diaspora_federation/validators/photo_validator_spec.rb new file mode 100644 index 0000000..ff1c5e1 --- /dev/null +++ b/spec/lib/diaspora_federation/validators/photo_validator_spec.rb @@ -0,0 +1,63 @@ +module DiasporaFederation + describe Validators::PhotoValidator do + let(:entity) { :photo_entity } + + it_behaves_like "a common validator" + + it_behaves_like "a diaspora id validator" do + let(:property) { :diaspora_id } + let(:mandatory) { true } + end + + context "#guid, #status_message_guid" do + %i(guid status_message_guid).each do |prop| + it_behaves_like "a guid validator" do + let(:property) { prop } + end + end + end + + it_behaves_like "a boolean validator" do + let(:property) { :public } + end + + context "#remote_photo_path, #remote_photo_name" do + %i(remote_photo_name remote_photo_path).each do |prop| + it "must not be empty" do + p = OpenStruct.new(FactoryGirl.attributes_for(:photo_entity)) + p.public_send("#{prop}=", "") + + v = Validators::PhotoValidator.new(p) + expect(v).not_to be_valid + expect(v.errors).to include(prop) + end + end + end + + context "#height, #width" do + %i(height width).each do |prop| + it "validates an integer" do + [123, "123"].each do |val| + p = OpenStruct.new(FactoryGirl.attributes_for(:photo_entity)) + p.public_send("#{prop}=", val) + + v = Validators::PhotoValidator.new(p) + expect(v).to be_valid + expect(v.errors).to be_empty + end + end + + it "fails for non numeric types" do + [true, :num, "asdf"].each do |val| + p = OpenStruct.new(FactoryGirl.attributes_for(:photo_entity)) + p.public_send("#{prop}=", val) + + v = Validators::PhotoValidator.new(p) + expect(v).not_to be_valid + expect(v.errors).to include(prop) + end + end + end + end + end +end diff --git a/spec/lib/diaspora_federation/validators/request_validator_spec.rb b/spec/lib/diaspora_federation/validators/request_validator_spec.rb new file mode 100644 index 0000000..79a34c4 --- /dev/null +++ b/spec/lib/diaspora_federation/validators/request_validator_spec.rb @@ -0,0 +1,16 @@ +module DiasporaFederation + describe Validators::RequestValidator do + let(:entity) { :request_entity } + + it_behaves_like "a common validator" + + context "#sender_id, #recipient_id" do + %i(sender_id recipient_id).each do |prop| + it_behaves_like "a diaspora id validator" do + let(:property) { prop } + let(:mandatory) { true } + end + end + end + end +end diff --git a/spec/lib/diaspora_federation/validators/status_message_validator_spec.rb b/spec/lib/diaspora_federation/validators/status_message_validator_spec.rb new file mode 100644 index 0000000..1d33a1c --- /dev/null +++ b/spec/lib/diaspora_federation/validators/status_message_validator_spec.rb @@ -0,0 +1,20 @@ +module DiasporaFederation + describe Validators::StatusMessageValidator do + let(:entity) { :status_message_entity } + + it_behaves_like "a common validator" + + it_behaves_like "a diaspora id validator" do + let(:property) { :diaspora_id } + let(:mandatory) { true } + end + + it_behaves_like "a guid validator" do + let(:property) { :guid } + end + + it_behaves_like "a boolean validator" do + let(:property) { :public } + end + end +end diff --git a/spec/support/shared_validator_specs.rb b/spec/support/shared_validator_specs.rb index 9b96d30..e3dd4f2 100644 --- a/spec/support/shared_validator_specs.rb +++ b/spec/support/shared_validator_specs.rb @@ -4,12 +4,24 @@ def entity_stub(entity, property, val) instance end +def entity_stub_data(entity, data={}) + OpenStruct.new(FactoryGirl.attributes_for(entity).merge(data)) +end + ALPHANUMERIC_RANGE = [*"0".."9", *"A".."Z", *"a".."z"] def alphanumeric_string(length) Array.new(length) { ALPHANUMERIC_RANGE.sample }.join end +shared_examples "a common validator" do + it "validates a well-formed instance" do + validator = described_class.new(entity_stub_data(entity)) + expect(validator).to be_valid + expect(validator.errors).to be_empty + end +end + shared_examples "a diaspora id validator" do it "must not be nil or empty if mandatory" do [nil, ""].each do |val|