add Callbacks

This commit is contained in:
Benjamin Neff 2015-07-05 15:57:24 +02:00
parent d7c248b94e
commit ec5667193b
4 changed files with 63 additions and 109 deletions

View file

@ -1,12 +1,20 @@
require "diaspora_federation/logging"
require "diaspora_federation/callbacks"
require "diaspora_federation/web_finger"
# diaspora* federation library
module DiasporaFederation
extend Logging
@callbacks = Callbacks.new %i(
person_webfinger_fetch
person_hcard_fetch
)
class << self
attr_reader :callbacks
# the pod url
#
# @example with uri
@ -15,124 +23,38 @@ module DiasporaFederation
# config.server_uri = AppConfig.pod_uri
attr_accessor :server_uri
# the class to use as +Person+
#
# @example
# config.person_class = Person
#
# This class must have the following class methods:::
#
# +find_local_by_diaspora_handle+:
# This should return a +Person+, which is on this pod and the account is not closed.
#
# +find_local_by_guid+:
# This should return a +Person+, which is on this pod and the account is not closed.
#
# This class must have the following instance methods or attributes:::
#
# +diaspora_handle+: the diaspora handle
# "user@server.example"
#
# +nickname+: the username on the pod
# "user"
#
# +guid+: the guid
# "0123456789abcdef"
#
# +serialized_public_key+: the public key of the person (DER-encoded PKCS#1 key)
# "-----BEGIN PUBLIC KEY-----
# ABCDEF==
# -----END PUBLIC KEY-----"
#
# +searchable+: if the person is searchable by name
# true
#
# +alias_url+: alias url to the profile
# "https://server.example/people/0123456789abcdef"
#
# +hcard_url+: url to the hcard
# "https://server.example/hcard/users/0123456789abcdef"
#
# +seed_url+: pod url
# "https://server.example/"
#
# +profile_url+: url to the profile
# "https://server.example/u/user"
#
# +atom_url+: url to the atom rss feed
# "https://server.example/public/user.atom"
#
# +salmon_url+: private receive url for salmon
# "https://server.example/receive/users/0123456789abcdef"
#
# +photo_large_url+: large photo
# "https://server.example/uploads/l.jpg"
#
# +photo_medium_url+: medium photo
# "https://server.example/uploads/m.jpg"
#
# +photo_small_url+: small photo
# "https://server.example/uploads/s.jpg"
#
# +full_name+: full name
# "User Name"
#
# +first_name+: first name
# "User"
#
# +last_name+: last name
# "Name"
attr_accessor :person_class
def person_class=(klass)
@person_class = klass.nil? ? nil : klass.to_s
end
def person_class
const_get(@person_class)
end
# configure the federation library
#
# @example
# DiasporaFederation.configure do |config|
# config.server_uri = "http://localhost:3000/"
# config.server_uri = URI("http://localhost:3000/")
#
# config.define_callbacks do
# # callback configuration
# end
# end
def configure
yield self
end
def define_callbacks(&block)
@callbacks.instance_eval(&block)
end
# validates if the engine is configured correctly
#
# called from after_initialize
# @raise [ConfigurationError] if the configuration is incomplete or invalid
def validate_config
configuration_error "missing server_uri" unless @server_uri.respond_to? :host
validate_class(@person_class, "person_class", %i(
find_local_by_diaspora_handle find_local_by_guid
diaspora_handle nickname guid serialized_public_key searchable
alias_url hcard_url seed_url profile_url atom_url salmon_url
photo_large_url photo_medium_url photo_small_url
full_name first_name last_name
))
configuration_error "Missing server_uri" unless @server_uri.respond_to? :host
unless @callbacks.definition_complete?
configuration_error "Missing handlers for #{@callbacks.missing_handlers.join(', ')}"
end
logger.info "successfully configured the federation library"
end
private
def validate_class(klass, name, methods)
configuration_error "missing #{name}" unless klass
entity = const_get(klass)
return logger.warn "table for #{entity} doesn't exist, skip validation" unless entity.table_exists?
methods.each {|method| entity_respond_to?(entity, name, method) }
end
def entity_respond_to?(entity, name, method)
valid = entity.respond_to?(method) || entity.column_names.include?(method.to_s) || entity.method_defined?(method)
configuration_error "the configured class #{entity} for #{name} doesn't respond to #{method}" unless valid
end
def configuration_error(message)
logger.fatal("diaspora federation configuration error: #{message}")
raise ConfigurationError, message

View file

@ -0,0 +1,29 @@
module DiasporaFederation
class Callbacks
def initialize(events)
@events = events
@handlers = {}
end
def on(event, &callback)
raise ArgumentError, "Undefined event #{event}" unless @events.include? event
raise ArgumentError, "Already defined event #{event}" if @handlers.has_key? event
@handlers[event] = callback
end
def trigger(event, *args)
raise ArgumentError, "Undefined event #{event}" unless @events.include? event
@handlers[event].call(*args)
end
def definition_complete?
missing_handlers.empty?
end
def missing_handlers
@events - @handlers.keys
end
end
end

View file

@ -2,22 +2,20 @@ module DiasporaFederation
describe DiasporaFederation do
context "validate_config" do
it "should validate the config" do
expect(DiasporaFederation).to receive(:validate_class)
expect(DiasporaFederation.callbacks).to receive(:definition_complete?).and_return(true)
DiasporaFederation.validate_config
end
it "should fails if the server_uri is missing" do
temp = DiasporaFederation.server_uri
DiasporaFederation.server_uri = nil
expect { DiasporaFederation.validate_config }.to raise_error ConfigurationError
expect { DiasporaFederation.validate_config }.to raise_error ConfigurationError, "Missing server_uri"
DiasporaFederation.server_uri = temp
end
it "should fails if the person_class is missing" do
temp = DiasporaFederation.person_class
DiasporaFederation.person_class = nil
expect { DiasporaFederation.validate_config }.to raise_error ConfigurationError
DiasporaFederation.person_class = temp
it "should validate the config" do
expect(DiasporaFederation.callbacks).to receive(:definition_complete?).and_return(false)
expect { DiasporaFederation.validate_config }.to raise_error ConfigurationError, "Missing handlers for "
end
end
end

View file

@ -3,6 +3,11 @@ DiasporaFederation.configure do |config|
# the pod url
config.server_uri = URI("http://localhost:3000/")
# the class to be used for a person
config.person_class = Person
config.define_callbacks do
on :person_webfinger_fetch do |handle|
end
on :person_hcard_fetch do |guid|
end
end
end