Completed
Pull Request — develop (#17)
by Stephen
02:38
created

SsoController::buildExtraParameters()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 1
eloc 6
c 3
b 0
f 0
nc 1
nop 0
dl 0
loc 8
ccs 0
cts 7
cp 0
crap 2
rs 10
1
<?php
2
3
namespace Spinen\Discourse\Controllers;
4
5
use Cviebrock\DiscoursePHP\SSOHelper;
6
use Illuminate\Contracts\Auth\Authenticatable as User;
7
use Illuminate\Contracts\Config\Repository as Config;
8
use Illuminate\Http\Request;
9
use Illuminate\Routing\Controller;
10
use Illuminate\Support\Collection;
11
12
/**
13
 * Class SsoController
14
 *
15
 * Controller to process the Discourse SSO request.  There is a good bit of logic in here that almost feels like too
16
 * much for a controller, but given that this is the only thing that this controller is doing, I am not going to break
17
 * it out into a service class.
18
 *
19
 * @package Spinen\Discourse\Controllers
20
 */
21
class SsoController extends Controller
22
{
23
    /**
24
     * Package configuration
25
     *
26
     * @var Collection
27
     */
28
    protected $config;
29
30
    /**
31
     * SSOHelper Instance
32
     *
33
     * @var SSOHelper
34
     */
35
    protected $sso;
36
37
    /**
38
     * Authenticated user
39
     *
40
     * @var User
41
     */
42
    protected $user;
43
44
    /**
45
     * SsoController constructor.
46
     *
47
     * @param Config $config
48
     * @param SSOHelper $sso
49
     */
50 4
    public function __construct(Config $config, SSOHelper $sso)
51
    {
52 4
        $this->loadConfigs($config);
53
54 4
        $this->sso = $sso->setSecret($this->config->get('secret'));
55
    }
56
57
    /**
58
     * Build out the extra parameters to send to Discourse
59
     *
60
     * @return array
61
     */
62
    protected function buildExtraParameters()
63
    {
64
        return $this->config->get('user')
65
                            ->except(['access', 'email', 'external_id'])
66
                            ->reject([$this, 'nullProperty'])
67
                            ->map([$this, 'parseUserValue'])
68
                            ->map([$this, 'castBooleansToString'])
69
                            ->toArray();
70
    }
71
72
    /**
73
     * Make boolean's into string
74
     *
75
     * The Discourse SSO API does not accept 0 or 1 for false or true.  You must send
76
     * "false" or "true", so convert any boolean property to the string version.
77
     *
78
     * @param $property
79
     *
80
     * @return string
81
     */
82
    public function castBooleansToString($property)
83
    {
84
        if (! is_bool($property)) {
85
            return $property;
86
        }
87
88
        return ($property) ? 'true' : 'false';
89
    }
90
91
    /**
92
     * Cache the configs on the object as a collection
93
     *
94
     * The 'user' property will be an array, so go ahead and convert it to a collection
95
     *
96
     * @param Config $config
97
     */
98 4
    protected function loadConfigs(Config $config)
99
    {
100 4
        $this->config = collect($config->get('services.discourse'));
101 4
        $this->config->put('user', collect($this->config->get('user')));
102
    }
103
104
    /**
105
     * Process the SSO login request from Discourse
106
     *
107
     * @param Request $request
108
     *
109
     * @return mixed
110
     * @throws 403
111
     */
112 3
    public function login(Request $request)
113
    {
114 3
        $this->user = $request->user();
115 3
        $access = $this->config->get('user')
116 3
                               ->get('access', null);
117
118 3
        if (! is_null($access) && ! $this->parseUserValue($access)) {
119 1
            abort(403); //Forbidden
120
        }
121
122 2
        if (! ($this->sso->validatePayload($payload = $request->get('sso'), $request->get('sig')))) {
123 2
            abort(403); //Forbidden
124
        }
125
126
        $query = $this->sso->getSignInString(
127
            $this->sso->getNonce($payload),
128
            $this->parseUserValue($this->config->get('user')
129
                                               ->get('external_id')),
130
            $this->parseUserValue($this->config->get('user')
131
                                               ->get('email')),
132
            $this->buildExtraParameters()
133
        );
134
135
        return redirect(str_finish($this->config->get('url'), '/').'session/sso_login?'.$query);
0 ignored issues
show
Bug introduced by
The function str_finish was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

135
        return redirect(/** @scrutinizer ignore-call */ str_finish($this->config->get('url'), '/').'session/sso_login?'.$query);
Loading history...
136
    }
137
138
    /**
139
     * Check to see if property is null
140
     *
141
     * @param string $property
142
     * @return bool
143
     */
144
    public function nullProperty($property)
145
    {
146
        return is_null($property);
147
    }
148
149
    /**
150
     * Get the property from the user
151
     *
152
     * If a string is passed in, then get it from the user object, otherwise, return what was given
153
     *
154
     * @param string $property
155
     * @return mixed
156
     */
157 1
    public function parseUserValue($property)
158
    {
159 1
        if (! is_string($property)) {
1 ignored issue
show
introduced by
The condition is_string($property) is always true.
Loading history...
160
            return $property;
161
        }
162
163 1
        return $this->user->{$property};
164
    }
165
}
166