summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Gemfile3
-rw-r--r--INSTALL.md52
-rw-r--r--TROUBLESHOOT.md46
-rw-r--r--certs/app/controllers/certs_controller.rb11
-rw-r--r--certs/app/models/client_certificate.rb18
-rw-r--r--certs/test/functional/certs_controller_test.rb37
-rw-r--r--certs/test/unit/client_certificate_test.rb23
-rw-r--r--config/defaults.yml3
-rw-r--r--core/test/support/with_config_helper.rb16
-rw-r--r--help/app/models/ticket.rb2
-rw-r--r--users/app/assets/javascripts/users.js.coffee4
-rw-r--r--users/app/controllers/users_controller.rb8
-rw-r--r--users/app/models/user.rb14
-rw-r--r--users/app/views/users/_cancel_account.html.haml9
-rw-r--r--users/app/views/users/_login_and_password_fields.html.haml2
-rw-r--r--users/app/views/users/_password_fields.html.haml2
-rw-r--r--users/app/views/users/edit.html.haml25
-rw-r--r--users/config/locales/en.yml7
-rw-r--r--users/test/functional/users_controller_test.rb13
19 files changed, 230 insertions, 65 deletions
diff --git a/Gemfile b/Gemfile
index 4bf0f3b..56cbf62 100644
--- a/Gemfile
+++ b/Gemfile
@@ -13,7 +13,8 @@ gem 'leap_web_help', :path => 'help'
# To use debugger
gem 'debugger', :platforms => :mri_19
-gem 'ruby-debug', :platforms => :mri_18
+# ruby 1.8 is not supported anymore
+# gem 'ruby-debug', :platforms => :mri_18
# unreleased so far ... but leap_web_certs need it
diff --git a/INSTALL.md b/INSTALL.md
index 9e93eb0..7e95b76 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -1,5 +1,23 @@
# Installation #
+Please see TROUBLESHOOT.md if you run into any issues during install.
+
+## TL;DR ##
+
+Install git, ruby 1.9, rubygems and couchdb on your system. Then run
+
+```
+gem install bundler
+git clone git://github.com/leapcode/leap_web.git
+cd leap_web
+git submodule init
+git submodule update
+bundle install --binstubs
+bin/rails server
+```
+
+You will find Leap Web running on `localhost:3000`. Check out the Cert Distribution section below for setting up the cert and server config.
+
## Requirements ##
The webapp only depends on very basic ruby packages and installs the other requirements as gems through bundler.
@@ -9,17 +27,31 @@ The webapp only depends on very basic ruby packages and installs the other requi
The following packages need to be installed:
* git
-* ruby (1.8.7 and 1.9.3 work)
+* ruby1.9.3
* rubygems
* couchdb
+### Code ###
+
+Simply clone the git repository:
+
+```
+ git clone git://github.com/leapcode/leap_web.git
+ cd leap_web
+```
+
### Gems ###
-We install most gems we depend upon through [bundler](http://gembundler.com). However the bundler gem needs to be installed and the `bundle` command needs to be available to the user used for deploy.
+We install most gems we depend upon through [bundler](http://gembundler.com). First install bundler
-### Bundler ###
+```
+ gem install bundler
+```
-Run `bundle install` to install all the required gems.
+Then install all the required gems:
+```
+ bundle install --binstubs
+```
## Setup ##
@@ -32,13 +64,15 @@ We currently use a git submodule to include srp-js. This will soon be replaced b
git submodule update
```
-### Cert Distribution ###
-
-The Webapp can hand out certs for the EIP client. These certs are either picked from a pool in CouchDB or from a file. For now you can either run [Leap CA](http://github.com/leapcode/leap_ca) to fill the pool or you can put your certs file in config/cert.
+### Provider Information ###
-We also ship provider information through the webapp. For now please add your eip-service.json to the public/config directory.
+The leap client fetches provider information via json files from the server.
+If you want to use that functionality please add your provider files the public/config directory.
## Running ##
-Run `rails server`, `bundle exec rails server` or whatever rack server you prefer.
+```
+bin/rails server
+```
+You'll find Leap Web running on `localhost:3000`
diff --git a/TROUBLESHOOT.md b/TROUBLESHOOT.md
new file mode 100644
index 0000000..f3db006
--- /dev/null
+++ b/TROUBLESHOOT.md
@@ -0,0 +1,46 @@
+# Troubleshooting #
+
+Here are some less common issues you might run into when installing Leap Web.
+
+## Cannot find Bundler ##
+
+### Error Messages ###
+
+`bundle: command not found`
+
+### Solution ###
+
+Make sure bundler is installed. `gem list bundler` should list `bundler`.
+You also need to be able to access the `bundler` executable in your PATH.
+
+## Outdated version of rubygems ##
+
+### Error Messages ###
+
+`bundler requires rubygems >= 1.3.6`
+
+### Solution ###
+
+`gem update --system` will install the latest rubygems
+
+## Missing development tools ##
+
+Some required gems will compile C extensions. They need a bunch of utils for this.
+
+### Error Messages ###
+
+`make: Command not found`
+
+### Solution ###
+
+Install the required tools. For linux the `build-essential` package provides most of them. For Mac OS you probably want the XCode Commandline tools.
+
+## Missing libraries and headers ##
+
+Some gem dependencies might not compile because they lack the needed c libraries.
+
+### Solution ###
+
+Install the libraries in question including their development files.
+
+
diff --git a/certs/app/controllers/certs_controller.rb b/certs/app/controllers/certs_controller.rb
index 6db270c..977e03e 100644
--- a/certs/app/controllers/certs_controller.rb
+++ b/certs/app/controllers/certs_controller.rb
@@ -1,11 +1,16 @@
class CertsController < ApplicationController
- before_filter :authorize
+ before_filter :logged_in_or_free_certs
# GET /cert
def show
- @cert = ClientCertificate.new
- render :text => @cert.key + @cert.cert, :content_type => 'text/plain'
+ @cert = ClientCertificate.new(free: !logged_in?)
+ render text: @cert.to_s, content_type: 'text/plain'
end
+ protected
+
+ def logged_in_or_free_certs
+ authorize unless APP_CONFIG[:free_certs_enabled]
+ end
end
diff --git a/certs/app/models/client_certificate.rb b/certs/app/models/client_certificate.rb
index be0ac63..13e0318 100644
--- a/certs/app/models/client_certificate.rb
+++ b/certs/app/models/client_certificate.rb
@@ -1,5 +1,5 @@
#
-# Model for certificates stored in CouchDB.
+# Model for certificates
#
# This file must be loaded after Config has been loaded.
#
@@ -17,11 +17,11 @@ class ClientCertificate
#
# generate the private key and client certificate
#
- def initialize
+ def initialize(options = {})
cert = CertificateAuthority::Certificate.new
# set subject
- cert.subject.common_name = random_common_name
+ cert.subject.common_name = common_name(options[:free])
# set expiration
cert.not_before = yesterday
@@ -35,8 +35,12 @@ class ClientCertificate
cert.parent = ClientCertificate.root_ca
cert.sign! client_signing_profile
- self.key = cert.key_material.private_key.to_pem
- self.cert = cert.to_pem
+ self.key = cert.key_material.private_key
+ self.cert = cert
+ end
+
+ def to_s
+ self.key.to_pem + self.cert.to_pem
end
private
@@ -61,6 +65,10 @@ class ClientCertificate
Digest::MD5.hexdigest("#{rand(10**10)} -- #{Time.now}").to_i(16)
end
+ def common_name(for_free_cert = false)
+ (for_free_cert ? APP_CONFIG[:free_cert_prefix] : '') + random_common_name
+ end
+
#
# for the random common name, we need a text string that will be unique across all certs.
# ruby 1.8 doesn't have a built-in uuid generator, or we would use SecureRandom.uuid
diff --git a/certs/test/functional/certs_controller_test.rb b/certs/test/functional/certs_controller_test.rb
index 75256ca..7826dd6 100644
--- a/certs/test/functional/certs_controller_test.rb
+++ b/certs/test/functional/certs_controller_test.rb
@@ -1,21 +1,40 @@
require 'test_helper'
class CertsControllerTest < ActionController::TestCase
- setup do
- end
- test "should require login" do
+ test "send free cert without login" do
+ cert = stub :to_s => "free cert"
+ ClientCertificate.expects(:new).with(free: true).returns(cert)
get :show
- assert_response :redirect
- assert_redirected_to login_url
+ assert_response :success
+ assert_equal cert.to_s, @response.body
end
- test "should send cert" do
+ test "send cert" do
login
- cert = stub :cert => "adsf", :key => "key"
- ClientCertificate.expects(:new).returns(cert)
+ cert = stub :to_s => "real cert"
+ ClientCertificate.expects(:new).with(free: false).returns(cert)
get :show
assert_response :success
- assert_equal cert.key + cert.cert, @response.body
+ assert_equal cert.to_s, @response.body
+ end
+
+ test "login required if free certs disabled" do
+ with_config free_certs_enabled: false do
+ get :show
+ assert_response :redirect
+ end
end
+
+ test "get paid cert if free certs disabled" do
+ with_config free_certs_enabled: false do
+ login
+ cert = stub :to_s => "real cert"
+ ClientCertificate.expects(:new).with(free: false).returns(cert)
+ get :show
+ assert_response :success
+ assert_equal cert.to_s, @response.body
+ end
+ end
+
end
diff --git a/certs/test/unit/client_certificate_test.rb b/certs/test/unit/client_certificate_test.rb
index 71a1d90..abb5560 100644
--- a/certs/test/unit/client_certificate_test.rb
+++ b/certs/test/unit/client_certificate_test.rb
@@ -2,17 +2,28 @@ require 'test_helper'
class ClientCertificateTest < ActiveSupport::TestCase
- setup do
- @sample = ClientCertificate.new
+ test "new cert has all we need" do
+ sample = ClientCertificate.new
+ assert sample.key
+ assert sample.cert
+ assert sample.to_s
end
- test "new cert has all we need" do
- assert @sample.key
- assert @sample.cert
+ test "free cert has configured prefix" do
+ sample = ClientCertificate.new(free: true)
+ prefix = APP_CONFIG[:free_cert_prefix]
+ assert sample.cert.subject.common_name.starts_with?(prefix)
+ end
+
+ test "real cert has no free cert prefix" do
+ sample = ClientCertificate.new
+ prefix = APP_CONFIG[:free_cert_prefix]
+ assert !sample.cert.subject.common_name.starts_with?(prefix)
end
test "cert issuer matches ca subject" do
- cert = OpenSSL::X509::Certificate.new(@sample.cert)
+ sample = ClientCertificate.new
+ cert = OpenSSL::X509::Certificate.new(sample.cert.to_pem)
assert_equal ClientCertificate.root_ca.openssl_body.subject, cert.issuer
end
diff --git a/config/defaults.yml b/config/defaults.yml
index cb8a627..d0fb52f 100644
--- a/config/defaults.yml
+++ b/config/defaults.yml
@@ -7,6 +7,8 @@ cert_options: &cert_options
client_cert_lifespan: 2
client_cert_bit_size: 2024
client_cert_hash: "SHA256"
+ free_certs_enabled: true
+ free_cert_prefix: "FREE"
development:
<<: *dev_ca
@@ -19,7 +21,6 @@ test:
<<: *cert_options
admins: [admin, admin2]
domain: test.me
-
production:
<<: *cert_options
diff --git a/core/test/support/with_config_helper.rb b/core/test/support/with_config_helper.rb
new file mode 100644
index 0000000..65eb7bc
--- /dev/null
+++ b/core/test/support/with_config_helper.rb
@@ -0,0 +1,16 @@
+module WithConfigHelper
+ extend ActiveSupport::Concern
+
+ def with_config(options)
+ old_config = APP_CONFIG.dup
+ APP_CONFIG.merge! options
+ yield
+ ensure
+ APP_CONFIG.replace old_config
+ end
+
+end
+
+class ActiveSupport::TestCase
+ include WithConfigHelper
+end
diff --git a/help/app/models/ticket.rb b/help/app/models/ticket.rb
index ed1ff9d..a456fe5 100644
--- a/help/app/models/ticket.rb
+++ b/help/app/models/ticket.rb
@@ -2,7 +2,7 @@ class Ticket < CouchRest::Model::Base
#include ActiveModel::Validations
use_database "tickets"
- require 'securerandom'
+ #require 'securerandom'
=begin
title
created_at
diff --git a/users/app/assets/javascripts/users.js.coffee b/users/app/assets/javascripts/users.js.coffee
index 86bacee..955556c 100644
--- a/users/app/assets/javascripts/users.js.coffee
+++ b/users/app/assets/javascripts/users.js.coffee
@@ -37,8 +37,8 @@ $(document).ready ->
$('#new_user').submit srp.signup
$('#new_session').submit preventDefault
$('#new_session').submit srp.login
- $('.user.form.change_password').submit srp.update
- $('.user.form.change_password').submit preventDefault
+ $('.user.form.update_login_and_password').submit srp.update
+ $('.user.form.update_login_and_password').submit preventDefault
$('.user.typeahead').typeahead({source: pollUsers});
$('a[data-toggle="tab"]').on('shown', ->
$(ClientSideValidations.selectors.forms).validate()
diff --git a/users/app/controllers/users_controller.rb b/users/app/controllers/users_controller.rb
index 9325bc0..dff1ed5 100644
--- a/users/app/controllers/users_controller.rb
+++ b/users/app/controllers/users_controller.rb
@@ -1,7 +1,8 @@
class UsersController < ApplicationController
- before_filter :authorize, :only => [:show, :edit, :update, :destroy]
+ before_filter :authorize, :only => [:show, :edit, :destroy, :update]
before_filter :fetch_user, :only => [:show, :edit, :update, :destroy]
+ before_filter :authorize_self, :only => [:update]
before_filter :set_anchor, :only => [:edit, :update]
before_filter :authorize_admin, :only => [:index]
@@ -57,6 +58,11 @@ class UsersController < ApplicationController
access_denied unless admin? or (@user == current_user)
end
+ def authorize_self
+ # have already checked that authorized
+ access_denied unless (@user == current_user)
+ end
+
def set_anchor
@anchor = email_settings? ? :email : :account
end
diff --git a/users/app/models/user.rb b/users/app/models/user.rb
index e41c2dc..c9b367f 100644
--- a/users/app/models/user.rb
+++ b/users/app/models/user.rb
@@ -18,9 +18,19 @@ class User < CouchRest::Model::Base
:uniqueness => true,
:if => :serverside?
+ # Have multiple regular expression validations so we can get specific error messages:
validates :login,
- :format => { :with => /\A[A-Za-z\d_\.]+\z/,
- :message => "Only letters, digits, . and _ allowed" }
+ :format => { :with => /\A.{2,}\z/,
+ :message => "Login 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 => "Login must begin with a lowercase letter"}
+ validates :login,
+ :format => { :with => /\A.*[a-z\d]\z/,
+ :message => "Login must end with a letter or digit"}
validate :login_is_unique_alias
diff --git a/users/app/views/users/_cancel_account.html.haml b/users/app/views/users/_cancel_account.html.haml
index 41580b0..756170b 100644
--- a/users/app/views/users/_cancel_account.html.haml
+++ b/users/app/views/users/_cancel_account.html.haml
@@ -1,6 +1,9 @@
%legend
- =t :cancel_account
- %small You will not be able to login anymore.
+ - if @user == current_user
+ =t :cancel_account
+ %small You will not be able to login anymore.
+ - else
+ =t :admin_cancel_account, :username => @user.login
= link_to user_path(@user), :method => :delete, :class => "btn btn-danger" do
%i.icon-remove.icon-white
- Remove my Account
+ =t :remove_account
diff --git a/users/app/views/users/_login_and_password_fields.html.haml b/users/app/views/users/_login_and_password_fields.html.haml
new file mode 100644
index 0000000..0baefc7
--- /dev/null
+++ b/users/app/views/users/_login_and_password_fields.html.haml
@@ -0,0 +1,2 @@
+= render :partial => 'login_field', :locals => {:f => f}
+= render :partial => 'password_fields', :locals => {:f => f, :password_confirmation_hint => t(:can_retype_old_password)} \ No newline at end of file
diff --git a/users/app/views/users/_password_fields.html.haml b/users/app/views/users/_password_fields.html.haml
index c2e6a69..47b7b07 100644
--- a/users/app/views/users/_password_fields.html.haml
+++ b/users/app/views/users/_password_fields.html.haml
@@ -1,2 +1,2 @@
= f.input :password, :required => true, :validate => true, :input_html => { :id => :srp_password }
-= f.input :password_confirmation, :required => true, :input_html => { :id => :srp_password_confirmation }
+= f.input :password_confirmation, :required => true, :hint => local_assigns[:password_confirmation_hint], :input_html => { :id => :srp_password_confirmation }
diff --git a/users/app/views/users/edit.html.haml b/users/app/views/users/edit.html.haml
index 950a3b1..97bd48d 100644
--- a/users/app/views/users/edit.html.haml
+++ b/users/app/views/users/edit.html.haml
@@ -1,14 +1,17 @@
.span8.offset2
%h2=t :settings
+ - tabs = []
- content_for :account do
- = user_form_with 'login_field', :legend => :change_login
- = user_form_with 'password_fields', :legend => :change_password
- = render 'cancel_account' if @user == current_user
- - content_for :email do
- %legend=t :email_address
- The associated email address is
- = render @user.email_address, :as => :span
- = user_form_with 'public_key_field', :legend => :public_key
- = user_form_with 'email_forward_field', :legend => :forward_email
- = user_form_with 'email_aliases', :legend => :add_email_alias
- = render 'tabs/tabs', :tabs => [:account, :email]
+ = user_form_with 'login_and_password_fields', :legend => :update_login_and_password if @user == current_user
+ = render 'cancel_account'
+ - tabs << :account
+ - if @user == current_user
+ - content_for :email do
+ %legend=t :email_address
+ =t :associated_email
+ = render @user.email_address, :as => :span
+ = user_form_with 'public_key_field', :legend => :public_key
+ = user_form_with 'email_forward_field', :legend => :forward_email
+ = user_form_with 'email_aliases', :legend => :add_email_alias
+ - tabs << :email
+ = render 'tabs/tabs', :tabs => tabs
diff --git a/users/config/locales/en.yml b/users/config/locales/en.yml
index 493b5db..1b2789e 100644
--- a/users/config/locales/en.yml
+++ b/users/config/locales/en.yml
@@ -7,9 +7,10 @@ en:
login_message: "Please login with your account."
wrong_password: "wrong password"
user_not_found: "could not be found"
- change_login: "Change Login"
- change_password: "Change Password"
+ update_login_and_password: "Update Login and Password"
cancel_account: "Cancel your account"
+ remove_account: "Remove Account"
+ admin_cancel_account: "Cancel the account %{username}"
set_email_address: "Set email address"
forward_email: "Forward email"
email_aliases: "Email aliases"
@@ -19,6 +20,8 @@ en:
user_created_successfully: "Successfully created your account."
email_alias_destroyed_successfully: "Successfully removed the alias '%{alias}'."
use_ascii_key: "Use ASCII-armored PGP key"
+ can_retype_old_password: "Retype your old password if you would like to keep that"
+ associated_email: "The associated email address is"
activemodel:
models:
diff --git a/users/test/functional/users_controller_test.rb b/users/test/functional/users_controller_test.rb
index 9fb06c9..fd8869a 100644
--- a/users/test/functional/users_controller_test.rb
+++ b/users/test/functional/users_controller_test.rb
@@ -130,20 +130,17 @@ class UsersControllerTest < ActionController::TestCase
assert_equal " ", @response.body
end
- test "admin can update user" do
+ # Eventually, admin will be able to update some user fields
+ test "admin cannot update user" do
user = find_record :user
changed_attribs = record_attributes_for :user_with_settings
- user.expects(:attributes=).with(changed_attribs.stringify_keys)
- user.expects(:changed?).returns(true)
- user.expects(:save).returns(true)
- user.stubs(:email_aliases).returns([])
login :is_admin? => true
put :update, :user => changed_attribs, :id => user.id, :format => :json
- assert_equal user, assigns[:user]
- assert_response 204
- assert_equal " ", @response.body
+ assert_response :redirect
+ assert_access_denied
+
end
test "admin can destroy user" do