diff --git a/.gitignore b/.gitignore index ae80164e502726efaa193dfbe2ddf3455a095011..d2c630c329ec00d89b5ed8026a41458fd8b04945 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,7 @@ bin */Gemfile.lock test/dummy/log/* test/dummy/tmp/* +*.pyc # ignore all deploy specific configuration config/couchdb.yml diff --git a/.gitmodules b/.gitmodules index 7884a42dc65c11e7d5390739a3f547fbc6867d01..0c28cd5e1e5bb9b1c10265545d4dc2ae0269c8db 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ -[submodule "users/app/assets/javascripts/srp"] - path = users/app/assets/javascripts/srp +[submodule "app/assets/javascripts/srp"] + path = app/assets/javascripts/srp url = https://leap.se/git/srp_js diff --git a/CUSTOM.md b/CUSTOM.md index 8671323e5bf80edad58109236b4f0986391abb5b..53e4d88dd616d2b7ec5d2bacc22a023d8d818efb 100644 --- a/CUSTOM.md +++ b/CUSTOM.md @@ -9,6 +9,6 @@ See config/customization/README.md Engines --------------------- -Leap Web is based on Engines. All things in `app` will overwrite the default behaviour. You can either create a new rails app and include the leap_web gem or clone the leap web repository and add your customizations to the `app` directory. +Leap Web includes some Engines. All things in `app` will overwrite the engine behaviour. You can clone the leap web repository and add your customizations to the `app` directory. Including leap_web as a gem is currently not supported. It should not require too much work though and we would be happy to include the changes required. -If you have no use for one of the engines you can remove it from the Gemfile. Not however that your app might still need to provide some functionality for the other engines to work. For example the users engine provides `current_user` and other methods. +If you have no use for one of the engines you can remove it from the Gemfile. Engines should really be plugins - no other engines should depend upon them. If you need functionality in different engines it should probably go into the toplevel. The 'users' engine will soon become part of the main webapp for that reason. diff --git a/DEVELOP.md b/DEVELOP.md index 6aeccfffbb88b8e3d2e8d90014fd6d5db6422813..0bc20312052dffa82bc9788f52bb0eaae68de013 100644 --- a/DEVELOP.md +++ b/DEVELOP.md @@ -5,21 +5,21 @@ Some tips on modifying the views: * Many of the forms use [simple_form gem](https://github.com/plataformatec/simple_form) +* We still use client_side_validations for the validation code but since it is not maintained anymore we want to drop it asap. ## Engines ## -Leap Web consists of different Engines. They live in their own subdirectory and are included through bundler via their path. This way changes to the engines immediately affect the server as if they were in the main `app` directory. +Leap Web contains some. They live in their own subdirectory and are included through bundler via their path. This way changes to the engines immediately affect the server as if they were in the main `app` directory. -Currently Leap Web consists of 5 Engines: +Currently Leap Web includes 2 Engines: -* [core](https://github.com/leapcode/leap_web/blob/master/core) - ships some dependencies that are used accross all engines. This might be removed at some point. -* [users](https://github.com/leapcode/leap_web/blob/master/users) - user registration and authorization -* [certs](https://github.com/leapcode/leap_web/blob/master/certs) - Cert distribution for the EIP client -* [help](https://github.com/leapcode/leap_web/blob/master/help) - Help ticket management -* [billing](https://github.com/leapcode/leap_web/blob/master/billing) - Billing System +* [support](https://github.com/leapcode/leap_web/blob/master/engines/support) - Help ticket management +* [billing](https://github.com/leapcode/leap_web/blob/master/engines/billing) - Billing System ## Creating a new engine ## +If you want to add functionality to the webapp but keep it easy to remove you might consider adding an engine. This only makes sense if your engine really is a plugin - so no other pieces of code depend on it. + ### Rails plugin new ### Create the basic tree structure for an engine using @@ -32,28 +32,10 @@ rails plugin new ENGINE_NAME -O --full See http://guides.rubyonrails.org/engines.html for more general info about engines. -### Require Leap Web Core and dependencies ### - -Leap Web Core provides a common set of dependencies for the engines with CouchRest Model etc. -It also comes with an optional set of UI gems like haml, sass, coffeescript, uglifier, bootstrap-sass, jquery and simple_form. +You need to require engine specific gems in lib/my_engine/engine.rb: -In order to use the core dependencies you need to add leap_web_core to your .gemspec: ```ruby -# make sure LeapWeb::VERSION is available -require File.expand_path('../../lib/leap_web/version.rb', __FILE__) -# ... - Gem::Specification.new do |s| - # ... - s.add_dependency "rails" - s.add_dependency "leap_web_core", LeapWeb::Version - end -``` - -You also need to require it before you define your engine in lib/my_engine/engine.rb: -```ruby -require "leap_web_core" -# uncomment if you want the ui gems: -# require "leap_web_core/ui_dependencies" +require "my_dependency" module MyEngine class Engine < ::Rails::Engine @@ -62,17 +44,9 @@ module MyEngine end ``` -Some development and UI dependencies can not be loaded via leap_web_core. To make them available add the following lines to your engines Gemfile - -```ruby - eval(File.read(File.dirname(__FILE__) + '/../common_dependencies.rb')) - # uncomment if you want the ui gems: - # eval(File.read(File.dirname(__FILE__) + '/../ui_dependencies.rb')) -``` - ## Creating Models ## -You can use the normal rails generators to create models. Since you required the leap_web_core gem you will be using CouchRest::Model. So your models inherit from CouchRest::Model::Base. +You can use the normal rails generators to create models. You probably want to require couchrest_model so your models inherit from CouchRest::Model::Base. http://www.couchrest.info/model/definition.html has some good first steps for setting up the model. CouchRest Model behaved strangely when using a model without a design block. So make sure to define an initial view: http://www.couchrest.info/model/view_objects.html . diff --git a/Gemfile b/Gemfile index 1d6c43204e5b6e195889d9421ddbc10ac426a949..816cc4a799c828ed0ae8fcd466f7ee82e1b664f0 100644 --- a/Gemfile +++ b/Gemfile @@ -1,16 +1,17 @@ source 'https://rubygems.org' -eval(File.read(File.dirname(__FILE__) + '/common_dependencies.rb')) -eval(File.read(File.dirname(__FILE__) + '/ui_dependencies.rb')) - -# EITHER fetch all of the leap_web gems in one go -# gem 'leap_web' -# OR use the local versions for development instead: -gem "leap_web_core", :path => 'core' -gem 'leap_web_users', :path => 'users' -gem 'leap_web_certs', :path => 'certs' -gem 'leap_web_help', :path => 'help' -gem 'leap_web_billing', :path => 'billing' +gem "rails", "~> 3.2.18" +gem "couchrest", "~> 1.1.3" +gem "couchrest_model", "~> 2.0.0" +gem "couchrest_session_store", "~> 0.2.4" +gem "json" + +# user management +gem "ruby-srp", "~> 0.2.1" +gem "rails_warden" + +gem 'leap_web_help', :path => 'engines/support' +gem 'leap_web_billing', :path => 'engines/billing' gem 'http_accept_language' @@ -19,12 +20,62 @@ gem 'debugger', :platforms => :mri_19 # ruby 1.8 is not supported anymore # gem 'ruby-debug', :platforms => :mri_18 +gem "haml", "~> 3.1.7" +gem "bootstrap-sass", "= 2.3.2.2" +gem "jquery-rails" +gem "simple_form" +gem 'client_side_validations' +gem 'client_side_validations-simple_form' +gem "bootswatch-rails", "~> 0.5.0" + +gem 'kaminari', "0.13.0" # for pagination. trying 0.13.0 as there seem to be + # issues with 0.14.0 when using couchrest + +gem 'rails-i18n' # locale files for built-in validation messages and times + # https://github.com/svenfuchs/rails-i18n + # for a list of keys: + # https://github.com/svenfuchs/rails-i18n/blob/master/rails/locale/en.yml + +gem 'rdiscount' # for rendering .md templates + group :test do - gem 'fake_braintree', require: false + + # integration testing gem 'capybara', require: false - gem 'launchy' # so save_and_open_page works in integration tests - gem 'phantomjs-binaries' - gem 'minitest-stub-const' + gem 'poltergeist' # headless js + gem 'launchy' # save_and_open_page + gem 'phantomjs-binaries' # binaries specific to the os + + # moching and stubbing + gem 'mocha', '~> 0.13.0', :require => false + gem 'minitest-stub-const' # why? + + # generating test data + gem 'factory_girl_rails' # test data factories + gem 'faker' # names and numbers for test data + + # billing tests + gem 'fake_braintree', require: false +end + +group :test, :development do + gem 'thin' +end + +group :assets do + gem "haml-rails", "~> 0.3.4" + gem "sass-rails", "~> 3.2.5" + gem "coffee-rails", "~> 3.2.2" + gem "uglifier", "~> 1.2.7" + + # See https://github.com/sstephenson/execjs#readme for more supported runtimes + gem 'therubyracer', "~> 0.10.2", :platforms => :ruby + gem 'quiet_assets' # stops logging all the asset requests +end + + +group :production do + gem 'SyslogLogger', '~> 2.0' end # unreleased so far ... but leap_web_certs need it diff --git a/Gemfile.lock b/Gemfile.lock index 0c7486f50c2796ac143dc6ac546f6239760028fe..67c04de8bec7c2cb29433ea5b3179624b2663af8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -6,53 +6,26 @@ GIT activemodel (>= 3.0.6) PATH - remote: billing + remote: engines/billing specs: leap_web_billing (0.5.0) braintree - leap_web_core (= 0.5.0) PATH - remote: certs - specs: - leap_web_certs (0.5.0) - certificate_authority (>= 0.2.0) - leap_web_core (= 0.5.0) - -PATH - remote: core - specs: - leap_web_core (0.5.0) - couchrest (~> 1.1.3) - couchrest_model (~> 2.0.0) - couchrest_session_store (~> 0.2.4) - json - rails (~> 3.2.11) - -PATH - remote: help + remote: engines/support specs: leap_web_help (0.5.0) - leap_web_core (= 0.5.0) - -PATH - remote: users - specs: - leap_web_users (0.5.0) - leap_web_core (= 0.5.0) - rails_warden - ruby-srp (~> 0.2.1) GEM remote: https://rubygems.org/ specs: SyslogLogger (2.0) - actionmailer (3.2.16) - actionpack (= 3.2.16) + actionmailer (3.2.18) + actionpack (= 3.2.18) mail (~> 2.5.4) - actionpack (3.2.16) - activemodel (= 3.2.16) - activesupport (= 3.2.16) + actionpack (3.2.18) + activemodel (= 3.2.18) + activesupport (= 3.2.18) builder (~> 3.0.0) erubis (~> 2.7.0) journey (~> 1.0.4) @@ -60,18 +33,18 @@ GEM rack-cache (~> 1.2) rack-test (~> 0.6.1) sprockets (~> 2.2.1) - activemodel (3.2.16) - activesupport (= 3.2.16) + activemodel (3.2.18) + activesupport (= 3.2.18) builder (~> 3.0.0) - activerecord (3.2.16) - activemodel (= 3.2.16) - activesupport (= 3.2.16) + activerecord (3.2.18) + activemodel (= 3.2.18) + activesupport (= 3.2.18) arel (~> 3.0.2) tzinfo (~> 0.3.29) - activeresource (3.2.16) - activemodel (= 3.2.16) - activesupport (= 3.2.16) - activesupport (3.2.16) + activeresource (3.2.18) + activemodel (= 3.2.18) + activesupport (= 3.2.18) + activesupport (3.2.18) i18n (~> 0.6, >= 0.6.4) multi_json (~> 1.0) addressable (2.3.5) @@ -101,7 +74,7 @@ GEM coffee-script-source execjs coffee-script-source (1.6.3) - columnize (0.3.6) + columnize (0.8.9) couchrest (1.1.3) mime-types (~> 1.15) multi_json (~> 1.0) @@ -116,12 +89,12 @@ GEM couchrest couchrest_model daemons (1.1.9) - debugger (1.6.3) + debugger (1.6.6) columnize (>= 0.3.1) debugger-linecache (~> 1.2.0) - debugger-ruby_core_source (~> 1.2.4) + debugger-ruby_core_source (~> 1.3.2) debugger-linecache (1.2.0) - debugger-ruby_core_source (1.2.4) + debugger-ruby_core_source (1.3.2) erubis (2.7.0) eventmachine (1.0.3) execjs (2.0.2) @@ -170,7 +143,7 @@ GEM minitest-stub-const (0.1) mocha (0.13.3) metaclass (~> 0.0.1) - multi_json (1.8.2) + multi_json (1.10.0) nokogiri (1.6.1) mini_portile (~> 0.5.0) phantomjs-binaries (1.9.2.3) @@ -180,7 +153,7 @@ GEM cliver (~> 0.3.1) multi_json (~> 1.0) websocket-driver (>= 0.2.0) - polyglot (0.3.3) + polyglot (0.3.4) quiet_assets (1.0.2) railties (>= 3.1, < 5.0) rack (1.4.5) @@ -188,31 +161,31 @@ GEM rack (>= 0.4) rack-protection (1.5.1) rack - rack-ssl (1.3.3) + rack-ssl (1.3.4) rack rack-test (0.6.2) rack (>= 1.0) - rails (3.2.16) - actionmailer (= 3.2.16) - actionpack (= 3.2.16) - activerecord (= 3.2.16) - activeresource (= 3.2.16) - activesupport (= 3.2.16) + rails (3.2.18) + actionmailer (= 3.2.18) + actionpack (= 3.2.18) + activerecord (= 3.2.18) + activeresource (= 3.2.18) + activesupport (= 3.2.18) bundler (~> 1.0) - railties (= 3.2.16) + railties (= 3.2.18) rails-i18n (3.0.0) i18n (~> 0.5) rails (>= 3.0.0, < 4.0.0) rails_warden (0.5.7) warden (>= 1.0.0) - railties (3.2.16) - actionpack (= 3.2.16) - activesupport (= 3.2.16) + railties (3.2.18) + actionpack (= 3.2.18) + activesupport (= 3.2.18) rack-ssl (~> 1.3.2) rake (>= 0.8.7) rdoc (~> 3.4) thor (>= 0.14.6, < 2.0) - rake (10.1.1) + rake (10.3.1) rdiscount (2.0.7) rdoc (3.12.2) json (~> 1.4) @@ -244,12 +217,12 @@ GEM daemons (>= 1.0.9) eventmachine (>= 1.0.0) rack (>= 1.0.0) - thor (0.18.1) + thor (0.19.1) tilt (1.4.1) treetop (1.4.15) polyglot polyglot (>= 0.3.1) - tzinfo (0.3.38) + tzinfo (0.3.39) uglifier (1.2.7) execjs (>= 0.3.0) multi_json (~> 1.3) @@ -271,6 +244,9 @@ DEPENDENCIES client_side_validations client_side_validations-simple_form coffee-rails (~> 3.2.2) + couchrest (~> 1.1.3) + couchrest_model (~> 2.0.0) + couchrest_session_store (~> 0.2.4) debugger factory_girl_rails fake_braintree @@ -279,20 +255,21 @@ DEPENDENCIES haml-rails (~> 0.3.4) http_accept_language jquery-rails + json kaminari (= 0.13.0) launchy leap_web_billing! - leap_web_certs! - leap_web_core! leap_web_help! - leap_web_users! minitest-stub-const mocha (~> 0.13.0) phantomjs-binaries poltergeist quiet_assets + rails (~> 3.2.18) rails-i18n + rails_warden rdiscount + ruby-srp (~> 0.2.1) sass-rails (~> 3.2.5) simple_form therubyracer (~> 0.10.2) diff --git a/certs/app/assets/images/leap_web_certs/.gitkeep b/app/assets/images/leap_web_users/.gitkeep similarity index 100% rename from certs/app/assets/images/leap_web_certs/.gitkeep rename to app/assets/images/leap_web_users/.gitkeep diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 03a40da6a96892b9e265db3ddd52811811fc46ba..9af373d93caccf136913c4e675d740d93597f04d 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -20,4 +20,4 @@ //= require platform //= require tickets //= require users -//= require_tree . +//= require buttons diff --git a/app/assets/javascripts/buttons.js b/app/assets/javascripts/buttons.js new file mode 100644 index 0000000000000000000000000000000000000000..714295764e143814902051efaa9307665c6ff4ca --- /dev/null +++ b/app/assets/javascripts/buttons.js @@ -0,0 +1,39 @@ +/* + * Buttons.js + * + * Use bootstrap loading state after submitting a form. + * + * Some form inputs are validaded before the submission + * so triggering loading state on click events is not a + * good idea. If the validation fails the errors will + * be displayed but the button would be in loading state. + * + * We used to trigger it based on form submission but + * we have a few forms that contain multiple buttons. + * So now we mark the buttons as clicked on click and + * put the clicked button into loading state on submit. + * + */ + +(function() { + markAsClicked = function () { + var btn = $(this) + btn.addClass('clicked') + setTimeout(function () { + btn.removeClass('clicked') + }, 1000) + }; + + markAsLoading = function(submitEvent) { + var form = submitEvent.target; + $(form).addClass('submitted') + // bootstrap loading state: + $(form).find('.btn.clicked[type="submit"]').button('loading'); + }; + + $(document).ready(function() { + $('form').submit(markAsLoading); + $('.btn[type="submit"]').click(markAsClicked); + }); + +}).call(this); diff --git a/core/app/assets/javascripts/leap.js b/app/assets/javascripts/leap.js similarity index 100% rename from core/app/assets/javascripts/leap.js rename to app/assets/javascripts/leap.js diff --git a/core/app/assets/javascripts/platform.js b/app/assets/javascripts/platform.js similarity index 100% rename from core/app/assets/javascripts/platform.js rename to app/assets/javascripts/platform.js diff --git a/users/app/assets/javascripts/srp b/app/assets/javascripts/srp similarity index 100% rename from users/app/assets/javascripts/srp rename to app/assets/javascripts/srp diff --git a/users/app/assets/javascripts/users.js b/app/assets/javascripts/users.js similarity index 52% rename from users/app/assets/javascripts/users.js rename to app/assets/javascripts/users.js index 8486756a00824dbe3573bae34b5e98184320cbb7..e6c2fcc657e6062ba16df3de7e5f2eecb1b7d120 100644 --- a/users/app/assets/javascripts/users.js +++ b/app/assets/javascripts/users.js @@ -1,13 +1,24 @@ (function() { + + + var settings = { + "error_class":"help-inline", + "error_tag":"span", + "wrapper_error_class":"error", + "wrapper_tag":"div", + "wrapper_class":"control-group" + } + // // LOCAL FUNCTIONS // - var poll_users, - prevent_default, - form_failed, - form_passed, + var poll_users, + prevent_default, clear_errors, + clear_field_errors, + validate_password_confirmation, + validate_password_length, update_user; prevent_default = function(event) { @@ -24,6 +35,10 @@ return $('#messages').empty(); }; + clear_field_errors = function() { + return $(settings.error_tag + '.' + settings.error_class).remove(); + }; + update_user = function(submitEvent) { var form = submitEvent.target; var token = form.dataset.token; @@ -35,22 +50,35 @@ data: $(form).serialize() }); req.done( function() { - $(form).find('input[type="submit"]').button('reset'); + $(form).find('.btn[type="submit"]').button('reset'); }); }; - markAsSubmitted = function(submitEvent) { + validate_password_confirmation = function(submitEvent) { var form = submitEvent.target; - $(form).addClass('submitted') - // bootstrap loading state: - $(form).find('input[type="submit"]').button('loading'); + var password = $(form).find('input#srp_password').val(); + var confirmation = $(form).find('input#srp_password_confirmation').val(); + if (password === confirmation) { + return true; + } + else { + displayFieldError("password_confirmation", "does not match."); + submitEvent.stopImmediatePropagation() + return false; + } }; - resetButtons = function(submitEvent) { - var form = $('form.submitted') - // bootstrap loading state: - $(form).find('input[type="submit"]').button('reset'); - $(form).removeClass('submitted') + validate_password_length = function(submitEvent) { + var form = submitEvent.target; + var password = $(form).find('input#srp_password').val(); + if (password.length > 7) { + return true; + } + else { + displayFieldError("password", "needs to be at least 8 characters long."); + submitEvent.stopImmediatePropagation() + return false; + } }; // @@ -79,7 +107,7 @@ clear_errors(); var errors = extractErrors(message); displayErrors(errors); - resetButtons(); + $('.btn[type="submit"]').button('reset'); } function extractErrors(message) { @@ -104,19 +132,40 @@ } function displayFieldError(field, error) { + var message = $.isArray(error) ? error[0] : error; var element = $('form input[name$="[' + field + ']"]'); if (element) { - element.trigger('element:validate:fail.ClientSideValidations', error).data('valid', false); + addError(element, settings, message); } }; - // - // INIT - // + function addError(element, settings, message) { + var errorElement, wrapper; + + errorElement = element.parent().find("" + settings.error_tag + "." + settings.error_class); + wrapper = element.closest(settings.wrapper_tag + '.' + settings.wrapper_class); + if (errorElement[0] == null) { + errorElement = $("<" + settings.error_tag + "/>", { + "class": settings.error_class, + text: message + }); + element.after(errorElement); + } + wrapper.addClass(settings.wrapper_error_class); + return errorElement.text(message); + } + +// +// INIT +// $(document).ready(function() { - $('form').submit(markAsSubmitted); + $('.hidden.js-show').removeClass('hidden'); + $('.js-show').show(); $('#new_user').submit(prevent_default); + $('#new_user').submit(clear_field_errors); + $('#new_user').submit(validate_password_length); + $('#new_user').submit(validate_password_confirmation); $('#new_user').submit(srp.signup); $('#new_session').submit(prevent_default); $('#new_session').submit(srp.login); diff --git a/app/assets/stylesheets/leap.scss b/app/assets/stylesheets/leap.scss index 4c0dfe3ae8c57b13178e97d7113b7103208fc65f..77104e53efb896861bc09a8e74de47ab9bdfca45 100644 --- a/app/assets/stylesheets/leap.scss +++ b/app/assets/stylesheets/leap.scss @@ -43,65 +43,6 @@ display: none; } -// -// OS specific -// - -.os-android { - display: none !important; -} - -html.android .os-android { - display: inherit !important; -} - -.os-linux { - display: none !important; -} - -html.linux .os-linux { - display: inherit !important; -} - -// .os-linux32 { -// display: none !important; -// } -// html.linux32 .os-linux32 { -// display: inherit !important; -// } -// .os-linux64 { -// display: none !important; -// } -// html.linux64 .os-linux64 { -// display: inherit !important; -// } - -.os-windows { - display: none !important; -} - -html.windows .os-windows { - display: inherit !important; -} - -.os-osx { - display: none !important; -} - -html.osx .os-osx { - display: inherit !important; -} - -.os-other { - display: none !important; -} - -html.oldmac, html.oldwin, html.ios, html.fxos, html.other { - .os-other { - display: inherit !important; - } -} - // // ICONS // @@ -230,14 +171,14 @@ input, textarea { } .download { a.btn { - width: 14em; + width: 15em; + font-weight: bold; small { font-weight: normal; } } } a.btn { - font-weight: bold; width: 11em; margin: 10px auto; display: block; diff --git a/certs/app/assets/javascripts/leap_web_certs/.gitkeep b/app/assets/stylesheets/leap_web_users/.gitkeep similarity index 100% rename from certs/app/assets/javascripts/leap_web_certs/.gitkeep rename to app/assets/stylesheets/leap_web_users/.gitkeep diff --git a/certs/app/assets/stylesheets/leap_web_certs/.gitkeep b/app/controllers/.gitkeep similarity index 100% rename from certs/app/assets/stylesheets/leap_web_certs/.gitkeep rename to app/controllers/.gitkeep diff --git a/users/app/controllers/account_settings_controller.rb b/app/controllers/account_settings_controller.rb similarity index 100% rename from users/app/controllers/account_settings_controller.rb rename to app/controllers/account_settings_controller.rb diff --git a/users/app/controllers/controller_extension/authentication.rb b/app/controllers/controller_extension/authentication.rb similarity index 74% rename from users/app/controllers/controller_extension/authentication.rb rename to app/controllers/controller_extension/authentication.rb index d831fbe9f1c6c12b2a709d4d1c2c2e149ee33423..1f73f38e6a6382f176332617efc811d6d4dc9576 100644 --- a/users/app/controllers/controller_extension/authentication.rb +++ b/app/controllers/controller_extension/authentication.rb @@ -8,17 +8,24 @@ module ControllerExtension::Authentication end def current_user - @current_user ||= token_authenticate || warden.user + @current_user ||= token_authenticate || warden.user || anonymous end def logged_in? - !!current_user + current_user.is_a? User end - def authorize + def require_login access_denied unless logged_in? end + # some actions only make sense if you are not logged in yet. + # (login, signup). If a user tries to perform these they will + # be redirected to their dashboard. + def redirect_if_logged_in + redirect_to home_url if logged_in? + end + def access_denied respond_to do |format| format.html do @@ -35,10 +42,10 @@ module ControllerExtension::Authentication end def admin? - current_user && current_user.is_admin? + current_user.is_admin? end - def authorize_admin + def require_admin access_denied unless admin? end @@ -65,4 +72,10 @@ module ControllerExtension::Authentication request.env['warden.options'] && request.env['warden.options'][:attempted_path] end + + protected + + def anonymous + AnonymousUser.new + end end diff --git a/app/controllers/controller_extension/token_authentication.rb b/app/controllers/controller_extension/token_authentication.rb new file mode 100644 index 0000000000000000000000000000000000000000..6e0a6ce9a78954caecb7ef1de8bab8958800d9ab --- /dev/null +++ b/app/controllers/controller_extension/token_authentication.rb @@ -0,0 +1,27 @@ +module ControllerExtension::TokenAuthentication + extend ActiveSupport::Concern + + def token + @token ||= authenticate_with_http_token do |token_id, options| + Token.find(token_id) + end + end + + def token_authenticate + @token_authenticated ||= token.authenticate if token + end + + def require_token + access_denied unless token_authenticate + end + + def logout + super + clear_token + end + + def clear_token + token.destroy if token + end +end + diff --git a/users/app/controllers/keys_controller.rb b/app/controllers/keys_controller.rb similarity index 100% rename from users/app/controllers/keys_controller.rb rename to app/controllers/keys_controller.rb diff --git a/users/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb similarity index 91% rename from users/app/controllers/sessions_controller.rb rename to app/controllers/sessions_controller.rb index 0195f30ce7c8c7f776be0c82463ffdbbdf9b8982..8919a4d59205f419a012a45d518434d31c9bef91 100644 --- a/users/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -1,7 +1,8 @@ class SessionsController < ApplicationController + before_filter :redirect_if_logged_in, :only => [:new] + def new - redirect_to home_url if logged_in? @session = Session.new if authentication_errors @errors = authentication_errors diff --git a/users/app/controllers/users_base_controller.rb b/app/controllers/users_base_controller.rb similarity index 100% rename from users/app/controllers/users_base_controller.rb rename to app/controllers/users_base_controller.rb diff --git a/users/app/controllers/users_controller.rb b/app/controllers/users_controller.rb similarity index 89% rename from users/app/controllers/users_controller.rb rename to app/controllers/users_controller.rb index a5461cda9ca510f97eda2bb003f47ab245cddacb..c8e09b6b886123da3a605d55505fcbda05c9439e 100644 --- a/users/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -4,9 +4,10 @@ class UsersController < UsersBaseController - before_filter :authorize, :only => [:show, :edit, :update, :destroy] + before_filter :require_login, :except => [:new] + before_filter :redirect_if_logged_in, :only => [:new] + before_filter :require_admin, :only => [:index, :deactivate, :enable] before_filter :fetch_user, :only => [:show, :edit, :update, :destroy, :deactivate, :enable] - before_filter :authorize_admin, :only => [:index, :deactivate, :enable] respond_to :html diff --git a/app/controllers/v1/certs_controller.rb b/app/controllers/v1/certs_controller.rb new file mode 100644 index 0000000000000000000000000000000000000000..73409ef0eaab29aa30717b2fb8b73b862292c626 --- /dev/null +++ b/app/controllers/v1/certs_controller.rb @@ -0,0 +1,20 @@ +class V1::CertsController < ApplicationController + + before_filter :require_login, :unless => :anonymous_certs_allowed? + + # GET /cert + def show + @cert = ClientCertificate.new(:prefix => service_level.cert_prefix) + render text: @cert.to_s, content_type: 'text/plain' + end + + protected + + def anonymous_certs_allowed? + APP_CONFIG[:allow_anonymous_certs] + end + + def service_level + current_user.effective_service_level + end +end diff --git a/app/controllers/v1/messages_controller.rb b/app/controllers/v1/messages_controller.rb new file mode 100644 index 0000000000000000000000000000000000000000..85156b71c04f26d23240a35969061436679d6557 --- /dev/null +++ b/app/controllers/v1/messages_controller.rb @@ -0,0 +1,24 @@ +module V1 + class MessagesController < ApplicationController + + skip_before_filter :verify_authenticity_token + before_filter :require_token + + respond_to :json + + def index + render json: current_user.messages + end + + def update + if message = Message.find(params[:id]) + message.mark_as_read_by(current_user) + message.save + render json: true + else + render json: false + end + end + + end +end diff --git a/app/controllers/v1/services_controller.rb b/app/controllers/v1/services_controller.rb new file mode 100644 index 0000000000000000000000000000000000000000..594940e0909c5af0327de604a35205686aeff114 --- /dev/null +++ b/app/controllers/v1/services_controller.rb @@ -0,0 +1,8 @@ +class V1::ServicesController < ApplicationController + + respond_to :json + + def show + respond_with current_user.effective_service_level + end +end diff --git a/users/app/controllers/v1/sessions_controller.rb b/app/controllers/v1/sessions_controller.rb similarity index 93% rename from users/app/controllers/v1/sessions_controller.rb rename to app/controllers/v1/sessions_controller.rb index eb6c3223c267bcd7d5466f9bc34e9db9988c9d3a..d88fcdc6ebfdac86bbaa8da1fc4e27a29e0320ba 100644 --- a/users/app/controllers/v1/sessions_controller.rb +++ b/app/controllers/v1/sessions_controller.rb @@ -2,6 +2,7 @@ module V1 class SessionsController < ApplicationController skip_before_filter :verify_authenticity_token + before_filter :require_token, only: :destroy def new @session = Session.new @@ -37,7 +38,7 @@ module V1 def login_response handshake = session.delete(:handshake) || {} - handshake.to_hash.merge(:id => current_user.id, :token => @token.id) + handshake.to_hash.merge(:id => current_user.id, :token => @token.to_s) end end diff --git a/users/app/controllers/v1/users_controller.rb b/app/controllers/v1/users_controller.rb similarity index 87% rename from users/app/controllers/v1/users_controller.rb rename to app/controllers/v1/users_controller.rb index 0903888c4cc8e6cd07f6c6eb405534bba57d96cc..8897d015cf160a91c2ddbfdc2848cfa34404d1ec 100644 --- a/users/app/controllers/v1/users_controller.rb +++ b/app/controllers/v1/users_controller.rb @@ -3,8 +3,8 @@ module V1 skip_before_filter :verify_authenticity_token before_filter :fetch_user, :only => [:update] - before_filter :authorize, :only => [:update] - before_filter :authorize_admin, :only => [:index] + before_filter :require_admin, :only => [:index] + before_filter :require_token, :only => [:update] respond_to :json diff --git a/users/app/controllers/webfinger_controller.rb b/app/controllers/webfinger_controller.rb similarity index 100% rename from users/app/controllers/webfinger_controller.rb rename to app/controllers/webfinger_controller.rb diff --git a/app/designs/message/by_user_ids_to_show.js b/app/designs/message/by_user_ids_to_show.js new file mode 100644 index 0000000000000000000000000000000000000000..e33566b9208aa98570292fd6712d9c580d63922f --- /dev/null +++ b/app/designs/message/by_user_ids_to_show.js @@ -0,0 +1,7 @@ +function (doc) { + if (doc.type === 'Message' && doc.user_ids_to_show && Array.isArray(doc.user_ids_to_show)) { + doc.user_ids_to_show.forEach(function (userId) { + emit(userId, 1); + }); + } +} diff --git a/app/designs/message/by_user_ids_to_show_and_created_at.js b/app/designs/message/by_user_ids_to_show_and_created_at.js new file mode 100644 index 0000000000000000000000000000000000000000..54e460443bf48e9cb6568a3ebc3937872a5c9d27 --- /dev/null +++ b/app/designs/message/by_user_ids_to_show_and_created_at.js @@ -0,0 +1,9 @@ +// not using at moment +// call with something like Message.by_user_ids_to_show_and_created_at.startkey([user_id, start_date]).endkey([user_id,end_date]) +function (doc) { + if (doc.type === 'Message' && doc.user_ids_to_show && Array.isArray(doc.user_ids_to_show)) { + doc.user_ids_to_show.forEach(function (userId) { + emit([userId, doc.created_at], 1); + }); + } +} diff --git a/app/designs/user/by_created_at_and_one_month_warning_not_sent.js b/app/designs/user/by_created_at_and_one_month_warning_not_sent.js new file mode 100644 index 0000000000000000000000000000000000000000..53a95dee667717907e6eb48d6baa060bed2103c5 --- /dev/null +++ b/app/designs/user/by_created_at_and_one_month_warning_not_sent.js @@ -0,0 +1,5 @@ +function (doc) { + if ((doc['type'] == 'User') && (doc['created_at'] != null) && (doc['one_month_warning_sent'] == null)) { + emit(doc['created_at'], 1); + } +} diff --git a/certs/app/controllers/.gitkeep b/app/helpers/.gitkeep similarity index 100% rename from certs/app/controllers/.gitkeep rename to app/helpers/.gitkeep diff --git a/core/app/helpers/core_helper.rb b/app/helpers/core_helper.rb similarity index 51% rename from core/app/helpers/core_helper.rb rename to app/helpers/core_helper.rb index a6c74790793b9d112243aa4bb520ade85f036ca6..4126906557dfbc0b310cd6358b06de830e4b715a 100644 --- a/core/app/helpers/core_helper.rb +++ b/app/helpers/core_helper.rb @@ -6,8 +6,8 @@ module CoreHelper # # insert common buttons (download, login, etc) # - def home_page_buttons(on_user_page = false) - render 'common/home_page_buttons', {:on_user_page => on_user_page} + def home_page_buttons + render 'common/home_page_buttons' end end diff --git a/core/app/helpers/download_helper.rb b/app/helpers/download_helper.rb similarity index 100% rename from core/app/helpers/download_helper.rb rename to app/helpers/download_helper.rb diff --git a/users/app/helpers/email_aliases_helper.rb b/app/helpers/email_aliases_helper.rb similarity index 100% rename from users/app/helpers/email_aliases_helper.rb rename to app/helpers/email_aliases_helper.rb diff --git a/core/app/helpers/navigation_helper.rb b/app/helpers/navigation_helper.rb similarity index 100% rename from core/app/helpers/navigation_helper.rb rename to app/helpers/navigation_helper.rb diff --git a/users/app/helpers/sessions_helper.rb b/app/helpers/sessions_helper.rb similarity index 100% rename from users/app/helpers/sessions_helper.rb rename to app/helpers/sessions_helper.rb diff --git a/users/app/helpers/users_helper.rb b/app/helpers/users_helper.rb similarity index 69% rename from users/app/helpers/users_helper.rb rename to app/helpers/users_helper.rb index f56faab0225cc4c75209e06f01fb6662fa9f200b..1b2dc5d227e1b512ae823aa0b91fc7611f487beb 100644 --- a/users/app/helpers/users_helper.rb +++ b/app/helpers/users_helper.rb @@ -1,7 +1,7 @@ module UsersHelper def user_form_class(*classes) - (classes + ['user', 'form', (@user.new_record? ? 'new' : 'edit')]).compact.join(' ') + (classes + ['user', 'hidden', 'js-show', (@user.new_record? ? 'new' : 'edit')]).compact.join(' ') end def wrapped(item, options = {}) diff --git a/users/app/models/account.rb b/app/models/account.rb similarity index 100% rename from users/app/models/account.rb rename to app/models/account.rb diff --git a/app/models/anonymous_service_level.rb b/app/models/anonymous_service_level.rb new file mode 100644 index 0000000000000000000000000000000000000000..4366a4a4e6d5fdee2427c0d22c8465615991e38b --- /dev/null +++ b/app/models/anonymous_service_level.rb @@ -0,0 +1,30 @@ +class AnonymousServiceLevel + + delegate :to_json, to: :config_hash + + def cert_prefix + if APP_CONFIG[:allow_limited_certs] + APP_CONFIG[:limited_cert_prefix] + elsif APP_CONFIG[:allow_unlimited_certs] + APP_CONFIG[:unlimited_cert_prefix] + end + end + + def description + if APP_CONFIG[:allow_anonymous_certs] + "anonymous access to the VPN" + else + "please login to access our services" + end + end + + protected + + def config_hash + { name: "anonymous", + description: description, + eip_rate_limit: APP_CONFIG[:allow_limited_certs] + } + end + +end diff --git a/app/models/anonymous_user.rb b/app/models/anonymous_user.rb new file mode 100644 index 0000000000000000000000000000000000000000..87239eb0a69e4e71cc7e082b09744a1040d9a510 --- /dev/null +++ b/app/models/anonymous_user.rb @@ -0,0 +1,31 @@ +# The nil object for the user class +class AnonymousUser < Object + + def effective_service_level + AnonymousServiceLevel.new + end + + def is_admin? + false + end + + def id + nil + end + + def email + nil + end + + def email_address + nil + end + + def login + nil + end + + def messages + [] + end +end diff --git a/certs/app/models/client_certificate.rb b/app/models/client_certificate.rb similarity index 100% rename from certs/app/models/client_certificate.rb rename to app/models/client_certificate.rb diff --git a/users/app/models/email.rb b/app/models/email.rb similarity index 100% rename from users/app/models/email.rb rename to app/models/email.rb diff --git a/users/app/models/identity.rb b/app/models/identity.rb similarity index 96% rename from users/app/models/identity.rb rename to app/models/identity.rb index 9b97b51b34d37dec0b15113a8c3e216739c9c370..ad8c01e45ea01a667a599d48b9deef4a7e9bfedb 100644 --- a/users/app/models/identity.rb +++ b/app/models/identity.rb @@ -70,6 +70,12 @@ class Identity < CouchRest::Model::Base end end + def self.destroy_all_for(user) + Identity.by_user_id.key(user.id).each do |identity| + identity.destroy + end + end + def self.destroy_all_disabled Identity.disabled.each do |identity| identity.destroy diff --git a/users/app/models/local_email.rb b/app/models/local_email.rb similarity index 100% rename from users/app/models/local_email.rb rename to app/models/local_email.rb diff --git a/users/app/models/login_format_validation.rb b/app/models/login_format_validation.rb similarity index 100% rename from users/app/models/login_format_validation.rb rename to app/models/login_format_validation.rb diff --git a/app/models/message.rb b/app/models/message.rb new file mode 100644 index 0000000000000000000000000000000000000000..424f0941c6f92e33fdb4c43f6037869bb4a9057a --- /dev/null +++ b/app/models/message.rb @@ -0,0 +1,29 @@ +class Message < CouchRest::Model::Base + + use_database :messages + + property :text, String + property :user_ids_to_show, [String] + property :user_ids_have_shown, [String] # is this necessary to store? + + timestamps! + + design do + own_path = Pathname.new(File.dirname(__FILE__)) + load_views(own_path.join('..', 'designs', 'message')) + end + + def mark_as_read_by(user) + user_ids_to_show.delete(user.id) + # is it necessary to keep track of what users have already seen it? + user_ids_have_shown << user.id unless read_by?(user) + end + + def read_by?(user) + user_ids_have_shown.include?(user.id) + end + + def unread_by?(user) + user_ids_to_show.include?(user.id) + end +end diff --git a/users/app/models/pgp_key.rb b/app/models/pgp_key.rb similarity index 100% rename from users/app/models/pgp_key.rb rename to app/models/pgp_key.rb diff --git a/app/models/service_level.rb b/app/models/service_level.rb new file mode 100644 index 0000000000000000000000000000000000000000..a8df55bcd25005498e7b00334277860702f225d5 --- /dev/null +++ b/app/models/service_level.rb @@ -0,0 +1,46 @@ +class ServiceLevel + + def initialize(attributes = {}) + @id = attributes[:id] || APP_CONFIG[:default_service_level] + end + + def self.select_options + APP_CONFIG[:service_levels].map do |id,config_hash| + [config_hash[:description], id] + end + end + + def id + @id + end + + delegate :to_json, to: :config_hash + + def cert_prefix + if limited_cert? + APP_CONFIG[:limited_cert_prefix] + elsif APP_CONFIG[:allow_unlimited_certs] + APP_CONFIG[:unlimited_cert_prefix] + end + end + + def provides?(service) + services.include? service + end + + def services + config_hash[:services] || [] + end + + protected + + def limited_cert? + APP_CONFIG[:allow_limited_certs] && + (!APP_CONFIG[:allow_unlimited_certs] || config_hash[:eip_rate_limit]) + end + + def config_hash + @config_hash || APP_CONFIG[:service_levels][@id].with_indifferent_access + end + +end diff --git a/users/app/models/session.rb b/app/models/session.rb similarity index 100% rename from users/app/models/session.rb rename to app/models/session.rb diff --git a/users/app/models/token.rb b/app/models/token.rb similarity index 81% rename from users/app/models/token.rb rename to app/models/token.rb index 001eb40d12b77f9980587a0f9ff564652a5b04c3..e759ee33871595aa84b7784ba87d4cc97f622a94 100644 --- a/users/app/models/token.rb +++ b/app/models/token.rb @@ -30,6 +30,10 @@ class Token < CouchRest::Model::Base end end + def to_s + id + end + def authenticate if expired? destroy @@ -40,6 +44,14 @@ class Token < CouchRest::Model::Base end end + # Tokens can be cleaned up in different ways. + # So let's make sure we don't crash if they disappeared + def destroy_with_rescue + destroy_without_rescue + rescue RestClient::ResourceNotFound + end + alias_method_chain :destroy, :rescue + def touch self.last_seen_at = Time.now save diff --git a/users/app/models/user.rb b/app/models/user.rb similarity index 66% rename from users/app/models/user.rb rename to app/models/user.rb index 720f5a95c2b2d1956b41bca0276c1941f9b14eb5..6678de6bafc322793fe151eb422cb99c34e1387f 100644 --- a/users/app/models/user.rb +++ b/app/models/user.rb @@ -13,6 +13,8 @@ class User < CouchRest::Model::Base property :desired_service_level_code, Integer, :accessible => true property :effective_service_level_code, Integer, :accessible => true + property :one_month_warning_sent, TrueClass + before_save :update_effective_service_level validates :login, :password_salt, :password_verifier, @@ -59,6 +61,15 @@ class User < CouchRest::Model::Base login end + # use this if you want to get a working email address only. + def email + if effective_service_level.provides?('email') + email_address + end + end + + # use this if you want the email address associated with a + # user no matter if the user actually has a local email account def email_address LocalEmail.new(login) end @@ -72,6 +83,14 @@ class User < CouchRest::Model::Base Ticket.for_user(self).limit(count).all #defaults to having most recent updated first end + def messages(unseen = true) + #TODO for now this only shows unseen messages. Will we ever want seen ones? Is it necessary to store? + + # we don't want to emit all the userids associated with a message, so only emit id and text. + Message.by_user_ids_to_show.key(self.id).map { |message| [message.id, message.text] } + + end + # DEPRECATED # # Please set the key on the identity directly @@ -110,6 +129,32 @@ class User < CouchRest::Model::Base ServiceLevel.new({id: code}) end + + def self.send_one_month_warnings + + # To determine warnings to send, need to get all users where one_month_warning_sent is not set, and where it was created greater than or equal to 1 month ago. + # TODO: might want to further limit to enabled accounts, and, based on provider's service level configuration, for particular service levels. + users_to_warn = User.by_created_at_and_one_month_warning_not_sent.endkey(Time.now-1.month) + + users_to_warn.each do |user| + # instead of loop could use something like: + # message.user_ids_to_show = users_to_warn.map(&:id) + # but would still need to loop through users to store one_month_warning_sent + + if !@message + # create a message for today's date + # only want to create once, and only if it will be used. + @message = Message.new(:text => I18n.t(:payment_one_month_warning, :date_in_one_month => (Time.now+1.month).strftime("%Y-%d-%m"))) + end + + @message.user_ids_to_show << user.id + user.one_month_warning_sent = true + user.save + end + @message.save if @message + + end + protected ## diff --git a/certs/app/helpers/.gitkeep b/app/views/.gitkeep similarity index 100% rename from certs/app/helpers/.gitkeep rename to app/views/.gitkeep diff --git a/app/views/common/_action_buttons.html.haml b/app/views/common/_action_buttons.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..c74fcd10f485e57a20775a3a8f6361b2517f0bcc --- /dev/null +++ b/app/views/common/_action_buttons.html.haml @@ -0,0 +1,11 @@ +.home-buttons + .row-fluid.second + .login.span4 + %span.link= link_to(icon('ok-sign', icon_color) + t(:login), login_path, :class => 'btn') + %span.info= t(:login_info) + .signup.span4 + %span.link= link_to(icon('user', icon_color) + t(:signup), signup_path, :class => 'btn') + %span.info= t(:signup_info) + .help.span4 + %span.link= link_to(icon('question-sign', icon_color) + t(:get_help), new_ticket_path, :class => 'btn') + %span.info= t(:help_info) diff --git a/app/views/common/_download_button.html.haml b/app/views/common/_download_button.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..e57c56b279f9a139e43fa0165832e2a4d58fd727 --- /dev/null +++ b/app/views/common/_download_button.html.haml @@ -0,0 +1,8 @@ +.home-buttons + .row-fluid.first + .span2 + .download.span8 + = link_to client_download_url, class: "btn btn-large btn-primary" do + = big_icon('download') + = t(:download_client) + .span2 diff --git a/app/views/common/_home_page_buttons.html.haml b/app/views/common/_home_page_buttons.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..8c479837a2202c5223789f2374e9c38fe9e04439 --- /dev/null +++ b/app/views/common/_home_page_buttons.html.haml @@ -0,0 +1,8 @@ +- icon_color = :black + += render 'common/download_button' +- if local_assigns[:divider] + .row-fluid + .span12 + = render local_assigns[:divider] += render 'common/action_buttons', icon_color: icon_color diff --git a/users/app/views/emails/_email.html.haml b/app/views/emails/_email.html.haml similarity index 100% rename from users/app/views/emails/_email.html.haml rename to app/views/emails/_email.html.haml diff --git a/app/views/home/_content.html.haml b/app/views/home/_content.html.haml index 3d351e9073a06f9052a7645e932601f701e8e3f5..e47fdaf21f3949117a1eb3af08fb05c866929fc0 100644 --- a/app/views/home/_content.html.haml +++ b/app/views/home/_content.html.haml @@ -8,7 +8,5 @@ - if Rails.env == 'development' .row-fluid %hr - %p - = link_to "fetch a cert", cert_path %p = link_to "make donation", new_payment_path if APP_CONFIG[:payment].present? diff --git a/core/app/views/kaminari/_first_page.html.haml b/app/views/kaminari/_first_page.html.haml similarity index 100% rename from core/app/views/kaminari/_first_page.html.haml rename to app/views/kaminari/_first_page.html.haml diff --git a/core/app/views/kaminari/_gap.html.haml b/app/views/kaminari/_gap.html.haml similarity index 100% rename from core/app/views/kaminari/_gap.html.haml rename to app/views/kaminari/_gap.html.haml diff --git a/core/app/views/kaminari/_last_page.html.haml b/app/views/kaminari/_last_page.html.haml similarity index 100% rename from core/app/views/kaminari/_last_page.html.haml rename to app/views/kaminari/_last_page.html.haml diff --git a/core/app/views/kaminari/_next_page.html.haml b/app/views/kaminari/_next_page.html.haml similarity index 100% rename from core/app/views/kaminari/_next_page.html.haml rename to app/views/kaminari/_next_page.html.haml diff --git a/core/app/views/kaminari/_page.html.haml b/app/views/kaminari/_page.html.haml similarity index 100% rename from core/app/views/kaminari/_page.html.haml rename to app/views/kaminari/_page.html.haml diff --git a/core/app/views/kaminari/_paginator.html.haml b/app/views/kaminari/_paginator.html.haml similarity index 100% rename from core/app/views/kaminari/_paginator.html.haml rename to app/views/kaminari/_paginator.html.haml diff --git a/core/app/views/kaminari/_prev_page.html.haml b/app/views/kaminari/_prev_page.html.haml similarity index 100% rename from core/app/views/kaminari/_prev_page.html.haml rename to app/views/kaminari/_prev_page.html.haml diff --git a/app/views/layouts/_footer.html.haml b/app/views/layouts/_footer.html.haml index 5909bdda9bce57bfa00e06a74d39fc9b625a41ce..340d36cd6bed867554db8e9ed5b5e6e09be3d40e 100644 --- a/app/views/layouts/_footer.html.haml +++ b/app/views/layouts/_footer.html.haml @@ -6,5 +6,5 @@ = link_to icon('info-sign') + t(:about), about_path - if lookup_context.exists?('pages/contact') = link_to icon('comment') + t(:contact), contact_path - - if APP_CONFIG[:service_levels] - = link_to icon('shopping-cart') + t(:pricing), pricing_path \ No newline at end of file + - if APP_CONFIG[:service_levels].present? + = link_to icon('shopping-cart') + t(:pricing), pricing_path diff --git a/app/views/layouts/_header.html.haml b/app/views/layouts/_header.html.haml index 157f1df68dbad3ce972a212ac00289d8abd0a8e7..a1dd47ae2f2fa180a05ab20d389d0d6b47032514 100644 --- a/app/views/layouts/_header.html.haml +++ b/app/views/layouts/_header.html.haml @@ -8,5 +8,5 @@ %li = link_to t(:logout), logout_path, :method => :delete - if @user && @show_navigation - .user_heading + .lead = @user.email_address diff --git a/app/views/layouts/_masthead.html.haml b/app/views/layouts/_masthead.html.haml index 35225a14f2744e29d0704fa49d86508ea29d4062..fde5915347cce6449272546f51c2ca3e0ebec56a 100644 --- a/app/views/layouts/_masthead.html.haml +++ b/app/views/layouts/_masthead.html.haml @@ -2,5 +2,3 @@ .title %span.sitename %a{:href => home_path}= APP_CONFIG[:domain] - - if @show_navigation - = t(:user_control_panel) \ No newline at end of file diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 1cd4ec380384fd23cc3026daebfdccaa728563a8..d213fe10789d93c8651b3c4bea60ff804feed0b2 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -14,6 +14,9 @@ = render 'layouts/masthead' #main .container-fluid + - if @show_navigation + .row-fluid + %h1= t(:user_control_panel) - if logged_in? .row-fluid .span12 diff --git a/app/views/pages/pricing.html.haml b/app/views/pages/pricing.html.haml index 77699d81d8de5dcbe2446ef0f122959f69c09f35..e339d2756cd1f637350735ddfc9b5675124377c2 100644 --- a/app/views/pages/pricing.html.haml +++ b/app/views/pages/pricing.html.haml @@ -13,9 +13,9 @@ %td= level[:name] %td= level[:description] %td - - if level[:cost].nil? || level[:cost] == 0 + - if level[:rate].nil? || level[:rate] == 0 = t(:free) - else - = level[:cost].map{|currency,cost| "#{cost} #{currency}"}.join(', ') + = level[:rate].collect{|currency, price| "#{currency} #{price}"}.join(', ') - else - No service levels are configured. \ No newline at end of file + No service levels are configured. diff --git a/app/views/sessions/new.html.haml b/app/views/sessions/new.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..bb7e4bdda6e8e4228fda6e71c2be3f0bf4349a19 --- /dev/null +++ b/app/views/sessions/new.html.haml @@ -0,0 +1,9 @@ +.span1 +.span9 + %h2=t :login + .lead=t :login_info + = render :partial => 'users/warnings' + = simple_form_for [:api, @session], validate: true, html: { id: :new_session, class: 'form-horizontal hidden js-show', style: "display:none;" } 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 } + = f.button :wrapped, value: t(:login), cancel: home_path diff --git a/users/app/views/sessions/new.json.erb b/app/views/sessions/new.json.erb similarity index 100% rename from users/app/views/sessions/new.json.erb rename to app/views/sessions/new.json.erb diff --git a/users/app/views/users/_change_password.html.haml b/app/views/users/_change_password.html.haml similarity index 100% rename from users/app/views/users/_change_password.html.haml rename to app/views/users/_change_password.html.haml diff --git a/users/app/views/users/_change_pgp_key.html.haml b/app/views/users/_change_pgp_key.html.haml similarity index 100% rename from users/app/views/users/_change_pgp_key.html.haml rename to app/views/users/_change_pgp_key.html.haml diff --git a/users/app/views/users/_change_service_level.html.haml b/app/views/users/_change_service_level.html.haml similarity index 71% rename from users/app/views/users/_change_service_level.html.haml rename to app/views/users/_change_service_level.html.haml index 61e67d98382c2f84b8ac9b19f50d14f1583ba17b..42315a2afd45b79385213041aba76070e30a3653 100644 --- a/users/app/views/users/_change_service_level.html.haml +++ b/app/views/users/_change_service_level.html.haml @@ -8,11 +8,11 @@ %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 + = f.select :desired_service_level_code, ServiceLevel.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 + = f.select :effective_service_level_code, ServiceLevel.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/app/views/users/_destroy_account.html.haml similarity index 100% rename from users/app/views/users/_destroy_account.html.haml rename to app/views/users/_destroy_account.html.haml diff --git a/users/app/views/users/_edit.html.haml b/app/views/users/_edit.html.haml similarity index 100% rename from users/app/views/users/_edit.html.haml rename to app/views/users/_edit.html.haml diff --git a/users/app/views/users/_user.html.haml b/app/views/users/_user.html.haml similarity index 100% rename from users/app/views/users/_user.html.haml rename to app/views/users/_user.html.haml diff --git a/users/app/views/users/_warnings.html.haml b/app/views/users/_warnings.html.haml similarity index 99% rename from users/app/views/users/_warnings.html.haml rename to app/views/users/_warnings.html.haml index 79ab1032f16d24479a97dbf4eb8e824e59efaaea..baf80a4409ce86450c1928a2d8ab0912d2812135 100644 --- a/users/app/views/users/_warnings.html.haml +++ b/app/views/users/_warnings.html.haml @@ -9,4 +9,4 @@ 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/app/views/users/edit.html.haml similarity index 100% rename from users/app/views/users/edit.html.haml rename to app/views/users/edit.html.haml diff --git a/users/app/views/users/index.html.haml b/app/views/users/index.html.haml similarity index 100% rename from users/app/views/users/index.html.haml rename to app/views/users/index.html.haml diff --git a/users/app/views/users/new.html.haml b/app/views/users/new.html.haml similarity index 53% rename from users/app/views/users/new.html.haml rename to app/views/users/new.html.haml index aecf831f2e4e0bd4035b3c5ee2c6cdc907287e80..bc36068fce91bcafe87cff0984c9929728902b27 100644 --- a/users/app/views/users/new.html.haml +++ b/app/views/users/new.html.haml @@ -1,19 +1,21 @@ -# --# This form is handled entirely by javascript, so take care when changing element ids. +-# This form is handled entirely by javascript +-# Please take care when changing element ids. +-# +-# The form is hidden when no js is available +-# to prevent submission in the clear. -# -- form_options = {:url => '/not-used', :html => {:id => 'new_user', :class => user_form_class('form-horizontal')}, :validate => true} +- form_options = {url: '/not-used', html: {id: 'new_user', class: user_form_class('form-horizontal'), style: 'display:none'}, validate: true} .span1 .span9 - = render :partial => 'warnings' %h2=t :signup + .lead=t :signup_info + = render :partial => 'warnings' = 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' + = f.button :wrapped, value: t(:signup), cancel: home_path diff --git a/users/app/views/users/show.html.haml b/app/views/users/show.html.haml similarity index 80% rename from users/app/views/users/show.html.haml rename to app/views/users/show.html.haml index c587017fecc1dac00bd0ad14e04418816e7b0370..ddc33ab3fafc0b7a70e66a5e22806090a6b88730 100644 --- a/users/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -20,6 +20,11 @@ - # %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 + %h4 To use bitmask services: + = link_to client_download_url, class: "btn btn-primary" do + %i.icon-arrow-down.icon-white + = t(:download_client) diff --git a/users/app/views/v1/sessions/new.json.erb b/app/views/v1/sessions/new.json.erb similarity index 100% rename from users/app/views/v1/sessions/new.json.erb rename to app/views/v1/sessions/new.json.erb diff --git a/users/app/views/webfinger/host_meta.xml.erb b/app/views/webfinger/host_meta.xml.erb similarity index 100% rename from users/app/views/webfinger/host_meta.xml.erb rename to app/views/webfinger/host_meta.xml.erb diff --git a/users/app/views/webfinger/search.xml.erb b/app/views/webfinger/search.xml.erb similarity index 100% rename from users/app/views/webfinger/search.xml.erb rename to app/views/webfinger/search.xml.erb diff --git a/certs/Gemfile b/certs/Gemfile deleted file mode 100644 index 992f2360d85037dc7c905f76287712639a380e9b..0000000000000000000000000000000000000000 --- a/certs/Gemfile +++ /dev/null @@ -1,14 +0,0 @@ -source "https://rubygems.org" - -eval(File.read(File.dirname(__FILE__) + '/../common_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/certs/Rakefile b/certs/Rakefile deleted file mode 100644 index 54ed86db506148695ffec9e3170e0152909e60cb..0000000000000000000000000000000000000000 --- a/certs/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 = 'LeapWebCerts' - rdoc.options << '--line-numbers' - rdoc.rdoc_files.include('README.rdoc') - rdoc.rdoc_files.include('lib/**/*.rb') -end - -spec = eval(File.read('leap_web_certs.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/certs/Readme.md b/certs/Readme.md deleted file mode 100644 index 4ea8d9da394745cff1a806ef8adc55f499afc1bb..0000000000000000000000000000000000000000 --- a/certs/Readme.md +++ /dev/null @@ -1,9 +0,0 @@ -LeapWebCerts -========= - - -Configuration -------------- - - -Currently LeapWebCerts falls back to handing out a cert in /config/cert if the cert pool is empty. You need to add that file in the application that includes this engine. diff --git a/certs/app/controllers/certs_controller.rb b/certs/app/controllers/certs_controller.rb deleted file mode 100644 index 62ef3fdf5ab310a583271a966419b41116155a78..0000000000000000000000000000000000000000 --- a/certs/app/controllers/certs_controller.rb +++ /dev/null @@ -1,51 +0,0 @@ -class CertsController < ApplicationController - - before_filter :login_if_required - - # GET /cert - def show - @cert = ClientCertificate.new(:prefix => certificate_prefix) - render text: @cert.to_s, content_type: 'text/plain' - end - - protected - - def login_if_required - authorize unless APP_CONFIG[:allow_anonymous_certs] - end - - # - # this is some temporary logic until we store the service level in the user db. - # - # better logic might look like this: - # - # if logged_in? - # service_level = user.service_level - # elsif allow_anonymous? - # service_level = service_levels[:anonymous] - # else - # service_level = nil - # end - # - # if service_level.bandwidth == 'limited' && allow_limited? - # prefix = limited - # elsif allow_unlimited? - # prefix = unlimited - # else - # prefix = nil - # end - # - def certificate_prefix - if logged_in? - if APP_CONFIG[:allow_unlimited_certs] - APP_CONFIG[:unlimited_cert_prefix] - elsif APP_CONFIG[:allow_limited_certs] - APP_CONFIG[:limited_cert_prefix] - end - elsif !APP_CONFIG[:allow_limited_certs] - APP_CONFIG[:unlimited_cert_prefix] - else - APP_CONFIG[:limited_cert_prefix] - end - end -end diff --git a/certs/app/helpers/certs_helper.rb b/certs/app/helpers/certs_helper.rb deleted file mode 100644 index 94e76b8eb7fa88ea462234b1e2614de101a990da..0000000000000000000000000000000000000000 --- a/certs/app/helpers/certs_helper.rb +++ /dev/null @@ -1,2 +0,0 @@ -module CertsHelper -end diff --git a/certs/app/models/.gitkeep b/certs/app/models/.gitkeep deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/certs/app/views/.gitkeep b/certs/app/views/.gitkeep deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/certs/config/locales/en.yml b/certs/config/locales/en.yml deleted file mode 100644 index 18e4f47f23cba785ecfd8e14cf1e89dab3d86825..0000000000000000000000000000000000000000 --- a/certs/config/locales/en.yml +++ /dev/null @@ -1,2 +0,0 @@ -en: - cert_pool_empty: "Sorry the Cert pool is empty, please check back later." diff --git a/certs/config/routes.rb b/certs/config/routes.rb deleted file mode 100644 index cb97757c658daafe0c9f06e5c33919f2f5613b41..0000000000000000000000000000000000000000 --- a/certs/config/routes.rb +++ /dev/null @@ -1,5 +0,0 @@ -Rails.application.routes.draw do - scope '/1' do - resource :cert, :only => [:show] - end -end diff --git a/certs/leap_web_certs.gemspec b/certs/leap_web_certs.gemspec deleted file mode 100644 index 21be09d9bda63aff7ac379dd3e913ed9a09c169e..0000000000000000000000000000000000000000 --- a/certs/leap_web_certs.gemspec +++ /dev/null @@ -1,21 +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_certs" - s.version = LeapWeb::VERSION - s.authors = ["Azul"] - s.email = ["azul@leap.se"] - s.homepage = "http://www.leap.se" - s.summary = "Cert distribution for the leap platform" - s.description = "This plugin for the leap platform distributes certs for the EIP client. It fetches the certs from a pool in CouchDB that is filled by leap-ca." - - s.files = Dir["{app,config,db,lib}/**/*"] + ["Rakefile", "Readme.md"] - s.test_files = Dir["test/**/*"] - - s.add_dependency "leap_web_core", LeapWeb::VERSION - s.add_dependency "certificate_authority", [">= 0.2.0"] - -end diff --git a/certs/lib/leap_web_certs.rb b/certs/lib/leap_web_certs.rb deleted file mode 100644 index beb683d94b18a04888d46e06704e3d1166da8ca6..0000000000000000000000000000000000000000 --- a/certs/lib/leap_web_certs.rb +++ /dev/null @@ -1,4 +0,0 @@ -require "leap_web_certs/engine" - -module LeapWebCerts -end diff --git a/certs/lib/leap_web_certs/engine.rb b/certs/lib/leap_web_certs/engine.rb deleted file mode 100644 index 3c8948a0d84ee364f89911ff7a406c1760840b78..0000000000000000000000000000000000000000 --- a/certs/lib/leap_web_certs/engine.rb +++ /dev/null @@ -1,7 +0,0 @@ -require "leap_web_core" - -module LeapWebCerts - class Engine < ::Rails::Engine - - end -end diff --git a/certs/lib/tasks/leap_web_certs_tasks.rake b/certs/lib/tasks/leap_web_certs_tasks.rake deleted file mode 100644 index e8fb7ffc57f2459f4b5c8c999a09900d6a5207e3..0000000000000000000000000000000000000000 --- a/certs/lib/tasks/leap_web_certs_tasks.rake +++ /dev/null @@ -1,4 +0,0 @@ -# desc "Explaining what the task does" -# task :leap_web_certs do -# # Task goes here -# end diff --git a/certs/script/rails b/certs/script/rails deleted file mode 100755 index 616d3c933f9dbbcd0d5d331d54a61ee6b23138b8..0000000000000000000000000000000000000000 --- a/certs/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_certs/engine', __FILE__) - -require 'rails/all' -require 'rails/engine/commands' diff --git a/certs/test/functional/certs_controller_test.rb b/certs/test/functional/certs_controller_test.rb deleted file mode 100644 index 503e74b9c9a18c4cf4d90d7045678b1ef18239d0..0000000000000000000000000000000000000000 --- a/certs/test/functional/certs_controller_test.rb +++ /dev/null @@ -1,44 +0,0 @@ -require 'test_helper' - -class CertsControllerTest < ActionController::TestCase - - test "send limited cert without login" do - with_config allow_limited_certs: true, allow_anonymous_certs: true do - cert = stub :to_s => "limited cert" - ClientCertificate.expects(:new).with(:prefix => APP_CONFIG[:limited_cert_prefix]).returns(cert) - get :show - assert_response :success - assert_equal cert.to_s, @response.body - end - end - - test "send unlimited cert" do - with_config allow_unlimited_certs: true do - login - cert = stub :to_s => "unlimited cert" - ClientCertificate.expects(:new).with(:prefix => APP_CONFIG[:unlimited_cert_prefix]).returns(cert) - get :show - assert_response :success - assert_equal cert.to_s, @response.body - end - end - - test "login required if anonymous certs disabled" do - with_config allow_anonymous_certs: false do - get :show - assert_response :redirect - end - end - - test "send limited cert" do - with_config allow_limited_certs: true, allow_unlimited_certs: false do - login - cert = stub :to_s => "real cert" - ClientCertificate.expects(:new).with(:prefix => APP_CONFIG[:limited_cert_prefix]).returns(cert) - get :show - assert_response :success - assert_equal cert.to_s, @response.body - end - end - -end diff --git a/certs/test/leap_web_certs_test.rb b/certs/test/leap_web_certs_test.rb deleted file mode 100644 index ee2058be12fe3c8e2ff4047d07acdda4852c07e2..0000000000000000000000000000000000000000 --- a/certs/test/leap_web_certs_test.rb +++ /dev/null @@ -1,7 +0,0 @@ -require 'test_helper' - -class LeapWebCertsTest < ActiveSupport::TestCase - test "truth" do - assert_kind_of Module, LeapWebCerts - end -end diff --git a/certs/test/test_helper.rb b/certs/test/test_helper.rb deleted file mode 100644 index f6b4eb830e3c12741a760b6237542d9607321687..0000000000000000000000000000000000000000 --- a/certs/test/test_helper.rb +++ /dev/null @@ -1,10 +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/common_dependencies.rb b/common_dependencies.rb deleted file mode 100644 index 2225613d4be561a315b2e1e93b319e574a871d15..0000000000000000000000000000000000000000 --- a/common_dependencies.rb +++ /dev/null @@ -1,22 +0,0 @@ -group :test do - # moching and stubing - gem 'mocha', '~> 0.13.0', :require => false - # integration testing - gem 'capybara' - # headless js integration testing - gem 'poltergeist' - # required for save_and_open_page in integration tests - # gem 'launchy' - gem 'fake_braintree' #depends on rspec? - gem 'faker' - gem 'factory_girl_rails' -end - -group :test, :development do - gem 'thin' - gem 'quiet_assets' -end - -group :production do - gem 'SyslogLogger', '~> 2.0' -end diff --git a/config/defaults.yml b/config/defaults.yml index cb1879544d339c5dd60cafe9be52758869d2f2f0..1c7e69498c70782c2d7cf03c42985603c65fa5b6 100644 --- a/config/defaults.yml +++ b/config/defaults.yml @@ -1,6 +1,6 @@ dev_ca: &dev_ca - client_ca_key: "./certs/test/files/ca.key" - client_ca_cert: "./certs/test/files/ca.crt" + client_ca_key: "./test/files/ca.key" + client_ca_cert: "./test/files/ca.crt" ca_key_password: nil cert_options: &cert_options @@ -49,23 +49,22 @@ common: &common service_levels: &service_levels service_levels: - 0: - name: anonymous - cert_prefix: "LIMITED" - description: "anonymous account, with rate limited VPN" 1: name: free - cert_prefix: "LIMITED" description: "free account, with rate limited VPN" - cost: 0 - quota: 100 + eip_rate_limit: true + storage: 100 + services: + - eip 2: name: premium - cert_prefix: "UNLIMITED" description: "premium account, with unlimited vpn" - cost: + rate: USD: 10 EUR: 10 + services: + - eip + - email default_service_level: 1 development: diff --git a/users/config/initializers/add_controller_methods.rb b/config/initializers/add_controller_methods.rb similarity index 100% rename from users/config/initializers/add_controller_methods.rb rename to config/initializers/add_controller_methods.rb diff --git a/core/config/initializers/couchrest_model.rb b/config/initializers/couchrest_model.rb similarity index 73% rename from core/config/initializers/couchrest_model.rb rename to config/initializers/couchrest_model.rb index ce4f41a249c7e83b0bb95df88dc1d7c55410865f..1a3e921114c5bf9245bf19e0b6c5d392dee0a1f5 100644 --- a/core/config/initializers/couchrest_model.rb +++ b/config/initializers/couchrest_model.rb @@ -1,3 +1,5 @@ +require 'extensions/couchrest' + CouchRest::Model::Base.configure do |config| config.auto_update_design_doc = false end diff --git a/users/config/initializers/error_constants.rb b/config/initializers/error_constants.rb similarity index 64% rename from users/config/initializers/error_constants.rb rename to config/initializers/error_constants.rb index d4a0f527c05eb1553b68cd04e40edaa85fe4eaf1..fdd3624591f50261811211f690e4afde477b3de7 100644 --- a/users/config/initializers/error_constants.rb +++ b/config/initializers/error_constants.rb @@ -1 +1,3 @@ +require 'ruby-srp' + WRONG_PASSWORD = SRP::WrongPassword diff --git a/core/config/initializers/simple_form.rb b/config/initializers/simple_form.rb similarity index 99% rename from core/config/initializers/simple_form.rb rename to config/initializers/simple_form.rb index e3f8d09623f3e0ee2c725fc5d91b8c24461ca576..710daccdd203c3f06f80469b5b98f84255f27d7c 100644 --- a/core/config/initializers/simple_form.rb +++ b/config/initializers/simple_form.rb @@ -1,3 +1,5 @@ +require 'extensions/simple_form' + # Use this setup block to configure all options available in SimpleForm. SimpleForm.setup do |config| # Wrappers are used by the form builder to generate a diff --git a/core/config/initializers/simple_form_bootstrap.rb b/config/initializers/simple_form_bootstrap.rb similarity index 100% rename from core/config/initializers/simple_form_bootstrap.rb rename to config/initializers/simple_form_bootstrap.rb diff --git a/core/config/initializers/validations.rb b/config/initializers/validations.rb similarity index 100% rename from core/config/initializers/validations.rb rename to config/initializers/validations.rb diff --git a/users/config/initializers/warden.rb b/config/initializers/warden.rb similarity index 70% rename from users/config/initializers/warden.rb rename to config/initializers/warden.rb index 45feb6cc28b37e6dca2715b59afc7c5738a4908e..22892b3538f9d4bb0a51d7140a718ea1f13a22a9 100644 --- a/users/config/initializers/warden.rb +++ b/config/initializers/warden.rb @@ -1,3 +1,6 @@ +require "warden/session_serializer" +require "warden/strategies/secure_remote_password" + Rails.configuration.middleware.use RailsWarden::Manager do |config| config.default_strategies :secure_remote_password config.failure_app = SessionsController diff --git a/config/initializers/webfinger.rb b/config/initializers/webfinger.rb new file mode 100644 index 0000000000000000000000000000000000000000..197062ce2a89c7b301f24a7e0089f1f86a42de80 --- /dev/null +++ b/config/initializers/webfinger.rb @@ -0,0 +1 @@ +require 'webfinger' diff --git a/config/locales/en.yml b/config/locales/en.yml index 96c47ca85bfdf7e8c4fb76c14336e61170419fd8..cebf0753bf754a506e1b7cb2db1ca407cd4799f2 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -3,4 +3,44 @@ en: terms_of_service: Terms of Service pricing: Pricing about: About Us - contact: Contact \ No newline at end of file + contact: Contact + no_such_thing: "No such %{thing}." + thing_was_successfully_created: "%{thing} was successfully created." + create_thing: "Create %{thing}" + + overview: "Overview" + user_control_panel: "user control panel" + + 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." + + download_client: "Download Bitmask" + client_info: "The Bitmask application allows you to use %{provider} services." + all_downloads_info: "It is available for %{clients}." + other_downloads_info: "Bitmask is also available for %{clients}." + login_info: "Log in to change your account settings, create support tickets, and manage payments." + signup_info: "Get a user account via this website. We recommend registering via the Bitmask application instead unless you are only using Bitmask for Android." + welcome: "Welcome to %{provider}." + get_help: "Get Help" + help_info: "Can't login? Create a new support ticket anonymously." + example_email: 'user@domain.org' + os: + linux32: "Linux (32 bit)" + linux64: "Linux (64 bit)" + linux: "GNU/Linux" + windows: "Windows" + android: "Android" + osx: "Mac OS" + other: "(not available for your OS)" + diff --git a/core/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml similarity index 79% rename from core/config/locales/simple_form.en.yml rename to config/locales/simple_form.en.yml index 0df11fe0f32d653ab1b9a11fa591f3a1d0bcbe1d..5d0c675abf70d2e56773d946904f29e55d6bcc21 100644 --- a/core/config/locales/simple_form.en.yml +++ b/config/locales/simple_form.en.yml @@ -10,6 +10,9 @@ en: # html: '<abbr title="required">*</abbr>' error_notification: default_message: "Please review the problems below:" + buttons: + cancel: 'Cancel' + loading: 'Loading...' # Labels and hints examples # labels: # defaults: @@ -23,4 +26,11 @@ en: # defaults: # username: 'User name to sign in.' # password: 'No special characters, please.' + helpers: + submit: + user: + create: "Sign up" + update: "Save" + session: + create: "Log in" diff --git a/users/config/locales/en.yml b/config/locales/users.en.yml similarity index 92% rename from users/config/locales/en.yml rename to config/locales/users.en.yml index e597164329657be34a1bab8a7a0798a77c079c5b..0ca5a730fceda765092b00907c593693db447b9a 100644 --- a/users/config/locales/en.yml +++ b/config/locales/users.en.yml @@ -3,13 +3,11 @@ en: 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)." @@ -37,6 +35,7 @@ en: 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? + 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." @@ -47,7 +46,7 @@ en: 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." + overview_account: "Destroy your account." # # rails diff --git a/config/routes.rb b/config/routes.rb index f8bb8fbf35f0a34c89e38732a10f9d17462bf483..745b97d0d8018f9e01fb8f644bfd8490faecdda0 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -16,4 +16,34 @@ LeapWeb::Application.routes.draw do end get '/provider.json' => 'static_config#provider' + + namespace "api", { module: "v1", + path: "/1/", + defaults: {format: 'json'} } do + resources :sessions, :only => [:new, :create, :update], + :constraints => { :id => /[^\/]+(?=\.json\z)|[^\/]+/ } + delete "logout" => "sessions#destroy", :as => "logout" + resources :users, :only => [:create, :update, :destroy, :index] + resources :messages, :only => [:index, :update] + resource :cert, :only => [:show] + resource :service, :only => [:show] + 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/core/Gemfile b/core/Gemfile deleted file mode 100644 index b552dc586bf6b33dc64646cce51c83ade4afeaf8..0000000000000000000000000000000000000000 --- a/core/Gemfile +++ /dev/null @@ -1,17 +0,0 @@ -source "https://rubygems.org" - -# Declare your gem's dependencies in leap_web_core.gemspec. -# Bundler will treat runtime dependencies like base dependencies, and -# development dependencies will be added by default to the :development group. -gemspec - -# jquery-rails is used by the dummy application -gem "jquery-rails" - -# Declare any dependencies that are still in development here instead of in -# your gemspec. These might include edge Rails or gems from your path or -# Git. Remember to move these dependencies to your gemspec before releasing -# your gem to rubygems.org. - -# To use debugger -# gem 'ruby-debug' diff --git a/core/Rakefile b/core/Rakefile deleted file mode 100644 index 3c6539ce230d8efdf22b357fd785f401df297d44..0000000000000000000000000000000000000000 --- a/core/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 = 'LeapWebCore' - rdoc.options << '--line-numbers' - rdoc.rdoc_files.include('README.rdoc') - rdoc.rdoc_files.include('lib/**/*.rb') -end - -spec = eval(File.read('leap_web_core.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/core/Readme.md b/core/Readme.md deleted file mode 100644 index 795c0a49dce0cf15e954761ae4dfe226629eb534..0000000000000000000000000000000000000000 --- a/core/Readme.md +++ /dev/null @@ -1,6 +0,0 @@ -Leap Web Core -=== - -[Leap](http://www.leap.se) is the Leap Encryption Access Project and this is the rails app for its web interface. - -This is the its core gem. Currently it only serves to load shared dependencies. diff --git a/core/app/views/common/_download_for_os.html.haml b/core/app/views/common/_download_for_os.html.haml deleted file mode 100644 index 3a11d1068573e09a1b36a247caef6a93f419d883..0000000000000000000000000000000000000000 --- a/core/app/views/common/_download_for_os.html.haml +++ /dev/null @@ -1,17 +0,0 @@ -- os = download_for_os -%div{:class => "os-#{os}"} - %span.link - - btn_class = (os == "other") ? "disabled" : "btn-primary" - = link_to client_download_url(os), :class => "btn btn-large #{btn_class}" do - = big_icon('download') - .pull-right - = t(:download_client) - %br/ - %small= I18n.t("os.#{os}") - %span.info - %div= t(:client_info, :provider => content_tag(:b,APP_CONFIG[:domain])).html_safe - %div - - if os == "other" - = t(:all_downloads_info, :clients => alternative_client_links(os).to_sentence).html_safe - - else - = t(:other_downloads_info, :clients => alternative_client_links(os).to_sentence).html_safe diff --git a/core/app/views/common/_home_page_buttons.html.haml b/core/app/views/common/_home_page_buttons.html.haml deleted file mode 100644 index c9ea7a27d89f411549e5d532449051837528a90f..0000000000000000000000000000000000000000 --- a/core/app/views/common/_home_page_buttons.html.haml +++ /dev/null @@ -1,23 +0,0 @@ -- icon_color = :black - -.home-buttons - .row-fluid.first - .span2 - .download.span8 - = render partial: 'common/download_for_os', collection: available_clients + ['other'] - .span2 - - if local_assigns[:divider] - .row-fluid - .span12 - = render local_assigns[:divider] - - if !local_assigns[:on_user_page] - .row-fluid.second - .login.span4 - %span.link= link_to(icon('ok-sign', icon_color) + t(:login), login_path, :class => 'btn') - %span.info= t(:login_info) - .signup.span4 - %span.link= link_to(icon('user', icon_color) + t(:signup), signup_path, :class => 'btn') - %span.info= t(:signup_info) - .help.span4 - %span.link= link_to(icon('question-sign', icon_color) + t(:get_help), new_ticket_path, :class => 'btn') - %span.info= t(:help_info) diff --git a/core/config/initializers/backtrace_silencers.rb b/core/config/initializers/backtrace_silencers.rb deleted file mode 100644 index 59385cdf379bd06a8d2326dcd4de6d5cd5d3f5b0..0000000000000000000000000000000000000000 --- a/core/config/initializers/backtrace_silencers.rb +++ /dev/null @@ -1,7 +0,0 @@ -# Be sure to restart your server when you modify this file. - -# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. -# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } - -# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. -# Rails.backtrace_cleaner.remove_silencers! diff --git a/core/config/initializers/inflections.rb b/core/config/initializers/inflections.rb deleted file mode 100644 index 5d8d9be237b28d4ebdad9cec9510764ab88154e6..0000000000000000000000000000000000000000 --- a/core/config/initializers/inflections.rb +++ /dev/null @@ -1,15 +0,0 @@ -# Be sure to restart your server when you modify this file. - -# Add new inflection rules using the following format -# (all these examples are active by default): -# ActiveSupport::Inflector.inflections do |inflect| -# inflect.plural /^(ox)$/i, '\1en' -# inflect.singular /^(ox)en/i, '\1' -# inflect.irregular 'person', 'people' -# inflect.uncountable %w( fish sheep ) -# end -# -# These inflection rules are supported but not enabled by default: -# ActiveSupport::Inflector.inflections do |inflect| -# inflect.acronym 'RESTful' -# end diff --git a/core/config/initializers/mime_types.rb b/core/config/initializers/mime_types.rb deleted file mode 100644 index 72aca7e441e1855f8c7a7ac1f1cbe5d42cd1235b..0000000000000000000000000000000000000000 --- a/core/config/initializers/mime_types.rb +++ /dev/null @@ -1,5 +0,0 @@ -# Be sure to restart your server when you modify this file. - -# Add new mime types for use in respond_to blocks: -# Mime::Type.register "text/richtext", :rtf -# Mime::Type.register_alias "text/html", :iphone diff --git a/core/config/initializers/wrap_parameters.rb b/core/config/initializers/wrap_parameters.rb deleted file mode 100644 index 5fe232e2ad1dd3ff6afb34bdd2eaed119374c0d4..0000000000000000000000000000000000000000 --- a/core/config/initializers/wrap_parameters.rb +++ /dev/null @@ -1,10 +0,0 @@ -# Be sure to restart your server when you modify this file. -# -# This file contains settings for ActionController::ParamsWrapper which -# is enabled by default. - -# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. -ActiveSupport.on_load(:action_controller) do - wrap_parameters :format => [:json] -end - diff --git a/core/config/locales/en.yml b/core/config/locales/en.yml deleted file mode 100644 index bb510d4af7e4a1f2a46acdb5ca1c4def43ba7b41..0000000000000000000000000000000000000000 --- a/core/config/locales/en.yml +++ /dev/null @@ -1,41 +0,0 @@ -en: - no_such_thing: "No such %{thing}." - thing_was_successfully_created: "%{thing} was successfully created." - create_thing: "Create %{thing}" - - overview: "Overview" - user_control_panel: "user control panel" - - 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." - - download_client: "Download Bitmask" - client_info: "The Bitmask application allows you to use %{provider} services." - all_downloads_info: "It is available for %{clients}." - other_downloads_info: "Bitmask is also available for %{clients}." - login_info: "Log in to change your account settings, create support tickets, and manage payments." - signup_info: "Sign up for a new user account via this website (it is better if you use the Bitmask application to sign up, but this website works too)." - welcome: "Welcome to %{provider}." - get_help: "Get Help" - help_info: "Can't login? Create a new support ticket anonymously." - example_email: 'user@domain.org' - os: - linux32: "Linux (32 bit)" - linux64: "Linux (64 bit)" - linux: "GNU/Linux" - windows: "Windows" - android: "Android" - osx: "Mac OS" - other: "(not available for your OS)" - diff --git a/core/config/routes.rb b/core/config/routes.rb deleted file mode 100644 index 1daf9a4121a8bcf72094c3164d96a8deea47be66..0000000000000000000000000000000000000000 --- a/core/config/routes.rb +++ /dev/null @@ -1,2 +0,0 @@ -Rails.application.routes.draw do -end diff --git a/core/leap_web_core.gemspec b/core/leap_web_core.gemspec deleted file mode 100644 index 7ca4d90380aff79025d4f1e57dd87ace74ff627f..0000000000000000000000000000000000000000 --- a/core/leap_web_core.gemspec +++ /dev/null @@ -1,25 +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_core" - s.version = LeapWeb::VERSION - s.authors = ["Azul"] - s.email = ["azul@leap.se"] - s.homepage = "http://www.leap.se" - s.summary = "Web interface to the leap platform - core engine" - s.description = "This web interface provides various administrative tools for the leap platform through plugins. Currently it manages user accounts and certificates." - - s.files = Dir["{app,config,db,lib}/**/*"] + ["Rakefile", "Readme.md"] - s.test_files = Dir["test/**/*"] - - s.add_dependency "rails", "~> 3.2.11" - - s.add_dependency "couchrest", "~> 1.1.3" - s.add_dependency "couchrest_model", "~> 2.0.0" - s.add_dependency "couchrest_session_store", "~> 0.2.4" - - s.add_dependency "json" -end diff --git a/core/lib/extensions/testing.rb b/core/lib/extensions/testing.rb deleted file mode 100644 index aad7fc1dbfa5293c7298e7a719221612eb7ff218..0000000000000000000000000000000000000000 --- a/core/lib/extensions/testing.rb +++ /dev/null @@ -1,46 +0,0 @@ -module LeapWebCore - module AssertResponses - - # response that works with different TestCases: - # ActionController::TestCase has @response - # ActionDispatch::IntegrationTest has @response - # Rack::Test::Methods defines last_response - def get_response - @response || last_response - end - - def assert_attachement_filename(name) - assert_equal %Q(attachment; filename="#{name}"), - get_response.headers["Content-Disposition"] - end - - def json_response - response = JSON.parse(get_response.body) - response.respond_to?(:with_indifferent_access) ? - response.with_indifferent_access : - response - end - - def assert_json_response(object) - if object.is_a? Hash - object.stringify_keys! if object.respond_to? :stringify_keys! - assert_equal object, json_response - else - assert_equal object.to_json, get_response.body - end - end - - def assert_json_error(object) - object.stringify_keys! if object.respond_to? :stringify_keys! - assert_json_response :errors => object - end - end -end - -class ::ActionController::TestCase - include LeapWebCore::AssertResponses -end - -class ::ActionDispatch::IntegrationTest - include LeapWebCore::AssertResponses -end diff --git a/core/lib/leap_web_core.rb b/core/lib/leap_web_core.rb deleted file mode 100644 index a58d140d38fb9032f8f2f7a0f769c2f9d76c798b..0000000000000000000000000000000000000000 --- a/core/lib/leap_web_core.rb +++ /dev/null @@ -1,14 +0,0 @@ -require "rails" - -require "couchrest" -require "couchrest_model" -require "couchrest_session_store" - -require "json" - -require "extensions/testing" -require "extensions/couchrest" -require "leap_web_core/engine" - -module LeapWebCore -end diff --git a/core/lib/leap_web_core/dependencies.rb b/core/lib/leap_web_core/dependencies.rb deleted file mode 100644 index 877e3d1fe4d57021e7fe437f6e4f84dba31f42b5..0000000000000000000000000000000000000000 --- a/core/lib/leap_web_core/dependencies.rb +++ /dev/null @@ -1,40 +0,0 @@ -module LeapWebCore - class Dependencies - UI_DEV = { - "haml-rails" => "~> 0.3.4", - "sass-rails" => "~> 3.2.5", - "coffee-rails" => "~> 3.2.2", - "uglifier" => "~> 1.2.7" - } - - UI = { - "haml" => "~> 3.1.7", - "jquery-rails" => nil, - "simple_form" => nil, - "bootswatch-rails", "~> 0.5.0" - } - - def self.require_ui_gems - UI.keys.each {|dep| require dep} - if Rails.env == "development" - # This will be run in the app including plugins that run it. - # However not all development_dependencies might be present. - # So we better only require those that are. - available = Bundler.definition.specs.map(&:name) - gems_to_require = available & UI_DEV.keys - gems_to_require.each {|dep| require dep} - end - end - - def self.add_ui_gems_to_spec(spec) - UI.each do |dep, version| - spec.add_dependency dep, version - end - - UI_DEV.each do |dep, version| - spec.add_development_dependency dep, version - end - end - - end -end diff --git a/core/lib/leap_web_core/engine.rb b/core/lib/leap_web_core/engine.rb deleted file mode 100644 index 940b5e2f7e0e436c40f54a06c6ef8d404f70c375..0000000000000000000000000000000000000000 --- a/core/lib/leap_web_core/engine.rb +++ /dev/null @@ -1,9 +0,0 @@ -# thou shall require all your dependencies in an engine. -require "couchrest" -require "couchrest_model" - -module LeapWebCore - class Engine < ::Rails::Engine - - end -end diff --git a/core/lib/leap_web_core/ui_dependencies.rb b/core/lib/leap_web_core/ui_dependencies.rb deleted file mode 100644 index 2daee375cb749fae44721aafc5ea2ad0de62f35b..0000000000000000000000000000000000000000 --- a/core/lib/leap_web_core/ui_dependencies.rb +++ /dev/null @@ -1,11 +0,0 @@ -require "haml" -require "jquery-rails" -require "simple_form" -require "bootswatch-rails" - -if Rails.env == "development" - require "haml-rails" - require "sass-rails" - require "coffee-rails" - require "uglifier" -end diff --git a/core/script/rails b/core/script/rails deleted file mode 100755 index c2ad53860af7d4952cffd515d8cb60eac8ba4e9e..0000000000000000000000000000000000000000 --- a/core/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_core/engine', __FILE__) - -require 'rails/all' -require 'rails/engine/commands' diff --git a/billing/Gemfile b/engines/billing/Gemfile similarity index 100% rename from billing/Gemfile rename to engines/billing/Gemfile diff --git a/billing/README.md b/engines/billing/README.md similarity index 100% rename from billing/README.md rename to engines/billing/README.md diff --git a/billing/Rakefile b/engines/billing/Rakefile similarity index 100% rename from billing/Rakefile rename to engines/billing/Rakefile diff --git a/billing/app/controllers/billing_admin_controller.rb b/engines/billing/app/controllers/billing_admin_controller.rb similarity index 95% rename from billing/app/controllers/billing_admin_controller.rb rename to engines/billing/app/controllers/billing_admin_controller.rb index cd6149fdc8fda2feef6f3d2fe13a6e14a982c32b..e11d4eea984c69c284eb20a5b5943f899f74c4e2 100644 --- a/billing/app/controllers/billing_admin_controller.rb +++ b/engines/billing/app/controllers/billing_admin_controller.rb @@ -1,5 +1,5 @@ class BillingAdminController < BillingBaseController - before_filter :authorize_admin + before_filter :require_admin def show diff --git a/billing/app/controllers/billing_base_controller.rb b/engines/billing/app/controllers/billing_base_controller.rb similarity index 100% rename from billing/app/controllers/billing_base_controller.rb rename to engines/billing/app/controllers/billing_base_controller.rb diff --git a/billing/app/controllers/credit_card_info_controller.rb b/engines/billing/app/controllers/credit_card_info_controller.rb similarity index 95% rename from billing/app/controllers/credit_card_info_controller.rb rename to engines/billing/app/controllers/credit_card_info_controller.rb index 717fa1830f5381bf3cd8d762ee2976d791880bd4..fbaa6f12780e904f685646f7983f02c4a7b39d13 100644 --- a/billing/app/controllers/credit_card_info_controller.rb +++ b/engines/billing/app/controllers/credit_card_info_controller.rb @@ -1,5 +1,5 @@ class CreditCardInfoController < ApplicationController - before_filter :authorize, :set_user + before_filter :require_login, :set_user def edit @credit_card = Braintree::CreditCard.find(params[:id]) diff --git a/billing/app/controllers/customer_controller.rb b/engines/billing/app/controllers/customer_controller.rb similarity index 97% rename from billing/app/controllers/customer_controller.rb rename to engines/billing/app/controllers/customer_controller.rb index 901cb3442af1d8a290ea16d84f4a88819fe02cea..6cbcb448afcdce593f29f843f98e69c9d39efd1c 100644 --- a/billing/app/controllers/customer_controller.rb +++ b/engines/billing/app/controllers/customer_controller.rb @@ -1,5 +1,5 @@ class CustomerController < BillingBaseController - before_filter :authorize, :fetch_customer + before_filter :require_login, :fetch_customer def show if @customer diff --git a/billing/app/controllers/payments_controller.rb b/engines/billing/app/controllers/payments_controller.rb similarity index 94% rename from billing/app/controllers/payments_controller.rb rename to engines/billing/app/controllers/payments_controller.rb index 0b5abe7817dbb4e068388e56c2d5d766e3c17c08..fce65705c375c685b71ed1636816f3c3f12dbb4b 100644 --- a/billing/app/controllers/payments_controller.rb +++ b/engines/billing/app/controllers/payments_controller.rb @@ -1,5 +1,5 @@ class PaymentsController < BillingBaseController - before_filter :authorize, :only => [:index] + before_filter :require_login, :only => [:index] def new fetch_transparent_redirect diff --git a/billing/app/controllers/subscriptions_controller.rb b/engines/billing/app/controllers/subscriptions_controller.rb similarity index 98% rename from billing/app/controllers/subscriptions_controller.rb rename to engines/billing/app/controllers/subscriptions_controller.rb index 01aaab4a0ff1175fab5c1af9c8eb08a1a70d489f..f066b3c3cd48fa2f80fa2814e6c6c36f1c2fbd03 100644 --- a/billing/app/controllers/subscriptions_controller.rb +++ b/engines/billing/app/controllers/subscriptions_controller.rb @@ -1,5 +1,5 @@ class SubscriptionsController < BillingBaseController - before_filter :authorize + before_filter :require_login before_filter :fetch_subscription, :only => [:show, :destroy] before_filter :confirm_cancel_subscription, :only => [:destroy] before_filter :confirm_self_or_admin, :only => [:index] diff --git a/billing/app/helpers/billing_helper.rb b/engines/billing/app/helpers/billing_helper.rb similarity index 100% rename from billing/app/helpers/billing_helper.rb rename to engines/billing/app/helpers/billing_helper.rb diff --git a/billing/app/helpers/braintree_form_helper.rb b/engines/billing/app/helpers/braintree_form_helper.rb similarity index 100% rename from billing/app/helpers/braintree_form_helper.rb rename to engines/billing/app/helpers/braintree_form_helper.rb diff --git a/billing/app/helpers/braintree_helper.rb b/engines/billing/app/helpers/braintree_helper.rb similarity index 100% rename from billing/app/helpers/braintree_helper.rb rename to engines/billing/app/helpers/braintree_helper.rb diff --git a/billing/app/models/customer.rb b/engines/billing/app/models/customer.rb similarity index 100% rename from billing/app/models/customer.rb rename to engines/billing/app/models/customer.rb diff --git a/billing/app/views/billing_admin/show.html.haml b/engines/billing/app/views/billing_admin/show.html.haml similarity index 100% rename from billing/app/views/billing_admin/show.html.haml rename to engines/billing/app/views/billing_admin/show.html.haml diff --git a/billing/app/views/credit_card_info/confirm.html.haml b/engines/billing/app/views/credit_card_info/confirm.html.haml similarity index 100% rename from billing/app/views/credit_card_info/confirm.html.haml rename to engines/billing/app/views/credit_card_info/confirm.html.haml diff --git a/billing/app/views/credit_card_info/edit.html.haml b/engines/billing/app/views/credit_card_info/edit.html.haml similarity index 100% rename from billing/app/views/credit_card_info/edit.html.haml rename to engines/billing/app/views/credit_card_info/edit.html.haml diff --git a/billing/app/views/customer/_customer_data.html.haml b/engines/billing/app/views/customer/_customer_data.html.haml similarity index 100% rename from billing/app/views/customer/_customer_data.html.haml rename to engines/billing/app/views/customer/_customer_data.html.haml diff --git a/billing/app/views/customer/_transaction.html.haml b/engines/billing/app/views/customer/_transaction.html.haml similarity index 100% rename from billing/app/views/customer/_transaction.html.haml rename to engines/billing/app/views/customer/_transaction.html.haml diff --git a/billing/app/views/customer/confirm.html.haml b/engines/billing/app/views/customer/confirm.html.haml similarity index 100% rename from billing/app/views/customer/confirm.html.haml rename to engines/billing/app/views/customer/confirm.html.haml diff --git a/billing/app/views/customer/edit.html.haml b/engines/billing/app/views/customer/edit.html.haml similarity index 100% rename from billing/app/views/customer/edit.html.haml rename to engines/billing/app/views/customer/edit.html.haml diff --git a/billing/app/views/customer/new.html.haml b/engines/billing/app/views/customer/new.html.haml similarity index 100% rename from billing/app/views/customer/new.html.haml rename to engines/billing/app/views/customer/new.html.haml diff --git a/billing/app/views/customer/show.html.haml b/engines/billing/app/views/customer/show.html.haml similarity index 100% rename from billing/app/views/customer/show.html.haml rename to engines/billing/app/views/customer/show.html.haml diff --git a/billing/app/views/payments/_non_customer_fields.html.haml b/engines/billing/app/views/payments/_non_customer_fields.html.haml similarity index 100% rename from billing/app/views/payments/_non_customer_fields.html.haml rename to engines/billing/app/views/payments/_non_customer_fields.html.haml diff --git a/billing/app/views/payments/_transaction_details.html.haml b/engines/billing/app/views/payments/_transaction_details.html.haml similarity index 100% rename from billing/app/views/payments/_transaction_details.html.haml rename to engines/billing/app/views/payments/_transaction_details.html.haml diff --git a/billing/app/views/payments/confirm.html.haml b/engines/billing/app/views/payments/confirm.html.haml similarity index 100% rename from billing/app/views/payments/confirm.html.haml rename to engines/billing/app/views/payments/confirm.html.haml diff --git a/billing/app/views/payments/index.html.haml b/engines/billing/app/views/payments/index.html.haml similarity index 100% rename from billing/app/views/payments/index.html.haml rename to engines/billing/app/views/payments/index.html.haml diff --git a/billing/app/views/payments/new.html.haml b/engines/billing/app/views/payments/new.html.haml similarity index 100% rename from billing/app/views/payments/new.html.haml rename to engines/billing/app/views/payments/new.html.haml diff --git a/billing/app/views/subscriptions/_subscription_details.html.haml b/engines/billing/app/views/subscriptions/_subscription_details.html.haml similarity index 100% rename from billing/app/views/subscriptions/_subscription_details.html.haml rename to engines/billing/app/views/subscriptions/_subscription_details.html.haml diff --git a/billing/app/views/subscriptions/create.html.haml b/engines/billing/app/views/subscriptions/create.html.haml similarity index 100% rename from billing/app/views/subscriptions/create.html.haml rename to engines/billing/app/views/subscriptions/create.html.haml diff --git a/billing/app/views/subscriptions/destroy.html.haml b/engines/billing/app/views/subscriptions/destroy.html.haml similarity index 100% rename from billing/app/views/subscriptions/destroy.html.haml rename to engines/billing/app/views/subscriptions/destroy.html.haml diff --git a/billing/app/views/subscriptions/index.html.haml b/engines/billing/app/views/subscriptions/index.html.haml similarity index 100% rename from billing/app/views/subscriptions/index.html.haml rename to engines/billing/app/views/subscriptions/index.html.haml diff --git a/billing/app/views/subscriptions/new.html.haml b/engines/billing/app/views/subscriptions/new.html.haml similarity index 100% rename from billing/app/views/subscriptions/new.html.haml rename to engines/billing/app/views/subscriptions/new.html.haml diff --git a/billing/app/views/subscriptions/show.html.haml b/engines/billing/app/views/subscriptions/show.html.haml similarity index 100% rename from billing/app/views/subscriptions/show.html.haml rename to engines/billing/app/views/subscriptions/show.html.haml diff --git a/billing/config/initializers/braintree.rb b/engines/billing/config/initializers/braintree.rb similarity index 83% rename from billing/config/initializers/braintree.rb rename to engines/billing/config/initializers/braintree.rb index c0c89e29418659dc0b6983aaaaf9f104b756ff6f..3d87f4c55f8b2d9fbb76321e646f73fbbaae643e 100644 --- a/billing/config/initializers/braintree.rb +++ b/engines/billing/config/initializers/braintree.rb @@ -8,14 +8,6 @@ else Braintree::Configuration.logger = Logger.new('log/braintree.log') end -# -# we use fake braintree in tests -# -if Rails.env.test? - require 'braintree_test_app' - Rails.application.config.middleware.use BraintreeTestApp -end - # # You can set these per environment in config/config.yml: # diff --git a/billing/config/locales/en.yml b/engines/billing/config/locales/en.yml similarity index 100% rename from billing/config/locales/en.yml rename to engines/billing/config/locales/en.yml diff --git a/billing/config/routes.rb b/engines/billing/config/routes.rb similarity index 100% rename from billing/config/routes.rb rename to engines/billing/config/routes.rb diff --git a/billing/leap_web_billing.gemspec b/engines/billing/leap_web_billing.gemspec similarity index 74% rename from billing/leap_web_billing.gemspec rename to engines/billing/leap_web_billing.gemspec index 94d92e0a87c587116bbd530a038f004c18a2f9c1..ff11c98409232532267205aa5979cc944b265ce6 100644 --- a/billing/leap_web_billing.gemspec +++ b/engines/billing/leap_web_billing.gemspec @@ -1,6 +1,6 @@ $:.push File.expand_path("../lib", __FILE__) -require File.expand_path('../../lib/leap_web/version.rb', __FILE__) +require File.expand_path('../../../lib/leap_web/version.rb', __FILE__) # Describe your gem and declare its dependencies: Gem::Specification.new do |s| @@ -12,10 +12,9 @@ Gem::Specification.new do |s| s.summary = "Billing for LeapWeb" s.description = "Billing System for a Leap provider" - s.files = Dir["{app,config,db,lib}/**/*"] + ["Rakefile", "README.md"] + s.files = Dir["{app,config,lib}/**/*"] + ["Rakefile", "README.md"] s.test_files = Dir["test/**/*"] - s.add_dependency "leap_web_core", LeapWeb::VERSION # s.add_dependency "braintree-rails", "~> 0.4.5" s.add_dependency "braintree" #s.add_dependency "carmen-rails" diff --git a/billing/lib/braintree_test_app.rb b/engines/billing/lib/braintree_test_app.rb similarity index 100% rename from billing/lib/braintree_test_app.rb rename to engines/billing/lib/braintree_test_app.rb diff --git a/billing/lib/leap_web_billing.rb b/engines/billing/lib/leap_web_billing.rb similarity index 100% rename from billing/lib/leap_web_billing.rb rename to engines/billing/lib/leap_web_billing.rb diff --git a/billing/lib/leap_web_billing/engine.rb b/engines/billing/lib/leap_web_billing/engine.rb similarity index 75% rename from billing/lib/leap_web_billing/engine.rb rename to engines/billing/lib/leap_web_billing/engine.rb index 6d76addc1dddd56325ca9dc42f80179a732f9f22..ab574f2c18e29306b42b16d6b7507d101f092e87 100644 --- a/billing/lib/leap_web_billing/engine.rb +++ b/engines/billing/lib/leap_web_billing/engine.rb @@ -1,7 +1,4 @@ # thou shall require all your dependencies in an engine. -require "leap_web_core" -require "leap_web_core/ui_dependencies" - #require "braintree-rails" require "braintree" #require "carmen-rails" diff --git a/billing/script/rails b/engines/billing/script/rails similarity index 100% rename from billing/script/rails rename to engines/billing/script/rails diff --git a/billing/test/integration/admin_customer_test.rb b/engines/billing/test/broken/admin_customer_test.rb similarity index 77% rename from billing/test/integration/admin_customer_test.rb rename to engines/billing/test/broken/admin_customer_test.rb index 58a75573ae4fb1f010eb6a5772f199786f28fb5a..df92a0d708739e3b4488f7cfd7338c315e87ab9d 100644 --- a/billing/test/integration/admin_customer_test.rb +++ b/engines/billing/test/broken/admin_customer_test.rb @@ -1,21 +1,16 @@ require 'test_helper' require 'fake_braintree' -require 'capybara/rails' -class AdminCustomerTest < ActionDispatch::IntegrationTest - include Warden::Test::Helpers - include Capybara::DSL +class AdminCustomerTest < BraintreeIntegrationTest setup do - Warden.test_mode! @admin = User.find_by_login('admin') || FactoryGirl.create(:user, login: 'admin') @user = FactoryGirl.create(:user) end teardown do - Warden.test_reset! - @user.destroy - @admin.destroy + @user.destroy if @user + @admin.destroy if @admin end test "check non customer as admin" do diff --git a/billing/test/integration/customer_creation_test.rb b/engines/billing/test/broken/customer_creation_test.rb similarity index 93% rename from billing/test/integration/customer_creation_test.rb rename to engines/billing/test/broken/customer_creation_test.rb index aabd9b6c1b4ce729d340e317035f62c6947cd02f..90319a9689bb07d6a43343bea769e4087a633b1b 100644 --- a/billing/test/integration/customer_creation_test.rb +++ b/engines/billing/test/broken/customer_creation_test.rb @@ -1,20 +1,15 @@ require 'test_helper' require 'fake_braintree' -require 'capybara/rails' -class CustomerCreationTest < ActionDispatch::IntegrationTest - include Warden::Test::Helpers - include Capybara::DSL +class CustomerCreationTest < BraintreeIntegrationTest setup do - Warden.test_mode! @user = FactoryGirl.create(:user) login_as @user end teardown do @user.destroy - Warden.test_reset! end # Let's test both steps together with capybara diff --git a/billing/test/integration/subscription_test.rb b/engines/billing/test/broken/subscription_test.rb similarity index 89% rename from billing/test/integration/subscription_test.rb rename to engines/billing/test/broken/subscription_test.rb index 1473eb00af5754e9576cca986aa6340d85d405a7..cd010bde849ebf9dc95722627dec6de5bc91acb8 100644 --- a/billing/test/integration/subscription_test.rb +++ b/engines/billing/test/broken/subscription_test.rb @@ -1,14 +1,11 @@ require 'test_helper' require 'fake_braintree' -require 'capybara/rails' -class SubscriptionTest < BrowserIntegrationTest - include Warden::Test::Helpers +class SubscriptionTest < BraintreeIntegrationTest include CustomerTestHelper include StubRecordHelper setup do - Warden.test_mode! @admin = User.find_by_login('admin') || FactoryGirl.create(:user, login: 'admin') @customer = stub_customer @braintree_customer = @customer.braintree_customer @@ -19,7 +16,6 @@ class SubscriptionTest < BrowserIntegrationTest end teardown do - Warden.test_reset! @admin.destroy end diff --git a/billing/test/factories.rb b/engines/billing/test/factories.rb similarity index 100% rename from billing/test/factories.rb rename to engines/billing/test/factories.rb diff --git a/billing/test/functional/customer_controller_test.rb b/engines/billing/test/functional/customer_controller_test.rb similarity index 100% rename from billing/test/functional/customer_controller_test.rb rename to engines/billing/test/functional/customer_controller_test.rb diff --git a/billing/test/functional/customers_controller_test.rb b/engines/billing/test/functional/customers_controller_test.rb similarity index 100% rename from billing/test/functional/customers_controller_test.rb rename to engines/billing/test/functional/customers_controller_test.rb diff --git a/billing/test/functional/payments_controller_test.rb b/engines/billing/test/functional/payments_controller_test.rb similarity index 100% rename from billing/test/functional/payments_controller_test.rb rename to engines/billing/test/functional/payments_controller_test.rb diff --git a/billing/test/functional/subscriptions_controller_test.rb b/engines/billing/test/functional/subscriptions_controller_test.rb similarity index 100% rename from billing/test/functional/subscriptions_controller_test.rb rename to engines/billing/test/functional/subscriptions_controller_test.rb diff --git a/engines/billing/test/support/braintree_integration_test.rb b/engines/billing/test/support/braintree_integration_test.rb new file mode 100644 index 0000000000000000000000000000000000000000..976c5a2e87ee1011923586586f1ee2d2807b97bd --- /dev/null +++ b/engines/billing/test/support/braintree_integration_test.rb @@ -0,0 +1,18 @@ +require 'capybara/rails' +# require 'fake_braintree' - messes up other integration tests +require 'braintree_test_app' + +class BraintreeIntegrationTest < BrowserIntegrationTest + include Warden::Test::Helpers + + setup do + Warden.test_mode! + Rails.application.config.middleware.use BraintreeTestApp + end + + teardown do + Warden.test_reset! + Rails.application.config.middleware.delete "BraintreeTestApp" + end + +end diff --git a/billing/test/support/customer_test_helper.rb b/engines/billing/test/support/customer_test_helper.rb similarity index 100% rename from billing/test/support/customer_test_helper.rb rename to engines/billing/test/support/customer_test_helper.rb diff --git a/help/test/test_helper.rb b/engines/billing/test/test_helper.rb similarity index 83% rename from help/test/test_helper.rb rename to engines/billing/test/test_helper.rb index 3381f44411e8a3eeb3d5faade6521727df00af7c..7ad3869a8a2817481069c25d46e5f20595ba035e 100644 --- a/help/test/test_helper.rb +++ b/engines/billing/test/test_helper.rb @@ -1,7 +1,7 @@ # Configure Rails Environment ENV["RAILS_ENV"] = "test" -require File.expand_path('../../../test/dummy/config/environment', __FILE__) +require File.expand_path("../../../../dummy/config/environment.rb", __FILE__) require "rails/test_help" Rails.backtrace_cleaner.remove_silencers! diff --git a/billing/test/unit/customer_test.rb b/engines/billing/test/unit/customer_test.rb similarity index 100% rename from billing/test/unit/customer_test.rb rename to engines/billing/test/unit/customer_test.rb diff --git a/billing/test/unit/customer_with_payment_info_test.rb b/engines/billing/test/unit/customer_with_payment_info_test.rb similarity index 100% rename from billing/test/unit/customer_with_payment_info_test.rb rename to engines/billing/test/unit/customer_with_payment_info_test.rb diff --git a/help/Gemfile b/engines/support/Gemfile similarity index 100% rename from help/Gemfile rename to engines/support/Gemfile diff --git a/help/README.md b/engines/support/README.md similarity index 100% rename from help/README.md rename to engines/support/README.md diff --git a/help/Rakefile b/engines/support/Rakefile similarity index 100% rename from help/Rakefile rename to engines/support/Rakefile diff --git a/help/app/assets/javascripts/tickets.js b/engines/support/app/assets/javascripts/tickets.js similarity index 100% rename from help/app/assets/javascripts/tickets.js rename to engines/support/app/assets/javascripts/tickets.js diff --git a/help/app/controllers/tickets_controller.rb b/engines/support/app/controllers/tickets_controller.rb similarity index 74% rename from help/app/controllers/tickets_controller.rb rename to engines/support/app/controllers/tickets_controller.rb index c193ff49238ff540aa83e9b7ef9c991873a48053..99357ab8f93a5371395c21b86ea0cf12637a0712 100644 --- a/help/app/controllers/tickets_controller.rb +++ b/engines/support/app/controllers/tickets_controller.rb @@ -4,31 +4,30 @@ class TicketsController < ApplicationController respond_to :html, :json #has_scope :open, :type => boolean - before_filter :authorize, :only => [:index] - before_filter :fetch_ticket, :only => [:show, :update, :destroy] # don't now have an edit method + before_filter :require_login, :only => [:index] + before_filter :fetch_ticket, :only => [:show, :update, :destroy] + before_filter :require_ticket_access, :only => [:show, :update, :destroy] before_filter :fetch_user before_filter :set_title def new @ticket = Ticket.new + @ticket.created_by = current_user.id @ticket.comments.build end def create @ticket = Ticket.new(params[:ticket]) - @ticket.comments.last.posted_by = (logged_in? ? current_user.id : nil) #protecting posted_by isn't working, so this should protect it. + #protecting posted_by isn't working, so this should protect it: + @ticket.comments.last.posted_by = current_user.id @ticket.comments.last.private = false unless admin? - @ticket.created_by = current_user.id if logged_in? - @ticket.email = current_user.email_address if logged_in? and current_user.email_address - + @ticket.created_by = current_user.id if @ticket.save flash[:notice] = t(:thing_was_successfully_created, :thing => t(:ticket)) - end - - # cannot set this until ticket has been saved, as @ticket.id will not be set - if !logged_in? and flash[:notice] - flash[:notice] += " " + t(:access_ticket_text, :full_url => ticket_url(@ticket.id)) + if !logged_in? + flash[:notice] += " " + t(:access_ticket_text, :full_url => ticket_url(@ticket.id)) + end end respond_with(@ticket, :location => auto_ticket_path(@ticket)) end @@ -42,23 +41,23 @@ class TicketsController < ApplicationController end def update - if params[:commit] == 'close' + if params[:button] == 'close' @ticket.is_open = false @ticket.save redirect_to_tickets - elsif params[:commit] == 'open' + elsif params[:button] == 'open' @ticket.is_open = true @ticket.save redirect_to auto_ticket_path(@ticket) else @ticket.attributes = cleanup_ticket_params(params[:ticket]) - if params[:commit] == 'reply_and_close' + if params[:button] == 'reply_and_close' @ticket.close end if @ticket.comments_changed? - @ticket.comments.last.posted_by = (current_user ? current_user.id : nil) + @ticket.comments.last.posted_by = current_user.id @ticket.comments.last.private = false unless admin? end @@ -97,7 +96,7 @@ class TicketsController < ApplicationController # def redirect_to_tickets if logged_in? - if params[:commit] == t(:reply_and_close) + if params[:button] == t(:reply_and_close) redirect_to auto_tickets_path else redirect_to auto_ticket_path(@ticket) @@ -120,19 +119,28 @@ class TicketsController < ApplicationController return ticket end - def ticket_access? - @ticket and (admin? or !@ticket.created_by or (current_user and current_user.id == @ticket.created_by)) - end - def fetch_ticket @ticket = Ticket.find(params[:id]) - if !@ticket and admin? - redirect_to auto_tickets_path, :alert => t(:no_such_thing, :thing => 'ticket') - return + if !@ticket + if admin? + redirect_to auto_tickets_path, + alert: t(:no_such_thing, thing: 'ticket') + else + access_denied + end end + end + + def require_ticket_access access_denied unless ticket_access? end + def ticket_access? + admin? or + @ticket.created_by.blank? or + current_user.id == @ticket.created_by + end + def fetch_user if params[:user_id] @user = User.find(params[:user_id]) diff --git a/help/app/designs/ticket/by_includes_post_by.js b/engines/support/app/designs/ticket/by_includes_post_by.js similarity index 100% rename from help/app/designs/ticket/by_includes_post_by.js rename to engines/support/app/designs/ticket/by_includes_post_by.js diff --git a/help/app/designs/ticket/by_includes_post_by_and_created_at.js b/engines/support/app/designs/ticket/by_includes_post_by_and_created_at.js similarity index 100% rename from help/app/designs/ticket/by_includes_post_by_and_created_at.js rename to engines/support/app/designs/ticket/by_includes_post_by_and_created_at.js diff --git a/help/app/designs/ticket/by_includes_post_by_and_is_open_and_created_at.js b/engines/support/app/designs/ticket/by_includes_post_by_and_is_open_and_created_at.js similarity index 100% rename from help/app/designs/ticket/by_includes_post_by_and_is_open_and_created_at.js rename to engines/support/app/designs/ticket/by_includes_post_by_and_is_open_and_created_at.js diff --git a/help/app/designs/ticket/by_includes_post_by_and_is_open_and_updated_at.js b/engines/support/app/designs/ticket/by_includes_post_by_and_is_open_and_updated_at.js similarity index 100% rename from help/app/designs/ticket/by_includes_post_by_and_is_open_and_updated_at.js rename to engines/support/app/designs/ticket/by_includes_post_by_and_is_open_and_updated_at.js diff --git a/help/app/designs/ticket/by_includes_post_by_and_updated_at.js b/engines/support/app/designs/ticket/by_includes_post_by_and_updated_at.js similarity index 100% rename from help/app/designs/ticket/by_includes_post_by_and_updated_at.js rename to engines/support/app/designs/ticket/by_includes_post_by_and_updated_at.js diff --git a/help/app/helpers/auto_tickets_path_helper.rb b/engines/support/app/helpers/auto_tickets_path_helper.rb similarity index 97% rename from help/app/helpers/auto_tickets_path_helper.rb rename to engines/support/app/helpers/auto_tickets_path_helper.rb index 93f3cb954d59a1ebe3f2d63bbcbc9ebbf3a92b6c..5638222573aba261a4c8e7c8a93be33a70d5931b 100644 --- a/help/app/helpers/auto_tickets_path_helper.rb +++ b/engines/support/app/helpers/auto_tickets_path_helper.rb @@ -23,6 +23,7 @@ module AutoTicketsPathHelper end def auto_ticket_path(ticket, options={}) + return unless ticket.persisted? options = ticket_view_options.merge options if @user user_ticket_path(@user, ticket, options) @@ -50,4 +51,4 @@ module AutoTicketsPathHelper hsh end -end \ No newline at end of file +end diff --git a/help/app/helpers/tickets_helper.rb b/engines/support/app/helpers/tickets_helper.rb similarity index 100% rename from help/app/helpers/tickets_helper.rb rename to engines/support/app/helpers/tickets_helper.rb diff --git a/help/app/models/account_extension/tickets.rb b/engines/support/app/models/account_extension/tickets.rb similarity index 100% rename from help/app/models/account_extension/tickets.rb rename to engines/support/app/models/account_extension/tickets.rb diff --git a/help/app/models/ticket.rb b/engines/support/app/models/ticket.rb similarity index 81% rename from help/app/models/ticket.rb rename to engines/support/app/models/ticket.rb index cd2275821115808ac3f7e275e76f717ed50e3815..bf5df530286d79431bbf98838a63a4e0701a8783 100644 --- a/help/app/models/ticket.rb +++ b/engines/support/app/models/ticket.rb @@ -19,8 +19,6 @@ class Ticket < CouchRest::Model::Base timestamps! - before_validation :set_email, :set_regarding_user, :on => :create - design do view :by_updated_at view :by_created_at @@ -34,7 +32,12 @@ class Ticket < CouchRest::Model::Base end validates :subject, :presence => true - validates :email, :allow_blank => true, :format => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/ + + # email can have three states: + # * nil - prefilled with created_by's email + # * "" - cleared + # * valid email address + validates :email, :allow_blank => true, :format => /\A(([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,}))?\Z/ def self.search(options = {}) @selection = TicketSelection.new(options) @@ -48,15 +51,15 @@ class Ticket < CouchRest::Model::Base end def is_creator_validated? - !!created_by + created_by_user.is_a? User end - def set_email - self.email = nil if self.email == "" + def email + read_attribute(:email) || created_by_user.email end - def set_regarding_user - self.regarding_user = nil if self.regarding_user == "" + def regarding_user + read_attribute(:regarding_user) || created_by_user.login end def close @@ -95,7 +98,11 @@ class Ticket < CouchRest::Model::Base end def created_by_user - User.find(self.created_by) + if self.created_by + User.find(self.created_by) || AnonymousUser.new + else + AnonymousUser.new + end end def regarding_user_actual_user diff --git a/help/app/models/ticket_comment.rb b/engines/support/app/models/ticket_comment.rb similarity index 100% rename from help/app/models/ticket_comment.rb rename to engines/support/app/models/ticket_comment.rb diff --git a/help/app/models/ticket_selection.rb b/engines/support/app/models/ticket_selection.rb similarity index 100% rename from help/app/models/ticket_selection.rb rename to engines/support/app/models/ticket_selection.rb diff --git a/help/app/views/tickets/_comment.html.haml b/engines/support/app/views/tickets/_comment.html.haml similarity index 100% rename from help/app/views/tickets/_comment.html.haml rename to engines/support/app/views/tickets/_comment.html.haml diff --git a/help/app/views/tickets/_edit_form.html.haml b/engines/support/app/views/tickets/_edit_form.html.haml similarity index 71% rename from help/app/views/tickets/_edit_form.html.haml rename to engines/support/app/views/tickets/_edit_form.html.haml index 714f8ff3a5d9bc823dad64f84e612094fd7896fa..b8da77964472aa7796ee2a2c053b6af597d70a10 100644 --- a/help/app/views/tickets/_edit_form.html.haml +++ b/engines/support/app/views/tickets/_edit_form.html.haml @@ -1,6 +1,6 @@ :ruby # created by user link - if @ticket.created_by_user + if @ticket.is_creator_validated? created_by = link_to @ticket.created_by_user.login, @ticket.created_by_user else created_by = t(:anonymous) @@ -17,14 +17,20 @@ regarding_user_link = '' end -= form_for @ticket do |f| += simple_form_for @ticket do |f| = hidden_ticket_fields %p.first - if @ticket.is_open? - %span.label.label-info= t(:open) + %span.label.label-info + %b{style: 'padding:10px'}= t(:open) + = f.button :loading, t(:close), value: 'close', class: 'btn-mini' - else - %span.label.label-success= t(:closed) + %span.label.label-success + %b{style: 'padding:10px'}= t(:closed) + = f.button :loading, t(:open), value: 'open', class: 'btn-mini' %span.label.label-clear= t(:created_by_on, :user => created_by, :time => @ticket.created_at.to_s(:short)).html_safe += simple_form_for @ticket do |f| + = hidden_ticket_fields %div= t(:subject) = f.text_field :subject, :class => 'large full-width' .row-fluid @@ -39,10 +45,6 @@ = t(:regarding_account) = regarding_user_link = f.text_field :regarding_user - = f.button t(:save), :name => 'commit', :class => 'btn', :type => 'submit', :value => 'save' - - if @ticket.is_open? - = f.button t(:close), :name => 'commit', :class => 'btn', :type => 'submit', :value => 'close' - - else - = f.button t(:open), :name => 'commit', :class => 'btn', :type => 'submit', :value => 'open' + = f.button :loading, t(:save), :value => 'save' - if admin? = link_to t(:destroy), auto_ticket_path(@ticket), :confirm => t(:are_you_sure), :method => :delete, :class => 'btn' diff --git a/help/app/views/tickets/_new_comment_form.html.haml b/engines/support/app/views/tickets/_new_comment_form.html.haml similarity index 68% rename from help/app/views/tickets/_new_comment_form.html.haml rename to engines/support/app/views/tickets/_new_comment_form.html.haml index 8418e01e937bea81deb1e4fc02cb562d39d58921..40c737fdf62eeee25dd51d72e8cb5c79c604ff88 100644 --- a/help/app/views/tickets/_new_comment_form.html.haml +++ b/engines/support/app/views/tickets/_new_comment_form.html.haml @@ -7,7 +7,7 @@ = c.input :body, :label => false, :as => :text, :input_html => {:class => "full-width", :rows=> 5} - if admin? = c.input :private, :as => :boolean, :label => false, :inline_label => true - = f.button :button, t(:post_reply), :name => 'commit', :class => 'btn-primary', :type => 'submit', :value => 'post_reply' + = f.button :loading, t(:post_reply), class: 'btn-primary', value: 'post_reply' - if logged_in? && @ticket.is_open - = f.button :button, t(:reply_and_close), :name => 'commit', :class => 'btn', :type => 'submit', :value => 'reply_and_close' + = f.button :loading, t(:reply_and_close), value: 'reply_and_close' = link_to t(:cancel), auto_tickets_path, :class => :btn diff --git a/help/app/views/tickets/_tabs.html.haml b/engines/support/app/views/tickets/_tabs.html.haml similarity index 86% rename from help/app/views/tickets/_tabs.html.haml rename to engines/support/app/views/tickets/_tabs.html.haml index b7b5d3a789c100858f9321cbe6655e55f606071b..445a9093896e02a609c2ea08061442b351689329 100644 --- a/help/app/views/tickets/_tabs.html.haml +++ b/engines/support/app/views/tickets/_tabs.html.haml @@ -1,7 +1,7 @@ -# -# SORT ORDER TABS -# -- unless action?(:new) +- unless action?(:new) or action?(:create) %ul.nav.nav-pills.pull-right.slim %li{:class=> ("active" if search_order.start_with? 'created_at')} = link_to_order('created') @@ -19,5 +19,5 @@ = link_to_status 'closed' %li{:class => ("active" if search_status == 'all')} = link_to_status 'all' - %li{:class => ("active" if action?(:new))} + %li{:class => ("active" if action?(:new) || action?(:create))} = link_to icon(:plus, :black) + t(:new_ticket), auto_new_ticket_path diff --git a/help/app/views/tickets/_ticket.html.haml b/engines/support/app/views/tickets/_ticket.html.haml similarity index 100% rename from help/app/views/tickets/_ticket.html.haml rename to engines/support/app/views/tickets/_ticket.html.haml diff --git a/help/app/views/tickets/index.html.haml b/engines/support/app/views/tickets/index.html.haml similarity index 86% rename from help/app/views/tickets/index.html.haml rename to engines/support/app/views/tickets/index.html.haml index c02a32654e1ba9c126a75ca4208c51bd1470a05d..a4df6e37b14f637155f67e8c553464357f094f99 100644 --- a/help/app/views/tickets/index.html.haml +++ b/engines/support/app/views/tickets/index.html.haml @@ -1,4 +1,4 @@ -- @show_navigation = !params[:user_id].nil? +- @show_navigation = params[:user_id].present? = render 'tickets/tabs' diff --git a/engines/support/app/views/tickets/new.html.haml b/engines/support/app/views/tickets/new.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..3de5fe90531fd24c387bd08fdaf445e3beb8d3aa --- /dev/null +++ b/engines/support/app/views/tickets/new.html.haml @@ -0,0 +1,17 @@ +- @show_navigation = params[:user_id].present? + += render 'tickets/tabs' + +- user = @user if admin? +- user ||= current_user + += simple_form_for @ticket, :validate => true, :html => {:class => 'form-horizontal'} do |f| + = hidden_ticket_fields + = f.input :subject + = f.input :email + = f.input :regarding_user + = f.simple_fields_for :comments, @comment do |c| + = c.input :body, :label => t(:description), :as => :text, :input_html => {:class => "full-width", :rows=> 5} + - if admin? + = c.input :private, :as => :boolean, :label => false, :inline_label => true + = f.button :wrapped, cancel: (logged_in? ? auto_tickets_path : home_path) diff --git a/help/app/views/tickets/show.html.haml b/engines/support/app/views/tickets/show.html.haml similarity index 59% rename from help/app/views/tickets/show.html.haml rename to engines/support/app/views/tickets/show.html.haml index bfdb7731643361008575b25856364ac7a825cb72..4f3c127da6c0d939a516fc8ef2e79164260a161c 100644 --- a/help/app/views/tickets/show.html.haml +++ b/engines/support/app/views/tickets/show.html.haml @@ -1,4 +1,4 @@ -- @show_navigation = !params[:user_id].nil? +- @show_navigation = params[:user_id].present? .ticket = render 'tickets/edit_form' @@ -7,6 +7,6 @@ = render :partial => 'tickets/comment', :collection => @ticket.comments %tr %td.user - = logged_in? ? current_user.login : t(:anonymous) + = current_user.login || t(:anonymous) %td.comment - = render 'tickets/new_comment_form' \ No newline at end of file + = render 'tickets/new_comment_form' diff --git a/help/config/initializers/account_lifecycle.rb b/engines/support/config/initializers/account_lifecycle.rb similarity index 100% rename from help/config/initializers/account_lifecycle.rb rename to engines/support/config/initializers/account_lifecycle.rb diff --git a/help/config/locales/en.yml b/engines/support/config/locales/en.yml similarity index 100% rename from help/config/locales/en.yml rename to engines/support/config/locales/en.yml diff --git a/help/config/routes.rb b/engines/support/config/routes.rb similarity index 100% rename from help/config/routes.rb rename to engines/support/config/routes.rb diff --git a/help/leap_web_help.gemspec b/engines/support/leap_web_help.gemspec similarity index 62% rename from help/leap_web_help.gemspec rename to engines/support/leap_web_help.gemspec index 49146945ab95d3026914ee6789d0d7157ad20f88..7b668d539cb3d1f545c327fed879444cebfc1c2f 100644 --- a/help/leap_web_help.gemspec +++ b/engines/support/leap_web_help.gemspec @@ -1,6 +1,6 @@ -$:.push File.expand_path("../lib", __FILE__) +$:.push File.expand_path("../../lib", __FILE__) -require File.expand_path('../../lib/leap_web/version.rb', __FILE__) +require File.expand_path('../../../lib/leap_web/version.rb', __FILE__) # Describe your gem and declare its dependencies: Gem::Specification.new do |s| @@ -12,8 +12,7 @@ Gem::Specification.new do |s| s.summary = "Help Desk for LeapWeb" s.description = "Managing Tickets for a Leap provider" - s.files = Dir["{app,config,db,lib}/**/*"] + ["Rakefile", "README.md"] + s.files = Dir["{app,config,lib}/**/*"] + ["Rakefile", "README.md"] s.test_files = Dir["test/**/*"] - s.add_dependency "leap_web_core", LeapWeb::VERSION end diff --git a/help/lib/leap_web_help.rb b/engines/support/lib/leap_web_help.rb similarity index 100% rename from help/lib/leap_web_help.rb rename to engines/support/lib/leap_web_help.rb diff --git a/engines/support/lib/leap_web_help/engine.rb b/engines/support/lib/leap_web_help/engine.rb new file mode 100644 index 0000000000000000000000000000000000000000..dfa763fd9e81ae175d33bdcff0718f35d1b7f8ce --- /dev/null +++ b/engines/support/lib/leap_web_help/engine.rb @@ -0,0 +1,4 @@ +module LeapWebHelp + class Engine < ::Rails::Engine + end +end diff --git a/help/lib/tasks/leap_web_help_tasks.rake b/engines/support/lib/tasks/leap_web_help_tasks.rake similarity index 100% rename from help/lib/tasks/leap_web_help_tasks.rake rename to engines/support/lib/tasks/leap_web_help_tasks.rake diff --git a/help/script/rails b/engines/support/script/rails similarity index 100% rename from help/script/rails rename to engines/support/script/rails diff --git a/help/test/factories.rb b/engines/support/test/factories.rb similarity index 100% rename from help/test/factories.rb rename to engines/support/test/factories.rb diff --git a/help/test/functional/tickets_controller_test.rb b/engines/support/test/functional/tickets_controller_test.rb similarity index 93% rename from help/test/functional/tickets_controller_test.rb rename to engines/support/test/functional/tickets_controller_test.rb index 2530ba112a8bb981fbb3fd29e39844a6cf0f52b9..fc4a6f86f3ddd141177405ae8e92784823bc126d 100644 --- a/help/test/functional/tickets_controller_test.rb +++ b/engines/support/test/functional/tickets_controller_test.rb @@ -2,6 +2,11 @@ require 'test_helper' class TicketsControllerTest < ActionController::TestCase + teardown do + # destroy all tickets that were created during the test + Ticket.all.each{|t| t.destroy} + end + test "should get index if logged in" do login get :index @@ -64,13 +69,23 @@ class TicketsControllerTest < ActionController::TestCase assert_equal 1, assigns(:ticket).comments.count assert_nil assigns(:ticket).comments.first.posted_by - assigns(:ticket).destroy # destroys without checking permission. is that okay? end + test "handle invalid ticket" do + params = {:subject => "unauth ticket test subject", :comments_attributes => {"0" => {"body" =>"body of test ticket"}}, :email => 'a'} + + assert_no_difference('Ticket.count') do + post :create, :ticket => params + end + + assert_template :new + assert_equal params[:subject], assigns(:ticket).subject + end + test "should create authenticated ticket" do - params = {:subject => "auth ticket test subject", :comments_attributes => {"0" => {"body" =>"body of test ticket"}}} + params = {:subject => "auth ticket test subject",:email => "", :comments_attributes => {"0" => {"body" =>"body of test ticket"}}} login @@ -82,12 +97,11 @@ class TicketsControllerTest < ActionController::TestCase assert_not_nil assigns(:ticket).created_by assert_equal assigns(:ticket).created_by, @current_user.id - assert_equal assigns(:ticket).email, @current_user.email_address + assert_equal "", assigns(:ticket).email assert_equal 1, assigns(:ticket).comments.count assert_not_nil assigns(:ticket).comments.first.posted_by assert_equal assigns(:ticket).comments.first.posted_by, @current_user.id - assigns(:ticket).destroy end test "add comment to unauthenticated ticket" do @@ -101,7 +115,6 @@ class TicketsControllerTest < ActionController::TestCase assert_equal ticket, assigns(:ticket) # still same ticket, with different comments assert_not_equal ticket.comments, assigns(:ticket).comments # ticket == assigns(:ticket), but they have different comments (which we want) - assigns(:ticket).destroy end @@ -118,7 +131,6 @@ class TicketsControllerTest < ActionController::TestCase assert_not_equal ticket.comments, assigns(:ticket).comments assert_not_nil assigns(:ticket).comments.last.posted_by assert_equal assigns(:ticket).comments.last.posted_by, @current_user.id - assigns(:ticket).destroy end @@ -153,12 +165,9 @@ class TicketsControllerTest < ActionController::TestCase assert_not_equal ticket.comments, assigns(:ticket).comments assert_not_nil assigns(:ticket).comments.last.posted_by assert_equal assigns(:ticket).comments.last.posted_by, @current_user.id - - assigns(:ticket).destroy end test "tickets by admin" do - begin other_user = find_record :user ticket = FactoryGirl.create :ticket, :created_by => other_user.id @@ -173,9 +182,6 @@ class TicketsControllerTest < ActionController::TestCase assigns(:tickets).first.save get :index, {:admin_status => "all", :open_status => "open"} end - ensure - ticket.reload.destroy if ticket - end end @@ -188,7 +194,6 @@ class TicketsControllerTest < ActionController::TestCase assert assigns(:all_tickets).include?(testticket) get :index, {:user_id => user.id, :open_status => "open"} assert !assigns(:all_tickets).include?(testticket) - testticket.destroy end test "commenting on a ticket adds to tickets that are mine" do @@ -204,8 +209,6 @@ class TicketsControllerTest < ActionController::TestCase assert assigns(:all_tickets).include?(assigns(:ticket)) assert_not_nil assigns(:ticket).comments.last.posted_by assert_equal assigns(:ticket).comments.last.posted_by, @current_user.id - - assigns(:ticket).destroy end test "admin ticket ordering" do @@ -228,7 +231,6 @@ class TicketsControllerTest < ActionController::TestCase assert_not_equal first_tick, assigns(:all_tickets).first assert_not_equal last_tick, assigns(:all_tickets).last - tickets.each {|ticket| ticket.destroy} end test "tickets for regular user" do @@ -275,7 +277,6 @@ class TicketsControllerTest < ActionController::TestCase assert assigns(:all_tickets).include?(other_ticket) assert_equal assigns(:all_tickets).count, number_closed_tickets + number_open_tickets - assigns(:all_tickets).each {|t| t.destroy} end diff --git a/engines/support/test/integration/create_ticket_test.rb b/engines/support/test/integration/create_ticket_test.rb new file mode 100644 index 0000000000000000000000000000000000000000..0f8453cf057b984e34813a404fdc4f0adafc282a --- /dev/null +++ b/engines/support/test/integration/create_ticket_test.rb @@ -0,0 +1,64 @@ +require 'test_helper' + +class CreateTicketTest < BrowserIntegrationTest + + test "can submit ticket anonymously" do + visit '/' + click_on 'Get Help' + fill_in 'Subject', with: 'test ticket' + fill_in 'Description', with: 'description of the problem goes here' + click_on 'Create Ticket' + assert page.has_content?("Ticket was successfully created.") + assert page.has_content?("You can later access this ticket at the URL") + assert page.has_content?(current_url) + assert ticket = Ticket.last + ticket.destroy + end + + test "get help when creating ticket with invalid email" do + visit '/' + click_on 'Get Help' + fill_in 'Subject', with: 'test ticket' + fill_in 'Email', with: 'invalid data' + fill_in 'Regarding user', with: 'some user' + fill_in 'Description', with: 'description of the problem goes here' + click_on 'Create Ticket' + assert page.has_content?("is invalid") + assert_equal 'invalid data', find_field('Email').value + assert_equal 'some user', find_field('Regarding user').value + end + + test "prefills fields" do + login FactoryGirl.create(:premium_user) + visit '/' + click_on "Support Tickets" + click_on "New Ticket" + email = "#{@user.login}@#{APP_CONFIG[:domain]}" + assert_equal email, find_field('Email').value + assert_equal @user.login, find_field('Regarding user').value + end + + test "no prefill of email without email service" do + login + visit '/' + click_on "Support Tickets" + click_on "New Ticket" + assert_equal "", find_field('Email').value + assert_equal @user.login, find_field('Regarding user').value + end + + test "cleared email field should remain clear" do + login FactoryGirl.create(:premium_user) + visit '/' + click_on "Support Tickets" + click_on "New Ticket" + fill_in 'Subject', with: 'test ticket' + fill_in 'Email', with: '' + fill_in 'Description', with: 'description of the problem goes here' + click_on 'Create Ticket' + ticket = Ticket.last + assert_equal "", ticket.email + ticket.destroy + end + +end diff --git a/certs/test/integration/navigation_test.rb b/engines/support/test/integration/navigation_test.rb similarity index 100% rename from certs/test/integration/navigation_test.rb rename to engines/support/test/integration/navigation_test.rb diff --git a/help/test/leap_web_help_test.rb b/engines/support/test/leap_web_help_test.rb similarity index 100% rename from help/test/leap_web_help_test.rb rename to engines/support/test/leap_web_help_test.rb diff --git a/billing/test/test_helper.rb b/engines/support/test/test_helper.rb similarity index 83% rename from billing/test/test_helper.rb rename to engines/support/test/test_helper.rb index 1e26a313cdcb35faa6dc58d2da694c80fcafbb9c..fff9173a516cc91c799160f89ffb39d60545c07a 100644 --- a/billing/test/test_helper.rb +++ b/engines/support/test/test_helper.rb @@ -1,7 +1,7 @@ # Configure Rails Environment ENV["RAILS_ENV"] = "test" -require File.expand_path("../dummy/config/environment.rb", __FILE__) +require File.expand_path('../../../../test/dummy/config/environment', __FILE__) require "rails/test_help" Rails.backtrace_cleaner.remove_silencers! diff --git a/help/test/unit/account_extension_test.rb b/engines/support/test/unit/account_extension_test.rb similarity index 100% rename from help/test/unit/account_extension_test.rb rename to engines/support/test/unit/account_extension_test.rb diff --git a/help/test/unit/ticket_comment_test.rb b/engines/support/test/unit/ticket_comment_test.rb similarity index 100% rename from help/test/unit/ticket_comment_test.rb rename to engines/support/test/unit/ticket_comment_test.rb diff --git a/help/test/unit/ticket_test.rb b/engines/support/test/unit/ticket_test.rb similarity index 97% rename from help/test/unit/ticket_test.rb rename to engines/support/test/unit/ticket_test.rb index f5e6ea73daee69819ec782ec62210c40805822c5..678d8dc8a398574d2a8c4bf3636bc776be54aca3 100644 --- a/help/test/unit/ticket_test.rb +++ b/engines/support/test/unit/ticket_test.rb @@ -27,10 +27,10 @@ class TicketTest < ActiveSupport::TestCase end test "creation validated" do + user = FactoryGirl.create :user @sample = Ticket.new assert !@sample.is_creator_validated? - #p current_user - @sample.created_by = 22 #current_user + @sample.created_by = user.id assert @sample.is_creator_validated? end diff --git a/help/app/views/tickets/new.html.haml b/help/app/views/tickets/new.html.haml deleted file mode 100644 index 8f217a5a80c4defbdf7a5f0b99f6d4270e6c99fb..0000000000000000000000000000000000000000 --- a/help/app/views/tickets/new.html.haml +++ /dev/null @@ -1,30 +0,0 @@ -- @show_navigation = !params[:user_id].nil? - -= render 'tickets/tabs' - -- if admin? && @user - - email = @user.email_address - - regarding = @user.login -- elsif logged_in? - - email = current_user.email_address - - regarding = current_user.login - -= simple_form_for @ticket, :validate => true, :html => {:class => 'form-horizontal'} do |f| - = hidden_ticket_fields - = f.input :subject - - if logged_in? - = f.input :email, input_html: {value: email} - = f.input :regarding_user, input_html: {value: regarding} - - else - = f.input :email - = f.input :regarding_user - = f.simple_fields_for :comments, @comment do |c| - = c.input :body, :label => t(:description), :as => :text, :input_html => {:class => "full-width", :rows=> 5} - - if admin? - = c.input :private, :as => :boolean, :label => false, :inline_label => true - .form-actions - = f.button :submit, :class => 'btn-primary', :value => t(:create_thing, :thing => t(:ticket)) - - if logged_in? - = link_to t(:cancel), auto_tickets_path, :class => :btn - - else - = link_to t(:cancel), home_path, :class => 'btn' \ No newline at end of file diff --git a/help/lib/leap_web_help/engine.rb b/help/lib/leap_web_help/engine.rb deleted file mode 100644 index 4146dfc0311f2304f9ba43f1f06a5534b81117a6..0000000000000000000000000000000000000000 --- a/help/lib/leap_web_help/engine.rb +++ /dev/null @@ -1,8 +0,0 @@ -# thou shall require all your dependencies in an engine. -require "leap_web_core" -require "leap_web_core/ui_dependencies" - -module LeapWebHelp - class Engine < ::Rails::Engine - end -end diff --git a/leap_web.gemspec b/leap_web.gemspec index 44a30e0715d6ed1600135254cb8e574d6cfda849..125c93013db46b5b99619582ed60b0e9bb93916e 100644 --- a/leap_web.gemspec +++ b/leap_web.gemspec @@ -19,7 +19,4 @@ Gem::Specification.new do |s| s.email = 'azul@leap.se' s.homepage = 'http://leap.se' - # s.add_dependency 'leap_web_core' - s.add_dependency 'leap_web_certs', LeapWeb::VERSION - s.add_dependency 'leap_web_users', LeapWeb::VERSION end diff --git a/core/lib/extensions/couchrest.rb b/lib/extensions/couchrest.rb similarity index 96% rename from core/lib/extensions/couchrest.rb rename to lib/extensions/couchrest.rb index a9a195e4ab49838c6eb72a20ed7462c71f3ce04f..95f5d92ea2c97afa73bbf1ee5c11719ea2f199b3 100644 --- a/core/lib/extensions/couchrest.rb +++ b/lib/extensions/couchrest.rb @@ -45,7 +45,7 @@ module CouchRest def self.load_all_models_with_engines self.load_all_models_without_engines return unless defined?(Rails) - Dir[Rails.root + '*/app/models/**/*.rb'].each do |path| + Dir[Rails.root + 'engines/*/app/models/**/*.rb'].each do |path| require path end end diff --git a/lib/extensions/simple_form.rb b/lib/extensions/simple_form.rb new file mode 100644 index 0000000000000000000000000000000000000000..f28e18f8d759ee7022b6b44c8b9a3898c640f7a9 --- /dev/null +++ b/lib/extensions/simple_form.rb @@ -0,0 +1,28 @@ +module WrappedButton + def wrapped_button(*args, &block) + template.content_tag :div, :class => "form-actions" do + options = args.extract_options! + options[:class] = ['btn-primary', options[:class]].compact + args.unshift :loading + args << options + if cancel = options.delete(:cancel) + cancel_link = template.link_to I18n.t('simple_form.buttons.cancel'), + cancel, class: :btn + button(*args, &block) + ' ' + cancel_link + else + button(*args, &block) + end + end + end +end +SimpleForm::FormBuilder.send :include, WrappedButton + +module LoadingButton + def loading_button(*args, &block) + options = args.extract_options! + options[:"data-loading-text"] = I18n.t('simple_form.buttons.loading') + args << options + button_button(*args, &block) + end +end +SimpleForm::FormBuilder.send :include, LoadingButton diff --git a/lib/leap_web.rb b/lib/leap_web.rb deleted file mode 100644 index 9495fc6ced8b1a5573e968135bf28aa153865d47..0000000000000000000000000000000000000000 --- a/lib/leap_web.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'leap_web_core' -require 'leap_web_certs' -require 'leap_web_users' -# do we want billing and help here? diff --git a/core/lib/tasks/leap_web_core_tasks.rake b/lib/tasks/leap_web_core_tasks.rake similarity index 100% rename from core/lib/tasks/leap_web_core_tasks.rake rename to lib/tasks/leap_web_core_tasks.rake diff --git a/lib/tasks/leap_web_users_tasks.rake b/lib/tasks/leap_web_users_tasks.rake new file mode 100644 index 0000000000000000000000000000000000000000..62bcbe94ec9b192a6e9c574a8194d9f8304b7a06 --- /dev/null +++ b/lib/tasks/leap_web_users_tasks.rake @@ -0,0 +1,10 @@ +# desc "Explaining what the task does" +# task :leap_web_users do +# # Task goes here +# end + +# recommended that for our setup, we should have this triggered from a cron job in puppet rather than using whenever gem +desc "Send one month warning messages" +task :leap_web_users do + User.send_one_month_warnings +end diff --git a/lib/tasks/test.rake b/lib/tasks/test.rake index 3c87b4538ddddcf374368915daa0b3970ddbebd4..d96b6258199b4139873d658d18829ba95512ee76 100644 --- a/lib/tasks/test.rake +++ b/lib/tasks/test.rake @@ -1,18 +1,11 @@ namespace :test do - Rails::SubTestTask.new(:units => "test:prepare") do |t| - t.libs << "test" - t.pattern = '*/test/unit/**/*_test.rb' - end - - Rails::SubTestTask.new(:functionals => "test:prepare") do |t| - t.libs << "test" - t.pattern = '*/test/functional/**/*_test.rb' - end - - Rails::SubTestTask.new(:integration => "test:prepare") do |t| - t.libs << "test" - t.pattern = '*/test/integration/**/*_test.rb' + [:units, :functionals, :integration].each do |type| + Rails::SubTestTask.new(type => "test:prepare") do |t| + t.libs << "test" + subdir = type.to_s.singularize + t.pattern = "engines/*/test/#{subdir}/**/*_test.rb" + end end end diff --git a/users/lib/warden/session_serializer.rb b/lib/warden/session_serializer.rb similarity index 100% rename from users/lib/warden/session_serializer.rb rename to lib/warden/session_serializer.rb diff --git a/users/lib/warden/strategies/secure_remote_password.rb b/lib/warden/strategies/secure_remote_password.rb similarity index 100% rename from users/lib/warden/strategies/secure_remote_password.rb rename to lib/warden/strategies/secure_remote_password.rb diff --git a/users/lib/webfinger.rb b/lib/webfinger.rb similarity index 100% rename from users/lib/webfinger.rb rename to lib/webfinger.rb diff --git a/users/lib/webfinger/host_meta_presenter.rb b/lib/webfinger/host_meta_presenter.rb similarity index 100% rename from users/lib/webfinger/host_meta_presenter.rb rename to lib/webfinger/host_meta_presenter.rb diff --git a/users/lib/webfinger/user_presenter.rb b/lib/webfinger/user_presenter.rb similarity index 100% rename from users/lib/webfinger/user_presenter.rb rename to lib/webfinger/user_presenter.rb diff --git a/test/factories.rb b/test/factories.rb index 6c671f82c76ad932640a24c2148ed0150e15006d..bebda5cc6d609e9a9497319f765f661534bc8392 100644 --- a/test/factories.rb +++ b/test/factories.rb @@ -1,3 +1,44 @@ -Dir.glob(Rails.root.join('**','test','factories.rb')) do |factory_file| +ENGINE_FACTORY_FILES = Rails.root.join('engines','*','test','factories.rb') +Dir.glob(ENGINE_FACTORY_FILES) do |factory_file| require factory_file end + +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 + + factory :premium_user do + effective_service_level_code 2 + 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/certs/test/files/ca.crt b/test/files/ca.crt similarity index 100% rename from certs/test/files/ca.crt rename to test/files/ca.crt diff --git a/certs/test/files/ca.key b/test/files/ca.key similarity index 100% rename from certs/test/files/ca.key rename to test/files/ca.key diff --git a/users/test/functional/application_controller_test.rb b/test/functional/application_controller_test.rb similarity index 66% rename from users/test/functional/application_controller_test.rb rename to test/functional/application_controller_test.rb index 94b77bdfe2dfc10c9752c10d1c44a315b801fb68..c4c922bbd1a57352965eaf189cd7af423a251212 100644 --- a/users/test/functional/application_controller_test.rb +++ b/test/functional/application_controller_test.rb @@ -7,21 +7,21 @@ class ApplicationControllerTest < ActionController::TestCase @controller.response = @response end - def test_authorize_redirect - @controller.send(:authorize) + def test_require_login_redirect + @controller.send(:require_login) assert_access_denied(true, false) end - def test_authorized + def test_require_login login - @controller.send(:authorize) + @controller.send(:require_login) assert_access_denied(false) end - def test_authorize_admin + def test_require_admin login @current_user.expects(:is_admin?).returns(false) - @controller.send(:authorize_admin) + @controller.send(:require_admin) assert_access_denied end diff --git a/users/test/functional/helper_methods_test.rb b/test/functional/helper_methods_test.rb similarity index 100% rename from users/test/functional/helper_methods_test.rb rename to test/functional/helper_methods_test.rb diff --git a/users/test/functional/keys_controller_test.rb b/test/functional/keys_controller_test.rb similarity index 100% rename from users/test/functional/keys_controller_test.rb rename to test/functional/keys_controller_test.rb diff --git a/users/test/functional/sessions_controller_test.rb b/test/functional/sessions_controller_test.rb similarity index 100% rename from users/test/functional/sessions_controller_test.rb rename to test/functional/sessions_controller_test.rb diff --git a/users/test/functional/test_helpers_test.rb b/test/functional/test_helpers_test.rb similarity index 100% rename from users/test/functional/test_helpers_test.rb rename to test/functional/test_helpers_test.rb diff --git a/users/test/functional/users_controller_test.rb b/test/functional/users_controller_test.rb similarity index 96% rename from users/test/functional/users_controller_test.rb rename to test/functional/users_controller_test.rb index 57ae94dfa95b272ec9174362f8e2d6ee7f7cfcf8..0713836ab66e061731117804b38b51566cb6bc8d 100644 --- a/users/test/functional/users_controller_test.rb +++ b/test/functional/users_controller_test.rb @@ -4,11 +4,17 @@ class UsersControllerTest < ActionController::TestCase test "should get new" do get :new - assert_equal User, assigns(:user).class assert_response :success end + test "new should redirect logged in users" do + login + get :new + assert_response :redirect + assert_redirected_to home_path + end + test "failed show without login" do user = find_record :user get :show, :id => user.id diff --git a/test/functional/v1/certs_controller_test.rb b/test/functional/v1/certs_controller_test.rb new file mode 100644 index 0000000000000000000000000000000000000000..fb8e9c42412220b4e47688305c37fada5f530781 --- /dev/null +++ b/test/functional/v1/certs_controller_test.rb @@ -0,0 +1,46 @@ +require 'test_helper' + +class V1::CertsControllerTest < ActionController::TestCase + + test "send unlimited cert without login" do + with_config allow_anonymous_certs: true do + cert = expect_cert('UNLIMITED') + get :show + assert_response :success + assert_equal cert.to_s, @response.body + end + end + + test "send limited cert" do + with_config allow_limited_certs: true do + login + cert = expect_cert('LIMITED') + get :show + assert_response :success + assert_equal cert.to_s, @response.body + end + end + + test "send unlimited cert" do + login effective_service_level: ServiceLevel.new(id: 2) + cert = expect_cert('UNLIMITED') + get :show + assert_response :success + assert_equal cert.to_s, @response.body + end + + test "redirect if no eip service offered" do + get :show + assert_response :redirect + end + + protected + + def expect_cert(prefix) + cert = stub :to_s => "#{prefix.downcase} cert" + ClientCertificate.expects(:new). + with(:prefix => prefix). + returns(cert) + return cert + end +end diff --git a/test/functional/v1/messages_controller_test.rb b/test/functional/v1/messages_controller_test.rb new file mode 100644 index 0000000000000000000000000000000000000000..24a5b1fff3f87b22a015bc4f25b13373b1f7e915 --- /dev/null +++ b/test/functional/v1/messages_controller_test.rb @@ -0,0 +1,57 @@ +require 'test_helper' + +class V1::MessagesControllerTest < ActionController::TestCase + + setup do + @user = FactoryGirl.build(:user) + @user.save + @message = Message.new(:text => 'a test message') + @message.user_ids_to_show << @user.id + @message.save + end + + teardown do + @message.destroy + @user.destroy + end + + test "get messages for user" do + login @user + get :index + assert response.body.include? @message.text + assert response.body.include? @message.id + end + + test "mark message read for user" do + login @user + assert @message.user_ids_to_show.include?(@user.id) + assert !@message.user_ids_have_shown.include?(@user.id) + put :update, :id => @message.id + @message.reload + assert !@message.user_ids_to_show.include?(@user.id) + assert @message.user_ids_have_shown.include?(@user.id) + assert_json_response true + end + + test "do not get seen messages" do + login @user + put :update, :id => @message.id + @message.reload + get :index + assert !(response.body.include? @message.text) + assert !(response.body.include? @message.id) + end + + + test "mark read responds even with bad inputs" do + login @user + put :update, :id => 'more nonsense' + assert_json_response false + end + + test "fails if not authenticated" do + get :index, :format => :json + assert_access_denied + end + +end diff --git a/test/functional/v1/services_controller_test.rb b/test/functional/v1/services_controller_test.rb new file mode 100644 index 0000000000000000000000000000000000000000..cde7d9f2e70824d8348999a051d86fe189a6af6a --- /dev/null +++ b/test/functional/v1/services_controller_test.rb @@ -0,0 +1,29 @@ +require 'test_helper' + +class V1::ServicesControllerTest < ActionController::TestCase + + test "anonymous user gets login required service info" do + get :show, format: :json + assert_json_response name: 'anonymous', + eip_rate_limit: false, + description: 'please login to access our services' + end + + test "anonymous user gets vpn service info" do + with_config allow_anonymous_certs: true do + get :show, format: :json + assert_json_response name: 'anonymous', + eip_rate_limit: false, + description: 'anonymous access to the VPN' + end + end + + test "user can see their service info" do + login + get :show, format: :json + default_level = APP_CONFIG[:default_service_level] + assert_json_response APP_CONFIG[:service_levels][default_level] + end + +end + diff --git a/users/test/functional/v1/sessions_controller_test.rb b/test/functional/v1/sessions_controller_test.rb similarity index 98% rename from users/test/functional/v1/sessions_controller_test.rb rename to test/functional/v1/sessions_controller_test.rb index 4200e8f27277f57341599304472acd42d8acbb5f..df0d681b643c23ba020318b1d4c7fa47d0bbf150 100644 --- a/users/test/functional/v1/sessions_controller_test.rb +++ b/test/functional/v1/sessions_controller_test.rb @@ -36,7 +36,7 @@ class V1::SessionsControllerTest < ActionController::TestCase post :create, :login => @user.login, 'A' => @client_hex end - test "should authorize" do + test "should authenticate" do request.env['warden'].expects(:authenticate!) @controller.stubs(:current_user).returns(@user) handshake = stub(:to_hash => {h: "ash"}) diff --git a/users/test/functional/v1/users_controller_test.rb b/test/functional/v1/users_controller_test.rb similarity index 100% rename from users/test/functional/v1/users_controller_test.rb rename to test/functional/v1/users_controller_test.rb diff --git a/users/test/functional/webfinger_controller_test.rb b/test/functional/webfinger_controller_test.rb similarity index 100% rename from users/test/functional/webfinger_controller_test.rb rename to test/functional/webfinger_controller_test.rb diff --git a/users/test/integration/api/Readme.md b/test/integration/api/Readme.md similarity index 100% rename from users/test/integration/api/Readme.md rename to test/integration/api/Readme.md diff --git a/test/integration/api/login_test.rb b/test/integration/api/login_test.rb new file mode 100644 index 0000000000000000000000000000000000000000..92d153f55b2c2569b88a126aff62fafd840d91fd --- /dev/null +++ b/test/integration/api/login_test.rb @@ -0,0 +1,50 @@ +require 'test_helper' +require_relative 'srp_test' + +class LoginTest < SrpTest + + setup do + register_user + end + + test "requires handshake before validation" do + validate("bla") + assert_json_error login: I18n.t(:all_strategies_failed) + end + + test "login with srp" do + authenticate + assert_equal ["M2", "id", "token"], server_auth.keys + assert last_response.successful? + assert_nil server_auth["errors"] + assert server_auth["M2"] + end + + test "wrong password login attempt" do + authenticate password: "wrong password" + assert_json_error "base" => "Not a valid username/password combination" + assert !last_response.successful? + assert_nil server_auth["M2"] + end + + test "wrong username login attempt" do + assert_raises RECORD_NOT_FOUND do + authenticate login: "wrong login" + end + assert_json_error "base" => "Not a valid username/password combination" + assert !last_response.successful? + assert_nil server_auth + end + + test "logout" do + authenticate + logout + assert_equal 204, last_response.status + end + + test "logout requires token" do + authenticate + logout(nil, {}) + assert_equal 422, last_response.status + end +end diff --git a/test/integration/api/pgp_key_test.rb b/test/integration/api/pgp_key_test.rb new file mode 100644 index 0000000000000000000000000000000000000000..4c7fb4c73069cd7677bb4efd40699dff1d2bf584 --- /dev/null +++ b/test/integration/api/pgp_key_test.rb @@ -0,0 +1,35 @@ +require 'test_helper' +require_relative 'srp_test' + +class PgpKeyTest < SrpTest + + setup do + # todo: prepare user and login without doing the srp dance + register_user + authenticate + end + + test "upload pgp key" do + update_user public_key: key + 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 + update_user public_key: "invalid key" + assert_nil Identity.for(@user).keys[:pgp] + end + + test "prevent emptying public key" do + update_user public_key: key + update_user public_key: "" + assert_equal key, Identity.for(@user).keys[:pgp] + end + + protected + + def key + @key ||= FactoryGirl.build :pgp_key + end +end diff --git a/users/test/integration/api/python/flow_with_srp.py b/test/integration/api/python/flow_with_srp.py similarity index 100% rename from users/test/integration/api/python/flow_with_srp.py rename to test/integration/api/python/flow_with_srp.py diff --git a/users/test/integration/api/python/login_wrong_username.py b/test/integration/api/python/login_wrong_username.py similarity index 100% rename from users/test/integration/api/python/login_wrong_username.py rename to test/integration/api/python/login_wrong_username.py diff --git a/users/test/integration/api/python/signup.py b/test/integration/api/python/signup.py similarity index 100% rename from users/test/integration/api/python/signup.py rename to test/integration/api/python/signup.py diff --git a/users/test/integration/api/python/signup_and_login.py b/test/integration/api/python/signup_and_login.py similarity index 100% rename from users/test/integration/api/python/signup_and_login.py rename to test/integration/api/python/signup_and_login.py diff --git a/users/test/integration/api/python/signup_and_login_wrong_password.py b/test/integration/api/python/signup_and_login_wrong_password.py similarity index 100% rename from users/test/integration/api/python/signup_and_login_wrong_password.py rename to test/integration/api/python/signup_and_login_wrong_password.py diff --git a/users/test/integration/api/python/umlauts.py b/test/integration/api/python/umlauts.py similarity index 100% rename from users/test/integration/api/python/umlauts.py rename to test/integration/api/python/umlauts.py diff --git a/test/integration/api/signup_test.rb b/test/integration/api/signup_test.rb new file mode 100644 index 0000000000000000000000000000000000000000..236c5474b0003eb947a32b4e75fe172f96b712ed --- /dev/null +++ b/test/integration/api/signup_test.rb @@ -0,0 +1,20 @@ +require 'test_helper' +require_relative 'srp_test' + +class SignupTest < SrpTest + + setup do + register_user + end + + test "signup response" do + assert_json_response :login => @login, :ok => true + assert last_response.successful? + end + + test "signup creates user" do + assert @user + assert_equal @login, @user.login + end +end + diff --git a/test/integration/api/srp_test.rb b/test/integration/api/srp_test.rb new file mode 100644 index 0000000000000000000000000000000000000000..26adc8c89e623f9edb2b4627360b45aac49f99ee --- /dev/null +++ b/test/integration/api/srp_test.rb @@ -0,0 +1,105 @@ +class SrpTest < RackTest + include AssertResponses + + teardown do + if @user + cleanup_user + 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 + + protected + + attr_reader :server_auth + + def register_user(login = "integration_test_user", password = 'srp, verify me!') + cleanup_user(login) + post 'http://api.lvh.me:3000/1/users.json', + user_params(login: login, password: password) + @user = User.find_by_login(login) + @login = login + @password = password + end + + def update_user(params) + put "http://api.lvh.me:3000/1/users/" + @user.id + '.json', + user_params(params), + auth_headers + end + + def authenticate(params = nil) + @server_auth = srp(params).authenticate(self) + end + + def auth_headers + return {} if @server_auth.nil? + { + "HTTP_AUTHORIZATION" => encoded_token + } + end + + def encoded_token + ActionController::HttpAuthentication::Token.encode_credentials(server_auth["token"]) + end + + def logout(params=nil, headers=nil) + delete "http://api.lvh.me:3000/1/logout.json", + params || {format: :json}, + headers || auth_headers + end + + def cleanup_user(login = nil) + login ||= @user.login + Identity.by_address.key(login + '@' + APP_CONFIG[:domain]).each do |identity| + identity.destroy + end + if user = User.find_by_login(login) + user.destroy + end + end + + def user_params(params) + if params.keys.include?(:password) + srp_process_password(params) + end + return { user: params, format: :json } + end + + def srp_process_password(params) + params.reverse_merge! login: @login, salt: @salt + @srp = SRP::Client.new params[:login], password: params.delete(:password) + @salt = srp.salt.to_s(16) + params.merge! :password_verifier => srp.verifier.to_s(16), + :password_salt => @salt + end + + def srp(params = nil) + if params.nil? + @srp + else + params.reverse_merge! password: @password + SRP::Client.new(params.delete(:login) || @login, params) + end + end +end diff --git a/test/integration/api/update_account_test.rb b/test/integration/api/update_account_test.rb new file mode 100644 index 0000000000000000000000000000000000000000..63429e7a1cd737fba98f44c2b115e85334a3d471 --- /dev/null +++ b/test/integration/api/update_account_test.rb @@ -0,0 +1,51 @@ +require 'test_helper' +require_relative 'srp_test' + +class UpdateAccountTest < SrpTest + + setup do + register_user + end + + test "require authentication" do + update_user password: "No! Verify me instead." + assert_access_denied + end + + test "require token" do + authenticate + put "http://api.lvh.me:3000/1/users/" + @user.id + '.json', + user_params(password: "No! Verify me instead.") + assert_access_denied + end + + test "update password via api" do + authenticate + update_user password: "No! Verify me instead." + authenticate + assert last_response.successful? + assert_nil server_auth["errors"] + assert server_auth["M2"] + end + + test "change login with password_verifier" do + authenticate + new_login = 'zaph' + cleanup_user new_login + update_user login: new_login, password: @password + authenticate + assert last_response.successful? + assert_equal new_login, @user.reload.login + end + + test "prevent changing login without changing password_verifier" do + authenticate + original_login = @user.login + new_login = 'zaph' + cleanup_user new_login + update_user login: new_login + assert last_response.successful? + # does not change login if no password_verifier is present + assert_equal original_login, @user.reload.login + end +end diff --git a/users/test/integration/browser/account_test.rb b/test/integration/browser/account_test.rb similarity index 78% rename from users/test/integration/browser/account_test.rb rename to test/integration/browser/account_test.rb index a5677ad388e78f20dfb0807880051f852eeae5f2..491a9e13ae53547c0ec5dc05428b7d7fc92ca9ac 100644 --- a/users/test/integration/browser/account_test.rb +++ b/test/integration/browser/account_test.rb @@ -6,7 +6,7 @@ class AccountTest < BrowserIntegrationTest Identity.destroy_all_disabled end - test "normal account workflow" do + test "signup successfully" do username, password = submit_signup assert page.has_content?("Welcome #{username}") click_on 'Logout' @@ -16,6 +16,12 @@ class AccountTest < BrowserIntegrationTest user.account.destroy end + test "signup with username ending in dot json" do + username = Faker::Internet.user_name + '.json' + submit_signup username + assert page.has_content?("Welcome #{username}") + end + test "successful login" do username, password = submit_signup click_on 'Logout' @@ -51,7 +57,7 @@ class AccountTest < BrowserIntegrationTest end test "default user actions" do - username, password = submit_signup + login click_on "Account Settings" assert page.has_content? I18n.t('destroy_my_account') assert page.has_no_css? '#update_login_and_password' @@ -59,8 +65,8 @@ class AccountTest < BrowserIntegrationTest end test "default admin actions" do - username, password = submit_signup - with_config admins: [username] do + login + with_config admins: [@user.login] do click_on "Account Settings" assert page.has_content? I18n.t('destroy_my_account') assert page.has_no_css? '#update_login_and_password' @@ -70,7 +76,7 @@ class AccountTest < BrowserIntegrationTest test "change password" do with_config user_actions: ['change_password'] do - username, password = submit_signup + login click_on "Account Settings" within('#update_login_and_password') do fill_in 'Password', with: "other password" @@ -78,16 +84,15 @@ class AccountTest < BrowserIntegrationTest 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 + attempt_login(@user.login, "other password") + assert page.has_content?("Welcome #{@user.login}") 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 + login click_on "Account Settings" within('#update_pgp_key') do fill_in 'Public key', with: pgp_key @@ -97,9 +102,7 @@ class AccountTest < BrowserIntegrationTest # 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 + assert_equal pgp_key, @user.reload.public_key end end @@ -123,6 +126,20 @@ class AccountTest < BrowserIntegrationTest assert page.has_content?("server failed") end + test "does not render signup form without js" do + Capybara.current_driver = :rack_test # no js + visit '/signup' + assert page.has_no_content?("Username") + assert page.has_no_content?("Password") + end + + test "does not render login form without js" do + Capybara.current_driver = :rack_test # no js + visit '/login' + assert page.has_no_content?("Username") + assert page.has_no_content?("Password") + end + def attempt_login(username, password) click_on 'Log In' fill_in 'Username', with: username @@ -131,9 +148,9 @@ class AccountTest < BrowserIntegrationTest end def assert_invalid_login(page) - assert page.has_selector? 'input.btn-primary.disabled' + assert page.has_selector? '.btn-primary.disabled' assert page.has_content? I18n.t(:invalid_user_pass) - assert page.has_no_selector? 'input.btn-primary.disabled' + assert page.has_no_selector? '.btn-primary.disabled' end def inject_malicious_js diff --git a/test/integration/browser/password_validation_test.rb b/test/integration/browser/password_validation_test.rb new file mode 100644 index 0000000000000000000000000000000000000000..45eb0bf5a33136c413af4e14c12f84c9e1bcf644 --- /dev/null +++ b/test/integration/browser/password_validation_test.rb @@ -0,0 +1,31 @@ +require 'test_helper' + +class PasswordValidationTest < BrowserIntegrationTest + + test "password confirmation is validated" do + 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 + "-typo" + click_on 'Sign Up' + assert page.has_content? "does not match." + assert_equal '/users/new', current_path + assert page.has_selector? ".error #srp_password_confirmation" + end + + test "password needs to be at least 8 chars long" do + username ||= "test_#{SecureRandom.urlsafe_base64}".downcase + password ||= SecureRandom.base64[0,7] + visit '/users/new' + fill_in 'Username', with: username + fill_in 'Password', with: password + fill_in 'Password confirmation', with: password + click_on 'Sign Up' + assert page.has_content? "needs to be at least 8 characters long" + assert_equal '/users/new', current_path + assert page.has_selector? ".error #srp_password" + end +end + diff --git a/test/integration/browser/session_test.rb b/test/integration/browser/session_test.rb new file mode 100644 index 0000000000000000000000000000000000000000..fb20847288499296b5e5cdf4dffbdad8f86e92c5 --- /dev/null +++ b/test/integration/browser/session_test.rb @@ -0,0 +1,17 @@ +require 'test_helper' + +class SessionTest < BrowserIntegrationTest + + test "valid session" do + login + assert page.has_content?("Logout") + end + + test "expired session" do + login + pretend_now_is(Time.now + 80.minutes) do + visit '/' + assert page.has_content?("Log In") + end + end +end diff --git a/help/test/integration/navigation_test.rb b/test/integration/navigation_test.rb similarity index 100% rename from help/test/integration/navigation_test.rb rename to test/integration/navigation_test.rb diff --git a/test/integration/os_detection_test.rb b/test/integration/os_detection_test.rb deleted file mode 100644 index 6d9a648d8fcacbe094baba725981b8bbbb275076..0000000000000000000000000000000000000000 --- a/test/integration/os_detection_test.rb +++ /dev/null @@ -1,20 +0,0 @@ -require 'test_helper' - -class OsDetectionTest < BrowserIntegrationTest - - test "old windows shows deactivated download" do - page.driver.add_headers "User-Agent" => "Win98" - visit '/' - assert_selector "html.oldwin" - assert has_text? "not available" - end - - test "android shows android download" do - page.driver.add_headers "User-Agent" => "Android" - visit '/' - assert_selector "html.android" - assert has_no_text? "not available" - assert_selector "small", text: "Android" - end - -end diff --git a/users/test/leap_web_users_test.rb b/test/leap_web_users_test.rb similarity index 100% rename from users/test/leap_web_users_test.rb rename to test/leap_web_users_test.rb diff --git a/test/nagios/soledad_sync.py b/test/nagios/soledad_sync.py index 3f176b5c6a6358d870caf96893e4656de3cbb37f..617dd3a8578667df4339f83ee2bc6ecc8c2b3945 100755 --- a/test/nagios/soledad_sync.py +++ b/test/nagios/soledad_sync.py @@ -7,13 +7,15 @@ import tempfile -import requests import os -import srp._pysrp as srp import shutil import u1db +from support.api import Api +from support.config import Config +from support.user import User + + from u1db.remote.http_target import HTTPSyncTarget -from webapp_login import read_config, parse, authenticate, fail # monkey patch U1DB's HTTPSyncTarget to perform token based auth @@ -37,58 +39,39 @@ HTTPSyncTarget._sign_request = _sign_request # to actually use the Soledad client in the future. def get_soledad_info(config, tempdir): - # get login and get user info - user = config['user'] - api = config['api'] - usr = srp.User( user['username'], user['password'], srp.SHA256, srp.NG_1024 ) - try: - auth = parse(authenticate(api, usr)) - except requests.exceptions.ConnectionError: - fail('no connection to server') - # get soledad server url - service_url = 'https://%s:%d/%d/config/soledad-service.json' % \ - (api['domain'], api['port'], api['version']) - soledad_hosts = requests.get(service_url).json['hosts'] - host = soledad_hosts.keys()[0] - server_url = 'https://%s:%d/user-%s' % \ - (soledad_hosts[host]['hostname'], soledad_hosts[host]['port'], - auth['id']) - # get provider ca certificate - #ca_cert = requests.get('https://127.0.0.1/ca.crt', verify=False).text - #cert_file = os.path.join(tempdir, 'ca.crt') - cert_file = None # not used for now - #with open(cert_file, 'w') as f: - # f.write(ca_cert) - return auth['id'], user['password'], server_url, cert_file, auth['token'] - - -def run_tests(): - tempdir = tempfile.mkdtemp() - uuid, password, server_url, cert_file, token = \ - get_soledad_info(read_config(), tempdir) - exc = None - try: - # in the future, we can replace the following by an actual Soledad - # client sync, if needed - db = u1db.open(os.path.join(tempdir, '%s.db' % uuid), True) - creds = {'token': {'uuid': uuid, 'token': token}} - db.sync(server_url, creds=creds, autocreate=False) - except Exception as e: - exc = e - shutil.rmtree(tempdir) - exit(report(exc)) - - -def report(exc): - if exc is None: - print '0 soledad_sync - OK - can sync soledad fine' - return 0 - if isinstance(exc, u1db.errors.U1DBError): - print '2 soledad_sync - CRITICAL - ' + exc.message - else: - print '2 soledad_sync - CRITICAL - ' + str(exc) - return 2 - + # get login and get user info + user = User(config) + api = Api(config, verify=False) + auth = user.login(api) + # get soledad server url + soledad_hosts = api.get('config/soledad-service.json')['hosts'] + host = soledad_hosts.keys()[0] + server_url = 'https://%s:%d/user-%s' % \ + (soledad_hosts[host]['hostname'], soledad_hosts[host]['port'], + auth['id']) + # get provider ca certificate + #ca_cert = requests.get('https://127.0.0.1/ca.crt', verify=False).text + #cert_file = os.path.join(tempdir, 'ca.crt') + cert_file = None # not used for now + #with open(cert_file, 'w') as f: + # f.write(ca_cert) + return auth['id'], server_url, cert_file, auth['token'] + + +def can_sync_soledad_fine(): + tempdir = tempfile.mkdtemp() + try: + uuid, server_url, cert_file, token = \ + get_soledad_info(Config(), tempdir) + # in the future, we can replace the following by an actual Soledad + # client sync, if needed + db = u1db.open(os.path.join(tempdir, '%s.db' % uuid), True) + creds = {'token': {'uuid': uuid, 'token': token}} + db.sync(server_url, creds=creds, autocreate=False) + finally: + shutil.rmtree(tempdir) if __name__ == '__main__': - run_tests() + from support import nagios_test + exit_code = nagios_test.run(can_sync_soledad_fine) + exit(exit_code) diff --git a/certs/app/mailers/.gitkeep b/test/nagios/support/__init__.py similarity index 100% rename from certs/app/mailers/.gitkeep rename to test/nagios/support/__init__.py diff --git a/test/nagios/support/api.py b/test/nagios/support/api.py new file mode 100644 index 0000000000000000000000000000000000000000..ec1af990d932220c87e4d7d6d99a47b8914aa014 --- /dev/null +++ b/test/nagios/support/api.py @@ -0,0 +1,39 @@ +import requests +import json + +class Api(): + def __init__(self, config, verify=True): + self.config = config.api + self.session = requests.session() + self.verify = verify + + def api_url(self, path): + return self.api_root() + path + + def api_root(self): + return "https://{domain}:{port}/{version}/".format(**self.config) + + def get(self, path, **args): + response = self.session.get(self.api_url(path), + verify=self.verify, + **args) + return self.parse_json(response) + + def post(self, path, **args): + response = self.session.post(self.api_url(path), + verify=self.verify, + **args) + return self.parse_json(response) + + def put(self, path, **args): + response = self.session.put(self.api_url(path), + verify=self.verify, + **args) + return self.parse_json(response) + + def parse_json(self, response): + try: + return response.json() + except TypeError: + return response.json # older versions of requests + diff --git a/test/nagios/support/config.py b/test/nagios/support/config.py new file mode 100644 index 0000000000000000000000000000000000000000..afb4464ed380b907c81453413815ced3b5eb2a69 --- /dev/null +++ b/test/nagios/support/config.py @@ -0,0 +1,14 @@ +import yaml + +class Config(): + def __init__(self, filename="/etc/leap/hiera.yaml"): + with open("/etc/leap/hiera.yaml", 'r') as stream: + config = yaml.load(stream) + self.user = config['webapp']['nagios_test_user'] + if 'username' not in self.user: + raise Exception('nagios test user lacks username') + if 'password' not in self.user: + raise Exception('nagios test user lacks password') + self.api = config['api'] + self.api['version'] = config['webapp']['api_version'] + diff --git a/test/nagios/support/nagios_report.py b/test/nagios/support/nagios_report.py new file mode 100644 index 0000000000000000000000000000000000000000..13cd5515f20cf1e7138e1f6f61ebf91d403a12a8 --- /dev/null +++ b/test/nagios/support/nagios_report.py @@ -0,0 +1,24 @@ +def functions_for_system(under_test): + """ + returns a set of functions to use for nagios reporting: + >>> ok, warn, critical, unknown = functions_for_system("tested system") + + each of them will print a nagios line with its argument and + return the exit code: + >>> warn("that looks strange") + 1 tested system - WARNING - that looks strange + 1 + """ + def report_function(code): + return lambda message : report(under_test, code, message) + return map(report_function, [0,1,2,3]) + +def report(system, code, message): + codes = {0: 'OK', 1: 'WARNING', 2: 'CRITICAL', 3: 'UNKNOWN'} + print "%d %s - %s - %s" % \ + (code, system, codes[code], message) + return code + +if __name__ == "__main__": + import doctest + doctest.testmod() diff --git a/test/nagios/support/nagios_test.py b/test/nagios/support/nagios_test.py new file mode 100644 index 0000000000000000000000000000000000000000..3eb8d55690382420de2b2dc775c45633a768f369 --- /dev/null +++ b/test/nagios/support/nagios_test.py @@ -0,0 +1,49 @@ +import __main__ as main +import os +import sys +import nagios_report + +def run(test): + """ + run takes a function and tries it out. + If it returns nothing or 0 everything is fine and run prints an OK message + with the function name. + >>> def this_works_fine(): return + >>> run(this_works_fine) + 0 nagios_test.py - OK - this_works_fine + 0 + >>> def this_also_works_fine(): return 0 + >>> run(this_also_works_fine) + 0 nagios_test.py - OK - this_also_works_fine + 0 + + If the function returns something else it will be printed as a warning. + >>> run(lambda : "this is a warning") + 1 nagios_test.py - WARNING - this is a warning + 1 + + Errors raised will result in a CRITICAL nagios string. + >>> def failure(): raise Exception("something went wrong") + >>> run(failure) + 2 nagios_test.py - CRITICAL - something went wrong + 2 + """ + try: + name = os.path.basename(main.__file__) + except AttributeError: + name = sys.argv[0] + ok, warn, fail, unknown = nagios_report.functions_for_system(name) + try: + warning = test() + if warning and warning != 0: + code = warn(warning) + else: + code = ok(test.__name__) + except Exception as exc: + code = fail(exc.message or str(exc)) + return code + + +if __name__ == "__main__": + import doctest + doctest.testmod() diff --git a/test/nagios/support/user.py b/test/nagios/support/user.py new file mode 100644 index 0000000000000000000000000000000000000000..9bf1d0a098b23897a3198ff3fc56b4c2b67ce8a6 --- /dev/null +++ b/test/nagios/support/user.py @@ -0,0 +1,64 @@ +import srp._pysrp as srp +import binascii +import string +import random + +safe_unhexlify = lambda x: binascii.unhexlify(x) if ( + len(x) % 2 == 0) else binascii.unhexlify('0' + x) + +# let's have some random name and password +def id_generator(size=6, chars=string.ascii_lowercase + string.digits): + return ''.join(random.choice(chars) for x in range(size)) + +class User(): + def __init__(self, config = None): + if config and config.user: + self.username = config.user["username"] + self.password = config.user["password"] + else: + self.username = 'test_' + id_generator() + self.password = id_generator() + id_generator() + self.srp_user = srp.User(self.username, self.password, srp.SHA256, srp.NG_1024) + + def signup(self, api): + salt, vkey = srp.create_salted_verification_key( self.username, self.password, srp.SHA256, srp.NG_1024 ) + user_params = { + 'user[login]': self.username, + 'user[password_verifier]': binascii.hexlify(vkey), + 'user[password_salt]': binascii.hexlify(salt) + } + return api.post('users.json', data = user_params) + + def login(self, api): + init=self.init_authentication(api) + if ('errors' in init): + raise Exception('test user not found') + auth=self.authenticate(api, init) + if ('errors' in auth): + raise Exception('srp password auth failed') + self.verify_server(auth) + if not self.is_authenticated(): + raise Exception('user is not authenticated') + return auth + + def init_authentication(self, api): + uname, A = self.srp_user.start_authentication() + params = { + 'login': uname, + 'A': binascii.hexlify(A) + } + return api.post('sessions', data=params) + + def authenticate(self, api, init): + M = self.srp_user.process_challenge( + safe_unhexlify(init['salt']), safe_unhexlify(init['B'])) + auth = api.put('sessions/' + self.username, + data={'client_auth': binascii.hexlify(M)}) + return auth + + def verify_server(self, auth): + self.srp_user.verify_session(safe_unhexlify(auth["M2"])) + + def is_authenticated(self): + return self.srp_user.authenticated() + diff --git a/test/nagios/webapp_login.py b/test/nagios/webapp_login.py index 171123892abc159b251f5562adfe4a53b6de825a..77413257b68a8f3b92a281012ed2a93e658c882b 100755 --- a/test/nagios/webapp_login.py +++ b/test/nagios/webapp_login.py @@ -2,85 +2,17 @@ # Test Authentication with the webapp API works. -import requests -import json -import string -import random -import srp._pysrp as srp -import binascii -import yaml +from support.api import Api +from support.config import Config +from support.user import User - -safe_unhexlify = lambda x: binascii.unhexlify(x) if ( - len(x) % 2 == 0) else binascii.unhexlify('0' + x) - - -def read_config(): - with open("/etc/leap/hiera.yaml", 'r') as stream: - config = yaml.load(stream) - user = config['webapp']['nagios_test_user'] - if 'username' not in user: - fail('nagios test user lacks username') - if 'password' not in user: - fail('nagios test user lacks password') - api = config['api'] - api['version'] = config['webapp']['api_version'] - return {'api': api, 'user': user} - - -def run_tests(config): - user = config['user'] - api = config['api'] - usr = srp.User(user['username'], user['password'], srp.SHA256, srp.NG_1024) - try: - auth = parse(authenticate(api, usr)) - except requests.exceptions.ConnectionError: - fail('no connection to server') - exit(report(auth, usr)) - -# parse the server responses - - -def parse(response): - request = response.request - try: - return json.loads(response.text) - except ValueError: - return None - - -def authenticate(api, usr): - api_url = "https://{domain}:{port}/{version}".format(**api) - session = requests.session() - uname, A = usr.start_authentication() - params = { - 'login': uname, - 'A': binascii.hexlify(A) - } - init = parse( - session.post(api_url + '/sessions', data=params, verify=False)) - if ('errors' in init): - fail('test user not found') - M = usr.process_challenge( - safe_unhexlify(init['salt']), safe_unhexlify(init['B'])) - return session.put(api_url + '/sessions/' + uname, verify=False, - data={'client_auth': binascii.hexlify(M)}) - - -def report(auth, usr): - if ('errors' in auth): - fail('srp password auth failed') - usr.verify_session(safe_unhexlify(auth["M2"])) - if usr.authenticated(): - print '0 webapp_login - OK - can login to webapp fine' - return 0 - print '1 webapp_login - WARNING - failed to verify webapp server' - return 1 - - -def fail(reason): - print '2 webapp_login - CRITICAL - ' + reason - exit(2) +def login_successfully(): + config = Config() + user = User(config) + api = Api(config, verify=False) + user.login(api) if __name__ == '__main__': - run_tests(read_config()) + from support import nagios_test + exit_code = nagios_test.run(login_successfully) + exit(exit_code) diff --git a/test/nagios/webapp_signup.py b/test/nagios/webapp_signup.py new file mode 100755 index 0000000000000000000000000000000000000000..3e7283e5a3bc60751310659fb098127615cbf193 --- /dev/null +++ b/test/nagios/webapp_signup.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python + +# Test Signup and Login with the webapp API works. + +from support.api import Api +from support.config import Config +from support.user import User + +def signup_successfully(): + config = Config() + user = User() + api = Api(config, verify=False) + user.signup(api) + user.login(api) + +if __name__ == '__main__': + from support import nagios_test + exit_code = nagios_test.run(signup_successfully) + exit(exit_code) diff --git a/test/support/assert_responses.rb b/test/support/assert_responses.rb new file mode 100644 index 0000000000000000000000000000000000000000..b01166f139ac8d5dd86ade40725a35da50650331 --- /dev/null +++ b/test/support/assert_responses.rb @@ -0,0 +1,46 @@ +module AssertResponses + + # response that works with different TestCases: + # ActionController::TestCase has @response + # ActionDispatch::IntegrationTest has @response + # Rack::Test::Methods defines last_response + def get_response + @response || last_response + end + + def assert_attachement_filename(name) + assert_equal %Q(attachment; filename="#{name}"), + get_response.headers["Content-Disposition"] + end + + def json_response + response = JSON.parse(get_response.body) + response.respond_to?(:with_indifferent_access) ? + response.with_indifferent_access : + response + end + + def assert_json_response(object) + assert_equal 'application/json', + get_response.content_type.to_s.split(';').first + if object.is_a? Hash + object.stringify_keys! if object.respond_to? :stringify_keys! + assert_equal object, json_response + else + assert_equal object.to_json, get_response.body + end + end + + def assert_json_error(object) + object.stringify_keys! if object.respond_to? :stringify_keys! + assert_json_response :errors => object + end +end + +class ::ActionController::TestCase + include AssertResponses +end + +class ::ActionDispatch::IntegrationTest + include AssertResponses +end diff --git a/users/test/support/auth_test_helper.rb b/test/support/auth_test_helper.rb similarity index 100% rename from users/test/support/auth_test_helper.rb rename to test/support/auth_test_helper.rb diff --git a/test/support/browser_integration_test.rb b/test/support/browser_integration_test.rb new file mode 100644 index 0000000000000000000000000000000000000000..1c872ff1056710c5d30a5bdd0f3bcdbd9ffe2276 --- /dev/null +++ b/test/support/browser_integration_test.rb @@ -0,0 +1,98 @@ +# +# BrowserIntegrationTest +# +# Use this class for capybara based integration tests for the ui. +# + +class BrowserIntegrationTest < ActionDispatch::IntegrationTest + + CONFIG_RU = (Rails.root + 'config.ru').to_s + OUTER_APP = Rack::Builder.parse_file(CONFIG_RU).first + + require 'capybara/poltergeist' + + Capybara.register_driver :rack_test do |app| + Capybara::RackTest::Driver.new(app) + end + + Capybara.register_driver :poltergeist do |app| + Capybara::Poltergeist::Driver.new(app) + end + + # this is integration testing. So let's make the whole + # rack stack available... + Capybara.app = OUTER_APP + Capybara.run_server = true + Capybara.app_host = 'http://lvh.me:3003' + Capybara.server_port = 3003 + Capybara.javascript_driver = :poltergeist + Capybara.default_wait_time = 5 + + + # Make the Capybara DSL available + include Capybara::DSL + + setup do + Capybara.current_driver = Capybara.javascript_driver + page.driver.add_headers 'ACCEPT-LANGUAGE' => 'en-EN' + end + + teardown do + Capybara.reset_sessions! # Forget the (simulated) browser state + Capybara.use_default_driver # Revert Capybara.current_driver to Capybara.default_driver + end + + 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 + + # currently this only works for tests with poltergeist. + def login(user = nil) + @user ||= user ||= FactoryGirl.create(:user) + token = Token.create user_id: user.id + page.driver.add_header "Authorization", %Q(Token token="#{token}") + visit '/' + end + + teardown do + if @user && @user.reload + Identity.destroy_all_for @user + @user.destroy + end + end + + add_teardown_hook do |testcase| + unless testcase.passed? + testcase.save_state + end + end + + def save_state + File.open(logfile_path, 'w') do |test_log| + test_log.puts self.class.name + test_log.puts "=========================" + test_log.puts __name__ + test_log.puts Time.now + test_log.puts current_path + test_log.puts page.status_code + test_log.puts page.response_headers + test_log.puts "page.html" + test_log.puts "------------------------" + test_log.puts page.html + test_log.puts "server log" + test_log.puts "------------------------" + test_log.puts `tail log/test.log -n 200` + end + page.save_screenshot screenshot_path + # some drivers do not support screenshots + rescue Capybara::NotSupportedByDriverError + end + +end diff --git a/test/support/rack_test.rb b/test/support/rack_test.rb new file mode 100644 index 0000000000000000000000000000000000000000..806339ac9983bd34e8d050defed3fef02b41d7e8 --- /dev/null +++ b/test/support/rack_test.rb @@ -0,0 +1,38 @@ +require_relative 'assert_responses' + +class RackTest < ActiveSupport::TestCase + include Rack::Test::Methods + include Warden::Test::Helpers + + CONFIG_RU = (Rails.root + 'config.ru').to_s + OUTER_APP = Rack::Builder.parse_file(CONFIG_RU).first + + def app + OUTER_APP + end + + def assert_access_denied + assert_json_response('error' => I18n.t(:not_authorized)) + assert_response :unprocessable_entity + end + + # inspired by rails 4 + # -> actionpack/lib/action_dispatch/testing/assertions/response.rb + def assert_response(type, message = nil) + # RackTest does not know @response + response_code = last_response.status + message ||= "Expected response to be a <#{type}>, but was <#{response_code}>" + + if Symbol === type + if [:success, :missing, :redirect, :error].include?(type) + assert last_response.send("#{type}?"), message + else + code = Rack::Utils::SYMBOL_TO_STATUS_CODE[type] + assert_equal code, response_code, message + end + else + assert_equal type, response_code, message + end + end + +end diff --git a/users/test/support/stub_record_helper.rb b/test/support/stub_record_helper.rb similarity index 100% rename from users/test/support/stub_record_helper.rb rename to test/support/stub_record_helper.rb diff --git a/users/test/support/time_test_helper.rb b/test/support/time_test_helper.rb similarity index 100% rename from users/test/support/time_test_helper.rb rename to test/support/time_test_helper.rb diff --git a/core/test/support/with_config_helper.rb b/test/support/with_config_helper.rb similarity index 100% rename from core/test/support/with_config_helper.rb rename to test/support/with_config_helper.rb diff --git a/test/test_helper.rb b/test/test_helper.rb index 3fb271618f38b07d3ee6d17210c1d8d2f729a076..d001ac7eeaed9126fd9debecac5c260e2414b848 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -4,80 +4,15 @@ require 'rails/test_help' require 'mocha/setup' +# Load support files from toplevel +Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f } + # Load support files from all engines -Dir["#{File.dirname(__FILE__)}/../*/test/support/**/*.rb"].each { |f| require f } +Dir["#{File.dirname(__FILE__)}/../engines/*/test/support/**/*.rb"].each { |f| require f } class ActiveSupport::TestCase # Add more helper methods to be used by all tests here... - def file_path(name) - File.join(Rails.root, 'test', 'files', name) - end - -end - -require 'capybara/poltergeist' - -CONFIG_RU = (Rails.root + 'config.ru').to_s -OUTER_APP = Rack::Builder.parse_file(CONFIG_RU).first - -Capybara.register_driver :rack_test do |app| - Capybara::RackTest::Driver.new(app) -end - -Capybara.register_driver :poltergeist do |app| - Capybara::Poltergeist::Driver.new(app) -end - -# this is integration testing. So let's make the whole -# rack stack available... -Capybara.app = OUTER_APP -Capybara.run_server = true -Capybara.app_host = 'http://lvh.me:3003' -Capybara.server_port = 3003 -Capybara.javascript_driver = :poltergeist -Capybara.default_wait_time = 5 - -class BrowserIntegrationTest < ActionDispatch::IntegrationTest - # Make the Capybara DSL available - include Capybara::DSL - include IntegrationTestHelper - - setup do - Capybara.current_driver = Capybara.javascript_driver - page.driver.add_headers 'ACCEPT-LANGUAGE' => 'en-EN' - end - - teardown do - Capybara.reset_sessions! # Forget the (simulated) browser state - Capybara.use_default_driver # Revert Capybara.current_driver to Capybara.default_driver - end - - add_teardown_hook do |testcase| - unless testcase.passed? - testcase.save_state - end - end - - def save_state - page.save_screenshot screenshot_path - File.open(logfile_path, 'w') do |test_log| - test_log.puts self.class.name - test_log.puts "=========================" - test_log.puts __name__ - test_log.puts Time.now - test_log.puts current_path - test_log.puts page.status_code - test_log.puts page.response_headers - test_log.puts "page.html" - test_log.puts "------------------------" - test_log.puts page.html - test_log.puts "server log" - test_log.puts "------------------------" - test_log.puts `tail log/test.log -n 200` - end - end - protected def logfile_path @@ -87,4 +22,9 @@ class BrowserIntegrationTest < ActionDispatch::IntegrationTest def screenshot_path Rails.root + 'tmp' + "#{self.class.name.underscore}.#{__name__}.png" end + + def file_path(name) + File.join(Rails.root, 'test', 'files', name) + end + end diff --git a/users/test/unit/account_test.rb b/test/unit/account_test.rb similarity index 95% rename from users/test/unit/account_test.rb rename to test/unit/account_test.rb index 4fb3c3dce4d6dfaf2d340babff01ab5335fa0109..b2bfe27319fe168442fa1bc52cce3a5f4384d5b8 100644 --- a/users/test/unit/account_test.rb +++ b/test/unit/account_test.rb @@ -8,7 +8,7 @@ class AccountTest < ActiveSupport::TestCase test "create a new account" do user = Account.create(FactoryGirl.attributes_for(:user)) - assert user.valid? + assert user.valid?, "unexpected errors: #{user.errors.inspect}" assert user.persisted? assert id = user.identity assert_equal user.email_address, id.address diff --git a/test/unit/anonymous_user_test.rb b/test/unit/anonymous_user_test.rb new file mode 100644 index 0000000000000000000000000000000000000000..6e94d39f2523363e048744d79a3ec66a02fc8160 --- /dev/null +++ b/test/unit/anonymous_user_test.rb @@ -0,0 +1,23 @@ +require 'test_helper' + +class AnonymousUserTest < ActiveSupport::TestCase + + setup do + @anonymous = AnonymousUser.new + end + + test "has nil values" do + assert_nil @anonymous.id + assert_nil @anonymous.email_address + assert_nil @anonymous.login + end + + test "has no messages" do + assert_equal [], @anonymous.messages + end + + test "has anonymous service level" do + assert @anonymous.effective_service_level.is_a? AnonymousServiceLevel + end + +end diff --git a/certs/test/unit/client_certificate_test.rb b/test/unit/client_certificate_test.rb similarity index 100% rename from certs/test/unit/client_certificate_test.rb rename to test/unit/client_certificate_test.rb diff --git a/users/test/unit/helpers/session_helper_test.rb b/test/unit/helpers/session_helper_test.rb similarity index 100% rename from users/test/unit/helpers/session_helper_test.rb rename to test/unit/helpers/session_helper_test.rb diff --git a/users/test/unit/helpers/users_helper_test.rb b/test/unit/helpers/users_helper_test.rb similarity index 100% rename from users/test/unit/helpers/users_helper_test.rb rename to test/unit/helpers/users_helper_test.rb diff --git a/users/test/unit/identity_test.rb b/test/unit/identity_test.rb similarity index 100% rename from users/test/unit/identity_test.rb rename to test/unit/identity_test.rb diff --git a/users/test/unit/local_email_test.rb b/test/unit/local_email_test.rb similarity index 100% rename from users/test/unit/local_email_test.rb rename to test/unit/local_email_test.rb diff --git a/users/test/unit/token_test.rb b/test/unit/token_test.rb similarity index 89% rename from users/test/unit/token_test.rb rename to test/unit/token_test.rb index 6c9f2096644a85d7978031ea328d8b6090c36449..a3c6cf65b492f5c3b577fe8b9ed2304950534c1c 100644 --- a/users/test/unit/token_test.rb +++ b/test/unit/token_test.rb @@ -78,6 +78,12 @@ class ClientCertificateTest < ActiveSupport::TestCase end - + test "Token.destroy_all_expired does not interfere with expired.authenticate" do + expired = FactoryGirl.create :token, last_seen_at: 2.hours.ago + with_config auth: {token_expires_after: 60} do + Token.destroy_all_expired + end + assert_nil expired.authenticate + end end diff --git a/users/test/unit/user_test.rb b/test/unit/user_test.rb similarity index 100% rename from users/test/unit/user_test.rb rename to test/unit/user_test.rb diff --git a/users/test/unit/warden_strategy_secure_remote_password_test.rb b/test/unit/warden_strategy_secure_remote_password_test.rb similarity index 100% rename from users/test/unit/warden_strategy_secure_remote_password_test.rb rename to test/unit/warden_strategy_secure_remote_password_test.rb diff --git a/users/test/unit/webfinger/host_meta_presenter_test.rb b/test/unit/webfinger/host_meta_presenter_test.rb similarity index 100% rename from users/test/unit/webfinger/host_meta_presenter_test.rb rename to test/unit/webfinger/host_meta_presenter_test.rb diff --git a/users/test/unit/webfinger/user_presenter_test.rb b/test/unit/webfinger/user_presenter_test.rb similarity index 100% rename from users/test/unit/webfinger/user_presenter_test.rb rename to test/unit/webfinger/user_presenter_test.rb diff --git a/ui_dependencies.rb b/ui_dependencies.rb deleted file mode 100644 index 4b5d70627ab9fd47aa30918573541d1a723c5cdb..0000000000000000000000000000000000000000 --- a/ui_dependencies.rb +++ /dev/null @@ -1,28 +0,0 @@ -gem "haml", "~> 3.1.7" -gem "bootstrap-sass", "= 2.3.2.2" -gem "jquery-rails" -gem "simple_form" -gem 'client_side_validations' -gem 'client_side_validations-simple_form' -gem "bootswatch-rails", "~> 0.5.0" - -gem 'kaminari', "0.13.0" # for pagination. trying 0.13.0 as there seem to be - # issues with 0.14.0 when using couchrest - -gem 'rails-i18n' # locale files for built-in validation messages and times - # https://github.com/svenfuchs/rails-i18n - # for a list of keys: - # https://github.com/svenfuchs/rails-i18n/blob/master/rails/locale/en.yml - -gem 'rdiscount' # for rendering .md templates - -group :assets do - gem "haml-rails", "~> 0.3.4" - gem "sass-rails", "~> 3.2.5" - gem "coffee-rails", "~> 3.2.2" - gem "uglifier", "~> 1.2.7" - - # See https://github.com/sstephenson/execjs#readme for more supported runtimes - gem 'therubyracer', "~> 0.10.2", :platforms => :ruby - -end diff --git a/users/Gemfile b/users/Gemfile deleted file mode 100644 index 4101ead2e8484c366485da8421e3bfdd064bb164..0000000000000000000000000000000000000000 --- 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 38da5fcc853df78540a5f92b06aeece4cc574f18..0000000000000000000000000000000000000000 --- 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 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 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 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 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 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/users/app/controllers/.gitkeep b/users/app/controllers/.gitkeep deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 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 530294a4217cc46802f67ef21232946ebaf414c3..0000000000000000000000000000000000000000 --- 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/helpers/.gitkeep b/users/app/helpers/.gitkeep deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/users/app/mailers/.gitkeep b/users/app/mailers/.gitkeep deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/users/app/models/.gitkeep b/users/app/models/.gitkeep deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/users/app/models/service_level.rb b/users/app/models/service_level.rb deleted file mode 100644 index 299aaf1e6e89d92c84be4e62d1b2870e57b9ea2c..0000000000000000000000000000000000000000 --- 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/unauthenticated_user.rb b/users/app/models/unauthenticated_user.rb deleted file mode 100644 index 0fc17d24cabae717b97597276e29fe43258a20fe..0000000000000000000000000000000000000000 --- 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/views/.gitkeep b/users/app/views/.gitkeep deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/users/app/views/sessions/new.html.haml b/users/app/views/sessions/new.html.haml deleted file mode 100644 index 771dc974ea17dce0310269a7c7ab50b231f1791b..0000000000000000000000000000000000000000 --- 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/config/routes.rb b/users/config/routes.rb deleted file mode 100644 index 736b28323093665f8222dcb60209f4e2d87263b9..0000000000000000000000000000000000000000 --- 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 7d1f220abf1e4e39721f14e243c83ec0ce3baad2..0000000000000000000000000000000000000000 --- 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 e1b7b1f8fcd710fbd3b728c5d26180f827636631..0000000000000000000000000000000000000000 --- 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 f8ed71cf56ee0d8e69b4950530a35b0beb47e11a..0000000000000000000000000000000000000000 --- 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 3d0649c7985a2cbe807bfe1de8b74b9b836f01da..0000000000000000000000000000000000000000 --- 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/script/rails b/users/script/rails deleted file mode 100755 index ee08520d0c91eacdd63a9b49bec4da6ccdb2e583..0000000000000000000000000000000000000000 --- 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 ae00d43020d922f31b645049b9790822c837786e..0000000000000000000000000000000000000000 --- 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 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/users/test/functional/.gitkeep b/users/test/functional/.gitkeep deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/users/test/integration/.gitkeep b/users/test/integration/.gitkeep deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 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 edd08597a8108f8252758e267fb136842ea98ffd..0000000000000000000000000000000000000000 --- 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 fb761e5e96325643fa331e3d21fda05437047390..0000000000000000000000000000000000000000 --- 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/rack_test.rb b/users/test/integration/api/rack_test.rb deleted file mode 100644 index 9a69f524ab839ee1784ee569d7f7cbc82c65ed78..0000000000000000000000000000000000000000 --- 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/session_test.rb b/users/test/integration/browser/session_test.rb deleted file mode 100644 index 3a41b3a349dd07170eaa1bac2962847c5aec3615..0000000000000000000000000000000000000000 --- 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 eec8c0efdd1ea802fc26146fe84b6bfdd964ed19..0000000000000000000000000000000000000000 --- 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/support/integration_test_helper.rb b/users/test/support/integration_test_helper.rb deleted file mode 100644 index 51e47c66f8fd18e5ba44f01ecb712b0cb7dbaad3..0000000000000000000000000000000000000000 --- 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/test_helper.rb b/users/test/test_helper.rb deleted file mode 100644 index 52dff539993c5c455c4acdc7c3c49cdb8720b641..0000000000000000000000000000000000000000 --- 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 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/users/test/unit/email_test.rb b/users/test/unit/email_test.rb deleted file mode 100644 index 7cfbc846dbeb3128040280933cc5bab9db7ab036..0000000000000000000000000000000000000000 --- 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/unauthorized_user_test.rb b/users/test/unit/unauthorized_user_test.rb deleted file mode 100644 index 5b96ae100127a02c577e7c8fbd08c5a1531f58eb..0000000000000000000000000000000000000000 --- 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