forked from
baileytownsend.dev/pds-gatekeeper
Microservice to bring 2FA to self hosted PDSes
1<html lang="en" class=" ">
2<head>
3 <meta charset="utf-8"/>
4 <meta
5 name="viewport"
6 content="width=device-width, initial-scale=1, minimum-scale=1, viewport-fit=cover"
7 />
8 <meta name="referrer" content="origin-when-cross-origin"/>
9
10 <title>
11 {{pds}} - Captcha
12 </title>
13 <style>
14 :root,
15 :root.light-mode {
16 --brand-color: rgb(16, 131, 254);
17 --primary-color: rgb(7, 10, 13);
18 --secondary-color: rgb(66, 86, 108);
19 --bg-primary-color: rgb(255, 255, 255);
20 --bg-secondary-color: rgb(240, 242, 245);
21 }
22
23 @media (prefers-color-scheme: dark) {
24 :root {
25 --brand-color: rgb(16, 131, 254);
26 --primary-color: rgb(255, 255, 255);
27 --secondary-color: rgb(133, 152, 173);
28 --bg-primary-color: rgb(7, 10, 13);
29 --bg-secondary-color: rgb(13, 18, 23);
30 }
31 }
32
33 :root.dark-mode {
34 --brand-color: rgb(16, 131, 254);
35 --primary-color: rgb(255, 255, 255);
36 --secondary-color: rgb(133, 152, 173);
37 --bg-primary-color: rgb(7, 10, 13);
38 --bg-secondary-color: rgb(13, 18, 23);
39 }
40
41 body {
42 font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica,
43 Arial, sans-serif;
44 background: var(--bg-primary-color);
45 color: var(--primary-color);
46 text-rendering: optimizeLegibility;
47 -webkit-font-smoothing: antialiased;
48 }
49
50 .info {
51 border-radius: 8px;
52 padding: 12px 14px;
53 letter-spacing: 0.25px;
54 font-weight: 400;
55 background-color: var(--bg-secondary-color);
56 color: var(--secondary-color);
57 }
58
59 .gate-page,
60 .error-page {
61 margin: 0;
62 margin-top: 10px;
63 display: flex;
64 justify-content: center;
65 }
66
67 .gate-page .main,
68 .error-page .main {
69 max-width: 600px;
70 width: 100%;
71 display: flex;
72 flex-direction: column;
73 }
74
75 .gate-page .main {
76 padding: 0;
77 }
78
79 .error-page .main {
80 padding: 20px;
81 }
82
83 .gate-page .main > :not(:first-child),
84 .error-page .main > :not(:first-child) {
85 margin-top: 20px;
86 }
87
88 .gate-page #gate-form {
89 margin: 0;
90 }
91
92 .gate-page #hcaptcha {
93 display: flex;
94 justify-content: center;
95 }
96
97 .pds-title {
98 font-size: 2.25rem;
99 font-weight: 700;
100 line-height: 1.2;
101 text-align: center;
102 color: var(--primary-color);
103 margin: 10px 0 16px;
104 }
105
106 </style>
107
108 <script type="text/javascript">
109 function onCaptchaReady() {
110 const theme = document.documentElement.classList.contains('dark-mode') ?
111 'dark' :
112 document.documentElement.classList.contains('light-mode') ?
113 'light' :
114 window.matchMedia('(prefers-color-scheme: dark)').matches ?
115 'dark' :
116 'light'
117 hcaptcha.render('hcaptcha', {theme});
118 }
119
120 function onCaptchaComplete() {
121 setTimeout(function () {
122 document.getElementById('gate-form').submit();
123 }, 1000);
124 }
125
126 function onCaptchaError() {
127 const url = new URL(location.href);
128 url.searchParams.set('error', 'true');
129 location.assign(url.search);
130 }
131
132 function onCaptchaExpired() {
133 const url = new URL(location.href);
134 url.searchParams.set('error', 'expired');
135 location.assign(url.search);
136 }
137 </script>
138 <script
139 src="https://js.hcaptcha.com/1/api.js?render=explicit&onload=onCaptchaReady"
140 async
141 defer
142 ></script>
143 <link rel="stylesheet" href="/gate/signup/assets/common.css"/>
144</head>
145
146<body class="gate-page">
147<div class="main">
148 <div class="pds-title">{{pds}}</div>
149 <form id="gate-form" action="" method="POST">
150 <div
151 id="hcaptcha"
152 data-sitekey="{{captcha_site_key}}"
153 data-callback="onCaptchaComplete"
154 data-error-callback="onCaptchaError"
155 data-expired-callback="onCaptchaExpired"
156 data-chalexpired-callback="onCaptchaExpired"
157 ></div>
158 <input type="hidden" name="redirect_url" value="{{redirect_url}}"/>
159 </form>
160 {{#if error_message }}
161 <div class="info">{{error_message}}</div>
162 {{/if}}
163
164</div>
165</body>
166</html>