consent.php
258 lines
| 1 | <?php |
| 2 | /** |
| 3 | * OAuth consent screen template. |
| 4 | * |
| 5 | * Rendered in isolation (no theme, no wp_head). All output is escaped at |
| 6 | * the point of emission. Variables provided by ConsentController::renderConsent: |
| 7 | * |
| 8 | * @var string $site_name Blog name from get_bloginfo(). |
| 9 | * @var string $client_name Human-readable client label. |
| 10 | * @var array<int, array{slug:string, description:string}> $scopes Requested scopes with descriptions. |
| 11 | * @var string $user_email Logged-in user's email. |
| 12 | * @var string $nonce_field Pre-rendered hidden nonce input HTML. |
| 13 | * @var string $form_action Same-URL POST target. |
| 14 | * @var string $redirect_uri Where the authorization code will be sent. |
| 15 | * |
| 16 | * @package PrestoPlayer |
| 17 | * @subpackage Services\OAuth\Consent |
| 18 | */ |
| 19 | |
| 20 | if ( ! defined( 'ABSPATH' ) ) { |
| 21 | exit; |
| 22 | } |
| 23 | ?><!doctype html> |
| 24 | <html lang="<?php echo esc_attr( get_bloginfo( 'language' ) ); ?>"> |
| 25 | <head> |
| 26 | <meta charset="utf-8"> |
| 27 | <meta name="viewport" content="width=device-width,initial-scale=1"> |
| 28 | <meta name="robots" content="noindex,nofollow"> |
| 29 | <title><?php echo esc_html( sprintf( /* translators: %s: client application name. */ __( 'Authorize %s', 'presto-player' ), $client_name ) ); ?></title> |
| 30 | <style> |
| 31 | :root { |
| 32 | color-scheme: light dark; |
| 33 | --bg: #f6f7f7; |
| 34 | --card-bg: #ffffff; |
| 35 | --text: #1d2327; |
| 36 | --muted: #50575e; |
| 37 | --border: #dcdcde; |
| 38 | --accent: #2271b1; |
| 39 | --accent-hover: #135e96; |
| 40 | --accent-text: #ffffff; |
| 41 | --danger-border: #c3c4c7; |
| 42 | --scope-bg: #f0f0f1; |
| 43 | } |
| 44 | @media (prefers-color-scheme: dark) { |
| 45 | :root { |
| 46 | --bg: #1d2327; |
| 47 | --card-bg: #2c3338; |
| 48 | --text: #f0f0f1; |
| 49 | --muted: #c3c4c7; |
| 50 | --border: #3c434a; |
| 51 | --accent: #2271b1; |
| 52 | --accent-hover: #72aee6; |
| 53 | --accent-text: #ffffff; |
| 54 | --danger-border: #50575e; |
| 55 | --scope-bg: #1d2327; |
| 56 | } |
| 57 | } |
| 58 | * { box-sizing: border-box; } |
| 59 | html, body { |
| 60 | margin: 0; |
| 61 | padding: 0; |
| 62 | background: var(--bg); |
| 63 | color: var(--text); |
| 64 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; |
| 65 | font-size: 15px; |
| 66 | line-height: 1.5; |
| 67 | } |
| 68 | .wrap { |
| 69 | min-height: 100vh; |
| 70 | display: flex; |
| 71 | align-items: center; |
| 72 | justify-content: center; |
| 73 | padding: 32px 16px; |
| 74 | } |
| 75 | .card { |
| 76 | width: 100%; |
| 77 | max-width: 480px; |
| 78 | background: var(--card-bg); |
| 79 | border: 1px solid var(--border); |
| 80 | border-radius: 12px; |
| 81 | padding: 32px; |
| 82 | box-shadow: 0 4px 24px rgba(0,0,0,0.06); |
| 83 | } |
| 84 | h1 { |
| 85 | font-size: 20px; |
| 86 | line-height: 1.3; |
| 87 | margin: 0 0 8px; |
| 88 | font-weight: 600; |
| 89 | } |
| 90 | .subtitle { |
| 91 | color: var(--muted); |
| 92 | margin: 0 0 24px; |
| 93 | font-size: 14px; |
| 94 | } |
| 95 | .client-name { font-weight: 600; } |
| 96 | .unverified { |
| 97 | margin: 0 0 24px; |
| 98 | padding: 10px 12px; |
| 99 | border: 1px solid var(--danger-border); |
| 100 | border-radius: 8px; |
| 101 | font-size: 13px; |
| 102 | color: var(--muted); |
| 103 | } |
| 104 | .section-label { |
| 105 | text-transform: uppercase; |
| 106 | font-size: 11px; |
| 107 | letter-spacing: 0.05em; |
| 108 | color: var(--muted); |
| 109 | margin: 24px 0 8px; |
| 110 | font-weight: 600; |
| 111 | } |
| 112 | ul.scopes { |
| 113 | list-style: none; |
| 114 | margin: 0; |
| 115 | padding: 0; |
| 116 | border: 1px solid var(--border); |
| 117 | border-radius: 8px; |
| 118 | overflow: hidden; |
| 119 | } |
| 120 | ul.scopes li { |
| 121 | padding: 12px 14px; |
| 122 | background: var(--scope-bg); |
| 123 | border-bottom: 1px solid var(--border); |
| 124 | } |
| 125 | ul.scopes li:last-child { border-bottom: 0; } |
| 126 | .scope-slug { |
| 127 | font-family: ui-monospace, SFMono-Regular, Menlo, monospace; |
| 128 | font-size: 12px; |
| 129 | color: var(--muted); |
| 130 | display: block; |
| 131 | margin-bottom: 2px; |
| 132 | } |
| 133 | .account { |
| 134 | margin: 16px 0 24px; |
| 135 | padding: 12px 14px; |
| 136 | border: 1px solid var(--border); |
| 137 | border-radius: 8px; |
| 138 | font-size: 13px; |
| 139 | color: var(--muted); |
| 140 | } |
| 141 | .account strong { color: var(--text); } |
| 142 | .destination { |
| 143 | margin: 0 0 8px; |
| 144 | } |
| 145 | .destination strong { |
| 146 | font-family: ui-monospace, SFMono-Regular, Menlo, monospace; |
| 147 | font-size: 12px; |
| 148 | word-break: break-all; |
| 149 | } |
| 150 | .actions { |
| 151 | display: flex; |
| 152 | gap: 12px; |
| 153 | margin-top: 24px; |
| 154 | } |
| 155 | button { |
| 156 | flex: 1; |
| 157 | border: 1px solid var(--border); |
| 158 | background: transparent; |
| 159 | color: var(--text); |
| 160 | padding: 12px 16px; |
| 161 | border-radius: 8px; |
| 162 | font-size: 14px; |
| 163 | font-weight: 600; |
| 164 | cursor: pointer; |
| 165 | font-family: inherit; |
| 166 | } |
| 167 | button:hover { border-color: var(--muted); } |
| 168 | button.primary { |
| 169 | background: var(--accent); |
| 170 | border-color: var(--accent); |
| 171 | color: var(--accent-text); |
| 172 | } |
| 173 | button.primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); } |
| 174 | .footer { |
| 175 | text-align: center; |
| 176 | margin-top: 16px; |
| 177 | font-size: 12px; |
| 178 | color: var(--muted); |
| 179 | } |
| 180 | </style> |
| 181 | </head> |
| 182 | <body> |
| 183 | <div class="wrap"> |
| 184 | <div class="card"> |
| 185 | <h1> |
| 186 | <?php |
| 187 | echo esc_html( |
| 188 | sprintf( |
| 189 | /* translators: %s: client application name. */ |
| 190 | __( 'Authorize %s', 'presto-player' ), |
| 191 | $client_name |
| 192 | ) |
| 193 | ); |
| 194 | ?> |
| 195 | </h1> |
| 196 | <p class="subtitle"> |
| 197 | <?php |
| 198 | echo wp_kses( |
| 199 | sprintf( |
| 200 | /* translators: 1: client application name, 2: site name. */ |
| 201 | __( '<span class="client-name">%1$s</span> is requesting access to your account on %2$s.', 'presto-player' ), |
| 202 | esc_html( $client_name ), |
| 203 | esc_html( $site_name ) |
| 204 | ), |
| 205 | array( 'span' => array( 'class' => array() ) ) |
| 206 | ); |
| 207 | ?> |
| 208 | </p> |
| 209 | |
| 210 | <p class="unverified"> |
| 211 | <?php esc_html_e( 'This is a third-party application that has not been verified. Only continue if you trust it.', 'presto-player' ); ?> |
| 212 | </p> |
| 213 | |
| 214 | <div class="section-label"><?php esc_html_e( 'This will allow the app to:', 'presto-player' ); ?></div> |
| 215 | <ul class="scopes"> |
| 216 | <?php foreach ( $scopes as $scope ) : ?> |
| 217 | <li> |
| 218 | <span class="scope-slug"><?php echo esc_html( $scope['slug'] ); ?></span> |
| 219 | <?php echo esc_html( $scope['description'] ); ?> |
| 220 | </li> |
| 221 | <?php endforeach; ?> |
| 222 | </ul> |
| 223 | |
| 224 | <?php if ( '' !== $redirect_uri ) : ?> |
| 225 | <div class="section-label"><?php esc_html_e( 'Access will be sent to:', 'presto-player' ); ?></div> |
| 226 | <div class="account destination"> |
| 227 | <strong><?php echo esc_html( $redirect_uri ); ?></strong> |
| 228 | </div> |
| 229 | <?php endif; ?> |
| 230 | |
| 231 | <div class="account"> |
| 232 | <?php esc_html_e( 'Signed in as', 'presto-player' ); ?> |
| 233 | <strong><?php echo esc_html( $user_email ); ?></strong> |
| 234 | </div> |
| 235 | |
| 236 | <form method="post" action="<?php echo esc_url( $form_action ); ?>" autocomplete="off"> |
| 237 | <?php |
| 238 | // Pre-built nonce field is already escaped HTML. |
| 239 | echo $nonce_field; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped |
| 240 | ?> |
| 241 | <div class="actions"> |
| 242 | <button type="submit" name="deny" value="1"> |
| 243 | <?php esc_html_e( 'Deny', 'presto-player' ); ?> |
| 244 | </button> |
| 245 | <button type="submit" name="allow" value="1" class="primary"> |
| 246 | <?php esc_html_e( 'Allow', 'presto-player' ); ?> |
| 247 | </button> |
| 248 | </div> |
| 249 | </form> |
| 250 | |
| 251 | <p class="footer"> |
| 252 | <?php esc_html_e( 'An administrator can revoke this access by turning off AI access in the Presto Player settings. That revokes every app at once.', 'presto-player' ); ?> |
| 253 | </p> |
| 254 | </div> |
| 255 | </div> |
| 256 | </body> |
| 257 | </html> |
| 258 |