Test Failed
Push — master ( cd250e...0bf454 )
by
unknown
12:40
created

DefaultController::assessmentsConfigApiAction()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 7
nc 1
nop 0
dl 0
loc 12
ccs 0
cts 8
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * This file contains only the DefaultController class.
4
 */
5
6
declare(strict_types=1);
7
8
namespace AppBundle\Controller;
9
10
use AppBundle\Model\Edit;
11
use AppBundle\Repository\ProjectRepository;
12
use MediaWiki\OAuthClient\Client;
13
use MediaWiki\OAuthClient\ClientConfig;
14
use MediaWiki\OAuthClient\Consumer;
15
use MediaWiki\OAuthClient\Exception;
16
use Symfony\Component\HttpFoundation\JsonResponse;
17
use Symfony\Component\HttpFoundation\RedirectResponse;
18
use Symfony\Component\HttpFoundation\Request;
19
use Symfony\Component\HttpFoundation\Response;
20
use Symfony\Component\HttpFoundation\Session\Session;
21
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
22
use Symfony\Component\Routing\Annotation\Route;
23
24
/**
25
 * The DefaultController handles the homepage, about pages, and user authentication.
26
 */
27
class DefaultController extends XtoolsController
28
{
29
    /** @var Client The Oauth HTTP client. */
30
    protected $oauthClient;
31
32
    /**
33
     * Required to be defined by XtoolsController, though here it is unused.
34
     * @return string
35
     * @codeCoverageIgnore
36
     */
37
    public function getIndexRoute(): string
38
    {
39
        return 'homepage';
40
    }
41
42
    /**
43
     * Display the homepage.
44
     * @Route("/", name="homepage")
45
     * @Route("/index.php", name="homepageIndexPhp")
46
     * @return Response
47
     */
48 1
    public function indexAction(): Response
49
    {
50 1
        return $this->render('default/index.html.twig', [
51 1
            'xtPage' => 'home',
52
        ]);
53
    }
54
55
    /**
56
     * Diplay XTools' about page.
57
     * @Route("/about", name="aboutPage")
58
     * @Route("/info.php", name="info")
59
     * @return Response
60
     */
61 1
    public function aboutAction(): Response
62
    {
63 1
        return $this->render('default/about.html.twig', [
64 1
            'xtPage' => 'about',
65
        ]);
66
    }
67
68
    /**
69
     * Display some configuration details, when in development mode.
70
     * @Route("/config", name="configPage")
71
     * @return Response
72
     * @codeCoverageIgnore
73
     */
74
    public function configAction(): Response
75
    {
76
77
        if ('dev' !== $this->container->getParameter('kernel.environment')) {
78
            throw new NotFoundHttpException();
79
        }
80
81
        $params = $this->container->getParameterBag()->all();
0 ignored issues
show
Bug introduced by
The method getParameterBag() does not exist on Symfony\Component\Depend...tion\ContainerInterface. Did you maybe mean getParameter()? ( Ignorable by Annotation )

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

81
        $params = $this->container->/** @scrutinizer ignore-call */ getParameterBag()->all();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
82
83
        foreach (array_keys($params) as $key) {
84
            if (false !== strpos($key, 'password')) {
85
                $params[$key] = '<REDACTED>';
86
            }
87
        }
88
89
        // replace this example code with whatever you need
90
        return $this->render('default/config.html.twig', [
91
            'xtTitle' => 'Config',
92
            'xtPageTitle' => 'Config',
93
            'xtPage' => 'index',
94
            'dump' => print_r($params, true),
95
        ]);
96
    }
97
98
    /**
99
     * Redirect to the default project (or Meta) for Oauth authentication.
100
     * @Route("/login", name="login")
101
     * @return RedirectResponse
102
     * @throws Exception If initialization fails.
103
     */
104
    public function loginAction(): RedirectResponse
105
    {
106
        try {
107
            [ $next, $token ] = $this->getOauthClient()->initiate();
108
        } catch (Exception $oauthException) {
109
            throw $oauthException;
110
            // @TODO Make this work.
111
            //$this->addFlash('error', $oauthException->getMessage());
112
            //return $this->redirectToRoute('homepage');
113
        }
114
115
        // Save the request token to the session.
116
        /** @var Session $session */
117
        $session = $this->get('session');
118
        $session->set('oauth_request_token', $token);
119
        return new RedirectResponse($next);
120
    }
121
122
    /**
123
     * Receive authentication credentials back from the Oauth wiki.
124
     * @Route("/oauth_callback", name="oauth_callback")
125
     * @Route("/oauthredirector.php", name="old_oauth_callback")
126
     * @param Request $request The HTTP request.
127
     * @return RedirectResponse
128
     */
129 1
    public function oauthCallbackAction(Request $request): RedirectResponse
130
    {
131
        // Give up if the required GET params don't exist.
132 1
        if (!$request->get('oauth_verifier')) {
133 1
            throw $this->createNotFoundException('No OAuth verifier given.');
134
        }
135
136
        /** @var Session $session */
137
        $session = $this->get('session');
138
139
        // Complete authentication.
140
        $client = $this->getOauthClient();
141
        $token = $session->get('oauth_request_token');
142
143
        if (!is_a($token, \MediaWiki\OAuthClient\Token::class)) {
144
            $this->addFlashMessage('notice', 'error-login');
145
            return $this->redirectToRoute('homepage');
146
        }
147
148
        $verifier = $request->get('oauth_verifier');
149
        $accessToken = $client->complete($token, $verifier);
150
151
        // Store access token, and remove request token.
152
        $session->set('oauth_access_token', $accessToken);
153
        $session->remove('oauth_request_token');
154
155
        // Store user identity.
156
        $ident = $client->identify($accessToken);
157
        $session->set('logged_in_user', $ident);
158
159
        // Send back to homepage.
160
        return $this->redirectToRoute('homepage');
161
    }
162
163
    /**
164
     * Get an OAuth client, configured to the default project.
165
     * (This shouldn't really be in this class, but oh well.)
166
     * @return Client
167
     * @codeCoverageIgnore
168
     */
169
    protected function getOauthClient(): Client
170
    {
171
        if ($this->oauthClient instanceof Client) {
0 ignored issues
show
introduced by
$this->oauthClient is always a sub-type of MediaWiki\OAuthClient\Client.
Loading history...
172
            return $this->oauthClient;
173
        }
174
        $defaultProject = ProjectRepository::getProject(
175
            $this->getParameter('central_auth_project'),
176
            $this->container
177
        );
178
        $endpoint = $defaultProject->getUrl(false)
179
                    . $defaultProject->getScript()
180
                    . '?title=Special:OAuth';
181
        $conf = new ClientConfig($endpoint);
182
        $consumerKey = $this->getParameter('oauth_key');
183
        $consumerSecret =  $this->getParameter('oauth_secret');
184
        $conf->setConsumer(new Consumer($consumerKey, $consumerSecret));
185
        $this->oauthClient = new Client($conf);
186
        // Callback URL is hardcoded in the consumer registration.
187
        $this->oauthClient->setCallback('oob');
188
        return $this->oauthClient;
189
    }
190
191
    /**
192
     * Log out the user and return to the homepage.
193
     * @Route("/logout", name="logout")
194
     * @return RedirectResponse
195
     */
196 1
    public function logoutAction(): RedirectResponse
197
    {
198 1
        $this->get('session')->invalidate();
199 1
        return $this->redirectToRoute('homepage');
200
    }
201
202
    /************************ API endpoints ************************/
203
204
    /**
205
     * Get domain name, URL, and API URL of the given project.
206
     * @Route("/api/project/normalize/{project}", name="ProjectApiNormalize")
207
     * @return JsonResponse
208
     */
209
    public function normalizeProjectApiAction(): JsonResponse
210
    {
211
        return $this->getFormattedApiResponse([
212
            'domain' => $this->project->getDomain(),
213
            'url' => $this->project->getUrl(),
214
            'api' => $this->project->getApiUrl(),
215
            'database' => $this->project->getDatabaseName(),
216
        ]);
217
    }
218
219
    /**
220
     * Get all namespaces of the given project. This endpoint also does the same thing
221
     * as the /project/normalize endpoint, returning other basic info about the project.
222
     * @Route("/api/project/namespaces/{project}", name="ProjectApiNamespaces")
223
     * @return JsonResponse
224
     */
225 1
    public function namespacesApiAction(): JsonResponse
226
    {
227 1
        return $this->getFormattedApiResponse([
228 1
            'domain' => $this->project->getDomain(),
229 1
            'url' => $this->project->getUrl(),
230 1
            'api' => $this->project->getApiUrl(),
231 1
            'database' => $this->project->getDatabaseName(),
232 1
            'namespaces' => $this->project->getNamespaces(),
233
        ]);
234
    }
235
236
    /**
237
     * Get assessment data for a given project.
238
     * @Route("/api/project/assessments/{project}", name="ProjectApiAssessments")
239
     * @return JsonResponse
240
     */
241 1
    public function projectAssessmentsApiAction(): JsonResponse
242
    {
243 1
        return $this->getFormattedApiResponse([
244 1
            'project' => $this->project->getDomain(),
245 1
            'assessments' => $this->project->getPageAssessments()->getConfig(),
246
        ]);
247
    }
248
249
    /**
250
     * Get assessment data for all projects.
251
     * @Route("/api/project/assessments", name="ApiAssessmentsConfig")
252
     * @return JsonResponse
253
     */
254
    public function assessmentsConfigApiAction(): JsonResponse
255
    {
256
        // Here there is no Project, so we don't use XtoolsController::getFormattedApiResponse().
257
        $response = new JsonResponse();
258
        $response->setEncodingOptions(JSON_NUMERIC_CHECK);
259
        $response->setStatusCode(Response::HTTP_OK);
260
        $response->setData([
261
            'projects' => array_keys($this->container->getParameter('assessments')),
262
            'config' => $this->container->getParameter('assessments'),
263
        ]);
264
265
        return $response;
266
    }
267
268
    /**
269
     * Transform given wikitext to HTML using the XTools parser. Wikitext must be passed in as the query 'wikitext'.
270
     * @Route("/api/project/parser/{project}")
271
     * @return JsonResponse Safe HTML.
272
     */
273
    public function wikifyApiAction(): JsonResponse
274
    {
275
        return new JsonResponse(
276
            Edit::wikifyString($this->request->query->get('wikitext', ''), $this->project)
277
        );
278
    }
279
}
280