|
35 | 35 | <link rel="icon" type="image/svg+xml" href="/favicon.svg" /> |
36 | 36 | <link rel="shortcut icon" href="/favicon.ico" /> |
37 | 37 | <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" /> |
38 | | - <meta name="apple-mobile-web-app-title" content="Locket" /> |
| 38 | + <meta name="apple-mobile-web-app-title" content="Authorize MCP" /> |
39 | 39 | <link rel="manifest" href="/site.webmanifest" /> |
40 | 40 |
|
41 | 41 | <link rel="preconnect" href="https://fonts.bunny.net"> |
|
51 | 51 | <!-- Header --> |
52 | 52 | <div class="flex flex-col space-y-1.5 p-6"> |
53 | 53 | <div class="flex items-center justify-center mb-4"> |
54 | | - <!-- Shield icon --> |
| 54 | + <!-- Shield Icon --> |
55 | 55 | <svg class="h-12 w-12 text-primary" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> |
56 | 56 | <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.618 5.984A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.031 9-11.622 0-1.042-.133-2.052-.382-3.016z"></path> |
57 | 57 | </svg> |
58 | 58 | </div> |
| 59 | + |
59 | 60 | <h3 class="text-2xl font-semibold leading-none tracking-tight text-center"> |
60 | 61 | Authorize {{ $client->name }} |
61 | 62 | </h3> |
| 63 | + |
62 | 64 | <p class="text-sm text-muted-foreground text-center"> |
63 | 65 | This application will be able to:<br/>Use available MCP functionality. |
64 | 66 | </p> |
|
72 | 74 | <p class="font-medium">{{ $user->email }}</p> |
73 | 75 | </div> |
74 | 76 |
|
75 | | - <!-- Scopes/Permissions --> |
| 77 | + <!-- Scopes / Permissions --> |
76 | 78 | @if(count($scopes) > 0) |
77 | 79 | <div class="space-y-2"> |
78 | 80 | <p class="text-sm font-medium">Permissions:</p> |
| 81 | + |
79 | 82 | <ul class="space-y-2"> |
80 | 83 | @foreach($scopes as $scope) |
81 | 84 | <li class="flex items-start gap-2"> |
|
92 | 95 | @endif |
93 | 96 | </div> |
94 | 97 |
|
95 | | - <!-- Footer with buttons --> |
| 98 | + <!-- Footer With Buttons --> |
96 | 99 | <div class="flex items-center p-6 pt-0 gap-3"> |
97 | | - <!-- Deny form --> |
| 100 | + <!-- Deny Form --> |
98 | 101 | <form method="POST" action="{{ route('passport.authorizations.deny') }}" class="flex-1"> |
99 | 102 | @csrf |
100 | 103 | @method('DELETE') |
101 | 104 | <input type="hidden" name="state" value=""> |
102 | 105 | <input type="hidden" name="client_id" value="{{ $client->id }}"> |
103 | 106 | <input type="hidden" name="auth_token" value="{{ $authToken }}"> |
104 | 107 | <button type="submit" class="inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border border-input bg-background hover:bg-accent hover:text-accent-foreground h-10 px-4 py-2 w-full"> |
105 | | - <!-- X icon --> |
106 | 108 | <svg class="mr-2 h-4 w-4" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> |
107 | 109 | <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path> |
108 | 110 | </svg> |
109 | 111 | Cancel |
110 | 112 | </button> |
111 | 113 | </form> |
112 | 114 |
|
113 | | - <!-- Approve form --> |
| 115 | + <!-- Approve Form --> |
114 | 116 | <form method="POST" action="{{ route('passport.authorizations.approve') }}" class="flex-1" id="authorizeForm"> |
115 | 117 | @csrf |
116 | 118 | <input type="hidden" name="state" value=""> |
117 | 119 | <input type="hidden" name="client_id" value="{{ $client->id }}"> |
118 | 120 | <input type="hidden" name="auth_token" value="{{ $authToken }}"> |
119 | 121 | <button type="submit" class="inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 bg-primary text-primary-foreground hover:bg-primary/90 h-10 px-4 py-2 w-full" id="authorizeButton"> |
120 | 122 | <span id="authorizeText">Authorize</span> |
| 123 | + |
121 | 124 | <svg id="loadingSpinner" class="animate-spin -ml-1 mr-3 h-4 w-4 text-white hidden" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"> |
122 | 125 | <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle> |
123 | 126 | <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path> |
|
137 | 140 | const loadingSpinner = document.getElementById('loadingSpinner'); |
138 | 141 |
|
139 | 142 | form.addEventListener('submit', function(e) { |
140 | | - // Show loading state |
| 143 | + // Show loading state... |
141 | 144 | button.disabled = true; |
142 | 145 | authorizeText.textContent = 'Authorizing...'; |
143 | 146 | loadingSpinner.classList.remove('hidden'); |
144 | 147 |
|
145 | | - // After form submission, watch for redirect and close window |
| 148 | + // After form submission, watch for redirect and close window... |
146 | 149 | setTimeout(function() { |
147 | 150 | const checkRedirect = setInterval(function() { |
148 | | - // If URL changed or we have OAuth params, redirect happened |
| 151 | + // If URL changed or we have OAuth params, redirect happened... |
149 | 152 | if (!window.location.href.includes('/oauth/authorize') || |
150 | 153 | window.location.search.includes('code=') || |
151 | 154 | window.location.search.includes('error=')) { |
|
154 | 157 | } |
155 | 158 | }, 100); |
156 | 159 |
|
157 | | - // Fallback: close after 5 seconds |
| 160 | + // Fallback: Close after five seconds... |
158 | 161 | setTimeout(function() { |
159 | 162 | clearInterval(checkRedirect); |
160 | 163 | window.close(); |
161 | 164 | }, 5000); |
162 | 165 | }, 200); |
163 | 166 | }); |
164 | 167 |
|
165 | | - // Handle cancel button |
| 168 | + // Handle cancel button... |
166 | 169 | const cancelForm = document.querySelector('form[method="POST"]:has(input[name="_method"][value="DELETE"])'); |
167 | 170 | if (cancelForm) { |
168 | 171 | cancelForm.addEventListener('submit', function(e) { |
|
0 commit comments