diff options
25 files changed, 309 insertions, 47 deletions
@@ -24,7 +24,6 @@ group :test do gem 'capybara', require: false gem 'launchy' # so save_and_open_page works in integration tests gem 'phantomjs-binaries' - gem 'minitest' gem 'minitest-stub-const' end diff --git a/Gemfile.lock b/Gemfile.lock index 09d3123..e8a9831 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -76,7 +76,8 @@ GEM multi_json (~> 1.0) addressable (2.3.5) arel (3.0.3) - bootstrap-sass (2.1.1.0) + bootstrap-sass (2.3.2.2) + sass (~> 3.2) bootswatch-rails (0.5.0) railties (>= 3.1) braintree (2.27.1) @@ -166,7 +167,6 @@ GEM metaclass (0.0.1) mime-types (1.25.1) mini_portile (0.5.2) - minitest (4.7.5) minitest-stub-const (0.1) mocha (0.13.3) metaclass (~> 0.0.1) @@ -213,6 +213,7 @@ GEM rdoc (~> 3.4) thor (>= 0.14.6, < 2.0) rake (10.1.1) + rdiscount (2.0.7) rdoc (3.12.2) json (~> 1.4) rest-client (1.6.7) @@ -263,7 +264,7 @@ PLATFORMS DEPENDENCIES SyslogLogger (~> 2.0) - bootstrap-sass (~> 2.1.0) + bootstrap-sass (= 2.3.2.2) bootswatch-rails (~> 0.5.0) capybara certificate_authority! @@ -285,13 +286,13 @@ DEPENDENCIES leap_web_core! leap_web_help! leap_web_users! - minitest minitest-stub-const mocha (~> 0.13.0) phantomjs-binaries poltergeist quiet_assets rails-i18n + rdiscount sass-rails (~> 3.2.5) simple_form therubyracer (~> 0.10.2) diff --git a/app/assets/stylesheets/leap.scss b/app/assets/stylesheets/leap.scss index 02b6241..120b978 100644 --- a/app/assets/stylesheets/leap.scss +++ b/app/assets/stylesheets/leap.scss @@ -4,7 +4,8 @@ // This is a trick to be able to use bootstrap fluid layout and also have a max-width. // It is like having your cake and eating it too. -#main { +// not needed in bootstrap 3 +#main, #masthead-text { *zoom: 1; margin-left: auto; margin-right: auto; @@ -212,6 +213,9 @@ input, textarea { .sitename { font-weight: bold; } + a { + color: $textColor; + } } .home-buttons { @@ -265,3 +269,55 @@ input, textarea { .overview li { padding: 6px 0; } + +// +// STICKY FOOTER for BOOSTRAP 2 +// http://getbootstrap.com/2.3.2/examples/sticky-footer.html +// when upgrading to bootstrap 3, use this instead: +// http://getbootstrap.com/examples/sticky-footer/ +// + +$footer-height: 60px; +$footer-border-width: 1px; +$footer-gutter: 20px; // vertical gap above footer +$footer-combined: $footer-height + $footer-border-width + $footer-gutter; +$footer-color: $grayLighter !default; + +html, body { + height: 100%; + padding: 0; + margin: 0; +} + +#wrap { + min-height: 100%; + height: auto !important; + height: 100%; + margin: 0 auto -1 * ($footer-height + $footer-border-width + $footer-gutter); +} + +#push { + height: $footer-height + $footer-gutter - $footer-border-width; +} + +#footer { + padding-top: $footer-gutter; + height: $footer-height - $footer-border-width; + .full-height { + text-align: center; + line-height: $footer-height - $footer-border-width; + border-top: $footer-border-width solid darken($footer-color, 10%); + background-color: $footer-color; + a { + color: $black; + margin: 0 5px; + } + } +} + + @media (max-width: 767px) { + #footer a { + font-size: 80%; + margin: 0 2px; + } +} diff --git a/app/controllers/pages_controller.rb b/app/controllers/pages_controller.rb new file mode 100644 index 0000000..c477b7c --- /dev/null +++ b/app/controllers/pages_controller.rb @@ -0,0 +1,18 @@ +# +# Render static pages +# + +class PagesController < ApplicationController + + def show + @show_navigation = false + render page_name + end + + private + + def page_name + request.path.sub(/^\/(#{MATCH_LOCALE}\/)?/, '') + end + +end diff --git a/app/views/home/_content.html.haml b/app/views/home/_content.html.haml new file mode 100644 index 0000000..3d351e9 --- /dev/null +++ b/app/views/home/_content.html.haml @@ -0,0 +1,14 @@ +.row-fluid + %h1= t(:welcome, :provider => APP_CONFIG[:domain]) + %p We provide secure communication services, including encrypted internet, email (coming soon), and chat (coming later). + +.row-fluid + = home_page_buttons + + - 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/app/views/home/_masthead.html.haml b/app/views/home/_masthead.html.haml new file mode 100644 index 0000000..6759339 --- /dev/null +++ b/app/views/home/_masthead.html.haml @@ -0,0 +1,4 @@ +-# An example masthead: +-# +-# #masthead +-# %h1 Example
\ No newline at end of file diff --git a/app/views/home/index.html.haml b/app/views/home/index.html.haml index 67b2c06..147cacd 100644 --- a/app/views/home/index.html.haml +++ b/app/views/home/index.html.haml @@ -1,21 +1,9 @@ -#main - .container-fluid - .row-fluid - %h1= t(:welcome, :provider => APP_CONFIG[:domain]) - - %p - We provide secure communication services, including encrypted internet, email (coming soon), and chat (coming later). - - .row-fluid - .span6.offset3 - = render 'layouts/messages' - .row-fluid - = home_page_buttons - - - 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? +#wrap + = render 'home/masthead' + #main + .container-fluid + = render 'home/content' + #push + -# #push is used for sticky footer in bootstrap 2. remove when upgrading to bootstrap 3 +#footer + = render 'layouts/footer'
\ No newline at end of file diff --git a/app/views/layouts/_footer.html.haml b/app/views/layouts/_footer.html.haml index e69de29..5909bdd 100644 --- a/app/views/layouts/_footer.html.haml +++ b/app/views/layouts/_footer.html.haml @@ -0,0 +1,10 @@ +.full-height + = link_to icon('home') + t(:home), home_path + = link_to icon('eye-close') + t(:privacy_policy), privacy_policy_path + = link_to icon('file') + t(:terms_of_service), terms_of_service_path + - if lookup_context.exists?('pages/about') + = 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 diff --git a/app/views/layouts/_masthead.html.haml b/app/views/layouts/_masthead.html.haml index 280f2c2..35225a1 100644 --- a/app/views/layouts/_masthead.html.haml +++ b/app/views/layouts/_masthead.html.haml @@ -1,4 +1,6 @@ -.title - %span.sitename - = APP_CONFIG[:domain] - = t(:user_control_panel)
\ No newline at end of file +#masthead + .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 816b558..1cd4ec3 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -10,15 +10,17 @@ = csrf_meta_tags = yield(:head) %body - #masthead + #wrap = render 'layouts/masthead' - #main - .container-fluid - - if logged_in? + #main + .container-fluid + - if logged_in? + .row-fluid + .span12 + = render 'layouts/header' .row-fluid - .span12 - = render 'layouts/header' - .row-fluid - = render 'layouts/content' + = render 'layouts/content' + #push + -# #push is used for sticky footer in bootstrap 2. remove when upgrading to bootstrap 3 #footer = render 'layouts/footer' diff --git a/app/views/layouts/home.html.haml b/app/views/layouts/home.html.haml index e6fa15d..8451de5 100644 --- a/app/views/layouts/home.html.haml +++ b/app/views/layouts/home.html.haml @@ -8,5 +8,5 @@ = javascript_include_tag "application" = csrf_meta_tags = yield(:head) - %body + %body.home = yield
\ No newline at end of file diff --git a/app/views/pages/bye.html.haml b/app/views/pages/bye.html.haml new file mode 100644 index 0000000..30b52e0 --- /dev/null +++ b/app/views/pages/bye.html.haml @@ -0,0 +1,6 @@ +%br/ +.hero-unit + %h2= t :bye + = t :bye_message + += render 'common/home_page_buttons'
\ No newline at end of file diff --git a/app/views/pages/pricing.html.haml b/app/views/pages/pricing.html.haml new file mode 100644 index 0000000..77699d8 --- /dev/null +++ b/app/views/pages/pricing.html.haml @@ -0,0 +1,21 @@ +%h1= t(:pricing) +%p= link_to(icon('user') + t(:signup), signup_path, :class => 'btn') + +- levels = APP_CONFIG[:service_levels] +- if levels + %table.table.table-striped.table-bordered + %tr + %th= t :plan + %th= t :description + %th= t :monthly_cost + - levels.each do |id, level| + %tr + %td= level[:name] + %td= level[:description] + %td + - if level[:cost].nil? || level[:cost] == 0 + = t(:free) + - else + = level[:cost].map{|currency,cost| "#{cost} #{currency}"}.join(', ') +- else + No service levels are configured.
\ No newline at end of file diff --git a/app/views/pages/privacy-policy.en.md b/app/views/pages/privacy-policy.en.md new file mode 100644 index 0000000..857bcd6 --- /dev/null +++ b/app/views/pages/privacy-policy.en.md @@ -0,0 +1,55 @@ +# Privacy Policy + +This document is our Privacy Policy, which describes what information we collect and what it's used for. It applies to all interactions with **<%=APP_CONFIG[:domain]%>**. Your use of **<%=APP_CONFIG[:domain]%>** services will constitute your agreement to this Privacy Policy. Please also review our [Terms of Service](terms-of-service). + +<p class="alert alert-info"> + <b>Summary:</b> We collect very little personal information, and none of the information we do collect is ever shared or disclosed to anyone. +</p> + +## Information we collect and retain + +**Registration information:** When you create an account, we retain the date and time you registered, along with your username and email aliases or forwarding addresses. + +**Customer code:** If you sign up for recurring payments, we retain a unique customer code. Although it may appear that you enter your billing information at <%=APP_CONFIG[:domain]%>, this information is sent directly to a separate payment processing company and is not seen or retained by us. However, the customer code that we do retain for recurring payments can be used to lookup billing information held by the payment processor. + +**Public key:** In order for secure communication to work, your device generates a private key and public key. The public key is pushed to our services and published publicly. + +**Help tickets:** The content of any help ticket you create or comment on while authenticated will be associated with your user account. You can choose to fill out a help ticket anonymously by creating a ticket while not logged in. We periodically delete old help tickets that are closed. + +**Session identifiers:** While currently logged in, either via the client application or the web application, we keep a temporary session identifier on your computer that your software uses to proves your authentication state. In the web browser, this consists of a session "cookie". In the client, this consists of a similar session token. In both cases, these are erased immediately after the user logs out or the session expires. We do not use any third party cookies or tracking of any kind. + +**Email transit logs:** In order to detect when our servers are under attack from a "spam bomb" or when a spammer is using our system, we keep a log of the "from" or "to" information for every message relayed. These logs are quickly purged on a daily basis. + +**Month of last log in**: We keep a record of the current calendar month and year of your last successful authentication (in order to be able to disable dormant accounts). We do not record the time or day of the last log in. + +## Information we choose to not retain + +**IP addresses**: No IP addresses of any user for any service are retained. The IP addresses are removed from all log files and replaced with all zeros before the logs are written to disk. This is important, because a user's IP address can disclose both their real identity and physical location. + +**Browser fingerprint**: Your web browser communicates uniquely identifying information to all web servers it visits by allowing the site to know details about your operating system, browser information, plugins installed, fonts installed, screen resolution, and much more. We do not retain any of this information. + +**Credentials for encrypted internet service**: If you use the encrypted internet service, your client presents our servers with a certificate to confirm you are a valid user before a connection is established. These certificates regularly expire, and the user must log in every month or two in order to obtain a new certificate. However, we do not keep a record of which user account is associated with which authentication certificate. + +**Message metadata**: Even when using end-to-end OpenPGP encryption for email messages, the email "subject" and routing information regarding the message "from" and "to" are seen by our servers in the clear when the message initially arrives. Immediately upon reception, we encrypt the entire message, including the metadata, and store it so that only you can read anything about the message (other than the size of the encrypted blob). + +**Cleartext messages**: Some messages that you send or receive will not be end-to-end encrypted (for example, when the other party does not support email encryption). In these cases, both when the message is received and sent, we do not retain anything about these messages other than what has been specified above. + +## Information we cannot retain + +**Your password**: Unlike most services, your user password never travels to our servers. We have no access to your password at any time. An attacker might still guess your password or discover it by trying millions of combinations, but we have no special access in this regard. Note: this guarantee is only strong if you use the client application for authentication, but is less strong if you login directly through the website (mostly because browser security is weak and an attacker could modify the computer code in the web page that handles this secure authentication). + +**Your communication**: Once stored, we cannot read the content or metadata of your communication. It is entirely encrypted and decrypted on your device. We also cannot recover it if you lose your password. + +**Your secret keys**: For encryption to work, the client application manages numerous secret keys on your behalf. These keys are also backed up and stored on our servers, but they are saved anonymously, and encrypted so that someone needs to know both the username and password to be have to query and decrypt these keys. + +## How we use or disclose collected information + +**We do not disclose user information**: We retain only the bare minimum of information about each user that is required to make the service work. We do not disclose, sell, or share any of it. + +**Academic research**: Anonymous, aggregated information that cannot be linked back to an individual user may be made available to third parties for the sole purpose of researching better systems for anonymous and privacy communication. For example, we may aggregate information on how many messages a typical user sends and receives, and with what frequency. + +**Account deletion**: You may choose to delete your <%=APP_CONFIG[:domain]%> account at any time. Doing so will destroy all the data we retain that is associated with your account. The one exception is that your public key may still be available, although we will revoke our endorsement of this key. The usernames associated with deleted accounts remain unavailable for others to use for at least two years, possibly longer. + +## Changes to this policy + +We reserve the right to change this policy. If we make major changes, we will notify our users in a clear and prominent manner. Minor changes may only be highlighted in the footer of our website.
\ No newline at end of file diff --git a/app/views/pages/terms-of-service.en.md b/app/views/pages/terms-of-service.en.md new file mode 100644 index 0000000..7b57027 --- /dev/null +++ b/app/views/pages/terms-of-service.en.md @@ -0,0 +1,49 @@ +# Terms of Service + +This document is our Terms of Service, which describes what activities are allowed, under what conditions we may terminate your account, and asserts our limited liability. It applies to all interactions with **<%=APP_CONFIG[:domain]%>**. Your use of **<%=APP_CONFIG[:domain]%>** services will constitute your agreement to these Terms of Service. + +<p class="alert alert-info"> + <b>Summary:</b><br/> + (1) If you do anything truly evil, we will terminate your account.<br/> + (2) We are not liable for any damages related to the use of this service. +</p> + +## Privacy policy + +We ask that you review the terms of our [Privacy Policy](privacy-policy), so that you are aware of how we collect and use your information. + +## Refraining from certain activities + +You may not engage in the following activities through the services provided by **<%= APP_CONFIG[:domain] %>**: + +* **Harassing and abusing others** by engaging in threats, stalking, or sending Spam. +* **Misuse of services** by distributing viruses or malware, engaging in a denial of service attack, or attempting to gain unauthorized access to any computer system, including this one. +* **Contributing to the abuse of others** by distributing material where the production process created violence or sexual assault against persons. + +## Account Termination + +**<%= APP_CONFIG[:domain] %>** may terminate your service at any time for any reason. Typically, however, accounts are destroyed because of one of the following conditions: + +* The account has been found to be sending Spam (excessive amounts of unsolicited email). +* The account is not paid up and the grace period has expired. +* The account has engaged one or more of the banned activities listed above. + +<% if APP_CONFIG[:jurisdiction] %> + +## Disputes and Jurisdiction + +If you seek to file a legal claim against us, you agree to file and resolve it exclusively in <%= APP_CONFIG[:jurisdiction] %>. + +You also agree that the laws of <%= APP_CONFIG[:jurisdiction] %> will govern these Terms of Service, as well as any legal claim that might arise between you and us (without reference to conflict of laws principles). You agree to submit to the personal jurisdiction of, and agree that venue is proper in, the courts located in <%= APP_CONFIG[:jurisdiction] %>, in any legal action or proceeding relating to us or these Terms of Service. + +To ensure that disputes are dealt with soon after they arise, you agree that regardless of any statute or law to the contrary, any claim or cause of action you might have arising out of or related to use of our services or these Terms of Service must be filed within the applicable statute of limitations or, if earlier, one (1) year after the pertinent facts underlying such claim or cause of action could have been discovered with reasonable diligence (or be forever barred). + +<% end %> + +## Limitation on Liability + +**<%= APP_CONFIG[:domain] %>** will not be liable to you or to any other party for any direct, indirect, incidental, special, consequential or exemplary damages, including but not limited to, damages for loss of profits, goodwill, use, data, or other intangible losses, regardless of whether we were advised of the possibility of such damage. In the case that applicable law may not allow the limitation or exclusion of liability or incidental or consequential damages, the above limitation or exclusion may not apply to you, although our liability will be limited to the fullest extent permitted by applicable law. + +## Changes to this policy + +We reserve the right to change this policy. If we make major changes, we will notify our users in a clear and prominent manner. Minor changes may only be highlighted in the footer of our website. diff --git a/billing/config/locales/en.yml b/billing/config/locales/en.yml index b418a17..1300958 100644 --- a/billing/config/locales/en.yml +++ b/billing/config/locales/en.yml @@ -5,3 +5,7 @@ en: save_customer_info: "Save Customer Information" donation_not_payment: "Note: This is a donation, and will not be applied towards your account." no_relevant_subscription: "No subscription which is Active, Pending, or Past Due" + plan: "Plan" + description: "Description" + cost: "Cost" + free: "Free"
\ No newline at end of file diff --git a/config/initializers/markdown_handler.rb b/config/initializers/markdown_handler.rb new file mode 100644 index 0000000..b9e73ba --- /dev/null +++ b/config/initializers/markdown_handler.rb @@ -0,0 +1,19 @@ +# +# This adds support for markdown in views. Just name the template with ".md" +# erb expansion is supported. +# + +require 'rdiscount' + +module MarkdownHandler + def self.erb + @erb ||= ActionView::Template.registered_template_handler(:erb) + end + + def self.call(template) + compiled_source = erb.call(template) + "RDiscount.new(begin;#{compiled_source};end, :generate_toc, :smart, :autolink).to_html" + end +end + +ActionView::Template.register_template_handler :md, MarkdownHandler diff --git a/config/locales/en.yml b/config/locales/en.yml index 63f1c3e..96c47ca 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1 +1,6 @@ en: + privacy_policy: Privacy Policy + terms_of_service: Terms of Service + pricing: Pricing + about: About Us + contact: Contact
\ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index b3e24b9..f8bb8fb 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -6,5 +6,14 @@ LeapWeb::Application.routes.draw do root :to => "home#index" get '(:locale)' => 'home#index', :locale => MATCH_LOCALE, :as => 'home' + scope "(:locale)", :locale => MATCH_LOCALE, :controller => 'pages', :action => 'show' do + get 'privacy-policy', :as => 'privacy_policy' + get 'terms-of-service', :as => 'terms_of_service' + get 'about', :as => 'about' + get 'contact', :as => 'contact' + get 'pricing', :as => 'pricing' + get 'bye', :as => 'bye' + end + get '/provider.json' => 'static_config#provider' end diff --git a/core/lib/leap_web_core/dependencies.rb b/core/lib/leap_web_core/dependencies.rb index e4a8807..877e3d1 100644 --- a/core/lib/leap_web_core/dependencies.rb +++ b/core/lib/leap_web_core/dependencies.rb @@ -9,7 +9,6 @@ module LeapWebCore UI = { "haml" => "~> 3.1.7", - "bootstrap-sass" => "~> 2.0.4", "jquery-rails" => nil, "simple_form" => nil, "bootswatch-rails", "~> 0.5.0" diff --git a/core/lib/leap_web_core/ui_dependencies.rb b/core/lib/leap_web_core/ui_dependencies.rb index c2fc8cf..2daee37 100644 --- a/core/lib/leap_web_core/ui_dependencies.rb +++ b/core/lib/leap_web_core/ui_dependencies.rb @@ -1,5 +1,4 @@ require "haml" -require "bootstrap-sass" require "jquery-rails" require "simple_form" require "bootswatch-rails" diff --git a/ui_dependencies.rb b/ui_dependencies.rb index 2cfd851..4b5d706 100644 --- a/ui_dependencies.rb +++ b/ui_dependencies.rb @@ -1,5 +1,5 @@ gem "haml", "~> 3.1.7" -gem "bootstrap-sass", "~> 2.1.0" +gem "bootstrap-sass", "= 2.3.2.2" gem "jquery-rails" gem "simple_form" gem 'client_side_validations' @@ -14,6 +14,8 @@ gem 'rails-i18n' # locale files for built-in validation messages and times # 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" @@ -24,4 +26,3 @@ group :assets do gem 'therubyracer', "~> 0.10.2", :platforms => :ruby end - diff --git a/users/app/controllers/users_controller.rb b/users/app/controllers/users_controller.rb index a874772..a5461cd 100644 --- a/users/app/controllers/users_controller.rb +++ b/users/app/controllers/users_controller.rb @@ -61,7 +61,7 @@ class UsersController < UsersBaseController else # let's remove the invalid session logout - redirect_to home_url + redirect_to bye_url end end diff --git a/users/config/locales/en.yml b/users/config/locales/en.yml index 0db63eb..ed6653a 100644 --- a/users/config/locales/en.yml +++ b/users/config/locales/en.yml @@ -37,8 +37,9 @@ 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." # # overview diff --git a/users/test/functional/users_controller_test.rb b/users/test/functional/users_controller_test.rb index 002a011..57ae94d 100644 --- a/users/test/functional/users_controller_test.rb +++ b/users/test/functional/users_controller_test.rb @@ -103,7 +103,7 @@ class UsersControllerTest < ActionController::TestCase delete :destroy, :id => @current_user.id assert_response :redirect - assert_redirected_to home_path + assert_redirected_to bye_url end test "non-admin can't destroy user" do |