@gjermundgaraba/clankerauth 0.26.3 → 0.28.0
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/README.md +13 -1
- package/dist/main.mjs +27 -9
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @gjermundgaraba/clankerauth
|
|
2
2
|
|
|
3
|
-
The `clankerauth` command: sign in to a [clankerauth](https://github.com/gjermundgaraba/clankerauth) issuer as its owner, run every administration action over HTTP, and hand other commands access tokens for the issuer's resources. It needs Node 26 or newer and an issuer at 0.24.0 or later.
|
|
3
|
+
The `clankerauth` command: sign in to a [clankerauth](https://github.com/gjermundgaraba/clankerauth) issuer as its owner, run every administration action over HTTP, and hand other commands access tokens for the issuer's resources. It needs Node 26 or newer and an issuer at 0.24.0 or later, or 0.28.0 for an administration key in `CLANKERAUTH_TOKEN`.
|
|
4
4
|
|
|
5
5
|
```sh
|
|
6
6
|
npm install --global @gjermundgaraba/clankerauth
|
|
@@ -18,6 +18,18 @@ The sign-ins are kept in `$XDG_CONFIG_HOME/clankerauth/sign-ins.json`, `~/.confi
|
|
|
18
18
|
|
|
19
19
|
Administration commands act at the issuer of the one administration sign-in kept. Signed in to administration at several issuers, name one with `CLANKERAUTH_URL`, its origin; a value that is no URL is refused.
|
|
20
20
|
|
|
21
|
+
Unattended, such as in a container with no browser or disk to keep a sign-in on, the commands take an administration key, an API key granted on the issuer's origin root, from `CLANKERAUTH_TOKEN` instead, and then act at the issuer `CLANKERAUTH_URL` names, which they require. No sign-in is read or written. The owner creates the key once, signed in:
|
|
22
|
+
|
|
23
|
+
```sh
|
|
24
|
+
clankerauth create-api-key --name deployer --expires-at null \
|
|
25
|
+
--permissions '{"https://clankerauth.home.example/":["clankerauth:read","clankerauth:write"]}'
|
|
26
|
+
|
|
27
|
+
CLANKERAUTH_URL=https://clankerauth.home.example CLANKERAUTH_TOKEN=clankerauth_… \
|
|
28
|
+
clankerauth list-api-keys
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The issuer checks the key on every request, so disabling or deleting it ends its access at once. With `clankerauth:write` it may create and delete administration keys too, itself among them.
|
|
32
|
+
|
|
21
33
|
## Tokens for other commands
|
|
22
34
|
|
|
23
35
|
`token <url>` prints a current access token for the resource signed in to that the URL is under, the most specific when several are, and nothing else, refreshing it first when it is about to expire; without a URL it prints administration's. Another command, or a script, gets its bearer token from there instead of keeping a key; a program written with Effect uses `token` of [`@gjermundgaraba/clankerauth-sdk/credentials`](../../packages/sdk/README.md) instead, which reads and refreshes the same sign-in:
|
package/dist/main.mjs
CHANGED
|
@@ -400,7 +400,7 @@ const OwnerHttp = ActionHttp.make(Administration, {
|
|
|
400
400
|
});
|
|
401
401
|
//#endregion
|
|
402
402
|
//#region package.json
|
|
403
|
-
var version = "0.
|
|
403
|
+
var version = "0.28.0";
|
|
404
404
|
//#endregion
|
|
405
405
|
//#region src/main.ts
|
|
406
406
|
const refused = (error) => new CliError.UserError({
|
|
@@ -437,12 +437,12 @@ const notSignedIn = new CliError.UserError({
|
|
|
437
437
|
cause: "not signed in",
|
|
438
438
|
userMessage: "Not signed in: run `clankerauth login <url>` first."
|
|
439
439
|
});
|
|
440
|
+
const issuerNamed = Config.option(Config.String("CLANKERAUTH_URL")).pipe(Effect.mapError(refused), Effect.flatMap((named) => Option.exists(named, (url) => !URL.canParse(url)) ? Effect.fail(new CliError.UserError({
|
|
441
|
+
cause: "CLANKERAUTH_URL",
|
|
442
|
+
userMessage: "CLANKERAUTH_URL is no URL: set it to the issuer's origin, its CLANKERAUTH_BASE_URL."
|
|
443
|
+
})) : Effect.succeed(named)));
|
|
440
444
|
const administrationSignIn = Effect.gen(function* () {
|
|
441
|
-
const named = yield*
|
|
442
|
-
if (Option.exists(named, (url) => !URL.canParse(url))) return yield* new CliError.UserError({
|
|
443
|
-
cause: "CLANKERAUTH_URL",
|
|
444
|
-
userMessage: "CLANKERAUTH_URL is no URL: set it to the issuer's origin, its CLANKERAUTH_BASE_URL."
|
|
445
|
-
});
|
|
445
|
+
const named = yield* issuerNamed;
|
|
446
446
|
const kept = (yield* Credentials.list().pipe(Effect.mapError(refused))).filter((signIn) => signIn.resource === administrationIdentifier(signIn.url)).filter((signIn) => Option.match(named, {
|
|
447
447
|
onNone: () => true,
|
|
448
448
|
onSome: (url) => new URL(url).origin === signIn.url
|
|
@@ -455,14 +455,32 @@ const administrationSignIn = Effect.gen(function* () {
|
|
|
455
455
|
});
|
|
456
456
|
return only;
|
|
457
457
|
});
|
|
458
|
+
const administrationKey = Config.Redacted("CLANKERAUTH_TOKEN");
|
|
459
|
+
const administrationTarget = Effect.gen(function* () {
|
|
460
|
+
const given = yield* Config.option(administrationKey).pipe(Effect.mapError(refused));
|
|
461
|
+
if (Option.isNone(given)) return yield* administrationSignIn;
|
|
462
|
+
const named = yield* issuerNamed;
|
|
463
|
+
if (Option.isNone(named)) return yield* new CliError.UserError({
|
|
464
|
+
cause: "CLANKERAUTH_URL",
|
|
465
|
+
userMessage: "CLANKERAUTH_TOKEN is set without CLANKERAUTH_URL: set it to the issuer's origin, its CLANKERAUTH_BASE_URL."
|
|
466
|
+
});
|
|
467
|
+
const url = new URL(named.value).origin;
|
|
468
|
+
return {
|
|
469
|
+
url,
|
|
470
|
+
resource: administrationIdentifier(url)
|
|
471
|
+
};
|
|
472
|
+
});
|
|
458
473
|
const tokenCommand = Command.make("token", { url: urlArgument("An address under the resource whose token to print, such as the application's URL; administration by default") }, ({ url }) => Effect.gen(function* () {
|
|
459
474
|
const named = Option.isSome(url) ? url.value : (yield* administrationSignIn).resource;
|
|
460
475
|
const token = yield* Credentials.token({ url: named }).pipe(Effect.mapError(refused));
|
|
461
476
|
yield* Effect.sync(() => process.stdout.write(`${Redacted.value(token)}\n`));
|
|
462
477
|
})).pipe(Command.withDescription("Print a current access token for the resource signed in to that a URL is under, refreshing it first when it has expired."));
|
|
463
|
-
const administrationClient = Effect.flatMap(
|
|
464
|
-
baseUrl:
|
|
465
|
-
transformClient: (client) => HttpClient.catchTag(Credentials.authorizing({
|
|
478
|
+
const administrationClient = Effect.flatMap(administrationTarget, (target) => ActionHttp.client(OwnerHttp, {
|
|
479
|
+
baseUrl: target.url,
|
|
480
|
+
transformClient: (client) => HttpClient.catchTag(Credentials.authorizing({
|
|
481
|
+
url: target.resource,
|
|
482
|
+
token: administrationKey
|
|
483
|
+
})(client), ["SignInRequired", "TokenUnavailable"], (error) => Effect.fail(refused(error)))
|
|
466
484
|
}));
|
|
467
485
|
const administration = Administration.map((action) => ActionCli.remoteCommand(OwnerHttp, action, { client: administrationClient }));
|
|
468
486
|
const cli = Command.make("clankerauth").pipe(Command.withDescription("Administer a clankerauth issuer as its owner, and hand other commands its tokens. Results are JSON on stdout; a created key or client secret is in it once."), Command.withSubcommands([
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gjermundgaraba/clankerauth",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.28.0",
|
|
4
4
|
"description": "The clankerauth command line: sign in to an issuer as its owner and administer it over HTTP.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -21,13 +21,13 @@
|
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@effect/platform-node": "4.0.5",
|
|
23
23
|
"@effect/platform-node-shared": "4.0.5",
|
|
24
|
-
"@gjermundgaraba/clankerauth-sdk": "0.
|
|
25
|
-
"@gjermundgaraba/effect-actions": "0.
|
|
24
|
+
"@gjermundgaraba/clankerauth-sdk": "0.28.0",
|
|
25
|
+
"@gjermundgaraba/effect-actions": "0.19.0",
|
|
26
26
|
"effect": "4.0.5"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@gjermundgaraba/clankerauth-admin-api": "0.
|
|
30
|
-
"@gjermundgaraba/clankerauth-dev": "0.
|
|
29
|
+
"@gjermundgaraba/clankerauth-admin-api": "0.28.0",
|
|
30
|
+
"@gjermundgaraba/clankerauth-dev": "0.28.0",
|
|
31
31
|
"@types/node": "26.6.5",
|
|
32
32
|
"typescript": "7.0.2",
|
|
33
33
|
"vite": "npm:@voidzero-dev/vite-plus-core@1.3.0",
|