1<?php
2
3// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the GNU Affero General Public License v3.0.
4// See the LICENCE file in the repository root for full licence text.
5
6namespace App\Libraries;
7
8use App\Http\Middleware\RequireScopes;
9use Illuminate\Auth\Middleware\Authenticate;
10
11class ApidocRouteHelper
12{
13 private $routeScopes = [];
14
15 public static function scopeBadge($scope)
16 {
17 $scopeLower = strtolower($scope);
18
19 return link_to(
20 "#scope-{$scopeLower}",
21 $scope,
22 ['class' => "badge badge-scope badge-scope-{$scopeLower}"],
23 );
24 }
25
26
27 public static function instance()
28 {
29 static $instance;
30
31 if ($instance === null) {
32 $instance = new static();
33 }
34
35 return $instance;
36 }
37
38 private static function keyFor(array $methods, string $uri)
39 {
40 return RouteScopesHelper::keyForMethods($methods).'@'.$uri;
41 }
42
43 private static function requiresAuthentication(array $route)
44 {
45 return !(
46 in_array('GET', $route['methods'], true)
47 && starts_with("{$route['uri']}/", RequireScopes::NO_TOKEN_REQUIRED)
48 );
49 }
50
51 private function __construct()
52 {
53 $routeScopesHelper = new RouteScopesHelper();
54 $routeScopesHelper->loadRoutes();
55
56 foreach ($routeScopesHelper->toArray() as $route) {
57 // apidoc doesn't contain HEAD.
58 if (in_array('HEAD', $route['methods'], true)) {
59 $route['methods'] = array_filter($route['methods'], function ($method) {
60 return $method !== 'HEAD';
61 });
62 }
63
64 if (static::requiresAuthentication($route)) {
65 if (empty($route['scopes'])) {
66 $route['scopes'][] = 'lazer'; // not osu!lazer to make the css handling simpler.
67 }
68
69 $route['scopes'] = array_filter($route['scopes'], function ($scope) {
70 return $scope !== 'any';
71 });
72
73 // anything that will list scopes will require OAuth.
74 array_unshift($route['scopes'], 'OAuth');
75 } else {
76 $route['scopes'] = [];
77 }
78
79 $route['auth'] = in_array(Authenticate::class, $route['middlewares'], true);
80
81 $this->routeScopes[static::keyFor($route['methods'], $route['uri'])] = $route;
82 }
83 }
84
85 public function getAuth(array $methods, string $uri)
86 {
87 return $this->routeScopes[static::keyFor($methods, $uri)]['auth'];
88 }
89
90 public function getScopeTags(array $methods, string $uri)
91 {
92 return $this->routeScopes[static::keyFor($methods, $uri)]['scopes'];
93 }
94}