Completed
Push — develop ( 80a004...042002 )
by Stephen
11s
created

SsoController::loadConfigs()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 5
rs 9.4285
cc 1
eloc 3
nc 1
nop 1
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 some service class.
18
 *
19
 * @package Spinen\Discourse
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
    public function __construct(Config $config, SSOHelper $sso)
51
    {
52
        $this->loadConfigs($config);
53
54
        $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
    protected function loadConfigs(Config $config)
99
    {
100
        $this->config = collect($config->get('services.discourse'));
101
        $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
     */
111
    public function login(Request $request)
112
    {
113
        $this->user = $request->user();
114
        $access = $this->config->get('user')
115
                               ->get('access', null);
116
117
        if (! is_null($access) && ! $this->parseUserValue($access)) {
118
            abort(403); //Forbidden
119
        }
120
121
        if (! ($this->sso->validatePayload($payload = $request->get('sso'), $request->get('sig')))) {
122
            abort(403); //Forbidden
123
        }
124
125
        $query = $this->sso->getSignInString(
126
            $this->sso->getNonce($payload),
127
            $this->parseUserValue($this->config->get('user')
128
                                               ->get('external_id')),
129
            $this->parseUserValue($this->config->get('user')
130
                                               ->get('email')),
131
            $this->buildExtraParameters()
132
        );
133
134
        return redirect(str_finish($this->config->get('url'), '/').'session/sso_login?'.$query);
135
    }
136
137
    /**
138
     * Check to see if property is null
139
     *
140
     * @param string $property
141
     * @return bool
142
     */
143
    public function nullProperty($property)
144
    {
145
        return is_null($property);
146
    }
147
148
    /**
149
     * Get the property from the user
150
     *
151
     * If a string is passed in, then get it from the user object, otherwise, return what was given
152
     *
153
     * @param string $property
154
     * @return mixed
155
     */
156
    public function parseUserValue($property)
157
    {
158
        if (! is_string($property)) {
159
            return $property;
160
        }
161
162
        return $this->user->{$property};
163
    }
164
}
165