@clioplaylists/clio 0.1.6 → 0.1.7
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/.env +7 -0
- package/dist/api/health.js +3 -10
- package/dist/api/index.js +2 -39
- package/dist/api/util.js +6 -10
- package/dist/auth-verifier.js +165 -273
- package/dist/client.js +8 -15
- package/dist/config.js +7 -23
- package/dist/context.js +3 -10
- package/dist/dataplane/client.js +25 -70
- package/dist/dataplane/index.js +2 -18
- package/dist/dataplane/server/background.js +8 -29
- package/dist/dataplane/server/db/database-schema.js +1 -2
- package/dist/dataplane/server/db/db.js +27 -103
- package/dist/dataplane/server/db/index.js +1 -17
- package/dist/dataplane/server/db/migrations/20230309T045948368Z-init.js +7 -11
- package/dist/dataplane/server/db/migrations/20230420T211446071Z-did-cache.js +2 -6
- package/dist/dataplane/server/db/migrations/index.js +2 -38
- package/dist/dataplane/server/db/migrations/provider.js +5 -17
- package/dist/dataplane/server/db/pagination.js +21 -37
- package/dist/dataplane/server/db/tables/actor-sync.js +1 -4
- package/dist/dataplane/server/db/tables/actor.js +1 -4
- package/dist/dataplane/server/db/tables/artist-list-item.js +1 -4
- package/dist/dataplane/server/db/tables/artist.js +1 -4
- package/dist/dataplane/server/db/tables/playlist-idea.js +1 -4
- package/dist/dataplane/server/db/tables/playlist-item.js +1 -4
- package/dist/dataplane/server/db/tables/playlist.js +1 -4
- package/dist/dataplane/server/db/tables/profile.js +1 -4
- package/dist/dataplane/server/db/tables/record.js +1 -4
- package/dist/dataplane/server/db/tables/song.js +1 -4
- package/dist/dataplane/server/db/types.js +1 -2
- package/dist/dataplane/server/db/util.js +18 -26
- package/dist/dataplane/server/index.js +17 -33
- package/dist/dataplane/server/indexing/index.js +39 -89
- package/dist/dataplane/server/indexing/plugins/playlist-idea.js +7 -44
- package/dist/dataplane/server/indexing/plugins/profile.js +5 -42
- package/dist/dataplane/server/indexing/processor.js +11 -29
- package/dist/dataplane/server/routes/identity.js +11 -13
- package/dist/dataplane/server/routes/index.js +10 -15
- package/dist/dataplane/server/routes/profile.js +9 -11
- package/dist/dataplane/server/routes/records.js +14 -51
- package/dist/dataplane/server/routes/sync.js +1 -3
- package/dist/dataplane/server/subscription.js +19 -47
- package/dist/error.js +5 -9
- package/dist/index.js +29 -89
- package/dist/lexicons/index.js +52 -227
- package/dist/lexicons/lexicons.js +5 -8
- package/dist/lexicons/types/com/atproto/admin/defs.js +27 -39
- package/dist/lexicons/types/com/atproto/admin/deleteAccount.js +1 -2
- package/dist/lexicons/types/com/atproto/admin/disableAccountInvites.js +1 -2
- package/dist/lexicons/types/com/atproto/admin/disableInviteCodes.js +1 -2
- package/dist/lexicons/types/com/atproto/admin/enableAccountInvites.js +1 -2
- package/dist/lexicons/types/com/atproto/admin/getAccountInfo.js +1 -2
- package/dist/lexicons/types/com/atproto/admin/getAccountInfos.js +1 -2
- package/dist/lexicons/types/com/atproto/admin/getInviteCodes.js +1 -2
- package/dist/lexicons/types/com/atproto/admin/getSubjectStatus.js +1 -2
- package/dist/lexicons/types/com/atproto/admin/searchAccounts.js +1 -2
- package/dist/lexicons/types/com/atproto/admin/sendEmail.js +1 -2
- package/dist/lexicons/types/com/atproto/admin/updateAccountEmail.js +1 -2
- package/dist/lexicons/types/com/atproto/admin/updateAccountHandle.js +1 -2
- package/dist/lexicons/types/com/atproto/admin/updateAccountPassword.js +1 -2
- package/dist/lexicons/types/com/atproto/admin/updateSubjectStatus.js +1 -2
- package/dist/lexicons/types/com/atproto/identity/defs.js +7 -11
- package/dist/lexicons/types/com/atproto/identity/getRecommendedDidCredentials.js +1 -2
- package/dist/lexicons/types/com/atproto/identity/refreshIdentity.js +1 -2
- package/dist/lexicons/types/com/atproto/identity/requestPlcOperationSignature.js +1 -2
- package/dist/lexicons/types/com/atproto/identity/resolveDid.js +1 -2
- package/dist/lexicons/types/com/atproto/identity/resolveHandle.js +1 -2
- package/dist/lexicons/types/com/atproto/identity/resolveIdentity.js +1 -2
- package/dist/lexicons/types/com/atproto/identity/signPlcOperation.js +1 -2
- package/dist/lexicons/types/com/atproto/identity/submitPlcOperation.js +1 -2
- package/dist/lexicons/types/com/atproto/identity/updateHandle.js +1 -2
- package/dist/lexicons/types/com/atproto/label/defs.js +27 -39
- package/dist/lexicons/types/com/atproto/label/queryLabels.js +1 -2
- package/dist/lexicons/types/com/atproto/label/subscribeLabels.js +12 -18
- package/dist/lexicons/types/com/atproto/lexicon/schema.js +7 -11
- package/dist/lexicons/types/com/atproto/moderation/createReport.js +1 -2
- package/dist/lexicons/types/com/atproto/moderation/defs.js +7 -10
- package/dist/lexicons/types/com/atproto/repo/applyWrites.js +32 -46
- package/dist/lexicons/types/com/atproto/repo/createRecord.js +1 -2
- package/dist/lexicons/types/com/atproto/repo/defs.js +7 -11
- package/dist/lexicons/types/com/atproto/repo/deleteRecord.js +1 -2
- package/dist/lexicons/types/com/atproto/repo/describeRepo.js +1 -2
- package/dist/lexicons/types/com/atproto/repo/getRecord.js +1 -2
- package/dist/lexicons/types/com/atproto/repo/importRepo.js +1 -2
- package/dist/lexicons/types/com/atproto/repo/listMissingBlobs.js +7 -11
- package/dist/lexicons/types/com/atproto/repo/listRecords.js +7 -11
- package/dist/lexicons/types/com/atproto/repo/putRecord.js +1 -2
- package/dist/lexicons/types/com/atproto/repo/strongRef.js +7 -11
- package/dist/lexicons/types/com/atproto/repo/uploadBlob.js +1 -2
- package/dist/lexicons/types/com/atproto/server/activateAccount.js +1 -2
- package/dist/lexicons/types/com/atproto/server/checkAccountStatus.js +1 -2
- package/dist/lexicons/types/com/atproto/server/confirmEmail.js +1 -2
- package/dist/lexicons/types/com/atproto/server/createAccount.js +1 -2
- package/dist/lexicons/types/com/atproto/server/createAppPassword.js +7 -11
- package/dist/lexicons/types/com/atproto/server/createInviteCode.js +1 -2
- package/dist/lexicons/types/com/atproto/server/createInviteCodes.js +7 -11
- package/dist/lexicons/types/com/atproto/server/createSession.js +1 -2
- package/dist/lexicons/types/com/atproto/server/deactivateAccount.js +1 -2
- package/dist/lexicons/types/com/atproto/server/defs.js +12 -18
- package/dist/lexicons/types/com/atproto/server/deleteAccount.js +1 -2
- package/dist/lexicons/types/com/atproto/server/deleteSession.js +1 -2
- package/dist/lexicons/types/com/atproto/server/describeServer.js +12 -18
- package/dist/lexicons/types/com/atproto/server/getAccountInviteCodes.js +1 -2
- package/dist/lexicons/types/com/atproto/server/getServiceAuth.js +1 -2
- package/dist/lexicons/types/com/atproto/server/getSession.js +1 -2
- package/dist/lexicons/types/com/atproto/server/listAppPasswords.js +7 -11
- package/dist/lexicons/types/com/atproto/server/refreshSession.js +1 -2
- package/dist/lexicons/types/com/atproto/server/requestAccountDelete.js +1 -2
- package/dist/lexicons/types/com/atproto/server/requestEmailConfirmation.js +1 -2
- package/dist/lexicons/types/com/atproto/server/requestEmailUpdate.js +1 -2
- package/dist/lexicons/types/com/atproto/server/requestPasswordReset.js +1 -2
- package/dist/lexicons/types/com/atproto/server/reserveSigningKey.js +1 -2
- package/dist/lexicons/types/com/atproto/server/resetPassword.js +1 -2
- package/dist/lexicons/types/com/atproto/server/revokeAppPassword.js +1 -2
- package/dist/lexicons/types/com/atproto/server/updateEmail.js +1 -2
- package/dist/lexicons/types/com/atproto/sync/getBlob.js +1 -2
- package/dist/lexicons/types/com/atproto/sync/getBlocks.js +1 -2
- package/dist/lexicons/types/com/atproto/sync/getCheckout.js +1 -2
- package/dist/lexicons/types/com/atproto/sync/getHead.js +1 -2
- package/dist/lexicons/types/com/atproto/sync/getLatestCommit.js +1 -2
- package/dist/lexicons/types/com/atproto/sync/getRecord.js +1 -2
- package/dist/lexicons/types/com/atproto/sync/getRepo.js +1 -2
- package/dist/lexicons/types/com/atproto/sync/getRepoStatus.js +1 -2
- package/dist/lexicons/types/com/atproto/sync/listBlobs.js +1 -2
- package/dist/lexicons/types/com/atproto/sync/listRepos.js +7 -11
- package/dist/lexicons/types/com/atproto/sync/listReposByCollection.js +7 -11
- package/dist/lexicons/types/com/atproto/sync/notifyOfUpdate.js +1 -2
- package/dist/lexicons/types/com/atproto/sync/requestCrawl.js +1 -2
- package/dist/lexicons/types/com/atproto/sync/subscribeRepos.js +32 -46
- package/dist/lexicons/types/com/atproto/temp/addReservedHandle.js +1 -2
- package/dist/lexicons/types/com/atproto/temp/checkSignupQueue.js +1 -2
- package/dist/lexicons/types/com/atproto/temp/fetchLabels.js +1 -2
- package/dist/lexicons/types/com/atproto/temp/requestPhoneVerification.js +1 -2
- package/dist/lexicons/types/com/clioplaylists/alpha/actor/profile.js +7 -11
- package/dist/lexicons/types/com/clioplaylists/alpha/feed/defs.js +12 -18
- package/dist/lexicons/types/com/clioplaylists/alpha/feed/getSongs.js +1 -2
- package/dist/lexicons/types/com/clioplaylists/alpha/feed/playlistIdea.js +17 -25
- package/dist/lexicons/util.js +2 -6
- package/dist/logger.js +10 -16
- package/dist/rpc/clio_connect.js +30 -33
- package/dist/rpc/clio_pb.js +402 -956
- package/dist/util/retry.js +7 -10
- package/dist/util/uris.js +3 -6
- package/dist/util.js +17 -60
- package/package.json +4 -4
package/dist/.env
ADDED
package/dist/api/health.js
CHANGED
|
@@ -1,12 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.createRouter = void 0;
|
|
7
|
-
const express_1 = __importDefault(require("express"));
|
|
8
|
-
const createRouter = (ctx) => {
|
|
9
|
-
const router = express_1.default.Router();
|
|
1
|
+
import express from 'express';
|
|
2
|
+
export const createRouter = (ctx) => {
|
|
3
|
+
const router = express.Router();
|
|
10
4
|
router.get('/', function (req, res) {
|
|
11
5
|
res.type('text/plain');
|
|
12
6
|
res.send(`
|
|
@@ -29,4 +23,3 @@ Most API routes are under /xrpc/
|
|
|
29
23
|
});
|
|
30
24
|
return router;
|
|
31
25
|
};
|
|
32
|
-
exports.createRouter = createRouter;
|
package/dist/api/index.js
CHANGED
|
@@ -1,43 +1,6 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.health = void 0;
|
|
37
|
-
exports.default = default_1;
|
|
38
1
|
// import getSongs from './com/clioplaylists/alpha/feed/getSongs'
|
|
39
|
-
|
|
40
|
-
function
|
|
2
|
+
export * as health from './health';
|
|
3
|
+
export default function (server, ctx) {
|
|
41
4
|
// getSongs(server, ctx)
|
|
42
5
|
return server;
|
|
43
6
|
}
|
package/dist/api/util.js
CHANGED
|
@@ -1,17 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
exports.ATPROTO_CONTENT_LABELERS = 'Atproto-Content-Labelers';
|
|
6
|
-
exports.ATPROTO_REPO_REV = 'Atproto-Repo-Rev';
|
|
7
|
-
const resHeaders = (opts) => {
|
|
1
|
+
import { formatLabelerHeader } from '../util';
|
|
2
|
+
export const ATPROTO_CONTENT_LABELERS = 'Atproto-Content-Labelers';
|
|
3
|
+
export const ATPROTO_REPO_REV = 'Atproto-Repo-Rev';
|
|
4
|
+
export const resHeaders = (opts) => {
|
|
8
5
|
const headers = {};
|
|
9
6
|
if (opts.labelers) {
|
|
10
|
-
headers[
|
|
7
|
+
headers[ATPROTO_CONTENT_LABELERS] = formatLabelerHeader(opts.labelers);
|
|
11
8
|
}
|
|
12
9
|
if (opts.repoRev) {
|
|
13
|
-
headers[
|
|
10
|
+
headers[ATPROTO_REPO_REV] = opts.repoRev;
|
|
14
11
|
}
|
|
15
12
|
return headers;
|
|
16
13
|
};
|
|
17
|
-
exports.resHeaders = resHeaders;
|
package/dist/auth-verifier.js
CHANGED
|
@@ -1,181 +1,125 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
38
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.verifySignatureWithKey = exports.createPublicKeyObject = exports.buildBasicAuth = exports.parseBasicAuth = exports.AuthVerifier = exports.RoleStatus = void 0;
|
|
40
|
-
const xrpc_server_1 = require("@atproto/xrpc-server");
|
|
41
|
-
const jose = __importStar(require("jose"));
|
|
42
|
-
const key_encoder_1 = __importDefault(require("key-encoder"));
|
|
43
|
-
const node_crypto_1 = __importDefault(require("node:crypto"));
|
|
44
|
-
const ui8 = __importStar(require("uint8arrays"));
|
|
1
|
+
import { AuthRequiredError, cryptoVerifySignatureWithKey, } from '@atproto/xrpc-server';
|
|
2
|
+
import * as jose from 'jose';
|
|
3
|
+
import KeyEncoder from 'key-encoder';
|
|
4
|
+
import crypto from 'node:crypto';
|
|
5
|
+
import * as ui8 from 'uint8arrays';
|
|
45
6
|
// import { GetIdentityByDidResponse } from './proto/bsky_pb'
|
|
46
|
-
|
|
47
|
-
var RoleStatus;
|
|
7
|
+
import { parseDidKey, SECP256K1_JWT_ALG } from '@atproto/crypto';
|
|
8
|
+
export var RoleStatus;
|
|
48
9
|
(function (RoleStatus) {
|
|
49
10
|
RoleStatus[RoleStatus["Valid"] = 0] = "Valid";
|
|
50
11
|
RoleStatus[RoleStatus["Invalid"] = 1] = "Invalid";
|
|
51
12
|
RoleStatus[RoleStatus["Missing"] = 2] = "Missing";
|
|
52
|
-
})(RoleStatus || (
|
|
13
|
+
})(RoleStatus || (RoleStatus = {}));
|
|
53
14
|
const ALLOWED_AUTH_SCOPES = new Set([
|
|
54
15
|
'com.atproto.access',
|
|
55
16
|
'com.atproto.appPass',
|
|
56
17
|
'com.atproto.appPassPrivileged',
|
|
57
18
|
]);
|
|
58
|
-
class AuthVerifier {
|
|
19
|
+
export class AuthVerifier {
|
|
20
|
+
dataplane;
|
|
21
|
+
ownDid;
|
|
22
|
+
standardAudienceDids;
|
|
23
|
+
modServiceDid;
|
|
24
|
+
adminPasses;
|
|
25
|
+
entrywayJwtPublicKey;
|
|
59
26
|
constructor(dataplane, opts) {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
Object.defineProperty(this, "modServiceDid", {
|
|
79
|
-
enumerable: true,
|
|
80
|
-
configurable: true,
|
|
81
|
-
writable: true,
|
|
82
|
-
value: void 0
|
|
83
|
-
});
|
|
84
|
-
Object.defineProperty(this, "adminPasses", {
|
|
85
|
-
enumerable: true,
|
|
86
|
-
configurable: true,
|
|
87
|
-
writable: true,
|
|
88
|
-
value: void 0
|
|
89
|
-
});
|
|
90
|
-
Object.defineProperty(this, "entrywayJwtPublicKey", {
|
|
91
|
-
enumerable: true,
|
|
92
|
-
configurable: true,
|
|
93
|
-
writable: true,
|
|
94
|
-
value: void 0
|
|
95
|
-
});
|
|
96
|
-
// verifiers (arrow fns to preserve scope)
|
|
97
|
-
Object.defineProperty(this, "standardOptionalParameterized", {
|
|
98
|
-
enumerable: true,
|
|
99
|
-
configurable: true,
|
|
100
|
-
writable: true,
|
|
101
|
-
value: (opts) => async (ctx) => {
|
|
102
|
-
// @TODO remove! basic auth + did supported just for testing.
|
|
103
|
-
if (isBasicToken(ctx.req)) {
|
|
104
|
-
const aud = this.ownDid;
|
|
105
|
-
const iss = ctx.req.headers['appview-as-did'];
|
|
106
|
-
if (typeof iss !== 'string' || !iss.startsWith('did:')) {
|
|
107
|
-
throw new xrpc_server_1.AuthRequiredError('bad issuer');
|
|
108
|
-
}
|
|
109
|
-
if (!this.parseRoleCreds(ctx.req).admin) {
|
|
110
|
-
throw new xrpc_server_1.AuthRequiredError('bad credentials');
|
|
111
|
-
}
|
|
112
|
-
return {
|
|
113
|
-
credentials: { type: 'standard', iss, aud },
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
else if (isBearerToken(ctx.req)) {
|
|
117
|
-
// @NOTE temporarily accept entryway session tokens to shed load from PDS instances
|
|
118
|
-
const token = bearerTokenFromReq(ctx.req);
|
|
119
|
-
const header = token ? jose.decodeProtectedHeader(token) : undefined;
|
|
120
|
-
if (header?.typ === 'at+jwt') {
|
|
121
|
-
// we should never use entryway session tokens in the case of flexible auth audiences (namely in the case of getFeed)
|
|
122
|
-
if (opts.skipAudCheck) {
|
|
123
|
-
throw new xrpc_server_1.AuthRequiredError('Malformed token', 'InvalidToken');
|
|
124
|
-
}
|
|
125
|
-
return this.entrywaySession(ctx);
|
|
126
|
-
}
|
|
127
|
-
// const { iss, aud } = await this.verifyServiceJwt(ctx, {
|
|
128
|
-
// lxmCheck: opts.lxmCheck,
|
|
129
|
-
// iss: null,
|
|
130
|
-
// aud: null,
|
|
131
|
-
// })
|
|
132
|
-
const { aud } = {
|
|
133
|
-
// iss: '',
|
|
134
|
-
aud: '',
|
|
135
|
-
};
|
|
136
|
-
if (!opts.skipAudCheck && !this.standardAudienceDids.has(aud)) {
|
|
137
|
-
throw new xrpc_server_1.AuthRequiredError('jwt audience does not match service did', 'BadJwtAudience');
|
|
138
|
-
}
|
|
139
|
-
return {
|
|
140
|
-
credentials: {
|
|
141
|
-
type: 'standard',
|
|
142
|
-
iss: '',
|
|
143
|
-
aud: '',
|
|
144
|
-
},
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
else {
|
|
148
|
-
return this.nullCreds();
|
|
149
|
-
}
|
|
27
|
+
this.dataplane = dataplane;
|
|
28
|
+
this.ownDid = opts.ownDid;
|
|
29
|
+
this.standardAudienceDids = new Set([
|
|
30
|
+
opts.ownDid,
|
|
31
|
+
...opts.alternateAudienceDids,
|
|
32
|
+
]);
|
|
33
|
+
this.modServiceDid = opts.modServiceDid;
|
|
34
|
+
this.adminPasses = new Set(opts.adminPasses);
|
|
35
|
+
this.entrywayJwtPublicKey = opts.entrywayJwtPublicKey;
|
|
36
|
+
}
|
|
37
|
+
// verifiers (arrow fns to preserve scope)
|
|
38
|
+
standardOptionalParameterized = (opts) => async (ctx) => {
|
|
39
|
+
// @TODO remove! basic auth + did supported just for testing.
|
|
40
|
+
if (isBasicToken(ctx.req)) {
|
|
41
|
+
const aud = this.ownDid;
|
|
42
|
+
const iss = ctx.req.headers['appview-as-did'];
|
|
43
|
+
if (typeof iss !== 'string' || !iss.startsWith('did:')) {
|
|
44
|
+
throw new AuthRequiredError('bad issuer');
|
|
150
45
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
enumerable: true,
|
|
154
|
-
configurable: true,
|
|
155
|
-
writable: true,
|
|
156
|
-
value: this.standardOptionalParameterized({})
|
|
157
|
-
});
|
|
158
|
-
Object.defineProperty(this, "standard", {
|
|
159
|
-
enumerable: true,
|
|
160
|
-
configurable: true,
|
|
161
|
-
writable: true,
|
|
162
|
-
value: async (ctx) => {
|
|
163
|
-
const output = await this.standardOptional(ctx);
|
|
164
|
-
if (output.credentials.type === 'none') {
|
|
165
|
-
throw new xrpc_server_1.AuthRequiredError(undefined, 'AuthMissing');
|
|
166
|
-
}
|
|
167
|
-
return output;
|
|
46
|
+
if (!this.parseRoleCreds(ctx.req).admin) {
|
|
47
|
+
throw new AuthRequiredError('bad credentials');
|
|
168
48
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
49
|
+
return {
|
|
50
|
+
credentials: { type: 'standard', iss, aud },
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
else if (isBearerToken(ctx.req)) {
|
|
54
|
+
// @NOTE temporarily accept entryway session tokens to shed load from PDS instances
|
|
55
|
+
const token = bearerTokenFromReq(ctx.req);
|
|
56
|
+
const header = token ? jose.decodeProtectedHeader(token) : undefined;
|
|
57
|
+
if (header?.typ === 'at+jwt') {
|
|
58
|
+
// we should never use entryway session tokens in the case of flexible auth audiences (namely in the case of getFeed)
|
|
59
|
+
if (opts.skipAudCheck) {
|
|
60
|
+
throw new AuthRequiredError('Malformed token', 'InvalidToken');
|
|
178
61
|
}
|
|
62
|
+
return this.entrywaySession(ctx);
|
|
63
|
+
}
|
|
64
|
+
// const { iss, aud } = await this.verifyServiceJwt(ctx, {
|
|
65
|
+
// lxmCheck: opts.lxmCheck,
|
|
66
|
+
// iss: null,
|
|
67
|
+
// aud: null,
|
|
68
|
+
// })
|
|
69
|
+
const { aud } = {
|
|
70
|
+
// iss: '',
|
|
71
|
+
aud: '',
|
|
72
|
+
};
|
|
73
|
+
if (!opts.skipAudCheck && !this.standardAudienceDids.has(aud)) {
|
|
74
|
+
throw new AuthRequiredError('jwt audience does not match service did', 'BadJwtAudience');
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
credentials: {
|
|
78
|
+
type: 'standard',
|
|
79
|
+
iss: '',
|
|
80
|
+
aud: '',
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
return this.nullCreds();
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
standardOptional = this.standardOptionalParameterized({});
|
|
89
|
+
standard = async (ctx) => {
|
|
90
|
+
const output = await this.standardOptional(ctx);
|
|
91
|
+
if (output.credentials.type === 'none') {
|
|
92
|
+
throw new AuthRequiredError(undefined, 'AuthMissing');
|
|
93
|
+
}
|
|
94
|
+
return output;
|
|
95
|
+
};
|
|
96
|
+
role = (ctx) => {
|
|
97
|
+
const creds = this.parseRoleCreds(ctx.req);
|
|
98
|
+
if (creds.status !== RoleStatus.Valid) {
|
|
99
|
+
throw new AuthRequiredError();
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
credentials: {
|
|
103
|
+
...creds,
|
|
104
|
+
type: 'role',
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
standardOrRole = async (ctx) => {
|
|
109
|
+
if (isBearerToken(ctx.req)) {
|
|
110
|
+
return this.standard(ctx);
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
return this.role(ctx);
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
optionalStandardOrRole = async (ctx) => {
|
|
117
|
+
if (isBearerToken(ctx.req)) {
|
|
118
|
+
return await this.standard(ctx);
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
const creds = this.parseRoleCreds(ctx.req);
|
|
122
|
+
if (creds.status === RoleStatus.Valid) {
|
|
179
123
|
return {
|
|
180
124
|
credentials: {
|
|
181
125
|
...creds,
|
|
@@ -183,101 +127,54 @@ class AuthVerifier {
|
|
|
183
127
|
},
|
|
184
128
|
};
|
|
185
129
|
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
enumerable: true,
|
|
189
|
-
configurable: true,
|
|
190
|
-
writable: true,
|
|
191
|
-
value: async (ctx) => {
|
|
192
|
-
if (isBearerToken(ctx.req)) {
|
|
193
|
-
return this.standard(ctx);
|
|
194
|
-
}
|
|
195
|
-
else {
|
|
196
|
-
return this.role(ctx);
|
|
197
|
-
}
|
|
130
|
+
else if (creds.status === RoleStatus.Missing) {
|
|
131
|
+
return this.nullCreds();
|
|
198
132
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
enumerable: true,
|
|
202
|
-
configurable: true,
|
|
203
|
-
writable: true,
|
|
204
|
-
value: async (ctx) => {
|
|
205
|
-
if (isBearerToken(ctx.req)) {
|
|
206
|
-
return await this.standard(ctx);
|
|
207
|
-
}
|
|
208
|
-
else {
|
|
209
|
-
const creds = this.parseRoleCreds(ctx.req);
|
|
210
|
-
if (creds.status === RoleStatus.Valid) {
|
|
211
|
-
return {
|
|
212
|
-
credentials: {
|
|
213
|
-
...creds,
|
|
214
|
-
type: 'role',
|
|
215
|
-
},
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
else if (creds.status === RoleStatus.Missing) {
|
|
219
|
-
return this.nullCreds();
|
|
220
|
-
}
|
|
221
|
-
else {
|
|
222
|
-
throw new xrpc_server_1.AuthRequiredError();
|
|
223
|
-
}
|
|
224
|
-
}
|
|
133
|
+
else {
|
|
134
|
+
throw new AuthRequiredError();
|
|
225
135
|
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
.catch((err) => {
|
|
246
|
-
if (err?.['code'] === 'ERR_JWT_EXPIRED') {
|
|
247
|
-
throw new xrpc_server_1.AuthRequiredError('Token has expired', 'ExpiredToken');
|
|
248
|
-
}
|
|
249
|
-
throw new xrpc_server_1.AuthRequiredError('Token could not be verified', 'InvalidToken');
|
|
250
|
-
});
|
|
251
|
-
const { sub, aud, scope } = res.payload;
|
|
252
|
-
if (typeof sub !== 'string' || !sub.startsWith('did:')) {
|
|
253
|
-
throw new xrpc_server_1.AuthRequiredError('Malformed token', 'InvalidToken');
|
|
254
|
-
}
|
|
255
|
-
else if (typeof aud !== 'string' ||
|
|
256
|
-
!aud.startsWith('did:web:') ||
|
|
257
|
-
!aud.endsWith('.bsky.network')) {
|
|
258
|
-
throw new xrpc_server_1.AuthRequiredError('Bad token aud', 'InvalidToken');
|
|
259
|
-
}
|
|
260
|
-
else if (typeof scope !== 'string' || !ALLOWED_AUTH_SCOPES.has(scope)) {
|
|
261
|
-
throw new xrpc_server_1.AuthRequiredError('Bad token scope', 'InvalidToken');
|
|
262
|
-
}
|
|
263
|
-
return {
|
|
264
|
-
credentials: {
|
|
265
|
-
type: 'standard',
|
|
266
|
-
aud: this.ownDid,
|
|
267
|
-
iss: sub,
|
|
268
|
-
},
|
|
269
|
-
};
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
// @NOTE this auth verifier method is not recommended to be implemented by most appviews
|
|
139
|
+
// this is a short term fix to remove proxy load from Bluesky's PDS and in line with possible
|
|
140
|
+
// future plans to have the client talk directly with the appview
|
|
141
|
+
entrywaySession = async (reqCtx) => {
|
|
142
|
+
const token = bearerTokenFromReq(reqCtx.req);
|
|
143
|
+
if (!token) {
|
|
144
|
+
throw new AuthRequiredError(undefined, 'AuthMissing');
|
|
145
|
+
}
|
|
146
|
+
// if entryway jwt key not configured then do not parsed these tokens
|
|
147
|
+
if (!this.entrywayJwtPublicKey) {
|
|
148
|
+
throw new AuthRequiredError('Malformed token', 'InvalidToken');
|
|
149
|
+
}
|
|
150
|
+
const res = await jose
|
|
151
|
+
.jwtVerify(token, this.entrywayJwtPublicKey)
|
|
152
|
+
.catch((err) => {
|
|
153
|
+
if (err?.['code'] === 'ERR_JWT_EXPIRED') {
|
|
154
|
+
throw new AuthRequiredError('Token has expired', 'ExpiredToken');
|
|
270
155
|
}
|
|
156
|
+
throw new AuthRequiredError('Token could not be verified', 'InvalidToken');
|
|
271
157
|
});
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
158
|
+
const { sub, aud, scope } = res.payload;
|
|
159
|
+
if (typeof sub !== 'string' || !sub.startsWith('did:')) {
|
|
160
|
+
throw new AuthRequiredError('Malformed token', 'InvalidToken');
|
|
161
|
+
}
|
|
162
|
+
else if (typeof aud !== 'string' ||
|
|
163
|
+
!aud.startsWith('did:web:') ||
|
|
164
|
+
!aud.endsWith('.bsky.network')) {
|
|
165
|
+
throw new AuthRequiredError('Bad token aud', 'InvalidToken');
|
|
166
|
+
}
|
|
167
|
+
else if (typeof scope !== 'string' || !ALLOWED_AUTH_SCOPES.has(scope)) {
|
|
168
|
+
throw new AuthRequiredError('Bad token scope', 'InvalidToken');
|
|
169
|
+
}
|
|
170
|
+
return {
|
|
171
|
+
credentials: {
|
|
172
|
+
type: 'standard',
|
|
173
|
+
aud: this.ownDid,
|
|
174
|
+
iss: sub,
|
|
175
|
+
},
|
|
176
|
+
};
|
|
177
|
+
};
|
|
281
178
|
// modService = async (reqCtx: ReqCtx): Promise<ModServiceOutput> => {
|
|
282
179
|
// const { iss, aud } = await this.verifyServiceJwt(reqCtx, {
|
|
283
180
|
// aud: this.ownDid,
|
|
@@ -295,7 +192,7 @@ class AuthVerifier {
|
|
|
295
192
|
// }
|
|
296
193
|
// }
|
|
297
194
|
parseRoleCreds(req) {
|
|
298
|
-
const parsed =
|
|
195
|
+
const parsed = parseBasicAuth(req.headers.authorization || '');
|
|
299
196
|
const { Missing, Valid, Invalid } = RoleStatus;
|
|
300
197
|
if (!parsed) {
|
|
301
198
|
return { status: Missing, admin: false, moderator: false, triage: false };
|
|
@@ -406,7 +303,6 @@ class AuthVerifier {
|
|
|
406
303
|
};
|
|
407
304
|
}
|
|
408
305
|
}
|
|
409
|
-
exports.AuthVerifier = AuthVerifier;
|
|
410
306
|
// HELPERS
|
|
411
307
|
// ---------
|
|
412
308
|
const BEARER = 'Bearer ';
|
|
@@ -423,7 +319,7 @@ const bearerTokenFromReq = (req) => {
|
|
|
423
319
|
return null;
|
|
424
320
|
return header.slice(BEARER.length).trim();
|
|
425
321
|
};
|
|
426
|
-
const parseBasicAuth = (token) => {
|
|
322
|
+
export const parseBasicAuth = (token) => {
|
|
427
323
|
if (!token.startsWith(BASIC))
|
|
428
324
|
return null;
|
|
429
325
|
const b64 = token.slice(BASIC.length);
|
|
@@ -439,35 +335,31 @@ const parseBasicAuth = (token) => {
|
|
|
439
335
|
return null;
|
|
440
336
|
return { username, password };
|
|
441
337
|
};
|
|
442
|
-
|
|
443
|
-
const buildBasicAuth = (username, password) => {
|
|
338
|
+
export const buildBasicAuth = (username, password) => {
|
|
444
339
|
return (BASIC +
|
|
445
340
|
ui8.toString(ui8.fromString(`${username}:${password}`, 'utf8'), 'base64pad'));
|
|
446
341
|
};
|
|
447
|
-
|
|
448
|
-
const
|
|
449
|
-
const createPublicKeyObject = (publicKeyHex) => {
|
|
342
|
+
const keyEncoder = new KeyEncoder('secp256k1');
|
|
343
|
+
export const createPublicKeyObject = (publicKeyHex) => {
|
|
450
344
|
const key = keyEncoder.encodePublic(publicKeyHex, 'raw', 'pem');
|
|
451
|
-
return
|
|
345
|
+
return crypto.createPublicKey({ format: 'pem', key });
|
|
452
346
|
};
|
|
453
|
-
exports.createPublicKeyObject = createPublicKeyObject;
|
|
454
347
|
const verifySig = (publicKey, data, sig) => {
|
|
455
|
-
const keyEncoder = new
|
|
348
|
+
const keyEncoder = new KeyEncoder('secp256k1');
|
|
456
349
|
const pemKey = keyEncoder.encodePublic(ui8.toString(publicKey, 'hex'), 'raw', 'pem');
|
|
457
|
-
const key =
|
|
458
|
-
return
|
|
350
|
+
const key = crypto.createPublicKey({ format: 'pem', key: pemKey });
|
|
351
|
+
return crypto.verify('sha256', data, {
|
|
459
352
|
key,
|
|
460
353
|
dsaEncoding: 'ieee-p1363',
|
|
461
354
|
}, sig);
|
|
462
355
|
};
|
|
463
|
-
const verifySignatureWithKey = async (didKey, msgBytes, sigBytes, alg) => {
|
|
464
|
-
if (alg ===
|
|
465
|
-
const parsed =
|
|
356
|
+
export const verifySignatureWithKey = async (didKey, msgBytes, sigBytes, alg) => {
|
|
357
|
+
if (alg === SECP256K1_JWT_ALG) {
|
|
358
|
+
const parsed = parseDidKey(didKey);
|
|
466
359
|
if (alg !== parsed.jwtAlg) {
|
|
467
360
|
throw new Error(`Expected key alg ${alg}, got ${parsed.jwtAlg}`);
|
|
468
361
|
}
|
|
469
362
|
return verifySig(parsed.keyBytes, msgBytes, sigBytes);
|
|
470
363
|
}
|
|
471
|
-
return
|
|
364
|
+
return cryptoVerifySignatureWithKey(didKey, msgBytes, sigBytes, alg);
|
|
472
365
|
};
|
|
473
|
-
exports.verifySignatureWithKey = verifySignatureWithKey;
|
package/dist/client.js
CHANGED
|
@@ -1,25 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
exports.createBaseClient = void 0;
|
|
7
|
-
const connect_1 = require("@connectrpc/connect");
|
|
8
|
-
const connect_node_1 = require("@connectrpc/connect-node");
|
|
9
|
-
const node_assert_1 = __importDefault(require("node:assert"));
|
|
10
|
-
const clio_connect_1 = require("./rpc/clio_connect");
|
|
11
|
-
const createBaseClient = (baseUrl, opts) => {
|
|
1
|
+
import { createClient } from '@connectrpc/connect';
|
|
2
|
+
import { createGrpcTransport } from '@connectrpc/connect-node';
|
|
3
|
+
import assert from 'node:assert';
|
|
4
|
+
import { ClioService } from './rpc/clio_connect';
|
|
5
|
+
export const createBaseClient = (baseUrl, opts) => {
|
|
12
6
|
const { httpVersion = '2', rejectUnauthorized = true } = opts;
|
|
13
|
-
const transport =
|
|
7
|
+
const transport = createGrpcTransport({
|
|
14
8
|
baseUrl,
|
|
15
9
|
acceptCompression: [],
|
|
16
10
|
httpVersion,
|
|
17
11
|
nodeOptions: { rejectUnauthorized },
|
|
18
12
|
});
|
|
19
|
-
(
|
|
20
|
-
return
|
|
13
|
+
assert(validateUrl(baseUrl));
|
|
14
|
+
return createClient(ClioService, transport);
|
|
21
15
|
};
|
|
22
|
-
exports.createBaseClient = createBaseClient;
|
|
23
16
|
const validateUrl = (urlStr) => {
|
|
24
17
|
let url;
|
|
25
18
|
try {
|