@atproto/pds 0.5.5 → 0.5.6
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/CHANGELOG.md +15 -0
- package/dist/account-manager/account-manager.d.ts +51 -13
- package/dist/account-manager/account-manager.d.ts.map +1 -1
- package/dist/account-manager/account-manager.js +86 -26
- package/dist/account-manager/account-manager.js.map +1 -1
- package/dist/account-manager/db/migrations/005-oauth-account-management.d.ts.map +1 -1
- package/dist/account-manager/db/migrations/005-oauth-account-management.js +3 -4
- package/dist/account-manager/db/migrations/005-oauth-account-management.js.map +1 -1
- package/dist/account-manager/db/schema/authorization-request.d.ts +2 -2
- package/dist/account-manager/db/schema/authorization-request.d.ts.map +1 -1
- package/dist/account-manager/db/schema/authorization-request.js.map +1 -1
- package/dist/account-manager/db/schema/authorized-client.d.ts +2 -2
- package/dist/account-manager/db/schema/authorized-client.d.ts.map +1 -1
- package/dist/account-manager/db/schema/authorized-client.js.map +1 -1
- package/dist/account-manager/db/schema/token.d.ts +2 -2
- package/dist/account-manager/db/schema/token.d.ts.map +1 -1
- package/dist/account-manager/db/schema/token.js.map +1 -1
- package/dist/account-manager/helpers/account-device.d.ts +23 -196
- package/dist/account-manager/helpers/account-device.d.ts.map +1 -1
- package/dist/account-manager/helpers/account-device.js +3 -3
- package/dist/account-manager/helpers/account-device.js.map +1 -1
- package/dist/account-manager/helpers/account.d.ts +14 -4
- package/dist/account-manager/helpers/account.d.ts.map +1 -1
- package/dist/account-manager/helpers/account.js +17 -11
- package/dist/account-manager/helpers/account.js.map +1 -1
- package/dist/account-manager/helpers/auth.js +1 -1
- package/dist/account-manager/helpers/auth.js.map +1 -1
- package/dist/account-manager/helpers/authorization-request.d.ts +83 -5
- package/dist/account-manager/helpers/authorization-request.d.ts.map +1 -1
- package/dist/account-manager/helpers/authorization-request.js +8 -8
- package/dist/account-manager/helpers/authorization-request.js.map +1 -1
- package/dist/account-manager/helpers/authorized-client.d.ts +5 -4
- package/dist/account-manager/helpers/authorized-client.d.ts.map +1 -1
- package/dist/account-manager/helpers/authorized-client.js +3 -0
- package/dist/account-manager/helpers/authorized-client.js.map +1 -1
- package/dist/account-manager/helpers/device.d.ts +9 -3
- package/dist/account-manager/helpers/device.d.ts.map +1 -1
- package/dist/account-manager/helpers/device.js +4 -4
- package/dist/account-manager/helpers/device.js.map +1 -1
- package/dist/account-manager/helpers/invite.d.ts +35 -2
- package/dist/account-manager/helpers/invite.d.ts.map +1 -1
- package/dist/account-manager/helpers/lexicon.d.ts.map +1 -1
- package/dist/account-manager/helpers/lexicon.js +6 -0
- package/dist/account-manager/helpers/lexicon.js.map +1 -1
- package/dist/account-manager/helpers/password.d.ts +1 -0
- package/dist/account-manager/helpers/password.d.ts.map +1 -1
- package/dist/account-manager/helpers/password.js +3 -0
- package/dist/account-manager/helpers/password.js.map +1 -1
- package/dist/account-manager/helpers/token.d.ts +72 -1031
- package/dist/account-manager/helpers/token.d.ts.map +1 -1
- package/dist/account-manager/helpers/token.js +13 -10
- package/dist/account-manager/helpers/token.js.map +1 -1
- package/dist/account-manager/helpers/used-refresh-token.d.ts +6 -2
- package/dist/account-manager/helpers/used-refresh-token.d.ts.map +1 -1
- package/dist/account-manager/oauth-store.d.ts +17 -13
- package/dist/account-manager/oauth-store.d.ts.map +1 -1
- package/dist/account-manager/oauth-store.js +89 -39
- package/dist/account-manager/oauth-store.js.map +1 -1
- package/dist/actor-store/blob/reader.d.ts.map +1 -1
- package/dist/actor-store/blob/reader.js +2 -3
- package/dist/actor-store/blob/reader.js.map +1 -1
- package/dist/actor-store/record/reader.js +3 -3
- package/dist/actor-store/record/reader.js.map +1 -1
- package/dist/actor-store/repo/sql-repo-reader.d.ts +5 -1
- package/dist/actor-store/repo/sql-repo-reader.d.ts.map +1 -1
- package/dist/actor-store/repo/sql-repo-reader.js.map +1 -1
- package/dist/api/com/atproto/admin/updateSubjectStatus.d.ts.map +1 -1
- package/dist/api/com/atproto/admin/updateSubjectStatus.js +12 -4
- package/dist/api/com/atproto/admin/updateSubjectStatus.js.map +1 -1
- package/dist/api/com/atproto/server/activateAccount.d.ts.map +1 -1
- package/dist/api/com/atproto/server/activateAccount.js +25 -31
- package/dist/api/com/atproto/server/activateAccount.js.map +1 -1
- package/dist/api/com/atproto/server/deactivateAccount.d.ts.map +1 -1
- package/dist/api/com/atproto/server/deactivateAccount.js +3 -4
- package/dist/api/com/atproto/server/deactivateAccount.js.map +1 -1
- package/dist/api/com/atproto/server/deleteAccount.d.ts.map +1 -1
- package/dist/api/com/atproto/server/deleteAccount.js +51 -37
- package/dist/api/com/atproto/server/deleteAccount.js.map +1 -1
- package/dist/api/com/atproto/server/util.d.ts +25 -6
- package/dist/api/com/atproto/server/util.d.ts.map +1 -1
- package/dist/api/com/atproto/server/util.js.map +1 -1
- package/dist/config/config.d.ts +2 -1
- package/dist/config/config.d.ts.map +1 -1
- package/dist/config/config.js +4 -1
- package/dist/config/config.js.map +1 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +1 -1
- package/dist/context.js.map +1 -1
- package/dist/db/migrator.d.ts +4 -3
- package/dist/db/migrator.d.ts.map +1 -1
- package/dist/db/migrator.js +1 -1
- package/dist/db/migrator.js.map +1 -1
- package/dist/db/pagination.d.ts +2 -1
- package/dist/db/pagination.d.ts.map +1 -1
- package/dist/db/pagination.js +2 -2
- package/dist/db/pagination.js.map +1 -1
- package/dist/db/util.d.ts +3 -3
- package/dist/db/util.d.ts.map +1 -1
- package/dist/db/util.js.map +1 -1
- package/dist/mailer/index.d.ts +2 -0
- package/dist/mailer/index.d.ts.map +1 -1
- package/dist/mailer/index.js +2 -0
- package/dist/mailer/index.js.map +1 -1
- package/dist/scripts/sequencer-recovery/recovery-db.js.map +1 -1
- package/dist/sequencer/events.d.ts.map +1 -1
- package/dist/sequencer/events.js +6 -13
- package/dist/sequencer/events.js.map +1 -1
- package/dist/sequencer/sequencer.d.ts +1 -1
- package/dist/sequencer/sequencer.d.ts.map +1 -1
- package/dist/sequencer/sequencer.js.map +1 -1
- package/package.json +13 -13
- package/src/account-manager/account-manager.ts +135 -36
- package/src/account-manager/db/migrations/005-oauth-account-management.ts +6 -5
- package/src/account-manager/db/schema/authorization-request.ts +2 -1
- package/src/account-manager/db/schema/authorized-client.ts +6 -2
- package/src/account-manager/db/schema/token.ts +2 -2
- package/src/account-manager/helpers/account-device.ts +5 -11
- package/src/account-manager/helpers/account.ts +39 -16
- package/src/account-manager/helpers/auth.ts +2 -2
- package/src/account-manager/helpers/authorization-request.ts +12 -8
- package/src/account-manager/helpers/authorized-client.ts +12 -6
- package/src/account-manager/helpers/device.ts +4 -4
- package/src/account-manager/helpers/lexicon.ts +8 -3
- package/src/account-manager/helpers/password.ts +6 -0
- package/src/account-manager/helpers/token.ts +17 -11
- package/src/account-manager/oauth-store.ts +129 -61
- package/src/actor-store/blob/reader.ts +8 -5
- package/src/actor-store/record/reader.ts +3 -3
- package/src/actor-store/repo/sql-repo-reader.ts +1 -1
- package/src/api/com/atproto/admin/updateSubjectStatus.ts +16 -4
- package/src/api/com/atproto/server/activateAccount.ts +27 -49
- package/src/api/com/atproto/server/deactivateAccount.ts +3 -7
- package/src/api/com/atproto/server/deleteAccount.ts +60 -43
- package/src/api/com/atproto/server/util.ts +24 -7
- package/src/config/config.ts +7 -2
- package/src/context.ts +2 -3
- package/src/db/migrator.ts +2 -1
- package/src/db/pagination.ts +7 -7
- package/src/db/util.ts +5 -2
- package/src/mailer/index.ts +4 -2
- package/src/scripts/sequencer-recovery/recovery-db.ts +1 -1
- package/src/sequencer/events.ts +8 -13
- package/src/sequencer/sequencer.ts +1 -3
- package/tests/account-manager.test.ts +79 -0
- package/tests/account-status.test.ts +206 -0
- package/tests/db.test.ts +3 -3
- package/tests/oauth.test.ts +91 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @atproto/pds
|
|
2
2
|
|
|
3
|
+
## 0.5.6
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#5053](https://github.com/bluesky-social/atproto/pull/5053) [`9acd39b`](https://github.com/bluesky-social/atproto/commit/9acd39b22ead6c0c56428297de425bd2b9a3c61f) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Calling `updateSubjectStatus` to both activate & take an account down will result in an error as takendown accounts can no longer be updated to an "active" status
|
|
8
|
+
|
|
9
|
+
- [#5053](https://github.com/bluesky-social/atproto/pull/5053) [`9acd39b`](https://github.com/bluesky-social/atproto/commit/9acd39b22ead6c0c56428297de425bd2b9a3c61f) Thanks [@matthieusieben](https://github.com/matthieusieben)! - `com.atproto.admin.updateSubjectStatus` will throw when trying to re-activate an account whose DID does not resolve to the right PDS
|
|
10
|
+
|
|
11
|
+
- [#5086](https://github.com/bluesky-social/atproto/pull/5086) [`20665c1`](https://github.com/bluesky-social/atproto/commit/20665c18322effe648f73d70fc1a8dcc7e312992) Thanks [@devinivy](https://github.com/devinivy)! - Upgrade kysely from 0.22 to 0.29
|
|
12
|
+
|
|
13
|
+
- [#5053](https://github.com/bluesky-social/atproto/pull/5053) [`9acd39b`](https://github.com/bluesky-social/atproto/commit/9acd39b22ead6c0c56428297de425bd2b9a3c61f) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Add ability to deactivate and delete account from the account manager interface
|
|
14
|
+
|
|
15
|
+
- Updated dependencies [[`9acd39b`](https://github.com/bluesky-social/atproto/commit/9acd39b22ead6c0c56428297de425bd2b9a3c61f), [`9acd39b`](https://github.com/bluesky-social/atproto/commit/9acd39b22ead6c0c56428297de425bd2b9a3c61f), [`9acd39b`](https://github.com/bluesky-social/atproto/commit/9acd39b22ead6c0c56428297de425bd2b9a3c61f)]:
|
|
16
|
+
- @atproto/oauth-provider@0.19.0
|
|
17
|
+
|
|
3
18
|
## 0.5.5
|
|
4
19
|
|
|
5
20
|
### Patch Changes
|
|
@@ -5,11 +5,13 @@ import { IdResolver } from '@atproto/identity';
|
|
|
5
5
|
import { AtIdentifierString, DidString, HandleString } from '@atproto/lex';
|
|
6
6
|
import { Cid } from '@atproto/lex-data';
|
|
7
7
|
import { AuthRequiredError } from '@atproto/xrpc-server';
|
|
8
|
+
import { ActorStore } from '../actor-store/actor-store.js';
|
|
9
|
+
import { ServerConfig } from '../config/config.js';
|
|
8
10
|
import { com } from '../lexicons/index.js';
|
|
9
11
|
import { ServerMailer } from '../mailer/index.js';
|
|
10
12
|
import { Sequencer } from '../sequencer/index.js';
|
|
11
13
|
import { AccountDb, EmailTokenPurpose } from './db/index.js';
|
|
12
|
-
import * as
|
|
14
|
+
import * as accountHelpers from './helpers/account.js';
|
|
13
15
|
import { AccountStatus, ActorAccount } from './helpers/account.js';
|
|
14
16
|
import * as password from './helpers/password.js';
|
|
15
17
|
export { AccountStatus, formatAccountStatus } from './helpers/account.js';
|
|
@@ -26,32 +28,46 @@ export { AccountStatus, formatAccountStatus } from './helpers/account.js';
|
|
|
26
28
|
* packages/pds/tests/auth.test.ts)
|
|
27
29
|
*/
|
|
28
30
|
export declare class InvalidPasswordError extends AuthRequiredError {
|
|
29
|
-
readonly did:
|
|
30
|
-
constructor(did:
|
|
31
|
+
readonly did: DidString;
|
|
32
|
+
constructor(did: DidString, errorMessage?: string);
|
|
31
33
|
}
|
|
32
34
|
export type AccountManagerDbConfig = {
|
|
33
35
|
accountDbLoc: string;
|
|
34
36
|
disableWalAutoCheckpoint: boolean;
|
|
35
37
|
};
|
|
36
38
|
export declare class AccountManager {
|
|
39
|
+
readonly cfg: ServerConfig;
|
|
40
|
+
readonly actorStore: ActorStore;
|
|
37
41
|
readonly idResolver: IdResolver;
|
|
38
42
|
readonly jwtKey: KeyObject;
|
|
39
43
|
readonly mailer: ServerMailer;
|
|
40
44
|
readonly sequencer: Sequencer;
|
|
41
45
|
readonly plcClient: PlcClient;
|
|
42
46
|
readonly plcRotationKey: Keypair;
|
|
43
|
-
readonly serviceDid: string;
|
|
44
|
-
readonly serviceHandleDomains: string[];
|
|
45
47
|
readonly db: AccountDb;
|
|
46
|
-
constructor(idResolver: IdResolver, jwtKey: KeyObject, mailer: ServerMailer, sequencer: Sequencer, plcClient: PlcClient, plcRotationKey: Keypair
|
|
48
|
+
constructor(cfg: ServerConfig, actorStore: ActorStore, idResolver: IdResolver, jwtKey: KeyObject, mailer: ServerMailer, sequencer: Sequencer, plcClient: PlcClient, plcRotationKey: Keypair);
|
|
49
|
+
get serviceDid(): DidString;
|
|
50
|
+
get serviceHandleDomains(): string[];
|
|
47
51
|
migrateOrThrow(): Promise<void>;
|
|
48
52
|
close(): void;
|
|
49
|
-
getAccount(handleOrDid: AtIdentifierString, flags?:
|
|
50
|
-
getAccounts(dids: DidString[], flags?:
|
|
51
|
-
getAccountByEmail(email: string, flags?:
|
|
53
|
+
getAccount(handleOrDid: AtIdentifierString, flags?: accountHelpers.AvailabilityFlags): Promise<ActorAccount | null>;
|
|
54
|
+
getAccounts(dids: DidString[], flags?: accountHelpers.AvailabilityFlags): Promise<Map<string, ActorAccount>>;
|
|
55
|
+
getAccountByEmail(email: string, flags?: accountHelpers.AvailabilityFlags): Promise<ActorAccount | null>;
|
|
52
56
|
isAccountActivated(did: DidString): Promise<boolean>;
|
|
53
|
-
getDidForActor(handleOrDid: AtIdentifierString, flags?:
|
|
54
|
-
getAccountStatus(handleOrDid: AtIdentifierString): Promise<
|
|
57
|
+
getDidForActor(handleOrDid: AtIdentifierString, flags?: accountHelpers.AvailabilityFlags): Promise<DidString | null>;
|
|
58
|
+
getAccountStatus(handleOrDid: AtIdentifierString): Promise<{
|
|
59
|
+
status: AccountStatus.Deleted;
|
|
60
|
+
account: null;
|
|
61
|
+
} | {
|
|
62
|
+
status: AccountStatus.Takendown;
|
|
63
|
+
account: ActorAccount;
|
|
64
|
+
} | {
|
|
65
|
+
status: AccountStatus.Deactivated;
|
|
66
|
+
account: ActorAccount;
|
|
67
|
+
} | {
|
|
68
|
+
status: AccountStatus.Active;
|
|
69
|
+
account: ActorAccount;
|
|
70
|
+
}>;
|
|
55
71
|
normalizeAndValidateHandle(handle: string, { did, allowAnyValid, }?: {
|
|
56
72
|
did?: string;
|
|
57
73
|
allowAnyValid?: boolean;
|
|
@@ -113,8 +129,30 @@ export declare class AccountManager {
|
|
|
113
129
|
deactivated: com.atproto.admin.defs.StatusAttr;
|
|
114
130
|
} | null>;
|
|
115
131
|
updateRepoRoot(did: DidString, cid: Cid, rev: string): Promise<void>;
|
|
116
|
-
deactivateAccount(did: DidString,
|
|
117
|
-
|
|
132
|
+
deactivateAccount(did: DidString, options?: {
|
|
133
|
+
deleteCredentials?: boolean;
|
|
134
|
+
deleteAfter?: string | null;
|
|
135
|
+
}): Promise<{
|
|
136
|
+
status: AccountStatus.Takendown;
|
|
137
|
+
account: ActorAccount;
|
|
138
|
+
} | {
|
|
139
|
+
status: AccountStatus.Deactivated;
|
|
140
|
+
account: ActorAccount;
|
|
141
|
+
} | {
|
|
142
|
+
status: AccountStatus.Active;
|
|
143
|
+
account: ActorAccount;
|
|
144
|
+
}>;
|
|
145
|
+
activateAccount(did: DidString): Promise<{
|
|
146
|
+
status: AccountStatus.Takendown;
|
|
147
|
+
account: ActorAccount;
|
|
148
|
+
} | {
|
|
149
|
+
status: AccountStatus.Deactivated;
|
|
150
|
+
account: ActorAccount;
|
|
151
|
+
} | {
|
|
152
|
+
status: AccountStatus.Active;
|
|
153
|
+
account: ActorAccount;
|
|
154
|
+
}>;
|
|
155
|
+
sequenceAccountStatus(did: DidString): Promise<void>;
|
|
118
156
|
createSession(did: DidString, appPassword: password.AppPassDescript | null, isSoftDeleted?: boolean): Promise<{
|
|
119
157
|
accessJwt: string;
|
|
120
158
|
refreshJwt: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account-manager.d.ts","sourceRoot":"","sources":["../../src/account-manager/account-manager.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"account-manager.d.ts","sourceRoot":"","sources":["../../src/account-manager/account-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,18 +1,21 @@
|
|
|
1
|
+
import assert from 'node:assert';
|
|
1
2
|
import { isEmailValid } from '@hapi/address';
|
|
2
3
|
import { isDisposableEmail } from 'disposable-email-domains-js';
|
|
3
4
|
import { HOUR, wait } from '@atproto/common';
|
|
4
5
|
import { isAtIdentifierString, } from '@atproto/lex';
|
|
5
|
-
import { currentDatetimeString, isValidTld } from '@atproto/syntax';
|
|
6
|
+
import { INVALID_HANDLE, currentDatetimeString, isValidTld, } from '@atproto/syntax';
|
|
6
7
|
import { AuthRequiredError, InvalidRequestError } from '@atproto/xrpc-server';
|
|
8
|
+
import { assertValidDidDocumentForService } from '../api/com/atproto/server/util.js';
|
|
7
9
|
import { AuthScope } from '../auth-scope.js';
|
|
8
10
|
import { softDeleted } from '../db/index.js';
|
|
9
11
|
import { hasExplicitSlur } from '../handle/explicit-slurs.js';
|
|
10
12
|
import { baseNormalizeAndValidate, ensureHandleServiceConstraints, isServiceDomain, } from '../handle/index.js';
|
|
11
13
|
import { httpLogger } from '../logger.js';
|
|
12
14
|
import { getDb, getMigrator } from './db/index.js';
|
|
13
|
-
import * as
|
|
15
|
+
import * as accountHelpers from './helpers/account.js';
|
|
14
16
|
import { AccountStatus } from './helpers/account.js';
|
|
15
17
|
import * as auth from './helpers/auth.js';
|
|
18
|
+
import * as authorizedClientHelper from './helpers/authorized-client.js';
|
|
16
19
|
import * as emailToken from './helpers/email-token.js';
|
|
17
20
|
import * as invite from './helpers/invite.js';
|
|
18
21
|
import * as password from './helpers/password.js';
|
|
@@ -39,16 +42,22 @@ export class InvalidPasswordError extends AuthRequiredError {
|
|
|
39
42
|
}
|
|
40
43
|
}
|
|
41
44
|
export class AccountManager {
|
|
42
|
-
constructor(idResolver, jwtKey, mailer, sequencer, plcClient, plcRotationKey
|
|
45
|
+
constructor(cfg, actorStore, idResolver, jwtKey, mailer, sequencer, plcClient, plcRotationKey) {
|
|
46
|
+
this.cfg = cfg;
|
|
47
|
+
this.actorStore = actorStore;
|
|
43
48
|
this.idResolver = idResolver;
|
|
44
49
|
this.jwtKey = jwtKey;
|
|
45
50
|
this.mailer = mailer;
|
|
46
51
|
this.sequencer = sequencer;
|
|
47
52
|
this.plcClient = plcClient;
|
|
48
53
|
this.plcRotationKey = plcRotationKey;
|
|
49
|
-
this.
|
|
50
|
-
|
|
51
|
-
|
|
54
|
+
this.db = getDb(cfg.db.accountDbLoc, cfg.db.disableWalAutoCheckpoint);
|
|
55
|
+
}
|
|
56
|
+
get serviceDid() {
|
|
57
|
+
return this.cfg.service.did;
|
|
58
|
+
}
|
|
59
|
+
get serviceHandleDomains() {
|
|
60
|
+
return this.cfg.identity.serviceHandleDomains;
|
|
52
61
|
}
|
|
53
62
|
async migrateOrThrow() {
|
|
54
63
|
await this.db.ensureWal();
|
|
@@ -60,13 +69,13 @@ export class AccountManager {
|
|
|
60
69
|
// Account
|
|
61
70
|
// ----------
|
|
62
71
|
async getAccount(handleOrDid, flags) {
|
|
63
|
-
return
|
|
72
|
+
return accountHelpers.getAccount(this.db, handleOrDid, flags);
|
|
64
73
|
}
|
|
65
74
|
async getAccounts(dids, flags) {
|
|
66
|
-
return
|
|
75
|
+
return accountHelpers.getAccounts(this.db, dids, flags);
|
|
67
76
|
}
|
|
68
77
|
async getAccountByEmail(email, flags) {
|
|
69
|
-
return
|
|
78
|
+
return accountHelpers.getAccountByEmail(this.db, email, flags);
|
|
70
79
|
}
|
|
71
80
|
async isAccountActivated(did) {
|
|
72
81
|
const account = await this.getAccount(did, { includeDeactivated: true });
|
|
@@ -83,8 +92,9 @@ export class AccountManager {
|
|
|
83
92
|
includeDeactivated: true,
|
|
84
93
|
includeTakenDown: true,
|
|
85
94
|
});
|
|
86
|
-
const
|
|
87
|
-
|
|
95
|
+
const { active, status = active ? AccountStatus.Active : undefined } = accountHelpers.formatAccountStatus(got);
|
|
96
|
+
assert(status != null);
|
|
97
|
+
return { status, account: got };
|
|
88
98
|
}
|
|
89
99
|
async normalizeAndValidateHandle(handle, { did, allowAnyValid = false, } = {}) {
|
|
90
100
|
const normalized = baseNormalizeAndValidate(handle);
|
|
@@ -126,9 +136,13 @@ export class AccountManager {
|
|
|
126
136
|
if (inviteCode) {
|
|
127
137
|
await invite.ensureInviteIsAvailable(dbTxn, inviteCode);
|
|
128
138
|
}
|
|
129
|
-
await
|
|
139
|
+
await accountHelpers.registerActor(dbTxn, { did, handle, deactivated });
|
|
130
140
|
if (email && passwordScrypt) {
|
|
131
|
-
await
|
|
141
|
+
await accountHelpers.registerAccount(dbTxn, {
|
|
142
|
+
did,
|
|
143
|
+
email,
|
|
144
|
+
passwordScrypt,
|
|
145
|
+
});
|
|
132
146
|
}
|
|
133
147
|
await invite.recordInviteUse(dbTxn, {
|
|
134
148
|
did,
|
|
@@ -201,7 +215,7 @@ export class AccountManager {
|
|
|
201
215
|
* can emit the event again by updating their handle to the same value.
|
|
202
216
|
*/
|
|
203
217
|
async updateAccountHandle(did, handle) {
|
|
204
|
-
await
|
|
218
|
+
await accountHelpers.updateHandle(this.db, did, handle);
|
|
205
219
|
try {
|
|
206
220
|
await this.sequencer.sequenceIdentity(did, handle);
|
|
207
221
|
}
|
|
@@ -210,26 +224,67 @@ export class AccountManager {
|
|
|
210
224
|
}
|
|
211
225
|
}
|
|
212
226
|
async deleteAccount(did) {
|
|
213
|
-
return
|
|
227
|
+
return accountHelpers.deleteAccount(this.db, did);
|
|
214
228
|
}
|
|
215
229
|
async takedownAccount(did, takedown) {
|
|
216
|
-
await this.db.transaction(async (dbTxn) =>
|
|
217
|
-
|
|
218
|
-
auth.revokeRefreshTokensByDid(dbTxn, did)
|
|
219
|
-
token.
|
|
220
|
-
|
|
230
|
+
await this.db.transaction(async (dbTxn) => {
|
|
231
|
+
await accountHelpers.updateAccountTakedownStatus(dbTxn, did, takedown);
|
|
232
|
+
await auth.revokeRefreshTokensByDid(dbTxn, did);
|
|
233
|
+
await token.removeByDid(dbTxn, did);
|
|
234
|
+
});
|
|
235
|
+
await this.sequenceAccountStatus(did);
|
|
221
236
|
}
|
|
222
237
|
async getAccountAdminStatus(did) {
|
|
223
|
-
return
|
|
238
|
+
return accountHelpers.getAccountAdminStatus(this.db, did);
|
|
224
239
|
}
|
|
225
240
|
async updateRepoRoot(did, cid, rev) {
|
|
226
241
|
return repo.updateRoot(this.db, did, cid, rev);
|
|
227
242
|
}
|
|
228
|
-
async deactivateAccount(did,
|
|
229
|
-
|
|
243
|
+
async deactivateAccount(did, options) {
|
|
244
|
+
const wasUpdated = await this.db.transaction(async (dbTxn) => {
|
|
245
|
+
if (options?.deleteCredentials) {
|
|
246
|
+
await token.removeByDid(dbTxn, did);
|
|
247
|
+
await authorizedClientHelper.deleteAllAuthorizedClients(dbTxn, did);
|
|
248
|
+
await password.deleteAllAppPasswords(dbTxn, did);
|
|
249
|
+
}
|
|
250
|
+
return accountHelpers.deactivateAccount(dbTxn, did, options?.deleteAfter ?? null);
|
|
251
|
+
});
|
|
252
|
+
if (!wasUpdated) {
|
|
253
|
+
throw new InvalidRequestError('Account not found');
|
|
254
|
+
}
|
|
255
|
+
const accountStatus = await this.getAccountStatus(did);
|
|
256
|
+
// Account is likely soft-deleted (takendown)
|
|
257
|
+
if (accountStatus.status === AccountStatus.Deleted) {
|
|
258
|
+
throw new InvalidRequestError('Account not found');
|
|
259
|
+
}
|
|
260
|
+
await this.sequencer.sequenceAccount(did, accountStatus.status);
|
|
261
|
+
return accountStatus;
|
|
230
262
|
}
|
|
231
263
|
async activateAccount(did) {
|
|
232
|
-
|
|
264
|
+
await assertValidDidDocumentForService(this, did);
|
|
265
|
+
const found = await accountHelpers.activateAccount(this.db, did, {
|
|
266
|
+
// We cannot activate a takendown account
|
|
267
|
+
includeTakenDown: false,
|
|
268
|
+
includeDeactivated: true,
|
|
269
|
+
});
|
|
270
|
+
if (!found) {
|
|
271
|
+
throw new InvalidRequestError('user not found', 'AccountNotFound');
|
|
272
|
+
}
|
|
273
|
+
const accountStatus = await this.getAccountStatus(did);
|
|
274
|
+
const { account, status } = accountStatus;
|
|
275
|
+
if (status === AccountStatus.Deleted) {
|
|
276
|
+
// A concurrent operation deleted the account
|
|
277
|
+
throw new InvalidRequestError('user not found', 'AccountNotFound');
|
|
278
|
+
}
|
|
279
|
+
const syncData = await this.actorStore.read(did, (store) => {
|
|
280
|
+
return store.repo.getSyncEventData();
|
|
281
|
+
});
|
|
282
|
+
await this.sequencer.sequenceAccountActivation(did, account.handle ?? INVALID_HANDLE, status, syncData);
|
|
283
|
+
return accountStatus;
|
|
284
|
+
}
|
|
285
|
+
async sequenceAccountStatus(did) {
|
|
286
|
+
const { status } = await this.getAccountStatus(did);
|
|
287
|
+
await this.sequencer.sequenceAccount(did, status);
|
|
233
288
|
}
|
|
234
289
|
// Auth
|
|
235
290
|
// ----------
|
|
@@ -345,6 +400,11 @@ export class AccountManager {
|
|
|
345
400
|
return password.listAppPasswords(this.db, did);
|
|
346
401
|
}
|
|
347
402
|
async verifyAccountPassword(did, passwordStr) {
|
|
403
|
+
if (passwordStr.length > scrypt.OLD_PASSWORD_MAX_LENGTH) {
|
|
404
|
+
// @NOTE Avoid throwing from here to avoid leaking account email validity
|
|
405
|
+
// through error messages.
|
|
406
|
+
return false;
|
|
407
|
+
}
|
|
348
408
|
return password.verifyAccountPassword(this.db, did, passwordStr);
|
|
349
409
|
}
|
|
350
410
|
async verifyAppPassword(did, passwordStr) {
|
|
@@ -428,7 +488,7 @@ export class AccountManager {
|
|
|
428
488
|
const now = currentDatetimeString();
|
|
429
489
|
await this.db.transaction(async (dbTxn) => {
|
|
430
490
|
await emailToken.deleteEmailToken(dbTxn, did, 'confirm_email');
|
|
431
|
-
await
|
|
491
|
+
await accountHelpers.setEmailConfirmedAt(dbTxn, did, now);
|
|
432
492
|
});
|
|
433
493
|
user.emailConfirmedAt = now;
|
|
434
494
|
return user;
|
|
@@ -489,7 +549,7 @@ export class AccountManager {
|
|
|
489
549
|
async updateAccountEmail(opts) {
|
|
490
550
|
const { did, email } = opts;
|
|
491
551
|
await this.db.transaction(async (dbTxn) => {
|
|
492
|
-
await
|
|
552
|
+
await accountHelpers.updateEmail(dbTxn, did, email);
|
|
493
553
|
await emailToken.deleteAllEmailTokens(dbTxn, did);
|
|
494
554
|
});
|
|
495
555
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account-manager.js","sourceRoot":"","sources":["../../src/account-manager/account-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import { KeyObject } from 'node:crypto'\nimport { Client as PlcClient } from '@did-plc/lib'\nimport { isEmailValid } from '@hapi/address'\nimport { isDisposableEmail } from 'disposable-email-domains-js'\nimport { HOUR, wait } from '@atproto/common'\nimport { Keypair } from '@atproto/crypto'\nimport { IdResolver } from '@atproto/identity'\nimport {\n AtIdentifierString,\n DidString,\n HandleString,\n isAtIdentifierString,\n} from '@atproto/lex'\nimport { Cid } from '@atproto/lex-data'\nimport { currentDatetimeString, isValidTld } from '@atproto/syntax'\nimport { AuthRequiredError, InvalidRequestError } from '@atproto/xrpc-server'\nimport { AuthScope } from '../auth-scope.js'\nimport { softDeleted } from '../db/index.js'\nimport { hasExplicitSlur } from '../handle/explicit-slurs.js'\nimport {\n baseNormalizeAndValidate,\n ensureHandleServiceConstraints,\n isServiceDomain,\n} from '../handle/index.js'\nimport { com } from '../lexicons/index.js'\nimport { httpLogger } from '../logger.js'\nimport { ServerMailer } from '../mailer/index.js'\nimport { Sequencer } from '../sequencer/index.js'\nimport { AccountDb, EmailTokenPurpose, getDb, getMigrator } from './db/index.js'\nimport * as account from './helpers/account.js'\nimport { AccountStatus, ActorAccount } from './helpers/account.js'\nimport * as auth from './helpers/auth.js'\nimport * as emailToken from './helpers/email-token.js'\nimport * as invite from './helpers/invite.js'\nimport * as password from './helpers/password.js'\nimport * as repo from './helpers/repo.js'\nimport * as scrypt from './helpers/scrypt.js'\nimport * as token from './helpers/token.js'\n\nexport { AccountStatus, formatAccountStatus } from './helpers/account.js'\n\n/**\n * Thrown by {@link AccountManager.login} when the identifier resolved to a\n * known account but the supplied credentials (account password / app\n * password) did not match. The matched `did` is attached so downstream\n * callers can distinguish \"identifier known, credentials wrong\" from\n * \"identifier unknown\" (which continues to throw a plain\n * {@link AuthRequiredError}).\n *\n * Callers should take care that remote clients *cannot* distinguish the above,\n * to prevent enumeration attacks. (Tested for in\n * packages/pds/tests/auth.test.ts)\n */\nexport class InvalidPasswordError extends AuthRequiredError {\n constructor(\n public readonly did: string,\n errorMessage = 'Invalid identifier or password',\n ) {\n super(errorMessage)\n }\n}\n\nexport type AccountManagerDbConfig = {\n accountDbLoc: string\n disableWalAutoCheckpoint: boolean\n}\n\nexport class AccountManager {\n readonly db: AccountDb\n\n constructor(\n readonly idResolver: IdResolver,\n readonly jwtKey: KeyObject,\n readonly mailer: ServerMailer,\n readonly sequencer: Sequencer,\n readonly plcClient: PlcClient,\n readonly plcRotationKey: Keypair,\n readonly serviceDid: string,\n readonly serviceHandleDomains: string[],\n db: AccountManagerDbConfig,\n ) {\n this.db = getDb(db.accountDbLoc, db.disableWalAutoCheckpoint)\n }\n\n async migrateOrThrow() {\n await this.db.ensureWal()\n await getMigrator(this.db).migrateToLatestOrThrow()\n }\n\n close() {\n this.db.close()\n }\n\n // Account\n // ----------\n\n async getAccount(\n handleOrDid: AtIdentifierString,\n flags?: account.AvailabilityFlags,\n ): Promise<ActorAccount | null> {\n return account.getAccount(this.db, handleOrDid, flags)\n }\n\n async getAccounts(\n dids: DidString[],\n flags?: account.AvailabilityFlags,\n ): Promise<Map<string, ActorAccount>> {\n return account.getAccounts(this.db, dids, flags)\n }\n\n async getAccountByEmail(\n email: string,\n flags?: account.AvailabilityFlags,\n ): Promise<ActorAccount | null> {\n return account.getAccountByEmail(this.db, email, flags)\n }\n\n async isAccountActivated(did: DidString): Promise<boolean> {\n const account = await this.getAccount(did, { includeDeactivated: true })\n if (!account) return false\n return !account.deactivatedAt\n }\n\n async getDidForActor(\n handleOrDid: AtIdentifierString,\n flags?: account.AvailabilityFlags,\n ): Promise<DidString | null> {\n const got = await this.getAccount(handleOrDid, flags)\n return got?.did ?? null\n }\n\n async getAccountStatus(\n handleOrDid: AtIdentifierString,\n ): Promise<AccountStatus> {\n const got = await this.getAccount(handleOrDid, {\n includeDeactivated: true,\n includeTakenDown: true,\n })\n\n const res = account.formatAccountStatus(got)\n return res.active ? AccountStatus.Active : res.status\n }\n\n async normalizeAndValidateHandle(\n handle: string,\n {\n did,\n allowAnyValid = false,\n }: {\n did?: string\n allowAnyValid?: boolean\n } = {},\n ): Promise<HandleString> {\n const normalized = baseNormalizeAndValidate(handle)\n\n // tld validation\n if (!isValidTld(normalized)) {\n throw new InvalidRequestError(\n 'Handle TLD is invalid or disallowed',\n 'InvalidHandle',\n )\n }\n // slur check\n if (!allowAnyValid && hasExplicitSlur(normalized)) {\n throw new InvalidRequestError(\n 'Inappropriate language in handle',\n 'InvalidHandle',\n )\n }\n if (isServiceDomain(normalized, this.serviceHandleDomains)) {\n // verify constraints on a service domain\n ensureHandleServiceConstraints(\n normalized,\n this.serviceHandleDomains,\n allowAnyValid,\n )\n } else {\n // When creating an account (no did yet), we require the handle to be a\n // local service domain. Updating to a custom handle will be possible once\n // the account was created.\n if (did == null) {\n throw new InvalidRequestError(\n 'Not a supported handle domain',\n 'UnsupportedDomain',\n )\n }\n\n // verify resolution of a non-service domain\n const resolvedDid = await this.idResolver.handle.resolve(normalized)\n if (resolvedDid !== did) {\n // @TODO This should use a distinct error code\n throw new InvalidRequestError('External handle did not resolve to DID')\n }\n }\n\n return normalized\n }\n\n async createAccount({\n did,\n handle,\n email,\n password,\n repoCid,\n repoRev,\n inviteCode,\n deactivated,\n refreshJwt,\n }: {\n did: DidString\n handle: HandleString\n email?: string\n password?: string\n repoCid: Cid\n repoRev: string\n inviteCode?: string\n deactivated?: boolean\n refreshJwt?: string\n }) {\n if (password && password.length > scrypt.NEW_PASSWORD_MAX_LENGTH) {\n throw new InvalidRequestError('Password too long')\n }\n\n const passwordScrypt =\n email && password ? await scrypt.genSaltAndHash(password) : undefined\n\n const now = currentDatetimeString()\n return this.db.transaction(async (dbTxn) => {\n if (inviteCode) {\n await invite.ensureInviteIsAvailable(dbTxn, inviteCode)\n }\n\n await account.registerActor(dbTxn, { did, handle, deactivated })\n\n if (email && passwordScrypt) {\n await account.registerAccount(dbTxn, { did, email, passwordScrypt })\n }\n\n await invite.recordInviteUse(dbTxn, {\n did,\n inviteCode,\n now,\n })\n\n if (refreshJwt) {\n await auth.storeRefreshToken(\n dbTxn,\n auth.decodeRefreshToken(refreshJwt),\n null,\n )\n }\n\n await repo.updateRoot(dbTxn, did, repoCid, repoRev)\n })\n }\n\n async createAccountAndSession(opts: {\n did: DidString\n handle: HandleString\n email?: string\n password?: string\n repoCid: Cid\n repoRev: string\n inviteCode?: string\n deactivated?: boolean\n }) {\n const { accessJwt, refreshJwt } = await auth.createTokens({\n did: opts.did,\n jwtKey: this.jwtKey,\n serviceDid: this.serviceDid,\n scope: AuthScope.Access,\n })\n\n await this.createAccount({ ...opts, refreshJwt })\n\n return { accessJwt, refreshJwt }\n }\n\n /**\n * Validates the requested handle, updates the PLC document if needed, persists\n * the new handle locally, and emits an identity event.\n *\n * @throws {InvalidRequestError} when the handle is invalid, taken by another\n * account, or cannot be resolved for non-service domains.\n *\n * @see {@link AccountManager.updateAccountHandle} for behavior when the PLC update fails.\n */\n async updateHandle(\n did: DidString,\n newHandle: string,\n options?: { allowAnyValid?: boolean },\n ): Promise<ActorAccount & { handle: HandleString }> {\n const { account, handle } = await this.validateHandleUpdate(\n did,\n newHandle,\n options,\n )\n\n if (did.startsWith('did:plc:')) {\n // @TODO We should verify the status before issuing a PLC update.\n await this.plcClient.updateHandle(did, this.plcRotationKey, handle)\n } else {\n const resolved = await this.idResolver.did.resolveAtprotoData(did, true)\n if (resolved.handle !== handle) {\n throw new InvalidRequestError(\n 'DID is not properly configured for handle',\n )\n }\n }\n\n // @NOTE If the next line fails (for any reason), we don't \"rollback\" the\n // PLC update above. The caller can just call this method again.\n await this.updateAccountHandle(did, handle)\n\n return { ...account, handle }\n }\n\n async validateHandleUpdate(\n did: DidString,\n newHandle: string,\n options?: { allowAnyValid?: boolean },\n ): Promise<{\n did: DidString\n handle: HandleString\n // Returned for convenience\n account: ActorAccount\n }> {\n const account = await this.getAccount(did, { includeDeactivated: true })\n if (!account) {\n throw new InvalidRequestError('Account not found')\n }\n\n const handle = await this.normalizeAndValidateHandle(newHandle, {\n allowAnyValid: options?.allowAnyValid,\n did,\n })\n\n // Pessimistic check to handle spam: also enforced by updateAccountHandle() and the db.\n const existing = await this.getAccount(handle, {\n includeDeactivated: true,\n includeTakenDown: true,\n })\n\n if (existing && existing.did !== did) {\n throw new InvalidRequestError(\n `Handle already taken: ${handle}`,\n 'HandleNotAvailable',\n )\n }\n\n return { did, handle, account }\n }\n\n /**\n * @note Failure to emit the identity event will silently be ignored. Users\n * can emit the event again by updating their handle to the same value.\n */\n async updateAccountHandle(\n did: DidString,\n handle: HandleString,\n ): Promise<void> {\n await account.updateHandle(this.db, did, handle)\n\n try {\n await this.sequencer.sequenceIdentity(did, handle)\n } catch (err) {\n httpLogger.error({ err, did, handle }, 'failed to sequence handle update')\n }\n }\n\n async deleteAccount(did: DidString) {\n return account.deleteAccount(this.db, did)\n }\n\n async takedownAccount(\n did: DidString,\n takedown: com.atproto.admin.defs.StatusAttr,\n ) {\n await this.db.transaction(async (dbTxn) =>\n Promise.all([\n account.updateAccountTakedownStatus(dbTxn, did, takedown),\n auth.revokeRefreshTokensByDid(dbTxn, did),\n token.removeByDidQB(dbTxn, did).execute(),\n ]),\n )\n }\n\n async getAccountAdminStatus(did: DidString) {\n return account.getAccountAdminStatus(this.db, did)\n }\n\n async updateRepoRoot(did: DidString, cid: Cid, rev: string) {\n return repo.updateRoot(this.db, did, cid, rev)\n }\n\n async deactivateAccount(did: DidString, deleteAfter: string | null) {\n return account.deactivateAccount(this.db, did, deleteAfter)\n }\n\n async activateAccount(did: DidString) {\n return account.activateAccount(this.db, did)\n }\n\n // Auth\n // ----------\n\n async createSession(\n did: DidString,\n appPassword: password.AppPassDescript | null,\n isSoftDeleted = false,\n ) {\n const { accessJwt, refreshJwt } = await auth.createTokens({\n did,\n jwtKey: this.jwtKey,\n serviceDid: this.serviceDid,\n scope: auth.formatScope(appPassword, isSoftDeleted),\n })\n // For soft deleted accounts don't store refresh token so that it can't be rotated.\n if (!isSoftDeleted) {\n const refreshPayload = auth.decodeRefreshToken(refreshJwt)\n await auth.storeRefreshToken(this.db, refreshPayload, appPassword)\n }\n return { accessJwt, refreshJwt }\n }\n\n async rotateRefreshToken(id: string) {\n const token = await auth.getRefreshToken(this.db, id)\n if (!token) return null\n\n const now = new Date()\n\n // take the chance to tidy all of a user's expired tokens\n // does not need to be transactional since this is just best-effort\n await auth.deleteExpiredRefreshTokens(this.db, token.did, now.toISOString())\n\n // Shorten the refresh token lifespan down from its\n // original expiration time to its revocation grace period.\n const prevExpiresAt = new Date(token.expiresAt)\n const REFRESH_GRACE_MS = 2 * HOUR\n const graceExpiresAt = new Date(now.getTime() + REFRESH_GRACE_MS)\n\n const expiresAt =\n graceExpiresAt < prevExpiresAt ? graceExpiresAt : prevExpiresAt\n\n if (expiresAt <= now) {\n return null\n }\n\n // Determine the next refresh token id: upon refresh token\n // reuse you always receive a refresh token with the same id.\n const nextId = token.nextId ?? auth.getRefreshTokenId()\n\n const { accessJwt, refreshJwt } = await auth.createTokens({\n did: token.did,\n jwtKey: this.jwtKey,\n serviceDid: this.serviceDid,\n scope: auth.formatScope(token.appPassword),\n jti: nextId,\n })\n\n const refreshPayload = auth.decodeRefreshToken(refreshJwt)\n try {\n await this.db.transaction((dbTxn) =>\n Promise.all([\n auth.addRefreshGracePeriod(dbTxn, {\n id,\n expiresAt: expiresAt.toISOString(),\n nextId,\n }),\n auth.storeRefreshToken(dbTxn, refreshPayload, token.appPassword),\n ]),\n )\n } catch (err) {\n if (err instanceof auth.ConcurrentRefreshError) {\n return this.rotateRefreshToken(id)\n }\n throw err\n }\n return { accessJwt, refreshJwt }\n }\n\n async revokeRefreshToken(id: string) {\n return auth.revokeRefreshToken(this.db, id)\n }\n\n // Login\n // ----------\n\n async login({\n identifier,\n password,\n }: {\n identifier: string\n password: string\n }): Promise<{\n user: ActorAccount\n appPassword: password.AppPassDescript | null\n isSoftDeleted: boolean\n }> {\n const start = Date.now()\n try {\n const identifierNormalized = identifier.toLowerCase()\n\n const user = identifierNormalized.includes('@')\n ? await this.getAccountByEmail(identifierNormalized, {\n includeDeactivated: true,\n includeTakenDown: true,\n })\n : isAtIdentifierString(identifierNormalized)\n ? await this.getAccount(identifierNormalized, {\n includeDeactivated: true,\n includeTakenDown: true,\n })\n : null\n\n if (!user) {\n throw new AuthRequiredError('Invalid identifier or password')\n }\n const isSoftDeleted = softDeleted(user)\n\n let appPassword: password.AppPassDescript | null = null\n const validAccountPass = await this.verifyAccountPassword(\n user.did,\n password,\n )\n if (!validAccountPass) {\n // takendown/suspended accounts cannot login with app password\n if (isSoftDeleted) {\n throw new InvalidPasswordError(user.did)\n }\n appPassword = await this.verifyAppPassword(user.did, password)\n if (appPassword === null) {\n throw new InvalidPasswordError(user.did)\n }\n }\n\n return { user, appPassword, isSoftDeleted }\n } finally {\n // Mitigate timing attacks\n await wait(350 - (Date.now() - start))\n }\n }\n\n // Passwords\n // ----------\n\n async createAppPassword(did: DidString, name: string, privileged: boolean) {\n return password.createAppPassword(this.db, did, name, privileged)\n }\n\n async listAppPasswords(did: DidString) {\n return password.listAppPasswords(this.db, did)\n }\n\n async verifyAccountPassword(\n did: DidString,\n passwordStr: string,\n ): Promise<boolean> {\n return password.verifyAccountPassword(this.db, did, passwordStr)\n }\n\n async verifyAppPassword(\n did: DidString,\n passwordStr: string,\n ): Promise<password.AppPassDescript | null> {\n return password.verifyAppPassword(this.db, did, passwordStr)\n }\n\n async revokeAppPassword(did: DidString, name: string) {\n await this.db.transaction(async (dbTxn) =>\n Promise.all([\n password.deleteAppPassword(dbTxn, did, name),\n auth.revokeAppPasswordRefreshToken(dbTxn, did, name),\n ]),\n )\n }\n\n // Invites\n // ----------\n\n async ensureInviteIsAvailable(code: string) {\n return invite.ensureInviteIsAvailable(this.db, code)\n }\n\n async createInviteCodes(\n toCreate: { account: string; codes: string[] }[],\n useCount: number,\n ) {\n return invite.createInviteCodes(this.db, toCreate, useCount)\n }\n\n async createAccountInviteCodes(\n forAccount: string,\n codes: string[],\n expectedTotal: number,\n disabled: 0 | 1,\n ) {\n return invite.createAccountInviteCodes(\n this.db,\n forAccount,\n codes,\n expectedTotal,\n disabled,\n )\n }\n\n async getAccountInvitesCodes(did: DidString) {\n const inviteCodes = await invite.getAccountsInviteCodes(this.db, [did])\n return inviteCodes.get(did) ?? []\n }\n\n async getAccountsInvitesCodes(dids: DidString[]) {\n return invite.getAccountsInviteCodes(this.db, dids)\n }\n\n async getInvitedByForAccounts(dids: DidString[]) {\n return invite.getInvitedByForAccounts(this.db, dids)\n }\n\n async getInviteCodesUses(codes: string[]) {\n return invite.getInviteCodesUses(this.db, codes)\n }\n\n async setAccountInvitesDisabled(did: DidString, disabled: boolean) {\n return invite.setAccountInvitesDisabled(this.db, did, disabled)\n }\n\n async disableInviteCodes(opts: { codes: string[]; accounts: string[] }) {\n return invite.disableInviteCodes(this.db, opts)\n }\n\n // Email Tokens\n // ----------\n\n async createEmailToken(did: DidString, purpose: EmailTokenPurpose) {\n return emailToken.createEmailToken(this.db, did, purpose)\n }\n\n async assertValidEmailToken(\n did: DidString,\n purpose: EmailTokenPurpose,\n token: string,\n ) {\n return emailToken.assertValidToken(this.db, did, purpose, token)\n }\n\n async assertValidEmailTokenAndCleanup(\n did: DidString,\n purpose: EmailTokenPurpose,\n token: string,\n ) {\n await emailToken.assertValidToken(this.db, did, purpose, token)\n await emailToken.deleteEmailToken(this.db, did, purpose)\n }\n\n async requestEmailConfirmation(did: DidString, opts?: { locale?: string }) {\n const account = await this.getAccount(did, {\n includeDeactivated: true,\n includeTakenDown: true,\n })\n\n if (!account) {\n throw new InvalidRequestError('account not found')\n }\n\n if (!account.email) {\n throw new InvalidRequestError('account does not have an email address')\n }\n\n const locale = opts?.locale\n const token = await this.createEmailToken(did, 'confirm_email')\n\n await this.mailer.sendConfirmEmail({ token, locale }, { to: account.email })\n }\n\n async confirmEmail(did: DidString, email: string, token: string) {\n const user = await this.getAccount(did, {\n includeDeactivated: true,\n includeTakenDown: true,\n })\n\n if (!user) {\n throw new InvalidRequestError('user not found', 'AccountNotFound')\n }\n\n if (user.email !== email.toLowerCase()) {\n throw new InvalidRequestError('invalid email', 'InvalidEmail')\n }\n\n await emailToken.assertValidToken(this.db, did, 'confirm_email', token)\n const now = currentDatetimeString()\n await this.db.transaction(async (dbTxn) => {\n await emailToken.deleteEmailToken(dbTxn, did, 'confirm_email')\n await account.setEmailConfirmedAt(dbTxn, did, now)\n })\n\n user.emailConfirmedAt = now\n\n return user\n }\n\n async requestEmailUpdate(\n did: DidString,\n opts?: { locale?: string },\n ): Promise<{ tokenRequired: boolean }> {\n const account = await this.getAccount(did, {\n includeDeactivated: true,\n includeTakenDown: true,\n })\n\n if (!account) {\n throw new InvalidRequestError('account not found')\n }\n\n if (!account.email) {\n throw new InvalidRequestError('account does not have an email address')\n }\n\n const token = account.emailConfirmedAt\n ? await this.createEmailToken(did, 'update_email')\n : null\n\n if (token) {\n await this.mailer.sendUpdateEmail(\n { token, locale: opts?.locale },\n { to: account.email },\n )\n }\n\n return { tokenRequired: !!token }\n }\n\n /**\n * @throws UserAlreadyExistsError if the new email is already in use by another account\n */\n async updateEmail(\n did: DidString,\n email: string,\n token?: string,\n opts?: { locale?: string; sendConfirmationEmail?: boolean },\n ): Promise<ActorAccount> {\n if (!isEmailValid(email) || isDisposableEmail(email)) {\n throw new InvalidRequestError(\n 'This email address is not supported, please use a different email.',\n )\n }\n\n const account = await this.getAccount(did, {\n includeDeactivated: true,\n includeTakenDown: true,\n })\n\n if (!account) {\n throw new InvalidRequestError('account not found')\n }\n\n const tokenRequired = !!account.emailConfirmedAt\n\n // require a token if account email is confirmed\n if (!token && tokenRequired) {\n throw new InvalidRequestError(\n 'confirmation token required',\n 'TokenRequired',\n )\n }\n\n if (token) {\n await this.assertValidEmailToken(did, 'update_email', token)\n }\n\n await this.updateAccountEmail({ did, email })\n\n account.email = email\n account.emailConfirmedAt = null\n\n // Proactively send a confirmation email so that the user can confirm the\n // new email immediately.\n if (opts?.sendConfirmationEmail) {\n const token = await this.createEmailToken(did, 'confirm_email')\n const locale = opts.locale\n await this.mailer.sendConfirmEmail({ token, locale }, { to: email })\n }\n\n return account\n }\n\n async updateAccountEmail(opts: { did: DidString; email: string }) {\n const { did, email } = opts\n await this.db.transaction(async (dbTxn) => {\n await account.updateEmail(dbTxn, did, email)\n await emailToken.deleteAllEmailTokens(dbTxn, did)\n })\n }\n\n async resetPassword(opts: { password: string; token: string }) {\n const did = await emailToken.assertValidTokenAndFindDid(\n this.db,\n 'reset_password',\n opts.token,\n )\n await this.updateAccountPassword({ did, password: opts.password })\n\n return did\n }\n\n async updateAccountPassword(opts: { did: DidString; password: string }) {\n const { did } = opts\n const passwordScrypt = await scrypt.genSaltAndHash(opts.password)\n await this.db.transaction(async (dbTxn) =>\n Promise.all([\n password.updateUserPassword(dbTxn, { did, passwordScrypt }),\n emailToken.deleteEmailToken(dbTxn, did, 'reset_password'),\n auth.revokeRefreshTokensByDid(dbTxn, did),\n ]),\n )\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"account-manager.js","sourceRoot":"","sources":["../../src/account-manager/account-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from 'node:assert'\nimport { KeyObject } from 'node:crypto'\nimport { Client as PlcClient } from '@did-plc/lib'\nimport { isEmailValid } from '@hapi/address'\nimport { isDisposableEmail } from 'disposable-email-domains-js'\nimport { HOUR, wait } from '@atproto/common'\nimport { Keypair } from '@atproto/crypto'\nimport { IdResolver } from '@atproto/identity'\nimport {\n AtIdentifierString,\n DidString,\n HandleString,\n isAtIdentifierString,\n} from '@atproto/lex'\nimport { Cid } from '@atproto/lex-data'\nimport {\n INVALID_HANDLE,\n currentDatetimeString,\n isValidTld,\n} from '@atproto/syntax'\nimport { AuthRequiredError, InvalidRequestError } from '@atproto/xrpc-server'\nimport { ActorStore } from '../actor-store/actor-store.js'\nimport { assertValidDidDocumentForService } from '../api/com/atproto/server/util.js'\nimport { AuthScope } from '../auth-scope.js'\nimport { ServerConfig } from '../config/config.js'\nimport { softDeleted } from '../db/index.js'\nimport { hasExplicitSlur } from '../handle/explicit-slurs.js'\nimport {\n baseNormalizeAndValidate,\n ensureHandleServiceConstraints,\n isServiceDomain,\n} from '../handle/index.js'\nimport { com } from '../lexicons/index.js'\nimport { httpLogger } from '../logger.js'\nimport { ServerMailer } from '../mailer/index.js'\nimport { Sequencer } from '../sequencer/index.js'\nimport { AccountDb, EmailTokenPurpose, getDb, getMigrator } from './db/index.js'\nimport * as accountHelpers from './helpers/account.js'\nimport { AccountStatus, ActorAccount } from './helpers/account.js'\nimport * as auth from './helpers/auth.js'\nimport * as authorizedClientHelper from './helpers/authorized-client.js'\nimport * as emailToken from './helpers/email-token.js'\nimport * as invite from './helpers/invite.js'\nimport * as password from './helpers/password.js'\nimport * as repo from './helpers/repo.js'\nimport * as scrypt from './helpers/scrypt.js'\nimport * as token from './helpers/token.js'\n\nexport { AccountStatus, formatAccountStatus } from './helpers/account.js'\n\n/**\n * Thrown by {@link AccountManager.login} when the identifier resolved to a\n * known account but the supplied credentials (account password / app\n * password) did not match. The matched `did` is attached so downstream\n * callers can distinguish \"identifier known, credentials wrong\" from\n * \"identifier unknown\" (which continues to throw a plain\n * {@link AuthRequiredError}).\n *\n * Callers should take care that remote clients *cannot* distinguish the above,\n * to prevent enumeration attacks. (Tested for in\n * packages/pds/tests/auth.test.ts)\n */\nexport class InvalidPasswordError extends AuthRequiredError {\n constructor(\n public readonly did: DidString,\n errorMessage = 'Invalid identifier or password',\n ) {\n super(errorMessage)\n }\n}\n\nexport type AccountManagerDbConfig = {\n accountDbLoc: string\n disableWalAutoCheckpoint: boolean\n}\n\nexport class AccountManager {\n readonly db: AccountDb\n\n constructor(\n readonly cfg: ServerConfig,\n readonly actorStore: ActorStore,\n readonly idResolver: IdResolver,\n readonly jwtKey: KeyObject,\n readonly mailer: ServerMailer,\n readonly sequencer: Sequencer,\n readonly plcClient: PlcClient,\n readonly plcRotationKey: Keypair,\n ) {\n this.db = getDb(cfg.db.accountDbLoc, cfg.db.disableWalAutoCheckpoint)\n }\n\n get serviceDid(): DidString {\n return this.cfg.service.did\n }\n\n get serviceHandleDomains(): string[] {\n return this.cfg.identity.serviceHandleDomains\n }\n\n async migrateOrThrow() {\n await this.db.ensureWal()\n await getMigrator(this.db).migrateToLatestOrThrow()\n }\n\n close() {\n this.db.close()\n }\n\n // Account\n // ----------\n\n async getAccount(\n handleOrDid: AtIdentifierString,\n flags?: accountHelpers.AvailabilityFlags,\n ): Promise<ActorAccount | null> {\n return accountHelpers.getAccount(this.db, handleOrDid, flags)\n }\n\n async getAccounts(\n dids: DidString[],\n flags?: accountHelpers.AvailabilityFlags,\n ): Promise<Map<string, ActorAccount>> {\n return accountHelpers.getAccounts(this.db, dids, flags)\n }\n\n async getAccountByEmail(\n email: string,\n flags?: accountHelpers.AvailabilityFlags,\n ): Promise<ActorAccount | null> {\n return accountHelpers.getAccountByEmail(this.db, email, flags)\n }\n\n async isAccountActivated(did: DidString): Promise<boolean> {\n const account = await this.getAccount(did, { includeDeactivated: true })\n if (!account) return false\n return !account.deactivatedAt\n }\n\n async getDidForActor(\n handleOrDid: AtIdentifierString,\n flags?: accountHelpers.AvailabilityFlags,\n ): Promise<DidString | null> {\n const got = await this.getAccount(handleOrDid, flags)\n return got?.did ?? null\n }\n\n async getAccountStatus(handleOrDid: AtIdentifierString) {\n const got = await this.getAccount(handleOrDid, {\n includeDeactivated: true,\n includeTakenDown: true,\n })\n\n const { active, status = active ? AccountStatus.Active : undefined } =\n accountHelpers.formatAccountStatus(got)\n assert(status != null)\n return { status, account: got } as\n | { status: AccountStatus.Deleted; account: null }\n | { status: AccountStatus.Takendown; account: ActorAccount }\n | { status: AccountStatus.Deactivated; account: ActorAccount }\n | { status: AccountStatus.Active; account: ActorAccount }\n }\n\n async normalizeAndValidateHandle(\n handle: string,\n {\n did,\n allowAnyValid = false,\n }: {\n did?: string\n allowAnyValid?: boolean\n } = {},\n ): Promise<HandleString> {\n const normalized = baseNormalizeAndValidate(handle)\n\n // tld validation\n if (!isValidTld(normalized)) {\n throw new InvalidRequestError(\n 'Handle TLD is invalid or disallowed',\n 'InvalidHandle',\n )\n }\n // slur check\n if (!allowAnyValid && hasExplicitSlur(normalized)) {\n throw new InvalidRequestError(\n 'Inappropriate language in handle',\n 'InvalidHandle',\n )\n }\n if (isServiceDomain(normalized, this.serviceHandleDomains)) {\n // verify constraints on a service domain\n ensureHandleServiceConstraints(\n normalized,\n this.serviceHandleDomains,\n allowAnyValid,\n )\n } else {\n // When creating an account (no did yet), we require the handle to be a\n // local service domain. Updating to a custom handle will be possible once\n // the account was created.\n if (did == null) {\n throw new InvalidRequestError(\n 'Not a supported handle domain',\n 'UnsupportedDomain',\n )\n }\n\n // verify resolution of a non-service domain\n const resolvedDid = await this.idResolver.handle.resolve(normalized)\n if (resolvedDid !== did) {\n // @TODO This should use a distinct error code\n throw new InvalidRequestError('External handle did not resolve to DID')\n }\n }\n\n return normalized\n }\n\n async createAccount({\n did,\n handle,\n email,\n password,\n repoCid,\n repoRev,\n inviteCode,\n deactivated,\n refreshJwt,\n }: {\n did: DidString\n handle: HandleString\n email?: string\n password?: string\n repoCid: Cid\n repoRev: string\n inviteCode?: string\n deactivated?: boolean\n refreshJwt?: string\n }) {\n if (password && password.length > scrypt.NEW_PASSWORD_MAX_LENGTH) {\n throw new InvalidRequestError('Password too long')\n }\n\n const passwordScrypt =\n email && password ? await scrypt.genSaltAndHash(password) : undefined\n\n const now = currentDatetimeString()\n return this.db.transaction(async (dbTxn) => {\n if (inviteCode) {\n await invite.ensureInviteIsAvailable(dbTxn, inviteCode)\n }\n\n await accountHelpers.registerActor(dbTxn, { did, handle, deactivated })\n\n if (email && passwordScrypt) {\n await accountHelpers.registerAccount(dbTxn, {\n did,\n email,\n passwordScrypt,\n })\n }\n\n await invite.recordInviteUse(dbTxn, {\n did,\n inviteCode,\n now,\n })\n\n if (refreshJwt) {\n await auth.storeRefreshToken(\n dbTxn,\n auth.decodeRefreshToken(refreshJwt),\n null,\n )\n }\n\n await repo.updateRoot(dbTxn, did, repoCid, repoRev)\n })\n }\n\n async createAccountAndSession(opts: {\n did: DidString\n handle: HandleString\n email?: string\n password?: string\n repoCid: Cid\n repoRev: string\n inviteCode?: string\n deactivated?: boolean\n }) {\n const { accessJwt, refreshJwt } = await auth.createTokens({\n did: opts.did,\n jwtKey: this.jwtKey,\n serviceDid: this.serviceDid,\n scope: AuthScope.Access,\n })\n\n await this.createAccount({ ...opts, refreshJwt })\n\n return { accessJwt, refreshJwt }\n }\n\n /**\n * Validates the requested handle, updates the PLC document if needed, persists\n * the new handle locally, and emits an identity event.\n *\n * @throws {InvalidRequestError} when the handle is invalid, taken by another\n * account, or cannot be resolved for non-service domains.\n *\n * @see {@link AccountManager.updateAccountHandle} for behavior when the PLC update fails.\n */\n async updateHandle(\n did: DidString,\n newHandle: string,\n options?: { allowAnyValid?: boolean },\n ): Promise<ActorAccount & { handle: HandleString }> {\n const { account, handle } = await this.validateHandleUpdate(\n did,\n newHandle,\n options,\n )\n\n if (did.startsWith('did:plc:')) {\n // @TODO We should verify the status before issuing a PLC update.\n await this.plcClient.updateHandle(did, this.plcRotationKey, handle)\n } else {\n const resolved = await this.idResolver.did.resolveAtprotoData(did, true)\n if (resolved.handle !== handle) {\n throw new InvalidRequestError(\n 'DID is not properly configured for handle',\n )\n }\n }\n\n // @NOTE If the next line fails (for any reason), we don't \"rollback\" the\n // PLC update above. The caller can just call this method again.\n await this.updateAccountHandle(did, handle)\n\n return { ...account, handle }\n }\n\n async validateHandleUpdate(\n did: DidString,\n newHandle: string,\n options?: { allowAnyValid?: boolean },\n ): Promise<{\n did: DidString\n handle: HandleString\n // Returned for convenience\n account: ActorAccount\n }> {\n const account = await this.getAccount(did, { includeDeactivated: true })\n if (!account) {\n throw new InvalidRequestError('Account not found')\n }\n\n const handle = await this.normalizeAndValidateHandle(newHandle, {\n allowAnyValid: options?.allowAnyValid,\n did,\n })\n\n // Pessimistic check to handle spam: also enforced by updateAccountHandle() and the db.\n const existing = await this.getAccount(handle, {\n includeDeactivated: true,\n includeTakenDown: true,\n })\n\n if (existing && existing.did !== did) {\n throw new InvalidRequestError(\n `Handle already taken: ${handle}`,\n 'HandleNotAvailable',\n )\n }\n\n return { did, handle, account }\n }\n\n /**\n * @note Failure to emit the identity event will silently be ignored. Users\n * can emit the event again by updating their handle to the same value.\n */\n async updateAccountHandle(\n did: DidString,\n handle: HandleString,\n ): Promise<void> {\n await accountHelpers.updateHandle(this.db, did, handle)\n\n try {\n await this.sequencer.sequenceIdentity(did, handle)\n } catch (err) {\n httpLogger.error({ err, did, handle }, 'failed to sequence handle update')\n }\n }\n\n async deleteAccount(did: DidString) {\n return accountHelpers.deleteAccount(this.db, did)\n }\n\n async takedownAccount(\n did: DidString,\n takedown: com.atproto.admin.defs.StatusAttr,\n ) {\n await this.db.transaction(async (dbTxn) => {\n await accountHelpers.updateAccountTakedownStatus(dbTxn, did, takedown)\n await auth.revokeRefreshTokensByDid(dbTxn, did)\n await token.removeByDid(dbTxn, did)\n })\n\n await this.sequenceAccountStatus(did)\n }\n\n async getAccountAdminStatus(did: DidString) {\n return accountHelpers.getAccountAdminStatus(this.db, did)\n }\n\n async updateRepoRoot(did: DidString, cid: Cid, rev: string) {\n return repo.updateRoot(this.db, did, cid, rev)\n }\n\n async deactivateAccount(\n did: DidString,\n options?: {\n deleteCredentials?: boolean\n deleteAfter?: string | null\n },\n ) {\n const wasUpdated = await this.db.transaction(async (dbTxn) => {\n if (options?.deleteCredentials) {\n await token.removeByDid(dbTxn, did)\n await authorizedClientHelper.deleteAllAuthorizedClients(dbTxn, did)\n await password.deleteAllAppPasswords(dbTxn, did)\n }\n\n return accountHelpers.deactivateAccount(\n dbTxn,\n did,\n options?.deleteAfter ?? null,\n )\n })\n\n if (!wasUpdated) {\n throw new InvalidRequestError('Account not found')\n }\n\n const accountStatus = await this.getAccountStatus(did)\n\n // Account is likely soft-deleted (takendown)\n if (accountStatus.status === AccountStatus.Deleted) {\n throw new InvalidRequestError('Account not found')\n }\n\n await this.sequencer.sequenceAccount(did, accountStatus.status)\n\n return accountStatus\n }\n\n async activateAccount(did: DidString) {\n await assertValidDidDocumentForService(this, did)\n\n const found = await accountHelpers.activateAccount(this.db, did, {\n // We cannot activate a takendown account\n includeTakenDown: false,\n includeDeactivated: true,\n })\n if (!found) {\n throw new InvalidRequestError('user not found', 'AccountNotFound')\n }\n\n const accountStatus = await this.getAccountStatus(did)\n\n const { account, status } = accountStatus\n\n if (status === AccountStatus.Deleted) {\n // A concurrent operation deleted the account\n throw new InvalidRequestError('user not found', 'AccountNotFound')\n }\n\n const syncData = await this.actorStore.read(did, (store) => {\n return store.repo.getSyncEventData()\n })\n\n await this.sequencer.sequenceAccountActivation(\n did,\n account.handle ?? INVALID_HANDLE,\n status,\n syncData,\n )\n\n return accountStatus\n }\n\n async sequenceAccountStatus(did: DidString) {\n const { status } = await this.getAccountStatus(did)\n await this.sequencer.sequenceAccount(did, status)\n }\n\n // Auth\n // ----------\n\n async createSession(\n did: DidString,\n appPassword: password.AppPassDescript | null,\n isSoftDeleted = false,\n ) {\n const { accessJwt, refreshJwt } = await auth.createTokens({\n did,\n jwtKey: this.jwtKey,\n serviceDid: this.serviceDid,\n scope: auth.formatScope(appPassword, isSoftDeleted),\n })\n // For soft deleted accounts don't store refresh token so that it can't be rotated.\n if (!isSoftDeleted) {\n const refreshPayload = auth.decodeRefreshToken(refreshJwt)\n await auth.storeRefreshToken(this.db, refreshPayload, appPassword)\n }\n return { accessJwt, refreshJwt }\n }\n\n async rotateRefreshToken(id: string) {\n const token = await auth.getRefreshToken(this.db, id)\n if (!token) return null\n\n const now = new Date()\n\n // take the chance to tidy all of a user's expired tokens\n // does not need to be transactional since this is just best-effort\n await auth.deleteExpiredRefreshTokens(this.db, token.did, now.toISOString())\n\n // Shorten the refresh token lifespan down from its\n // original expiration time to its revocation grace period.\n const prevExpiresAt = new Date(token.expiresAt)\n const REFRESH_GRACE_MS = 2 * HOUR\n const graceExpiresAt = new Date(now.getTime() + REFRESH_GRACE_MS)\n\n const expiresAt =\n graceExpiresAt < prevExpiresAt ? graceExpiresAt : prevExpiresAt\n\n if (expiresAt <= now) {\n return null\n }\n\n // Determine the next refresh token id: upon refresh token\n // reuse you always receive a refresh token with the same id.\n const nextId = token.nextId ?? auth.getRefreshTokenId()\n\n const { accessJwt, refreshJwt } = await auth.createTokens({\n did: token.did,\n jwtKey: this.jwtKey,\n serviceDid: this.serviceDid,\n scope: auth.formatScope(token.appPassword),\n jti: nextId,\n })\n\n const refreshPayload = auth.decodeRefreshToken(refreshJwt)\n try {\n await this.db.transaction((dbTxn) =>\n Promise.all([\n auth.addRefreshGracePeriod(dbTxn, {\n id,\n expiresAt: expiresAt.toISOString(),\n nextId,\n }),\n auth.storeRefreshToken(dbTxn, refreshPayload, token.appPassword),\n ]),\n )\n } catch (err) {\n if (err instanceof auth.ConcurrentRefreshError) {\n return this.rotateRefreshToken(id)\n }\n throw err\n }\n return { accessJwt, refreshJwt }\n }\n\n async revokeRefreshToken(id: string) {\n return auth.revokeRefreshToken(this.db, id)\n }\n\n // Login\n // ----------\n\n async login({\n identifier,\n password,\n }: {\n identifier: string\n password: string\n }): Promise<{\n user: ActorAccount\n appPassword: password.AppPassDescript | null\n isSoftDeleted: boolean\n }> {\n const start = Date.now()\n try {\n const identifierNormalized = identifier.toLowerCase()\n\n const user = identifierNormalized.includes('@')\n ? await this.getAccountByEmail(identifierNormalized, {\n includeDeactivated: true,\n includeTakenDown: true,\n })\n : isAtIdentifierString(identifierNormalized)\n ? await this.getAccount(identifierNormalized, {\n includeDeactivated: true,\n includeTakenDown: true,\n })\n : null\n\n if (!user) {\n throw new AuthRequiredError('Invalid identifier or password')\n }\n const isSoftDeleted = softDeleted(user)\n\n let appPassword: password.AppPassDescript | null = null\n const validAccountPass = await this.verifyAccountPassword(\n user.did,\n password,\n )\n if (!validAccountPass) {\n // takendown/suspended accounts cannot login with app password\n if (isSoftDeleted) {\n throw new InvalidPasswordError(user.did)\n }\n appPassword = await this.verifyAppPassword(user.did, password)\n if (appPassword === null) {\n throw new InvalidPasswordError(user.did)\n }\n }\n\n return { user, appPassword, isSoftDeleted }\n } finally {\n // Mitigate timing attacks\n await wait(350 - (Date.now() - start))\n }\n }\n\n // Passwords\n // ----------\n\n async createAppPassword(did: DidString, name: string, privileged: boolean) {\n return password.createAppPassword(this.db, did, name, privileged)\n }\n\n async listAppPasswords(did: DidString) {\n return password.listAppPasswords(this.db, did)\n }\n\n async verifyAccountPassword(\n did: DidString,\n passwordStr: string,\n ): Promise<boolean> {\n if (passwordStr.length > scrypt.OLD_PASSWORD_MAX_LENGTH) {\n // @NOTE Avoid throwing from here to avoid leaking account email validity\n // through error messages.\n return false\n }\n\n return password.verifyAccountPassword(this.db, did, passwordStr)\n }\n\n async verifyAppPassword(\n did: DidString,\n passwordStr: string,\n ): Promise<password.AppPassDescript | null> {\n return password.verifyAppPassword(this.db, did, passwordStr)\n }\n\n async revokeAppPassword(did: DidString, name: string) {\n await this.db.transaction(async (dbTxn) =>\n Promise.all([\n password.deleteAppPassword(dbTxn, did, name),\n auth.revokeAppPasswordRefreshToken(dbTxn, did, name),\n ]),\n )\n }\n\n // Invites\n // ----------\n\n async ensureInviteIsAvailable(code: string) {\n return invite.ensureInviteIsAvailable(this.db, code)\n }\n\n async createInviteCodes(\n toCreate: { account: string; codes: string[] }[],\n useCount: number,\n ) {\n return invite.createInviteCodes(this.db, toCreate, useCount)\n }\n\n async createAccountInviteCodes(\n forAccount: string,\n codes: string[],\n expectedTotal: number,\n disabled: 0 | 1,\n ) {\n return invite.createAccountInviteCodes(\n this.db,\n forAccount,\n codes,\n expectedTotal,\n disabled,\n )\n }\n\n async getAccountInvitesCodes(did: DidString) {\n const inviteCodes = await invite.getAccountsInviteCodes(this.db, [did])\n return inviteCodes.get(did) ?? []\n }\n\n async getAccountsInvitesCodes(dids: DidString[]) {\n return invite.getAccountsInviteCodes(this.db, dids)\n }\n\n async getInvitedByForAccounts(dids: DidString[]) {\n return invite.getInvitedByForAccounts(this.db, dids)\n }\n\n async getInviteCodesUses(codes: string[]) {\n return invite.getInviteCodesUses(this.db, codes)\n }\n\n async setAccountInvitesDisabled(did: DidString, disabled: boolean) {\n return invite.setAccountInvitesDisabled(this.db, did, disabled)\n }\n\n async disableInviteCodes(opts: { codes: string[]; accounts: string[] }) {\n return invite.disableInviteCodes(this.db, opts)\n }\n\n // Email Tokens\n // ----------\n\n async createEmailToken(did: DidString, purpose: EmailTokenPurpose) {\n return emailToken.createEmailToken(this.db, did, purpose)\n }\n\n async assertValidEmailToken(\n did: DidString,\n purpose: EmailTokenPurpose,\n token: string,\n ) {\n return emailToken.assertValidToken(this.db, did, purpose, token)\n }\n\n async assertValidEmailTokenAndCleanup(\n did: DidString,\n purpose: EmailTokenPurpose,\n token: string,\n ) {\n await emailToken.assertValidToken(this.db, did, purpose, token)\n await emailToken.deleteEmailToken(this.db, did, purpose)\n }\n\n async requestEmailConfirmation(did: DidString, opts?: { locale?: string }) {\n const account = await this.getAccount(did, {\n includeDeactivated: true,\n includeTakenDown: true,\n })\n\n if (!account) {\n throw new InvalidRequestError('account not found')\n }\n\n if (!account.email) {\n throw new InvalidRequestError('account does not have an email address')\n }\n\n const locale = opts?.locale\n const token = await this.createEmailToken(did, 'confirm_email')\n\n await this.mailer.sendConfirmEmail({ token, locale }, { to: account.email })\n }\n\n async confirmEmail(did: DidString, email: string, token: string) {\n const user = await this.getAccount(did, {\n includeDeactivated: true,\n includeTakenDown: true,\n })\n\n if (!user) {\n throw new InvalidRequestError('user not found', 'AccountNotFound')\n }\n\n if (user.email !== email.toLowerCase()) {\n throw new InvalidRequestError('invalid email', 'InvalidEmail')\n }\n\n await emailToken.assertValidToken(this.db, did, 'confirm_email', token)\n const now = currentDatetimeString()\n await this.db.transaction(async (dbTxn) => {\n await emailToken.deleteEmailToken(dbTxn, did, 'confirm_email')\n await accountHelpers.setEmailConfirmedAt(dbTxn, did, now)\n })\n\n user.emailConfirmedAt = now\n\n return user\n }\n\n async requestEmailUpdate(\n did: DidString,\n opts?: { locale?: string },\n ): Promise<{ tokenRequired: boolean }> {\n const account = await this.getAccount(did, {\n includeDeactivated: true,\n includeTakenDown: true,\n })\n\n if (!account) {\n throw new InvalidRequestError('account not found')\n }\n\n if (!account.email) {\n throw new InvalidRequestError('account does not have an email address')\n }\n\n const token = account.emailConfirmedAt\n ? await this.createEmailToken(did, 'update_email')\n : null\n\n if (token) {\n await this.mailer.sendUpdateEmail(\n { token, locale: opts?.locale },\n { to: account.email },\n )\n }\n\n return { tokenRequired: !!token }\n }\n\n /**\n * @throws UserAlreadyExistsError if the new email is already in use by another account\n */\n async updateEmail(\n did: DidString,\n email: string,\n token?: string,\n opts?: { locale?: string; sendConfirmationEmail?: boolean },\n ): Promise<ActorAccount> {\n if (!isEmailValid(email) || isDisposableEmail(email)) {\n throw new InvalidRequestError(\n 'This email address is not supported, please use a different email.',\n )\n }\n\n const account = await this.getAccount(did, {\n includeDeactivated: true,\n includeTakenDown: true,\n })\n\n if (!account) {\n throw new InvalidRequestError('account not found')\n }\n\n const tokenRequired = !!account.emailConfirmedAt\n\n // require a token if account email is confirmed\n if (!token && tokenRequired) {\n throw new InvalidRequestError(\n 'confirmation token required',\n 'TokenRequired',\n )\n }\n\n if (token) {\n await this.assertValidEmailToken(did, 'update_email', token)\n }\n\n await this.updateAccountEmail({ did, email })\n\n account.email = email\n account.emailConfirmedAt = null\n\n // Proactively send a confirmation email so that the user can confirm the\n // new email immediately.\n if (opts?.sendConfirmationEmail) {\n const token = await this.createEmailToken(did, 'confirm_email')\n const locale = opts.locale\n await this.mailer.sendConfirmEmail({ token, locale }, { to: email })\n }\n\n return account\n }\n\n async updateAccountEmail(opts: { did: DidString; email: string }) {\n const { did, email } = opts\n await this.db.transaction(async (dbTxn) => {\n await accountHelpers.updateEmail(dbTxn, did, email)\n await emailToken.deleteAllEmailTokens(dbTxn, did)\n })\n }\n\n async resetPassword(opts: { password: string; token: string }) {\n const did = await emailToken.assertValidTokenAndFindDid(\n this.db,\n 'reset_password',\n opts.token,\n )\n await this.updateAccountPassword({ did, password: opts.password })\n\n return did\n }\n\n async updateAccountPassword(opts: { did: DidString; password: string }) {\n const { did } = opts\n const passwordScrypt = await scrypt.genSaltAndHash(opts.password)\n await this.db.transaction(async (dbTxn) =>\n Promise.all([\n password.updateUserPassword(dbTxn, { did, passwordScrypt }),\n emailToken.deleteEmailToken(dbTxn, did, 'reset_password'),\n auth.revokeRefreshTokensByDid(dbTxn, did),\n ]),\n )\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"005-oauth-account-management.d.ts","sourceRoot":"","sources":["../../../../src/account-manager/db/migrations/005-oauth-account-management.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/B,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAC5D,OAAO,EAAE,OAAO,EAAE,WAAW,EAAa,MAAM,sBAAsB,CAAA;AAUtE,wBAAsB,EAAE,CACtB,EAAE,EAAE,MAAM,CAAC;IACT,OAAO,EAAE;QACP,GAAG,EAAE,MAAM,CAAA;KACZ,CAAA;IACD,cAAc,EAAE;QACd,GAAG,EAAE,MAAM,CAAA;QACX,QAAQ,EAAE,QAAQ,CAAA;QAElB,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAA;QACf,eAAe,EAAE,MAAM,CAAA;QACvB,iBAAiB,EAAE,WAAW,CAAC,QAAQ,EAAE,CAAC,CAAA;KAC3C,CAAA;IACD,cAAc,EAAE;QACd,GAAG,EAAE,MAAM,CAAA;QACX,QAAQ,EAAE,QAAQ,CAAA;QAElB,SAAS,EAAE,OAAO,CAAA;QAClB,SAAS,EAAE,OAAO,CAAA;KACnB,CAAA;CACF,CAAC,GACD,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"005-oauth-account-management.d.ts","sourceRoot":"","sources":["../../../../src/account-manager/db/migrations/005-oauth-account-management.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/B,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAC5D,OAAO,EAAE,OAAO,EAAE,WAAW,EAAa,MAAM,sBAAsB,CAAA;AAUtE,wBAAsB,EAAE,CACtB,EAAE,EAAE,MAAM,CAAC;IACT,OAAO,EAAE;QACP,GAAG,EAAE,MAAM,CAAA;KACZ,CAAA;IACD,cAAc,EAAE;QACd,GAAG,EAAE,MAAM,CAAA;QACX,QAAQ,EAAE,QAAQ,CAAA;QAElB,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAA;QACf,eAAe,EAAE,MAAM,CAAA;QACvB,iBAAiB,EAAE,WAAW,CAAC,QAAQ,EAAE,CAAC,CAAA;KAC3C,CAAA;IACD,cAAc,EAAE;QACd,GAAG,EAAE,MAAM,CAAA;QACX,QAAQ,EAAE,QAAQ,CAAA;QAElB,SAAS,EAAE,OAAO,CAAA;QAClB,SAAS,EAAE,OAAO,CAAA;KACnB,CAAA;CACF,CAAC,GACD,OAAO,CAAC,IAAI,CAAC,CAgGf;AAED,wBAAsB,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAG7D"}
|
|
@@ -47,13 +47,12 @@ export async function up(db) {
|
|
|
47
47
|
.select('authenticatedAt as createdAt') // Best we can do
|
|
48
48
|
.select('authenticatedAt as updatedAt')
|
|
49
49
|
.where('remember', '=', 1)
|
|
50
|
-
.
|
|
50
|
+
.where(({ exists, selectFrom }) =>
|
|
51
51
|
// device_account does not have fkey on account.did,
|
|
52
52
|
// so we satisfy account_device_did_fk with this condition.
|
|
53
|
-
|
|
54
|
-
.selectFrom('account')
|
|
53
|
+
exists(selectFrom('account')
|
|
55
54
|
.selectAll()
|
|
56
|
-
.whereRef('account.did', '=', 'device_account.did')))
|
|
55
|
+
.whereRef('account.did', '=', 'device_account.did'))))
|
|
57
56
|
.onConflict((oc) => oc.doNothing())
|
|
58
57
|
.execute();
|
|
59
58
|
// @NOTE No need to create an index on "deviceId" for "account_device" because
|