Commit b96e5d24 authored by o@immerda.ch's avatar o@immerda.ch
Browse files

improve error messages

parent d2beb328
class AppPasswordsController < ApplicationController
def show
res = ApiBackend::app_passwords(current_user)
if res && res['result'] == 'success'
begin
res = ApiBackend::app_passwords(current_user)
@passwords = res['names']
if session[:app_pw]
@app_pw = session[:app_pw]
session[:app_pw] = nil
end
else
rescue
flash[:notice] = :failed
redirect_to '/'
end
end
def edit
if params[:app_name]
res = ApiBackend::app_password_create(
current_user, params[:password], params[:app_name])
if res && res['result'] == 'success'
begin
res = ApiBackend::app_password_create(
current_user, params[:password], params[:app_name])
session[:app_pw] = res['app_pw']
else
flash[:notice] = :failed
rescue => e
puts e.inspect
if e.api_msg
flash[:notice] = e.api_msg
else
flash[:notice] = :failed
end
end
elsif params[:delete]
ApiBackend::app_password_delete(current_user, params[:delete])
begin
ApiBackend::app_password_delete(current_user, params[:delete])
rescue
flash[:notice] = :failed
end
else
flash[:notice] = :failed
redirect_to '/'
......
require 'uri'
module ApiBackend
class ApiError < RuntimeError
attr_reader :msg, :api_msg
def initialize(msg, api_msg = nil)
@msg = msg
@api_msg = api_msg
end
end
def self.sanitize(parts)
parts.map{|v| URI.encode(v)}.join("/")
end
......@@ -13,9 +21,16 @@ module ApiBackend
:verify_ssl => OpenSSL::SSL::VERIFY_PEER)
begin
response = res.post(data.to_json)
JSON.parse(response)
rescue
false
res = JSON.parse(response)
if !res || res['result'] != "success"
puts "Expected success from iapi, but got #{res}"
raise ApiError.new("blocked #{res}")
end
res
rescue RestClient::BadRequest => e
raise ApiError.new("400", JSON.parse(e.response)['errors'])
rescue => e
raise ApiError.new("#{e}")
end
end
......@@ -27,21 +42,21 @@ module ApiBackend
:verify_ssl => OpenSSL::SSL::VERIFY_PEER)
begin
response = res.get(:params => data)
JSON.parse(response)
rescue
false
res = JSON.parse(response)
if !res['result'] == "success"
puts "Expected success from iapi, but got #{res}"
raise ApiError.new("blocked #{res}")
end
res
rescue RestClient::BadRequest => e
raise ApiError.new("400", JSON.parse(e.response)['errors'])
rescue => e
raise ApiError.new("#{e}")
end
end
def self.auth(user, pw, options = {})
email_regex = %r{^
[a-z0-9\-\._]+
@
[0-9a-z]
[0-9a-z.\-]+
[0-9a-z]
$}xi
if user =~ email_regex
if EmailValidation::immerda_email_conform(user)
return post(["authenticate"],
options.merge({"email"=>user, "password" => pw}))
end
......@@ -67,8 +82,8 @@ module ApiBackend
get(["info"], {'id' => id})
end
def self.new_email_token_valid?(token)
get(["check_new_email_token"], {'token' => token})
def self.invite_valid?(token)
get(["check_invite"], {'token' => token})
end
def self.valid_new_email?(email)
......@@ -80,7 +95,7 @@ module ApiBackend
end
def self.list_domains
@domains ||= get(["list_domains"], {})
@domains ||= get(["list_domains"], {})['domains']
end
def self.change_password(user, old, pw)
......@@ -99,15 +114,15 @@ module ApiBackend
post(["set_recovery_email"], {"email"=> email, "recovery_email" => recovery})
end
def self.generate_new_email_tokens(num)
post(["generate_new_email_tokens"], {"number"=> num})
def self.generate_invites(num)
post(["generate_invites"], {"number"=> num})
end
def self.create_new_mailbox(email, pw, trees_enabled, new_email_token, recovery_email, keep_recovery_token)
def self.create_new_mailbox(email, pw, trees_enabled, invite, recovery_email, keep_recovery_token)
post(["create_new_mailbox"], {"email" => email,
"password" => pw,
"trees_enabled" => trees_enabled,
"new_email_token" => new_email_token,
"invite" => invite,
"recovery_email" => recovery_email,
"keep_recovery_token" => keep_recovery_token,
})
......
require 'resolv'
require 'uri'
module EmailValidation
def self.valid_email_host?(hostname)
valid = true
begin
Resolv::DNS.new.getresource(hostname, Resolv::DNS::Resource::IN::MX)
rescue Resolv::ResolvError
begin
Resolv::DNS.new.getresource(hostname, Resolv::DNS::Resource::IN::A)
rescue Resolv::ResolvError
valid = false
end
end
return valid
end
def self.check_external_email(string)
if string.match(URI::MailTo::EMAIL_REGEXP)
string =~ /(.*)@([^@]+)$/
local = $1
domain = $2
if valid_email_host?(domain)
return [local, domain]
end
end
false
end
def self.immerda_email_conform(string)
email_regex = %r{^
([a-z0-9\-\._]+)
@
([0-9a-z]
[0-9a-z.\-]+
[0-9a-z])
$}xi
if string =~ email_regex
local = $1
domain = $2
[local, domain]
else
false
end
end
end
class InvitesController < AdminController
def show
if params['num_tokens']
res = ApiBackend::generate_new_email_tokens(params['num_tokens'])
if res && res['result'] == 'success'
begin
res = ApiBackend::generate_invites(params['num_tokens'])
@tokens = res['tokens']
rescue
flash[:notice] = :failed
end
end
end
......
......@@ -9,9 +9,14 @@ class PasswordController < ApplicationController
redirect_to '/password'
return
end
res = ApiBackend::change_password(current_user, params['old'], params['new'])
if !res || res['result'] != 'success'
flash[:notice] = :password_change_failed
begin
ApiBackend::change_password(current_user, params['old'], params['new'])
rescue => e
if e.api_msg == 'auth_fail'
flash[:notice] = :auth_fail
else
flash[:notice] = :password_change_failed
end
redirect_to '/password'
return
end
......
class RecoveryEmailController < ApplicationController
def show
if params[:recovery_email]
res = ApiBackend::set_recovery_email(current_user, params[:recovery_email])
if res && res['result'] == "success"
if !EmailValidation::check_external_email(params[:recovery_email])
flash[:notice] = :invalid_recovery_email
return
end
begin
ApiBackend::set_recovery_email(current_user, params[:recovery_email])
flash[:notice] = :success
redirect_to '/'
else
rescue
flash[:notice] = :failed
end
end
......
......@@ -25,14 +25,9 @@ class SessionsController < ApplicationController
if h && allowed_handoff.include?(h)
@handoff = h
end
if @handoff
res = ApiBackend::auth(params[:user_id], params[:password],
master_pw: true, generate_temp_pw: true)
else
res = ApiBackend::auth(params[:user_id], params[:password],
master_pw: true)
end
if res && res['state'] == 'success'
query = {master_pw: true, generate_temp_pw: @handoff}
begin
res = ApiBackend::auth(params[:user_id], params[:password], query)
session[:user_id] = params[:user_id]
session[:trees_enabled] = res['trees_enabled']
session[:pow_factor] = 1
......@@ -47,7 +42,10 @@ class SessionsController < ApplicationController
end
redirect_to '/'
end
# successful login
return
rescue
# Fallthrough, error handling below
end
end
if session[:pow_factor] < 4
......
......@@ -3,9 +3,10 @@ class SignupController < ApplicationController
@token = nil
token = params[:token]
if token
check_token = ApiBackend::new_email_token_valid?(token)
if check_token && check_token['result'] == 'success'
begin
ApiBackend::invite_valid?(token)
@token = token
rescue
end
end
end
......@@ -26,18 +27,11 @@ class SignupController < ApplicationController
if request.post? && @domain && @email && @email != ""
full_email = "#{@email}@#{@domain}"
check = ApiBackend::valid_new_email?(full_email)
if !check || check['result'] != 'success'
if check && check['msg'] == 'invalid_domain'
flash[:notice] = :invalid_domain
else
flash[:notice] = :invalid_email
end
return
end
if check['exists']
flash[:notice] = :account_exists_already
begin
ApiBackend::valid_new_email?(full_email)
rescue => e
sleep 5
flash[:notice] = e.api_msg
return
end
......@@ -49,21 +43,28 @@ class SignupController < ApplicationController
return
end
if !@keep_recovery_token
if @recovery_email && @recovery_email != '' &&
!EmailValidation::check_external_email(@recovery_email)
flash[:notice] = :invalid_recovery_email
return
end
if @enable_trees && !@keep_recovery_token
flash[:notice] = :decide_recovery_token
return
end
res = ApiBackend::create_new_mailbox(
full_email, @new_pw, @enable_trees, @token,
@recovery_email, @keep_recovery_token == 'yes')
if res && res['result'] == 'success'
begin
res = ApiBackend::create_new_mailbox(
full_email, @new_pw, @enable_trees, @token,
@recovery_email, @keep_recovery_token == 'yes')
flash.delete(:notice)
if @keep_recovery_token == 'no'
puts res
if @keep_recovery_token != 'yes'
@trees_recovery_token = res['trees_recovery_token']
end
@account_successfully_created = true
else
rescue
flash[:notice] = :signup_failed
end
end
......
class TreesController < ApplicationController
def show
if params[:pass]
res = ApiBackend::trees_enable(current_user, params['pass'])
if res && res['result'] == 'success'
begin
ApiBackend::trees_enable(current_user, params['pass'])
session[:trees_enabled] = true
flash[:notice] = :trees_enabled
redirect_to '/trees_token'
else
flash[:notice] = :trees_enable_failed
rescue => e
if e.api_msg == 'auth_fail'
flash[:notice] = :auth_fail
else
flash[:notice] = :trees_enable_failed
end
end
end
end
......
class TreesTokenController < ApplicationController
def show
if params[:pass]
res = ApiBackend::trees_token(current_user, params[:pass])
if res && res['result'] == "success"
begin
res = ApiBackend::trees_token(current_user, params[:pass])
session[:trees_recovery_token] = res['trees_recovery_token']
flash.delete(:notice)
else
flash[:notice] = :get_token_failed
rescue => e
if e.api_msg == 'auth_fail'
flash[:notice] = :auth_fail
else
flash[:notice] = :get_token_failed
end
end
end
end
......
......@@ -3,9 +3,14 @@
<p><%= @app_pw %></p>
<% end %>
<% if @passwords && !@passwords.empty? %>
<h3><%= t :app_passwords %></h3>
<p>
<%= t :app_passwords_help %>
</p>
<% if @passwords && !@passwords.empty? %>
<ul>
<% @passwords.each do |pw| %>
<li>
......@@ -17,11 +22,11 @@
</li>
<% end %>
</ul>
<% end %>
<hr/ >
<% end %>
<br />
<h3><%= t :new_app_passwords %></h3>
<%= form_tag("/app_passwords", method: "post") do %>
<table>
<tr><td>
......@@ -35,7 +40,7 @@
</td></tr>
</table>
<p>
<%= submit_tag(t :submit) %>
<%= link_to "Cancel", :back %>
<%= submit_tag(t :generate) %>
<%= link_to t(:back), '/' %>
</p>
<% end %>
......@@ -9,4 +9,5 @@
<%= text_field_tag(:recovery_email) %>
<br />
<%= submit_tag(t :submit) %>
<%= link_to t(:back), '/' %>
<% end %>
......@@ -3,7 +3,7 @@
<% if !@token || @token == "" %>
<%= form_tag("/signup", method: "post") do %>
<%= label_tag(:token, (t :token)) %>
<%= label_tag(:token, (t :invite_token)) %>
<%= text_field_tag(:token) %>
<%= submit_tag(t :submit) %>
<% end %>
......
......@@ -36,6 +36,8 @@ de:
create: "erstellen"
app_passwords: "App Passwörter"
app_passwords_short_help: "Um via Mail Programm einzuloggen, musst du ein App Passwort erstellen."
app_passwords_help: "Um mit externen Programmen einzuloggen, brauchst du ein App Passwort. Das Haupt Passwort funktioniert nur auf unseren Webseiten. Für alle anderen Zugänge, zum Beispiel für Thunderbird, oder Exchange Sync via Phone, kannst du hier ein Spezifisches Passwort generieren. Gib dazu den Verwendungszweck ein und klicke auf generieren. Das Passwort wird dir danach angezeigt und du kannst es kopieren. Ebenfalls kannst du hier bestehende App Passwörter löschen."
generate: "generieren"
change_password_short_help: "Das Hauptpasswort ändern"
trees_token_short_help: "Wenn du dein Passwort vergisst können deine Mails nur mit diesem Token wiederhergestellt werden"
enable_trees_short_help: "Verschlüsselt Mails in deiner Mailbox mit deinem Passwort"
......@@ -56,3 +58,11 @@ de:
keep_recovery_token_help: "Beim Passwortverlust brauchst du ein Token, um deine Mailbox wiederherzustellen."
init_keep_token: "Ich kann jetzt gerade das Token nicht sicher aufbewahren und werde es später abholen."
init_delete_token: "Ich bewahre das Token selber auf."
invite_token: "Einladungscode"
new_account: "Neues Konto"
invalid_recovery_email: "Backup Email ist keine gültige Adresse"
decide_recovery_token: "Bitte wähle aus, ob du dein Wiederherstellungs Token aufbewahren kannst"
auth_fail: "Falsches Passwort"
app_password_duplicate: "App Passwort mit diesem Namen besteht bereits"
back: "zurück"
account_exists_already: "Diese Email besteht bereits"
......@@ -15,7 +15,6 @@ en:
encrypt_mailbox_help: "WARNING: This feature is not stable yet and it might happen that mails become unreadable. Activate this option to encrypt all new incomming mails in your mailbox."
encrypt_mailbox_help_existing: "(Currently only applies to new incoming mails)"
trees_enabled: "Encryption activated"
token_cleared: "Token copy erased"
password_changed: "Password changed"
login_failed: "Login failed"
login: "Login"
......@@ -40,6 +39,8 @@ en:
enable_trees_short_help: "Encrypt your mailbox with your password"
your_pw: "Your password"
new_app_passwords: "Request new app password"
app_passwords_help: "To connect with external programs you need an app specific password. Your main password only works on our own websites. For other access, like Thunderbird, or Exchange sync by phone, you need to create a special password here. To do so enter the intended usage and click generate. The app password will be shown and you can copy/paste it. Additionally you can delete existing app passwords here."
generate: "generate"
password_for_reveal: "Enter password to show token"
password_for_clear: "Enter password to clear our copy"
password_for_enable: "Enter password to enable encryption"
......@@ -55,3 +56,9 @@ en:
keep_recovery_token_help: "You need this token to recover your data, when you forget your password."
init_keep_token: "Ich can't safely store the token right now. I will pick it up later."
init_delete_token: "Ich will safely store my token."
invite_token: "Invite Code"
new_account: "New Account"
invalid_recovery_email: "Recovery email is not valid"
decide_recovery_token: "Please decide if your store your recovery token"
auth_fail: "password wrong"
app_password_duplicate: "App password with this name already exists"
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment