Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion services/celest_cloud_auth/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
## NEXT
## 0.3.4

- fix: Database checks in debug mode
- perf: Improve efficiency of several DB operations
- chore: Bump Dart SDK constraint to `^3.7.0`
- chore: Reformat with Dart 3.7

## 0.3.3

Expand Down
12 changes: 5 additions & 7 deletions services/celest_cloud_auth/example/example.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ Future<void> main() async {
final database = CloudAuthDatabase.memory();
final cloudAuth = await CelestCloudAuth.create(database: database);

final router = Router()
..get('/test/hello', () => Response.ok('Hello, world!'))
..mount('/v1alpha1/auth', cloudAuth.handler);
final router =
Router()
..get('/test/hello', () => Response.ok('Hello, world!'))
..mount('/v1alpha1/auth', cloudAuth.handler);
final handler = const Pipeline()
.addMiddleware(logRequests())
.addMiddleware(cloudAuth.middleware.call)
Expand All @@ -37,10 +38,7 @@ final exampleProject = ResolvedProject(
environmentId: 'production',
sdkConfig: SdkConfiguration(
celest: Version(1, 0, 0),
dart: Sdk(
type: SdkType.dart,
version: Version(3, 5, 0),
),
dart: Sdk(type: SdkType.dart, version: Version(3, 5, 0)),
),
apis: {
AuthenticationService.api.apiId: AuthenticationService.api,
Expand Down
82 changes: 37 additions & 45 deletions services/celest_cloud_auth/lib/celest_cloud_auth.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,7 @@ export 'package:celest_cloud_auth/src/users/users_service.dart';

/// The Celest authentication and authorization service.
final class CelestCloudAuth {
CelestCloudAuth._({
required this.db,
required this.cryptoKeys,
}) {
CelestCloudAuth._({required this.db, required this.cryptoKeys}) {
celest.context.put(contextKey, this);
}

Expand Down Expand Up @@ -77,10 +74,7 @@ final class CelestCloudAuth {
if (emailProvider != null) {
celest.context.put(contextKeyEmailOtpProvider, emailProvider);
}
return CelestCloudAuth._(
db: database,
cryptoKeys: cryptoKeys,
);
return CelestCloudAuth._(db: database, cryptoKeys: cryptoKeys);
}

@visibleForTesting
Expand All @@ -93,22 +87,19 @@ final class CelestCloudAuth {
db: db,
rootKey: rootKey,
);
return CelestCloudAuth._(
db: db,
cryptoKeys: cryptoKeys,
);
return CelestCloudAuth._(db: db, cryptoKeys: cryptoKeys);
}

/// An authorization middleware which can be added to a Shelf pipeline.
AuthorizationMiddleware get middleware => AuthorizationMiddleware(
issuer: context.rootEntity,
routeMap: routeMap,
corks: corks,
cryptoKeys: cryptoKeys,
users: users,
db: db,
authorizer: authorizer,
);
issuer: context.rootEntity,
routeMap: routeMap,
corks: corks,
cryptoKeys: cryptoKeys,
users: users,
db: db,
authorizer: authorizer,
);

@visibleForTesting
final CloudAuthDatabaseMixin db;
Expand All @@ -124,18 +115,18 @@ final class CelestCloudAuth {

@visibleForTesting
CorksRepository get corks => CorksRepository(
issuer: context.rootEntity,
db: db,
cryptoKeys: cryptoKeys,
);
issuer: context.rootEntity,
db: db,
cryptoKeys: cryptoKeys,
);

@visibleForTesting
SessionsRepository get sessions => SessionsRepository(
corks: corks,
db: db,
cryptoKeys: cryptoKeys,
users: users,
);
corks: corks,
db: db,
cryptoKeys: cryptoKeys,
users: users,
);

@visibleForTesting
UsersRepository get users => UsersRepository(db: db);
Expand All @@ -147,16 +138,16 @@ final class CelestCloudAuth {
@visibleForTesting
late final AuthenticationService authenticationService =
AuthenticationService(
issuer: context.rootEntity,
routeMap: routeMap,
otp: otp,
authorizer: authorizer,
corks: corks,
cryptoKeys: cryptoKeys,
db: db,
sessions: sessions,
users: users,
);
issuer: context.rootEntity,
routeMap: routeMap,
otp: otp,
authorizer: authorizer,
corks: corks,
cryptoKeys: cryptoKeys,
db: db,
sessions: sessions,
users: users,
);

@visibleForTesting
late final UsersService usersService = UsersService(
Expand All @@ -170,12 +161,13 @@ final class CelestCloudAuth {
);

Handler get handler {
final pipeline =
const Pipeline().addMiddleware(const CloudExceptionMiddleware().call);
final cascade = Cascade(statusCodes: [HttpStatus.notFound])
.add(authenticationService.handler)
.add(usersService.handler)
.handler;
final pipeline = const Pipeline().addMiddleware(
const CloudExceptionMiddleware().call,
);
final cascade =
Cascade(
statusCodes: [HttpStatus.notFound],
).add(authenticationService.handler).add(usersService.handler).handler;
return pipeline.addHandler(cascade);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ sealed class AuthenticationFactor {
AuthenticationFactorEmailOtp.fromProto(proto.emailOtp),
pb.AuthenticationFactor_Factor.smsOtp =>
AuthenticationFactorSmsOtp.fromProto(proto.smsOtp),
final unknown => throw ArgumentError.value(
final unknown =>
throw ArgumentError.value(
unknown,
'factor',
'Invalid AuthenticationFactor. Expected one of: emailOtp, smsOtp',
Expand All @@ -27,13 +28,13 @@ sealed class AuthenticationFactor {
}

pb.AuthenticationFactor toProto() => switch (this) {
final AuthenticationFactorEmailOtp emailOtp => pb.AuthenticationFactor(
emailOtp: emailOtp.toValueProto(),
),
final AuthenticationFactorSmsOtp smsOtp => pb.AuthenticationFactor(
smsOtp: smsOtp.toValueProto(),
),
};
final AuthenticationFactorEmailOtp emailOtp => pb.AuthenticationFactor(
emailOtp: emailOtp.toValueProto(),
),
final AuthenticationFactorSmsOtp smsOtp => pb.AuthenticationFactor(
smsOtp: smsOtp.toValueProto(),
),
};

GeneratedMessage toValueProto();

Expand All @@ -42,10 +43,7 @@ sealed class AuthenticationFactor {
}

final class AuthenticationFactorEmailOtp extends AuthenticationFactor {
const AuthenticationFactorEmailOtp({
required this.email,
this.code,
});
const AuthenticationFactorEmailOtp({required this.email, this.code});

factory AuthenticationFactorEmailOtp.fromProto(
pb.AuthenticationFactorEmailOtp emailOtp,
Expand All @@ -66,17 +64,11 @@ final class AuthenticationFactorEmailOtp extends AuthenticationFactor {

@override
pb.AuthenticationFactorEmailOtp toValueProto() =>
pb.AuthenticationFactorEmailOtp(
email: email,
code: code,
);
pb.AuthenticationFactorEmailOtp(email: email, code: code);
}

final class AuthenticationFactorSmsOtp extends AuthenticationFactor {
const AuthenticationFactorSmsOtp({
required this.phoneNumber,
this.code,
});
const AuthenticationFactorSmsOtp({required this.phoneNumber, this.code});

factory AuthenticationFactorSmsOtp.fromProto(
pb.AuthenticationFactorSmsOtp smsOtp,
Expand All @@ -96,10 +88,8 @@ final class AuthenticationFactorSmsOtp extends AuthenticationFactor {
final String? code;

@override
pb.AuthenticationFactorSmsOtp toValueProto() => pb.AuthenticationFactorSmsOtp(
phoneNumber: phoneNumber,
code: code,
);
pb.AuthenticationFactorSmsOtp toValueProto() =>
pb.AuthenticationFactorSmsOtp(phoneNumber: phoneNumber, code: code);
}

final class SessionClient {
Expand All @@ -122,20 +112,17 @@ final class SessionClient {
final SessionCallbacks callbacks;

pb.SessionClient toProto() => pb.SessionClient(
clientId: clientId,
clientType: clientType,
callbacks: callbacks.toProto(),
);
clientId: clientId,
clientType: clientType,
callbacks: callbacks.toProto(),
);

@override
String toString() => toProto().toString();
}

final class SessionCallbacks {
const SessionCallbacks({
required this.successUri,
this.errorUri,
});
const SessionCallbacks({required this.successUri, this.errorUri});

factory SessionCallbacks.fromProto(pb.SessionCallbacks callbacks) {
return SessionCallbacks(
Expand All @@ -149,9 +136,9 @@ final class SessionCallbacks {
final Uri? errorUri;

pb.SessionCallbacks toProto() => pb.SessionCallbacks(
successUri: successUri.toString(),
errorUri: errorUri?.toString(),
);
successUri: successUri.toString(),
errorUri: errorUri?.toString(),
);

@override
String toString() => toProto().toString();
Expand Down Expand Up @@ -196,22 +183,24 @@ final class SessionStateSuccess extends SessionState {

@override
pb.AuthenticationSuccess toProto() => pb.AuthenticationSuccess(
identityToken: cork.toString(),
user: user.toProto(),
isNewUser: isNewUser,
);
identityToken: cork.toString(),
user: user.toProto(),
isNewUser: isNewUser,
);
}

sealed class SessionStateNextStep extends SessionState {
const SessionStateNextStep();

factory SessionStateNextStep.fromProto(pb.AuthenticationStep proto) {
return switch (proto.whichStep()) {
pb.AuthenticationStep_Step.needsProof =>
SessionStateNeedsProof.fromProto(proto.needsProof),
pb.AuthenticationStep_Step.needsProof => SessionStateNeedsProof.fromProto(
proto.needsProof,
),
pb.AuthenticationStep_Step.pendingConfirmation =>
SessionStatePendingConfirmation.fromProto(proto.pendingConfirmation),
final unknown => throw ArgumentError.value(
final unknown =>
throw ArgumentError.value(
unknown,
'step',
'Invalid AuthenticationStep. Expected one of: needsProof, pendingConfirmation',
Expand All @@ -221,14 +210,14 @@ sealed class SessionStateNextStep extends SessionState {

@override
pb.AuthenticationStep toProto() => switch (this) {
final SessionStateNeedsProof needsProof => pb.AuthenticationStep(
needsProof: needsProof.toValueProto(),
),
final SessionStatePendingConfirmation pendingConfirmation =>
pb.AuthenticationStep(
pendingConfirmation: pendingConfirmation.toValueProto(),
),
};
final SessionStateNeedsProof needsProof => pb.AuthenticationStep(
needsProof: needsProof.toValueProto(),
),
final SessionStatePendingConfirmation pendingConfirmation =>
pb.AuthenticationStep(
pendingConfirmation: pendingConfirmation.toValueProto(),
),
};

@override
void apply(pb.Session session) {
Expand All @@ -237,9 +226,7 @@ sealed class SessionStateNextStep extends SessionState {
}

final class SessionStateNeedsProof extends SessionStateNextStep {
const SessionStateNeedsProof({
required this.factor,
});
const SessionStateNeedsProof({required this.factor});
factory SessionStateNeedsProof.fromProto(pb.AuthenticationFactor proto) {
return SessionStateNeedsProof(
factor: AuthenticationFactor.fromProto(proto),
Expand Down Expand Up @@ -291,8 +278,8 @@ final class Session {
this.clientInfo,
this.ipAddress,
this.externalSessionId,
}) : parent = parent ?? context.rootEntity,
sessionId = TypeId<Session>.decode(sessionId);
}) : parent = parent ?? context.rootEntity,
sessionId = TypeId<Session>.decode(sessionId);

const Session._({
required this.parent,
Expand Down Expand Up @@ -323,9 +310,7 @@ final class Session {
final String? ipAddress;
final String? externalSessionId;

pb.Session toProto({
String? sessionToken,
}) {
pb.Session toProto({String? sessionToken}) {
final session = pb.Session(
parent: parent?.id,
sessionId: sessionId.encoded,
Expand Down
Loading