Feature: Single sign-on (SSO).
This commit is contained in:
parent
0afb105dd7
commit
33bef7123d
10 changed files with 242 additions and 252 deletions
|
@ -5,7 +5,7 @@ class ApplicationController < ActionController::Base
|
||||||
include ApplicationController::HandlesTransitions
|
include ApplicationController::HandlesTransitions
|
||||||
include ApplicationController::Authenticates
|
include ApplicationController::Authenticates
|
||||||
include ApplicationController::SetsHeaders
|
include ApplicationController::SetsHeaders
|
||||||
include ApplicationController::ChecksMaintainance
|
include ApplicationController::ChecksMaintenance
|
||||||
include ApplicationController::RendersModels
|
include ApplicationController::RendersModels
|
||||||
include ApplicationController::HasUser
|
include ApplicationController::HasUser
|
||||||
include ApplicationController::HasResponseExtentions
|
include ApplicationController::HasResponseExtentions
|
||||||
|
|
|
@ -50,15 +50,6 @@ module ApplicationController::Authenticates
|
||||||
return authentication_check_prerequesits(user, 'session', auth_param) if user
|
return authentication_check_prerequesits(user, 'session', auth_param) if user
|
||||||
end
|
end
|
||||||
|
|
||||||
# check sso based authentication
|
|
||||||
sso_user = User.sso(params)
|
|
||||||
if sso_user
|
|
||||||
if authentication_check_prerequesits(sso_user, 'session', auth_param)
|
|
||||||
session[:persistent] = true
|
|
||||||
return sso_user
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# check http basic based authentication
|
# check http basic based authentication
|
||||||
authenticate_with_http_basic do |username, password|
|
authenticate_with_http_basic do |username, password|
|
||||||
request.session_options[:skip] = true # do not send a session cookie
|
request.session_options[:skip] = true # do not send a session cookie
|
||||||
|
@ -135,21 +126,37 @@ module ApplicationController::Authenticates
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def authenticate_with_password
|
||||||
|
user = User.authenticate(params[:username], params[:password])
|
||||||
|
raise Exceptions::NotAuthorized, 'Wrong Username or Password combination.' if !user
|
||||||
|
|
||||||
|
session.delete(:switched_from_user_id)
|
||||||
|
authentication_check_prerequesits(user, 'session', {})
|
||||||
|
end
|
||||||
|
|
||||||
|
def authenticate_with_sso
|
||||||
|
user = begin
|
||||||
|
login = request.env['REMOTE_USER'] ||
|
||||||
|
request.env['HTTP_REMOTE_USER'] ||
|
||||||
|
request.headers['X-Forwarded-User']
|
||||||
|
|
||||||
|
User.lookup(login: login&.downcase)
|
||||||
|
end
|
||||||
|
|
||||||
|
raise Exceptions::NotAuthorized, 'no valid session' if !user
|
||||||
|
|
||||||
|
session.delete(:switched_from_user_id)
|
||||||
|
authentication_check_prerequesits(user, 'session', {})
|
||||||
|
end
|
||||||
|
|
||||||
def authentication_check_prerequesits(user, auth_type, auth_param)
|
def authentication_check_prerequesits(user, auth_type, auth_param)
|
||||||
if check_maintenance_only(user)
|
raise Exceptions::NotAuthorized, 'Maintenance mode enabled!' if in_maintenance_mode?(user)
|
||||||
raise Exceptions::NotAuthorized, 'Maintenance mode enabled!'
|
|
||||||
end
|
|
||||||
|
|
||||||
raise Exceptions::NotAuthorized, 'User is inactive!' if !user.active
|
raise Exceptions::NotAuthorized, 'User is inactive!' if !user.active
|
||||||
|
raise Exceptions::NotAuthorized, 'Not authorized (user)!' if auth_param[:permission] && !user.permissions?(auth_param[:permission])
|
||||||
# check scopes / permission check
|
|
||||||
if auth_param[:permission] && !user.permissions?(auth_param[:permission])
|
|
||||||
raise Exceptions::NotAuthorized, 'Not authorized (user)!'
|
|
||||||
end
|
|
||||||
|
|
||||||
current_user_set(user, auth_type)
|
current_user_set(user, auth_type)
|
||||||
user_device_log(user, auth_type)
|
user_device_log(user, auth_type)
|
||||||
logger.debug { "#{auth_type} for '#{user.login}'" }
|
logger.debug { "#{auth_type} for '#{user.login}'" }
|
||||||
true
|
user
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,16 +1,9 @@
|
||||||
module ApplicationController::ChecksMaintainance
|
module ApplicationController::ChecksMaintenance
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def check_maintenance(user)
|
def in_maintenance_mode?(user)
|
||||||
return false if !check_maintenance_only(user)
|
|
||||||
|
|
||||||
raise Exceptions::NotAuthorized, 'Maintenance mode enabled!'
|
|
||||||
end
|
|
||||||
|
|
||||||
# check maintenance mode
|
|
||||||
def check_maintenance_only(user)
|
|
||||||
return false if Setting.get('maintenance_mode') != true
|
return false if Setting.get('maintenance_mode') != true
|
||||||
return false if user.permissions?('admin.maintenance')
|
return false if user.permissions?('admin.maintenance')
|
||||||
|
|
|
@ -2,112 +2,32 @@
|
||||||
|
|
||||||
class SessionsController < ApplicationController
|
class SessionsController < ApplicationController
|
||||||
prepend_before_action :authentication_check, only: %i[switch_to_user list delete]
|
prepend_before_action :authentication_check, only: %i[switch_to_user list delete]
|
||||||
skip_before_action :verify_csrf_token, only: %i[show destroy create_omniauth failure_omniauth create_sso]
|
skip_before_action :verify_csrf_token, only: %i[show destroy create_omniauth failure_omniauth]
|
||||||
|
|
||||||
# "Create" a login, aka "log the user in"
|
# "Create" a login, aka "log the user in"
|
||||||
def create
|
def create
|
||||||
|
user = authenticate_with_password
|
||||||
# in case, remove switched_from_user_id
|
initiate_session_for(user)
|
||||||
session[:switched_from_user_id] = nil
|
|
||||||
|
|
||||||
# authenticate user
|
|
||||||
user = User.authenticate(params[:username], params[:password])
|
|
||||||
|
|
||||||
# check maintenance mode
|
|
||||||
check_maintenance(user)
|
|
||||||
|
|
||||||
# auth failed
|
|
||||||
raise Exceptions::NotAuthorized, 'Wrong Username or Password combination.' if !user
|
|
||||||
|
|
||||||
# remember me - set session cookie to expire later
|
|
||||||
expire_after = nil
|
|
||||||
if params[:remember_me]
|
|
||||||
expire_after = 1.year
|
|
||||||
end
|
|
||||||
request.env['rack.session.options'][:expire_after] = expire_after
|
|
||||||
|
|
||||||
# set session user
|
|
||||||
current_user_set(user)
|
|
||||||
|
|
||||||
# log device
|
|
||||||
return if !user_device_log(user, 'session')
|
|
||||||
|
|
||||||
# log new session
|
|
||||||
user.activity_stream_log('session started', user.id, true)
|
|
||||||
|
|
||||||
# add session user assets
|
|
||||||
assets = {}
|
|
||||||
assets = user.assets(assets)
|
|
||||||
|
|
||||||
# auto population of default collections
|
|
||||||
collections, assets = SessionHelper.default_collections(user, assets)
|
|
||||||
|
|
||||||
# get models
|
|
||||||
models = SessionHelper.models(user)
|
|
||||||
|
|
||||||
# sessions created via this
|
|
||||||
# controller are persistent
|
|
||||||
session[:persistent] = true
|
|
||||||
|
|
||||||
# return new session data
|
# return new session data
|
||||||
render status: :created,
|
render status: :created,
|
||||||
json: {
|
json: SessionHelper.json_hash(user).merge(config: config_frontend)
|
||||||
session: user,
|
|
||||||
config: config_frontend,
|
|
||||||
models: models,
|
|
||||||
collections: collections,
|
|
||||||
assets: assets,
|
|
||||||
}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
|
user = authentication_check_only || authenticate_with_sso
|
||||||
user_id = nil
|
initiate_session_for(user)
|
||||||
|
|
||||||
# no valid sessions
|
|
||||||
if session[:user_id]
|
|
||||||
user_id = session[:user_id]
|
|
||||||
end
|
|
||||||
|
|
||||||
if !user_id || !User.exists?(user_id)
|
|
||||||
# get models
|
|
||||||
models = SessionHelper.models()
|
|
||||||
|
|
||||||
render json: {
|
|
||||||
error: 'no valid session',
|
|
||||||
config: config_frontend,
|
|
||||||
models: models,
|
|
||||||
collections: {
|
|
||||||
Locale.to_app_model => Locale.where(active: true)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
# Save the user ID in the session so it can be used in
|
|
||||||
# subsequent requests
|
|
||||||
user = User.find(user_id)
|
|
||||||
|
|
||||||
# log device
|
|
||||||
return if !user_device_log(user, 'session')
|
|
||||||
|
|
||||||
# add session user assets
|
|
||||||
assets = {}
|
|
||||||
assets = user.assets(assets)
|
|
||||||
|
|
||||||
# auto population of default collections
|
|
||||||
collections, assets = SessionHelper.default_collections(user, assets)
|
|
||||||
|
|
||||||
# get models
|
|
||||||
models = SessionHelper.models(user)
|
|
||||||
|
|
||||||
# return current session
|
# return current session
|
||||||
|
render json: SessionHelper.json_hash(user).merge(config: config_frontend)
|
||||||
|
rescue Exceptions::NotAuthorized => e
|
||||||
|
raise if e.message != 'no valid session'
|
||||||
|
|
||||||
render json: {
|
render json: {
|
||||||
session: user,
|
error: e.message,
|
||||||
config: config_frontend,
|
config: config_frontend,
|
||||||
models: models,
|
models: SessionHelper.models,
|
||||||
collections: collections,
|
collections: { Locale.to_app_model => Locale.where(active: true) }
|
||||||
assets: assets,
|
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -146,8 +66,7 @@ class SessionsController < ApplicationController
|
||||||
authorization = Authorization.create_from_hash(auth, current_user)
|
authorization = Authorization.create_from_hash(auth, current_user)
|
||||||
end
|
end
|
||||||
|
|
||||||
# check maintenance mode
|
if in_maintenance_mode?(authorization.user)
|
||||||
if check_maintenance_only(authorization.user)
|
|
||||||
redirect_to '/#'
|
redirect_to '/#'
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
@ -169,36 +88,6 @@ class SessionsController < ApplicationController
|
||||||
raise Exceptions::UnprocessableEntity, "Message from #{params[:strategy]}: #{params[:message]}"
|
raise Exceptions::UnprocessableEntity, "Message from #{params[:strategy]}: #{params[:message]}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_sso
|
|
||||||
|
|
||||||
# in case, remove switched_from_user_id
|
|
||||||
session[:switched_from_user_id] = nil
|
|
||||||
|
|
||||||
user = User.sso(params)
|
|
||||||
|
|
||||||
# Log the authorizing user in.
|
|
||||||
if user
|
|
||||||
|
|
||||||
# check maintenance mode
|
|
||||||
if check_maintenance_only(user)
|
|
||||||
redirect_to '/#'
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
# set current session user
|
|
||||||
current_user_set(user)
|
|
||||||
|
|
||||||
# log new session
|
|
||||||
user.activity_stream_log('session started', user.id, true)
|
|
||||||
|
|
||||||
# remember last login date
|
|
||||||
user.update_last_login
|
|
||||||
end
|
|
||||||
|
|
||||||
# redirect to app
|
|
||||||
redirect_to '/#'
|
|
||||||
end
|
|
||||||
|
|
||||||
# "switch" to user
|
# "switch" to user
|
||||||
def switch_to_user
|
def switch_to_user
|
||||||
permission_check(['admin.session', 'admin.user'])
|
permission_check(['admin.session', 'admin.user'])
|
||||||
|
@ -308,6 +197,12 @@ class SessionsController < ApplicationController
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def initiate_session_for(user)
|
||||||
|
request.env['rack.session.options'][:expire_after] = 1.year if params[:remember_me]
|
||||||
|
session[:persistent] = true
|
||||||
|
user.activity_stream_log('session started', user.id, true)
|
||||||
|
end
|
||||||
|
|
||||||
def config_frontend
|
def config_frontend
|
||||||
|
|
||||||
# config
|
# config
|
||||||
|
@ -333,4 +228,5 @@ class SessionsController < ApplicationController
|
||||||
|
|
||||||
config
|
config
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -333,27 +333,6 @@ returns
|
||||||
|
|
||||||
=begin
|
=begin
|
||||||
|
|
||||||
authenticate user again sso
|
|
||||||
|
|
||||||
result = User.sso(sso_params)
|
|
||||||
|
|
||||||
returns
|
|
||||||
|
|
||||||
result = user_model # user model if authentication was successfully
|
|
||||||
|
|
||||||
=end
|
|
||||||
|
|
||||||
def self.sso(params)
|
|
||||||
|
|
||||||
# try to login against configure auth backends
|
|
||||||
user_auth = Sso.check(params)
|
|
||||||
return if !user_auth
|
|
||||||
|
|
||||||
user_auth
|
|
||||||
end
|
|
||||||
|
|
||||||
=begin
|
|
||||||
|
|
||||||
create user from from omni auth hash
|
create user from from omni auth hash
|
||||||
|
|
||||||
result = User.create_from_hash!(hash)
|
result = User.create_from_hash!(hash)
|
||||||
|
|
|
@ -5,9 +5,6 @@ Zammad::Application.routes.draw do
|
||||||
match '/auth/:provider/callback', to: 'sessions#create_omniauth', via: %i[post get puts delete]
|
match '/auth/:provider/callback', to: 'sessions#create_omniauth', via: %i[post get puts delete]
|
||||||
match '/auth/failure', to: 'sessions#failure_omniauth', via: %i[post get]
|
match '/auth/failure', to: 'sessions#failure_omniauth', via: %i[post get]
|
||||||
|
|
||||||
# sso
|
|
||||||
match '/auth/sso', to: 'sessions#create_sso', via: %i[post get]
|
|
||||||
|
|
||||||
# sessions
|
# sessions
|
||||||
match api_path + '/signin', to: 'sessions#create', via: :post
|
match api_path + '/signin', to: 'sessions#create', via: :post
|
||||||
match api_path + '/signshow', to: 'sessions#show', via: %i[get post]
|
match api_path + '/signshow', to: 'sessions#show', via: %i[get post]
|
||||||
|
|
|
@ -1,8 +1,20 @@
|
||||||
module SessionHelper
|
module SessionHelper
|
||||||
def self.default_collections(user, assets = {})
|
def self.json_hash(user)
|
||||||
|
collections, assets = default_collections(user)
|
||||||
|
|
||||||
|
{
|
||||||
|
session: user,
|
||||||
|
models: models(user),
|
||||||
|
collections: collections,
|
||||||
|
assets: assets,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.default_collections(user)
|
||||||
|
|
||||||
# auto population collections, store all here
|
# auto population collections, store all here
|
||||||
default_collection = {}
|
default_collection = {}
|
||||||
|
assets = user.assets({})
|
||||||
|
|
||||||
# load collections to deliver from external files
|
# load collections to deliver from external files
|
||||||
dir = File.expand_path('..', __dir__)
|
dir = File.expand_path('..', __dir__)
|
||||||
|
|
53
lib/sso.rb
53
lib/sso.rb
|
@ -1,53 +0,0 @@
|
||||||
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
|
|
||||||
|
|
||||||
class Sso
|
|
||||||
include ApplicationLib
|
|
||||||
|
|
||||||
=begin
|
|
||||||
|
|
||||||
authenticate user via username and password
|
|
||||||
|
|
||||||
result = Sso.check( params )
|
|
||||||
|
|
||||||
returns
|
|
||||||
|
|
||||||
result = user_model # if authentication was successfully
|
|
||||||
|
|
||||||
=end
|
|
||||||
|
|
||||||
def self.check(params)
|
|
||||||
|
|
||||||
# use std. auth backends
|
|
||||||
config = [
|
|
||||||
{
|
|
||||||
adapter: 'Sso::Env',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
# added configured backends
|
|
||||||
Setting.where( area: 'Security::SSO' ).each do |setting|
|
|
||||||
if setting.state_current[:value]
|
|
||||||
config.push setting.state_current[:value]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# try to login against configure auth backends
|
|
||||||
user_auth = nil
|
|
||||||
config.each do |config_item|
|
|
||||||
next if !config_item[:adapter]
|
|
||||||
|
|
||||||
user_auth = config_item[:adapter].constantize.check( params, config_item )
|
|
||||||
|
|
||||||
# auth not ok
|
|
||||||
next if !user_auth
|
|
||||||
|
|
||||||
Rails.logger.info "Authentication against #{config_item[:adapter]} for user #{user_auth.login} ok."
|
|
||||||
|
|
||||||
# remember last login date
|
|
||||||
user_auth.update_last_login
|
|
||||||
|
|
||||||
return user_auth
|
|
||||||
end
|
|
||||||
nil
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,19 +0,0 @@
|
||||||
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
|
|
||||||
|
|
||||||
module Sso::Env
|
|
||||||
def self.check( _params, _config_item )
|
|
||||||
|
|
||||||
# try to find user based on login
|
|
||||||
if ENV['REMOTE_USER']
|
|
||||||
user = User.where( login: ENV['REMOTE_USER'], active: true ).first
|
|
||||||
return user if user
|
|
||||||
end
|
|
||||||
|
|
||||||
if ENV['HTTP_REMOTE_USER']
|
|
||||||
user = User.where( login: ENV['HTTP_REMOTE_USER'], active: true ).first
|
|
||||||
return user if user
|
|
||||||
end
|
|
||||||
|
|
||||||
false
|
|
||||||
end
|
|
||||||
end
|
|
178
spec/requests/session_spec.rb
Normal file
178
spec/requests/session_spec.rb
Normal file
|
@ -0,0 +1,178 @@
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe 'Sessions endpoints', type: :request do
|
||||||
|
# The frontend sends a device fingerprint in the request parameters during authentication
|
||||||
|
# (as part of App.Auth.loginCheck() and App.WebSocket.auth()).
|
||||||
|
#
|
||||||
|
# Without this parameter, the controller will raise a 422 Unprocessable Entity error
|
||||||
|
# (in ApplicationController::HandlesDevices#user_device_log).
|
||||||
|
let(:fingerprint) { { fingerprint: 'foo' } }
|
||||||
|
|
||||||
|
describe 'GET /api/v1/signshow (single sign-on)' do
|
||||||
|
context 'with invalid user login' do
|
||||||
|
let(:login) { User.pluck(:login).max.next }
|
||||||
|
|
||||||
|
context 'in "REMOTE_USER" request env var' do
|
||||||
|
let(:env) { { 'REMOTE_USER' => login } }
|
||||||
|
|
||||||
|
it 'returns invalid session response' do
|
||||||
|
get '/api/v1/signshow', as: :json, env: env, params: fingerprint
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:ok)
|
||||||
|
expect(json_response)
|
||||||
|
.to include('error' => 'no valid session')
|
||||||
|
.and not_include('session')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'in "HTTP_REMOTE_USER" request env var' do
|
||||||
|
let(:env) { { 'HTTP_REMOTE_USER' => login } }
|
||||||
|
|
||||||
|
it 'returns invalid session response' do
|
||||||
|
get '/api/v1/signshow', as: :json, env: env, params: fingerprint
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:ok)
|
||||||
|
expect(json_response)
|
||||||
|
.to include('error' => 'no valid session')
|
||||||
|
.and not_include('session')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'in "X-Forwarded-User" request header' do
|
||||||
|
let(:headers) { { 'X-Forwarded-User' => login } }
|
||||||
|
|
||||||
|
it 'returns invalid session response' do
|
||||||
|
get '/api/v1/signshow', as: :json, headers: headers, params: fingerprint
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:ok)
|
||||||
|
expect(json_response)
|
||||||
|
.to include('error' => 'no valid session')
|
||||||
|
.and not_include('session')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with valid user login' do
|
||||||
|
let(:user) { User.last }
|
||||||
|
let(:login) { user.login }
|
||||||
|
|
||||||
|
context 'in Maintenance Mode' do
|
||||||
|
before { Setting.set('maintenance_mode', true) }
|
||||||
|
|
||||||
|
context 'in "REMOTE_USER" request env var' do
|
||||||
|
let(:env) { { 'REMOTE_USER' => login } }
|
||||||
|
|
||||||
|
it 'returns 401 unauthorized' do
|
||||||
|
get '/api/v1/signshow', as: :json, env: env, params: fingerprint
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:unauthorized)
|
||||||
|
expect(json_response).to include('error' => 'Maintenance mode enabled!')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'in "HTTP_REMOTE_USER" request env var' do
|
||||||
|
let(:env) { { 'HTTP_REMOTE_USER' => login } }
|
||||||
|
|
||||||
|
it 'returns 401 unauthorized' do
|
||||||
|
get '/api/v1/signshow', as: :json, env: env, params: fingerprint
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:unauthorized)
|
||||||
|
expect(json_response).to include('error' => 'Maintenance mode enabled!')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'in "X-Forwarded-User" request header' do
|
||||||
|
let(:headers) { { 'X-Forwarded-User' => login } }
|
||||||
|
|
||||||
|
it 'returns 401 unauthorized' do
|
||||||
|
get '/api/v1/signshow', as: :json, headers: headers, params: fingerprint
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:unauthorized)
|
||||||
|
expect(json_response).to include('error' => 'Maintenance mode enabled!')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'in "REMOTE_USER" request env var' do
|
||||||
|
let(:env) { { 'REMOTE_USER' => login } }
|
||||||
|
|
||||||
|
it 'returns a new user-session response' do
|
||||||
|
get '/api/v1/signshow', as: :json, env: env, params: fingerprint
|
||||||
|
|
||||||
|
expect(json_response)
|
||||||
|
.to include('session' => hash_including('login' => login))
|
||||||
|
.and not_include('error')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'sets the :user_id session parameter' do
|
||||||
|
expect { get '/api/v1/signshow', as: :json, env: env, params: fingerprint }
|
||||||
|
.to change { request&.session&.fetch(:user_id) }.to(user.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'sets the :persistent session parameter' do
|
||||||
|
expect { get '/api/v1/signshow', as: :json, env: env, params: fingerprint }
|
||||||
|
.to change { request&.session&.fetch(:persistent) }.to(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'adds an activity stream entry for the user’s session' do
|
||||||
|
expect { get '/api/v1/signshow', as: :json, env: env, params: fingerprint }
|
||||||
|
.to change(ActivityStream, :count).by(1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'in "HTTP_REMOTE_USER" request env var' do
|
||||||
|
let(:env) { { 'HTTP_REMOTE_USER' => login } }
|
||||||
|
|
||||||
|
it 'returns a new user-session response' do
|
||||||
|
get '/api/v1/signshow', as: :json, env: env, params: fingerprint
|
||||||
|
|
||||||
|
expect(json_response)
|
||||||
|
.to include('session' => hash_including('login' => login))
|
||||||
|
.and not_include('error')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'sets the :user_id session parameter' do
|
||||||
|
expect { get '/api/v1/signshow', as: :json, env: env, params: fingerprint }
|
||||||
|
.to change { request&.session&.fetch(:user_id) }.to(user.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'sets the :persistent session parameter' do
|
||||||
|
expect { get '/api/v1/signshow', as: :json, env: env, params: fingerprint }
|
||||||
|
.to change { request&.session&.fetch(:persistent) }.to(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'adds an activity stream entry for the user’s session' do
|
||||||
|
expect { get '/api/v1/signshow', as: :json, env: env, params: fingerprint }
|
||||||
|
.to change(ActivityStream, :count).by(1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'in "X-Forwarded-User" request header' do
|
||||||
|
let(:headers) { { 'X-Forwarded-User' => login } }
|
||||||
|
|
||||||
|
it 'returns a new user-session response' do
|
||||||
|
get '/api/v1/signshow', as: :json, headers: headers, params: fingerprint
|
||||||
|
|
||||||
|
expect(json_response)
|
||||||
|
.to include('session' => hash_including('login' => login))
|
||||||
|
.and not_include('error')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'sets the :user_id session parameter on the client' do
|
||||||
|
expect { get '/api/v1/signshow', as: :json, headers: headers, params: fingerprint }
|
||||||
|
.to change { request&.session&.fetch(:user_id) }.to(user.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'sets the :persistent session parameter' do
|
||||||
|
expect { get '/api/v1/signshow', as: :json, headers: headers, params: fingerprint }
|
||||||
|
.to change { request&.session&.fetch(:persistent) }.to(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'adds an activity stream entry for the user’s session' do
|
||||||
|
expect { get '/api/v1/signshow', as: :json, headers: headers, params: fingerprint }
|
||||||
|
.to change(ActivityStream, :count).by(1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue