summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAzul <azul@leap.se>2013-01-25 11:46:22 +0100
committerAzul <azul@leap.se>2013-01-25 11:46:22 +0100
commitdac578781baf73a006cc78e29588dd1f6fdc0fd3 (patch)
treea56ecff398a87efdd4840a8fc897d6471fbdaa69
parent75442ad26f3d30519f747bc98bc83cdc76aff750 (diff)
parent9d053b6c9b61c68bf11f95bcb37631a518f1fba4 (diff)
Merge branch 'feature/webfinger' of https://github.com/leapcode/leap_web
Conflicts: users/app/views/users/edit.html.haml
-rw-r--r--app/controllers/application_controller.rb1
-rw-r--r--core/lib/extensions/couchrest.rb37
-rw-r--r--users/app/controllers/webfinger_controller.rb19
-rw-r--r--users/app/models/user.rb2
-rw-r--r--users/app/views/users/_public_key_field.html.haml1
-rw-r--r--users/app/views/users/edit.html.haml1
-rw-r--r--users/app/views/webfinger/host_meta.xml.erb11
-rw-r--r--users/app/views/webfinger/search.xml.erb7
-rw-r--r--users/config/locales/en.yml2
-rw-r--r--users/config/routes.rb2
-rw-r--r--users/lib/leap_web_users/engine.rb2
-rw-r--r--users/lib/webfinger.rb6
-rw-r--r--users/lib/webfinger/host_meta_presenter.rb30
-rw-r--r--users/lib/webfinger/user_presenter.rb35
-rw-r--r--users/test/functional/webfinger_controller_test.rb33
-rw-r--r--users/test/unit/webfinger/host_meta_presenter_test.rb24
-rw-r--r--users/test/unit/webfinger/user_presenter_test.rb49
17 files changed, 248 insertions, 14 deletions
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index be7aa1f..06b245a 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -2,4 +2,5 @@ class ApplicationController < ActionController::Base
protect_from_forgery
ActiveSupport.run_load_hooks(:application_controller, self)
+
end
diff --git a/core/lib/extensions/couchrest.rb b/core/lib/extensions/couchrest.rb
index 5938df4..ca4b608 100644
--- a/core/lib/extensions/couchrest.rb
+++ b/core/lib/extensions/couchrest.rb
@@ -1,23 +1,32 @@
-module CouchRest::Model::Designs
+module CouchRest
+ module Model::Designs
- class View
+ class View
- # so we can called Ticket.method.descending or Ticket.method.ascending
- def ascending
- self
+ # so we can called Ticket.method.descending or Ticket.method.ascending
+ def ascending
+ self
+ end
end
- end
- class DesignMapper
- def load_views(dir)
- Dir.glob("#{dir}/*.js") do |js|
- name = File.basename(js, '.js')
- file = File.open(js, 'r')
- view name.to_sym,
- :map => file.read,
- :reduce => "function(key, values, rereduce) { return sum(values); }"
+ class DesignMapper
+ def load_views(dir)
+ Dir.glob("#{dir}/*.js") do |js|
+ name = File.basename(js, '.js')
+ file = File.open(js, 'r')
+ view name.to_sym,
+ :map => file.read,
+ :reduce => "function(key, values, rereduce) { return sum(values); }"
+ end
end
end
+
end
+ class ModelRailtie
+ config.action_dispatch.rescue_responses.merge!(
+ 'CouchRest::Model::DocumentNotFound' => :not_found,
+ 'RestClient::ResourceNotFound' => :not_found
+ )
+ end
end
diff --git a/users/app/controllers/webfinger_controller.rb b/users/app/controllers/webfinger_controller.rb
new file mode 100644
index 0000000..8872802
--- /dev/null
+++ b/users/app/controllers/webfinger_controller.rb
@@ -0,0 +1,19 @@
+class WebfingerController < ApplicationController
+
+ respond_to :xml, :json
+ layout false
+
+ def host_meta
+ @host_meta = Webfinger::HostMetaPresenter.new(request)
+ respond_with @host_meta
+ end
+
+ def search
+ username = params[:q].split('@')[0].to_s.downcase
+ user = User.find_by_login(username)
+ raise RECORD_NOT_FOUND, 'User not found' unless user.present?
+ @presenter = Webfinger::UserPresenter.new(user, request)
+ respond_with @presenter
+ end
+
+end
diff --git a/users/app/models/user.rb b/users/app/models/user.rb
index 292fb13..80d49a3 100644
--- a/users/app/models/user.rb
+++ b/users/app/models/user.rb
@@ -9,6 +9,8 @@ class User < CouchRest::Model::Base
property :email_forward, String, :accessible => true
property :email_aliases, [LocalEmail]
+ property :public_key, :accessible => true
+
validates :login, :password_salt, :password_verifier,
:presence => true
diff --git a/users/app/views/users/_public_key_field.html.haml b/users/app/views/users/_public_key_field.html.haml
new file mode 100644
index 0000000..af88cbd
--- /dev/null
+++ b/users/app/views/users/_public_key_field.html.haml
@@ -0,0 +1 @@
+= f.input :public_key, :as => :text, :hint => t(:use_ascii_key), :input_html => {:class => "span5", :rows => 20} # will want to tweak this to be wide enough (maybe smaller text?)
diff --git a/users/app/views/users/edit.html.haml b/users/app/views/users/edit.html.haml
index 238c0eb..950a3b1 100644
--- a/users/app/views/users/edit.html.haml
+++ b/users/app/views/users/edit.html.haml
@@ -8,6 +8,7 @@
%legend=t :email_address
The associated email address is
= render @user.email_address, :as => :span
+ = user_form_with 'public_key_field', :legend => :public_key
= user_form_with 'email_forward_field', :legend => :forward_email
= user_form_with 'email_aliases', :legend => :add_email_alias
= render 'tabs/tabs', :tabs => [:account, :email]
diff --git a/users/app/views/webfinger/host_meta.xml.erb b/users/app/views/webfinger/host_meta.xml.erb
new file mode 100644
index 0000000..cfcbcc0
--- /dev/null
+++ b/users/app/views/webfinger/host_meta.xml.erb
@@ -0,0 +1,11 @@
+<?xml version='1.0' encoding='UTF-8'?>
+ <XRD xmlns='http://docs.oasis-open.org/ns/xri/xrd-1.0'>
+
+ <Subject><%= @host_meta.subject %></Subject>
+
+ <%- @host_meta.links.each do |rel, link| %>
+ <Link rel='<%= rel %>'
+ type='<%= link[:type] %>'
+ template='<%= link[:template] %>' />
+ <%- end %>
+ </XRD>
diff --git a/users/app/views/webfinger/search.xml.erb b/users/app/views/webfinger/search.xml.erb
new file mode 100644
index 0000000..7328552
--- /dev/null
+++ b/users/app/views/webfinger/search.xml.erb
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
+ <Subject><%= @presenter.subject %></Subject>
+ <%- @presenter.links.each do |rel, link| %>
+ <Link rel=<%=rel%> type=<%=link[:type]%> href="<%= link[:key] %>"/>
+ <% end %>
+</XRD>
diff --git a/users/config/locales/en.yml b/users/config/locales/en.yml
index 7a6ab90..493b5db 100644
--- a/users/config/locales/en.yml
+++ b/users/config/locales/en.yml
@@ -13,10 +13,12 @@ en:
set_email_address: "Set email address"
forward_email: "Forward email"
email_aliases: "Email aliases"
+ public_key: "Public Key"
add_email_alias: "Add email alias"
user_updated_successfully: "Settings have been updated successfully."
user_created_successfully: "Successfully created your account."
email_alias_destroyed_successfully: "Successfully removed the alias '%{alias}'."
+ use_ascii_key: "Use ASCII-armored PGP key"
activemodel:
models:
diff --git a/users/config/routes.rb b/users/config/routes.rb
index 0c2d8d9..4127862 100644
--- a/users/config/routes.rb
+++ b/users/config/routes.rb
@@ -18,4 +18,6 @@ Rails.application.routes.draw do
resources :email_aliases, :only => [:destroy], :id => /.*/
end
+ get "/.well-known/host-meta" => 'webfinger#host_meta'
+ get "/webfinger" => 'webfinger#search'
end
diff --git a/users/lib/leap_web_users/engine.rb b/users/lib/leap_web_users/engine.rb
index 7033576..f8ed71c 100644
--- a/users/lib/leap_web_users/engine.rb
+++ b/users/lib/leap_web_users/engine.rb
@@ -7,6 +7,8 @@ require "ruby-srp"
require "warden/session_serializer"
require "warden/strategies/secure_remote_password"
+require "webfinger"
+
module LeapWebUsers
class Engine < ::Rails::Engine
diff --git a/users/lib/webfinger.rb b/users/lib/webfinger.rb
new file mode 100644
index 0000000..dd49b41
--- /dev/null
+++ b/users/lib/webfinger.rb
@@ -0,0 +1,6 @@
+module Webfinger
+
+ autoload :HostMetaPresenter, 'webfinger/host_meta_presenter'
+ autoload :UserPresenter, 'webfinger/user_presenter'
+
+end
diff --git a/users/lib/webfinger/host_meta_presenter.rb b/users/lib/webfinger/host_meta_presenter.rb
new file mode 100644
index 0000000..84ab7a9
--- /dev/null
+++ b/users/lib/webfinger/host_meta_presenter.rb
@@ -0,0 +1,30 @@
+require 'uri'
+
+class Webfinger::HostMetaPresenter
+ def initialize(request)
+ @request = request
+ end
+
+ def to_json(options = {})
+ {
+ subject: subject,
+ links: links
+ }.to_json(options)
+ end
+
+ def subject
+ url = URI.parse(@request.url)
+ url.path = ''
+ url.to_s
+ end
+
+ def links
+ { lrdd: { type: 'application/xrd+xml', template: webfinger_template } }
+ end
+
+ protected
+
+ def webfinger_template(path = 'webfinger', query_param='q')
+ "#{subject}/#{path}?#{query_param}={uri}"
+ end
+end
diff --git a/users/lib/webfinger/user_presenter.rb b/users/lib/webfinger/user_presenter.rb
new file mode 100644
index 0000000..329f477
--- /dev/null
+++ b/users/lib/webfinger/user_presenter.rb
@@ -0,0 +1,35 @@
+class Webfinger::UserPresenter
+ include Rails.application.routes.url_helpers
+ attr_accessor :user
+
+ def initialize(user, request)
+ @user = user
+ @request = request
+ end
+
+ def to_json(options = {})
+ {
+ subject: subject,
+ links: links
+ }.to_json(options)
+ end
+
+ def subject
+ "acct:#{@user.email_address}"
+ end
+
+ def links
+ links = {}
+ links[:public_key] = { type: 'PGP', href: key } if key
+ return links
+ end
+
+ protected
+
+ def key
+ if @user.public_key.present?
+ Base64.encode64(@user.public_key.to_s)
+ end
+ end
+
+end
diff --git a/users/test/functional/webfinger_controller_test.rb b/users/test/functional/webfinger_controller_test.rb
new file mode 100644
index 0000000..6597b69
--- /dev/null
+++ b/users/test/functional/webfinger_controller_test.rb
@@ -0,0 +1,33 @@
+require 'test_helper'
+
+class WebfingerControllerTest < ActionController::TestCase
+
+ test "get host meta xml" do
+ get :host_meta, :format => :xml
+ assert_response :success
+ assert_equal "application/xml", response.content_type
+ end
+
+ test "get host meta json" do
+ get :host_meta, :format => :json
+ assert_response :success
+ assert_equal "application/json", response.content_type
+ end
+
+ test "get user webfinger xml" do
+ @user = stub_record :user, :public_key => 'my public key'
+ User.stubs(:find_by_login).with(@user.login).returns(@user)
+ get :search, :q => @user.email_address.to_s, :format => :xml
+ assert_response :success
+ assert_equal "application/xml", response.content_type
+ end
+
+ test "get user webfinger json" do
+ @user = stub_record :user, :public_key => 'my public key'
+ User.stubs(:find_by_login).with(@user.login).returns(@user)
+ get :search, :q => @user.email_address.to_s, :format => :json
+ assert_response :success
+ assert_equal "application/json", response.content_type
+ end
+
+end
diff --git a/users/test/unit/webfinger/host_meta_presenter_test.rb b/users/test/unit/webfinger/host_meta_presenter_test.rb
new file mode 100644
index 0000000..af86404
--- /dev/null
+++ b/users/test/unit/webfinger/host_meta_presenter_test.rb
@@ -0,0 +1,24 @@
+require 'test_helper'
+require 'webfinger'
+require 'json'
+
+class Webfinger::HostMetaPresenterTest < ActiveSupport::TestCase
+
+ setup do
+ @request = stub(
+ url: "https://#{APP_CONFIG[:domain]}/.well-known/host-meta"
+ )
+ @meta = Webfinger::HostMetaPresenter.new(@request)
+ end
+
+ test "creates proper json" do
+ hash = JSON.parse @meta.to_json
+ assert_equal ["subject", "links"].sort, hash.keys.sort
+ hash.each do |key, value|
+ assert_equal @meta.send(key.to_sym).to_json, value.to_json
+ end
+ end
+
+end
+
+
diff --git a/users/test/unit/webfinger/user_presenter_test.rb b/users/test/unit/webfinger/user_presenter_test.rb
new file mode 100644
index 0000000..04aeb22
--- /dev/null
+++ b/users/test/unit/webfinger/user_presenter_test.rb
@@ -0,0 +1,49 @@
+require 'test_helper'
+require 'webfinger'
+require 'json'
+
+class Webfinger::UserPresenterTest < ActiveSupport::TestCase
+
+
+ setup do
+ @user = stub(
+ username: 'testuser',
+ email_address: "testuser@#{APP_CONFIG[:domain]}"
+ )
+ @request = stub(
+ host: APP_CONFIG[:domain]
+ )
+ end
+
+ test "user without key has no links" do
+ @user.stubs :public_key => nil
+ presenter = Webfinger::UserPresenter.new(@user, @request)
+ assert_equal Hash.new, presenter.links
+ end
+
+ test "user with key has corresponding link" do
+ @user.stubs :public_key => "here's a key"
+ presenter = Webfinger::UserPresenter.new(@user, @request)
+ assert_equal [:public_key], presenter.links.keys
+ assert_equal "PGP", presenter.links[:public_key][:type]
+ assert_equal presenter.send(:key), presenter.links[:public_key][:href]
+ end
+
+ test "key is base64 encoded" do
+ @user.stubs :public_key => "here's a key"
+ presenter = Webfinger::UserPresenter.new(@user, @request)
+ assert_equal Base64.encode64(@user.public_key), presenter.send(:key)
+ end
+
+ test "creates proper json representation" do
+ @user.stubs :public_key => "here's a key"
+ presenter = Webfinger::UserPresenter.new(@user, @request)
+ hash = JSON.parse presenter.to_json
+ assert_equal ["subject", "links"].sort, hash.keys.sort
+ hash.each do |key, value|
+ assert_equal presenter.send(key.to_sym).to_json, value.to_json
+ end
+ end
+
+
+end