# SPDX-FileCopyrightText: 2020 IN COMMON Collective # # SPDX-License-Identifier: AGPL-3.0-or-later class WelcomeController < ApplicationController # GET / def index @map = Map.first @taxonomy = @map&.taxonomy @resources = Resource.order(:uuid).page params[:page] Rails.logger.info "WECLOME ///// #{@resources&.count || 0}" end # GET /authenticate(/:token) # Discourse SSO Authentication def authenticate validate_token_format! # Try an ongoing SSO or create a new one @sso = SSO::FromDiscourse.new(token: params[:token], nonce: session[params[:token]]) clear_current_session # Start SSO roundtrip if we're not passed a token if params[:token].nil? # Record this token and nonce in the session session[@sso.token] = @sso.nonce # Send to SSO authenticator redirect_to @sso.request_uri and return end # Validate authentication params from SSO begin @sso.parse(params) rescue ArgumentError => e Rails.logger.debug("SSO request failed: #{e.message}") return :forbidden end # Resolve SSO and finish authentication case @sso.status when :ok Rails.logger.info("Authentication succeeded!") find_or_create_current_user perform_background_jobs update_current_session when :unauthorized Rails.logger.info("Authentication failed!") end return :forbidden unless @current_user.present? # TODO add some memory of previously called URL and return there redirect_to '/my/dashboard' end # GET /dashboard def dashboard redirect_to '/authenticate' and return unless current_user.present? @stats = { counts: { resources: Resource.count, agents: Agent.count, categories: Category.count, sections: Section.count }, current_agent: { name: current_agent.name, uuid: current_agent.uuid, counts: { resources: current_agent.resources&.count, taxonomies: current_agent.taxonomies&.count, categories: current_agent.categories&.count, sectiions: current_agent.sections&.count } }, my_agents: current_user.agents.map { |a| { uuid: a.uuid, name: a.name } } } end # GET /logout def logout session.destroy render :index end private # Ensure nobody tries silly things with our session def validate_token_format! if params[:token].present? && !params[:token].match?(/[a-z0-9]{32}/) raise(ArgumentError, "Token invalid") end end # Remove any current session def clear_current_session Rails.logger.info("Removing current session (#{session[:current_user]})") session.destroy @current_user = nil end # Set @current_user to existing or new User record from SSO user info def find_or_create_current_user user_data = { external_id: @sso.user_info[:external_id], avatar_url: @sso.user_info[:avatar_url], email: @sso.user_info[:email], name: @sso.user_info[:name], username: @sso.user_info[:username] } @current_user = User.find_by(external_id: user_data[:external_id]) || begin Rails.logger.info('new user...') u = User.create(user_data) Rails.logger.info('created user %s' % u.inspect) u rescue Exception => e Rails.logger.warning("#{e.type}: #{e.message}") end user_data.reverse_merge!(@current_user.attributes.symbolize_keys) @current_user.update(user_data) if user_data != @current_user.attributes @current_user end # Update user agents def perform_background_jobs if @current_user.present? EnsureAgentJob.perform_later(@current_user, @sso.user_info[:groups].split(',')) end end # Save User ID and current agent in session def update_current_session if @current_user.present? session[:current_user] = @current_user[:external_id] session[:current_agent] = current_agent_name end end end