@blinkk/root-password-protect 1.0.0-rc.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2023-2024 Blinkk LLC
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env node
2
+
3
+ import {createRequire} from 'node:module';
4
+ import path from 'node:path';
5
+ import {fileURLToPath} from 'node:url';
6
+ import {Command} from 'commander';
7
+ import {bgGreen, black} from 'kleur/colors';
8
+ import {generateHash} from '../dist/cli.js';
9
+
10
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
11
+ const require = createRequire(import.meta.url);
12
+ const packageJson = require(path.join(__dirname, '../package.json'));
13
+
14
+ async function main() {
15
+ console.log(`🥕 ${bgGreen(black(' root-password-protect'))} v${packageJson.version}`);
16
+
17
+ const program = new Command('root-password-protect');
18
+ program.version(packageJson.version);
19
+ program
20
+ .command('generate-hash <password>')
21
+ .description('generates root-cms.d.ts from *.schema.ts files in the project')
22
+ .action(generateHash);
23
+ await program.parseAsync(process.argv);
24
+ }
25
+
26
+ main();
package/dist/cli.js ADDED
@@ -0,0 +1,45 @@
1
+ // core/password.ts
2
+ import crypto from "crypto";
3
+ var PASSWORD_ITERATIONS = 1e4;
4
+ var PASSWORD_HASH_LENGTH = 64;
5
+ var PASSWORD_DIGEST = "sha256";
6
+ async function hashPassword(password) {
7
+ const salt = crypto.randomBytes(16).toString("hex");
8
+ const hash = await generateHash(password, salt);
9
+ return { hash, salt };
10
+ }
11
+ function generateHash(password, salt) {
12
+ return new Promise((resolve, reject) => {
13
+ crypto.pbkdf2(
14
+ password,
15
+ salt,
16
+ PASSWORD_ITERATIONS,
17
+ PASSWORD_HASH_LENGTH,
18
+ PASSWORD_DIGEST,
19
+ (err, derivedKey) => {
20
+ if (err) {
21
+ console.error("password hashing failed");
22
+ console.error(err);
23
+ reject(err);
24
+ return;
25
+ }
26
+ const hash = derivedKey.toString("hex");
27
+ resolve(hash);
28
+ }
29
+ );
30
+ });
31
+ }
32
+
33
+ // cli/commands/generate-hash.ts
34
+ async function generateHash2(password) {
35
+ const { hash, salt } = await hashPassword(password);
36
+ console.log('// Generated by: `root-password-protect generate-hash "..."`.');
37
+ console.log("password: {");
38
+ console.log(` hash: '${hash}',`);
39
+ console.log(` salt: '${salt}',`);
40
+ console.log("}");
41
+ }
42
+ export {
43
+ generateHash2 as generateHash
44
+ };
45
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vY29yZS9wYXNzd29yZC50cyIsICIuLi9jbGkvY29tbWFuZHMvZ2VuZXJhdGUtaGFzaC50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiaW1wb3J0IGNyeXB0byBmcm9tICdjcnlwdG8nO1xuXG5jb25zdCBQQVNTV09SRF9JVEVSQVRJT05TID0gMTAwMDA7XG5jb25zdCBQQVNTV09SRF9IQVNIX0xFTkdUSCA9IDY0O1xuY29uc3QgUEFTU1dPUkRfRElHRVNUID0gJ3NoYTI1Nic7XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBoYXNoUGFzc3dvcmQoXG4gIHBhc3N3b3JkOiBzdHJpbmdcbik6IFByb21pc2U8e2hhc2g6IHN0cmluZzsgc2FsdDogc3RyaW5nfT4ge1xuICBjb25zdCBzYWx0ID0gY3J5cHRvLnJhbmRvbUJ5dGVzKDE2KS50b1N0cmluZygnaGV4Jyk7XG4gIGNvbnN0IGhhc2ggPSBhd2FpdCBnZW5lcmF0ZUhhc2gocGFzc3dvcmQsIHNhbHQpO1xuICByZXR1cm4ge2hhc2gsIHNhbHR9O1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gdmVyaWZ5UGFzc3dvcmQoXG4gIHBhc3N3b3JkOiBzdHJpbmcsXG4gIGhhc2g6IHN0cmluZyxcbiAgc2FsdDogc3RyaW5nXG4pOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgY29uc3QgZ2VuZXJhdGVkSGFzaCA9IGF3YWl0IGdlbmVyYXRlSGFzaChwYXNzd29yZCwgc2FsdCk7XG4gIHJldHVybiBoYXNoID09PSBnZW5lcmF0ZWRIYXNoO1xufVxuXG5mdW5jdGlvbiBnZW5lcmF0ZUhhc2gocGFzc3dvcmQ6IHN0cmluZywgc2FsdDogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICBjcnlwdG8ucGJrZGYyKFxuICAgICAgcGFzc3dvcmQsXG4gICAgICBzYWx0LFxuICAgICAgUEFTU1dPUkRfSVRFUkFUSU9OUyxcbiAgICAgIFBBU1NXT1JEX0hBU0hfTEVOR1RILFxuICAgICAgUEFTU1dPUkRfRElHRVNULFxuICAgICAgKGVyciwgZGVyaXZlZEtleSkgPT4ge1xuICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcigncGFzc3dvcmQgaGFzaGluZyBmYWlsZWQnKTtcbiAgICAgICAgICBjb25zb2xlLmVycm9yKGVycik7XG4gICAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGhhc2ggPSBkZXJpdmVkS2V5LnRvU3RyaW5nKCdoZXgnKTtcbiAgICAgICAgcmVzb2x2ZShoYXNoKTtcbiAgICAgIH1cbiAgICApO1xuICB9KTtcbn1cbiIsICJpbXBvcnQge2hhc2hQYXNzd29yZH0gZnJvbSAnLi4vLi4vY29yZS9wYXNzd29yZC5qcyc7XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZW5lcmF0ZUhhc2gocGFzc3dvcmQ6IHN0cmluZykge1xuICBjb25zdCB7aGFzaCwgc2FsdH0gPSBhd2FpdCBoYXNoUGFzc3dvcmQocGFzc3dvcmQpO1xuICBjb25zb2xlLmxvZygnLy8gR2VuZXJhdGVkIGJ5OiBgcm9vdC1wYXNzd29yZC1wcm90ZWN0IGdlbmVyYXRlLWhhc2ggXCIuLi5cImAuJyk7XG4gIGNvbnNvbGUubG9nKCdwYXNzd29yZDogeycpO1xuICBjb25zb2xlLmxvZyhgICBoYXNoOiAnJHtoYXNofScsYCk7XG4gIGNvbnNvbGUubG9nKGAgIHNhbHQ6ICcke3NhbHR9JyxgKTtcbiAgY29uc29sZS5sb2coJ30nKTtcbn1cbiJdLAogICJtYXBwaW5ncyI6ICI7QUFBQSxPQUFPLFlBQVk7QUFFbkIsSUFBTSxzQkFBc0I7QUFDNUIsSUFBTSx1QkFBdUI7QUFDN0IsSUFBTSxrQkFBa0I7QUFFeEIsZUFBc0IsYUFDcEIsVUFDdUM7QUFDdkMsUUFBTSxPQUFPLE9BQU8sWUFBWSxFQUFFLEVBQUUsU0FBUyxLQUFLO0FBQ2xELFFBQU0sT0FBTyxNQUFNLGFBQWEsVUFBVSxJQUFJO0FBQzlDLFNBQU8sRUFBQyxNQUFNLEtBQUk7QUFDcEI7QUFXQSxTQUFTLGFBQWEsVUFBa0IsTUFBK0I7QUFDckUsU0FBTyxJQUFJLFFBQVEsQ0FBQyxTQUFTLFdBQVc7QUFDdEMsV0FBTztBQUFBLE1BQ0w7QUFBQSxNQUNBO0FBQUEsTUFDQTtBQUFBLE1BQ0E7QUFBQSxNQUNBO0FBQUEsTUFDQSxDQUFDLEtBQUssZUFBZTtBQUNuQixZQUFJLEtBQUs7QUFDUCxrQkFBUSxNQUFNLHlCQUF5QjtBQUN2QyxrQkFBUSxNQUFNLEdBQUc7QUFDakIsaUJBQU8sR0FBRztBQUNWO0FBQUEsUUFDRjtBQUNBLGNBQU0sT0FBTyxXQUFXLFNBQVMsS0FBSztBQUN0QyxnQkFBUSxJQUFJO0FBQUEsTUFDZDtBQUFBLElBQ0Y7QUFBQSxFQUNGLENBQUM7QUFDSDs7O0FDekNBLGVBQXNCQSxjQUFhLFVBQWtCO0FBQ25ELFFBQU0sRUFBQyxNQUFNLEtBQUksSUFBSSxNQUFNLGFBQWEsUUFBUTtBQUNoRCxVQUFRLElBQUksK0RBQStEO0FBQzNFLFVBQVEsSUFBSSxhQUFhO0FBQ3pCLFVBQVEsSUFBSSxZQUFZLElBQUksSUFBSTtBQUNoQyxVQUFRLElBQUksWUFBWSxJQUFJLElBQUk7QUFDaEMsVUFBUSxJQUFJLEdBQUc7QUFDakI7IiwKICAibmFtZXMiOiBbImdlbmVyYXRlSGFzaCJdCn0K
package/dist/core.d.ts ADDED
@@ -0,0 +1,2 @@
1
+
2
+ export { }
package/dist/core.js ADDED
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFtdLAogICJzb3VyY2VzQ29udGVudCI6IFtdLAogICJtYXBwaW5ncyI6ICIiLAogICJuYW1lcyI6IFtdCn0K
@@ -0,0 +1,36 @@
1
+ import { Plugin } from '@blinkk/root';
2
+
3
+ interface PasswordProtectedRoute {
4
+ /**
5
+ * URL glob pattern to match (regex not supported yet).
6
+ */
7
+ source: string;
8
+ password: {
9
+ /**
10
+ * A hash of the password. Note: a plain-text password should never be
11
+ * stored in code. Consider storing this value in a `.env` file for extra
12
+ * security.
13
+ *
14
+ * Generate this by running:
15
+ * ```
16
+ * root-password-protect generate-hash "MY_PASSWORD"
17
+ * ````
18
+ */
19
+ hash: string;
20
+ /**
21
+ * A random string used to generate the password hash.
22
+ *
23
+ * Generate this by running:
24
+ * ```
25
+ * root-password-protect generate-hash "MY_PASSWORD"
26
+ * ````
27
+ */
28
+ salt: string;
29
+ };
30
+ }
31
+ interface PasswordProtectPluginOptions {
32
+ protectedRoutes: PasswordProtectedRoute[];
33
+ }
34
+ declare function passwordProtectPlugin(options: PasswordProtectPluginOptions): Plugin;
35
+
36
+ export { type PasswordProtectPluginOptions, type PasswordProtectedRoute, passwordProtectPlugin };
package/dist/plugin.js ADDED
@@ -0,0 +1,311 @@
1
+ // core/plugin.ts
2
+ import bodyParser from "body-parser";
3
+ import micromatch from "micromatch";
4
+
5
+ // core/password-page.tsx
6
+ import { render as renderToString } from "preact-render-to-string";
7
+ import { jsx, jsxs } from "preact/jsx-runtime";
8
+ var CSS = `
9
+ .signin {
10
+ font-family: 'Google Sans', arial, sans-serif;
11
+ text-align: center;
12
+ padding: 48px 20px;
13
+ color: #3c4043;
14
+ }
15
+
16
+ .signin__headline {
17
+ margin-bottom: 40px;
18
+ }
19
+
20
+ .signin__headline__icon {
21
+ margin-bottom: 20px;
22
+ }
23
+
24
+ .signin__headline__icon svg {
25
+ width: 72px;
26
+ height: 72px;
27
+ }
28
+
29
+ .signin__headline__title {
30
+ font-size: 36px;
31
+ line-height: 1.3;
32
+ font-weight: 500;
33
+ margin-bottom: 20px;
34
+ }
35
+
36
+ .signin__headline__body {
37
+ font-size: 18px;
38
+ line-height: 1.5;
39
+ font-weight: 500;
40
+ }
41
+
42
+ .signin__form {
43
+ display: flex;
44
+ gap: 8px;
45
+ justify-content: center;
46
+ }
47
+
48
+ .signin__form__password {
49
+ box-sizing: border-box;
50
+ border: 1px solid #dadce0;
51
+ border-radius: 4px;
52
+ height: 40px;
53
+ font-family: inherit;
54
+ font-size: 14px;
55
+ line-height: 1;
56
+ letter-spacing: .25px;
57
+ padding: 0 12px;
58
+ min-width: 250px;
59
+ transition: all 0.218s ease;
60
+ }
61
+
62
+ .signin__form__password:focus {
63
+ border-color: #d2e3fc;
64
+ background-color: rgba(66, 133, 244, 0.04);
65
+ }
66
+
67
+ .signin__button {
68
+ align-items: center;
69
+ -webkit-appearance: none;
70
+ -moz-appearance: none;
71
+ appearance: none;
72
+ display: inline-flex;
73
+ align-items: center;
74
+ text-align: center;
75
+ gap: 12px;
76
+ padding: 8px 11px;
77
+ background: white;
78
+ border: 1px solid #dadce0;
79
+ border-radius: 4px;
80
+ cursor: pointer;
81
+ font-family: inherit;
82
+ padding: 0 12px;
83
+ height: 40px;
84
+ box-sizing: border-box;
85
+ transition: all 0.218s ease;
86
+ }
87
+
88
+ .signin__button:hover {
89
+ border-color: #d2e3fc;
90
+ background-color: rgba(66, 133, 244, 0.04);
91
+ }
92
+
93
+ .signin__button__icon {
94
+ width: 18px;
95
+ height: 18px;
96
+ background-color: white;
97
+ }
98
+
99
+ .signin__button__label {
100
+ font-size: 14px;
101
+ line-height: 1;
102
+ letter-spacing: .25px;
103
+ font-weight: 500;
104
+ color: #3c4043;
105
+ }
106
+
107
+ .signin__error {
108
+ color: red;
109
+ font-weight: bold;
110
+ text-align: center;
111
+ max-width: 60ch;
112
+ margin: 20px auto 0;
113
+ }
114
+ `;
115
+ function PasswordPage(props) {
116
+ return /* @__PURE__ */ jsxs("html", { children: [
117
+ /* @__PURE__ */ jsxs("head", { children: [
118
+ /* @__PURE__ */ jsx("meta", { charset: "utf-8" }),
119
+ /* @__PURE__ */ jsx("title", { children: "Protected" }),
120
+ /* @__PURE__ */ jsx(
121
+ "link",
122
+ {
123
+ rel: "icon",
124
+ href: "https://lh3.googleusercontent.com/ijK50TfQlV_yJw3i-CMlnD6osH4PboZBILZrJcWhoNMEmoyCD5e1bAxXbaOPe5w4gG_Scf37EXrmZ6p8sP2lue5fLZ419m5JyLMs=e385-w256",
125
+ type: "image/png"
126
+ }
127
+ ),
128
+ /* @__PURE__ */ jsx(
129
+ "link",
130
+ {
131
+ rel: "stylesheet",
132
+ href: "https://fonts.googleapis.com/css2?family=Google+Sans:wght@500&display=swap"
133
+ }
134
+ ),
135
+ /* @__PURE__ */ jsx("style", { children: CSS })
136
+ ] }),
137
+ /* @__PURE__ */ jsx("body", { children: /* @__PURE__ */ jsx("div", { id: "root", children: /* @__PURE__ */ jsxs("div", { className: "signin", children: [
138
+ /* @__PURE__ */ jsxs("div", { className: "signin__headline", children: [
139
+ /* @__PURE__ */ jsx("div", { className: "signin__headline__icon", children: /* @__PURE__ */ jsx(ShieldIcon, {}) }),
140
+ /* @__PURE__ */ jsx("h1", { children: "This page is protected." }),
141
+ /* @__PURE__ */ jsx("p", { className: "signin__headline__body", children: "Enter the password below to continue:" })
142
+ ] }),
143
+ /* @__PURE__ */ jsxs("form", { className: "signin__form", method: "POST", children: [
144
+ /* @__PURE__ */ jsx(
145
+ "input",
146
+ {
147
+ id: "password",
148
+ className: "signin__form__password",
149
+ name: "password",
150
+ type: "password",
151
+ placeholder: "Password"
152
+ }
153
+ ),
154
+ /* @__PURE__ */ jsx("button", { className: "signin__button", type: "submit", children: /* @__PURE__ */ jsx("div", { className: "signin__button__label", children: "Submit" }) })
155
+ ] }),
156
+ props.error && /* @__PURE__ */ jsx("p", { className: "signin__error", children: props.error })
157
+ ] }) }) })
158
+ ] });
159
+ }
160
+ function ShieldIcon() {
161
+ return /* @__PURE__ */ jsxs(
162
+ "svg",
163
+ {
164
+ xmlns: "http://www.w3.org/2000/svg",
165
+ class: "icon icon-tabler icon-tabler-shield-lock-filled",
166
+ width: "36",
167
+ height: "36",
168
+ viewBox: "0 0 24 24",
169
+ "stroke-width": "1.5",
170
+ stroke: "#ff4500",
171
+ fill: "none",
172
+ "stroke-linecap": "round",
173
+ "stroke-linejoin": "round",
174
+ children: [
175
+ /* @__PURE__ */ jsx("path", { stroke: "none", d: "M0 0h24v24H0z", fill: "none" }),
176
+ /* @__PURE__ */ jsx(
177
+ "path",
178
+ {
179
+ d: "M11.998 2l.118 .007l.059 .008l.061 .013l.111 .034a.993 .993 0 0 1 .217 .112l.104 .082l.255 .218a11 11 0 0 0 7.189 2.537l.342 -.01a1 1 0 0 1 1.005 .717a13 13 0 0 1 -9.208 16.25a1 1 0 0 1 -.502 0a13 13 0 0 1 -9.209 -16.25a1 1 0 0 1 1.005 -.717a11 11 0 0 0 7.531 -2.527l.263 -.225l.096 -.075a.993 .993 0 0 1 .217 -.112l.112 -.034a.97 .97 0 0 1 .119 -.021l.115 -.007zm.002 7a2 2 0 0 0 -1.995 1.85l-.005 .15l.005 .15a2 2 0 0 0 .995 1.581v1.769l.007 .117a1 1 0 0 0 1.993 -.117l.001 -1.768a2 2 0 0 0 -1.001 -3.732z",
180
+ "stroke-width": "0",
181
+ fill: "currentColor"
182
+ }
183
+ )
184
+ ]
185
+ }
186
+ );
187
+ }
188
+ async function renderPasswordPage(req, res, props) {
189
+ const mainHtml = renderToString(/* @__PURE__ */ jsx(PasswordPage, { ...props }));
190
+ const html = `<!doctype html>
191
+ ${mainHtml}`;
192
+ res.setHeader("Content-Type", "text/html");
193
+ res.send(html);
194
+ }
195
+
196
+ // core/password.ts
197
+ import crypto from "crypto";
198
+ var PASSWORD_ITERATIONS = 1e4;
199
+ var PASSWORD_HASH_LENGTH = 64;
200
+ var PASSWORD_DIGEST = "sha256";
201
+ async function hashPassword(password) {
202
+ const salt = crypto.randomBytes(16).toString("hex");
203
+ const hash = await generateHash(password, salt);
204
+ return { hash, salt };
205
+ }
206
+ async function verifyPassword(password, hash, salt) {
207
+ const generatedHash = await generateHash(password, salt);
208
+ return hash === generatedHash;
209
+ }
210
+ function generateHash(password, salt) {
211
+ return new Promise((resolve, reject) => {
212
+ crypto.pbkdf2(
213
+ password,
214
+ salt,
215
+ PASSWORD_ITERATIONS,
216
+ PASSWORD_HASH_LENGTH,
217
+ PASSWORD_DIGEST,
218
+ (err, derivedKey) => {
219
+ if (err) {
220
+ console.error("password hashing failed");
221
+ console.error(err);
222
+ reject(err);
223
+ return;
224
+ }
225
+ const hash = derivedKey.toString("hex");
226
+ resolve(hash);
227
+ }
228
+ );
229
+ });
230
+ }
231
+
232
+ // core/plugin.ts
233
+ function passwordProtectPlugin(options) {
234
+ const protectedRoutesUserConfig = options.protectedRoutes || [];
235
+ const protectedRoutes = protectedRoutesUserConfig.filter((protectedRoute) => {
236
+ return Boolean(
237
+ protectedRoute.source && protectedRoute.password && protectedRoute.password.hash && protectedRoute.password.salt
238
+ );
239
+ });
240
+ function getProtectedRouteConfig(req) {
241
+ for (const protectedRoute of protectedRoutes) {
242
+ if (micromatch.isMatch(req.path, protectedRoute.source)) {
243
+ return protectedRoute;
244
+ }
245
+ }
246
+ return null;
247
+ }
248
+ return {
249
+ name: "root-password-protect",
250
+ configureServer: (server) => {
251
+ if (protectedRoutes.length === 0) {
252
+ return;
253
+ }
254
+ server.use(bodyParser.urlencoded({ extended: true }));
255
+ server.use(async (req, res, next) => {
256
+ const protectedRoute = getProtectedRouteConfig(req);
257
+ if (protectedRoute) {
258
+ await handleProtectedRoute(protectedRoute, req, res, next);
259
+ return;
260
+ }
261
+ next();
262
+ });
263
+ }
264
+ };
265
+ }
266
+ async function handleProtectedRoute(protectedRoute, req, res, next) {
267
+ if (req.method === "POST") {
268
+ if (req.get("content-type") !== "application/x-www-form-urlencoded" || !req.body || !req.body.password) {
269
+ res.status(400);
270
+ renderPasswordPage(req, res, { error: "Bad request (no password)." });
271
+ return;
272
+ }
273
+ const password = req.body.password;
274
+ const isValid2 = await verifyPassword(
275
+ password,
276
+ protectedRoute.password.hash,
277
+ protectedRoute.password.salt
278
+ );
279
+ if (!isValid2) {
280
+ renderPasswordPage(req, res, { error: "Incorrect password." });
281
+ return;
282
+ }
283
+ await setSessionCookie(protectedRoute, res);
284
+ next();
285
+ return;
286
+ }
287
+ const isValid = await verifySessionCookie(protectedRoute, req);
288
+ if (isValid) {
289
+ next();
290
+ return;
291
+ }
292
+ renderPasswordPage(req, res);
293
+ }
294
+ async function setSessionCookie(protectedRoute, res) {
295
+ const { hash, salt } = await hashPassword(protectedRoute.password.hash);
296
+ res.session.setItem("password_protect.hash", hash);
297
+ res.session.setItem("password_protect.salt", salt);
298
+ res.saveSession();
299
+ }
300
+ async function verifySessionCookie(protectedRoute, req) {
301
+ const hash = req.session.getItem("password_protect.hash");
302
+ const salt = req.session.getItem("password_protect.salt");
303
+ if (!hash || !salt) {
304
+ return false;
305
+ }
306
+ return await verifyPassword(protectedRoute.password.hash, hash, salt);
307
+ }
308
+ export {
309
+ passwordProtectPlugin
310
+ };
311
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vY29yZS9wbHVnaW4udHMiLCAiLi4vY29yZS9wYXNzd29yZC1wYWdlLnRzeCIsICIuLi9jb3JlL3Bhc3N3b3JkLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyJpbXBvcnQge1JlcXVlc3QsIFJlc3BvbnNlLCBOZXh0RnVuY3Rpb24sIFBsdWdpbiwgU2VydmVyfSBmcm9tICdAYmxpbmtrL3Jvb3QnO1xuaW1wb3J0IGJvZHlQYXJzZXIgZnJvbSAnYm9keS1wYXJzZXInO1xuaW1wb3J0IG1pY3JvbWF0Y2ggZnJvbSAnbWljcm9tYXRjaCc7XG5pbXBvcnQge3JlbmRlclBhc3N3b3JkUGFnZX0gZnJvbSAnLi9wYXNzd29yZC1wYWdlLmpzJztcbmltcG9ydCB7aGFzaFBhc3N3b3JkLCB2ZXJpZnlQYXNzd29yZH0gZnJvbSAnLi9wYXNzd29yZC5qcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUGFzc3dvcmRQcm90ZWN0ZWRSb3V0ZSB7XG4gIC8qKlxuICAgKiBVUkwgZ2xvYiBwYXR0ZXJuIHRvIG1hdGNoIChyZWdleCBub3Qgc3VwcG9ydGVkIHlldCkuXG4gICAqL1xuICBzb3VyY2U6IHN0cmluZztcblxuICBwYXNzd29yZDoge1xuICAgIC8qKlxuICAgICAqIEEgaGFzaCBvZiB0aGUgcGFzc3dvcmQuIE5vdGU6IGEgcGxhaW4tdGV4dCBwYXNzd29yZCBzaG91bGQgbmV2ZXIgYmVcbiAgICAgKiBzdG9yZWQgaW4gY29kZS4gQ29uc2lkZXIgc3RvcmluZyB0aGlzIHZhbHVlIGluIGEgYC5lbnZgIGZpbGUgZm9yIGV4dHJhXG4gICAgICogc2VjdXJpdHkuXG4gICAgICpcbiAgICAgKiBHZW5lcmF0ZSB0aGlzIGJ5IHJ1bm5pbmc6XG4gICAgICogYGBgXG4gICAgICogcm9vdC1wYXNzd29yZC1wcm90ZWN0IGdlbmVyYXRlLWhhc2ggXCJNWV9QQVNTV09SRFwiXG4gICAgICogYGBgYFxuICAgICAqL1xuICAgIGhhc2g6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEEgcmFuZG9tIHN0cmluZyB1c2VkIHRvIGdlbmVyYXRlIHRoZSBwYXNzd29yZCBoYXNoLlxuICAgICAqXG4gICAgICogR2VuZXJhdGUgdGhpcyBieSBydW5uaW5nOlxuICAgICAqIGBgYFxuICAgICAqIHJvb3QtcGFzc3dvcmQtcHJvdGVjdCBnZW5lcmF0ZS1oYXNoIFwiTVlfUEFTU1dPUkRcIlxuICAgICAqIGBgYGBcbiAgICAgKi9cbiAgICBzYWx0OiBzdHJpbmc7XG4gIH07XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUGFzc3dvcmRQcm90ZWN0UGx1Z2luT3B0aW9ucyB7XG4gIHByb3RlY3RlZFJvdXRlczogUGFzc3dvcmRQcm90ZWN0ZWRSb3V0ZVtdO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcGFzc3dvcmRQcm90ZWN0UGx1Z2luKFxuICBvcHRpb25zOiBQYXNzd29yZFByb3RlY3RQbHVnaW5PcHRpb25zXG4pOiBQbHVnaW4ge1xuICBjb25zdCBwcm90ZWN0ZWRSb3V0ZXNVc2VyQ29uZmlnID0gb3B0aW9ucy5wcm90ZWN0ZWRSb3V0ZXMgfHwgW107XG4gIGNvbnN0IHByb3RlY3RlZFJvdXRlcyA9IHByb3RlY3RlZFJvdXRlc1VzZXJDb25maWcuZmlsdGVyKChwcm90ZWN0ZWRSb3V0ZSkgPT4ge1xuICAgIHJldHVybiBCb29sZWFuKFxuICAgICAgcHJvdGVjdGVkUm91dGUuc291cmNlICYmXG4gICAgICAgIHByb3RlY3RlZFJvdXRlLnBhc3N3b3JkICYmXG4gICAgICAgIHByb3RlY3RlZFJvdXRlLnBhc3N3b3JkLmhhc2ggJiZcbiAgICAgICAgcHJvdGVjdGVkUm91dGUucGFzc3dvcmQuc2FsdFxuICAgICk7XG4gIH0pO1xuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBmaXJzdCBwYXNzd29yZC1wcm90ZWN0ZWQgcm91dGUgdGhhdCBtYXRjaGVzLlxuICAgKi9cbiAgZnVuY3Rpb24gZ2V0UHJvdGVjdGVkUm91dGVDb25maWcoXG4gICAgcmVxOiBSZXF1ZXN0XG4gICk6IFBhc3N3b3JkUHJvdGVjdGVkUm91dGUgfCBudWxsIHtcbiAgICBmb3IgKGNvbnN0IHByb3RlY3RlZFJvdXRlIG9mIHByb3RlY3RlZFJvdXRlcykge1xuICAgICAgaWYgKG1pY3JvbWF0Y2guaXNNYXRjaChyZXEucGF0aCwgcHJvdGVjdGVkUm91dGUuc291cmNlKSkge1xuICAgICAgICByZXR1cm4gcHJvdGVjdGVkUm91dGU7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAncm9vdC1wYXNzd29yZC1wcm90ZWN0JyxcbiAgICBjb25maWd1cmVTZXJ2ZXI6IChzZXJ2ZXI6IFNlcnZlcikgPT4ge1xuICAgICAgaWYgKHByb3RlY3RlZFJvdXRlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgc2VydmVyLnVzZShib2R5UGFyc2VyLnVybGVuY29kZWQoe2V4dGVuZGVkOiB0cnVlfSkpO1xuICAgICAgc2VydmVyLnVzZShhc3luYyAocmVxOiBSZXF1ZXN0LCByZXM6IFJlc3BvbnNlLCBuZXh0OiBOZXh0RnVuY3Rpb24pID0+IHtcbiAgICAgICAgY29uc3QgcHJvdGVjdGVkUm91dGUgPSBnZXRQcm90ZWN0ZWRSb3V0ZUNvbmZpZyhyZXEpO1xuICAgICAgICBpZiAocHJvdGVjdGVkUm91dGUpIHtcbiAgICAgICAgICBhd2FpdCBoYW5kbGVQcm90ZWN0ZWRSb3V0ZShwcm90ZWN0ZWRSb3V0ZSwgcmVxLCByZXMsIG5leHQpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBuZXh0KCk7XG4gICAgICB9KTtcbiAgICB9LFxuICB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBoYW5kbGVQcm90ZWN0ZWRSb3V0ZShcbiAgcHJvdGVjdGVkUm91dGU6IFBhc3N3b3JkUHJvdGVjdGVkUm91dGUsXG4gIHJlcTogUmVxdWVzdCxcbiAgcmVzOiBSZXNwb25zZSxcbiAgbmV4dDogTmV4dEZ1bmN0aW9uXG4pIHtcbiAgaWYgKHJlcS5tZXRob2QgPT09ICdQT1NUJykge1xuICAgIC8vIFZlcmlmeSBwYXNzd29yZCBhbmQgaWYgdmFsaWQgc2V0IGEgc2Vzc2lvbiBjb29raWUuXG4gICAgaWYgKFxuICAgICAgcmVxLmdldCgnY29udGVudC10eXBlJykgIT09ICdhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQnIHx8XG4gICAgICAhcmVxLmJvZHkgfHxcbiAgICAgICFyZXEuYm9keS5wYXNzd29yZFxuICAgICkge1xuICAgICAgcmVzLnN0YXR1cyg0MDApO1xuICAgICAgcmVuZGVyUGFzc3dvcmRQYWdlKHJlcSwgcmVzLCB7ZXJyb3I6ICdCYWQgcmVxdWVzdCAobm8gcGFzc3dvcmQpLid9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBwYXNzd29yZCA9IHJlcS5ib2R5LnBhc3N3b3JkIGFzIHN0cmluZztcbiAgICBjb25zdCBpc1ZhbGlkID0gYXdhaXQgdmVyaWZ5UGFzc3dvcmQoXG4gICAgICBwYXNzd29yZCxcbiAgICAgIHByb3RlY3RlZFJvdXRlLnBhc3N3b3JkLmhhc2gsXG4gICAgICBwcm90ZWN0ZWRSb3V0ZS5wYXNzd29yZC5zYWx0XG4gICAgKTtcbiAgICBpZiAoIWlzVmFsaWQpIHtcbiAgICAgIHJlbmRlclBhc3N3b3JkUGFnZShyZXEsIHJlcywge2Vycm9yOiAnSW5jb3JyZWN0IHBhc3N3b3JkLid9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgLy8gU2V0IGEgc2Vzc2lvbiBjb29raWUgdmFsdWUgdG8gdmVyaWZ5IHN1YnNlcXVlbnQgcmVxdWVzdHMuXG4gICAgYXdhaXQgc2V0U2Vzc2lvbkNvb2tpZShwcm90ZWN0ZWRSb3V0ZSwgcmVzKTtcbiAgICBuZXh0KCk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8gSWYgcHJldmlvdXNseSBsb2dnZWQgaW4sIGNoZWNrIHRoZSBzZXNzaW9uIGNvb2tpZSBhZ2FpbnN0IHRoZSBjdXJyZW50XG4gIC8vIHBhc3N3b3JkIGhhc2guXG4gIGNvbnN0IGlzVmFsaWQgPSBhd2FpdCB2ZXJpZnlTZXNzaW9uQ29va2llKHByb3RlY3RlZFJvdXRlLCByZXEpO1xuICBpZiAoaXNWYWxpZCkge1xuICAgIG5leHQoKTtcbiAgICByZXR1cm47XG4gIH1cblxuICByZW5kZXJQYXNzd29yZFBhZ2UocmVxLCByZXMpO1xufVxuXG4vKipcbiAqIFNhdmVzIGEgdmVyaWZpY2F0aW9uIHRva2VuIHRvIHRoZSBzZXNzaW9uIGNvb2tpZSBmb3Igc3Vic2VxdWVudCByZXF1ZXN0cy5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gc2V0U2Vzc2lvbkNvb2tpZShcbiAgcHJvdGVjdGVkUm91dGU6IFBhc3N3b3JkUHJvdGVjdGVkUm91dGUsXG4gIHJlczogUmVzcG9uc2Vcbikge1xuICBjb25zdCB7aGFzaCwgc2FsdH0gPSBhd2FpdCBoYXNoUGFzc3dvcmQocHJvdGVjdGVkUm91dGUucGFzc3dvcmQuaGFzaCk7XG4gIHJlcy5zZXNzaW9uLnNldEl0ZW0oJ3Bhc3N3b3JkX3Byb3RlY3QuaGFzaCcsIGhhc2gpO1xuICByZXMuc2Vzc2lvbi5zZXRJdGVtKCdwYXNzd29yZF9wcm90ZWN0LnNhbHQnLCBzYWx0KTtcbiAgcmVzLnNhdmVTZXNzaW9uKCk7XG59XG5cbi8qKlxuICogVmVyaWZpZXMgdGhlIHNlc3Npb24gY29va2llIHZhbHVlIGlzIHZhbGlkLlxuICovXG5hc3luYyBmdW5jdGlvbiB2ZXJpZnlTZXNzaW9uQ29va2llKFxuICBwcm90ZWN0ZWRSb3V0ZTogUGFzc3dvcmRQcm90ZWN0ZWRSb3V0ZSxcbiAgcmVxOiBSZXF1ZXN0XG4pIHtcbiAgY29uc3QgaGFzaCA9IHJlcS5zZXNzaW9uLmdldEl0ZW0oJ3Bhc3N3b3JkX3Byb3RlY3QuaGFzaCcpO1xuICBjb25zdCBzYWx0ID0gcmVxLnNlc3Npb24uZ2V0SXRlbSgncGFzc3dvcmRfcHJvdGVjdC5zYWx0Jyk7XG4gIGlmICghaGFzaCB8fCAhc2FsdCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICByZXR1cm4gYXdhaXQgdmVyaWZ5UGFzc3dvcmQocHJvdGVjdGVkUm91dGUucGFzc3dvcmQuaGFzaCwgaGFzaCwgc2FsdCk7XG59XG4iLCAiaW1wb3J0IHBhdGggZnJvbSAnbm9kZTpwYXRoJztcbmltcG9ydCB7ZmlsZVVSTFRvUGF0aH0gZnJvbSAnbm9kZTp1cmwnO1xuaW1wb3J0IHtSZXF1ZXN0LCBSZXNwb25zZX0gZnJvbSAnQGJsaW5ray9yb290JztcbmltcG9ydCB7cmVuZGVyIGFzIHJlbmRlclRvU3RyaW5nfSBmcm9tICdwcmVhY3QtcmVuZGVyLXRvLXN0cmluZyc7XG5cbmNvbnN0IENTUyA9IGBcbi5zaWduaW4ge1xuICBmb250LWZhbWlseTogJ0dvb2dsZSBTYW5zJywgYXJpYWwsIHNhbnMtc2VyaWY7XG4gIHRleHQtYWxpZ246IGNlbnRlcjtcbiAgcGFkZGluZzogNDhweCAyMHB4O1xuICBjb2xvcjogIzNjNDA0Mztcbn1cblxuLnNpZ25pbl9faGVhZGxpbmUge1xuICBtYXJnaW4tYm90dG9tOiA0MHB4O1xufVxuXG4uc2lnbmluX19oZWFkbGluZV9faWNvbiB7XG4gIG1hcmdpbi1ib3R0b206IDIwcHg7XG59XG5cbi5zaWduaW5fX2hlYWRsaW5lX19pY29uIHN2ZyB7XG4gIHdpZHRoOiA3MnB4O1xuICBoZWlnaHQ6IDcycHg7XG59XG5cbi5zaWduaW5fX2hlYWRsaW5lX190aXRsZSB7XG4gIGZvbnQtc2l6ZTogMzZweDtcbiAgbGluZS1oZWlnaHQ6IDEuMztcbiAgZm9udC13ZWlnaHQ6IDUwMDtcbiAgbWFyZ2luLWJvdHRvbTogMjBweDtcbn1cblxuLnNpZ25pbl9faGVhZGxpbmVfX2JvZHkge1xuICBmb250LXNpemU6IDE4cHg7XG4gIGxpbmUtaGVpZ2h0OiAxLjU7XG4gIGZvbnQtd2VpZ2h0OiA1MDA7XG59XG5cbi5zaWduaW5fX2Zvcm0ge1xuICBkaXNwbGF5OiBmbGV4O1xuICBnYXA6IDhweDtcbiAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XG59XG5cbi5zaWduaW5fX2Zvcm1fX3Bhc3N3b3JkIHtcbiAgYm94LXNpemluZzogYm9yZGVyLWJveDtcbiAgYm9yZGVyOiAxcHggc29saWQgI2RhZGNlMDtcbiAgYm9yZGVyLXJhZGl1czogNHB4O1xuICBoZWlnaHQ6IDQwcHg7XG4gIGZvbnQtZmFtaWx5OiBpbmhlcml0O1xuICBmb250LXNpemU6IDE0cHg7XG4gIGxpbmUtaGVpZ2h0OiAxO1xuICBsZXR0ZXItc3BhY2luZzogLjI1cHg7XG4gIHBhZGRpbmc6IDAgMTJweDtcbiAgbWluLXdpZHRoOiAyNTBweDtcbiAgdHJhbnNpdGlvbjogYWxsIDAuMjE4cyBlYXNlO1xufVxuXG4uc2lnbmluX19mb3JtX19wYXNzd29yZDpmb2N1cyB7XG4gIGJvcmRlci1jb2xvcjogI2QyZTNmYztcbiAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSg2NiwgMTMzLCAyNDQsIDAuMDQpO1xufVxuXG4uc2lnbmluX19idXR0b24ge1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAtd2Via2l0LWFwcGVhcmFuY2U6IG5vbmU7XG4gIC1tb3otYXBwZWFyYW5jZTogbm9uZTtcbiAgYXBwZWFyYW5jZTogbm9uZTtcbiAgZGlzcGxheTogaW5saW5lLWZsZXg7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIHRleHQtYWxpZ246IGNlbnRlcjtcbiAgZ2FwOiAxMnB4O1xuICBwYWRkaW5nOiA4cHggMTFweDtcbiAgYmFja2dyb3VuZDogd2hpdGU7XG4gIGJvcmRlcjogMXB4IHNvbGlkICNkYWRjZTA7XG4gIGJvcmRlci1yYWRpdXM6IDRweDtcbiAgY3Vyc29yOiBwb2ludGVyO1xuICBmb250LWZhbWlseTogaW5oZXJpdDtcbiAgcGFkZGluZzogMCAxMnB4O1xuICBoZWlnaHQ6IDQwcHg7XG4gIGJveC1zaXppbmc6IGJvcmRlci1ib3g7XG4gIHRyYW5zaXRpb246IGFsbCAwLjIxOHMgZWFzZTtcbn1cblxuLnNpZ25pbl9fYnV0dG9uOmhvdmVyIHtcbiAgYm9yZGVyLWNvbG9yOiAjZDJlM2ZjO1xuICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDY2LCAxMzMsIDI0NCwgMC4wNCk7XG59XG5cbi5zaWduaW5fX2J1dHRvbl9faWNvbiB7XG4gIHdpZHRoOiAxOHB4O1xuICBoZWlnaHQ6IDE4cHg7XG4gIGJhY2tncm91bmQtY29sb3I6IHdoaXRlO1xufVxuXG4uc2lnbmluX19idXR0b25fX2xhYmVsIHtcbiAgZm9udC1zaXplOiAxNHB4O1xuICBsaW5lLWhlaWdodDogMTtcbiAgbGV0dGVyLXNwYWNpbmc6IC4yNXB4O1xuICBmb250LXdlaWdodDogNTAwO1xuICBjb2xvcjogIzNjNDA0Mztcbn1cblxuLnNpZ25pbl9fZXJyb3Ige1xuICBjb2xvcjogcmVkO1xuICBmb250LXdlaWdodDogYm9sZDtcbiAgdGV4dC1hbGlnbjogY2VudGVyO1xuICBtYXgtd2lkdGg6IDYwY2g7XG4gIG1hcmdpbjogMjBweCBhdXRvIDA7XG59XG5gO1xuXG5pbnRlcmZhY2UgUGFzc3dvcmRQYWdlUHJvcHMge1xuICBlcnJvcj86IHN0cmluZztcbn1cblxuZnVuY3Rpb24gUGFzc3dvcmRQYWdlKHByb3BzOiBQYXNzd29yZFBhZ2VQcm9wcykge1xuICByZXR1cm4gKFxuICAgIDxodG1sPlxuICAgICAgPGhlYWQ+XG4gICAgICAgIDxtZXRhIGNoYXJzZXQ9XCJ1dGYtOFwiIC8+XG4gICAgICAgIDx0aXRsZT5Qcm90ZWN0ZWQ8L3RpdGxlPlxuICAgICAgICA8bGlua1xuICAgICAgICAgIHJlbD1cImljb25cIlxuICAgICAgICAgIGhyZWY9XCJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vaWpLNTBUZlFsVl95SnczaS1DTWxuRDZvc0g0UGJvWkJJTFpySmNXaG9OTUVtb3lDRDVlMWJBeFhiYU9QZTV3NGdHX1NjZjM3RVhybVo2cDhzUDJsdWU1ZkxaNDE5bTVKeUxNcz1lMzg1LXcyNTZcIlxuICAgICAgICAgIHR5cGU9XCJpbWFnZS9wbmdcIlxuICAgICAgICAvPlxuICAgICAgICA8bGlua1xuICAgICAgICAgIHJlbD1cInN0eWxlc2hlZXRcIlxuICAgICAgICAgIGhyZWY9XCJodHRwczovL2ZvbnRzLmdvb2dsZWFwaXMuY29tL2NzczI/ZmFtaWx5PUdvb2dsZStTYW5zOndnaHRANTAwJmRpc3BsYXk9c3dhcFwiXG4gICAgICAgIC8+XG4gICAgICAgIDxzdHlsZT57Q1NTfTwvc3R5bGU+XG4gICAgICA8L2hlYWQ+XG4gICAgICA8Ym9keT5cbiAgICAgICAgPGRpdiBpZD1cInJvb3RcIj5cbiAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cInNpZ25pblwiPlxuICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJzaWduaW5fX2hlYWRsaW5lXCI+XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwic2lnbmluX19oZWFkbGluZV9faWNvblwiPlxuICAgICAgICAgICAgICAgIDxTaGllbGRJY29uIC8+XG4gICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICA8aDE+VGhpcyBwYWdlIGlzIHByb3RlY3RlZC48L2gxPlxuICAgICAgICAgICAgICA8cCBjbGFzc05hbWU9XCJzaWduaW5fX2hlYWRsaW5lX19ib2R5XCI+XG4gICAgICAgICAgICAgICAgRW50ZXIgdGhlIHBhc3N3b3JkIGJlbG93IHRvIGNvbnRpbnVlOlxuICAgICAgICAgICAgICA8L3A+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDxmb3JtIGNsYXNzTmFtZT1cInNpZ25pbl9fZm9ybVwiIG1ldGhvZD1cIlBPU1RcIj5cbiAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgaWQ9XCJwYXNzd29yZFwiXG4gICAgICAgICAgICAgICAgY2xhc3NOYW1lPVwic2lnbmluX19mb3JtX19wYXNzd29yZFwiXG4gICAgICAgICAgICAgICAgbmFtZT1cInBhc3N3b3JkXCJcbiAgICAgICAgICAgICAgICB0eXBlPVwicGFzc3dvcmRcIlxuICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwiUGFzc3dvcmRcIlxuICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICA8YnV0dG9uIGNsYXNzTmFtZT1cInNpZ25pbl9fYnV0dG9uXCIgdHlwZT1cInN1Ym1pdFwiPlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwic2lnbmluX19idXR0b25fX2xhYmVsXCI+U3VibWl0PC9kaXY+XG4gICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgPC9mb3JtPlxuICAgICAgICAgICAge3Byb3BzLmVycm9yICYmIDxwIGNsYXNzTmFtZT1cInNpZ25pbl9fZXJyb3JcIj57cHJvcHMuZXJyb3J9PC9wPn1cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2JvZHk+XG4gICAgPC9odG1sPlxuICApO1xufVxuXG5mdW5jdGlvbiBTaGllbGRJY29uKCkge1xuICByZXR1cm4gKFxuICAgIDxzdmdcbiAgICAgIHhtbG5zPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIlxuICAgICAgY2xhc3M9XCJpY29uIGljb24tdGFibGVyIGljb24tdGFibGVyLXNoaWVsZC1sb2NrLWZpbGxlZFwiXG4gICAgICB3aWR0aD1cIjM2XCJcbiAgICAgIGhlaWdodD1cIjM2XCJcbiAgICAgIHZpZXdCb3g9XCIwIDAgMjQgMjRcIlxuICAgICAgc3Ryb2tlLXdpZHRoPVwiMS41XCJcbiAgICAgIHN0cm9rZT1cIiNmZjQ1MDBcIlxuICAgICAgZmlsbD1cIm5vbmVcIlxuICAgICAgc3Ryb2tlLWxpbmVjYXA9XCJyb3VuZFwiXG4gICAgICBzdHJva2UtbGluZWpvaW49XCJyb3VuZFwiXG4gICAgPlxuICAgICAgPHBhdGggc3Ryb2tlPVwibm9uZVwiIGQ9XCJNMCAwaDI0djI0SDB6XCIgZmlsbD1cIm5vbmVcIiAvPlxuICAgICAgPHBhdGhcbiAgICAgICAgZD1cIk0xMS45OTggMmwuMTE4IC4wMDdsLjA1OSAuMDA4bC4wNjEgLjAxM2wuMTExIC4wMzRhLjk5MyAuOTkzIDAgMCAxIC4yMTcgLjExMmwuMTA0IC4wODJsLjI1NSAuMjE4YTExIDExIDAgMCAwIDcuMTg5IDIuNTM3bC4zNDIgLS4wMWExIDEgMCAwIDEgMS4wMDUgLjcxN2ExMyAxMyAwIDAgMSAtOS4yMDggMTYuMjVhMSAxIDAgMCAxIC0uNTAyIDBhMTMgMTMgMCAwIDEgLTkuMjA5IC0xNi4yNWExIDEgMCAwIDEgMS4wMDUgLS43MTdhMTEgMTEgMCAwIDAgNy41MzEgLTIuNTI3bC4yNjMgLS4yMjVsLjA5NiAtLjA3NWEuOTkzIC45OTMgMCAwIDEgLjIxNyAtLjExMmwuMTEyIC0uMDM0YS45NyAuOTcgMCAwIDEgLjExOSAtLjAyMWwuMTE1IC0uMDA3em0uMDAyIDdhMiAyIDAgMCAwIC0xLjk5NSAxLjg1bC0uMDA1IC4xNWwuMDA1IC4xNWEyIDIgMCAwIDAgLjk5NSAxLjU4MXYxLjc2OWwuMDA3IC4xMTdhMSAxIDAgMCAwIDEuOTkzIC0uMTE3bC4wMDEgLTEuNzY4YTIgMiAwIDAgMCAtMS4wMDEgLTMuNzMyelwiXG4gICAgICAgIHN0cm9rZS13aWR0aD1cIjBcIlxuICAgICAgICBmaWxsPVwiY3VycmVudENvbG9yXCJcbiAgICAgIC8+XG4gICAgPC9zdmc+XG4gICk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZW5kZXJQYXNzd29yZFBhZ2UoXG4gIHJlcTogUmVxdWVzdCxcbiAgcmVzOiBSZXNwb25zZSxcbiAgcHJvcHM/OiBQYXNzd29yZFBhZ2VQcm9wc1xuKSB7XG4gIGNvbnN0IG1haW5IdG1sID0gcmVuZGVyVG9TdHJpbmcoPFBhc3N3b3JkUGFnZSB7Li4ucHJvcHN9IC8+KTtcbiAgY29uc3QgaHRtbCA9IGA8IWRvY3R5cGUgaHRtbD5cXG4ke21haW5IdG1sfWA7XG4gIHJlcy5zZXRIZWFkZXIoJ0NvbnRlbnQtVHlwZScsICd0ZXh0L2h0bWwnKTtcbiAgcmVzLnNlbmQoaHRtbCk7XG59XG4iLCAiaW1wb3J0IGNyeXB0byBmcm9tICdjcnlwdG8nO1xuXG5jb25zdCBQQVNTV09SRF9JVEVSQVRJT05TID0gMTAwMDA7XG5jb25zdCBQQVNTV09SRF9IQVNIX0xFTkdUSCA9IDY0O1xuY29uc3QgUEFTU1dPUkRfRElHRVNUID0gJ3NoYTI1Nic7XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBoYXNoUGFzc3dvcmQoXG4gIHBhc3N3b3JkOiBzdHJpbmdcbik6IFByb21pc2U8e2hhc2g6IHN0cmluZzsgc2FsdDogc3RyaW5nfT4ge1xuICBjb25zdCBzYWx0ID0gY3J5cHRvLnJhbmRvbUJ5dGVzKDE2KS50b1N0cmluZygnaGV4Jyk7XG4gIGNvbnN0IGhhc2ggPSBhd2FpdCBnZW5lcmF0ZUhhc2gocGFzc3dvcmQsIHNhbHQpO1xuICByZXR1cm4ge2hhc2gsIHNhbHR9O1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gdmVyaWZ5UGFzc3dvcmQoXG4gIHBhc3N3b3JkOiBzdHJpbmcsXG4gIGhhc2g6IHN0cmluZyxcbiAgc2FsdDogc3RyaW5nXG4pOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgY29uc3QgZ2VuZXJhdGVkSGFzaCA9IGF3YWl0IGdlbmVyYXRlSGFzaChwYXNzd29yZCwgc2FsdCk7XG4gIHJldHVybiBoYXNoID09PSBnZW5lcmF0ZWRIYXNoO1xufVxuXG5mdW5jdGlvbiBnZW5lcmF0ZUhhc2gocGFzc3dvcmQ6IHN0cmluZywgc2FsdDogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICBjcnlwdG8ucGJrZGYyKFxuICAgICAgcGFzc3dvcmQsXG4gICAgICBzYWx0LFxuICAgICAgUEFTU1dPUkRfSVRFUkFUSU9OUyxcbiAgICAgIFBBU1NXT1JEX0hBU0hfTEVOR1RILFxuICAgICAgUEFTU1dPUkRfRElHRVNULFxuICAgICAgKGVyciwgZGVyaXZlZEtleSkgPT4ge1xuICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcigncGFzc3dvcmQgaGFzaGluZyBmYWlsZWQnKTtcbiAgICAgICAgICBjb25zb2xlLmVycm9yKGVycik7XG4gICAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGhhc2ggPSBkZXJpdmVkS2V5LnRvU3RyaW5nKCdoZXgnKTtcbiAgICAgICAgcmVzb2x2ZShoYXNoKTtcbiAgICAgIH1cbiAgICApO1xuICB9KTtcbn1cbiJdLAogICJtYXBwaW5ncyI6ICI7QUFDQSxPQUFPLGdCQUFnQjtBQUN2QixPQUFPLGdCQUFnQjs7O0FDQ3ZCLFNBQVEsVUFBVSxzQkFBcUI7QUFxSGpDLFNBQ0UsS0FERjtBQW5ITixJQUFNLE1BQU07QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQWdIWixTQUFTLGFBQWEsT0FBMEI7QUFDOUMsU0FDRSxxQkFBQyxVQUNDO0FBQUEseUJBQUMsVUFDQztBQUFBLDBCQUFDLFVBQUssU0FBUSxTQUFRO0FBQUEsTUFDdEIsb0JBQUMsV0FBTSx1QkFBUztBQUFBLE1BQ2hCO0FBQUEs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
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "@blinkk/root-password-protect",
3
+ "version": "1.0.0-rc.34",
4
+ "author": "s@blinkk.com",
5
+ "license": "MIT",
6
+ "engines": {
7
+ "node": ">=16.0.0"
8
+ },
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/blinkk/rootjs.git",
12
+ "directory": "packages/root-password-protect"
13
+ },
14
+ "files": [
15
+ "dist/**/*"
16
+ ],
17
+ "bin": {
18
+ "root-password-protect": "./bin/root-password-protect.js"
19
+ },
20
+ "type": "module",
21
+ "module": "./dist/index.js",
22
+ "types": "./dist/index.d.ts",
23
+ "exports": {
24
+ ".": {
25
+ "types": "./dist/core.d.ts",
26
+ "import": "./dist/core.js"
27
+ },
28
+ "./plugin": {
29
+ "types": "./dist/plugin.d.ts",
30
+ "import": "./dist/plugin.js"
31
+ }
32
+ },
33
+ "dependencies": {
34
+ "@types/micromatch": "4.0.6",
35
+ "body-parser": "1.20.2",
36
+ "commander": "11.0.0",
37
+ "kleur": "4.1.5",
38
+ "micromatch": "4.0.5"
39
+ },
40
+ "peerDependencies": {
41
+ "@blinkk/root": "1.0.0-rc.34",
42
+ "firebase-admin": ">=11",
43
+ "firebase-functions": ">=4",
44
+ "preact": ">=10",
45
+ "preact-render-to-string": ">=5"
46
+ },
47
+ "devDependencies": {
48
+ "@types/body-parser": "1.19.3",
49
+ "@types/node": "20.11.25",
50
+ "preact": "10.19.3",
51
+ "preact-render-to-string": "6.3.1",
52
+ "tsup": "8.0.1",
53
+ "vite": "5.0.8",
54
+ "@blinkk/root": "1.0.0-rc.34"
55
+ },
56
+ "scripts": {
57
+ "build": "tsup-node --config=./core/tsup.config.ts",
58
+ "dev": "pnpm build --watch",
59
+ "test": "pnpm build"
60
+ }
61
+ }