@se-oss/htpasswd 1.0.0 → 1.0.1
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/dist/chunk-2R65SLIB.cjs +100 -0
- package/dist/chunk-BXMJPERD.cjs +108 -0
- package/dist/fs.cjs +8 -226
- package/dist/index.cjs +7 -131
- package/package.json +18 -16
- package/dist/cli.cjs +0 -230
- package/dist/cli.d.ts +0 -1
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }// src/index.ts
|
|
2
|
+
var _apr1 = require('@se-oss/apr1');
|
|
3
|
+
var _bcryptjs = require('bcryptjs'); var _bcryptjs2 = _interopRequireDefault(_bcryptjs);
|
|
4
|
+
|
|
5
|
+
// src/sha1.ts
|
|
6
|
+
var _sha1 = require('@se-oss/sha1');
|
|
7
|
+
|
|
8
|
+
// src/utils.ts
|
|
9
|
+
var _timingsafecompare = require('@se-oss/timing-safe-compare');
|
|
10
|
+
function detectAlgorithm(hash) {
|
|
11
|
+
if (hash.startsWith("$2y$") || hash.startsWith("$2a$") || hash.startsWith("$2b$")) {
|
|
12
|
+
return "bcrypt";
|
|
13
|
+
}
|
|
14
|
+
if (hash.startsWith("$apr1$")) {
|
|
15
|
+
return "md5";
|
|
16
|
+
}
|
|
17
|
+
if (hash.startsWith("{SHA}")) {
|
|
18
|
+
return "sha1";
|
|
19
|
+
}
|
|
20
|
+
if (hash.length === 13) {
|
|
21
|
+
return "crypt";
|
|
22
|
+
}
|
|
23
|
+
return "plain";
|
|
24
|
+
}
|
|
25
|
+
function bytesToBase64(bytes) {
|
|
26
|
+
if (typeof Buffer !== "undefined") {
|
|
27
|
+
return Buffer.from(bytes).toString("base64");
|
|
28
|
+
}
|
|
29
|
+
return btoa(String.fromCharCode(...bytes));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// src/sha1.ts
|
|
33
|
+
function verifySha1(password, hash) {
|
|
34
|
+
return _timingsafecompare.safeCompare.call(void 0, generateSha1(password), hash);
|
|
35
|
+
}
|
|
36
|
+
function generateSha1(password) {
|
|
37
|
+
const digest = _sha1.sha1.call(void 0, password);
|
|
38
|
+
const b64 = bytesToBase64(digest);
|
|
39
|
+
return `{SHA}${b64}`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// src/index.ts
|
|
43
|
+
function verify(password, hash) {
|
|
44
|
+
const algo = detectAlgorithm(hash);
|
|
45
|
+
switch (algo) {
|
|
46
|
+
case "bcrypt":
|
|
47
|
+
return _bcryptjs2.default.compareSync(password, hash);
|
|
48
|
+
case "md5":
|
|
49
|
+
return _apr1.verifyApr1.call(void 0, password, hash);
|
|
50
|
+
case "sha1":
|
|
51
|
+
return verifySha1(password, hash);
|
|
52
|
+
case "plain":
|
|
53
|
+
return _timingsafecompare.safeCompare.call(void 0, password, hash);
|
|
54
|
+
case "crypt":
|
|
55
|
+
throw new Error('Algorithm "crypt" is insecure and not supported.');
|
|
56
|
+
default:
|
|
57
|
+
throw new Error(`Unsupported algorithm: ${algo}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
async function verifyAsync(password, hash) {
|
|
61
|
+
const algo = detectAlgorithm(hash);
|
|
62
|
+
switch (algo) {
|
|
63
|
+
case "bcrypt":
|
|
64
|
+
return _bcryptjs2.default.compare(password, hash);
|
|
65
|
+
case "md5":
|
|
66
|
+
return _apr1.verifyApr1.call(void 0, password, hash);
|
|
67
|
+
case "sha1":
|
|
68
|
+
return verifySha1(password, hash);
|
|
69
|
+
case "plain":
|
|
70
|
+
return _timingsafecompare.safeCompare.call(void 0, password, hash);
|
|
71
|
+
case "crypt":
|
|
72
|
+
throw new Error('Algorithm "crypt" is insecure and not supported.');
|
|
73
|
+
default:
|
|
74
|
+
throw new Error(`Unsupported algorithm: ${algo}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function parse(content, options = {}) {
|
|
78
|
+
return content.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#")).map((line) => {
|
|
79
|
+
const [username, ...rest] = line.split(":");
|
|
80
|
+
const hash = rest.join(":");
|
|
81
|
+
const algorithm = detectAlgorithm(hash);
|
|
82
|
+
if (algorithm === "plain" && !options.unsafe) {
|
|
83
|
+
throw new Error(
|
|
84
|
+
`Plaintext password detected for user "${username}". Use options.unsafe to allow this.`
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
return { username, hash, algorithm };
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
function stringify(entries) {
|
|
91
|
+
return entries.map((entry) => `${entry.username}:${entry.hash}`).join("\n");
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
exports.generateSha1 = generateSha1; exports.verify = verify; exports.verifyAsync = verifyAsync; exports.parse = parse; exports.stringify = stringify;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
var _chunk2R65SLIBcjs = require('./chunk-2R65SLIB.cjs');
|
|
8
|
+
|
|
9
|
+
// src/fs.ts
|
|
10
|
+
var _promises = require('fs/promises');
|
|
11
|
+
var _apr1 = require('@se-oss/apr1');
|
|
12
|
+
var _bcryptjs = require('bcryptjs'); var _bcryptjs2 = _interopRequireDefault(_bcryptjs);
|
|
13
|
+
async function readEntries(filepath, handleEnoent = false) {
|
|
14
|
+
try {
|
|
15
|
+
const content = await _promises.readFile.call(void 0, filepath, "utf-8");
|
|
16
|
+
return _chunk2R65SLIBcjs.parse.call(void 0, content, { unsafe: true });
|
|
17
|
+
} catch (error) {
|
|
18
|
+
if (handleEnoent && error.code === "ENOENT") {
|
|
19
|
+
return [];
|
|
20
|
+
}
|
|
21
|
+
throw error;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
async function writeAtomic(filepath, content) {
|
|
25
|
+
const tempPath = `${filepath}.${Math.random().toString(36).slice(2)}.tmp`;
|
|
26
|
+
await _promises.writeFile.call(void 0, tempPath, content);
|
|
27
|
+
await _promises.rename.call(void 0, tempPath, filepath);
|
|
28
|
+
}
|
|
29
|
+
async function updateAndSave(filepath, username, hash, algorithm) {
|
|
30
|
+
const entries = await readEntries(filepath, true);
|
|
31
|
+
const existingIndex = entries.findIndex((e) => e.username === username);
|
|
32
|
+
if (existingIndex !== -1) {
|
|
33
|
+
entries[existingIndex].hash = hash;
|
|
34
|
+
entries[existingIndex].algorithm = algorithm;
|
|
35
|
+
} else {
|
|
36
|
+
entries.push({ username, hash, algorithm });
|
|
37
|
+
}
|
|
38
|
+
await writeAtomic(filepath, _chunk2R65SLIBcjs.stringify.call(void 0, entries) + "\n");
|
|
39
|
+
}
|
|
40
|
+
async function authenticate(filepath, username, password) {
|
|
41
|
+
const entries = await readEntries(filepath);
|
|
42
|
+
const entry = entries.find((e) => e.username === username);
|
|
43
|
+
if (!entry) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
return _chunk2R65SLIBcjs.verify.call(void 0, password, entry.hash);
|
|
47
|
+
}
|
|
48
|
+
async function authenticateAsync(filepath, username, password) {
|
|
49
|
+
const entries = await readEntries(filepath);
|
|
50
|
+
const entry = entries.find((e) => e.username === username);
|
|
51
|
+
if (!entry) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
return _chunk2R65SLIBcjs.verifyAsync.call(void 0, password, entry.hash);
|
|
55
|
+
}
|
|
56
|
+
async function addUser(filepath, username, password, algorithm = "bcrypt") {
|
|
57
|
+
let hash;
|
|
58
|
+
switch (algorithm) {
|
|
59
|
+
case "bcrypt":
|
|
60
|
+
hash = _bcryptjs2.default.hashSync(password, 10);
|
|
61
|
+
break;
|
|
62
|
+
case "md5":
|
|
63
|
+
hash = _apr1.generateApr1.call(void 0, password);
|
|
64
|
+
break;
|
|
65
|
+
case "sha1":
|
|
66
|
+
hash = _chunk2R65SLIBcjs.generateSha1.call(void 0, password);
|
|
67
|
+
break;
|
|
68
|
+
case "plain":
|
|
69
|
+
hash = password;
|
|
70
|
+
break;
|
|
71
|
+
default:
|
|
72
|
+
throw new Error(`Unsupported algorithm for generation: ${algorithm}`);
|
|
73
|
+
}
|
|
74
|
+
await updateAndSave(filepath, username, hash, algorithm);
|
|
75
|
+
}
|
|
76
|
+
async function addUserAsync(filepath, username, password, algorithm = "bcrypt") {
|
|
77
|
+
let hash;
|
|
78
|
+
switch (algorithm) {
|
|
79
|
+
case "bcrypt":
|
|
80
|
+
hash = await _bcryptjs2.default.hash(password, 10);
|
|
81
|
+
break;
|
|
82
|
+
case "md5":
|
|
83
|
+
hash = _apr1.generateApr1.call(void 0, password);
|
|
84
|
+
break;
|
|
85
|
+
case "sha1":
|
|
86
|
+
hash = _chunk2R65SLIBcjs.generateSha1.call(void 0, password);
|
|
87
|
+
break;
|
|
88
|
+
case "plain":
|
|
89
|
+
hash = password;
|
|
90
|
+
break;
|
|
91
|
+
default:
|
|
92
|
+
throw new Error(`Unsupported algorithm for generation: ${algorithm}`);
|
|
93
|
+
}
|
|
94
|
+
await updateAndSave(filepath, username, hash, algorithm);
|
|
95
|
+
}
|
|
96
|
+
async function removeUser(filepath, username) {
|
|
97
|
+
const entries = await readEntries(filepath);
|
|
98
|
+
const newEntries = entries.filter((e) => e.username !== username);
|
|
99
|
+
await writeAtomic(filepath, _chunk2R65SLIBcjs.stringify.call(void 0, newEntries) + "\n");
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
exports.authenticate = authenticate; exports.authenticateAsync = authenticateAsync; exports.addUser = addUser; exports.addUserAsync = addUserAsync; exports.removeUser = removeUser;
|
package/dist/fs.cjs
CHANGED
|
@@ -1,233 +1,15 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __export = (target, all) => {
|
|
9
|
-
for (var name in all)
|
|
10
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
-
};
|
|
12
|
-
var __copyProps = (to, from, except, desc) => {
|
|
13
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
-
for (let key of __getOwnPropNames(from))
|
|
15
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
-
}
|
|
18
|
-
return to;
|
|
19
|
-
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
29
2
|
|
|
30
|
-
// src/fs.ts
|
|
31
|
-
var fs_exports = {};
|
|
32
|
-
__export(fs_exports, {
|
|
33
|
-
addUser: () => addUser,
|
|
34
|
-
addUserAsync: () => addUserAsync,
|
|
35
|
-
authenticate: () => authenticate,
|
|
36
|
-
authenticateAsync: () => authenticateAsync,
|
|
37
|
-
removeUser: () => removeUser
|
|
38
|
-
});
|
|
39
|
-
module.exports = __toCommonJS(fs_exports);
|
|
40
|
-
var import_promises = require("fs/promises");
|
|
41
|
-
var import_apr12 = require("@se-oss/apr1");
|
|
42
|
-
var import_bcryptjs2 = __toESM(require("bcryptjs"), 1);
|
|
43
3
|
|
|
44
|
-
// src/index.ts
|
|
45
|
-
var import_apr1 = require("@se-oss/apr1");
|
|
46
|
-
var import_bcryptjs = __toESM(require("bcryptjs"), 1);
|
|
47
4
|
|
|
48
|
-
// src/sha1.ts
|
|
49
|
-
var import_sha1 = require("@se-oss/sha1");
|
|
50
5
|
|
|
51
|
-
// src/utils.ts
|
|
52
|
-
var import_timing_safe_compare = require("@se-oss/timing-safe-compare");
|
|
53
|
-
function detectAlgorithm(hash) {
|
|
54
|
-
if (hash.startsWith("$2y$") || hash.startsWith("$2a$") || hash.startsWith("$2b$")) {
|
|
55
|
-
return "bcrypt";
|
|
56
|
-
}
|
|
57
|
-
if (hash.startsWith("$apr1$")) {
|
|
58
|
-
return "md5";
|
|
59
|
-
}
|
|
60
|
-
if (hash.startsWith("{SHA}")) {
|
|
61
|
-
return "sha1";
|
|
62
|
-
}
|
|
63
|
-
if (hash.length === 13) {
|
|
64
|
-
return "crypt";
|
|
65
|
-
}
|
|
66
|
-
return "plain";
|
|
67
|
-
}
|
|
68
|
-
function bytesToBase64(bytes) {
|
|
69
|
-
if (typeof Buffer !== "undefined") {
|
|
70
|
-
return Buffer.from(bytes).toString("base64");
|
|
71
|
-
}
|
|
72
|
-
return btoa(String.fromCharCode(...bytes));
|
|
73
|
-
}
|
|
74
6
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
return (0, import_timing_safe_compare.safeCompare)(generateSha1(password), hash);
|
|
78
|
-
}
|
|
79
|
-
function generateSha1(password) {
|
|
80
|
-
const digest = (0, import_sha1.sha1)(password);
|
|
81
|
-
const b64 = bytesToBase64(digest);
|
|
82
|
-
return `{SHA}${b64}`;
|
|
83
|
-
}
|
|
7
|
+
var _chunkBXMJPERDcjs = require('./chunk-BXMJPERD.cjs');
|
|
8
|
+
require('./chunk-2R65SLIB.cjs');
|
|
84
9
|
|
|
85
|
-
// src/index.ts
|
|
86
|
-
function verify(password, hash) {
|
|
87
|
-
const algo = detectAlgorithm(hash);
|
|
88
|
-
switch (algo) {
|
|
89
|
-
case "bcrypt":
|
|
90
|
-
return import_bcryptjs.default.compareSync(password, hash);
|
|
91
|
-
case "md5":
|
|
92
|
-
return (0, import_apr1.verifyApr1)(password, hash);
|
|
93
|
-
case "sha1":
|
|
94
|
-
return verifySha1(password, hash);
|
|
95
|
-
case "plain":
|
|
96
|
-
return (0, import_timing_safe_compare.safeCompare)(password, hash);
|
|
97
|
-
case "crypt":
|
|
98
|
-
throw new Error('Algorithm "crypt" is insecure and not supported.');
|
|
99
|
-
default:
|
|
100
|
-
throw new Error(`Unsupported algorithm: ${algo}`);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
async function verifyAsync(password, hash) {
|
|
104
|
-
const algo = detectAlgorithm(hash);
|
|
105
|
-
switch (algo) {
|
|
106
|
-
case "bcrypt":
|
|
107
|
-
return import_bcryptjs.default.compare(password, hash);
|
|
108
|
-
case "md5":
|
|
109
|
-
return (0, import_apr1.verifyApr1)(password, hash);
|
|
110
|
-
case "sha1":
|
|
111
|
-
return verifySha1(password, hash);
|
|
112
|
-
case "plain":
|
|
113
|
-
return (0, import_timing_safe_compare.safeCompare)(password, hash);
|
|
114
|
-
case "crypt":
|
|
115
|
-
throw new Error('Algorithm "crypt" is insecure and not supported.');
|
|
116
|
-
default:
|
|
117
|
-
throw new Error(`Unsupported algorithm: ${algo}`);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
function parse(content, options = {}) {
|
|
121
|
-
return content.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#")).map((line) => {
|
|
122
|
-
const [username, ...rest] = line.split(":");
|
|
123
|
-
const hash = rest.join(":");
|
|
124
|
-
const algorithm = detectAlgorithm(hash);
|
|
125
|
-
if (algorithm === "plain" && !options.unsafe) {
|
|
126
|
-
throw new Error(
|
|
127
|
-
`Plaintext password detected for user "${username}". Use options.unsafe to allow this.`
|
|
128
|
-
);
|
|
129
|
-
}
|
|
130
|
-
return { username, hash, algorithm };
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
function stringify(entries) {
|
|
134
|
-
return entries.map((entry) => `${entry.username}:${entry.hash}`).join("\n");
|
|
135
|
-
}
|
|
136
10
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
} catch (error) {
|
|
143
|
-
if (handleEnoent && error.code === "ENOENT") {
|
|
144
|
-
return [];
|
|
145
|
-
}
|
|
146
|
-
throw error;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
async function writeAtomic(filepath, content) {
|
|
150
|
-
const tempPath = `${filepath}.${Math.random().toString(36).slice(2)}.tmp`;
|
|
151
|
-
await (0, import_promises.writeFile)(tempPath, content);
|
|
152
|
-
await (0, import_promises.rename)(tempPath, filepath);
|
|
153
|
-
}
|
|
154
|
-
async function updateAndSave(filepath, username, hash, algorithm) {
|
|
155
|
-
const entries = await readEntries(filepath, true);
|
|
156
|
-
const existingIndex = entries.findIndex((e) => e.username === username);
|
|
157
|
-
if (existingIndex !== -1) {
|
|
158
|
-
entries[existingIndex].hash = hash;
|
|
159
|
-
entries[existingIndex].algorithm = algorithm;
|
|
160
|
-
} else {
|
|
161
|
-
entries.push({ username, hash, algorithm });
|
|
162
|
-
}
|
|
163
|
-
await writeAtomic(filepath, stringify(entries) + "\n");
|
|
164
|
-
}
|
|
165
|
-
async function authenticate(filepath, username, password) {
|
|
166
|
-
const entries = await readEntries(filepath);
|
|
167
|
-
const entry = entries.find((e) => e.username === username);
|
|
168
|
-
if (!entry) {
|
|
169
|
-
return false;
|
|
170
|
-
}
|
|
171
|
-
return verify(password, entry.hash);
|
|
172
|
-
}
|
|
173
|
-
async function authenticateAsync(filepath, username, password) {
|
|
174
|
-
const entries = await readEntries(filepath);
|
|
175
|
-
const entry = entries.find((e) => e.username === username);
|
|
176
|
-
if (!entry) {
|
|
177
|
-
return false;
|
|
178
|
-
}
|
|
179
|
-
return verifyAsync(password, entry.hash);
|
|
180
|
-
}
|
|
181
|
-
async function addUser(filepath, username, password, algorithm = "bcrypt") {
|
|
182
|
-
let hash;
|
|
183
|
-
switch (algorithm) {
|
|
184
|
-
case "bcrypt":
|
|
185
|
-
hash = import_bcryptjs2.default.hashSync(password, 10);
|
|
186
|
-
break;
|
|
187
|
-
case "md5":
|
|
188
|
-
hash = (0, import_apr12.generateApr1)(password);
|
|
189
|
-
break;
|
|
190
|
-
case "sha1":
|
|
191
|
-
hash = generateSha1(password);
|
|
192
|
-
break;
|
|
193
|
-
case "plain":
|
|
194
|
-
hash = password;
|
|
195
|
-
break;
|
|
196
|
-
default:
|
|
197
|
-
throw new Error(`Unsupported algorithm for generation: ${algorithm}`);
|
|
198
|
-
}
|
|
199
|
-
await updateAndSave(filepath, username, hash, algorithm);
|
|
200
|
-
}
|
|
201
|
-
async function addUserAsync(filepath, username, password, algorithm = "bcrypt") {
|
|
202
|
-
let hash;
|
|
203
|
-
switch (algorithm) {
|
|
204
|
-
case "bcrypt":
|
|
205
|
-
hash = await import_bcryptjs2.default.hash(password, 10);
|
|
206
|
-
break;
|
|
207
|
-
case "md5":
|
|
208
|
-
hash = (0, import_apr12.generateApr1)(password);
|
|
209
|
-
break;
|
|
210
|
-
case "sha1":
|
|
211
|
-
hash = generateSha1(password);
|
|
212
|
-
break;
|
|
213
|
-
case "plain":
|
|
214
|
-
hash = password;
|
|
215
|
-
break;
|
|
216
|
-
default:
|
|
217
|
-
throw new Error(`Unsupported algorithm for generation: ${algorithm}`);
|
|
218
|
-
}
|
|
219
|
-
await updateAndSave(filepath, username, hash, algorithm);
|
|
220
|
-
}
|
|
221
|
-
async function removeUser(filepath, username) {
|
|
222
|
-
const entries = await readEntries(filepath);
|
|
223
|
-
const newEntries = entries.filter((e) => e.username !== username);
|
|
224
|
-
await writeAtomic(filepath, stringify(newEntries) + "\n");
|
|
225
|
-
}
|
|
226
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
227
|
-
0 && (module.exports = {
|
|
228
|
-
addUser,
|
|
229
|
-
addUserAsync,
|
|
230
|
-
authenticate,
|
|
231
|
-
authenticateAsync,
|
|
232
|
-
removeUser
|
|
233
|
-
});
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
exports.addUser = _chunkBXMJPERDcjs.addUser; exports.addUserAsync = _chunkBXMJPERDcjs.addUserAsync; exports.authenticate = _chunkBXMJPERDcjs.authenticate; exports.authenticateAsync = _chunkBXMJPERDcjs.authenticateAsync; exports.removeUser = _chunkBXMJPERDcjs.removeUser;
|
package/dist/index.cjs
CHANGED
|
@@ -1,136 +1,12 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __export = (target, all) => {
|
|
9
|
-
for (var name in all)
|
|
10
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
-
};
|
|
12
|
-
var __copyProps = (to, from, except, desc) => {
|
|
13
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
-
for (let key of __getOwnPropNames(from))
|
|
15
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
-
}
|
|
18
|
-
return to;
|
|
19
|
-
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
29
2
|
|
|
30
|
-
// src/index.ts
|
|
31
|
-
var index_exports = {};
|
|
32
|
-
__export(index_exports, {
|
|
33
|
-
parse: () => parse,
|
|
34
|
-
stringify: () => stringify,
|
|
35
|
-
verify: () => verify,
|
|
36
|
-
verifyAsync: () => verifyAsync
|
|
37
|
-
});
|
|
38
|
-
module.exports = __toCommonJS(index_exports);
|
|
39
|
-
var import_apr1 = require("@se-oss/apr1");
|
|
40
|
-
var import_bcryptjs = __toESM(require("bcryptjs"), 1);
|
|
41
3
|
|
|
42
|
-
// src/sha1.ts
|
|
43
|
-
var import_sha1 = require("@se-oss/sha1");
|
|
44
4
|
|
|
45
|
-
// src/utils.ts
|
|
46
|
-
var import_timing_safe_compare = require("@se-oss/timing-safe-compare");
|
|
47
|
-
function detectAlgorithm(hash) {
|
|
48
|
-
if (hash.startsWith("$2y$") || hash.startsWith("$2a$") || hash.startsWith("$2b$")) {
|
|
49
|
-
return "bcrypt";
|
|
50
|
-
}
|
|
51
|
-
if (hash.startsWith("$apr1$")) {
|
|
52
|
-
return "md5";
|
|
53
|
-
}
|
|
54
|
-
if (hash.startsWith("{SHA}")) {
|
|
55
|
-
return "sha1";
|
|
56
|
-
}
|
|
57
|
-
if (hash.length === 13) {
|
|
58
|
-
return "crypt";
|
|
59
|
-
}
|
|
60
|
-
return "plain";
|
|
61
|
-
}
|
|
62
|
-
function bytesToBase64(bytes) {
|
|
63
|
-
if (typeof Buffer !== "undefined") {
|
|
64
|
-
return Buffer.from(bytes).toString("base64");
|
|
65
|
-
}
|
|
66
|
-
return btoa(String.fromCharCode(...bytes));
|
|
67
|
-
}
|
|
68
5
|
|
|
69
|
-
|
|
70
|
-
function verifySha1(password, hash) {
|
|
71
|
-
return (0, import_timing_safe_compare.safeCompare)(generateSha1(password), hash);
|
|
72
|
-
}
|
|
73
|
-
function generateSha1(password) {
|
|
74
|
-
const digest = (0, import_sha1.sha1)(password);
|
|
75
|
-
const b64 = bytesToBase64(digest);
|
|
76
|
-
return `{SHA}${b64}`;
|
|
77
|
-
}
|
|
6
|
+
var _chunk2R65SLIBcjs = require('./chunk-2R65SLIB.cjs');
|
|
78
7
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
return import_bcryptjs.default.compareSync(password, hash);
|
|
85
|
-
case "md5":
|
|
86
|
-
return (0, import_apr1.verifyApr1)(password, hash);
|
|
87
|
-
case "sha1":
|
|
88
|
-
return verifySha1(password, hash);
|
|
89
|
-
case "plain":
|
|
90
|
-
return (0, import_timing_safe_compare.safeCompare)(password, hash);
|
|
91
|
-
case "crypt":
|
|
92
|
-
throw new Error('Algorithm "crypt" is insecure and not supported.');
|
|
93
|
-
default:
|
|
94
|
-
throw new Error(`Unsupported algorithm: ${algo}`);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
async function verifyAsync(password, hash) {
|
|
98
|
-
const algo = detectAlgorithm(hash);
|
|
99
|
-
switch (algo) {
|
|
100
|
-
case "bcrypt":
|
|
101
|
-
return import_bcryptjs.default.compare(password, hash);
|
|
102
|
-
case "md5":
|
|
103
|
-
return (0, import_apr1.verifyApr1)(password, hash);
|
|
104
|
-
case "sha1":
|
|
105
|
-
return verifySha1(password, hash);
|
|
106
|
-
case "plain":
|
|
107
|
-
return (0, import_timing_safe_compare.safeCompare)(password, hash);
|
|
108
|
-
case "crypt":
|
|
109
|
-
throw new Error('Algorithm "crypt" is insecure and not supported.');
|
|
110
|
-
default:
|
|
111
|
-
throw new Error(`Unsupported algorithm: ${algo}`);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
function parse(content, options = {}) {
|
|
115
|
-
return content.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#")).map((line) => {
|
|
116
|
-
const [username, ...rest] = line.split(":");
|
|
117
|
-
const hash = rest.join(":");
|
|
118
|
-
const algorithm = detectAlgorithm(hash);
|
|
119
|
-
if (algorithm === "plain" && !options.unsafe) {
|
|
120
|
-
throw new Error(
|
|
121
|
-
`Plaintext password detected for user "${username}". Use options.unsafe to allow this.`
|
|
122
|
-
);
|
|
123
|
-
}
|
|
124
|
-
return { username, hash, algorithm };
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
function stringify(entries) {
|
|
128
|
-
return entries.map((entry) => `${entry.username}:${entry.hash}`).join("\n");
|
|
129
|
-
}
|
|
130
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
131
|
-
0 && (module.exports = {
|
|
132
|
-
parse,
|
|
133
|
-
stringify,
|
|
134
|
-
verify,
|
|
135
|
-
verifyAsync
|
|
136
|
-
});
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
exports.parse = _chunk2R65SLIBcjs.parse; exports.stringify = _chunk2R65SLIBcjs.stringify; exports.verify = _chunk2R65SLIBcjs.verify; exports.verifyAsync = _chunk2R65SLIBcjs.verifyAsync;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@se-oss/htpasswd",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "High-performance, modern TypeScript library for managing HTTP Basic Authentication password files with support for Bcrypt, APR1, SHA1, and Plaintext.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"htpasswd",
|
|
@@ -40,21 +40,10 @@
|
|
|
40
40
|
},
|
|
41
41
|
"files": [
|
|
42
42
|
"dist/**",
|
|
43
|
+
"!dist/cli.d.*",
|
|
44
|
+
"!dist/cli.cjs",
|
|
43
45
|
"!**/*.d.cts"
|
|
44
46
|
],
|
|
45
|
-
"scripts": {
|
|
46
|
-
"bench": "vitest bench --run",
|
|
47
|
-
"build": "pnpm typecheck && tsup",
|
|
48
|
-
"clean": "git clean -dfx **/node_modules/** dist .tsbuildinfo",
|
|
49
|
-
"dev": "tsup --watch",
|
|
50
|
-
"format": "prettier --write .",
|
|
51
|
-
"format:check": "prettier --check .",
|
|
52
|
-
"lint": "pnpm typecheck && eslint .",
|
|
53
|
-
"lint:fix": "eslint --fix .",
|
|
54
|
-
"prepublishOnly": "pnpm build && pnpm lint && pnpm format:check && pnpm test",
|
|
55
|
-
"test": "vitest --run",
|
|
56
|
-
"typecheck": "tsc --noEmit"
|
|
57
|
-
},
|
|
58
47
|
"prettier": "@shahrad/prettier-config",
|
|
59
48
|
"dependencies": {
|
|
60
49
|
"@se-oss/apr1": "^1.0.0",
|
|
@@ -63,6 +52,7 @@
|
|
|
63
52
|
"bcryptjs": "^3.0.3"
|
|
64
53
|
},
|
|
65
54
|
"devDependencies": {
|
|
55
|
+
"@changesets/cli": "^2.29.8",
|
|
66
56
|
"@shahrad/eslint-config": "^1.0.1",
|
|
67
57
|
"@shahrad/prettier-config": "^1.2.2",
|
|
68
58
|
"@shahrad/tsconfig": "^1.2.0",
|
|
@@ -74,9 +64,21 @@
|
|
|
74
64
|
"typescript": "^5.9.3",
|
|
75
65
|
"vitest": "^4.0.18"
|
|
76
66
|
},
|
|
77
|
-
"packageManager": "pnpm@10.29.3+sha512.498e1fb4cca5aa06c1dcf2611e6fafc50972ffe7189998c409e90de74566444298ffe43e6cd2acdc775ba1aa7cc5e092a8b7054c811ba8c5770f84693d33d2dc",
|
|
78
67
|
"publishConfig": {
|
|
79
68
|
"access": "public",
|
|
80
69
|
"provenance": true
|
|
70
|
+
},
|
|
71
|
+
"scripts": {
|
|
72
|
+
"bench": "vitest bench --run",
|
|
73
|
+
"build": "pnpm typecheck && tsup",
|
|
74
|
+
"ci:publish": "changeset publish",
|
|
75
|
+
"clean": "git clean -dfx **/node_modules/** dist .tsbuildinfo",
|
|
76
|
+
"dev": "tsup --watch",
|
|
77
|
+
"format": "prettier --write .",
|
|
78
|
+
"format:check": "prettier --check .",
|
|
79
|
+
"lint": "pnpm typecheck && eslint .",
|
|
80
|
+
"lint:fix": "eslint --fix .",
|
|
81
|
+
"test": "vitest --run",
|
|
82
|
+
"typecheck": "tsc --noEmit"
|
|
81
83
|
}
|
|
82
|
-
}
|
|
84
|
+
}
|
package/dist/cli.cjs
DELETED
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
"use strict";
|
|
3
|
-
var __create = Object.create;
|
|
4
|
-
var __defProp = Object.defineProperty;
|
|
5
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
-
var __copyProps = (to, from, except, desc) => {
|
|
10
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
-
for (let key of __getOwnPropNames(from))
|
|
12
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
-
}
|
|
15
|
-
return to;
|
|
16
|
-
};
|
|
17
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
18
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
19
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
20
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
21
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
22
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
23
|
-
mod
|
|
24
|
-
));
|
|
25
|
-
|
|
26
|
-
// src/cli.ts
|
|
27
|
-
var readline = __toESM(require("readline"), 1);
|
|
28
|
-
var import_node_stream = require("stream");
|
|
29
|
-
var tty = __toESM(require("tty"), 1);
|
|
30
|
-
var import_node_util = require("util");
|
|
31
|
-
|
|
32
|
-
// src/fs.ts
|
|
33
|
-
var import_promises = require("fs/promises");
|
|
34
|
-
var import_apr12 = require("@se-oss/apr1");
|
|
35
|
-
var import_bcryptjs2 = __toESM(require("bcryptjs"), 1);
|
|
36
|
-
|
|
37
|
-
// src/index.ts
|
|
38
|
-
var import_apr1 = require("@se-oss/apr1");
|
|
39
|
-
var import_bcryptjs = __toESM(require("bcryptjs"), 1);
|
|
40
|
-
|
|
41
|
-
// src/sha1.ts
|
|
42
|
-
var import_sha1 = require("@se-oss/sha1");
|
|
43
|
-
|
|
44
|
-
// src/utils.ts
|
|
45
|
-
var import_timing_safe_compare = require("@se-oss/timing-safe-compare");
|
|
46
|
-
function detectAlgorithm(hash) {
|
|
47
|
-
if (hash.startsWith("$2y$") || hash.startsWith("$2a$") || hash.startsWith("$2b$")) {
|
|
48
|
-
return "bcrypt";
|
|
49
|
-
}
|
|
50
|
-
if (hash.startsWith("$apr1$")) {
|
|
51
|
-
return "md5";
|
|
52
|
-
}
|
|
53
|
-
if (hash.startsWith("{SHA}")) {
|
|
54
|
-
return "sha1";
|
|
55
|
-
}
|
|
56
|
-
if (hash.length === 13) {
|
|
57
|
-
return "crypt";
|
|
58
|
-
}
|
|
59
|
-
return "plain";
|
|
60
|
-
}
|
|
61
|
-
function bytesToBase64(bytes) {
|
|
62
|
-
if (typeof Buffer !== "undefined") {
|
|
63
|
-
return Buffer.from(bytes).toString("base64");
|
|
64
|
-
}
|
|
65
|
-
return btoa(String.fromCharCode(...bytes));
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// src/sha1.ts
|
|
69
|
-
function generateSha1(password) {
|
|
70
|
-
const digest = (0, import_sha1.sha1)(password);
|
|
71
|
-
const b64 = bytesToBase64(digest);
|
|
72
|
-
return `{SHA}${b64}`;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// src/index.ts
|
|
76
|
-
function parse(content, options = {}) {
|
|
77
|
-
return content.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#")).map((line) => {
|
|
78
|
-
const [username, ...rest] = line.split(":");
|
|
79
|
-
const hash = rest.join(":");
|
|
80
|
-
const algorithm = detectAlgorithm(hash);
|
|
81
|
-
if (algorithm === "plain" && !options.unsafe) {
|
|
82
|
-
throw new Error(
|
|
83
|
-
`Plaintext password detected for user "${username}". Use options.unsafe to allow this.`
|
|
84
|
-
);
|
|
85
|
-
}
|
|
86
|
-
return { username, hash, algorithm };
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
function stringify(entries) {
|
|
90
|
-
return entries.map((entry) => `${entry.username}:${entry.hash}`).join("\n");
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// src/fs.ts
|
|
94
|
-
async function readEntries(filepath, handleEnoent = false) {
|
|
95
|
-
try {
|
|
96
|
-
const content = await (0, import_promises.readFile)(filepath, "utf-8");
|
|
97
|
-
return parse(content, { unsafe: true });
|
|
98
|
-
} catch (error) {
|
|
99
|
-
if (handleEnoent && error.code === "ENOENT") {
|
|
100
|
-
return [];
|
|
101
|
-
}
|
|
102
|
-
throw error;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
async function writeAtomic(filepath, content) {
|
|
106
|
-
const tempPath = `${filepath}.${Math.random().toString(36).slice(2)}.tmp`;
|
|
107
|
-
await (0, import_promises.writeFile)(tempPath, content);
|
|
108
|
-
await (0, import_promises.rename)(tempPath, filepath);
|
|
109
|
-
}
|
|
110
|
-
async function updateAndSave(filepath, username, hash, algorithm) {
|
|
111
|
-
const entries = await readEntries(filepath, true);
|
|
112
|
-
const existingIndex = entries.findIndex((e) => e.username === username);
|
|
113
|
-
if (existingIndex !== -1) {
|
|
114
|
-
entries[existingIndex].hash = hash;
|
|
115
|
-
entries[existingIndex].algorithm = algorithm;
|
|
116
|
-
} else {
|
|
117
|
-
entries.push({ username, hash, algorithm });
|
|
118
|
-
}
|
|
119
|
-
await writeAtomic(filepath, stringify(entries) + "\n");
|
|
120
|
-
}
|
|
121
|
-
async function addUserAsync(filepath, username, password, algorithm = "bcrypt") {
|
|
122
|
-
let hash;
|
|
123
|
-
switch (algorithm) {
|
|
124
|
-
case "bcrypt":
|
|
125
|
-
hash = await import_bcryptjs2.default.hash(password, 10);
|
|
126
|
-
break;
|
|
127
|
-
case "md5":
|
|
128
|
-
hash = (0, import_apr12.generateApr1)(password);
|
|
129
|
-
break;
|
|
130
|
-
case "sha1":
|
|
131
|
-
hash = generateSha1(password);
|
|
132
|
-
break;
|
|
133
|
-
case "plain":
|
|
134
|
-
hash = password;
|
|
135
|
-
break;
|
|
136
|
-
default:
|
|
137
|
-
throw new Error(`Unsupported algorithm for generation: ${algorithm}`);
|
|
138
|
-
}
|
|
139
|
-
await updateAndSave(filepath, username, hash, algorithm);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// src/cli.ts
|
|
143
|
-
async function main() {
|
|
144
|
-
const { values, positionals } = (0, import_node_util.parseArgs)({
|
|
145
|
-
options: {
|
|
146
|
-
create: { type: "boolean", short: "c" },
|
|
147
|
-
batch: { type: "boolean", short: "b" },
|
|
148
|
-
bcrypt: { type: "boolean", short: "B" },
|
|
149
|
-
md5: { type: "boolean", short: "m" },
|
|
150
|
-
sha: { type: "boolean", short: "s" },
|
|
151
|
-
plain: { type: "boolean", short: "p" },
|
|
152
|
-
help: { type: "boolean", short: "h" }
|
|
153
|
-
},
|
|
154
|
-
allowPositionals: true
|
|
155
|
-
});
|
|
156
|
-
if (values.help || positionals.length < 2) {
|
|
157
|
-
console.log(`
|
|
158
|
-
Usage: htpasswd [options] [file] [username]
|
|
159
|
-
htpasswd -b [options] [file] [username] [password]
|
|
160
|
-
|
|
161
|
-
Options:
|
|
162
|
-
-c, --create Create a new file.
|
|
163
|
-
-b, --batch Use batch mode (read password from command line).
|
|
164
|
-
-B, --bcrypt Use bcrypt encryption (default).
|
|
165
|
-
-m, --md5 Use MD5 encryption.
|
|
166
|
-
-s, --sha Use SHA encryption.
|
|
167
|
-
-p, --plain Use plaintext.
|
|
168
|
-
-h, --help Show this help message.
|
|
169
|
-
`);
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
|
-
const [file, username] = positionals;
|
|
173
|
-
let password = positionals[2];
|
|
174
|
-
if (!password) {
|
|
175
|
-
if (values.batch) {
|
|
176
|
-
console.error("Error: Password is required in batch mode.");
|
|
177
|
-
process.exit(1);
|
|
178
|
-
}
|
|
179
|
-
if (!tty.isatty(process.stdin.fd)) {
|
|
180
|
-
console.error("Error: Password input requires a terminal.");
|
|
181
|
-
process.exit(1);
|
|
182
|
-
}
|
|
183
|
-
password = await getHiddenPassword("New password: ");
|
|
184
|
-
const confirm = await getHiddenPassword("Re-type new password: ");
|
|
185
|
-
if (password !== confirm) {
|
|
186
|
-
console.error("Error: Passwords don't match.");
|
|
187
|
-
process.exit(1);
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
let algorithm = "bcrypt";
|
|
191
|
-
if (values.md5) algorithm = "md5";
|
|
192
|
-
else if (values.sha) algorithm = "sha1";
|
|
193
|
-
else if (values.plain) algorithm = "plain";
|
|
194
|
-
try {
|
|
195
|
-
await addUserAsync(file, username, password, algorithm);
|
|
196
|
-
console.log(`User ${username} ${values.create ? "created" : "updated"} successfully.`);
|
|
197
|
-
} catch (error) {
|
|
198
|
-
console.error(`Error: ${error.message}`);
|
|
199
|
-
process.exit(1);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
var MutableStream = class extends import_node_stream.Writable {
|
|
203
|
-
muted = false;
|
|
204
|
-
_write(chunk, encoding, callback) {
|
|
205
|
-
if (!this.muted) {
|
|
206
|
-
process.stdout.write(chunk, encoding);
|
|
207
|
-
}
|
|
208
|
-
callback();
|
|
209
|
-
}
|
|
210
|
-
};
|
|
211
|
-
function getHiddenPassword(query) {
|
|
212
|
-
const mutableStdout = new MutableStream();
|
|
213
|
-
const rl = readline.createInterface({
|
|
214
|
-
input: process.stdin,
|
|
215
|
-
output: mutableStdout,
|
|
216
|
-
terminal: true
|
|
217
|
-
});
|
|
218
|
-
return new Promise((resolve) => {
|
|
219
|
-
rl.question(query, (password) => {
|
|
220
|
-
process.stdout.write("\n");
|
|
221
|
-
rl.close();
|
|
222
|
-
resolve(password);
|
|
223
|
-
});
|
|
224
|
-
mutableStdout.muted = true;
|
|
225
|
-
});
|
|
226
|
-
}
|
|
227
|
-
main().catch((err) => {
|
|
228
|
-
console.error(err);
|
|
229
|
-
process.exit(1);
|
|
230
|
-
});
|
package/dist/cli.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|