diff options
-rw-r--r-- | Gemfile.lock | 4 | ||||
-rw-r--r-- | README.md | 74 | ||||
-rw-r--r-- | app/controllers/errors_controller.rb | 2 | ||||
-rw-r--r-- | app/controllers/v1/users_controller.rb | 12 | ||||
-rw-r--r-- | config/defaults.yml | 2 | ||||
-rw-r--r-- | config/initializers/exception_filter.rb | 10 | ||||
-rw-r--r-- | config/locales/errors.en.yml | 2 | ||||
-rw-r--r-- | lib/en_US.yml | 185 | ||||
-rw-r--r-- | lib/leap_web/version.rb | 2 | ||||
-rw-r--r-- | lib/tasks/i18n.rake | 54 | ||||
-rw-r--r-- | test/functional/errors_controller_test.rb | 14 |
11 files changed, 332 insertions, 29 deletions
diff --git a/Gemfile.lock b/Gemfile.lock index 0a269f0..c14847f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -8,13 +8,13 @@ GIT PATH remote: engines/billing specs: - leap_web_billing (0.5.3) + leap_web_billing (0.6.0) braintree PATH remote: engines/support specs: - leap_web_help (0.5.3) + leap_web_help (0.6.0) GEM remote: https://rubygems.org/ @@ -1,7 +1,8 @@ LEAP Web --------------------- -"LEAP Web" is the web-based component of the LEAP Platform, providing the following services: +"LEAP Web" is the web-based component of the LEAP Platform, providing +the following services: * REST API for user registration. * Admin interface to manage users. @@ -9,9 +10,12 @@ LEAP Web * User support help tickets. * Billing -This web application is written in Ruby on Rails 3, using CouchDB as the backend data store. +This web application is written in Ruby on Rails 3, using CouchDB as the +backend data store. -Original code specific to this web application is licensed under the GNU Affero General Public License (version 3.0 or higher). See http://www.gnu.org/licenses/agpl-3.0.html for more information. +Original code specific to this web application is licensed under the GNU +Affero General Public License (version 3.0 or higher). See +http://www.gnu.org/licenses/agpl-3.0.html for more information. Documentation --------------------------- @@ -25,26 +29,31 @@ For more information, see these files in the ``doc`` directory: Known problems --------------------------- -* Client certificates are generated without a CSR. The problem is that this makes the web - application extremely vulnerable to denial of service attacks. This was not an issue until we - started to allow the possibility of anonymously fetching a client certificate without +* Client certificates are generated without a CSR. The problem is that + this makes the web application extremely vulnerable to denial of + service attacks. This is not an issue unless the provider enables the + possibility of anonymously fetching a client certificate without authenticating first. -* By its very nature, the user database is vulnerable to enumeration attacks. These are - very hard to prevent, because our protocol is designed to allow query of a user database via - proxy in order to provide network perspective. +* By its very nature, the user database is vulnerable to enumeration + attacks. These are very hard to prevent, because our protocol is + designed to allow query of a user database via proxy in order to + provide network perspective. Installation --------------------------- -Typically, this application is installed automatically as part of the LEAP Platform. To install it manually for testing or development, follow these instructions: +Typically, this application is installed automatically as part of the +LEAP Platform. To install it manually for testing or development, follow +these instructions: ### Install system requirements sudo apt-get install git ruby1.9.3 rubygems couchdb sudo gem install bundler -On Debian Wheezy or later, there is a Debian package for bundler, so you can alternately run ``sudo apt-get install bundler``. +On Debian Wheezy or later, there is a Debian package for bundler, so you +can alternately run ``sudo apt-get install bundler``. ### Download source @@ -55,15 +64,18 @@ On Debian Wheezy or later, there is a Debian package for bundler, so you can alt ### Install required ruby libraries cd leap_web - bundle + bundle --binstubs -Typically, you run ``bundle`` as a normal user and it will ask you for a sudo password when it is time to install the required gems. If you don't have sudo, run ``bundle`` as root. +Typically, you run ``bundle`` as a normal user and it will ask you for a +sudo password when it is time to install the required gems. If you don't +have sudo, run ``bundle`` as root. Configuration ---------------------------- -The configuration file `config/defaults.yml` providers good defaults for most -values. You can override these defaults by creating a file `config/config.yml`. +The configuration file `config/defaults.yml` providers good defaults for +most values. You can override these defaults by creating a file +`config/config.yml`. There are a few values you should make sure to modify: @@ -76,22 +88,39 @@ There are a few values you should make sure to modify: client_ca_cert: "/etc/ssl/ca.crt" ca_key_password: nil -* `admins` is an array of usernames that are granted special admin privilege. +* `admins` is an array of usernames that are granted special admin + privilege. + * `domain` is your fully qualified domain name. -* `force_ssl`, if set to true, will require secure cookies and turn on HSTS. Don't do this if you are using a self-signed server certificate. -* `secret_token`, used for cookie security, you can create one with `rake secret`. Should be at least 30 characters. -* `client_ca_key`, the private key of the CA used to generate client certificates. -* `client_ca_cert`, the public certificate the CA used to generate client certificates. + +* `force_ssl`, if set to true, will require secure cookies and turn on + HSTS. Don't do this if you are using a self-signed server certificate. + +* `secret_token`, used for cookie security, you can create one with + `rake secret`. Should be at least 30 characters. + +* `client_ca_key`, the private key of the CA used to generate client + certificates. + +* `client_ca_cert`, the public certificate the CA used to generate client + certificates. + * `ca_key_password`, used to unlock the client_ca_key, if needed. Running ----------------------------- +To run leap_web: + cd leap_web - rails server + bin/rails server Then open http://localhost:3000 in your web browser. +When running in development mode, you can login with administrative +powers by creating an account with username 'staff', 'blue', or 'red' +(configured in config/default.yml). + To peruse the database, visit http://localhost:5984/_utils/ Testing @@ -105,4 +134,5 @@ To run an individual test: rake test TEST=certs/test/unit/client_certificate_test.rb or - ruby -Itest certs/test/unit/client_certificate_test.rb
\ No newline at end of file + ruby -Itest certs/test/unit/client_certificate_test.rb + diff --git a/app/controllers/errors_controller.rb b/app/controllers/errors_controller.rb index 6c659e6..d869ab5 100644 --- a/app/controllers/errors_controller.rb +++ b/app/controllers/errors_controller.rb @@ -2,9 +2,11 @@ class ErrorsController < ApplicationController # 404 def not_found + render status: 404 end # 500 def server_error + render status: 500 end end diff --git a/app/controllers/v1/users_controller.rb b/app/controllers/v1/users_controller.rb index bfa04fc..d57db6f 100644 --- a/app/controllers/v1/users_controller.rb +++ b/app/controllers/v1/users_controller.rb @@ -2,9 +2,9 @@ module V1 class UsersController < ApiController include ControllerExtension::FetchUser - before_filter :fetch_user, :only => [:update] + before_filter :fetch_user, :only => [:update, :destroy] before_filter :require_admin, :only => [:index] - before_filter :require_login, :only => [:index, :update] + before_filter :require_login, :only => [:index, :update, :destroy] before_filter :require_registration_allowed, only: :create respond_to :json @@ -29,6 +29,14 @@ module V1 respond_with @user end + def destroy + @user.account.destroy + if @user == current_user + logout + end + render :json => {'success' => 'user deleted'} + end + protected def require_registration_allowed diff --git a/config/defaults.yml b/config/defaults.yml index daef122..9eccb5e 100644 --- a/config/defaults.yml +++ b/config/defaults.yml @@ -81,7 +81,7 @@ development: <<: *cert_options <<: *common <<: *service_levels - admins: [blue, admin, admin2] + admins: [blue, red, staff] domain: example.org secret_token: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' reraise_errors: true diff --git a/config/initializers/exception_filter.rb b/config/initializers/exception_filter.rb new file mode 100644 index 0000000..18c74d9 --- /dev/null +++ b/config/initializers/exception_filter.rb @@ -0,0 +1,10 @@ +class ActionDispatch::DebugExceptions + def log_error_with_exception_filter(env, wrapper) + if wrapper.exception.is_a? ActionController::RoutingError + return + else + log_error_without_exception_filter env, wrapper + end + end + alias_method_chain :log_error, :exception_filter +end diff --git a/config/locales/errors.en.yml b/config/locales/errors.en.yml index e0a909f..a8e7c6e 100644 --- a/config/locales/errors.en.yml +++ b/config/locales/errors.en.yml @@ -9,4 +9,4 @@ en: text: not_found: "You may have mistyped the address or the page may have moved." server_error: The problem has been logged and we will look into it. - not_found: Not found. + #not_found: Not found. diff --git a/lib/en_US.yml b/lib/en_US.yml new file mode 100644 index 0000000..b00f29e --- /dev/null +++ b/lib/en_US.yml @@ -0,0 +1,185 @@ +en_US: + +### Do NOT edit this file directly, as all changes will be overwritten by `rake i18:bundle` +### Instead, make changes in the appropriate file in config/locales. +### Source strings in transifex are automatically updated from this file (via github url) + +######################################## +### errors.en.yml + errors: + title: + not_found: Page not found. + server_error: Ouch! + subtitle: + not_found: The page you were looking for doesn't exist. + server_error: We ran into a server error. + text: + not_found: You may have mistyped the address or the page may have moved. + server_error: The problem has been logged and we will look into it. + + +######################################## +### flash.en.yml + flash: + success: ! '%{resource} was successfully saved.' + error: ! '%{resource} could not be saved.' + create: + success: ! '%{resource} was successfully created.' + error: ! '%{resource} could not be created.' + update: + success: ! '%{resource} was successfully updated.' + error: ! '%{resource} could not be updated.' + + +######################################## +### footer.en.yml + privacy_policy: Privacy Policy + terms_of_service: Terms of Service + pricing: Pricing + about: About Us + contact: Contact + + +######################################## +### generic.en.yml + signup: Sign Up + login: Log In + logout: Log Out + cancel: Cancel + created: Created + created_by_on: Created by %{user} on %{time} + updated: Updated + none: None + unknown: Unknown + admin: Admin + anonymous: Anonymous + save: Save + add: Add + remove: Remove + changes_saved: Changes saved successfully. + are_you_sure: Are you sure? This change cannot be undone. + example_email: user@domain.org + no_such_thing: No such %{thing}. + create_thing: Create %{thing} + overview: Overview + + +######################################## +### home.en.yml + home: Home + welcome: Welcome to %{provider}. + download_bitmask: Download Bitmask + login_info: Log in to change your account settings, create support tickets, and manage + payments. + signup_info: Create a new user account. For higher security, we recommend you create + your account via the Bitmask application instead. + support_info: Can't login? Create a new support ticket anonymously. + + +######################################## +### messages.en.yml + messages: + not_found: That message could not be found. + marked_as_read: Message has been marked as read. + + +######################################## +### simple_form.en.yml + simple_form: + 'yes': 'Yes' + 'no': 'No' + required: + text: required + mark: ! '*' + error_notification: + default_message: ! 'Please review the problems below:' + buttons: + cancel: Cancel + loading: Loading... + helpers: + submit: + user: + create: Sign Up + update: Save + session: + create: Log In + + +######################################## +### users.en.yml + common: + navigation_item: + users: Users + identities: Usernames + tickets: Tickets + user_control_panel: user control panel + account_settings: Account Settings + username: Username + password: Password + change_password: Change Password + 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. + payment_one_month_warning: We hope you have been enjoying this service this past month. + Please sign up to pay within the next month, by %{date_in_one_month}. Directions + for payment are available at INSERT_URL + bye: Goodbye! + bye_message: So long and thanks for all the fish. + users: + overview: + welcome: Welcome %{username}. + intro: ! 'From this user control panel, you can:' + tickets: Create and check support tickets. + email: Modify email settings. + account: Destroy your account. + 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/lib/leap_web/version.rb b/lib/leap_web/version.rb index 9ff7c46..6bb9848 100644 --- a/lib/leap_web/version.rb +++ b/lib/leap_web/version.rb @@ -1,3 +1,3 @@ module LeapWeb - VERSION = "0.5.3" unless defined?(LeapWeb::VERSION) + VERSION = "0.6.0" unless defined?(LeapWeb::VERSION) end diff --git a/lib/tasks/i18n.rake b/lib/tasks/i18n.rake new file mode 100644 index 0000000..daa1834 --- /dev/null +++ b/lib/tasks/i18n.rake @@ -0,0 +1,54 @@ +require 'yaml' +require 'fileutils' + +namespace :i18n do + # + # for coding, it helps to have the english strings in separate files. + # for translating, it helps to have a single file. This action will combine + # the small files into one big one. + # + # Also, transifex insists that the files be en_US and not just en. + # grrr. transifex is configured to automatically update from the + # file lib/en_US.yml. + # + desc "combine config/locales/*.en.yml to lib/en_US.yml" + task :bundle do + en_yml = File.join(Rails.root, 'lib', 'en_US.yml') + Dir.chdir('config/locales/') do + if File.exists?(en_yml) + File.unlink en_yml + end + File.open(en_yml, 'w') do |output| + output.write("en_US:\n\n"+ + "### Do NOT edit this file directly, as all changes will be overwritten by `rake i18:bundle`\n"+ + "### Instead, make changes in the appropriate file in config/locales.\n"+ + "### Source strings in transifex are automatically updated from this file (via github url)") + + Dir.glob('*.en.yml').sort.each do |file| + ## print separator to see where another file begins + output.write("\n\n" + '#' * 40 + "\n" + '### ' + file + "\n") + output.write( + # remove the toplevel "en" key + YAML.load_file(file)['en']. + to_yaml. + # prefix all lines with two spaces (we're nested below "en:") + lines.map {|line| " #{line}"}[ + 1..-1 # << skip the first line (it's "---" and freaks out the parser if it sees it multiple times in a file) + ].join) + end + end + puts "You can now find the bundled locale yml in: #{en_yml}" + end + end + + + # elijah: this does not actually work, but I think could be a starting point + # for something that will work. + desc "pull translations from transifex" + task :download do + Conf.enabled_languages.each do |lang| + next unless lang == 'en' + `curl -L --user #{Conf.transifex_user}:#{Conf.transifex_password} -X GET https://www.transifex.net/api/2/project/crabgrass/resource/master/translation/#{lang}/?file > config/locales/#{lang}.yml` + end + end +end diff --git a/test/functional/errors_controller_test.rb b/test/functional/errors_controller_test.rb new file mode 100644 index 0000000..e6d2367 --- /dev/null +++ b/test/functional/errors_controller_test.rb @@ -0,0 +1,14 @@ +class ErrorsControllerTest < ActionController::TestCase + + def test_not_found_resonds_with_404 + get 'not_found' + assert_response 404 + assert_template 'errors/not_found' + end + + def test_server_error_resonds_with_500 + get 'server_error' + assert_response 500 + assert_template 'errors/server_error' + end +end |