@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 +22 -0
- package/bin/root-password-protect.js +26 -0
- package/dist/cli.js +45 -0
- package/dist/core.d.ts +2 -0
- package/dist/core.js +1 -0
- package/dist/plugin.d.ts +36 -0
- package/dist/plugin.js +311 -0
- package/package.json +61 -0
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
package/dist/core.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFtdLAogICJzb3VyY2VzQ29udGVudCI6IFtdLAogICJtYXBwaW5ncyI6ICIiLAogICJuYW1lcyI6IFtdCn0K
|
package/dist/plugin.d.ts
ADDED
|
@@ -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
|
+
}
|