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

Merge branch 'saml'

parents ecc43eb8 64a7998b
...@@ -39,6 +39,8 @@ gem 'rotp' ...@@ -39,6 +39,8 @@ gem 'rotp'
gem 'rucaptcha' gem 'rucaptcha'
gem 'jsobfu' gem 'jsobfu'
gem 'ruby-saml', '~> 1.9.0'
group :development, :test do group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console # Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
......
...@@ -157,6 +157,8 @@ GEM ...@@ -157,6 +157,8 @@ GEM
rotp (3.3.1) rotp (3.3.1)
rqrcode (0.10.1) rqrcode (0.10.1)
chunky_png (~> 1.0) chunky_png (~> 1.0)
ruby-saml (1.9.0)
nokogiri (>= 1.5.10)
ruby_dep (1.5.0) ruby_dep (1.5.0)
rubyzip (1.2.1) rubyzip (1.2.1)
rucaptcha (2.3.0) rucaptcha (2.3.0)
...@@ -227,6 +229,7 @@ DEPENDENCIES ...@@ -227,6 +229,7 @@ DEPENDENCIES
rest-client rest-client
rotp rotp
rqrcode rqrcode
ruby-saml (~> 1.9.0)
rucaptcha rucaptcha
sass-rails (~> 5.0) sass-rails (~> 5.0)
selenium-webdriver selenium-webdriver
......
class AclController < AdminController
include ApiBackend
def show
begin
@acl = api.acl_show
rescue ApiBackend::ApiError => e
flash[:notice] = e.api_msg
end
end
end
class AppPasswordsController < ApplicationController class AppPasswordsController < ApplicationController
include ApiBackend
def show def show
begin begin
res = ApiBackend::app_passwords(current_user) res = api.app_passwords
puts res puts res
@passwords = res['res'] @passwords = res['res']
if session[:app_pw] if session[:app_pw]
...@@ -23,15 +25,15 @@ class AppPasswordsController < ApplicationController ...@@ -23,15 +25,15 @@ class AppPasswordsController < ApplicationController
def edit def edit
if params[:app_name] if params[:app_name]
begin begin
res = ApiBackend::app_password_create( res = api.app_password_create(
current_user, params[:password], params[:app_name]) params[:password], params[:app_name])
session[:app_pw] = res['app_pw'] session[:app_pw] = res['app_pw']
rescue ApiBackend::ApiError => e rescue ApiBackend::ApiError => e
flash[:notice] = e.api_msg || :failed flash[:notice] = e.api_msg || :failed
end end
elsif params[:delete] elsif params[:delete]
begin begin
ApiBackend::app_password_delete(current_user, params[:delete]) api.app_password_delete(params[:delete])
rescue ApiBackend::ApiError rescue ApiBackend::ApiError
flash[:notice] = :failed flash[:notice] = :failed
end end
......
...@@ -65,7 +65,7 @@ class ApplicationController < ActionController::Base ...@@ -65,7 +65,7 @@ class ApplicationController < ActionController::Base
helper_method :recovery_email_set? helper_method :recovery_email_set?
def resource_enabled?(resource) def resource_enabled?(resource)
session[:possible_resources][resource].present? (session[:possible_resources]||{})[resource].present?
end end
helper_method :resource_enabled? helper_method :resource_enabled?
...@@ -75,7 +75,7 @@ class ApplicationController < ActionController::Base ...@@ -75,7 +75,7 @@ class ApplicationController < ActionController::Base
helper_method :any_resources_enabled? helper_method :any_resources_enabled?
def admin? def admin?
@is_admin ||= Admin::Enabled && Admin::Admins.include?(current_user) @is_admin ||= Admin::Enabled && session[:is_admin]
end end
helper_method :admin? helper_method :admin?
...@@ -124,8 +124,15 @@ class ApplicationController < ActionController::Base ...@@ -124,8 +124,15 @@ class ApplicationController < ActionController::Base
def reset_user_session def reset_user_session
session[:user_id] = nil session[:user_id] = nil
session[:is_admin] = false
session[:mail_crypt_recovery_token] = nil session[:mail_crypt_recovery_token] = nil
reset_session reset_session
session[:locale] = I18n.locale session[:locale] = I18n.locale
session[:api_token] = nil
update_session_expiry
end
def api_token
session[:api_token]
end end
end end
...@@ -9,270 +9,300 @@ module ApiBackend ...@@ -9,270 +9,300 @@ module ApiBackend
end end
end end
def self.sanitize(parts) class TheBackendImplementation
parts.map{|v| URI.encode(v)}.join("/") def sanitize(parts)
end parts.map{|v| URI.encode(v)}.join("/")
end
def initialize(controller)
@controller = controller
end
def session
@controller.session
end
def self.post(what, data) def merge_token(data)
res = RestClient::Resource.new("#{IAPI::Endpoint}/#{sanitize(what)}", unless session[:user_id]
:ssl_client_cert => IAPI::Cert, return data
:ssl_client_key => IAPI::Key, end
:ssl_ca_file => IAPI::CA, auth = {"token" => session[:api_token]}
:verify_ssl => OpenSSL::SSL::VERIFY_PEER) if Admin::Enabled
begin auth["admin_email"] = session[:user_id]
response = res.post(data.to_json, content_type: :json) else
res = JSON.parse(response) auth["email"] = session[:user_id]
if !res || res['result'] != "success"
puts "Expected success from iapi, but got #{res}"
raise ApiError.new("blocked #{res}")
end end
res auth.merge(data)
rescue RestClient::BadRequest => e
raise ApiError.new("400", JSON.parse(e.response)['errors'])
rescue => e
raise ApiError.new("#{e}")
end end
end
def self.get(what, data) def post(what, data = {})
res = RestClient::Resource.new("#{IAPI::Endpoint}/#{sanitize(what)}", data = merge_token(data)
:ssl_client_cert => IAPI::Cert, res = RestClient::Resource.new("#{IAPI::Endpoint}/#{sanitize(what)}",
:ssl_client_key => IAPI::Key, :ssl_client_cert => IAPI::Cert,
:ssl_ca_file => IAPI::CA, :ssl_client_key => IAPI::Key,
:verify_ssl => OpenSSL::SSL::VERIFY_PEER) :ssl_ca_file => IAPI::CA,
begin :verify_ssl => OpenSSL::SSL::VERIFY_PEER)
response = res.get(:params => data) begin
res = JSON.parse(response) response = res.post(data.to_json, content_type: :json)
if !res['result'] == "success" res = JSON.parse(response)
puts "Expected success from iapi, but got #{res}" if !res || res['result'] != "success"
raise ApiError.new("blocked #{res}") 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
res
rescue RestClient::BadRequest => e
raise ApiError.new("400", JSON.parse(e.response)['errors'])
rescue => e
raise ApiError.new("#{e}")
end end
end
def self.auth(user, pw, handoff, options = {}) def get(what, data = {})
if EmailValidation::immerda_email_conform(user) data = merge_token(data)
return post(['auth', if handoff then 'handoff' else 'master' end], puts data
{"email"=>user, "password" => pw}.merge(options)) res = RestClient::Resource.new("#{IAPI::Endpoint}/#{sanitize(what)}",
:ssl_client_cert => IAPI::Cert,
:ssl_client_key => IAPI::Key,
:ssl_ca_file => IAPI::CA,
:verify_ssl => OpenSSL::SSL::VERIFY_PEER)
begin
response = res.get(:params => data)
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 end
false
end
def self.pre_auth(email) def account_properties
get(['auth', 'pre_auth'], {'email' => email}) get(['users', 'properties'])
end end
def self.app_passwords(email) def app_passwords
get(['users', 'app_passwords'], {'email' => email}) get(['users', 'app_passwords'])
end end
def self.app_password_delete(email, pw_name) def app_password_delete(pw_name)
post(['users', 'app_password_delete'], {'email' => email, post(['users', 'app_password_delete'], {'pw_name' => pw_name})
'pw_name' => pw_name}) end
end
def self.app_password_create(email, pw, pw_name) def app_password_create(pw, pw_name)
post(['users', 'app_password_create'], {'email' => email, post(['users', 'app_password_create'], {'password' => pw,
'password' => pw, 'pw_name' => pw_name})
'pw_name' => pw_name}) end
end
def self.user_info(email, include_deleted=false) def check_invite(token)
get(['users_admin', 'info'], {'email' => email, 'include_deleted' => include_deleted }) get(['invites', 'validate'], {'token' => token})
end end
def self.user_update(email, action, value) def valid_new_email?(email)
post(['users_admin', 'update'], {'email' => email, 'action' => action, 'value' => value}) get(['users', 'check_valid_new_email'], {'email' => email})
end end
def self.check_invite(token) def list_domains
get(['invites', 'validate'], {'token' => token}) get(['domains', 'list'], {})['domains']
end end
def self.valid_new_email?(email) def get_domain(domain)
get(['users', 'check_valid_new_email'], {'email' => email}) get(['domains', 'get'], {'domain' => domain})
end end
def self.list(filter = nil, domain = nil, mailbox = nil, deleted = nil) def update_domain(domain, values)
get(['users_admin', 'list'], {'filter' => filter, post(['domains', 'update'], {'domain' => domain, 'values' => values})
'domain' => domain, end
'mailbox' => mailbox,
'deleted' => deleted,})
end
def self.list_public_domains def create_domain(domain, values)
@public_domains ||= get(['domains', 'list_public'], {})['domains'] post(['domains', 'create'], {'domain' => domain, 'values' => values})
end end
def self.list_domains def delete_domain(domain)
get(['domains', 'list'], {})['domains'] post(['domains', 'delete'], {'domain' => domain})
end end
def storagehosts
get(['mail', 'storagehosts'], {})
end
def self.get_domain(domain) def jabber_get_jid(jid, host = nil, include_deleted = false)
get(['domains', 'get'], {'domain' => domain}) get(['jabber', 'info'], {
end 'jid' => jid,
'host' => host,
'include_deleted' => include_deleted,
})
end
def self.update_domain(domain, values) def jabber_delete_jid(jid, password)
post(['domains', 'update'], {'domain' => domain, 'values' => values}) post(['jabber', 'delete'], {
end 'jid' => jid,
'account_password' => password,
})
end
def self.create_domain(domain, values) def jabber_create(jid_alias = nil, domain = nil)
post(['domains', 'create'], {'domain' => domain, 'values' => values}) post(['jabber', 'create'], {
end 'jid_alias' => jid_alias,
'domain' => domain,
})
end
def self.delete_domain(domain) def jabber_reset_password(jid)
post(['domains', 'delete'], {'domain' => domain}) post(['jabber', 'reset_password'], {
end 'jid' => jid,
def self.storagehosts })
get(['mail', 'storagehosts'], {}) end
end
def self.jabber_get_jid(email, jid, host = nil, include_deleted = false) def jabber_purge_jid(jid)
get(['jabber', 'info'], { post(['jabber', 'purge'], {
'email' => email, 'jid' => jid,
'jid' => jid, })
'host' => host, end
'include_deleted' => include_deleted,
})
end
def self.jabber_delete_jid(email, jid, password) def jabber_get_jids_admin(filter)
post(['jabber', 'delete'], { get(['jabber', 'list_admin'], filter)
'email' => email, end
'jid' => jid,
'account_password' => password,
})
end
def self.jabber_create(email, jid_alias = nil, domain = nil) def jabber_get_jids
post(['jabber', 'create'], { get(['jabber', 'list'])
'email' => email, end
'jid_alias' => jid_alias,
'domain' => domain,
})
end
def self.jabber_reset_password(email, jid) def jabber_domains_public
post(['jabber', 'reset_password'], { get(['jabber_domains', 'list_public'])['domains']
'email' => email, end
'jid' => jid, def jabber_domains
}) get(['jabber_domains', 'list'])['domains']
end end
def jabber_get_domain(domain)
get(['jabber_domains', 'get'],{
'domain' => domain,
})
end
def self.jabber_purge_jid(jid) def jabber_create_domain(domain, host, ispublic = false)
post(['jabber', 'purge'], { post(['jabber_domains', 'create'],{
'jid' => jid, 'domain' => domain,
}) 'host' => host,
end 'ispublic' => ispublic,
})
end
def self.jabber_get_jids(filter = {}) def jabber_delete_domain(domain)
get(['jabber', 'list'], filter) post(['jabber_domains', 'delete'],{
end 'domain' => domain,
})
end
def self.jabber_domains_public def jabber_update_domain(domain, host, ispublic = false)
get(['jabber_domains', 'list_public'], {})['domains'] post(['jabber_domains', 'update'],{
end 'domain' => domain,
def self.jabber_domains 'host' => host,
get(['jabber_domains', 'list'], {})['domains'] 'ispublic' => ispublic,
end })
def self.jabber_get_domain(domain) end
get(['jabber_domains', 'get'],{
'domain' => domain,
})
end
def self.jabber_create_domain(domain, host, ispublic = false) def jabber_get_jabberhosts
post(['jabber_domains', 'create'],{ get(['jabber_domains', 'jabberhosts'], {})['hosts']
'domain' => domain, end
'host' => host,
'ispublic' => ispublic,
})
end
def self.jabber_get_jabberhosts def change_password(old, pw)
get(['jabber_domains', 'jabberhosts'], {})['hosts'] post(['users', 'change_password'], {"current_password" => old, "new_password" => pw})
end end
def self.jabber_update_domain(domain, host, ispublic = false) def delete_account(pw)
post(['jabber_domains', 'update'],{ post(['users', 'delete_account'], {"password" => pw})
'domain' => domain, end
'host' => host,
'ispublic' => ispublic,
})
end
def self.jabber_delete_domain(domain) def mail_crypt_enable(pw)
post(['jabber_domains', 'delete'],{ post(['users', 'enable_mail_crypt'], {"password" => pw})
'domain' => domain, end
})
end
def self.change_password(user, old, pw) def enable_totp(name)
post(['users', 'change_password'], {"email"=>user, "current_password" => old, "new_password" => pw}) post(['users', 'enable_totp'], {'name' => name})
end end
def self.delete_account(user, pw) def get_totp_names
post(['users', 'delete_account'], {"email"=> user, "password" => pw}) get(['users', 'totp_names'])
end end
def self.mail_crypt_enable(user, pw) def delete_totp(name)
post(['users', 'enable_mail_crypt'], {"email"=> user, "password" => pw}) post(['users', 'delete_totp'], {'name' => name })
end end
def self.enable_totp(user, name) def mail_crypt_token(pw)
post(['users', 'enable_totp'], {"email"=> user, 'name' => name}) post(['users', 'generate_recovery_token'], {"password" => pw})
end end
def self.get_totp_names(user) def set_recovery_email(recovery, email_token, pass = nil)
get(['users', 'totp_names'], {"email" => user }) post(['users', 'set_recovery_email'], {"recovery_email" => recovery, 'email_recovery_token' => email_token, 'password' => pass})
end end
def self.delete_totp(user, name)
post(['users', 'delete_totp'], {"email" => user, 'name' => name })
end
def self.mail_crypt_token(user, pw) def create_new_mailbox(email, pw, mail_crypt_enabled, invite, recovery_email, recovery_token)
post(['users', 'generate_recovery_token'], {"email"=> user, "password" => pw}) post(['users', 'create_new_mailbox'], {"email" => email,
end "password" => pw,
"mail_crypt_enabled" => mail_crypt_enabled,
"invite" => invite,
"recovery_email" => recovery_email,
"keep_recovery_token" => recovery_token == 'yes',
"email_recovery_token" => recovery_token == 'email',
"language" => I18n.locale,
<