diff options
Diffstat (limited to 'users')
113 files changed, 0 insertions, 3669 deletions
diff --git a/users/Gemfile b/users/Gemfile deleted file mode 100644 index 4101ead..0000000 --- a/users/Gemfile +++ /dev/null @@ -1,15 +0,0 @@ -source "https://rubygems.org" - -eval(File.read(File.dirname(__FILE__) + '/../common_dependencies.rb')) -eval(File.read(File.dirname(__FILE__) + '/../ui_dependencies.rb')) - -# We require leap_web_core from here so we can use the path option. -gem "leap_web_core", :path => '../core' - -# Declare your gem's dependencies in leap_web_users.gemspec. -# Bundler will treat runtime dependencies like base dependencies, and -# development dependencies will be added by default to the :development group. -gemspec - -# To use debugger -# gem 'ruby-debug' diff --git a/users/Rakefile b/users/Rakefile deleted file mode 100644 index 38da5fc..0000000 --- a/users/Rakefile +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env rake - -require 'rake/packagetask' -require 'rubygems/package_task' - -begin - require 'bundler/setup' -rescue LoadError - puts 'You must `gem install bundler` and `bundle install` to run rake tasks' -end -begin - require 'rdoc/task' -rescue LoadError - require 'rdoc/rdoc' - require 'rake/rdoctask' - RDoc::Task = Rake::RDocTask -end - -RDoc::Task.new(:rdoc) do |rdoc| - rdoc.rdoc_dir = 'rdoc' - rdoc.title = 'LeapWebUsers' - rdoc.options << '--line-numbers' - rdoc.rdoc_files.include('README.rdoc') - rdoc.rdoc_files.include('lib/**/*.rb') -end - -spec = eval(File.read('leap_web_users.gemspec')) -Gem::PackageTask.new(spec) do |p| - p.gem_spec = spec -end - -Bundler::GemHelper.install_tasks - -require 'rake/testtask' - -Rake::TestTask.new(:test) do |t| - t.libs << 'lib' - t.libs << 'test' - t.pattern = 'test/**/*_test.rb' - t.verbose = false -end - - -task :default => :test diff --git a/users/app/assets/images/leap_web_users/.gitkeep b/users/app/assets/images/leap_web_users/.gitkeep deleted file mode 100644 index e69de29..0000000 --- a/users/app/assets/images/leap_web_users/.gitkeep +++ /dev/null diff --git a/users/app/assets/javascripts/leap_web_users/.gitkeep b/users/app/assets/javascripts/leap_web_users/.gitkeep deleted file mode 100644 index e69de29..0000000 --- a/users/app/assets/javascripts/leap_web_users/.gitkeep +++ /dev/null diff --git a/users/app/assets/javascripts/srp b/users/app/assets/javascripts/srp deleted file mode 160000 -Subproject 8f33d32d40b1e21ae7fb9a92c78a275422af421 diff --git a/users/app/assets/javascripts/users.js b/users/app/assets/javascripts/users.js deleted file mode 100644 index 8486756..0000000 --- a/users/app/assets/javascripts/users.js +++ /dev/null @@ -1,132 +0,0 @@ -(function() { - // - // LOCAL FUNCTIONS - // - - var poll_users, - prevent_default, - form_failed, - form_passed, - clear_errors, - update_user; - - prevent_default = function(event) { - return event.preventDefault(); - }; - - poll_users = function(query, process) { - return $.get("/1/users.json", { - query: query - }).done(process); - }; - - clear_errors = function() { - return $('#messages').empty(); - }; - - update_user = function(submitEvent) { - var form = submitEvent.target; - var token = form.dataset.token; - var url = form.action; - var req = $.ajax({ - url: url, - type: 'PUT', - headers: { Authorization: 'Token token="' + token + '"' }, - data: $(form).serialize() - }); - req.done( function() { - $(form).find('input[type="submit"]').button('reset'); - }); - }; - - markAsSubmitted = function(submitEvent) { - var form = submitEvent.target; - $(form).addClass('submitted') - // bootstrap loading state: - $(form).find('input[type="submit"]').button('loading'); - }; - - resetButtons = function(submitEvent) { - var form = $('form.submitted') - // bootstrap loading state: - $(form).find('input[type="submit"]').button('reset'); - $(form).removeClass('submitted') - }; - - // - // PUBLIC FUNCTIONS - // - - srp.session = new srp.Session(); - - srp.signedUp = function() { - return srp.login(); - }; - - srp.loggedIn = function() { - return window.location = '/'; - }; - - srp.updated = function() { - return window.location = '/users/' + srp.session.id(); - }; - - // - // if a json request returns an error, this function gets called and - // decorates the appropriate fields with the error messages. - // - srp.error = function(message) { - clear_errors(); - var errors = extractErrors(message); - displayErrors(errors); - resetButtons(); - } - - function extractErrors(message) { - if ($.isPlainObject(message) && message.errors) { - return message.errors; - } else { - return { - base: (message.error || JSON.stringify(message)) - }; - } - } - - function displayErrors(errors) { - for (var field in errors) { - var error = errors[field]; - if (field === 'base') { - alert_message(error); - } else { - displayFieldError(field, error); - } - } - } - - function displayFieldError(field, error) { - var element = $('form input[name$="[' + field + ']"]'); - if (element) { - element.trigger('element:validate:fail.ClientSideValidations', error).data('valid', false); - } - }; - - // - // INIT - // - - $(document).ready(function() { - $('form').submit(markAsSubmitted); - $('#new_user').submit(prevent_default); - $('#new_user').submit(srp.signup); - $('#new_session').submit(prevent_default); - $('#new_session').submit(srp.login); - $('#update_login_and_password').submit(prevent_default); - $('#update_login_and_password').submit(srp.update); - $('#update_pgp_key').submit(prevent_default); - $('#update_pgp_key').submit(update_user); - return $('#user-typeahead').typeahead({ - source: poll_users - }); - }); - -}).call(this); diff --git a/users/app/assets/stylesheets/leap_web_users/.gitkeep b/users/app/assets/stylesheets/leap_web_users/.gitkeep deleted file mode 100644 index e69de29..0000000 --- a/users/app/assets/stylesheets/leap_web_users/.gitkeep +++ /dev/null diff --git a/users/app/controllers/.gitkeep b/users/app/controllers/.gitkeep deleted file mode 100644 index e69de29..0000000 --- a/users/app/controllers/.gitkeep +++ /dev/null diff --git a/users/app/controllers/account_settings_controller.rb b/users/app/controllers/account_settings_controller.rb deleted file mode 100644 index e69de29..0000000 --- a/users/app/controllers/account_settings_controller.rb +++ /dev/null diff --git a/users/app/controllers/controller_extension/authentication.rb b/users/app/controllers/controller_extension/authentication.rb deleted file mode 100644 index d831fbe..0000000 --- a/users/app/controllers/controller_extension/authentication.rb +++ /dev/null @@ -1,68 +0,0 @@ -module ControllerExtension::Authentication - extend ActiveSupport::Concern - - private - - included do - helper_method :current_user, :logged_in?, :admin? - end - - def current_user - @current_user ||= token_authenticate || warden.user - end - - def logged_in? - !!current_user - end - - def authorize - access_denied unless logged_in? - end - - def access_denied - respond_to do |format| - format.html do - if logged_in? - redirect_to home_url, :alert => t(:not_authorized) - else - redirect_to login_url, :alert => t(:not_authorized_login) - end - end - format.json do - render :json => {'error' => t(:not_authorized)}, status: :unprocessable_entity - end - end - end - - def admin? - current_user && current_user.is_admin? - end - - def authorize_admin - access_denied unless admin? - end - - def authentication_errors - return unless attempted_login? - errors = get_warden_errors - errors.inject({}) do |translated,err| - translated[err.first] = I18n.t(err.last) - translated - end - end - - def get_warden_errors - if strategy = warden.winning_strategy - message = strategy.message - # in case we get back the default message to fail! - message.respond_to?(:inject) ? message : { base: message } - else - { login: :all_strategies_failed } - end - end - - def attempted_login? - request.env['warden.options'] && - request.env['warden.options'][:attempted_path] - end -end diff --git a/users/app/controllers/controller_extension/token_authentication.rb b/users/app/controllers/controller_extension/token_authentication.rb deleted file mode 100644 index 530294a..0000000 --- a/users/app/controllers/controller_extension/token_authentication.rb +++ /dev/null @@ -1,23 +0,0 @@ -module ControllerExtension::TokenAuthentication - extend ActiveSupport::Concern - - def token_authenticate - authenticate_with_http_token do |token_id, options| - @token = Token.find(token_id) - end - @token.authenticate if @token - end - - def logout - super - clear_token - end - - def clear_token - authenticate_with_http_token do |token_id, options| - @token = Token.find(token_id) - @token.destroy if @token - end - end -end - diff --git a/users/app/controllers/keys_controller.rb b/users/app/controllers/keys_controller.rb deleted file mode 100644 index fb28901..0000000 --- a/users/app/controllers/keys_controller.rb +++ /dev/null @@ -1,18 +0,0 @@ -class KeysController < ApplicationController - - # - # Render the user's key as plain text, without a layout. - # - # We will show blank page if user doesn't have key (which shouldn't generally occur) - # and a 404 error if user doesn't exist - # - def show - user = User.find_by_login(params[:login]) - if user - render text: user.public_key, content_type: 'text/text' - else - raise ActionController::RoutingError.new('Not Found') - end - end - -end diff --git a/users/app/controllers/sessions_controller.rb b/users/app/controllers/sessions_controller.rb deleted file mode 100644 index 0195f30..0000000 --- a/users/app/controllers/sessions_controller.rb +++ /dev/null @@ -1,27 +0,0 @@ -class SessionsController < ApplicationController - - def new - redirect_to home_url if logged_in? - @session = Session.new - if authentication_errors - @errors = authentication_errors - render :status => 422 - end - end - - def destroy - logout - redirect_to home_url - end - - # - # this is a bad hack, but user_url(user) is not available - # also, this doesn't work because the redirect happens as a PUT. no idea why. - # - #Warden::Manager.after_authentication do |user, auth, opts| - # response = Rack::Response.new - # response.redirect "/users/#{user.id}" - # throw :warden, response.finish - #end - -end diff --git a/users/app/controllers/users_base_controller.rb b/users/app/controllers/users_base_controller.rb deleted file mode 100644 index 9becf0d..0000000 --- a/users/app/controllers/users_base_controller.rb +++ /dev/null @@ -1,18 +0,0 @@ -# -# common base class for all user related controllers -# - -class UsersBaseController < ApplicationController - - protected - - def fetch_user - @user = User.find(params[:user_id] || params[:id]) - if !@user && admin? - redirect_to users_url, :alert => t(:no_such_thing, :thing => 'user') - elsif !admin? && @user != current_user - access_denied - end - end - -end diff --git a/users/app/controllers/users_controller.rb b/users/app/controllers/users_controller.rb deleted file mode 100644 index a5461cd..0000000 --- a/users/app/controllers/users_controller.rb +++ /dev/null @@ -1,68 +0,0 @@ -# -# This is an HTML-only controller. For the JSON-only controller, see v1/users_controller.rb -# - -class UsersController < UsersBaseController - - before_filter :authorize, :only => [:show, :edit, :update, :destroy] - before_filter :fetch_user, :only => [:show, :edit, :update, :destroy, :deactivate, :enable] - before_filter :authorize_admin, :only => [:index, :deactivate, :enable] - - respond_to :html - - def index - if params[:query] - if @user = User.find_by_login(params[:query]) - redirect_to @user - return - else - @users = User.by_login.startkey(params[:query]).endkey(params[:query].succ) - end - else - @users = User.by_created_at.descending - end - @users = @users.limit(100) - end - - def new - @user = User.new - end - - def show - end - - def edit - end - - ## added so updating service level works, but not sure we will actually want this. also not sure that this is place to prevent user from updating own effective service level, but here as placeholder: - def update - @user.update_attributes(params[:user]) unless (!admin? and params[:user][:effective_service_level]) - respond_with @user - end - - def deactivate - @user.enabled = false - @user.save - respond_with @user - end - - def enable - @user.enabled = true - @user.save - respond_with @user - end - - def destroy - @user.account.destroy - flash[:notice] = I18n.t(:account_destroyed) - # admins can destroy other users - if @user != current_user - redirect_to users_url - else - # let's remove the invalid session - logout - redirect_to bye_url - end - end - -end diff --git a/users/app/controllers/v1/sessions_controller.rb b/users/app/controllers/v1/sessions_controller.rb deleted file mode 100644 index eb6c322..0000000 --- a/users/app/controllers/v1/sessions_controller.rb +++ /dev/null @@ -1,44 +0,0 @@ -module V1 - class SessionsController < ApplicationController - - skip_before_filter :verify_authenticity_token - - def new - @session = Session.new - if authentication_errors - @errors = authentication_errors - render :status => 422 - end - end - - def create - logout if logged_in? - if params['A'] - authenticate! - else - @user = User.find_by_login(params['login']) - render :json => {salt: @user.salt} - end - end - - def update - authenticate! - @token = Token.create(:user_id => current_user.id) - session[:token] = @token.id - render :json => login_response - end - - def destroy - logout - head :no_content - end - - protected - - def login_response - handshake = session.delete(:handshake) || {} - handshake.to_hash.merge(:id => current_user.id, :token => @token.id) - end - - end -end diff --git a/users/app/controllers/v1/users_controller.rb b/users/app/controllers/v1/users_controller.rb deleted file mode 100644 index 0903888..0000000 --- a/users/app/controllers/v1/users_controller.rb +++ /dev/null @@ -1,32 +0,0 @@ -module V1 - class UsersController < UsersBaseController - - skip_before_filter :verify_authenticity_token - before_filter :fetch_user, :only => [:update] - before_filter :authorize, :only => [:update] - before_filter :authorize_admin, :only => [:index] - - respond_to :json - - # used for autocomplete for admins in the web ui - def index - if params[:query] - @users = User.by_login.startkey(params[:query]).endkey(params[:query].succ) - respond_with @users.map(&:login).sort - else - render :json => {'error' => 'query required', 'status' => :unprocessable_entity} - end - end - - def create - @user = Account.create(params[:user]) - respond_with @user # return ID instead? - end - - def update - @user.account.update params[:user] - respond_with @user - end - - end -end diff --git a/users/app/controllers/webfinger_controller.rb b/users/app/controllers/webfinger_controller.rb deleted file mode 100644 index 8872802..0000000 --- a/users/app/controllers/webfinger_controller.rb +++ /dev/null @@ -1,19 +0,0 @@ -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/helpers/.gitkeep b/users/app/helpers/.gitkeep deleted file mode 100644 index e69de29..0000000 --- a/users/app/helpers/.gitkeep +++ /dev/null diff --git a/users/app/helpers/email_aliases_helper.rb b/users/app/helpers/email_aliases_helper.rb deleted file mode 100644 index b56b068..0000000 --- a/users/app/helpers/email_aliases_helper.rb +++ /dev/null @@ -1,11 +0,0 @@ -module EmailAliasesHelper - - def email_alias_form(options = {}) - simple_form_for [@user, EmailAlias.new()], - :html => {:class => "form-horizontal email-alias form"}, - :validate => true do |f| - yield f - end - end - -end diff --git a/users/app/helpers/sessions_helper.rb b/users/app/helpers/sessions_helper.rb deleted file mode 100644 index 309f8b2..0000000 --- a/users/app/helpers/sessions_helper.rb +++ /dev/null @@ -1,2 +0,0 @@ -module SessionsHelper -end diff --git a/users/app/helpers/users_helper.rb b/users/app/helpers/users_helper.rb deleted file mode 100644 index f56faab..0000000 --- a/users/app/helpers/users_helper.rb +++ /dev/null @@ -1,14 +0,0 @@ -module UsersHelper - - def user_form_class(*classes) - (classes + ['user', 'form', (@user.new_record? ? 'new' : 'edit')]).compact.join(' ') - end - - def wrapped(item, options = {}) - options[:as] ||= :div - content_tag options[:as], :class => dom_class(item), :id => dom_id(item) do - yield - end - end - -end diff --git a/users/app/mailers/.gitkeep b/users/app/mailers/.gitkeep deleted file mode 100644 index e69de29..0000000 --- a/users/app/mailers/.gitkeep +++ /dev/null diff --git a/users/app/models/.gitkeep b/users/app/models/.gitkeep deleted file mode 100644 index e69de29..0000000 --- a/users/app/models/.gitkeep +++ /dev/null diff --git a/users/app/models/account.rb b/users/app/models/account.rb deleted file mode 100644 index cf998e4..0000000 --- a/users/app/models/account.rb +++ /dev/null @@ -1,68 +0,0 @@ -# -# The Account model takes care of the livecycle of a user. -# It composes a User record and it's identity records. -# It also allows for other engines to hook into the livecycle by -# monkeypatching the create, update and destroy methods. -# There's an ActiveSupport load_hook at the end of this file to -# make this more easy. -# -class Account - - attr_reader :user - - def initialize(user = nil) - @user = user - end - - # Returns the user record so it can be used in views. - def self.create(attrs) - @user = User.create(attrs).tap do |user| - Identity.create_for user - end - end - - def update(attrs) - if attrs[:password_verifier].present? - update_login(attrs[:login]) - @user.update_attributes attrs.slice(:password_verifier, :password_salt) - end - # TODO: move into identity controller - key = update_pgp_key(attrs[:public_key]) - @user.errors.set :public_key, key.errors.full_messages - @user.save && save_identities - @user.refresh_identity - end - - def destroy - return unless @user - Identity.disable_all_for(@user) - @user.destroy - end - - protected - - def update_login(login) - return unless login.present? - @old_identity = Identity.for(@user) - @user.login = login - @new_identity = Identity.for(@user) # based on the new login - @old_identity.destination = @user.email_address # alias old -> new - end - - def update_pgp_key(key) - PgpKey.new(key).tap do |key| - if key.present? && key.valid? - @new_identity ||= Identity.for(@user) - @new_identity.set_key(:pgp, key) - end - end - end - - def save_identities - @new_identity.try(:save) && @old_identity.try(:save) - end - - # You can hook into the account lifecycle from different engines using - # ActiveSupport.on_load(:account) do ... - ActiveSupport.run_load_hooks(:account, self) -end diff --git a/users/app/models/email.rb b/users/app/models/email.rb deleted file mode 100644 index a9a503f..0000000 --- a/users/app/models/email.rb +++ /dev/null @@ -1,26 +0,0 @@ -class Email < String - include ActiveModel::Validations - - validates :email, - :format => { - :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/, #local part of email is case-sensitive, so allow uppercase letter. - :message => "needs to be a valid email address" - } - - def to_partial_path - "emails/email" - end - - def to_param - to_s - end - - def email - self - end - - def handle - self.split('@').first - end - -end diff --git a/users/app/models/identity.rb b/users/app/models/identity.rb deleted file mode 100644 index 9b97b51..0000000 --- a/users/app/models/identity.rb +++ /dev/null @@ -1,136 +0,0 @@ -class Identity < CouchRest::Model::Base - include LoginFormatValidation - - use_database :identities - - belongs_to :user - - property :address, LocalEmail - property :destination, Email - property :keys, HashWithIndifferentAccess - - validate :unique_forward - validate :alias_available - validate :address_local_email - validate :destination_email - - design do - view :by_user_id - view :by_address_and_destination - view :by_address - view :pgp_key_by_email, - map: <<-EOJS - function(doc) { - if (doc.type != 'Identity') { - return; - } - if (typeof doc.keys === "object") { - emit(doc.address, doc.keys["pgp"]); - } - } - EOJS - view :disabled, - map: <<-EOJS - function(doc) { - if (doc.type != 'Identity') { - return; - } - if (typeof doc.user_id === "undefined") { - emit(doc._id, 1); - } - } - EOJS - - end - - def self.for(user, attributes = {}) - find_for(user, attributes) || build_for(user, attributes) - end - - def self.find_for(user, attributes = {}) - attributes.reverse_merge! attributes_from_user(user) - find_by_address_and_destination [attributes[:address], attributes[:destination]] - end - - def self.build_for(user, attributes = {}) - attributes.reverse_merge! attributes_from_user(user) - Identity.new(attributes) - end - - def self.create_for(user, attributes = {}) - identity = build_for(user, attributes) - identity.save - identity - end - - def self.disable_all_for(user) - Identity.by_user_id.key(user.id).each do |identity| - identity.disable - identity.save - end - end - - def self.destroy_all_disabled - Identity.disabled.each do |identity| - identity.destroy - end - end - - def self.attributes_from_user(user) - { user_id: user.id, - address: user.email_address, - destination: user.email_address - } - end - - def enabled? - self.destination && self.user_id - end - - def disable - self.destination = nil - self.user_id = nil - end - - def keys - read_attribute('keys') || HashWithIndifferentAccess.new - end - - def set_key(type, key) - return if keys[type] == key.to_s - write_attribute('keys', keys.merge(type => key.to_s)) - end - - # for LoginFormatValidation - def login - self.address.handle - end - - protected - - def unique_forward - same = Identity.find_by_address_and_destination([address, destination]) - if same && same != self - errors.add :base, "This alias already exists" - end - end - - def alias_available - same = Identity.find_by_address(address) - if same && same.user != self.user - errors.add :base, "This email has already been taken" - end - end - - def address_local_email - return if address.valid? #this ensures it is LocalEmail - self.errors.add(:address, address.errors.messages[:email].first) #assumes only one error - end - - def destination_email - return if destination.nil? # this identity is disabled - return if destination.valid? # this ensures it is Email - self.errors.add(:destination, destination.errors.messages[:email].first) #assumes only one error #TODO - end - -end diff --git a/users/app/models/local_email.rb b/users/app/models/local_email.rb deleted file mode 100644 index 2b4c65e..0000000 --- a/users/app/models/local_email.rb +++ /dev/null @@ -1,68 +0,0 @@ -class LocalEmail < Email - - BLACKLIST_FROM_RFC2142 = [ - 'postmaster', 'hostmaster', 'domainadmin', 'webmaster', 'www', - 'abuse', 'noc', 'security', 'usenet', 'news', 'uucp', - 'ftp', 'sales', 'marketing', 'support', 'info' - ] - - def self.domain - APP_CONFIG[:domain] - end - - validates :email, - :format => { - :with => /@#{domain}\Z/i, - :message => "needs to end in @#{domain}" - } - - validate :handle_allowed - - def initialize(s) - super - append_domain_if_needed - end - - def to_key - [handle] - end - - def domain - LocalEmail.domain - end - - protected - - def append_domain_if_needed - unless self.index('@') - self << '@' + domain - end - end - - def handle_allowed - errors.add(:handle, "is reserved.") if handle_reserved? - end - - def handle_reserved? - # *ARRAY in a case statement tests if ARRAY includes the handle. - case handle - when *APP_CONFIG[:handle_blacklist] - true - when *APP_CONFIG[:handle_whitelist] - false - when *BLACKLIST_FROM_RFC2142 - true - else - handle_in_passwd? - end - end - - def handle_in_passwd? - begin - !!Etc.getpwnam(handle) - rescue ArgumentError - # handle was not found - return false - end - end -end diff --git a/users/app/models/login_format_validation.rb b/users/app/models/login_format_validation.rb deleted file mode 100644 index c1fcf70..0000000 --- a/users/app/models/login_format_validation.rb +++ /dev/null @@ -1,21 +0,0 @@ -module LoginFormatValidation - extend ActiveSupport::Concern - - #TODO: Probably will replace this. Playing with using it for aliases too, but won't want it connected to login field. - - included do - # Have multiple regular expression validations so we can get specific error messages: - validates :login, - :format => { :with => /\A.{2,}\z/, - :message => "Must have at least two characters"} - validates :login, - :format => { :with => /\A[a-z\d_\.-]+\z/, - :message => "Only lowercase letters, digits, . - and _ allowed."} - validates :login, - :format => { :with => /\A[a-z].*\z/, - :message => "Must begin with a lowercase letter"} - validates :login, - :format => { :with => /\A.*[a-z\d]\z/, - :message => "Must end with a letter or digit"} - end -end diff --git a/users/app/models/pgp_key.rb b/users/app/models/pgp_key.rb deleted file mode 100644 index 66f8660..0000000 --- a/users/app/models/pgp_key.rb +++ /dev/null @@ -1,48 +0,0 @@ -class PgpKey - include ActiveModel::Validations - - KEYBLOCK_IDENTIFIERS = [ - '-----BEGIN PGP PUBLIC KEY BLOCK-----', - '-----END PGP PUBLIC KEY BLOCK-----', - ] - - # mostly for testing. - attr_accessor :keyblock - - validate :validate_keyblock_format - - def initialize(keyblock = nil) - @keyblock = keyblock - end - - def to_s - @keyblock - end - - def present? - @keyblock.present? - end - - # allow comparison with plain keyblock strings. - def ==(other) - self.equal?(other) or - # relax the comparison on line ends. - self.to_s.tr_s("\n\r", '') == other.tr_s("\r\n", '') - end - - protected - - def validate_keyblock_format - if keyblock_identifier_missing? - errors.add :public_key_block, - "does not look like an armored pgp public key block" - end - end - - def keyblock_identifier_missing? - KEYBLOCK_IDENTIFIERS.find do |identify| - !@keyblock.include?(identify) - end - end - -end diff --git a/users/app/models/service_level.rb b/users/app/models/service_level.rb deleted file mode 100644 index 299aaf1..0000000 --- a/users/app/models/service_level.rb +++ /dev/null @@ -1,19 +0,0 @@ -class ServiceLevel - - def initialize(attributes = {}) - @id = attributes[:id] || APP_CONFIG[:default_service_level] - end - - def self.authenticated_select_options - APP_CONFIG[:service_levels].map { |id,config_hash| [config_hash[:description], id] if config_hash[:name] != 'anonymous'}.compact - end - - def id - @id - end - - def config_hash - APP_CONFIG[:service_levels][@id] - end - -end diff --git a/users/app/models/session.rb b/users/app/models/session.rb deleted file mode 100644 index 0d7e10e..0000000 --- a/users/app/models/session.rb +++ /dev/null @@ -1,32 +0,0 @@ -class Session < SRP::Session - include ActiveModel::Validations - include LoginFormatValidation - - attr_accessor :login - - validates :login, :presence => true - - def initialize(user = nil, aa = nil) - super(user, aa) if user - end - - def persisted? - false - end - - def new_record? - true - end - - def to_model - self - end - - def to_key - [object_id] - end - - def to_param - nil - end -end diff --git a/users/app/models/token.rb b/users/app/models/token.rb deleted file mode 100644 index 001eb40..0000000 --- a/users/app/models/token.rb +++ /dev/null @@ -1,61 +0,0 @@ -class Token < CouchRest::Model::Base - - use_database :tokens - - belongs_to :user - - # timestamps! does not create setters and only sets updated_at - # if the object has changed and been saved. Instead of triggering - # that we rather use our own property we have control over: - property :last_seen_at, Time, accessible: false - - validates :user_id, presence: true - - design do - view :by_last_seen_at - end - - def self.expires_after - APP_CONFIG[:auth] && APP_CONFIG[:auth][:token_expires_after] - end - - def self.expired - return [] unless expires_after - by_last_seen_at.endkey(expires_after.minutes.ago) - end - - def self.destroy_all_expired - self.expired.each do |token| - token.destroy - end - end - - def authenticate - if expired? - destroy - return nil - else - touch - return user - end - end - - def touch - self.last_seen_at = Time.now - save - end - - def expired? - Token.expires_after and - last_seen_at < Token.expires_after.minutes.ago - end - - def initialize(*args) - super - if new_record? - self.id = SecureRandom.urlsafe_base64(32).gsub(/^_*/, '') - self.last_seen_at = Time.now - end - end -end - diff --git a/users/app/models/unauthenticated_user.rb b/users/app/models/unauthenticated_user.rb deleted file mode 100644 index 0fc17d2..0000000 --- a/users/app/models/unauthenticated_user.rb +++ /dev/null @@ -1,6 +0,0 @@ -# The nil object for the user class -class UnauthenticatedUser < Object - - # will probably want something here to return service level as APP_CONFIG[:service_levels][0] but not sure how will be accessing. - -end diff --git a/users/app/models/user.rb b/users/app/models/user.rb deleted file mode 100644 index 720f5a9..0000000 --- a/users/app/models/user.rb +++ /dev/null @@ -1,143 +0,0 @@ -class User < CouchRest::Model::Base - include LoginFormatValidation - - use_database :users - - property :login, String, :accessible => true - property :password_verifier, String, :accessible => true - property :password_salt, String, :accessible => true - - property :enabled, TrueClass, :default => true - - # these will be null by default but we shouldn't ever pull them directly, but only via the methods that will return the full ServiceLevel - property :desired_service_level_code, Integer, :accessible => true - property :effective_service_level_code, Integer, :accessible => true - - before_save :update_effective_service_level - - validates :login, :password_salt, :password_verifier, - :presence => true - - validates :login, - :uniqueness => true, - :if => :serverside? - - validate :login_is_unique_alias - - validates :password_salt, :password_verifier, - :format => { :with => /\A[\dA-Fa-f]+\z/, :message => "Only hex numbers allowed" } - - validates :password, :presence => true, - :confirmation => true, - :format => { :with => /.{8}.*/, :message => "needs to be at least 8 characters long" } - - timestamps! - - design do - own_path = Pathname.new(File.dirname(__FILE__)) - load_views(own_path.join('..', 'designs', 'user')) - view :by_login - view :by_created_at - end # end of design - - def to_json(options={}) - { - :login => login, - :ok => valid? - }.to_json(options) - end - - def salt - password_salt.hex - end - - def verifier - password_verifier.hex - end - - def username - login - end - - def email_address - LocalEmail.new(login) - end - - # Since we are storing admins by login, we cannot allow admins to change their login. - def is_admin? - APP_CONFIG['admins'].include? self.login - end - - def most_recent_tickets(count=3) - Ticket.for_user(self).limit(count).all #defaults to having most recent updated first - end - - # DEPRECATED - # - # Please set the key on the identity directly - # WARNING: This will not be serialized with the user record! - # It is only a workaround for the key form. - def public_key=(value) - identity.set_key(:pgp, value) - end - - # DEPRECATED - # - # Please access identity.keys[:pgp] directly - def public_key - identity.keys[:pgp] - end - - def account - Account.new(self) - end - - def identity - @identity ||= Identity.for(self) - end - - def refresh_identity - @identity = Identity.for(self) - end - - def desired_service_level - code = self.desired_service_level_code || APP_CONFIG[:default_service_level] - ServiceLevel.new({id: code}) - end - - def effective_service_level - code = self.effective_service_level_code || self.desired_service_level.id - ServiceLevel.new({id: code}) - end - - protected - - ## - # Validation Functions - ## - - def login_is_unique_alias - alias_identity = Identity.find_by_address(self.email_address) - return if alias_identity.blank? - if alias_identity.user != self - errors.add(:login, "has already been taken") - end - end - - def password - password_verifier - end - - # used as a condition for validations that are server side only - def serverside? - true - end - - def update_effective_service_level - # TODO: Is this always the case? Might there be a situation where the admin has set the effective service level and we don't want it changed to match the desired one? - if self.desired_service_level_code_changed? - self.effective_service_level_code = self.desired_service_level_code - end - end - -end diff --git a/users/app/views/.gitkeep b/users/app/views/.gitkeep deleted file mode 100644 index e69de29..0000000 --- a/users/app/views/.gitkeep +++ /dev/null diff --git a/users/app/views/emails/_email.html.haml b/users/app/views/emails/_email.html.haml deleted file mode 100644 index ea59cec..0000000 --- a/users/app/views/emails/_email.html.haml +++ /dev/null @@ -1,6 +0,0 @@ -= wrapped(email, local_assigns) do - = email - - if local_assigns[:with].try(:include?, :delete) - = link_to(user_email_alias_path(@user, email), :method => :delete) do - %i.icon-remove - diff --git a/users/app/views/sessions/new.html.haml b/users/app/views/sessions/new.html.haml deleted file mode 100644 index 771dc97..0000000 --- a/users/app/views/sessions/new.html.haml +++ /dev/null @@ -1,10 +0,0 @@ -.span1 -.span9 - = render :partial => 'users/warnings' - %h2=t :login - = simple_form_for [:api, @session], :validate => true, :html => { :id => :new_session, :class => 'form-horizontal' } do |f| - = f.input :login, :required => false, :label => t(:username), :input_html => { :id => :srp_username } - = f.input :password, :required => false, :input_html => { :id => :srp_password } - .form-actions - = f.button :submit, :value => t(:login), :class => 'btn-primary' - = link_to t(:cancel), home_path, :class => 'btn' diff --git a/users/app/views/sessions/new.json.erb b/users/app/views/sessions/new.json.erb deleted file mode 100644 index 36154b8..0000000 --- a/users/app/views/sessions/new.json.erb +++ /dev/null @@ -1,3 +0,0 @@ -{ -"errors": <%= raw @errors.to_json %> -} diff --git a/users/app/views/users/_change_password.html.haml b/users/app/views/users/_change_password.html.haml deleted file mode 100644 index 425e3ee..0000000 --- a/users/app/views/users/_change_password.html.haml +++ /dev/null @@ -1,21 +0,0 @@ --# --# CHANGE PASSWORD --# --# * everything about this form is handled with javascript. So take care when changing any ids. --# * the login is required when changing the password because it is used as part of the salt when calculating the password verifier. --# however, we don't want the user to change their login without generating a new key, so we hide the ui for this --# (although it works perfectly fine to change username if the field was visible). --# - -- form_options = {:url => '/not-used', :html => {:class => user_form_class('form-horizontal'), :id => 'update_login_and_password', :data => {token: session[:token]}}, :validate => true} -= simple_form_for @user, form_options do |f| - %legend= t(:change_password) - = hidden_field_tag 'user_param', @user.to_param - .hidden - = f.input :login, :label => t(:username), :required => false, :input_html => {:id => :srp_username} - = f.input :password, :required => false, :validate => true, :input_html => { :id => :srp_password } - = f.input :password_confirmation, :required => false, :input_html => { :id => :srp_password_confirmation } - .control-group - .controls - = f.submit t(:save), :class => 'btn btn-primary' - diff --git a/users/app/views/users/_change_pgp_key.html.haml b/users/app/views/users/_change_pgp_key.html.haml deleted file mode 100644 index e465125..0000000 --- a/users/app/views/users/_change_pgp_key.html.haml +++ /dev/null @@ -1,13 +0,0 @@ --# --# CHANGE PGP KEY --# --# this will be replaced by a identities controller/view at some point --# - -- form_options = {:html => {:class => user_form_class('form-horizontal'), :id => 'update_pgp_key', :data => {token: session[:token]}}, :validate => true} -= simple_form_for [:api, @user], form_options do |f| - %legend= t(:advanced_options) - = f.input :public_key, :as => :text, :hint => t(:use_ascii_key), :input_html => {:class => "full-width", :rows => 4} - .control-group - .controls - = f.submit t(:save), :class => 'btn', :data => {"loading-text" => "Saving..."} diff --git a/users/app/views/users/_change_service_level.html.haml b/users/app/views/users/_change_service_level.html.haml deleted file mode 100644 index 61e67d9..0000000 --- a/users/app/views/users/_change_service_level.html.haml +++ /dev/null @@ -1,18 +0,0 @@ --# TODO: probably won't want here, but here for now. Also, we will need way to ensure payment if they pick a non-free plan. --# --# SERVICE LEVEL --# -- if APP_CONFIG[:service_levels] - - form_options = {:html => {:class => user_form_class('form-horizontal'), :id => 'update_service_level', :data => {token: session[:token]}}, :validate => true} - = simple_form_for @user, form_options do |f| - %legend= t(:service_level) - - if @user != current_user - = t(:desired_service_level) - = f.select :desired_service_level_code, ServiceLevel.authenticated_select_options, :selected => @user.desired_service_level.id - - if @user != current_user - %p - = t(:effective_service_level) - = f.select :effective_service_level_code, ServiceLevel.authenticated_select_options, :selected => @user.effective_service_level.id - .control-group - .controls - = f.submit t(:save), :class => 'btn', :data => {"loading-text" => "Saving..."} diff --git a/users/app/views/users/_destroy_account.html.haml b/users/app/views/users/_destroy_account.html.haml deleted file mode 100644 index 445f3c4..0000000 --- a/users/app/views/users/_destroy_account.html.haml +++ /dev/null @@ -1,27 +0,0 @@ --# --# DESTROY ACCOUNT --# - -%legend - - if @user == current_user - = t(:destroy_my_account) - - else - = t(:admin_destroy_account, :username => @user.login) -%p= t(:destroy_account_info) -= link_to user_path(@user), :method => :delete, :confirm => t(:are_you_sure), :class => "btn btn-danger" do - %i.icon-remove.icon-white - = t(:destroy_my_account) -- if @user != current_user and @user.enabled? - %legend - = t(:deactivate_account, :username => @user.login) - %p= t(:deactivate_description) - = link_to deactivate_user_path(@user), :method => :post, :class => "btn btn-warning" do - %i.icon-pause.icon-white - = t(:deactivate) -- elsif @user != current_user and !@user.enabled? - %legend - = t(:enable_account, :username => @user.login) - %p= t(:enable_description) - = link_to enable_user_path(@user), :method => :post, :class => "btn btn-warning" do - %i.icon-ok.icon-white - = t(:enable) diff --git a/users/app/views/users/_edit.html.haml b/users/app/views/users/_edit.html.haml deleted file mode 100644 index 1d2b68a..0000000 --- a/users/app/views/users/_edit.html.haml +++ /dev/null @@ -1,14 +0,0 @@ --# --# edit user form, used by both show and edit actions. --# --# We render a bunch of forms here. Which we use depends upon config settings --# user_actions and admin_actions. They both include an array of actions --# allowed to users and admins. --# Possible forms are: --# 'change_password' --# 'change_pgp_key' --# 'change_service_level' --# 'destroy_account' -- actions = APP_CONFIG[admin? ? :admin_actions : :user_actions] || [] -- actions.each do |action| - = render action diff --git a/users/app/views/users/_user.html.haml b/users/app/views/users/_user.html.haml deleted file mode 100644 index 583d22f..0000000 --- a/users/app/views/users/_user.html.haml +++ /dev/null @@ -1,4 +0,0 @@ -%tr - %td= link_to user.login, user - %td= l(user.created_at, :format => :short) - %td= l(user.updated_at, :format => :short) diff --git a/users/app/views/users/_warnings.html.haml b/users/app/views/users/_warnings.html.haml deleted file mode 100644 index 79ab103..0000000 --- a/users/app/views/users/_warnings.html.haml +++ /dev/null @@ -1,12 +0,0 @@ -%noscript - %div.alert.alert-error=t :js_required_html -#cookie_warning.alert.alert-error{:style => "display:none"} - =t :cookie_disabled_warning -:javascript - document.cookie = "testing=cookies_enabled; path=/"; - if(document.cookie.indexOf("testing=cookies_enabled") < 0) - { - document.getElementById('cookie_warning').style.display = 'block'; - } else { - document.getElementById('cookie_warning').style.display = 'none'; - }
\ No newline at end of file diff --git a/users/app/views/users/edit.html.haml b/users/app/views/users/edit.html.haml deleted file mode 100644 index 434c025..0000000 --- a/users/app/views/users/edit.html.haml +++ /dev/null @@ -1 +0,0 @@ -= render 'edit' diff --git a/users/app/views/users/index.html.haml b/users/app/views/users/index.html.haml deleted file mode 100644 index fc1001e..0000000 --- a/users/app/views/users/index.html.haml +++ /dev/null @@ -1,13 +0,0 @@ -- @show_navigation = false - -= form_tag users_path, :method => :get, :class => "form-search" do - .input-append - = text_field_tag :query, params[:query], :id => 'user-typeahead', :class => "search-query", :autocomplete => :off - %button.btn{:type => :submit}= t(:search) - -%table.table.table-striped - %tr - %th= t(:username) - %th= t(:created) - %th= t(:updated) - = render @users.all diff --git a/users/app/views/users/new.html.haml b/users/app/views/users/new.html.haml deleted file mode 100644 index aecf831..0000000 --- a/users/app/views/users/new.html.haml +++ /dev/null @@ -1,19 +0,0 @@ --# --# This form is handled entirely by javascript, so take care when changing element ids. --# - -- form_options = {:url => '/not-used', :html => {:id => 'new_user', :class => user_form_class('form-horizontal')}, :validate => true} - -.span1 -.span9 - = render :partial => 'warnings' - %h2=t :signup - = simple_form_for(@user, form_options) do |f| - %legend= t(:signup_message) - = f.input :login, :label => t(:username), :required => false, :input_html => { :id => :srp_username } - = f.input :password, :required => false, :validate => true, :input_html => { :id => :srp_password } - = f.input :password_confirmation, :required => false, :validate => true, :input_html => { :id => :srp_password_confirmation } - .form-actions - = f.button :submit, :value => t(:signup), :class => 'btn btn-primary' - = link_to t(:cancel), home_path, :class => 'btn' - diff --git a/users/app/views/users/show.html.haml b/users/app/views/users/show.html.haml deleted file mode 100644 index c587017..0000000 --- a/users/app/views/users/show.html.haml +++ /dev/null @@ -1,25 +0,0 @@ -.overview - - %h2.first= t(:overview_welcome, :username => @user.login) - - - if admin? - %p - = t(:created) - = @user.created_at - %br - = t(:updated) - = @user.updated_at - %br - = t(:enabled) - = @user.enabled? - - %p= t(:overview_intro) - - %ul.unstyled - %li= icon('user') + link_to(t(:overview_account), edit_user_path(@user)) - - # %li= icon('envelope') + link_to(t(:overview_email), {insert path for user identities, presuambly} - %li= icon('question-sign') + link_to(t(:overview_tickets), user_tickets_path(@user)) - %li= icon('shopping-cart') + link_to(t(:overview_billing), billing_top_link(@user)) if APP_CONFIG[:billing] - .container-fluid - .row-fluid - = home_page_buttons(true)
\ No newline at end of file diff --git a/users/app/views/v1/sessions/new.json.erb b/users/app/views/v1/sessions/new.json.erb deleted file mode 100644 index 36154b8..0000000 --- a/users/app/views/v1/sessions/new.json.erb +++ /dev/null @@ -1,3 +0,0 @@ -{ -"errors": <%= raw @errors.to_json %> -} diff --git a/users/app/views/webfinger/host_meta.xml.erb b/users/app/views/webfinger/host_meta.xml.erb deleted file mode 100644 index cfcbcc0..0000000 --- a/users/app/views/webfinger/host_meta.xml.erb +++ /dev/null @@ -1,11 +0,0 @@ -<?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 deleted file mode 100644 index 7328552..0000000 --- a/users/app/views/webfinger/search.xml.erb +++ /dev/null @@ -1,7 +0,0 @@ -<?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/initializers/add_controller_methods.rb b/users/config/initializers/add_controller_methods.rb deleted file mode 100644 index f572ecb..0000000 --- a/users/config/initializers/add_controller_methods.rb +++ /dev/null @@ -1,4 +0,0 @@ -ActiveSupport.on_load(:application_controller) do - include ControllerExtension::Authentication - include ControllerExtension::TokenAuthentication -end diff --git a/users/config/initializers/error_constants.rb b/users/config/initializers/error_constants.rb deleted file mode 100644 index d4a0f52..0000000 --- a/users/config/initializers/error_constants.rb +++ /dev/null @@ -1 +0,0 @@ -WRONG_PASSWORD = SRP::WrongPassword diff --git a/users/config/initializers/warden.rb b/users/config/initializers/warden.rb deleted file mode 100644 index 45feb6c..0000000 --- a/users/config/initializers/warden.rb +++ /dev/null @@ -1,7 +0,0 @@ -Rails.configuration.middleware.use RailsWarden::Manager do |config| - config.default_strategies :secure_remote_password - config.failure_app = SessionsController -end - -RailsWarden.unauthenticated_action = :new - diff --git a/users/config/locales/en.yml b/users/config/locales/en.yml deleted file mode 100644 index e597164..0000000 --- a/users/config/locales/en.yml +++ /dev/null @@ -1,72 +0,0 @@ -en: - account_settings: "Account Settings" - logout: "Logout" - none: "None" - signup: "Sign Up" - signup_message: "Please create an account." - cancel: "Cancel" - login: "Log In" - username: "Username" - password: "Password" - change_password: "Change Password" - login_message: "Please log in with your account." - invalid_user_pass: "Not a valid username/password combination" - invalid_ephemeral: "Invalid random key used. This looked like an attempt to hack the site to us. If it wasn't please contact support so we can look into the issue." - all_strategies_failed: "Could not understand your login attempt. Please first send your login and a SRP ephemeral value A and then send the client_auth in the same session (using cookies)." - update_login_and_password: "Update Login and Password" - destroy_my_account: "Destroy my account" - destroy_account_info: "This will permanently destroy your account and all the data associated with it. Proceed with caution!" - admin_destroy_account: "Destroy the account %{username}" - account_destroyed: "The account has been destroyed successfully." - 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: "Removed email alias %{alias}." - use_ascii_key: "OpenPGP public key. Do not change this value unless you know what you are doing." - advanced_options: "Advanced Options" - not_authorized: "Sorry, but you are not authorized to perform that action." - not_authorized_login: "Please log in to perform that action." - search: "Search" - cookie_disabled_warning: "You have cookies disabled. You will not be able to login until you enable cookies." - js_required_html: "We are sorry, but this doesn't work without javascript enabled. This is because the authentication system used, <a href='http://srp.stanford.edu/'>SRP</a>, requires javascript." - enable_account: "Enable the account %{username}" - enable_description: "This will restore the account to full functionality" - deactivate_account: "Deactivate the account %{username}" - deactivate_description: "This will temporarily deactivate some account functionality." #todo detail exact functionality. can receive email but not send or renew client certificate? - bye: "Goodbye!" - bye_message: "So long and thanks for all the fish." - - # - # overview - # - overview_welcome: "Welcome %{username}." - overview_intro: "From this user control panel, you can:" - overview_tickets: "Create and check support tickets." - overview_email: "Modify email settings." - overview_account: "Delete your account." - - # - # rails - # - activemodel: - models: - user: - one: User - other: "%{count} Users" - simple_form: - labels: - user: - email_forward: "Email Forward" - hints: - user: - email_forward: > - Forward all email messages to this address. Messages will be encrypted before being forwarded. - This is an option for advanced users who are familar with OpenPGP. - placeholders: - user: - email_forward: "my_other_email@domain.net" - diff --git a/users/config/routes.rb b/users/config/routes.rb deleted file mode 100644 index 736b283..0000000 --- a/users/config/routes.rb +++ /dev/null @@ -1,28 +0,0 @@ -Rails.application.routes.draw do - - namespace "api", { module: "v1", - path: "/1/", - defaults: {format: 'json'} } do - resources :sessions, :only => [:new, :create, :update] - delete "logout" => "sessions#destroy", :as => "logout" - resources :users, :only => [:create, :update, :destroy, :index] - end - - scope "(:locale)", :locale => MATCH_LOCALE do - get "login" => "sessions#new", :as => "login" - delete "logout" => "sessions#destroy", :as => "logout" - - get "signup" => "users#new", :as => "signup" - resources :users, :except => [:create, :update] do - # resource :email_settings, :only => [:edit, :update] - # resources :email_aliases, :only => [:destroy], :id => /.*/ - post 'deactivate', on: :member - post 'enable', on: :member - end - end - - get "/.well-known/host-meta" => 'webfinger#host_meta' - get "/webfinger" => 'webfinger#search' - get "/key/:login" => 'keys#show' - -end diff --git a/users/leap_web_users.gemspec b/users/leap_web_users.gemspec deleted file mode 100644 index 7d1f220..0000000 --- a/users/leap_web_users.gemspec +++ /dev/null @@ -1,22 +0,0 @@ -$:.push File.expand_path("../lib", __FILE__) - -require File.expand_path('../../lib/leap_web/version.rb', __FILE__) - -# Describe your gem and declare its dependencies: -Gem::Specification.new do |s| - s.name = "leap_web_users" - s.version = LeapWeb::VERSION - s.authors = ["Azul"] - s.email = ["azul@leap.se"] - s.homepage = "http://www.leap.se" - s.summary = "User registration and authorization for the leap platform" - s.description = "This this plugin for the leap platform provides user signup and login. It uses Secure Remote Password for the authentication." - - s.files = Dir["{app,config,db,lib}/**/*"] + ["Rakefile"] - s.test_files = Dir["test/**/*"] - - s.add_dependency "leap_web_core", LeapWeb::VERSION - - s.add_dependency "ruby-srp", "~> 0.2.1" - s.add_dependency "rails_warden" -end diff --git a/users/lib/leap_web_users.rb b/users/lib/leap_web_users.rb deleted file mode 100644 index e1b7b1f..0000000 --- a/users/lib/leap_web_users.rb +++ /dev/null @@ -1,4 +0,0 @@ -require "leap_web_users/engine" - -module LeapWebUsers -end diff --git a/users/lib/leap_web_users/engine.rb b/users/lib/leap_web_users/engine.rb deleted file mode 100644 index f8ed71c..0000000 --- a/users/lib/leap_web_users/engine.rb +++ /dev/null @@ -1,16 +0,0 @@ -# thou shall require all your dependencies in an engine. -require "leap_web_core" -require "leap_web_core/ui_dependencies" -require "rails_warden" -require "ruby-srp" - -require "warden/session_serializer" -require "warden/strategies/secure_remote_password" - -require "webfinger" - -module LeapWebUsers - class Engine < ::Rails::Engine - - end -end diff --git a/users/lib/tasks/leap_web_users_tasks.rake b/users/lib/tasks/leap_web_users_tasks.rake deleted file mode 100644 index 3d0649c..0000000 --- a/users/lib/tasks/leap_web_users_tasks.rake +++ /dev/null @@ -1,4 +0,0 @@ -# desc "Explaining what the task does" -# task :leap_web_users do -# # Task goes here -# end diff --git a/users/lib/warden/session_serializer.rb b/users/lib/warden/session_serializer.rb deleted file mode 100644 index 81d7076..0000000 --- a/users/lib/warden/session_serializer.rb +++ /dev/null @@ -1,13 +0,0 @@ -module Warden - # Setup Session Serialization - class SessionSerializer - def serialize(record) - [record.class.name, record.id] - end - - def deserialize(keys) - klass, id = keys - klass.constantize.find(id) - end - end -end diff --git a/users/lib/warden/strategies/secure_remote_password.rb b/users/lib/warden/strategies/secure_remote_password.rb deleted file mode 100644 index 2c334c6..0000000 --- a/users/lib/warden/strategies/secure_remote_password.rb +++ /dev/null @@ -1,81 +0,0 @@ -module Warden - module Strategies - class SecureRemotePassword < Warden::Strategies::Base - - def valid? - handshake? || authentication? - end - - def authenticate! - if authentication? - validate! - else # handshake - initialize! - end - end - - protected - - def handshake? - params['A'] && params['login'] - end - - def authentication? - params['client_auth'] && session[:handshake] - end - - def validate! - if client = validate - success!(User.find_by_login(client.username)) - else - Rails.logger.warn "Login attempt failed." - Rails.logger.debug debug_info - Rails.logger.debug "Received: #{params['client_auth']}" - session.delete(:handshake) - fail!(:base => "invalid_user_pass") - end - end - - def validate - session[:handshake].authenticate(params['client_auth']) - end - - def initialize! - if user = User.find_by_login(id) - client = SRP::Client.new user.username, - :verifier => user.verifier, - :salt => user.salt - session[:handshake] = SRP::Session.new(client, params['A']) - custom! json_response(session[:handshake]) - else - fail! :base => 'invalid_user_pass' - end - rescue SRP::InvalidEphemeral - fail!(:base => "invalid_ephemeral") - end - - def json_response(object) - [ 200, - {"Content-Type" => "application/json; charset=utf-8"}, - [object.to_json] - ] - end - - def id - params["id"] || params["login"] - end - - protected - - def debug_info - JSON.pretty_generate(session[:handshake].internal_state) - end - - end - end - Warden::Strategies.add :secure_remote_password, - Warden::Strategies::SecureRemotePassword - -end - - diff --git a/users/lib/webfinger.rb b/users/lib/webfinger.rb deleted file mode 100644 index dd49b41..0000000 --- a/users/lib/webfinger.rb +++ /dev/null @@ -1,6 +0,0 @@ -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 deleted file mode 100644 index 84ab7a9..0000000 --- a/users/lib/webfinger/host_meta_presenter.rb +++ /dev/null @@ -1,30 +0,0 @@ -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 deleted file mode 100644 index 329f477..0000000 --- a/users/lib/webfinger/user_presenter.rb +++ /dev/null @@ -1,35 +0,0 @@ -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/script/rails b/users/script/rails deleted file mode 100755 index ee08520..0000000 --- a/users/script/rails +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env ruby1.8 -# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application. - -ENGINE_ROOT = File.expand_path('../..', __FILE__) -ENGINE_PATH = File.expand_path('../../lib/leap_web_users/engine', __FILE__) - -require 'rails/all' -require 'rails/engine/commands' diff --git a/users/test/factories.rb b/users/test/factories.rb deleted file mode 100644 index ae00d43..0000000 --- a/users/test/factories.rb +++ /dev/null @@ -1,34 +0,0 @@ -FactoryGirl.define do - - factory :user do - login { Faker::Internet.user_name } - password_verifier "1234ABCD" - password_salt "4321AB" - - factory :user_with_settings do - email_forward { Faker::Internet.email } - email_aliases_attributes do - {:a => Faker::Internet.user_name + '@' + APP_CONFIG[:domain]} - end - end - - factory :admin_user do - after(:build) do |admin| - admin.stubs(:is_admin?).returns(true) - end - end - end - - factory :token do - user - end - - factory :pgp_key do - keyblock <<-EOPGP ------BEGIN PGP PUBLIC KEY BLOCK----- -+Dummy+PGP+KEY+++Dummy+PGP+KEY+++Dummy+PGP+KEY+++Dummy+PGP+KEY+ -#{SecureRandom.base64(4032)} ------END PGP PUBLIC KEY BLOCK----- - EOPGP - end -end diff --git a/users/test/fixtures/.gitkeep b/users/test/fixtures/.gitkeep deleted file mode 100644 index e69de29..0000000 --- a/users/test/fixtures/.gitkeep +++ /dev/null diff --git a/users/test/functional/.gitkeep b/users/test/functional/.gitkeep deleted file mode 100644 index e69de29..0000000 --- a/users/test/functional/.gitkeep +++ /dev/null diff --git a/users/test/functional/application_controller_test.rb b/users/test/functional/application_controller_test.rb deleted file mode 100644 index 94b77bd..0000000 --- a/users/test/functional/application_controller_test.rb +++ /dev/null @@ -1,28 +0,0 @@ -require 'test_helper' - -class ApplicationControllerTest < ActionController::TestCase - - def setup - # so we can test the effect on the response - @controller.response = @response - end - - def test_authorize_redirect - @controller.send(:authorize) - assert_access_denied(true, false) - end - - def test_authorized - login - @controller.send(:authorize) - assert_access_denied(false) - end - - def test_authorize_admin - login - @current_user.expects(:is_admin?).returns(false) - @controller.send(:authorize_admin) - assert_access_denied - end - -end diff --git a/users/test/functional/helper_methods_test.rb b/users/test/functional/helper_methods_test.rb deleted file mode 100644 index 44226ae..0000000 --- a/users/test/functional/helper_methods_test.rb +++ /dev/null @@ -1,39 +0,0 @@ -# -# Testing and documenting the helper methods available from -# ApplicationController -# - -require 'test_helper' - -class HelperMethodsTest < ActionController::TestCase - tests ApplicationController - - # we test them right in here... - include ApplicationController._helpers - - # the helpers all reference the controller. - def controller - @controller - end - - def test_current_user - login - assert_equal @current_user, current_user - end - - def test_logged_in - login - assert logged_in? - end - - def test_logged_out - assert !logged_in? - end - - def test_admin - login - @current_user.expects(:is_admin?).returns(bool = stub) - assert_equal bool, admin? - end - -end diff --git a/users/test/functional/keys_controller_test.rb b/users/test/functional/keys_controller_test.rb deleted file mode 100644 index 863be93..0000000 --- a/users/test/functional/keys_controller_test.rb +++ /dev/null @@ -1,32 +0,0 @@ -require 'test_helper' - -class KeysControllerTest < ActionController::TestCase - - test "get existing public key" do - public_key = 'my public key' - @user = stub_record :user, :public_key => public_key - User.stubs(:find_by_login).with(@user.login).returns(@user) - get :show, :login => @user.login - assert_response :success - assert_equal "text/text", response.content_type - assert_equal public_key, response.body - end - - test "get non-existing public key for user" do - # this isn't a scenerio that should generally occur. - @user = stub_record :user - User.stubs(:find_by_login).with(@user.login).returns(@user) - get :show, :login => @user.login - assert_response :success - assert_equal "text/text", response.content_type - assert_equal '', response.body.strip - end - - test "get public key for non-existing user" do - # raise 404 error if user doesn't exist (doesn't need to be this routing error, but seems fine to assume for now): - assert_raise(ActionController::RoutingError) { - get :show, :login => 'asdkljslksjfdlskfj' - } - end - -end diff --git a/users/test/functional/sessions_controller_test.rb b/users/test/functional/sessions_controller_test.rb deleted file mode 100644 index fe7903f..0000000 --- a/users/test/functional/sessions_controller_test.rb +++ /dev/null @@ -1,59 +0,0 @@ -require 'test_helper' - -# This is a simple controller unit test. -# We're stubbing out both warden and srp. -# There's an integration test testing the full rack stack and srp -class SessionsControllerTest < ActionController::TestCase - - setup do - @user = stub :login => "me", :id => 123 - @client_hex = 'a123' - end - - test "should get login screen" do - get :new - assert_response :success - assert_equal "text/html", response.content_type - assert_template "sessions/new" - end - - test "redirect to home_url if logged in" do - login - get :new - assert_response :redirect - assert_redirected_to home_url - end - - test "renders json" do - get :new, :format => :json - assert_response :success - assert_json_error nil - end - - test "renders warden errors" do - request.env['warden.options'] = {attempted_path: '/1/sessions/asdf.json'} - strategy = stub :message => {:field => :translate_me} - request.env['warden'].stubs(:winning_strategy).returns(strategy) - I18n.expects(:t).with(:translate_me).at_least_once.returns("translation stub") - get :new, :format => :json - assert_response 422 - assert_json_error :field => "translation stub" - end - - test "renders failed attempt message" do - request.env['warden.options'] = {attempted_path: '/1/sessions/asdf.json'} - request.env['warden'].stubs(:winning_strategy).returns(nil) - get :new, :format => :json - assert_response 422 - assert_json_error :login => I18n.t(:all_strategies_failed) - end - - test "destory should logout" do - login - expect_logout - delete :destroy - assert_response :redirect - assert_redirected_to home_url - end - -end diff --git a/users/test/functional/test_helpers_test.rb b/users/test/functional/test_helpers_test.rb deleted file mode 100644 index 845e516..0000000 --- a/users/test/functional/test_helpers_test.rb +++ /dev/null @@ -1,38 +0,0 @@ -# -# There are a few test helpers for dealing with login etc. -# We test them here and also document their behaviour. -# - -require 'test_helper' - -class TestHelpersTest < ActionController::TestCase - tests ApplicationController # testing no controller in particular - - def test_login_stubs_warden - login - assert_equal @current_user, request.env['warden'].user - end - - def test_login_token_authenticates - login - assert_equal @current_user, @controller.send(:token_authenticate) - end - - def test_login_stubs_token - login - assert @token - assert_equal @current_user, @token.authenticate - end - - def test_login_adds_token_header - login - token_present = @controller.authenticate_with_http_token do |token, options| - assert_equal @token.id, token - end - # authenticate_with_http_token just returns nil and does not - # execute the block if there is no token. So we have to also - # ensure it was run: - assert token_present - end -end - diff --git a/users/test/functional/users_controller_test.rb b/users/test/functional/users_controller_test.rb deleted file mode 100644 index 57ae94d..0000000 --- a/users/test/functional/users_controller_test.rb +++ /dev/null @@ -1,159 +0,0 @@ -require 'test_helper' - -class UsersControllerTest < ActionController::TestCase - - test "should get new" do - get :new - - assert_equal User, assigns(:user).class - assert_response :success - end - - test "failed show without login" do - user = find_record :user - get :show, :id => user.id - assert_response :redirect - assert_redirected_to login_path - end - - test "user can see user" do - user = find_record :user, - :most_recent_tickets => [] - login user - get :show, :id => user.id - assert_response :success - end - - test "admin can see other user" do - user = find_record :user, - :most_recent_tickets => [] - login :is_admin? => true - get :show, :id => user.id - assert_response :success - - end - - test "user cannot see other user" do - user = find_record :user, - :most_recent_tickets => [] - login - get :show, :id => user.id - assert_response :redirect - assert_access_denied - end - - test "may not show non-existing user without auth" do - nonid = 'thisisnotanexistinguserid' - - get :show, :id => nonid - assert_access_denied(true, false) - end - - test "may not show non-existing user without admin" do - nonid = 'thisisnotanexistinguserid' - login - - get :show, :id => nonid - assert_access_denied - end - - test "redirect admin to user list for non-existing user" do - nonid = 'thisisnotanexistinguserid' - login :is_admin? => true - get :show, :id => nonid - assert_response :redirect - assert_equal({:alert => "No such user."}, flash.to_hash) - assert_redirected_to users_path - end - - test "should get edit view" do - user = find_record :user - - login user - get :edit, :id => user.id - - assert_equal user, assigns[:user] - end - - test "admin can destroy user" do - user = find_record :user - - # we destroy the user record and the associated data... - user.expects(:destroy) - Identity.expects(:disable_all_for).with(user) - Ticket.expects(:destroy_all_from).with(user) - - login :is_admin? => true - delete :destroy, :id => user.id - - assert_response :redirect - assert_redirected_to users_path - end - - test "user can cancel account" do - user = find_record :user - - # we destroy the user record and the associated data... - user.expects(:destroy) - Identity.expects(:disable_all_for).with(user) - Ticket.expects(:destroy_all_from).with(user) - - login user - expect_logout - delete :destroy, :id => @current_user.id - - assert_response :redirect - assert_redirected_to bye_url - end - - test "non-admin can't destroy user" do - user = find_record :user - - login - delete :destroy, :id => user.id - - assert_access_denied - end - - test "admin can list users" do - login :is_admin? => true - get :index - - assert_response :success - assert assigns(:users) - end - - test "non-admin can't list users" do - login - get :index - - assert_access_denied - end - - test "admin can search users" do - login :is_admin? => true - get :index, :query => "a" - - assert_response :success - assert assigns(:users) - end - - test "user cannot enable own account" do - user = find_record :user - login - post :enable, :id => user.id - assert_access_denied - end - - test "admin can deactivate user" do - user = find_record :user - assert user.enabled? - user.expects(:save).returns(true) - - login :is_admin? => true - - post :deactivate, :id => user.id - assert !assigns(:user).enabled? - end - -end diff --git a/users/test/functional/v1/sessions_controller_test.rb b/users/test/functional/v1/sessions_controller_test.rb deleted file mode 100644 index 4200e8f..0000000 --- a/users/test/functional/v1/sessions_controller_test.rb +++ /dev/null @@ -1,62 +0,0 @@ -require 'test_helper' - -# This is a simple controller unit test. -# We're stubbing out both warden and srp. -# There's an integration test testing the full rack stack and srp -class V1::SessionsControllerTest < ActionController::TestCase - - setup do - @request.env['HTTP_HOST'] = 'api.lvh.me' - @user = stub_record :user, {}, true - @client_hex = 'a123' - end - - test "renders json" do - get :new, :format => :json - assert_response :success - assert_json_error nil - end - - test "renders warden errors" do - request.env['warden.options'] = {attempted_path: 'path/to/controller'} - strategy = stub :message => {:field => :translate_me} - request.env['warden'].stubs(:winning_strategy).returns(strategy) - I18n.expects(:t).with(:translate_me).at_least_once.returns("translation stub") - get :new, :format => :json - assert_response 422 - assert_json_error :field => "translation stub" - end - - # Warden takes care of parsing the params and - # rendering the response. So not much to test here. - test "should perform handshake" do - request.env['warden'].expects(:authenticate!) - # make sure we don't get a template missing error: - @controller.stubs(:render) - post :create, :login => @user.login, 'A' => @client_hex - end - - test "should authorize" do - request.env['warden'].expects(:authenticate!) - @controller.stubs(:current_user).returns(@user) - handshake = stub(:to_hash => {h: "ash"}) - session[:handshake] = handshake - - post :update, :id => @user.login, :client_auth => @client_hex - - assert_nil session[:handshake] - assert_response :success - assert json_response.keys.include?("id") - assert json_response.keys.include?("token") - assert token = Token.find(json_response['token']) - assert_equal @user.id, token.user_id - end - - test "destroy should logout" do - login - expect_logout - delete :destroy - assert_response 204 - end - -end diff --git a/users/test/functional/v1/users_controller_test.rb b/users/test/functional/v1/users_controller_test.rb deleted file mode 100644 index 7cd9b0c..0000000 --- a/users/test/functional/v1/users_controller_test.rb +++ /dev/null @@ -1,74 +0,0 @@ -require 'test_helper' - -class V1::UsersControllerTest < ActionController::TestCase - - test "user can change settings" do - user = find_record :user - changed_attribs = record_attributes_for :user_with_settings - account_settings = stub - account_settings.expects(:update).with(changed_attribs) - Account.expects(:new).with(user).returns(account_settings) - - login user - put :update, :user => changed_attribs, :id => user.id, :format => :json - - assert_equal user, assigns[:user] - assert_response 204 - assert_equal " ", @response.body - end - - test "admin can update user" do - user = find_record :user - changed_attribs = record_attributes_for :user_with_settings - account_settings = stub - account_settings.expects(:update).with(changed_attribs) - Account.expects(:new).with(user).returns(account_settings) - - login :is_admin? => true - put :update, :user => changed_attribs, :id => user.id, :format => :json - - assert_equal user, assigns[:user] - assert_response 204 - end - - test "user cannot update other user" do - user = find_record :user - login - put :update, :user => record_attributes_for(:user_with_settings), :id => user.id, :format => :json - assert_access_denied - end - - test "should create new user" do - user_attribs = record_attributes_for :user - user = User.new(user_attribs) - Account.expects(:create).with(user_attribs).returns(user) - - post :create, :user => user_attribs, :format => :json - - assert_nil session[:user_id] - assert_json_response user - assert_response :success - end - - test "should redirect to signup form on failed attempt" do - user_attribs = record_attributes_for :user - user_attribs.slice!('login') - user = User.new(user_attribs) - assert !user.valid? - Account.expects(:create).with(user_attribs).returns(user) - - post :create, :user => user_attribs, :format => :json - - assert_json_error user.errors.messages - assert_response 422 - end - - test "admin can autocomplete users" do - login :is_admin? => true - get :index, :query => 'a', :format => :json - - assert_response :success - assert assigns(:users) - end - -end diff --git a/users/test/functional/webfinger_controller_test.rb b/users/test/functional/webfinger_controller_test.rb deleted file mode 100644 index 6597b69..0000000 --- a/users/test/functional/webfinger_controller_test.rb +++ /dev/null @@ -1,33 +0,0 @@ -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/integration/.gitkeep b/users/test/integration/.gitkeep deleted file mode 100644 index e69de29..0000000 --- a/users/test/integration/.gitkeep +++ /dev/null diff --git a/users/test/integration/api/Readme.md b/users/test/integration/api/Readme.md deleted file mode 100644 index 04363bd..0000000 --- a/users/test/integration/api/Readme.md +++ /dev/null @@ -1,23 +0,0 @@ -API tests -========== - - -Testing the restful api from a simple python client as that's what we'll be using. - -This test so far mostly demoes the API. We have no SRP calc in there. - -TODO: keep track of the cookies during login. The server uses the session to keep track of the random numbers A and B. - -The output of signup_and_login_wrong_password pretty well describes the SRP API: - -``` -POST: http://localhost:9292/users.json - {"user[password_salt]": "54321", "user[password_verifier]": "12345", "user[login]": "SWQ055"} - -> {"password_salt":"54321","login":"SWQ055"} -POST: http://localhost:9292/sessions - {"A": "12345", "login": "SWQ055"} - -> {"B":"1778367531e93a4c7713c76f67649f35a4211ebc520926ae8c3848cd66171651"} -PUT: http://localhost:9292/sessions/SWQ055 - {"M": "123ABC"} - -> {"errors":[{"login":"Not a valid username/password combination"},{"password":"Not a valid username/password combination"}]} -``` diff --git a/users/test/integration/api/account_flow_test.rb b/users/test/integration/api/account_flow_test.rb deleted file mode 100644 index edd0859..0000000 --- a/users/test/integration/api/account_flow_test.rb +++ /dev/null @@ -1,136 +0,0 @@ -require 'test_helper' -require_relative 'rack_test' - -class AccountFlowTest < RackTest - - setup do - @login = "integration_test_user" - Identity.find_by_address(@login + '@' + APP_CONFIG[:domain]).tap{|i| i.destroy if i} - User.find_by_login(@login).tap{|u| u.destroy if u} - @password = "srp, verify me!" - @srp = SRP::Client.new @login, :password => @password - @user_params = { - :login => @login, - :password_verifier => @srp.verifier.to_s(16), - :password_salt => @srp.salt.to_s(16) - } - post 'http://api.lvh.me:3000/1/users.json', :user => @user_params - @user = User.find_by_login(@login) - end - - teardown do - if @user.reload - @user.identity.destroy - @user.destroy - end - Warden.test_reset! - end - - # this test wraps the api and implements the interface the ruby-srp client. - def handshake(login, aa) - post "http://api.lvh.me:3000/1/sessions.json", - :login => login, - 'A' => aa, - :format => :json - response = JSON.parse(last_response.body) - if response['errors'] - raise RECORD_NOT_FOUND.new(response['errors']) - else - return response['B'] - end - end - - def validate(m) - put "http://api.lvh.me:3000/1/sessions/" + @login + '.json', - :client_auth => m, - :format => :json - return JSON.parse(last_response.body) - end - - test "signup response" do - assert_json_response :login => @login, :ok => true - assert last_response.successful? - end - - test "signup and login with srp via api" do - server_auth = @srp.authenticate(self) - assert last_response.successful? - assert_nil server_auth["errors"] - assert server_auth["M2"] - end - - test "signup and wrong password login attempt" do - srp = SRP::Client.new @login, :password => "wrong password" - server_auth = srp.authenticate(self) - assert_json_error "base" => "Not a valid username/password combination" - assert !last_response.successful? - assert_nil server_auth["M2"] - end - - test "signup and wrong username login attempt" do - srp = SRP::Client.new "wrong_login", :password => @password - server_auth = nil - assert_raises RECORD_NOT_FOUND do - server_auth = srp.authenticate(self) - end - assert_json_error "base" => "Not a valid username/password combination" - assert !last_response.successful? - assert_nil server_auth - end - - test "update password via api" do - @srp.authenticate(self) - @password = "No! Verify me instead." - @srp = SRP::Client.new @login, :password => @password - @user_params = { - # :login => @login, - :password_verifier => @srp.verifier.to_s(16), - :password_salt => @srp.salt.to_s(16) - } - put "http://api.lvh.me:3000/1/users/" + @user.id + '.json', - :user => @user_params, - :format => :json - server_auth = @srp.authenticate(self) - assert last_response.successful? - assert_nil server_auth["errors"] - assert server_auth["M2"] - end - - test "prevent changing login without changing password_verifier" do - server_auth = @srp.authenticate(self) - original_login = @user.login - new_login = 'zaph' - User.find_by_login(new_login).try(:destroy) - Identity.by_address.key(new_login + '@' + APP_CONFIG[:domain]).each do |identity| - identity.destroy - end - put "http://api.lvh.me:3000/1/users/" + @user.id + '.json', :user => {:login => new_login}, :format => :json - assert last_response.successful? - # does not change login if no password_verifier is present - assert_equal original_login, @user.login - end - - test "upload pgp key" do - server_auth = @srp.authenticate(self) - key = FactoryGirl.build :pgp_key - put "http://api.lvh.me:3000/1/users/" + @user.id + '.json', :user => {:public_key => key}, :format => :json - assert_equal key, Identity.for(@user).keys[:pgp] - end - - # eventually probably want to remove most of this into a non-integration - # functional test - test "prevent uploading invalid key" do - server_auth = @srp.authenticate(self) - put "http://api.lvh.me:3000/1/users/" + @user.id + '.json', :user => {:public_key => :blah}, :format => :json - assert_nil Identity.for(@user).keys[:pgp] - end - - test "prevent emptying public key" do - server_auth = @srp.authenticate(self) - key = FactoryGirl.build :pgp_key - put "http://api.lvh.me:3000/1/users/" + @user.id + '.json', :user => {:public_key => key}, :format => :json - put "http://api.lvh.me:3000/1/users/" + @user.id + '.json', :user => {:public_key => ""}, :format => :json - assert_equal key, Identity.for(@user).keys[:pgp] - end - -end diff --git a/users/test/integration/api/login_test.rb b/users/test/integration/api/login_test.rb deleted file mode 100644 index fb761e5..0000000 --- a/users/test/integration/api/login_test.rb +++ /dev/null @@ -1,16 +0,0 @@ -require 'test_helper' -require_relative 'rack_test' - -class AccountFlowTest < RackTest - - setup do - @login = "integration_test_user" - end - - test "require json requests" do - put "http://api.lvh.me:3000/1/sessions/" + @login, - :client_auth => "This is not a valid login anyway" - assert_json_error login: I18n.t(:all_strategies_failed) - end - -end diff --git a/users/test/integration/api/python/flow_with_srp.py b/users/test/integration/api/python/flow_with_srp.py deleted file mode 100755 index 9fc168b..0000000 --- a/users/test/integration/api/python/flow_with_srp.py +++ /dev/null @@ -1,96 +0,0 @@ -#!/usr/bin/env python - -# under development - -import requests -import json -import string -import random -import srp._pysrp as srp -import binascii - -safe_unhexlify = lambda x: binascii.unhexlify(x) if (len(x) % 2 == 0) else binascii.unhexlify('0'+x) - -# using globals for now -# server = 'https://dev.bitmask.net/1' -server = 'http://api.lvh.me:3000/1' - -def run_tests(): - login = 'test_' + id_generator() - password = id_generator() + id_generator() - usr = srp.User( login, password, srp.SHA256, srp.NG_1024 ) - print_and_parse(signup(login, password)) - - auth = print_and_parse(authenticate(usr)) - verify_or_debug(auth, usr) - assert usr.authenticated() - - usr = change_password(auth['id'], login, auth['token']) - - auth = print_and_parse(authenticate(usr)) - verify_or_debug(auth, usr) - # At this point the authentication process is complete. - assert usr.authenticated() - -# let's have some random name -def id_generator(size=6, chars=string.ascii_lowercase + string.digits): - return ''.join(random.choice(chars) for x in range(size)) - -# log the server communication -def print_and_parse(response): - request = response.request - print request.method + ': ' + response.url - if hasattr(request, 'data'): - print " " + json.dumps(response.request.data) - print " -> " + response.text - try: - return json.loads(response.text) - except ValueError: - return None - -def signup(login, password): - salt, vkey = srp.create_salted_verification_key( login, password, srp.SHA256, srp.NG_1024 ) - user_params = { - 'user[login]': login, - 'user[password_verifier]': binascii.hexlify(vkey), - 'user[password_salt]': binascii.hexlify(salt) - } - return requests.post(server + '/users.json', data = user_params, verify = False) - -def change_password(user_id, login, token): - password = id_generator() + id_generator() - salt, vkey = srp.create_salted_verification_key( login, password, srp.SHA256, srp.NG_1024 ) - user_params = { - 'user[password_verifier]': binascii.hexlify(vkey), - 'user[password_salt]': binascii.hexlify(salt) - } - auth_headers = { 'Authorization': 'Token token="' + token + '"'} - print user_params - print_and_parse(requests.put(server + '/users/' + user_id + '.json', data = user_params, verify = False, headers = auth_headers)) - return srp.User( login, password, srp.SHA256, srp.NG_1024 ) - - -def authenticate(usr): - session = requests.session() - uname, A = usr.start_authentication() - params = { - 'login': uname, - 'A': binascii.hexlify(A) - } - init = print_and_parse(session.post(server + '/sessions', data = params, verify=False)) - M = usr.process_challenge( safe_unhexlify(init['salt']), safe_unhexlify(init['B']) ) - return session.put(server + '/sessions/' + uname, verify = False, - data = {'client_auth': binascii.hexlify(M)}) - -def verify_or_debug(auth, usr): - if ( 'errors' in auth ): - print ' u = "%x"' % usr.u - print ' x = "%x"' % usr.x - print ' v = "%x"' % usr.v - print ' S = "%x"' % usr.S - print ' K = "' + binascii.hexlify(usr.K) + '"' - print ' M = "' + binascii.hexlify(usr.M) + '"' - else: - usr.verify_session( safe_unhexlify(auth["M2"]) ) - -run_tests() diff --git a/users/test/integration/api/python/login_wrong_username.py b/users/test/integration/api/python/login_wrong_username.py deleted file mode 100755 index 390f250..0000000 --- a/users/test/integration/api/python/login_wrong_username.py +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env python - -server = 'http://localhost:3000' - -import requests -import json -import string -import random - -def id_generator(size=6, chars=string.ascii_uppercase + string.digits): - return ''.join(random.choice(chars) for x in range(size)) - -params = { - 'login': 'python_test_user_'+id_generator(), - 'A': '12345', - } -r = requests.post(server + '/sessions', data = params) -print r.url -print r.text diff --git a/users/test/integration/api/python/signup.py b/users/test/integration/api/python/signup.py deleted file mode 100755 index 0d3a4e0..0000000 --- a/users/test/integration/api/python/signup.py +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env python - -server = 'http://localhost:3000' - -import requests -import json -import string -import random - -def id_generator(size=6, chars=string.ascii_uppercase + string.digits): - return ''.join(random.choice(chars) for x in range(size)) - -user_params = { - 'user[login]': 'python_test_user_'+id_generator(), - 'user[password_verifier]': '12345', - 'user[password_salt]': '54321' - } -r = requests.post(server + '/users.json', data = user_params) -print r.url -print r.text diff --git a/users/test/integration/api/python/signup_and_login.py b/users/test/integration/api/python/signup_and_login.py deleted file mode 100755 index ac611d7..0000000 --- a/users/test/integration/api/python/signup_and_login.py +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env python - -# FAILS -# -# This test is currently failing for me because the session is not kept. -# Played with it a bunch - is probably messed up right now as well. - - -server = 'http://localhost:3000' - -import requests -import json -import string -import random - -def id_generator(size=6, chars=string.ascii_uppercase + string.digits): - return ''.join(random.choice(chars) for x in range(size)) - -def print_and_parse(response): - print response.request.method + ': ' + response.url - print " " + json.dumps(response.request.data) - print " -> " + response.text - return json.loads(response.text) - -def signup(session): - user_params = { - 'user[login]': id_generator(), - 'user[password_verifier]': '12345', - 'user[password_salt]': 'AB54321' - } - return session.post(server + '/users.json', data = user_params) - -def authenticate(session, login): - params = { - 'login': login, - 'A': '12345', - } - init = print_and_parse(session.post(server + '/sessions', data = params)) - return session.put(server + '/sessions/' + login, data = {'client_auth': '123'}) - -session = requests.session() -user = print_and_parse(signup(session)) -# SRP signup would happen here and calculate M hex -auth = print_and_parse(authenticate(session, user['login'])) diff --git a/users/test/integration/api/python/signup_and_login_wrong_password.py b/users/test/integration/api/python/signup_and_login_wrong_password.py deleted file mode 100755 index 9efffa1..0000000 --- a/users/test/integration/api/python/signup_and_login_wrong_password.py +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env python - -server = 'http://localhost:9292' - -import requests -import json -import string -import random - -def id_generator(size=6, chars=string.ascii_uppercase + string.digits): - return ''.join(random.choice(chars) for x in range(size)) - -def print_and_parse(response): - print response.request.method + ': ' + response.url - print " " + json.dumps(response.request.data) - print " -> " + response.text -# print " () " + json.dumps(requests.utils.dict_from_cookiejar(response.cookies)) - return json.loads(response.text) - -def signup(): - user_params = { - 'user[login]': id_generator(), - 'user[password_verifier]': '12345', - 'user[password_salt]': '54321' - } - return requests.post(server + '/users.json', data = user_params) - -def handshake(login): - params = { - 'login': login, - 'A': '12345', - } - return requests.post(server + '/sessions', data = params) - -def authenticate(login, M): - return requests.put(server + '/sessions/' + login, data = {'M': M}) - - -user = print_and_parse(signup()) -handshake = print_and_parse(handshake(user['login'])) -# SRP signup would happen here and calculate M hex -M = '123ABC' -auth = print_and_parse(authenticate(user['login'], M)) diff --git a/users/test/integration/api/python/umlauts.py b/users/test/integration/api/python/umlauts.py deleted file mode 100755 index 96fecbf..0000000 --- a/users/test/integration/api/python/umlauts.py +++ /dev/null @@ -1,79 +0,0 @@ -#!/usr/bin/env python -# coding: utf-8 - -# under development - -import requests -import json -import string -import random -import srp._pysrp as srp -import binascii - -safe_unhexlify = lambda x: binascii.unhexlify(x) if (len(x) % 2 == 0) else binascii.unhexlify('0'+x) - -# using globals for now -# server = 'https://dev.bitmask.net/1' -server = 'http://api.lvh.me:3000/1' - -def run_tests(): - login = 'test_' + id_generator() - password = id_generator() + "äöì" + id_generator() - usr = srp.User( login, password, srp.SHA256, srp.NG_1024 ) - print_and_parse(signup(login, password)) - - auth = print_and_parse(authenticate(usr)) - verify_or_debug(auth, usr) - assert usr.authenticated() - - -# let's have some random name -def id_generator(size=6, chars=string.ascii_lowercase + string.digits): - return ''.join(random.choice(chars) for x in range(size)) - -# log the server communication -def print_and_parse(response): - request = response.request - print request.method + ': ' + response.url - if hasattr(request, 'data'): - print " " + json.dumps(response.request.data) - print " -> " + response.text - try: - return json.loads(response.text) - except ValueError: - return None - -def signup(login, password): - salt, vkey = srp.create_salted_verification_key( login, password, srp.SHA256, srp.NG_1024 ) - user_params = { - 'user[login]': login, - 'user[password_verifier]': binascii.hexlify(vkey), - 'user[password_salt]': binascii.hexlify(salt) - } - print json.dumps(user_params) - return requests.post(server + '/users.json', data = user_params, verify = False) - -def authenticate(usr): - session = requests.session() - uname, A = usr.start_authentication() - params = { - 'login': uname, - 'A': binascii.hexlify(A) - } - init = print_and_parse(session.post(server + '/sessions', data = params, verify=False)) - M = usr.process_challenge( safe_unhexlify(init['salt']), safe_unhexlify(init['B']) ) - return session.put(server + '/sessions/' + uname, verify = False, - data = {'client_auth': binascii.hexlify(M)}) - -def verify_or_debug(auth, usr): - if ( 'errors' in auth ): - print ' u = "%x"' % usr.u - print ' x = "%x"' % usr.x - print ' v = "%x"' % usr.v - print ' S = "%x"' % usr.S - print ' K = "' + binascii.hexlify(usr.K) + '"' - print ' M = "' + binascii.hexlify(usr.M) + '"' - else: - usr.verify_session( safe_unhexlify(auth["M2"]) ) - -run_tests() diff --git a/users/test/integration/api/rack_test.rb b/users/test/integration/api/rack_test.rb deleted file mode 100644 index 9a69f52..0000000 --- a/users/test/integration/api/rack_test.rb +++ /dev/null @@ -1,9 +0,0 @@ -class RackTest < ActiveSupport::TestCase - include Rack::Test::Methods - include Warden::Test::Helpers - include LeapWebCore::AssertResponses - - def app - OUTER_APP - end -end diff --git a/users/test/integration/browser/account_test.rb b/users/test/integration/browser/account_test.rb deleted file mode 100644 index a5677ad..0000000 --- a/users/test/integration/browser/account_test.rb +++ /dev/null @@ -1,147 +0,0 @@ -require 'test_helper' - -class AccountTest < BrowserIntegrationTest - - teardown do - Identity.destroy_all_disabled - end - - test "normal account workflow" do - username, password = submit_signup - assert page.has_content?("Welcome #{username}") - click_on 'Logout' - assert page.has_content?("Log In") - assert_equal '/', current_path - assert user = User.find_by_login(username) - user.account.destroy - end - - test "successful login" do - username, password = submit_signup - click_on 'Logout' - attempt_login(username, password) - assert page.has_content?("Welcome #{username}") - within('.sidenav li.active') do - assert page.has_content?("Overview") - end - User.find_by_login(username).account.destroy - end - - test "failed login" do - visit '/' - attempt_login("username", "wrong password") - assert_invalid_login(page) - end - - test "account destruction" do - username, password = submit_signup - click_on I18n.t('account_settings') - click_on I18n.t('destroy_my_account') - assert page.has_content?(I18n.t('account_destroyed')) - attempt_login(username, password) - assert_invalid_login(page) - end - - test "handle blocked after account destruction" do - username, password = submit_signup - click_on I18n.t('account_settings') - click_on I18n.t('destroy_my_account') - submit_signup(username) - assert page.has_content?('has already been taken') - end - - test "default user actions" do - username, password = submit_signup - click_on "Account Settings" - assert page.has_content? I18n.t('destroy_my_account') - assert page.has_no_css? '#update_login_and_password' - assert page.has_no_css? '#update_pgp_key' - end - - test "default admin actions" do - username, password = submit_signup - with_config admins: [username] do - click_on "Account Settings" - assert page.has_content? I18n.t('destroy_my_account') - assert page.has_no_css? '#update_login_and_password' - assert page.has_css? '#update_pgp_key' - end - end - - test "change password" do - with_config user_actions: ['change_password'] do - username, password = submit_signup - click_on "Account Settings" - within('#update_login_and_password') do - fill_in 'Password', with: "other password" - fill_in 'Password confirmation', with: "other password" - click_on 'Save' - end - click_on 'Logout' - attempt_login(username, "other password") - assert page.has_content?("Welcome #{username}") - User.find_by_login(username).account.destroy - end - end - - test "change pgp key" do - with_config user_actions: ['change_pgp_key'] do - pgp_key = FactoryGirl.build :pgp_key - username, password = submit_signup - click_on "Account Settings" - within('#update_pgp_key') do - fill_in 'Public key', with: pgp_key - click_on 'Save' - end - page.assert_selector 'input[value="Saving..."]' - # at some point we're done: - page.assert_no_selector 'input[value="Saving..."]' - assert page.has_field? 'Public key', with: pgp_key.to_s - user = User.find_by_login(username) - assert_equal pgp_key, user.public_key - user.account.destroy - end - end - - - # trying to seed an invalid A for srp login - test "detects attempt to circumvent SRP" do - user = FactoryGirl.create :user - visit '/login' - fill_in 'Username', with: user.login - fill_in 'Password', with: "password" - inject_malicious_js - click_on 'Log In' - assert page.has_content?("Invalid random key") - assert page.has_no_content?("Welcome") - user.destroy - end - - test "reports internal server errors" do - V1::UsersController.any_instance.stubs(:create).raises - submit_signup - assert page.has_content?("server failed") - end - - def attempt_login(username, password) - click_on 'Log In' - fill_in 'Username', with: username - fill_in 'Password', with: password - click_on 'Log In' - end - - def assert_invalid_login(page) - assert page.has_selector? 'input.btn-primary.disabled' - assert page.has_content? I18n.t(:invalid_user_pass) - assert page.has_no_selector? 'input.btn-primary.disabled' - end - - def inject_malicious_js - page.execute_script <<-EOJS - var calc = new srp.Calculate(); - calc.A = function(_a) {return "00";}; - calc.S = calc.A; - srp.session = new srp.Session(null, calc); - EOJS - end -end diff --git a/users/test/integration/browser/session_test.rb b/users/test/integration/browser/session_test.rb deleted file mode 100644 index 3a41b3a..0000000 --- a/users/test/integration/browser/session_test.rb +++ /dev/null @@ -1,27 +0,0 @@ -require 'test_helper' - -class SessionTest < BrowserIntegrationTest - - setup do - @username, password = submit_signup - end - - teardown do - user = User.find_by_login(@username) - id = user.identity - id.destroy - user.destroy - end - - test "valid session" do - assert page.has_content?("Welcome #{@username}") - end - - test "expired session" do - assert page.has_content?("Welcome #{@username}") - pretend_now_is(Time.now + 40.minutes) do - visit '/' - assert page.has_no_content?("Welcome #{@username}") - end - end -end diff --git a/users/test/integration/navigation_test.rb b/users/test/integration/navigation_test.rb deleted file mode 100644 index eec8c0e..0000000 --- a/users/test/integration/navigation_test.rb +++ /dev/null @@ -1,9 +0,0 @@ -require 'test_helper' - -class NavigationTest < ActionDispatch::IntegrationTest - - # test "the truth" do - # assert true - # end -end - diff --git a/users/test/leap_web_users_test.rb b/users/test/leap_web_users_test.rb deleted file mode 100644 index f142e54..0000000 --- a/users/test/leap_web_users_test.rb +++ /dev/null @@ -1,7 +0,0 @@ -require 'test_helper' - -class LeapWebUsersTest < ActiveSupport::TestCase - test "module exists" do - assert_kind_of Module, LeapWebUsers - end -end diff --git a/users/test/support/auth_test_helper.rb b/users/test/support/auth_test_helper.rb deleted file mode 100644 index 57f9f9b..0000000 --- a/users/test/support/auth_test_helper.rb +++ /dev/null @@ -1,65 +0,0 @@ -module AuthTestHelper - extend ActiveSupport::Concern - - # Controller will fetch current user from warden. - # Make it pick up our current_user - included do - setup do - request.env['warden'] ||= stub :user => nil - end - end - - def login(user_or_method_hash = {}) - if user_or_method_hash.respond_to?(:reverse_merge) - user_or_method_hash.reverse_merge! :is_admin? => false - end - @current_user = stub_record(:user, user_or_method_hash) - request.env['warden'] = stub :user => @current_user - request.env['HTTP_AUTHORIZATION'] = header_for_token_auth - return @current_user - end - - def assert_access_denied(denied = true, logged_in = true) - if denied - if @response.content_type == 'application/json' - assert_json_response('error' => I18n.t(:not_authorized)) - assert_response :unprocessable_entity - else - if logged_in - assert_equal({:alert => I18n.t(:not_authorized)}, flash.to_hash) - assert_redirected_to home_url - else - assert_equal({:alert => I18n.t(:not_authorized_login)}, flash.to_hash) - assert_redirected_to login_url - end - end - else - assert flash[:alert].blank? - end - end - - def expect_logout - expect_warden_logout - @token.expects(:destroy) if @token - end - - protected - - def header_for_token_auth - @token = find_record(:token, :authenticate => @current_user) - ActionController::HttpAuthentication::Token.encode_credentials @token.id - end - - def expect_warden_logout - raw = mock('raw session') do - expects(:inspect) - end - request.env['warden'].expects(:raw_session).returns(raw) - request.env['warden'].expects(:logout) - end - -end - -class ActionController::TestCase - include AuthTestHelper -end diff --git a/users/test/support/integration_test_helper.rb b/users/test/support/integration_test_helper.rb deleted file mode 100644 index 51e47c6..0000000 --- a/users/test/support/integration_test_helper.rb +++ /dev/null @@ -1,12 +0,0 @@ -module IntegrationTestHelper - def submit_signup(username = nil, password = nil) - username ||= "test_#{SecureRandom.urlsafe_base64}".downcase - password ||= SecureRandom.base64 - visit '/users/new' - fill_in 'Username', with: username - fill_in 'Password', with: password - fill_in 'Password confirmation', with: password - click_on 'Sign Up' - return username, password - end -end diff --git a/users/test/support/stub_record_helper.rb b/users/test/support/stub_record_helper.rb deleted file mode 100644 index 25138a0..0000000 --- a/users/test/support/stub_record_helper.rb +++ /dev/null @@ -1,53 +0,0 @@ -module StubRecordHelper - - # - # We will stub find when called on the records class and - # return the record given. - # - # If no record is given but a hash or nil will create a stub based on - # that instead and returns the stub. - # - def find_record(factory, record_or_attribs_hash = {}) - record = stub_record factory, record_or_attribs_hash, true - klass = record.class - # find is just an alias for get with CouchRest Model - klass.stubs(:get).with(record.to_param.to_s).returns(record) - klass.stubs(:find).with(record.to_param.to_s).returns(record) - return record - end - - # Create a stub that has the usual functions of a database record. - # It won't fail on rendering a form for example. - # - # If the second parameter is a record we return the record itself. - # This way you can build functions that either take a record or a - # method hash to stub from. See find_record for an example. - def stub_record(factory, record_or_method_hash = {}, persisted=false) - if record_or_method_hash && !record_or_method_hash.is_a?(Hash) - return record_or_method_hash - end - FactoryGirl.build_stubbed(factory).tap do |record| - if persisted or record.persisted? - record_or_method_hash.reverse_merge! :created_at => Time.now, - :updated_at => Time.now, :id => Random.rand(100000).to_s - end - record.stubs(record_or_method_hash) if record_or_method_hash.present? - end - end - - # returns deep stringified attributes so they can be compared to - # what the controller receives as params - def record_attributes_for(factory, attribs_hash = nil) - FactoryGirl.attributes_for(factory, attribs_hash).tap do |attribs| - attribs.keys.each do |key| - val = attribs.delete(key) - attribs[key.to_s] = val.is_a?(Hash) ? val.stringify_keys! : val - end - end - end - -end - -class ActionController::TestCase - include StubRecordHelper -end diff --git a/users/test/support/time_test_helper.rb b/users/test/support/time_test_helper.rb deleted file mode 100644 index f673f12..0000000 --- a/users/test/support/time_test_helper.rb +++ /dev/null @@ -1,30 +0,0 @@ -# Extend the Time class so that we can offset the time that 'now' -# returns. This should allow us to effectively time warp for functional -# tests that require limits per hour, what not. -class Time #:nodoc: - class <<self - attr_accessor :testing_offset - - def now_with_testing_offset - now_without_testing_offset - testing_offset - end - alias_method_chain :now, :testing_offset - end -end -Time.testing_offset = 0 - -module TimeTestHelper - # Time warp to the specified time for the duration of the passed block - def pretend_now_is(time) - begin - Time.testing_offset = Time.now - time - yield - ensure - Time.testing_offset = 0 - end - end -end - -class ActiveSupport::TestCase - include TimeTestHelper -end diff --git a/users/test/test_helper.rb b/users/test/test_helper.rb deleted file mode 100644 index 52dff53..0000000 --- a/users/test/test_helper.rb +++ /dev/null @@ -1,9 +0,0 @@ -ENV["RAILS_ENV"] = "test" -require File.expand_path('../../../test/dummy/config/environment', __FILE__) -require 'rails/test_help' -require 'mocha/setup' - -Rails.backtrace_cleaner.remove_silencers! - -# Load support files -Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f } diff --git a/users/test/unit/.gitkeep b/users/test/unit/.gitkeep deleted file mode 100644 index e69de29..0000000 --- a/users/test/unit/.gitkeep +++ /dev/null diff --git a/users/test/unit/account_test.rb b/users/test/unit/account_test.rb deleted file mode 100644 index 4fb3c3d..0000000 --- a/users/test/unit/account_test.rb +++ /dev/null @@ -1,47 +0,0 @@ -require 'test_helper' - -class AccountTest < ActiveSupport::TestCase - - teardown do - Identity.destroy_all_disabled - end - - test "create a new account" do - user = Account.create(FactoryGirl.attributes_for(:user)) - assert user.valid? - assert user.persisted? - assert id = user.identity - assert_equal user.email_address, id.address - assert_equal user.email_address, id.destination - user.account.destroy - end - - test "create and remove a user account" do - # We keep an identity that will block the handle from being reused. - assert_difference "Identity.count" do - assert_no_difference "User.count" do - user = Account.create(FactoryGirl.attributes_for(:user)) - user.account.destroy - end - end - end - - test "change username and create alias" do - user = Account.create(FactoryGirl.attributes_for(:user)) - old_id = user.identity - old_email = user.email_address - user.account.update(FactoryGirl.attributes_for(:user)) - user.reload - old_id.reload - assert user.valid? - assert user.persisted? - assert id = user.identity - assert id.persisted? - assert_equal user.email_address, id.address - assert_equal user.email_address, id.destination - assert_equal user.email_address, old_id.destination - assert_equal old_email, old_id.address - user.account.destroy - end - -end diff --git a/users/test/unit/email_test.rb b/users/test/unit/email_test.rb deleted file mode 100644 index 7cfbc84..0000000 --- a/users/test/unit/email_test.rb +++ /dev/null @@ -1,19 +0,0 @@ -require 'test_helper' - -class EmailTest < ActiveSupport::TestCase - - test "valid format" do - email = Email.new(email_string) - assert email.valid? - end - - test "validates format" do - email = Email.new("email") - assert !email.valid? - assert_equal ["needs to be a valid email address"], email.errors[:email] - end - - def email_string - @email_string ||= Faker::Internet.email - end -end diff --git a/users/test/unit/helpers/session_helper_test.rb b/users/test/unit/helpers/session_helper_test.rb deleted file mode 100644 index 2824733..0000000 --- a/users/test/unit/helpers/session_helper_test.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'test_helper' - -class SessionHelperTest < ActionView::TestCase -end diff --git a/users/test/unit/helpers/users_helper_test.rb b/users/test/unit/helpers/users_helper_test.rb deleted file mode 100644 index 96af37a..0000000 --- a/users/test/unit/helpers/users_helper_test.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'test_helper' - -class UsersHelperTest < ActionView::TestCase -end diff --git a/users/test/unit/identity_test.rb b/users/test/unit/identity_test.rb deleted file mode 100644 index eca104f..0000000 --- a/users/test/unit/identity_test.rb +++ /dev/null @@ -1,133 +0,0 @@ -require 'test_helper' - -class IdentityTest < ActiveSupport::TestCase - include StubRecordHelper - - setup do - @user = find_record :user - end - - test "initial identity for a user" do - id = Identity.for(@user) - assert_equal @user.email_address, id.address - assert_equal @user.email_address, id.destination - assert_equal @user, id.user - end - - test "add alias" do - id = Identity.for @user, address: alias_name - assert_equal LocalEmail.new(alias_name), id.address - assert_equal @user.email_address, id.destination - assert_equal @user, id.user - end - - test "add forward" do - id = Identity.for @user, destination: forward_address - assert_equal @user.email_address, id.address - assert_equal Email.new(forward_address), id.destination - assert_equal @user, id.user - end - - test "forward alias" do - id = Identity.for @user, address: alias_name, destination: forward_address - assert_equal LocalEmail.new(alias_name), id.address - assert_equal Email.new(forward_address), id.destination - assert_equal @user, id.user - end - - test "prevents duplicates" do - id = Identity.create_for @user, address: alias_name, destination: forward_address - dup = Identity.build_for @user, address: alias_name, destination: forward_address - assert !dup.valid? - assert_equal ["This alias already exists"], dup.errors[:base] - id.destroy - end - - test "validates availability" do - other_user = find_record :user - id = Identity.create_for @user, address: alias_name, destination: forward_address - taken = Identity.build_for other_user, address: alias_name - assert !taken.valid? - assert_equal ["This email has already been taken"], taken.errors[:base] - id.destroy - end - - test "setting and getting pgp key" do - id = Identity.for(@user) - id.set_key(:pgp, pgp_key_string) - assert_equal pgp_key_string, id.keys[:pgp] - end - - test "querying pgp key via couch" do - id = Identity.for(@user) - id.set_key(:pgp, pgp_key_string) - id.save - view = Identity.pgp_key_by_email.key(id.address) - assert_equal 1, view.rows.count - assert result = view.rows.first - assert_equal id.address, result["key"] - assert_equal id.keys[:pgp], result["value"] - id.destroy - end - - test "fail to add non-local email address as identity address" do - id = Identity.for @user, address: forward_address - assert !id.valid? - assert_match /needs to end in/, id.errors[:address].first - end - - test "alias must meet same conditions as login" do - id = Identity.create_for @user, address: alias_name.capitalize - assert !id.valid? - #hacky way to do this, but okay for now: - assert id.errors.messages.flatten(2).include? "Must begin with a lowercase letter" - assert id.errors.messages.flatten(2).include? "Only lowercase letters, digits, . - and _ allowed." - end - - test "destination must be valid email address" do - id = Identity.create_for @user, address: @user.email_address, destination: 'ASKJDLFJD' - assert !id.valid? - assert id.errors.messages[:destination].include? "needs to be a valid email address" - end - - test "disabled identity" do - id = Identity.for(@user) - id.disable - assert_equal @user.email_address, id.address - assert_equal nil, id.destination - assert_equal nil, id.user - assert !id.enabled? - assert id.valid? - end - - test "disabled identity blocks handle" do - id = Identity.for(@user) - id.disable - id.save - other_user = find_record :user - taken = Identity.build_for other_user, address: id.address - assert !taken.valid? - Identity.destroy_all_disabled - end - - test "destroy all disabled identities" do - id = Identity.for(@user) - id.disable - id.save - assert Identity.count > 0 - Identity.destroy_all_disabled - assert_equal 0, Identity.disabled.count - end - - def alias_name - @alias_name ||= Faker::Internet.user_name - end - - def forward_address - @forward_address ||= Faker::Internet.email - end - - def pgp_key_string - @pgp_key ||= "DUMMY PGP KEY ... "+SecureRandom.base64(4096) - end -end diff --git a/users/test/unit/local_email_test.rb b/users/test/unit/local_email_test.rb deleted file mode 100644 index 20ee7f1..0000000 --- a/users/test/unit/local_email_test.rb +++ /dev/null @@ -1,65 +0,0 @@ -require 'test_helper' - -class LocalEmailTest < ActiveSupport::TestCase - - test "appends domain" do - local = LocalEmail.new(handle) - assert_equal LocalEmail.new(email), local - assert local.valid? - end - - test "returns handle" do - local = LocalEmail.new(email) - assert_equal handle, local.handle - end - - test "prints full email" do - local = LocalEmail.new(handle) - assert_equal email, "#{local}" - end - - test "validates domain" do - local = LocalEmail.new(Faker::Internet.email) - assert !local.valid? - assert_equal ["needs to end in @#{LocalEmail.domain}"], local.errors[:email] - end - - test "blacklists rfc2142" do - black_listed = LocalEmail.new('hostmaster') - assert !black_listed.valid? - end - - test "blacklists etc passwd" do - black_listed = LocalEmail.new('nobody') - assert !black_listed.valid? - end - - test "whitelist overwrites automatic blacklists" do - with_config handle_whitelist: ['nobody', 'hostmaster'] do - white_listed = LocalEmail.new('nobody') - assert white_listed.valid? - white_listed = LocalEmail.new('hostmaster') - assert white_listed.valid? - end - end - - test "blacklists from config" do - black_listed = LocalEmail.new('www-data') - assert !black_listed.valid? - end - - test "blacklist from config overwrites whitelist" do - with_config handle_whitelist: ['www-data'] do - black_listed = LocalEmail.new('www-data') - assert !black_listed.valid? - end - end - - def handle - @handle ||= Faker::Internet.user_name - end - - def email - handle + "@" + APP_CONFIG[:domain] - end -end diff --git a/users/test/unit/token_test.rb b/users/test/unit/token_test.rb deleted file mode 100644 index 6c9f209..0000000 --- a/users/test/unit/token_test.rb +++ /dev/null @@ -1,83 +0,0 @@ -require 'test_helper' - -class ClientCertificateTest < ActiveSupport::TestCase - include StubRecordHelper - - setup do - @user = find_record :user - end - - test "new token for user" do - sample = Token.new(:user_id => @user.id) - assert sample.valid? - assert_equal @user.id, sample.user_id - assert_equal @user, sample.authenticate - end - - test "token id is secure" do - sample = Token.new(:user_id => @user.id) - other = Token.new(:user_id => @user.id) - assert sample.id, - "id is set on initialization" - assert sample.id[0..10] != other.id[0..10], - "token id prefixes should not repeat" - assert /[g-zG-Z]/.match(sample.id), - "should use non hex chars in the token id" - assert sample.id.size > 16, - "token id should be more than 16 chars long" - end - - test "token checks for user" do - sample = Token.new - assert !sample.valid?, "Token should require a user record" - end - - test "token updates timestamps" do - sample = Token.new(user_id: @user.id) - sample.last_seen_at = 1.minute.ago - sample.expects(:save) - assert_equal @user, sample.authenticate - assert Time.now - sample.last_seen_at < 1.minute, "last_seen_at has not been updated" - end - - test "token will not expire if token_expires_after is not set" do - sample = Token.new(user_id: @user.id) - sample.last_seen_at = 2.years.ago - with_config auth: {} do - sample.expects(:save) - assert_equal @user, sample.authenticate - end - end - - test "expired token returns nil on authenticate" do - sample = Token.new(user_id: @user.id) - sample.last_seen_at = 2.hours.ago - with_config auth: {token_expires_after: 60} do - sample.expects(:destroy) - assert_nil sample.authenticate - end - end - - test "Token.destroy_all_expired is noop if no expiry is set" do - expired = FactoryGirl.create :token, last_seen_at: 2.hours.ago - with_config auth: {} do - Token.destroy_all_expired - end - assert_equal expired, Token.find(expired.id) - end - - test "Token.destroy_all_expired cleans up expired tokens only" do - expired = FactoryGirl.create :token, last_seen_at: 2.hours.ago - fresh = FactoryGirl.create :token - with_config auth: {token_expires_after: 60} do - Token.destroy_all_expired - end - assert_nil Token.find(expired.id) - assert_equal fresh, Token.find(fresh.id) - fresh.destroy - end - - - - -end diff --git a/users/test/unit/unauthorized_user_test.rb b/users/test/unit/unauthorized_user_test.rb deleted file mode 100644 index 5b96ae1..0000000 --- a/users/test/unit/unauthorized_user_test.rb +++ /dev/null @@ -1,7 +0,0 @@ -require 'test_helper' - -class UnauthorizedUserTest < ActiveSupport::TestCase - # test "the truth" do - # assert true - # end -end diff --git a/users/test/unit/user_test.rb b/users/test/unit/user_test.rb deleted file mode 100644 index ffbb7d8..0000000 --- a/users/test/unit/user_test.rb +++ /dev/null @@ -1,68 +0,0 @@ -require 'test_helper' - -class UserTest < ActiveSupport::TestCase - - include SRP::Util - setup do - @user = FactoryGirl.build(:user) - end - - test "design docs in database are authorative" do - assert !User.design_doc.auto_update, - "Automatic update of design docs should be disabled" - end - - test "test set of attributes should be valid" do - @user.valid? - assert_equal Hash.new, @user.errors.messages - end - - test "test require hex for password_verifier" do - @user.password_verifier = "QWER" - assert !@user.valid? - end - - test "test require alphanumerical for login" do - @user.login = "qw#r" - assert !@user.valid? - end - - test "verifier returns number for the hex in password_verifier" do - assert_equal @user.password_verifier.hex, @user.verifier - end - - test "salt returns number for the hex in password_salt" do - assert_equal @user.password_salt.hex, @user.salt - end - - test 'normal user is no admin' do - assert !@user.is_admin? - end - - test 'user with login in APP_CONFIG is an admin' do - admin_login = APP_CONFIG['admins'].first - @user.login = admin_login - assert @user.is_admin? - end - - test "login needs to be unique" do - other_user = FactoryGirl.create :user, login: @user.login - assert !@user.valid? - other_user.destroy - end - - test "login needs to be unique amongst aliases" do - other_user = FactoryGirl.create :user - id = Identity.create_for other_user, address: @user.login - assert !@user.valid? - id.destroy - other_user.destroy - end - - test "deprecated public key api still works" do - key = SecureRandom.base64(4096) - @user.public_key = key - assert_equal key, @user.public_key - end - -end diff --git a/users/test/unit/warden_strategy_secure_remote_password_test.rb b/users/test/unit/warden_strategy_secure_remote_password_test.rb deleted file mode 100644 index e6fcfbe..0000000 --- a/users/test/unit/warden_strategy_secure_remote_password_test.rb +++ /dev/null @@ -1,63 +0,0 @@ -class WardenStrategySecureRemotePasswordTest < ActiveSupport::TestCase - -# TODO : turn this into sth. real -=begin - setup do - @user = stub :login => "me", :id => 123 - @client_hex = 'a123' - @client_rnd = @client_hex.hex - @server_hex = 'b123' - @server_rnd = @server_hex.hex - @server_rnd_exp = 'e123'.hex - @salt = 'stub user salt' - @server_handshake = stub :aa => @client_rnd, :bb => @server_rnd, :b => @server_rnd_exp - @server_auth = 'adfe' - end - - - test "should perform handshake" do - @user.expects(:initialize_auth). - with(@client_rnd). - returns(@server_handshake) - @server_handshake.expects(:to_json). - returns({'B' => @server_hex, 'salt' => @salt}.to_json) - User.expects(:find).with(@user.login).returns(@user) - assert_equal @server_handshake, session[:handshake] - assert_response :success - assert_json_response :B => @server_hex, :salt => @salt - end - - test "should report user not found" do - unknown = "login_that_does_not_exist" - User.expects(:find).with(unknown).raises(RECORD_NOT_FOUND) - post :create, :login => unknown - assert_response :success - assert_json_error "login" => ["unknown user"] - end - - test "should authorize" do - session[:handshake] = @server_handshake - @server_handshake.expects(:authenticate!). - with(@client_rnd). - returns(@user) - @server_handshake.expects(:to_json). - returns({:M2 => @server_auth}.to_json) - post :update, :id => @user.login, :client_auth => @client_hex - assert_nil session[:handshake] - assert_json_response :M2 => @server_auth - assert_equal @user.id, session[:user_id] - end - - test "should report wrong password" do - session[:handshake] = @server_handshake - @server_handshake.expects(:authenticate!). - with(@client_rnd). - raises(WRONG_PASSWORD) - post :update, :id => @user.login, :client_auth => @client_hex - assert_nil session[:handshake] - assert_nil session[:user_id] - assert_json_error "password" => ["wrong password"] - end - -=end -end diff --git a/users/test/unit/webfinger/host_meta_presenter_test.rb b/users/test/unit/webfinger/host_meta_presenter_test.rb deleted file mode 100644 index af86404..0000000 --- a/users/test/unit/webfinger/host_meta_presenter_test.rb +++ /dev/null @@ -1,24 +0,0 @@ -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 deleted file mode 100644 index 04aeb22..0000000 --- a/users/test/unit/webfinger/user_presenter_test.rb +++ /dev/null @@ -1,49 +0,0 @@ -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 |