src/Http/Controllers/SsoController.php
<?php
namespace Goemktg\Seat\SeatDiscourse\Http\Controllers;
use Cviebrock\DiscoursePHP\SSOHelper;
use Goemktg\Seat\SeatDiscourse\Action\Discourse\Groups\Sync;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Seat\Web\Http\Controllers\Controller;
use Seat\Web\Models\Acl\Role;
//use Illumdinate\Contracts\Auth\Authenticatable as User;
//use Illuminate\Contracts\Config\Repository as Config;
//use Illuminate\Routing\Controller;
//use Illuminate\Support\Collection;
//use Seat\Web\Models\Acl\Role;
// temp
//use Illuminate\Support\Str;
/**
* Class SsoController.
*
* Controller to process the Discourse SSO request. There is a good bit of logic in here that almost feels like too
* much for a controller, but given that this is the only thing that this controller is doing, I am not going to break
* it out into some service class.
*
* @package Spinen\Discourse
*/
class SsoController extends Controller
{
/**
* Package configuration.
*
* @var Collection
*/
//protected $config;
/**
* SSOHelper Instance.
*
* @var SSOHelper
*/
protected $sso;
/**
* Authenticated user.
*
* @var User
*/
//protected $user;
/**
* SsoController constructor.
*
* @param SSOHelper $sso
*/
public function __construct(SSOHelper $sso)
{
$this->sso = $sso->setSecret(config('seatdiscourse.config.connect_secret'));
}
public function redirect()
{
if (! auth()->user()->email) {
return redirect()->route('seatcore::profile.view')->with('error', 'You must enter an email address to use the forum.');
}
return redirect()->away(config('seatdiscourse.config.url'));
}
/**
* Build out the extra parameters to send to Discourse.
*
* @return array
*/
protected function buildExtraParameters()
{
return [
// Groups to make sure that the user is part of in a comma-separated string
// NOTE: Groups cannot have spaces in their names & must already exist in Discourse
'add_groups' => $this->user->roles->map(function ($role) {
return str::studly($role->title);
})->implode(','),
// Boolean for user a Discourse admin, leave null to ignore
//'admin' => null,
// Full path to user's avatar image
'avatar_url' => 'http://image.eveonline.com/Character/' . $this->user->main_character_id . '_128.jpg',
// The avatar is cached, so this triggers an update
'avatar_force_update' => true,
// Content of the user's bio
//'bio' => null,
// Boolean for user a Discourse admin, leave null to ignore
//'moderator' => null,
// Full name on Discourse if the user is new or
// if SiteSetting.sso_overrides_name is set
'name' => $this->user->name,
// Groups to make sure that the user is *NOT* part of in a comma-separated string
// NOTE: Groups cannot have spaces in their names & must already exist in Discourse
// There is not a way to specify the exact list of groups that a user is in, so
// you may want to send the inverse of the 'add_groups'
'remove_groups' => Role::all()->diff($this->user->roles)->map(function ($role) {
return str::studly($role->title);
})->implode(','),
// If the email has not been verified, set this to true
'require_activation' => false,
// username on Discourse if the user is new or
// if SiteSetting.sso_overrides_username is set
'username' => $this->user->name,
];
}
/**
* Make boolean's into string.
*
* The Discourse SSO API does not accept 0 or 1 for false or true. You must send
* "false" or "true", so convert any boolean property to the string version.
*
* @param $property
* @return string
*/
public function castBooleansToString($property)
{
if (! is_bool($property)) {
return $property;
}
return ($property) ? 'true' : 'false';
}
/**
* Process the SSO login request from Discourse.
*
* @param Request $request
* @param \Goemktg\Seat\SeatDiscourse\Action\Discourse\Groups\Sync $sync
* @return mixed
*
* @throws \Cviebrock\DiscoursePHP\Exception\PayloadException
*/
public function login(Request $request, Sync $sync)
{
if(! auth()->user()->email){
return redirect()->route('seatcore::profile.view')->with('error', 'You must enter an email address to use the forum.');
}
//ToDo: Refactoring sync by replacing it with model events
$sync->execute();
/* TODO : fix this ( with setting - strict token check )
foreach ($request->user()->all_characters() as $char_info) {
dd($char_info->refresh_token());
}
foreach ($this->user->group->users as $user){
if (is_null($user->refresh_token))
return redirect()->route('profile.view')->with('error', 'One of your characters is missing its refresh token. Please login with him again');
}
*/
$this->user = $request->user();
if (! $this->sso->validatePayload($payload = $request->get('sso'), $request->get('sig'))) {
abort(403); //Forbidden
}
$query = $this->sso->getSignInString(
$this->sso->getNonce($payload),
$this->user->main_character_id,
$this->user->email,
$this->buildExtraParameters()
);
return redirect(str::finish(config('seatdiscourse.config.url'), '/') . 'session/sso_login?' . $query);
}
/**
* Check to see if property is null.
*
* @param string $property
* @return bool
*/
public function nullProperty($property)
{
return is_null($property);
}
/**
* Get the property from the user.
*
* If a string is passed in, then get it from the user object, otherwise, return what was given
*
* @param string $property
* @return mixed
*/
public function parseUserValue($property)
{
if (! is_string($property)) {
return $property;
}
return $this->user->{$property};
}
}