ソースを参照

Update web ui design for demo-client

Issue gh-1196
Joe Grandja 2 年 前
コミット
f05592f023

+ 3 - 2
samples/demo-client/samples-demo-client.gradle

@@ -21,6 +21,7 @@ dependencies {
 	implementation "org.springframework:spring-webflux"
 	implementation "io.projectreactor.netty:reactor-netty"
 	implementation "org.webjars:webjars-locator-core"
-	implementation "org.webjars:bootstrap:3.4.1"
-	implementation "org.webjars:jquery:3.4.1"
+	implementation "org.webjars:bootstrap:5.2.3"
+	implementation "org.webjars:popper.js:2.9.3"
+	implementation "org.webjars:jquery:3.6.4"
 }

+ 0 - 13
samples/demo-client/src/main/resources/static/assets/css/style.css

@@ -1,13 +0,0 @@
-html, body, .container, .jumbotron {
-    height: 100%;
-}
-.jumbotron {
-    margin-bottom: 0;
-}
-.gap {
-    margin-top: 70px;
-}
-.code {
-    font-size: 2em;
-    letter-spacing: 2rem;
-}

BIN
samples/demo-client/src/main/resources/static/assets/img/devices.png


+ 1 - 0
samples/demo-client/src/main/resources/static/assets/img/spring-security.svg

@@ -0,0 +1 @@
+<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 108.08 150.97"><defs><style>.cls-1{fill:#6bb344;}</style></defs><title>logo-security</title><path class="cls-1" d="M108.08,13,54,0,0,13V54.6H28.67a23.94,23.94,0,0,0,0,6H0V80.14C0,125,54,151,54,151s54-26,54-70.83V60.62H79.4a22.75,22.75,0,0,0,0-6h28.68ZM54,77.15A19.54,19.54,0,1,1,73.58,57.61,19.54,19.54,0,0,1,54,77.15Z"/><path class="cls-1" d="M54,48.34a5.06,5.06,0,0,0-2.32,9.56v1.31l1.49,1.49v1l1,1v1l-.88.88.94,1.55v1l-1,1.19,1.4,1.4,1.55-1.55V58A5.06,5.06,0,0,0,54,48.34Zm0,5.26a1.88,1.88,0,1,1,1.88-1.88A1.88,1.88,0,0,1,54,53.6Z"/></svg>

+ 23 - 22
samples/demo-client/src/main/resources/templates/device-activate.html

@@ -1,26 +1,27 @@
 <!DOCTYPE html>
 <html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org">
-    <head>
-        <meta charset="utf-8">
-        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
-        <title>Device Grant Example</title>
-        <link rel="stylesheet" href="/webjars/bootstrap/css/bootstrap.css" th:href="@{/webjars/bootstrap/css/bootstrap.css}" />
-        <link rel="stylesheet" href="/assets/css/style.css" th:href="@{/assets/css/style.css}" />
-    </head>
-    <body>
-        <div class="jumbotron">
-            <div class="container">
-                <div class="row">
-                    <div class="col-md-8">
-                        <h2>Activation Required</h2>
-                        <p>You must activate this device.</p>
-                        <a th:href="@{/device_authorize}" class="btn btn-primary" role="button">Activate</a>
-                    </div>
-                    <div class="col-md-4">
-                        <img src="https://cdn.pixabay.com/photo/2017/07/03/15/20/technology-2468063_1280.png" class="img-responsive" alt="Devices">
-                    </div>
-                </div>
-            </div>
+<head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <title>Spring Authorization Server sample</title>
+    <link rel="stylesheet" href="/webjars/bootstrap/css/bootstrap.css" th:href="@{/webjars/bootstrap/css/bootstrap.css}" />
+</head>
+<body>
+<div th:replace="~{page-templates :: navbar}"></div>
+<div class="container">
+    <div class="row">
+        <div class="col-md-5">
+            <h2>Activation Required</h2>
+            <p>You must activate this device.</p>
+            <a th:href="@{/device_authorize}" class="btn btn-primary" role="button">Activate</a>
         </div>
-    </body>
+        <div class="col-md-7">
+            <img src="/assets/img/devices.png" th:src="@{/assets/img/devices.png}" class="img-responsive" alt="Devices">
+        </div>
+    </div>
+</div>
+<script src="/webjars/bootstrap/js/bootstrap.bundle.min.js" th:src="@{/webjars/bootstrap/js/bootstrap.bundle.min.js}"></script>
+<script src="/webjars/jquery/jquery.min.js" th:src="@{/webjars/jquery/jquery.min.js}"></script>
+<script src="/webjars/popper.js/umd/popper.js" th:src="@{/webjars/popper.js/umd/popper.js}"></script>
+</body>
 </html>

+ 76 - 76
samples/demo-client/src/main/resources/templates/device-authorize.html

@@ -1,87 +1,87 @@
 <!DOCTYPE html>
 <html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org">
-    <head>
-        <meta charset="utf-8">
-        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
-        <title>Device Grant Example</title>
-        <link rel="stylesheet" href="/webjars/bootstrap/css/bootstrap.css" th:href="@{/webjars/bootstrap/css/bootstrap.css}" />
-        <link rel="stylesheet" href="/assets/css/style.css" th:href="@{/assets/css/style.css}" />
-    </head>
-    <body>
-        <div class="jumbotron">
-            <div class="container">
-                <div class="row">
-                    <div class="col-md-8">
-                        <h2>Device Activation</h2>
-                        <p>Please visit <a th:href="${verificationUri}" th:text="${verificationUri?.replaceFirst('https?://', '')}"></a> on another device to continue.</p>
-                        <p class="gap">Activation Code</p>
-                        <div class="well">
-                            <span class="code" th:text="${userCode}"></span>
-                            <form id="authorize-form" th:action="@{/device_authorize}" method="post">
-                                <input type="hidden" id="device_code" name="device_code" th:value="${deviceCode}" />
-                            </form>
-                        </div>
-                    </div>
-                    <div class="col-md-4">
-                        <img src="https://cdn.pixabay.com/photo/2017/07/03/15/20/technology-2468063_1280.png" class="img-responsive" alt="Devices">
-                    </div>
-                </div>
+<head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <title>Spring Authorization Server sample</title>
+    <link rel="stylesheet" href="/webjars/bootstrap/css/bootstrap.css" th:href="@{/webjars/bootstrap/css/bootstrap.css}" />
+</head>
+<body>
+<div th:replace="~{page-templates :: navbar}"></div>
+<div class="container">
+    <div class="row">
+        <div class="col-md-5">
+            <h2>Device Activation</h2>
+            <p>Please visit <a th:href="${verificationUri}" th:text="${verificationUri?.replaceFirst('https?://', '')}"></a> on another device to continue.</p>
+            <p style="margin-top: 70px">Activation Code</p>
+            <div class="card text-bg-light">
+                <span class="card-body" style="font-size: 2em; letter-spacing: 2rem" th:text="${userCode}"></span>
+                <form id="authorize-form" th:action="@{/device_authorize}" method="post">
+                    <input type="hidden" id="device_code" name="device_code" th:value="${deviceCode}" />
+                </form>
             </div>
         </div>
-        <script src="/webjars/jquery/jquery.min.js" th:src="@{/webjars/jquery/jquery.min.js}"></script>
-        <script type="text/javascript">
-            function authorize() {
-                let deviceCode = $('#device_code').val();
-                let csrfToken = $('[name=_csrf]').val();
-                if (deviceCode) {
-                    $.ajax({
-                        url: '/device_authorize',
-                        method: 'POST',
-                        data: {
-                            device_code: deviceCode,
-                            _csrf: csrfToken
-                        },
-                        timeout: 0
-                    }).fail((err) => {
-                        let response = err.responseJSON;
-                        if (response.errorCode === 'authorization_pending') {
-                            console.log('authorization pending, continuing to poll...');
-                        } else if (response.errorCode === 'slow_down') {
-                            console.log('slowing down...');
-                            slowDown();
-                        } else if (response.errorCode === 'token_expired') {
-                            console.log('token expired, stopping...');
-                            clear();
-                            location.href = '/';
-                        } else if (response.errorCode === 'access_denied') {
-                            console.log('access denied, stopping...');
-                            clear();
-                            location.href = '/';
-                        }
-                    }).done(() => window.location.href = '/device_authorized');
+        <div class="col-md-7">
+            <img src="/assets/img/devices.png" th:src="@{/assets/img/devices.png}" class="img-responsive" alt="Devices">
+        </div>
+    </div>
+</div>
+<script src="/webjars/bootstrap/js/bootstrap.bundle.min.js" th:src="@{/webjars/bootstrap/js/bootstrap.bundle.min.js}"></script>
+<script src="/webjars/jquery/jquery.min.js" th:src="@{/webjars/jquery/jquery.min.js}"></script>
+<script src="/webjars/popper.js/umd/popper.js" th:src="@{/webjars/popper.js/umd/popper.js}"></script>
+<script type="text/javascript">
+    function authorize() {
+        let deviceCode = $('#device_code').val();
+        let csrfToken = $('[name=_csrf]').val();
+        if (deviceCode) {
+            $.ajax({
+                url: '/device_authorize',
+                method: 'POST',
+                data: {
+                    device_code: deviceCode,
+                    _csrf: csrfToken
+                },
+                timeout: 0
+            }).fail((err) => {
+                let response = err.responseJSON;
+                if (response.errorCode === 'authorization_pending') {
+                    console.log('authorization pending, continuing to poll...');
+                } else if (response.errorCode === 'slow_down') {
+                    console.log('slowing down...');
+                    slowDown();
+                } else if (response.errorCode === 'token_expired') {
+                    console.log('token expired, stopping...');
+                    clear();
+                    location.href = '/';
+                } else if (response.errorCode === 'access_denied') {
+                    console.log('access denied, stopping...');
+                    clear();
+                    location.href = '/';
                 }
-            }
+            }).done(() => window.location.href = '/device_authorized');
+        }
+    }
 
-            function schedule() {
-                authorize.handler = window.setInterval(authorize, authorize.interval * 1000);
-            }
+    function schedule() {
+        authorize.handler = window.setInterval(authorize, authorize.interval * 1000);
+    }
 
-            function clear() {
-                if (authorize.handler !== null) {
-                    window.clearInterval(authorize.handler);
-                }
-            }
+    function clear() {
+        if (authorize.handler !== null) {
+            window.clearInterval(authorize.handler);
+        }
+    }
 
-            function slowDown() {
-                authorize.interval += 5;
-                clear();
-                schedule();
-            }
+    function slowDown() {
+        authorize.interval += 5;
+        clear();
+        schedule();
+    }
 
-            authorize.interval = 5;
-            authorize.handler = null;
+    authorize.interval = 5;
+    authorize.handler = null;
 
-            window.addEventListener('load', schedule);
-        </script>
-    </body>
+    window.addEventListener('load', schedule);
+</script>
+</body>
 </html>

+ 17 - 55
samples/demo-client/src/main/resources/templates/index.html

@@ -1,57 +1,19 @@
 <!DOCTYPE html>
-<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org" xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity6">
-    <head>
-        <title>Spring Security OAuth 2.0 Sample</title>
-        <meta charset="utf-8" />
-        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
-        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
-        <link rel="stylesheet" href="/webjars/bootstrap/css/bootstrap.css" th:href="@{/webjars/bootstrap/css/bootstrap.css}" />
-    </head>
-    <body>
-        <div th:fragment="header">
-            <nav class="navbar navbar-default">
-                <div class="container-fluid">
-                    <div class="collapse navbar-collapse">
-                        <form class="navbar-form navbar-right" th:action="@{/logout}" method="post">
-                            <button type="submit" class="btn btn-default navbar-btn">Logout</button>
-                        </form>
-                    </div>
-                </div>
-            </nav>
-        </div>
-        <div class="container">
-            <div th:if="${error}" class="alert alert-danger alert-dismissible" role="alert">
-                <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
-                <h4 th:text="${error}" class="text-center"></h4>
-            </div>
-            <div class="panel panel-default">
-                <div class="panel-heading">
-                    <h3 class="panel-title">Authorize the client using <span style="font-family:monospace">grant_type</span>:</h3>
-                </div>
-                <ul class="list-group">
-                    <li class="list-group-item">
-                        <a href="/authorize?grant_type=authorization_code" th:href="@{/authorize?grant_type=authorization_code}"><span style="font-size:medium">Authorization Code</span></a>
-                    </li>
-                    <li class="list-group-item">
-                        <a href="/authorize?grant_type=client_credentials" th:href="@{/authorize?grant_type=client_credentials}"><span style="font-size:medium">Client Credentials</span></a>
-                    </li>
-                    <li class="list-group-item">
-                        <a href="/authorize?grant_type=device_code" th:href="@{/authorize?grant_type=device_code}"><span style="font-size:medium">Device Code</span></a>
-                    </li>
-                </ul>
-                <div th:if="${messages}" class="panel-footer">
-                    <h4>Messages:</h4>
-                    <table class="table table-condensed">
-                        <tbody>
-                            <tr class="row" th:each="message : ${messages}">
-                                <td th:text="${message}">message</td>
-                            </tr>
-                        </tbody>
-                    </table>
-                </div>
-            </div>
-        </div>
-        <script src="/webjars/jquery/jquery.min.js" th:src="@{/webjars/jquery/jquery.min.js}"></script>
-        <script src="/webjars/bootstrap/js/bootstrap.min.js" th:src="@{/webjars/bootstrap/js/bootstrap.min.js}"></script>
-    </body>
+<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org">
+<head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <title>Spring Authorization Server sample</title>
+    <link rel="stylesheet" href="/webjars/bootstrap/css/bootstrap.css" th:href="@{/webjars/bootstrap/css/bootstrap.css}" />
+</head>
+<body>
+<div th:replace="~{page-templates :: navbar}"></div>
+<div class="container">
+    <div th:replace="~{page-templates :: error-message}"></div>
+    <div th:replace="~{page-templates :: message-list}"></div>
+</div>
+<script src="/webjars/bootstrap/js/bootstrap.bundle.min.js" th:src="@{/webjars/bootstrap/js/bootstrap.bundle.min.js}"></script>
+<script src="/webjars/jquery/jquery.min.js" th:src="@{/webjars/jquery/jquery.min.js}"></script>
+<script src="/webjars/popper.js/umd/popper.js" th:src="@{/webjars/popper.js/umd/popper.js}"></script>
+</body>
 </html>

+ 11 - 13
samples/demo-client/src/main/resources/templates/logged-out.html

@@ -1,22 +1,20 @@
 <!DOCTYPE html>
-<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org" xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity6">
+<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org">
 <head>
-	<title>Spring Security OAuth 2.0 Sample</title>
-	<meta charset="utf-8"/>
-	<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
-	<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
-	<link rel="stylesheet" href="/webjars/bootstrap/css/bootstrap.css"
-		  th:href="@{/webjars/bootstrap/css/bootstrap.css}"/>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <title>Spring Authorization Server sample</title>
+    <link rel="stylesheet" href="/webjars/bootstrap/css/bootstrap.css" th:href="@{/webjars/bootstrap/css/bootstrap.css}" />
 </head>
 <body>
-<div th:fragment="header">
-	<nav class="navbar navbar-default"></nav>
-</div>
+<div th:replace="~{page-templates :: navbar}"></div>
 <div class="container">
-	<h1>You are now logged out.</h1>
-	<a href="/" th:href="@{/}">Go back home</a>
+    <div class="row">
+        <h2>You are now logged out.</h2>
+    </div>
 </div>
+<script src="/webjars/bootstrap/js/bootstrap.bundle.min.js" th:src="@{/webjars/bootstrap/js/bootstrap.bundle.min.js}"></script>
 <script src="/webjars/jquery/jquery.min.js" th:src="@{/webjars/jquery/jquery.min.js}"></script>
-<script src="/webjars/bootstrap/js/bootstrap.min.js" th:src="@{/webjars/bootstrap/js/bootstrap.min.js}"></script>
+<script src="/webjars/popper.js/umd/popper.js" th:src="@{/webjars/popper.js/umd/popper.js}"></script>
 </body>
 </html>

+ 65 - 0
samples/demo-client/src/main/resources/templates/page-templates.html

@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org">
+<head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <title>Spring Authorization Server sample</title>
+    <link rel="stylesheet" href="/webjars/bootstrap/css/bootstrap.css" th:href="@{/webjars/bootstrap/css/bootstrap.css}" />
+</head>
+<body>
+<nav th:fragment="navbar" class="navbar navbar-expand-lg bg-light">
+    <div class="container-fluid">
+        <a class="navbar-brand" href="#">
+            <img src="/assets/img/spring-security.svg" th:src="@{/assets/img/spring-security.svg}" width="40" height="32">
+        </a>
+        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
+            <span class="navbar-toggler-icon"></span>
+        </button>
+        <div class="collapse navbar-collapse" id="navbarSupportedContent">
+            <ul class="navbar-nav me-auto mb-2 mb-lg-0">
+                <li class="nav-item">
+                    <a class="nav-link active" aria-current="page" href="/" th:href="@{/}">Home</a>
+                </li>
+                <li class="nav-item dropdown">
+                    <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">Authorize</a>
+                    <ul class="dropdown-menu">
+                        <li><a class="dropdown-item" href="/authorize?grant_type=authorization_code" th:href="@{/authorize?grant_type=authorization_code}">Authorization Code</a></li>
+                        <li><a class="dropdown-item" href="/authorize?grant_type=client_credentials" th:href="@{/authorize?grant_type=client_credentials}">Client Credentials</a></li>
+                        <li><a class="dropdown-item" href="/authorize?grant_type=device_code" th:href="@{/authorize?grant_type=device_code}">Device Code</a></li>
+                    </ul>
+                </li>
+            </ul>
+            <form class="d-flex" th:action="@{/logout}" method="post">
+                <button class="btn btn-outline-dark" type="submit">Logout</button>
+            </form>
+        </div>
+    </div>
+</nav>
+<div class="container">
+    <div th:fragment="error-message" th:if="${error}" class="row alert alert-danger alert-dismissible fade show" role="alert">
+        <strong th:text="${error}"></strong>
+        <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
+    </div>
+    <div th:fragment="message-list" th:if="${messages}" class="row">
+        <table class="table table-striped caption-top">
+            <caption>Messages</caption>
+            <thead>
+            <tr>
+                <th scope="col">#</th>
+                <th scope="col">Message</th>
+            </tr>
+            </thead>
+            <tbody>
+            <tr th:each="message,iterStat : ${messages}">
+                <th scope="row" th:text="${iterStat.count}"></th>
+                <td th:text="${message}"></td>
+            </tr>
+            </tbody>
+        </table>
+    </div>
+</div>
+<script src="/webjars/bootstrap/js/bootstrap.bundle.min.js" th:src="@{/webjars/bootstrap/js/bootstrap.bundle.min.js}"></script>
+<script src="/webjars/jquery/jquery.min.js" th:src="@{/webjars/jquery/jquery.min.js}"></script>
+<script src="/webjars/popper.js/umd/popper.js" th:src="@{/webjars/popper.js/umd/popper.js}"></script>
+</body>
+</html>