Skip to content

Commit 0ec0033

Browse files
authored
feat(cloud_auth): Make database modular (#289)
Allows the `CloudAuthDatabase` to be incorporated into other Drift databases via the `include` field and a `CloudAuthDatabaseMixin` mixin. This means that only one database class is required per project. In order to control schema upgrades in the Cloud Auth portion of the database, a new meta table is created so that the version pragma can be used for the host database's schema version.
1 parent b094e88 commit 0ec0033

29 files changed

+7236
-890
lines changed

services/celest_cloud_auth/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
## 0.2.1-wip
22

3+
- feat: Make database modular
4+
- refactor: Rename `AuthDatabase` to `CloudAuthDatabase`
35
- chore: Make `Authorizer` a class
46

57
## 0.2.0

services/celest_cloud_auth/drift_schema/auth_database/drift_schema_v3.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

services/celest_cloud_auth/lib/celest_cloud_auth.dart

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import 'package:cedar/cedar.dart';
21
import 'package:celest/src/core/context.dart' as celest;
32
// ignore: invalid_use_of_internal_member
43
import 'package:celest/src/runtime/http/cloud_middleware.dart';
@@ -7,9 +6,9 @@ import 'package:celest_cloud_auth/src/authorization/authorization_middleware.dar
76
import 'package:celest_cloud_auth/src/authorization/authorizer.dart';
87
import 'package:celest_cloud_auth/src/authorization/corks_repository.dart';
98
import 'package:celest_cloud_auth/src/context.dart';
10-
import 'package:celest_cloud_auth/src/crypto/crypto_key_model.dart';
119
import 'package:celest_cloud_auth/src/crypto/crypto_key_repository.dart';
1210
import 'package:celest_cloud_auth/src/database/auth_database.dart';
11+
import 'package:celest_cloud_auth/src/database/auth_database_accessors.dart';
1312
import 'package:celest_cloud_auth/src/email/email_provider.dart';
1413
import 'package:celest_cloud_auth/src/model/route_map.dart';
1514
import 'package:celest_cloud_auth/src/otp/otp_repository.dart';
@@ -22,8 +21,10 @@ import 'package:shelf/shelf.dart';
2221

2322
export 'package:celest_cloud_auth/src/authentication/authentication_service.dart';
2423
export 'package:celest_cloud_auth/src/database/auth_database.dart';
24+
export 'package:celest_cloud_auth/src/database/auth_database_accessors.dart';
2525
export 'package:celest_cloud_auth/src/email/email_provider.dart';
2626
export 'package:celest_cloud_auth/src/otp/otp_provider.dart';
27+
export 'package:celest_cloud_auth/src/users/users_service.dart';
2728

2829
/// The Celest authentication and authorization service.
2930
final class CelestCloudAuth {
@@ -69,10 +70,9 @@ final class CelestCloudAuth {
6970
/// }
7071
/// ```
7172
static Future<CelestCloudAuth> create({
72-
required AuthDatabase database,
73+
required CloudAuthDatabaseMixin database,
7374
EmailOtpProvider? emailProvider,
7475
}) async {
75-
await database.ping();
7676
final cryptoKeys = await CryptoKeyRepository.create(db: database);
7777
if (emailProvider != null) {
7878
celest.context.put(contextKeyEmailOtpProvider, emailProvider);
@@ -85,11 +85,10 @@ final class CelestCloudAuth {
8585

8686
@visibleForTesting
8787
static Future<CelestCloudAuth> test({
88-
AuthDatabase? db,
88+
CloudAuthDatabaseMixin? db,
8989
CryptoKey? rootKey,
9090
}) async {
91-
db ??= AuthDatabase.memory();
92-
await db.ping();
91+
db ??= CloudAuthDatabase.memory();
9392
final cryptoKeys = await CryptoKeyRepository.create(
9493
db: db,
9594
rootKey: rootKey,
@@ -110,7 +109,7 @@ final class CelestCloudAuth {
110109
);
111110

112111
@visibleForTesting
113-
final AuthDatabase db;
112+
final CloudAuthDatabaseMixin db;
114113

115114
@visibleForTesting
116115
final CryptoKeyRepository cryptoKeys;

services/celest_cloud_auth/lib/src/authentication/authentication_service.dart

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,12 @@ import 'package:cedar/cedar.dart';
33
import 'package:celest/src/runtime/http/cloud_middleware.dart';
44
import 'package:celest_ast/celest_ast.dart';
55
import 'package:celest_cloud/src/proto.dart' as pb;
6-
import 'package:celest_cloud_auth/src/authentication/authentication_model.dart';
76
import 'package:celest_cloud_auth/src/authorization/authorization_middleware.dart';
87
import 'package:celest_cloud_auth/src/authorization/authorizer.dart';
98
import 'package:celest_cloud_auth/src/authorization/corks_repository.dart';
109
import 'package:celest_cloud_auth/src/context.dart';
1110
import 'package:celest_cloud_auth/src/crypto/crypto_key_repository.dart';
12-
import 'package:celest_cloud_auth/src/database/auth_database.dart';
11+
import 'package:celest_cloud_auth/src/database/auth_database_accessors.dart';
1312
import 'package:celest_cloud_auth/src/http/http_helpers.dart';
1413
import 'package:celest_cloud_auth/src/model/route_map.dart';
1514
import 'package:celest_cloud_auth/src/otp/otp_repository.dart';
@@ -25,7 +24,7 @@ import 'package:shelf_router/shelf_router.dart';
2524
typedef _Deps = ({
2625
EntityUid issuer,
2726
RouteMap routeMap,
28-
AuthDatabase db,
27+
CloudAuthDatabaseMixin db,
2928
OtpRepository otp,
3029
CryptoKeyRepository cryptoKeys,
3130
Authorizer authorizer,
@@ -38,7 +37,7 @@ extension type AuthenticationService._(_Deps _deps) implements Object {
3837
AuthenticationService({
3938
required EntityUid issuer,
4039
required RouteMap routeMap,
41-
required AuthDatabase db,
40+
required CloudAuthDatabaseMixin db,
4241
required OtpRepository otp,
4342
required CryptoKeyRepository cryptoKeys,
4443
required Authorizer authorizer,
@@ -59,7 +58,7 @@ extension type AuthenticationService._(_Deps _deps) implements Object {
5958
),
6059
);
6160

62-
AuthDatabase get _db => _deps.db;
61+
CloudAuthDatabaseAccessors get _db => _deps.db.cloudAuth;
6362
OtpRepository get _otp => _deps.otp;
6463
CorksRepository get _corks => _deps.corks;
6564
SessionsRepository get _sessions => _deps.sessions;

services/celest_cloud_auth/lib/src/authorization/authorization_middleware.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import 'package:cedar/cedar.dart';
22
import 'package:celest_cloud_auth/src/authorization/authorizer.dart';
33
import 'package:celest_cloud_auth/src/authorization/corks_repository.dart';
44
import 'package:celest_cloud_auth/src/context.dart';
5-
import 'package:celest_cloud_auth/src/database/auth_database.dart';
5+
import 'package:celest_cloud_auth/src/database/auth_database_accessors.dart';
66
import 'package:celest_cloud_auth/src/http/http_helpers.dart';
77
import 'package:celest_cloud_auth/src/model/interop.dart';
88
import 'package:celest_cloud_auth/src/model/route_map.dart';
@@ -16,7 +16,7 @@ import 'package:shelf/shelf.dart' show Handler, Request;
1616
typedef _Deps = ({
1717
RouteMap routeMap,
1818
CorksRepository corks,
19-
AuthDatabase db,
19+
CloudAuthDatabaseMixin db,
2020
Authorizer authorizer,
2121
EntityUid issuer,
2222
});
@@ -29,7 +29,7 @@ extension type AuthorizationMiddleware._(_Deps _deps) implements Object {
2929
AuthorizationMiddleware({
3030
required RouteMap routeMap,
3131
required CorksRepository corks,
32-
required AuthDatabase db,
32+
required CloudAuthDatabaseMixin db,
3333
required Authorizer authorizer,
3434
required EntityUid issuer,
3535
}) : this._(
@@ -44,7 +44,7 @@ extension type AuthorizationMiddleware._(_Deps _deps) implements Object {
4444

4545
RouteMap get _routeMap => _deps.routeMap;
4646
CorksRepository get _corks => _deps.corks;
47-
AuthDatabase get _db => _deps.db;
47+
CloudAuthDatabaseAccessors get _db => _deps.db.cloudAuth;
4848
Authorizer get _authorizer => _deps.authorizer;
4949

5050
Handler call(Handler inner) {

services/celest_cloud_auth/lib/src/authorization/authorizer.dart

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
import 'dart:async';
22

33
import 'package:cedar/cedar.dart';
4-
import 'package:celest_cloud_auth/src/database/auth_database.dart';
4+
import 'package:celest_cloud_auth/src/database/auth_database_accessors.dart';
55
import 'package:celest_core/celest_core.dart';
66
import 'package:logging/logging.dart';
77
import 'package:meta/meta.dart';
88

99
class Authorizer {
10-
Authorizer({required AuthDatabase db}) : _db = db;
10+
Authorizer({required CloudAuthDatabaseMixin db}) : _db = db.cloudAuth;
1111

1212
static final Logger _logger = Logger('Celest.Authorizer');
1313

14-
final AuthDatabase _db;
14+
final CloudAuthDatabaseAccessors _db;
1515

1616
Future<void> expectAuthorized({
1717
Component? principal,
@@ -65,6 +65,25 @@ class Authorizer {
6565
},
6666
);
6767
final response = policySet.isAuthorized(request);
68+
_logger.finest(() {
69+
final buffer = StringBuffer()
70+
..writeln('Request:')
71+
..writeln(' Principal: $principal')
72+
..writeln(' Resource: $resource')
73+
..writeln(' Action: $action');
74+
75+
final jsonContext = context?.map((k, v) => MapEntry(k, v.toJson()));
76+
buffer.writeln(' Context: $jsonContext');
77+
78+
buffer.writeln('Decision: ${response.decision}');
79+
if (response.errors.isNotEmpty) {
80+
buffer.writeln(' Errors: ${response.errors.join(', ')}');
81+
}
82+
if (response.reasons.isNotEmpty) {
83+
buffer.writeln(' Reasons: ${response.reasons.join(', ')}');
84+
}
85+
return buffer;
86+
});
6887
unawaited(_recordAuthorization(request, response));
6988
return response;
7089
}

services/celest_cloud_auth/lib/src/authorization/corks_repository.dart

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
import 'dart:typed_data';
22

33
import 'package:cedar/cedar.dart';
4-
import 'package:celest_cloud_auth/src/authentication/authentication_model.dart';
54
import 'package:celest_cloud_auth/src/context.dart';
65
import 'package:celest_cloud_auth/src/crypto/crypto_key_repository.dart';
7-
import 'package:celest_cloud_auth/src/database/auth_database.dart';
6+
import 'package:celest_cloud_auth/src/database/auth_database_accessors.dart';
87
import 'package:celest_cloud_auth/src/database/schema/auth.drift.dart' as drift;
98
import 'package:celest_cloud_auth/src/model/interop.dart';
109
import 'package:celest_core/celest_core.dart';
@@ -13,14 +12,14 @@ import 'package:drift/drift.dart' as drift;
1312

1413
typedef _Dependencies = ({
1514
EntityUid issuer,
16-
AuthDatabase db,
15+
CloudAuthDatabaseMixin db,
1716
CryptoKeyRepository cryptoKeys,
1817
});
1918

2019
extension type CorksRepository._(_Dependencies _deps) implements Object {
2120
CorksRepository({
2221
required EntityUid issuer,
23-
required AuthDatabase db,
22+
required CloudAuthDatabaseMixin db,
2423
required CryptoKeyRepository cryptoKeys,
2524
}) : this._(
2625
(
@@ -31,7 +30,7 @@ extension type CorksRepository._(_Dependencies _deps) implements Object {
3130
);
3231

3332
EntityUid get issuer => _deps.issuer;
34-
AuthDatabase get _db => _deps.db;
33+
CloudAuthDatabaseAccessors get _db => _deps.db.cloudAuth;
3534
CryptoKeyRepository get _cryptoKeys => _deps.cryptoKeys;
3635

3736
Future<drift.Cork?> getCork({

services/celest_cloud_auth/lib/src/crypto/crypto_key_repository.dart

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
1-
import 'package:celest_cloud_auth/src/crypto/crypto_key_model.dart';
2-
import 'package:celest_cloud_auth/src/database/auth_database.dart';
1+
import 'package:celest_cloud_auth/celest_cloud_auth.dart';
32
import 'package:celest_cloud_auth/src/util/random_bytes.dart';
43
import 'package:drift/drift.dart';
54

65
typedef _Deps = ({
7-
AuthDatabase db,
6+
CloudAuthDatabaseMixin db,
87
CryptoKey rootKey,
98
});
109

1110
extension type CryptoKeyRepository._(_Deps _deps) implements Object {
1211
static Future<CryptoKeyRepository> create({
13-
required AuthDatabase db,
12+
required CloudAuthDatabaseMixin db,
1413
CryptoKey? rootKey,
1514
}) async {
1615
rootKey ??= LocalCryptoKey(
@@ -19,7 +18,7 @@ extension type CryptoKeyRepository._(_Deps _deps) implements Object {
1918
keyAlgorithm: KeyAlgorithm.hmacSha256,
2019
keyMaterial: secureRandomBytes(32),
2120
);
22-
rootKey = (await db.authDrift.createCryptoKey(
21+
rootKey = (await db.cloudAuth.authDrift.createCryptoKey(
2322
cryptoKeyId: rootKey.cryptoKeyId,
2423
keyPurpose: rootKey.keyPurpose.name,
2524
keyAlgorithm: rootKey.keyAlgorithm.name,
@@ -34,7 +33,7 @@ extension type CryptoKeyRepository._(_Deps _deps) implements Object {
3433
);
3534
}
3635

37-
AuthDatabase get _db => _deps.db;
36+
CloudAuthDatabaseAccessors get _db => _deps.db.cloudAuth;
3837
CryptoKey get rootKey => _deps.rootKey;
3938

4039
Future<CryptoKey> getKey({

0 commit comments

Comments
 (0)