summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorAzul <azul@leap.se>2014-06-09 11:00:28 +0200
committerAzul <azul@leap.se>2014-06-09 11:00:28 +0200
commit728d6d3985126c2890638bb2ee24020fa0e36a80 (patch)
tree1fcbb560b0103123d49fb953e86fdb960ee5dd13 /app
parentb9174fdc9d9bd403d9a16650bafc4715e3dbf2d4 (diff)
parent9fa52ed80d71ec56ed5acf18dfd63bd03b201cc5 (diff)
Merge tag '0.5.2'
Diffstat (limited to 'app')
-rw-r--r--app/controllers/application_controller.rb10
-rw-r--r--app/controllers/controller_extension/flash.rb43
-rw-r--r--app/controllers/controller_extension/token_authentication.rb4
-rw-r--r--app/controllers/errors_controller.rb10
-rw-r--r--app/controllers/v1/certs_controller.rb8
-rw-r--r--app/controllers/v1/smtp_certs_controller.rb37
-rw-r--r--app/helpers/application_helper.rb3
-rw-r--r--app/helpers/core_helper.rb7
-rw-r--r--app/helpers/link_helper.rb49
-rw-r--r--app/models/account.rb8
-rw-r--r--app/models/client_certificate.rb8
-rw-r--r--app/models/email.rb5
-rw-r--r--app/models/identity.rb66
-rw-r--r--app/models/local_email.rb10
-rw-r--r--app/models/pgp_key.rb3
-rw-r--r--app/models/token.rb13
-rw-r--r--app/models/user.rb16
-rw-r--r--app/views/common/_action_buttons.html.haml12
-rw-r--r--app/views/common/_download_button.html.haml4
-rw-r--r--app/views/common/_home_page_buttons.html.haml4
-rw-r--r--app/views/errors/not_found.html.haml7
-rw-r--r--app/views/errors/server_error.html.haml7
-rw-r--r--app/views/layouts/_footer.html.haml2
-rw-r--r--app/views/layouts/_header.html.haml4
-rw-r--r--app/views/layouts/_messages.html.haml2
-rw-r--r--app/views/layouts/_navigation.html.haml2
-rw-r--r--app/views/pages/pricing.html.haml2
-rw-r--r--app/views/pages/terms-of-service.en.md4
-rw-r--r--app/views/users/_destroy_account.html.haml6
-rw-r--r--app/views/users/_overview.html.haml24
-rw-r--r--app/views/users/new.html.haml2
-rw-r--r--app/views/users/show.html.haml37
32 files changed, 315 insertions, 104 deletions
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 35d6cb4..a4560e2 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -23,16 +23,6 @@ class ApplicationController < ActionController::Base
json: {error: "The server failed to process your request. We'll look into it."}
end
- #
- # Allows us to pass through bold text to flash messages. See format_flash() for where this is reversed.
- #
- # TODO: move to core
- #
- def bold(str)
- "[b]#{str}[/b]"
- end
- helper_method :bold
-
##
## LOCALE
##
diff --git a/app/controllers/controller_extension/flash.rb b/app/controllers/controller_extension/flash.rb
new file mode 100644
index 0000000..1642141
--- /dev/null
+++ b/app/controllers/controller_extension/flash.rb
@@ -0,0 +1,43 @@
+module ControllerExtension::Flash
+ extend ActiveSupport::Concern
+
+ protected
+
+ def flash_for(resource, options = {})
+ return unless resource.changed?
+ add_flash_message_for resource
+ add_flash_errors_for resource if options[:with_errors]
+ end
+
+ def add_flash_message_for(resource)
+ message = flash_message_for(resource)
+ type = flash_type_for(resource)
+ if message.present?
+ flash[type] = message
+ end
+ end
+
+ def flash_message_for(resource)
+ I18n.t flash_i18n_key(resource),
+ scope: :flash,
+ cascade: true,
+ resource: resource.class.model_name.human
+ end
+
+ def flash_i18n_key(resource)
+ namespace = [action_name]
+ namespace += controller_path.split('/')
+ namespace << flash_type_for(resource)
+ namespace.join(".")
+ end
+
+ def flash_type_for(resource)
+ resource.valid? ? :success : :error
+ end
+
+ def add_flash_errors_for(resource)
+ return if resource.valid?
+ flash[:error] += "<br>"
+ flash[:error] += resource.errors.full_messages.join(". <br>")
+ end
+end
diff --git a/app/controllers/controller_extension/token_authentication.rb b/app/controllers/controller_extension/token_authentication.rb
index 6e0a6ce..b0ed624 100644
--- a/app/controllers/controller_extension/token_authentication.rb
+++ b/app/controllers/controller_extension/token_authentication.rb
@@ -2,8 +2,8 @@ module ControllerExtension::TokenAuthentication
extend ActiveSupport::Concern
def token
- @token ||= authenticate_with_http_token do |token_id, options|
- Token.find(token_id)
+ @token ||= authenticate_with_http_token do |token, options|
+ Token.find_by_token(token)
end
end
diff --git a/app/controllers/errors_controller.rb b/app/controllers/errors_controller.rb
new file mode 100644
index 0000000..6c659e6
--- /dev/null
+++ b/app/controllers/errors_controller.rb
@@ -0,0 +1,10 @@
+# We render http errors ourselves so we can customize them
+class ErrorsController < ApplicationController
+ # 404
+ def not_found
+ end
+
+ # 500
+ def server_error
+ end
+end
diff --git a/app/controllers/v1/certs_controller.rb b/app/controllers/v1/certs_controller.rb
index 73409ef..b6d1d0b 100644
--- a/app/controllers/v1/certs_controller.rb
+++ b/app/controllers/v1/certs_controller.rb
@@ -3,7 +3,15 @@ class V1::CertsController < ApplicationController
before_filter :require_login, :unless => :anonymous_certs_allowed?
# GET /cert
+ # deprecated - we actually create a new cert and that can
+ # be reflected in the action. GET /cert will eventually go
+ # away and be replaced by POST /cert
def show
+ create
+ end
+
+ # POST /cert
+ def create
@cert = ClientCertificate.new(:prefix => service_level.cert_prefix)
render text: @cert.to_s, content_type: 'text/plain'
end
diff --git a/app/controllers/v1/smtp_certs_controller.rb b/app/controllers/v1/smtp_certs_controller.rb
new file mode 100644
index 0000000..377a49c
--- /dev/null
+++ b/app/controllers/v1/smtp_certs_controller.rb
@@ -0,0 +1,37 @@
+class V1::SmtpCertsController < ApplicationController
+
+ before_filter :require_login
+ before_filter :require_email_account
+ before_filter :fetch_identity
+
+ # POST /1/smtp_cert
+ def create
+ @cert = ClientCertificate.new prefix: current_user.email_address
+ @identity.register_cert(@cert)
+ @identity.save
+ render text: @cert.to_s, content_type: 'text/plain'
+ end
+
+ protected
+
+ #
+ # Filters
+ #
+
+ def require_email_account
+ access_denied unless service_level.provides? 'email'
+ end
+
+ def fetch_identity
+ @identity = current_user.identity
+ end
+
+ #
+ # Helper methods
+ #
+
+ def service_level
+ current_user.effective_service_level
+ end
+
+end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 90e649a..6de5e1b 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -40,8 +40,9 @@ module ApplicationHelper
end
end
+ # fairly strict sanitation for flash messages
def format_flash(msg)
- html_escape(msg).gsub('[b]', '<b>').gsub('[/b]', '</b>').html_safe
+ sanitize(msg, tags: %w(em strong b br), attributes: [])
end
end
diff --git a/app/helpers/core_helper.rb b/app/helpers/core_helper.rb
index 4126906..46e8fa4 100644
--- a/app/helpers/core_helper.rb
+++ b/app/helpers/core_helper.rb
@@ -10,4 +10,11 @@ module CoreHelper
render 'common/home_page_buttons'
end
+ #
+ # returns true if the configured service levels contain a level with a price attached
+ #
+ def paid_service_level?
+ APP_CONFIG[:service_levels].present? && APP_CONFIG[:service_levels].detect{|k,v| v['rate'].present?}
+ end
+
end
diff --git a/app/helpers/link_helper.rb b/app/helpers/link_helper.rb
new file mode 100644
index 0000000..55e392b
--- /dev/null
+++ b/app/helpers/link_helper.rb
@@ -0,0 +1,49 @@
+module LinkHelper
+
+ #
+ # markup for bootstrap button
+ #
+ # takes same arguments as link_to and adds a 'btn' class.
+ # In addition:
+ # * the name will be translated if it is a symbol
+ # * html_options[:type] will be converted into a btn-type class
+ #
+ # example:
+ # btn :home, home_path, type: [:large, :primary]
+ #
+ def btn(*args, &block)
+ html_options = extract_html_options!(args, &block)
+ type = Array(html_options.delete(:type))
+ type.map! {|t| "btn-#{t}"}
+ html_options[:class] = concat_classes(html_options[:class], 'btn', type)
+ args[0] = t(args[0]) if args[0].is_a?(Symbol)
+ link_to *args, html_options, &block
+ end
+
+ def destroy_btn(*args, &block)
+ html_options = extract_html_options!(args, &block)
+ confirmation = t "#{controller_symbol}.confirm.destroy.are_you_sure",
+ cascade: true
+ html_options.merge! method: :delete, confirm: confirmation
+ btn *args, html_options, &block
+ end
+
+ #
+ # concat_classes will combine classes in a fairly flexible way.
+ # it can handle nil, arrays, space separated strings
+ # it returns a space separated string of classes.
+ def concat_classes(*classes)
+ classes.compact!
+ classes.map {|c| c.respond_to?(:split) ? c.split(' ') : c }
+ classes.flatten!
+ classes.join ' '
+ end
+
+ def extract_html_options!(args)
+ if args.count > 2 or args.count > 1 && block_given?
+ args.extract_options!
+ else
+ {}
+ end
+ end
+end
diff --git a/app/models/account.rb b/app/models/account.rb
index cf998e4..32ed445 100644
--- a/app/models/account.rb
+++ b/app/models/account.rb
@@ -16,9 +16,13 @@ class Account
# Returns the user record so it can be used in views.
def self.create(attrs)
- @user = User.create(attrs).tap do |user|
- Identity.create_for user
+ @user = User.create(attrs)
+ if @user.persisted?
+ identity = @user.identity
+ identity.user_id = @user.id
+ identity.save
end
+ return @user
end
def update(attrs)
diff --git a/app/models/client_certificate.rb b/app/models/client_certificate.rb
index 76b07a2..63de9e1 100644
--- a/app/models/client_certificate.rb
+++ b/app/models/client_certificate.rb
@@ -43,8 +43,16 @@ class ClientCertificate
self.key.to_pem + self.cert.to_pem
end
+ def fingerprint
+ OpenSSL::Digest::SHA1.hexdigest(openssl_cert.to_der).scan(/../).join(':')
+ end
+
private
+ def openssl_cert
+ cert.openssl_body
+ end
+
def self.root_ca
@root_ca ||= begin
crt = File.read(APP_CONFIG[:client_ca_cert])
diff --git a/app/models/email.rb b/app/models/email.rb
index a9a503f..4090275 100644
--- a/app/models/email.rb
+++ b/app/models/email.rb
@@ -7,6 +7,11 @@ class Email < String
:message => "needs to be a valid email address"
}
+ # Make sure we can call Email.new(nil) and get an invalid email address
+ def initialize(s)
+ super(s.to_s)
+ end
+
def to_partial_path
"emails/email"
end
diff --git a/app/models/identity.rb b/app/models/identity.rb
index ad8c01e..2f6241c 100644
--- a/app/models/identity.rb
+++ b/app/models/identity.rb
@@ -8,9 +8,12 @@ class Identity < CouchRest::Model::Base
property :address, LocalEmail
property :destination, Email
property :keys, HashWithIndifferentAccess
+ property :cert_fingerprints, Hash
- validate :unique_forward
- validate :alias_available
+ validates :address, presence: true
+ validate :address_available
+ validates :destination, presence: true, if: :enabled?
+ validates :destination, uniqueness: {scope: :address}
validate :address_local_email
validate :destination_email
@@ -49,7 +52,8 @@ class Identity < CouchRest::Model::Base
def self.find_for(user, attributes = {})
attributes.reverse_merge! attributes_from_user(user)
- find_by_address_and_destination [attributes[:address], attributes[:destination]]
+ id = find_by_address_and_destination attributes.values_at(:address, :destination)
+ return id if id && id.user == user
end
def self.build_for(user, attributes = {})
@@ -66,7 +70,9 @@ class Identity < CouchRest::Model::Base
def self.disable_all_for(user)
Identity.by_user_id.key(user.id).each do |identity|
identity.disable
- identity.save
+ # if the identity is not unique anymore because the destination
+ # was reset to nil we destroy it.
+ identity.save || identity.destroy
end
end
@@ -90,7 +96,11 @@ class Identity < CouchRest::Model::Base
end
def enabled?
- self.destination && self.user_id
+ self.user_id
+ end
+
+ def disabled?
+ !enabled?
end
def disable
@@ -107,36 +117,50 @@ class Identity < CouchRest::Model::Base
write_attribute('keys', keys.merge(type => key.to_s))
end
+ def cert_fingerprints
+ read_attribute('cert_fingerprints') || Hash.new
+ end
+
+ def register_cert(cert)
+ today = DateTime.now.to_date.to_s
+ write_attribute 'cert_fingerprints',
+ cert_fingerprints.merge(cert.fingerprint => today)
+ end
+
# for LoginFormatValidation
def login
- self.address.handle
+ address.handle if address.present?
end
protected
- def unique_forward
- same = Identity.find_by_address_and_destination([address, destination])
- if same && same != self
- errors.add :base, "This alias already exists"
+ def address_available
+ blocking_identities = Identity.by_address.key(address).all
+ blocking_identities.delete self
+ if self.user
+ blocking_identities.reject! { |other| other.user == self.user }
end
- end
-
- def alias_available
- same = Identity.find_by_address(address)
- if same && same.user != self.user
- errors.add :base, "This email has already been taken"
+ if blocking_identities.any?
+ errors.add :address, :taken
end
end
def address_local_email
- return if address.valid? #this ensures it is LocalEmail
- self.errors.add(:address, address.errors.messages[:email].first) #assumes only one error
+ # caught by presence validation
+ return if address.blank?
+ return if address.valid?
+ address.errors.each do |attribute, error|
+ self.errors.add(:address, error)
+ end
end
def destination_email
- return if destination.nil? # this identity is disabled
- return if destination.valid? # this ensures it is Email
- self.errors.add(:destination, destination.errors.messages[:email].first) #assumes only one error #TODO
+ # caught by presence validation or this identity is disabled
+ return if destination.blank?
+ return if destination.valid?
+ destination.errors.each do |attribute, error|
+ self.errors.add(:destination, error)
+ end
end
end
diff --git a/app/models/local_email.rb b/app/models/local_email.rb
index 2b4c65e..ded7baf 100644
--- a/app/models/local_email.rb
+++ b/app/models/local_email.rb
@@ -58,11 +58,9 @@ class LocalEmail < Email
end
def handle_in_passwd?
- begin
- !!Etc.getpwnam(handle)
- rescue ArgumentError
- # handle was not found
- return false
- end
+ Etc.getpwnam(handle).present?
+ rescue ArgumentError
+ # handle was not found
+ return false
end
end
diff --git a/app/models/pgp_key.rb b/app/models/pgp_key.rb
index 66f8660..3384f4c 100644
--- a/app/models/pgp_key.rb
+++ b/app/models/pgp_key.rb
@@ -25,9 +25,10 @@ class PgpKey
# allow comparison with plain keyblock strings.
def ==(other)
+ return false if (self.present? != other.present?)
self.equal?(other) or
# relax the comparison on line ends.
- self.to_s.tr_s("\n\r", '') == other.tr_s("\r\n", '')
+ self.to_s.tr_s("\n\r", '') == other.tr_s("\n\r", '')
end
protected
diff --git a/app/models/token.rb b/app/models/token.rb
index e759ee3..ff2ad12 100644
--- a/app/models/token.rb
+++ b/app/models/token.rb
@@ -1,3 +1,5 @@
+require 'digest/sha2'
+
class Token < CouchRest::Model::Base
use_database :tokens
@@ -11,10 +13,16 @@ class Token < CouchRest::Model::Base
validates :user_id, presence: true
+ attr_accessor :token
+
design do
view :by_last_seen_at
end
+ def self.find_by_token(token)
+ self.find Digest::SHA512.hexdigest(token)
+ end
+
def self.expires_after
APP_CONFIG[:auth] && APP_CONFIG[:auth][:token_expires_after]
end
@@ -31,7 +39,7 @@ class Token < CouchRest::Model::Base
end
def to_s
- id
+ token
end
def authenticate
@@ -65,7 +73,8 @@ class Token < CouchRest::Model::Base
def initialize(*args)
super
if new_record?
- self.id = SecureRandom.urlsafe_base64(32).gsub(/^_*/, '')
+ self.token = SecureRandom.urlsafe_base64(32).gsub(/^_*/, '')
+ self.id = Digest::SHA512.hexdigest(self.token)
self.last_seen_at = Time.now
end
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 6678de6..f8b9ddc 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -24,7 +24,7 @@ class User < CouchRest::Model::Base
:uniqueness => true,
:if => :serverside?
- validate :login_is_unique_alias
+ validate :identity_is_valid
validates :password_salt, :password_verifier,
:format => { :with => /\A[\dA-Fa-f]+\z/, :message => "Only hex numbers allowed" }
@@ -42,6 +42,11 @@ class User < CouchRest::Model::Base
view :by_created_at
end # end of design
+ def reload
+ @identity = nil
+ super
+ end
+
def to_json(options={})
{
:login => login,
@@ -161,11 +166,10 @@ class User < CouchRest::Model::Base
# Validation Functions
##
- def login_is_unique_alias
- alias_identity = Identity.find_by_address(self.email_address)
- return if alias_identity.blank?
- if alias_identity.user != self
- errors.add(:login, "has already been taken")
+ def identity_is_valid
+ return if identity.valid?
+ identity.errors.each do |attribute, error|
+ self.errors.add(:login, error)
end
end
diff --git a/app/views/common/_action_buttons.html.haml b/app/views/common/_action_buttons.html.haml
index c74fcd1..266abe1 100644
--- a/app/views/common/_action_buttons.html.haml
+++ b/app/views/common/_action_buttons.html.haml
@@ -1,11 +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)
+ %span.link= btn icon('ok-sign') + t(:login), login_path
+ %span.info= t(:login_info, default: "")
.signup.span4
- %span.link= link_to(icon('user', icon_color) + t(:signup), signup_path, :class => 'btn')
- %span.info= t(:signup_info)
+ %span.link= btn icon('user') + t(:signup), signup_path
+ %span.info= t(:signup_info, default: "")
.help.span4
- %span.link= link_to(icon('question-sign', icon_color) + t(:get_help), new_ticket_path, :class => 'btn')
- %span.info= t(:help_info)
+ %span.link= btn icon('question-sign') + t(:get_help), new_ticket_path
+ %span.info= t(:support_info, default: "")
diff --git a/app/views/common/_download_button.html.haml b/app/views/common/_download_button.html.haml
index e57c56b..9c26860 100644
--- a/app/views/common/_download_button.html.haml
+++ b/app/views/common/_download_button.html.haml
@@ -2,7 +2,7 @@
.row-fluid.first
.span2
.download.span8
- = link_to client_download_url, class: "btn btn-large btn-primary" do
+ = btn client_download_url, type: [:large, :primary] do
= big_icon('download')
- = t(:download_client)
+ = t(:download_bitmask)
.span2
diff --git a/app/views/common/_home_page_buttons.html.haml b/app/views/common/_home_page_buttons.html.haml
index 8c47983..fc6348e 100644
--- a/app/views/common/_home_page_buttons.html.haml
+++ b/app/views/common/_home_page_buttons.html.haml
@@ -1,8 +1,6 @@
-- 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
+= render 'common/action_buttons'
diff --git a/app/views/errors/not_found.html.haml b/app/views/errors/not_found.html.haml
new file mode 100644
index 0000000..c7fec22
--- /dev/null
+++ b/app/views/errors/not_found.html.haml
@@ -0,0 +1,7 @@
+.hero-unit
+ %h1=t 'errors.title.page_not_found'
+ %h2=t 'errors.subtitle.page_not_found', default: ''
+ %p.lead=t 'errors.text.page_not_found', default: ''
+ %a.btn.btn-primary.btn-large{href:'/'}
+ %i.icon-home.icon-white
+ =t :home
diff --git a/app/views/errors/server_error.html.haml b/app/views/errors/server_error.html.haml
new file mode 100644
index 0000000..a4133da
--- /dev/null
+++ b/app/views/errors/server_error.html.haml
@@ -0,0 +1,7 @@
+.hero-unit
+ %h1=t 'errors.title.server_error'
+ %h2=t 'errors.subtitle.server_error', default: ''
+ %p.lead=t 'errors.text.server_error', default: ''
+ %a.btn.btn-primary.btn-large{href:'/'}
+ %i.icon-home.icon-white
+ =t :home
diff --git a/app/views/layouts/_footer.html.haml b/app/views/layouts/_footer.html.haml
index 340d36c..de53667 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].present?
+ - if paid_service_level?
= 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 a1dd47a..e827f60 100644
--- a/app/views/layouts/_header.html.haml
+++ b/app/views/layouts/_header.html.haml
@@ -2,9 +2,9 @@
%ul.nav.nav-tabs
= # this navigation isn't quite right. also, we will want to active for an identity controller once it is added.
%li{:class => ("active" if controller?('users', 'overviews') || params[:user_id])}
- = link_to t(:users), users_path
+ = link_to t(".users"), users_path
%li{:class => ("active" if controller?('tickets') && !params[:user_id])}
- = link_to t(:tickets), tickets_path
+ = link_to t(".tickets", cascade: true), tickets_path
%li
= link_to t(:logout), logout_path, :method => :delete
- if @user && @show_navigation
diff --git a/app/views/layouts/_messages.html.haml b/app/views/layouts/_messages.html.haml
index 7ff985f..18be54f 100644
--- a/app/views/layouts/_messages.html.haml
+++ b/app/views/layouts/_messages.html.haml
@@ -1,6 +1,6 @@
#messages
- flash.each do |name, msg|
- if msg.is_a?(String)
- %div{:class => "alert alert-#{name == :notice ? "success" : "error"}"}
+ %div{:class => "alert alert-#{name == :notice ? "success" : name}"}
%a.close{"data-dismiss" => "alert"} ×
= content_tag :div, format_flash(msg), :id => "flash_#{name}"
diff --git a/app/views/layouts/_navigation.html.haml b/app/views/layouts/_navigation.html.haml
index b81c43d..94f71f7 100644
--- a/app/views/layouts/_navigation.html.haml
+++ b/app/views/layouts/_navigation.html.haml
@@ -2,6 +2,6 @@
= link_to_navigation t(:overview), @user, :active => (controller?(:users) && action?(:show))
= link_to_navigation t(:account_settings), edit_user_path(@user), :active => (controller?(:users) && !action?(:show))
- # will want link for identity settings
- = link_to_navigation t(:support_tickets), auto_tickets_path, :active => controller?(:tickets)
+ = link_to_navigation t(".tickets"), auto_tickets_path, :active => controller?(:tickets)
= link_to_navigation t(:billing_settings), billing_top_link(@user), :active => controller?(:customer, :payments, :subscriptions, :credit_card_info) if APP_CONFIG[:billing]
= link_to_navigation t(:logout), logout_path, :method => :delete
diff --git a/app/views/pages/pricing.html.haml b/app/views/pages/pricing.html.haml
index e339d27..983501e 100644
--- a/app/views/pages/pricing.html.haml
+++ b/app/views/pages/pricing.html.haml
@@ -1,5 +1,5 @@
%h1= t(:pricing)
-%p= link_to(icon('user') + t(:signup), signup_path, :class => 'btn')
+%p= btn icon('user') + t(:signup), signup_path
- levels = APP_CONFIG[:service_levels]
- if levels
diff --git a/app/views/pages/terms-of-service.en.md b/app/views/pages/terms-of-service.en.md
index 7b57027..93490b7 100644
--- a/app/views/pages/terms-of-service.en.md
+++ b/app/views/pages/terms-of-service.en.md
@@ -3,8 +3,8 @@
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/>
+ <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>
diff --git a/app/views/users/_destroy_account.html.haml b/app/views/users/_destroy_account.html.haml
index 445f3c4..a2c4ddd 100644
--- a/app/views/users/_destroy_account.html.haml
+++ b/app/views/users/_destroy_account.html.haml
@@ -8,20 +8,20 @@
- else
= t(:admin_destroy_account, :username => @user.login)
%p= t(:destroy_account_info)
-= link_to user_path(@user), :method => :delete, :confirm => t(:are_you_sure), :class => "btn btn-danger" do
+= destroy_btn user_path(@user), :type => "danger" do
%i.icon-remove.icon-white
= t(:destroy_my_account)
- if @user != current_user and @user.enabled?
%legend
= t(:deactivate_account, :username => @user.login)
%p= t(:deactivate_description)
- = link_to deactivate_user_path(@user), :method => :post, :class => "btn btn-warning" do
+ = btn deactivate_user_path(@user), :method => :post, :type => "warning" do
%i.icon-pause.icon-white
= t(:deactivate)
- elsif @user != current_user and !@user.enabled?
%legend
= t(:enable_account, :username => @user.login)
%p= t(:enable_description)
- = link_to enable_user_path(@user), :method => :post, :class => "btn btn-warning" do
+ = btn enable_user_path(@user), :method => :post, :type => "warning" do
%i.icon-ok.icon-white
= t(:enable)
diff --git a/app/views/users/_overview.html.haml b/app/views/users/_overview.html.haml
new file mode 100644
index 0000000..e38fdc8
--- /dev/null
+++ b/app/views/users/_overview.html.haml
@@ -0,0 +1,24 @@
+.overview
+
+ %h2.first= t(".welcome", username: @user.login, cascade: true)
+
+ - if admin?
+ %p
+ = t(:created)
+ = @user.created_at
+ %br
+ = t(:updated)
+ = @user.updated_at
+ %br
+ = t(:enabled)
+ = @user.enabled?
+
+ %p= t(:overview_intro, default: "")
+
+ %ul.unstyled
+ %li= icon('user') + link_to(t(".account"), edit_user_path(@user))
+ - # %li= icon('envelope') + link_to(t(:overview_email), {insert path for user identities, presuambly}
+ %li= icon('question-sign') + link_to(t(".tickets"), user_tickets_path(@user))
+ %li= icon('shopping-cart') + link_to(t(".billing"), billing_top_link(@user)) if APP_CONFIG[:billing]
+
+
diff --git a/app/views/users/new.html.haml b/app/views/users/new.html.haml
index bc36068..41a9d55 100644
--- a/app/views/users/new.html.haml
+++ b/app/views/users/new.html.haml
@@ -17,5 +17,5 @@
= 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 }
- = f.button :wrapped, value: t(:signup), cancel: home_path
+ = f.button :wrapped, cancel: home_path
diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml
index ddc33ab..da8e467 100644
--- a/app/views/users/show.html.haml
+++ b/app/views/users/show.html.haml
@@ -1,30 +1,7 @@
-.overview
-
- %h2.first= t(:overview_welcome, :username => @user.login)
-
- - if admin?
- %p
- = t(:created)
- = @user.created_at
- %br
- = t(:updated)
- = @user.updated_at
- %br
- = t(:enabled)
- = @user.enabled?
-
- %p= t(:overview_intro)
-
- %ul.unstyled
- %li= icon('user') + link_to(t(:overview_account), edit_user_path(@user))
- - # %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
- %h4 To use bitmask services:
- = link_to client_download_url, class: "btn btn-primary" do
- %i.icon-arrow-down.icon-white
- = t(:download_client)
+= render 'overview'
+.container-fluid
+ .row-fluid
+ %h4 To use bitmask services:
+ = btn client_download_url, type: "primary" do
+ %i.icon-arrow-down.icon-white
+ = t(:download_bitmask)