From ef31958bd6d253d72cb301bb2939979cbab792b0 Mon Sep 17 00:00:00 2001 From: Benjamin ter Kuile Date: Thu, 22 Nov 2012 15:47:28 +0100 Subject: [PATCH] update security handling for user namespace --- app/assets/images/logo.svg | 35 ++- app/assets/images/site/tablet-phone.xcf | Bin 452028 -> 452028 bytes app/assets/javascripts/application.js | 1 - .../javascripts/user/application.js.erb | 16 +- app/assets/javascripts/user/quser.js.coffee | 7 +- .../stylesheets/obtain_token/application.css | 16 + .../stylesheets/obtain_token/darkstrap.sass | 290 ++++++++++++++++++ .../obtain_token/structure.css.sass | 6 + app/controllers/application_controller.rb | 4 +- app/controllers/user_controller.rb | 31 +- app/helpers/devise_helper.rb | 7 + app/views/devise/_links.html.slim | 12 +- app/views/devise/passwords/edit.html.erb | 16 - app/views/devise/passwords/edit.html.slim | 14 + app/views/devise/passwords/new.html.erb | 12 - app/views/devise/passwords/new.html.slim | 10 + app/views/devise/registrations/new.html.slim | 2 +- app/views/layouts/obtain_token.html.slim | 19 ++ app/views/layouts/phone.html.slim | 5 +- config/locales/devise.en.yml | 5 + config/locales/devise.nl.yml | 6 +- .../devise/bootstrap-devise-rails.css.less | 51 +++ vendor/assets/devise/devise.css.sass | 119 +++++++ vendor/assets/devise/devise.js.coffee | 14 + 24 files changed, 634 insertions(+), 64 deletions(-) create mode 100644 app/assets/stylesheets/obtain_token/application.css create mode 100644 app/assets/stylesheets/obtain_token/darkstrap.sass create mode 100644 app/assets/stylesheets/obtain_token/structure.css.sass create mode 100644 app/helpers/devise_helper.rb delete mode 100644 app/views/devise/passwords/edit.html.erb create mode 100644 app/views/devise/passwords/edit.html.slim delete mode 100644 app/views/devise/passwords/new.html.erb create mode 100644 app/views/devise/passwords/new.html.slim create mode 100644 app/views/layouts/obtain_token.html.slim create mode 100644 vendor/assets/devise/bootstrap-devise-rails.css.less create mode 100644 vendor/assets/devise/devise.css.sass create mode 100644 vendor/assets/devise/devise.js.coffee diff --git a/app/assets/images/logo.svg b/app/assets/images/logo.svg index 28a31436..558ff089 100644 --- a/app/assets/images/logo.svg +++ b/app/assets/images/logo.svg @@ -130,9 +130,9 @@ inkscape:window-height="852" id="namedview43" showgrid="false" - inkscape:zoom="1" - inkscape:cx="70.721631" - inkscape:cy="87.591402" + inkscape:zoom="6.34" + inkscape:cx="50" + inkscape:cy="50" inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="0" @@ -148,21 +148,22 @@ style="font-size:9.42450047px;fill:#634227;font-family:HelveticaRounded-Bold" x="25.508852" y="72.998604" - inkscape:export-filename="/Users/bterkuile/companytools/development/rails/qwaiter/app/assets/images/icons/logo-medium.png" - inkscape:export-xdpi="112.82128" - inkscape:export-ydpi="112.82128">Q + WAITE + R + 0*&^q_KdCeOs)3Jt@bRf_N-g&*=nBx0K=FIBLDyZ delta 32 ocmdmUT6)iE=?Qj>e2w<4_KdCeOs)3Jt@bRf_N-g&*=nBx0K;kvApigX diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 4dbf3ebb..1e9c8553 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -16,4 +16,3 @@ //= require twitter/bootstrap //= require_directory . //= require_self - diff --git a/app/assets/javascripts/user/application.js.erb b/app/assets/javascripts/user/application.js.erb index cfab7a9a..c952fa90 100644 --- a/app/assets/javascripts/user/application.js.erb +++ b/app/assets/javascripts/user/application.js.erb @@ -110,6 +110,14 @@ function redirect_to(mapping, variables){ } window.location = QMobile.root_url() + path_mapping[mapping] + '.html?' + vars.join('&') } +function direct_to_site(mapping, variables){ + variables || (variables = {}); + var vars = [] + for(var name in variables){ + vars.push(name + '=' +variables[name]) + } + window.location = data_host + path_mapping[mapping] + '.html?' + vars.join('&') +} function currency(num) { return Qwaiter.currency(num); } @@ -131,9 +139,11 @@ function t(path, vars){ return result; } $.ajaxSetup({ - error: function(xhr, ajaxOptions, error){ - if(xhr.status == 401 || xhr.status == 0){ - window.location = data_host + '/user/obtain_token.html'; + error: function(xhr, ajaxOptions, error, another){ + if(xhr.status == 401){ + direct_to_site('obtain_user_token'); + }else if(xhr.status == 0){ + QMobile.connection_problem(); } } }); diff --git a/app/assets/javascripts/user/quser.js.coffee b/app/assets/javascripts/user/quser.js.coffee index c2abe4b6..83f20d68 100644 --- a/app/assets/javascripts/user/quser.js.coffee +++ b/app/assets/javascripts/user/quser.js.coffee @@ -13,7 +13,9 @@ window.Quser= $.getJSON(data_host + '/user/list_info.json?' + authentication_string, (res) -> Quser.handle_active_list_default_actions(res)) handle_active_list: (callback) -> $.getJSON(data_host + '/user/list_info.json?' + authentication_string, (res) -> - if !res.list_active + if(res.ok == false && res.status && res.status == 401) + direct_to_site('obtain_user_token') + else if !res.list_active redirect_to 'user_root', {list_closed: 'true'} return window.active_list = res @@ -22,6 +24,9 @@ window.Quser= ) handle_active_list_default_actions: (response)-> response ||= {} + if(response.ok == false && response.status && response.status == 401) + direct_to_site('obtain_user_token') + return if response.table_number $('.table-number').text(response.table_number) if response.supplier_name diff --git a/app/assets/stylesheets/obtain_token/application.css b/app/assets/stylesheets/obtain_token/application.css new file mode 100644 index 00000000..470029b0 --- /dev/null +++ b/app/assets/stylesheets/obtain_token/application.css @@ -0,0 +1,16 @@ +/* + * This is a manifest file that'll be compiled into application.css, which will include all the files + * listed below. + * + * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, + * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path. + * + * You're free to add application-wide styles to this file and they'll appear at the top of the + * compiled file, but it's generally better to create a new file per style scope. + * + *= require 'twitter-bootstrap/bootstrap_and_overrides' + *= require 'general' + *= require_directory . + *= require 'devise' + *= require_self + */ diff --git a/app/assets/stylesheets/obtain_token/darkstrap.sass b/app/assets/stylesheets/obtain_token/darkstrap.sass new file mode 100644 index 00000000..1a0ce23d --- /dev/null +++ b/app/assets/stylesheets/obtain_token/darkstrap.sass @@ -0,0 +1,290 @@ +@import compass +@import mixins + +// Contents: +// =General +// =Breadcrumbs +// =Headings +// =Navigation +// =Forms +// =Tables +// =Pagination +// =Misc + +$color: #c6c6c6 +$bg: #2f2f2f +$link: #0088cc + +$warning: #faa732 +$success: #5bb75b +$error: #fc5b5e + +// ds original: #FB292D +$info: #3a87ad + +$input-bg: #666666 + +// ds default: #444 +$input-border: #111111 + +// default: white +$input-placeholder: #666666 +$input-color: white + +//=General ======================================== +// Everything with the inset panel just extends .well +.well + +inset-panel-dark + +body + background: $bg + color: $color + +//=Breadcrumbs ======================================= +.breadcrumb + @extend .well + border: 0 + //over bs + li + text-shadow: 0 1px 0 #000 + //over bs + +//=Headings ====================================== +.page-header + +horizontal-rule-dark + +h1,h2,h3,h4,h5,h6 + color: white + +h6 + color: #999 + +//=Navigation +.nav .dropdown-menu + +.nav-tabs .open .dropdown-toggle, +.nav-pills .open .dropdown-toggle, +.nav > .open.active > a:hover + background-color: darken($bg, 5%) + border-color: $bg $bg transparent $bg + +.nav > .dropdown.active > a:hover + color: #fff + +.nav-tabs .active .dropdown-toggle .caret, +.nav-pills .active .dropdown-toggle .caret + border-top-color: #fff + +.nav-tabs + border-bottom: 1px solid #666 + & > .active > a, + & > .active > a:hover + background-color: $bg + color: #fff + border-color: #666 #666 transparent #666 + & > li > a:hover + border-color: $bg $bg #666666 $bg + background-color: darken($bg, 5%) + color: lighten($link, 10%) + &.nav-stacked + & > li > a, + & > li > a:hover + border-color: #666 + +.nav-pills + & > li > a + &:hover + background-color: darken($bg, 5%) + color: lighten($link, 10%) + &.btn + padding-bottom: 2px + background-color: #e6e6e6 + +.nav-list > li > a, +.nav-list .nav-header + text-shadow: 0 1px 0 #000 + +.nav-list > li > a:hover + background-color: darken($bg, 10%) + color: lighten($link, 10%) + +.nav-list .active + & > a:hover + background-color: #0088cc + color: white + +.tabs-below .nav-tabs + border-top: 1px solid #666 + +.tabs-left .nav-tabs + border-right: 1px solid #666 + +.tabs-right .nav-tabs + border-left: 1px solid #666 + +.tabs-below .nav-tabs > li > a:hover + border-top: 1px solid #666 + +.tabs-left .nav-tabs > li > a:hover + border-color: transparent #666 transparent transparent + +.tabs-right .nav-tabs > li > a:hover + border-color: transparent transparent transparent #666 + +.tabs-below .nav-tabs .active > a, +.tabs-below .nav-tabs .active > a:hover + border-color: transparent #666 #666 #666 + +.tabs-left .nav-tabs .active > a, +.tabs-left .nav-tabs .active > a:hover + border-color: #666 transparent #666 #666 + +.tabs-right .nav-tabs .active > a, +.tabs-right .nav-tabs .active > a:hover + border-color: #666 #666 #666 transparent + +//=Forms ======================================== ++placeholder($input-placeholder) + +.input-prepend .add-on, +.input-append .add-on + background: #444 + color: $color + border-color: #111 + text-shadow: 0 1px 0 black + +label + color: $color + +input, +input[type="file"], +select, +textarea + color: $input-color + //background-color: $input-bg; + border-color: $input-border + @extend .well + +.search-query + -webkit-box-shadow: rgba(255, 255, 255, 0.1) 0 1px 0, rgba(0, 0, 0, 0) 0 1px 7px 0px inset + +legend + color: white + +horizontal-rule-dark + +.form-actions + border-top-color: #222 + background-color: #444 + +.help-inline + color: #999 + +.control-group + &.warning + +controls($warning) + &.success + +controls($success) + &.error + +controls($error) + +//=Tables ======================================== +.table + thead + color: white + td + border-top-color: #666 + +.table-striped + tbody tr:nth-child(2n+1) + td, th + background-color: #444 + +.table-bordered + border: 1px solid #666 + th + th, + td + td, + th + td, + td + th + border-left: 1px solid #666 + +//=Pagination +.pagination a:hover + color: lighten($link, 10%) + background-color: darken($bg, 5%) + +.pagination .active a + color: #fff + background-color: darken($bg, 5%) + +.pagination a + border-color: #666 + +//=Pager +.pager a + background-color: $bg + border-color: #666 + &:hover + background-color: darken($bg, 5%) + color: lighten($link, 10%) + +//=Alerts +=alert($color) + color: #fff + background-color: $color + text-shadow: 0 1px 0 rgba(0, 0, 0, 0.25) + border-color: darken($color, 25%) + h4 + color: darken($color, 20%) + +.alert + +alert($warning) + +.alert-success + +alert($success) + +.alert-error + +alert($error) + +.alert-info + +alert($info) + +//=Modals + +.modal + background-color: #444 + +.modal-header + border-bottom: 1px solid #222 + +.modal-body p + color: $color + +.modal-footer + background-color: darken(#444444, 5%) + border-top: 1px solid #222 + +box-shadow(0 1px 0 #333333 inset) + +//=Progress bars +.progress + @extend .well + +//=Misc ======================================== +blockquote + border-left-color: #111 + &.pull-right + border-right-color: #111 + +hr + +horizontal-rule-dark + border-top: none + +code + @extend .well + border: none + //over bs + +pre + @extend .well + border: none + //over bs + color: $color diff --git a/app/assets/stylesheets/obtain_token/structure.css.sass b/app/assets/stylesheets/obtain_token/structure.css.sass new file mode 100644 index 00000000..92817efa --- /dev/null +++ b/app/assets/stylesheets/obtain_token/structure.css.sass @@ -0,0 +1,6 @@ +@import constants +html + background-image: $wood + background-color: $background-brown +body + background-color: transparent diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 0a772fb5..1fdb70d9 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -3,7 +3,7 @@ class ApplicationController < ActionController::Base layout :layout_by_resource - #protect_from_forgery + protect_from_forgery private @@ -13,7 +13,7 @@ class ApplicationController < ActionController::Base def layout_by_resource if devise_controller? - 'theme1' + session[:user_return_to] =~ /obtain_token/ ? 'obtain_token' : 'theme1' else "application" end diff --git a/app/controllers/user_controller.rb b/app/controllers/user_controller.rb index 7b4e81d2..392ad38f 100644 --- a/app/controllers/user_controller.rb +++ b/app/controllers/user_controller.rb @@ -1,14 +1,30 @@ class UserController < ApplicationController - before_filter :allow_mobile, :authenticate_user! + before_filter :allow_mobile + before_filter :user_authentication #, except: :obtain_token layout 'phone' + def user_authentication + if params[:auth_token].present? + user = User.find_by_authentication_token(params[:auth_token]) + sign_in user if user + sign_out current_user if current_user && !user # Other token attempt of logged in user + else + authenticate_user! + end + unless current_user.present? + respond_to do |format| + format.html {redirect_to new_user_session_path} + format.json {render json: json_response(ok: false, status: 401)} + end + end + end + def authenticate_user_wrapper! authenticate_user! unless request.format.html? authenticate_user! if params[:action] == 'obtain_token' end def obtain_token - end alias :list :active_list @@ -178,14 +194,14 @@ class UserController < ApplicationController if list.present? if !list.try(:active?) current_user.list_is_closed! - render json: {list_active: false} + render json: json_response(list_active: false) return else list_obj = list.as_json.merge(list_active: list.active? ).merge(list.join_requests_as_json) - render json: list_obj + render json: json_response(list_obj) end else - render json: {not_present: true} + render json: json_response(not_present: true) end end end @@ -292,4 +308,9 @@ class UserController < ApplicationController flash.now[:notice] = t('messages.the_list_has_been_closed', list: List.model_name.human) if params[:list_closed].present? flash.now[:notice] = t("messages.#{params[:message]}", list: List.model_name.human, supplier: Supplier.model_name.human) if params[:message].present? && params[:message] =~ /^\w+$/ end + + def json_response(obj = {}) + obj[:ok] = true unless obj.has_key?(:ok) + obj + end end diff --git a/app/helpers/devise_helper.rb b/app/helpers/devise_helper.rb new file mode 100644 index 00000000..17fad922 --- /dev/null +++ b/app/helpers/devise_helper.rb @@ -0,0 +1,7 @@ +module DeviseHelper + def devise_error_messages! + if resource.errors.present? + content_tag(:div, content_tag(:h2, t("errors.messages.not_saved.#{resource.errors.size == 1 ? 'one' : 'other'}", count: resource.errors.size)) +content_tag(:ul, resource.errors.full_messages.map{|m| content_tag(:li, m)}.join.html_safe), class: 'alert alert-error') + end + end +end diff --git a/app/views/devise/_links.html.slim b/app/views/devise/_links.html.slim index 6bbd5bcf..689d28c9 100644 --- a/app/views/devise/_links.html.slim +++ b/app/views/devise/_links.html.slim @@ -1,19 +1,19 @@ ul.nav.nav-pills - if controller_name != 'sessions' - li= link_to t('devise.sessions.button'), new_session_path(resource_name) + li= link_to t('devise.sessions.button'), new_session_path(resource_name), class: [:devise, :btn] - if devise_mapping.registerable? && controller_name != 'registrations' - li= link_to t('devise.registrations.button'), new_registration_path(resource_name) + li= link_to t('devise.registrations.button'), new_registration_path(resource_name), class: [:devise, :btn] - if devise_mapping.recoverable? && controller_name != 'passwords' - li= link_to t('devise.sessions.forgot_your_password'), new_password_path(resource_name) + li= link_to t('devise.sessions.forgot_your_password'), new_password_path(resource_name), class: [:devise, :btn] - if devise_mapping.confirmable? && controller_name != 'confirmations' - li= link_to t('devise.confirmations.did_not_receive_instructions_link'), new_confirmation_path(resource_name) + li= link_to t('devise.confirmations.did_not_receive_instructions_link'), new_confirmation_path(resource_name), class: [:devise, :btn] - if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' - li= link_to t('devise.unlocks.did_not_receive_instructions_link'), new_unlock_path(resource_name) + li= link_to t('devise.unlocks.did_not_receive_instructions_link'), new_unlock_path(resource_name), class: [:devise, :btn] - if devise_mapping.omniauthable? - resource_class.omniauth_providers.each do |provider| - li= link_to t('devise.omniauth_callbacks.sign_in_with', provider: provider.to_s.titleize), omniauth_authorize_path(resource_name, provider) + li= link_to t('devise.omniauth_callbacks.sign_in_with', provider: provider.to_s.titleize), omniauth_authorize_path(resource_name, provider), class: [:devise, :btn] diff --git a/app/views/devise/passwords/edit.html.erb b/app/views/devise/passwords/edit.html.erb deleted file mode 100644 index 5f7bcf87..00000000 --- a/app/views/devise/passwords/edit.html.erb +++ /dev/null @@ -1,16 +0,0 @@ -

Change your password

- -<%= form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :put }) do |f| %> - <%= devise_error_messages! %> - <%= f.hidden_field :reset_password_token %> - -
<%= f.label :password, "New password" %>
- <%= f.password_field :password %>
- -
<%= f.label :password_confirmation, "Confirm new password" %>
- <%= f.password_field :password_confirmation %>
- -
<%= f.submit "Change my password" %>
-<% end %> - -<%= render "links" %> \ No newline at end of file diff --git a/app/views/devise/passwords/edit.html.slim b/app/views/devise/passwords/edit.html.slim new file mode 100644 index 00000000..6a71746c --- /dev/null +++ b/app/views/devise/passwords/edit.html.slim @@ -0,0 +1,14 @@ +h2= t('devise.passwords.edit.title') += form_for(resource, :as => resource_name, :url => password_path(resource_name), html: {class: 'form-horizontal', method: :put}) do |f| + = devise_error_messages! + = f.hidden_field :reset_password_token + .control-group + = f.label :password, class: 'control-label' + .controls= f.password_field :password + .control-group + = f.label :password_confirmation, class: 'control-label' + .controls= f.password_field :password_confirmation + .control-group + .controls + = f.submit t('devise.passwords.edit.button'), class: 'btn btn-primary' += render "links" diff --git a/app/views/devise/passwords/new.html.erb b/app/views/devise/passwords/new.html.erb deleted file mode 100644 index b0b5690f..00000000 --- a/app/views/devise/passwords/new.html.erb +++ /dev/null @@ -1,12 +0,0 @@ -

Forgot your password?

- -<%= form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :post }) do |f| %> - <%= devise_error_messages! %> - -
<%= f.label :email %>
- <%= f.email_field :email %>
- -
<%= f.submit "Send me reset password instructions" %>
-<% end %> - -<%= render "links" %> \ No newline at end of file diff --git a/app/views/devise/passwords/new.html.slim b/app/views/devise/passwords/new.html.slim new file mode 100644 index 00000000..c0304fc9 --- /dev/null +++ b/app/views/devise/passwords/new.html.slim @@ -0,0 +1,10 @@ +h2= t('devise.passwords.title') += form_for(resource, :as => resource_name, :url => password_path(resource_name), html: {class: 'form-horizontal'}) do |f| + = devise_error_messages! + .control-group + = f.label :email, class: 'control-label' + .controls= f.email_field :email + .control-group + .controls + = f.submit t('devise.passwords.button'), class: 'btn btn-primary' += render "links" diff --git a/app/views/devise/registrations/new.html.slim b/app/views/devise/registrations/new.html.slim index df13a99b..35ad441b 100644 --- a/app/views/devise/registrations/new.html.slim +++ b/app/views/devise/registrations/new.html.slim @@ -12,5 +12,5 @@ h2= t('devise.registrations.title') .controls= f.password_field :password_confirmation .control-group .controls - = f.submit t('devise.registrations.button') + = f.submit t('devise.registrations.button'), class: 'btn btn-primary' = render "links" diff --git a/app/views/layouts/obtain_token.html.slim b/app/views/layouts/obtain_token.html.slim new file mode 100644 index 00000000..852c0df3 --- /dev/null +++ b/app/views/layouts/obtain_token.html.slim @@ -0,0 +1,19 @@ +doctype html +html lang="en" + head + meta charset="utf-8" + meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1" + meta name="viewport" content="width=device-width, initial-scale=1.0" + title= content_for?(:title) ? yield(:title) : application_title + = stylesheet_link_tag 'obtain_token/application' + = csrf_meta_tags + body class=action_name + - if flash[:alert].present? + .alert.alert-error + a.close data-dismiss="alert" × + div= flash[:alert] + - if flash[:notice].present? + .alert.alert-success + a.close data-dismiss="alert" × + div= flash[:notice] + #obtain-token-container= yield diff --git a/app/views/layouts/phone.html.slim b/app/views/layouts/phone.html.slim index 0fb71dec..a5fcb484 100644 --- a/app/views/layouts/phone.html.slim +++ b/app/views/layouts/phone.html.slim @@ -19,7 +19,7 @@ html lang="en" javascript: var data_host = '#{Rails.env == 'development' ? 'http://localhost:3000' : 'http://data.qwaiter.com' }'; //var data_host = 'http://localhost:3000'; - //var data_host = 'http://192.168.1.74:3000'; + data_host = 'http://192.168.1.148:3000'; var $locale = '#{I18n.locale}'; var $url_vars = null; // Dummy holder when Qmobile object is not supplied by the mobile phone @@ -36,7 +36,8 @@ html lang="en" }, root_url: function(){return 'file:///Users/bterkuile/Documents/workspace/Qwaiter/assets'}, root_url: function(){return ''}, - goHome: function(){ window.location = QMobile.root_url() + path_mapping['user_root'] + '.html'} + goHome: function(){ redirect_to('user_root')}, + connection_problem: function(){alert('There is a problem connecting to the server')} }); //QMobile.setAuthToken('i5brDZ1HS1okoEq3pMyh'); diff --git a/config/locales/devise.en.yml b/config/locales/devise.en.yml index bb9b0da3..2ede53ba 100644 --- a/config/locales/devise.en.yml +++ b/config/locales/devise.en.yml @@ -29,10 +29,15 @@ en: signed_in: 'Signed in successfully.' signed_out: 'Signed out successfully.' passwords: + title: Forgot your password? + button: 'Send me reset password instructions' send_instructions: 'You will receive an email with instructions about how to reset your password in a few minutes.' updated: 'Your password was changed successfully. You are now signed in.' updated_not_active: 'Your password was changed successfully.' send_paranoid_instructions: "If your e-mail exists on our database, you will receive a password recovery link on your e-mail" + edit: + title: 'Change your password' + button: 'Change my password' confirmations: did_not_receive_instructions_link: "Didn't receive confirmation instructions?" send_instructions: 'You will receive an email with instructions about how to confirm your account in a few minutes.' diff --git a/config/locales/devise.nl.yml b/config/locales/devise.nl.yml index dde4263b..5c740d21 100644 --- a/config/locales/devise.nl.yml +++ b/config/locales/devise.nl.yml @@ -4,7 +4,9 @@ nl: not_found: "bestaat niet" already_confirmed: "was reeds bevestigd" not_locked: "was niet vergrendeld" - not_saved: "niet uitgevoerd" + not_saved: + one: "Een fout verhinderde het uitvoeren van de actie:" + other: "%{count} fouten verhinderden het uitvoeren van de actie:" devise: failure: @@ -27,6 +29,8 @@ nl: sign_in: Inloggen remember_me: Ingelogd blijven? passwords: + title: Wachtwoord vergeten? + button: 'Stuur mij instructies voor het vernieuwen van mijn wachtwoord' send_instructions: 'U ontvangt binnen enkele minuten een e-mail met instructies voor het resetten van uw wachtwoord' updated: 'Uw wachtwoord is succesvol gewijzigd. U bent nu ingelogd.' forgot_password: Wachtwoord vergeten? diff --git a/vendor/assets/devise/bootstrap-devise-rails.css.less b/vendor/assets/devise/bootstrap-devise-rails.css.less new file mode 100644 index 00000000..8e8935ba --- /dev/null +++ b/vendor/assets/devise/bootstrap-devise-rails.css.less @@ -0,0 +1,51 @@ +// require 'twitter/bootstrap/bootstrap' +@import "twitter/bootstrap/variables"; +@import "twitter/bootstrap/mixins"; +@import "twitter/bootstrap/alerts"; +@import "twitter/bootstrap/buttons"; +@import "twitter/bootstrap/forms"; +.devise { + br { display:none; } + // Copied from forms.less's legend + > h2, > h3 { + display: block; + width: 100%; + padding: 0; + margin-bottom: @baseLineHeight * 1.5; + font-size: @baseFontSize * 1.5; + line-height: @baseLineHeight * 2; + color: @grayDark; + border: 0; + border-bottom: 1px solid #eee; + } + > h2, >h3 { + margin-bottom: @baseLineHeight; + } + form { + // Base form styles + margin:0; + label[for=user_remember_me] { display: inline; } + input[type=submit] { + .btn-primary; + .btn-large; + margin:6px 0; + } + i { display: block; } + // Errors + #error_explanation { + h2 { + line-height: @baseLineHeight; + font-size: 14px; + .alert-error; + } + ul { margin-bottom: 0; } + .alert; + .alert-error; + } + .field_with_errors { + .control-group .error; + } + } + a:last-of-type:after { content: ''; } + a:after { content: '\0020\007c'; } +} diff --git a/vendor/assets/devise/devise.css.sass b/vendor/assets/devise/devise.css.sass new file mode 100644 index 00000000..620981e5 --- /dev/null +++ b/vendor/assets/devise/devise.css.sass @@ -0,0 +1,119 @@ +$baseline: 14px +$gray: #666 +$wellBackground: #f5f5f5 +$baseBorderRadius: 4px +$grayDark: #333 +$baseLineHeight: 20px +@mixin transition($transitions...) + transition: $transitions +@mixin box-shadow($shadows...) + box-shadow: $shadows +@mixin border-radius($str) + border-radius: $str +@mixin opacity($str) + opacity: $str +@mixin well + min-height: 20px + padding: 19px + margin-bottom: 20px + background-color: $wellBackground + border: 1px solid darken($wellBackground, 7%) + +border-radius($baseBorderRadius) + +box-shadow(inset 0 1px 1px rgba(0,0,0,.05)) + blockquote + border-color: #ddd + border-color: rgba(0,0,0,.15) +@mixin close + float: right + font-size: 20px + font-weight: bold + line-height: $baseLineHeight + color: black + text-shadow: 0 1px 0 rgba(255,255,255,1) + +opacity(.20) + &:hover + color: black + text-decoration: none + cursor: pointer + +opacity(.40) +.devise + form + // This is all copy/pasted. I can't get element-based rulesets to work + input[type=email] + display: inline-block + width: 210px + margin: 0 + padding: 4px + font-size: 13px + line-height: $baseline + height: $baseline + color: $gray + border: 1px solid #ccc + +border-radius(3px) + + // Focus states + input[type=email] + +transition(border linear .2s, box-shadow linear .2s) + +box-shadow(inset 0 1px 3px rgba(0,0,0,.1)) + &:focus + outline: none + border-color: rgba(82,168,236,.8) + +box-shadow(inset 0 1px 3px rgba(0,0,0,.1), 0 0 8px rgba(82,168,236,.6)) + margin-top: 20px + //.columns(7) + //.offset(4) + //.well + +well + h2 + margin-left: 150px + margin-bottom: 15px + font-size: 20px + font-weight: normal + color: $grayDark + form + div + margin-bottom: baseline + a + margin: 0 + &:after + content: '\0000a0' + &:before + content: none + br, i + display: none + input + margin-left: 20px + //* Oh, dear... * + label[for=user_remember_me] + padding: 0 + position: relative + left: 130px + input[type=submit] + margin-left: 150px + //+btn + //+primary + a, h3, p + margin-left: 150px + p + a + margin: 0 + &:before + content: none + a:before, p:before + content: '\002022\0000a0' + #error_explanation + //.alert-message.error + //.block-message + margin-left: 150px + + text-shadow: none + h2 + font-size: 13px + line-height: 18px + font-weight: bold + margin: 0 0 6px 0 + h2, li + color: white + a + +close + //.alert-message.close diff --git a/vendor/assets/devise/devise.js.coffee b/vendor/assets/devise/devise.js.coffee new file mode 100644 index 00000000..d571a043 --- /dev/null +++ b/vendor/assets/devise/devise.js.coffee @@ -0,0 +1,14 @@ +$ -> + $('.close').live 'click', (e) -> + e.preventDefault() + $(this).parent().hide() + $('.devise form div i').each -> + $this = $(this) + text = $this.text() + sibling = $this.prev('label') + a = $("").text("*").attr('title', text) + a.prependTo(sibling) + devise_errors = $('.devise #error_explanation') + if devise_errors.length + close_link = $('').addClass('close').attr('href', '#').text('\u00d7') + devise_errors.prepend(close_link)