diff --git a/packages/shorebird_cli/test/src/auth/auth_test.dart b/packages/shorebird_cli/test/src/auth/auth_test.dart index a41f83e12..7632a5a80 100644 --- a/packages/shorebird_cli/test/src/auth/auth_test.dart +++ b/packages/shorebird_cli/test/src/auth/auth_test.dart @@ -127,7 +127,7 @@ void main() { authProvider: AuthProvider.google, ); const email = 'test@email.com'; - const user = User( + const user = PrivateUser( id: 42, email: email, jwtIssuer: googleJwtIssuer, diff --git a/packages/shorebird_code_push_client/lib/src/code_push_client.dart b/packages/shorebird_code_push_client/lib/src/code_push_client.dart index 1ac3aa487..28db86249 100644 --- a/packages/shorebird_code_push_client/lib/src/code_push_client.dart +++ b/packages/shorebird_code_push_client/lib/src/code_push_client.dart @@ -111,7 +111,7 @@ class CodePushClient { Uri get _v1 => Uri.parse('$hostedUri/api/v1'); /// Fetches the currently logged-in user. - Future getCurrentUser() async { + Future getCurrentUser() async { final uri = Uri.parse('$_v1/users/me'); final response = await _httpClient.get(uri); @@ -122,7 +122,7 @@ class CodePushClient { } final json = jsonDecode(response.body) as Map; - return User.fromJson(json); + return PrivateUser.fromJson(json); } /// Create a new artifact for a specific [patchId]. @@ -331,7 +331,7 @@ class CodePushClient { /// Create a new Shorebird user with the provided [name]. /// /// The email associated with the user's JWT will be used as the user's email. - Future createUser({ + Future createUser({ required String name, }) async { final response = await _httpClient.post( @@ -344,7 +344,7 @@ class CodePushClient { } final body = json.decode(response.body) as Json; - return User.fromJson(body); + return PrivateUser.fromJson(body); } /// Delete the app with the provided [appId]. diff --git a/packages/shorebird_code_push_client/test/src/code_push_client_test.dart b/packages/shorebird_code_push_client/test/src/code_push_client_test.dart index fac28b01d..e6f6ecac8 100644 --- a/packages/shorebird_code_push_client/test/src/code_push_client_test.dart +++ b/packages/shorebird_code_push_client/test/src/code_push_client_test.dart @@ -100,7 +100,7 @@ void main() { }); group('getCurrentUser', () { - const user = User( + const user = PrivateUser( id: 123, email: 'tester@shorebird.dev', jwtIssuer: 'https://accounts.google.com', @@ -1221,7 +1221,7 @@ void main() { group('createUser', () { const userName = 'Jane Doe'; - final user = User( + final user = PrivateUser( id: 1, email: 'tester@shorebird.dev', displayName: userName, diff --git a/packages/shorebird_code_push_protocol/lib/src/models/models.dart b/packages/shorebird_code_push_protocol/lib/src/models/models.dart index b3e4f9ebf..59f0c14ea 100644 --- a/packages/shorebird_code_push_protocol/lib/src/models/models.dart +++ b/packages/shorebird_code_push_protocol/lib/src/models/models.dart @@ -10,9 +10,10 @@ export 'organization_user.dart'; export 'patch.dart'; export 'patch_artifact.dart'; export 'plan.dart'; +export 'private_user.dart'; +export 'public_user.dart'; export 'release.dart'; export 'release_artifact.dart'; export 'release_patch.dart'; export 'release_platform.dart'; export 'release_status.dart'; -export 'user.dart'; diff --git a/packages/shorebird_code_push_protocol/lib/src/models/organization_user.dart b/packages/shorebird_code_push_protocol/lib/src/models/organization_user.dart index ebfa63c02..f38fd5080 100644 --- a/packages/shorebird_code_push_protocol/lib/src/models/organization_user.dart +++ b/packages/shorebird_code_push_protocol/lib/src/models/organization_user.dart @@ -22,7 +22,7 @@ class OrganizationUser { Map toJson() => _$OrganizationUserToJson(this); /// The user that is a member of the organization. - final User user; + final PublicUser user; /// The role [user] has in the organization. final OrganizationRole role; diff --git a/packages/shorebird_code_push_protocol/lib/src/models/organization_user.g.dart b/packages/shorebird_code_push_protocol/lib/src/models/organization_user.g.dart index dfab00147..57e29695d 100644 --- a/packages/shorebird_code_push_protocol/lib/src/models/organization_user.g.dart +++ b/packages/shorebird_code_push_protocol/lib/src/models/organization_user.g.dart @@ -15,7 +15,7 @@ OrganizationUser _$OrganizationUserFromJson(Map json) => ($checkedConvert) { final val = OrganizationUser( user: $checkedConvert( - 'user', (v) => User.fromJson(v as Map)), + 'user', (v) => PublicUser.fromJson(v as Map)), role: $checkedConvert( 'role', (v) => $enumDecode(_$OrganizationRoleEnumMap, v)), ); diff --git a/packages/shorebird_code_push_protocol/lib/src/models/user.dart b/packages/shorebird_code_push_protocol/lib/src/models/private_user.dart similarity index 71% rename from packages/shorebird_code_push_protocol/lib/src/models/user.dart rename to packages/shorebird_code_push_protocol/lib/src/models/private_user.dart index a8e4b14c2..51e306a66 100644 --- a/packages/shorebird_code_push_protocol/lib/src/models/user.dart +++ b/packages/shorebird_code_push_protocol/lib/src/models/private_user.dart @@ -1,15 +1,18 @@ import 'package:json_annotation/json_annotation.dart'; import 'package:meta/meta.dart'; +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; -part 'user.g.dart'; +part 'private_user.g.dart'; /// {@template user} -/// A user account which contains zero or more apps. +/// A fully-detailed user object, possibly including sensitive information. +/// This should only be used when querying the user's own information. For other +/// users, use [PublicUser]. /// {@endtemplate} @JsonSerializable() -class User { +class PrivateUser { /// {@macro user} - const User({ + const PrivateUser({ required this.id, required this.email, required this.jwtIssuer, @@ -19,13 +22,14 @@ class User { this.patchOverageLimit, }); - /// Converts a Map to a [User] - factory User.fromJson(Map json) => _$UserFromJson(json); + /// Converts a Map to a [PrivateUser] + factory PrivateUser.fromJson(Map json) => + _$PrivateUserFromJson(json); // coverage:ignore-start /// Constructs a user with arbitrary default values for testing. @visibleForTesting - factory User.forTest({ + factory PrivateUser.forTest({ int id = 42, String email = 'test@shorebird.dev', String jwtIssuer = 'https://accounts.google.com', @@ -34,7 +38,7 @@ class User { String? stripeCustomerId, int? patchOverageLimit = 0, }) => - User( + PrivateUser( id: id, email: email, jwtIssuer: jwtIssuer, @@ -45,8 +49,8 @@ class User { ); // coverage:ignore-end - /// Converts a [User] to a Map - Map toJson() => _$UserToJson(this); + /// Converts a [PrivateUser] to a Map + Map toJson() => _$PrivateUserToJson(this); /// The unique user identifier. final int id; diff --git a/packages/shorebird_code_push_protocol/lib/src/models/user.g.dart b/packages/shorebird_code_push_protocol/lib/src/models/private_user.g.dart similarity index 86% rename from packages/shorebird_code_push_protocol/lib/src/models/user.g.dart rename to packages/shorebird_code_push_protocol/lib/src/models/private_user.g.dart index 7941cc29a..a21bb7a01 100644 --- a/packages/shorebird_code_push_protocol/lib/src/models/user.g.dart +++ b/packages/shorebird_code_push_protocol/lib/src/models/private_user.g.dart @@ -2,17 +2,17 @@ // ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars -part of 'user.dart'; +part of 'private_user.dart'; // ************************************************************************** // JsonSerializableGenerator // ************************************************************************** -User _$UserFromJson(Map json) => $checkedCreate( - 'User', +PrivateUser _$PrivateUserFromJson(Map json) => $checkedCreate( + 'PrivateUser', json, ($checkedConvert) { - final val = User( + final val = PrivateUser( id: $checkedConvert('id', (v) => (v as num).toInt()), email: $checkedConvert('email', (v) => v as String), jwtIssuer: $checkedConvert('jwt_issuer', (v) => v as String), @@ -35,7 +35,8 @@ User _$UserFromJson(Map json) => $checkedCreate( }, ); -Map _$UserToJson(User instance) => { +Map _$PrivateUserToJson(PrivateUser instance) => + { 'id': instance.id, 'email': instance.email, 'display_name': instance.displayName, diff --git a/packages/shorebird_code_push_protocol/lib/src/models/public_user.dart b/packages/shorebird_code_push_protocol/lib/src/models/public_user.dart new file mode 100644 index 000000000..8d6b2a9ff --- /dev/null +++ b/packages/shorebird_code_push_protocol/lib/src/models/public_user.dart @@ -0,0 +1,43 @@ +import 'package:json_annotation/json_annotation.dart'; +import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; + +part 'public_user.g.dart'; + +/// {@template user} +/// A Shorebird user. This is a pared down version of [PrivateUser]. +/// {@endtemplate} +@JsonSerializable() +class PublicUser { + /// {@macro user} + PublicUser({ + required this.id, + required this.email, + required this.displayName, + }); + + /// Converts a Map to a [PublicUser] + factory PublicUser.fromJson(Map json) => + _$PublicUserFromJson(json); + + /// Constructs a [PublicUser] from a [PrivateUser], removing sensitive + /// information. + factory PublicUser.fromPrivateUser(PrivateUser fullUser) { + return PublicUser( + id: fullUser.id, + email: fullUser.email, + displayName: fullUser.displayName, + ); + } + + /// Converts a [PublicUser] to a JSON map. + Map toJson() => _$PublicUserToJson(this); + + /// The user's unique identifier. + final int id; + + /// The user's email address. + final String email; + + /// The user's name. + final String? displayName; +} diff --git a/packages/shorebird_code_push_protocol/lib/src/models/public_user.g.dart b/packages/shorebird_code_push_protocol/lib/src/models/public_user.g.dart new file mode 100644 index 000000000..df20477a1 --- /dev/null +++ b/packages/shorebird_code_push_protocol/lib/src/models/public_user.g.dart @@ -0,0 +1,30 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars + +part of 'public_user.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +PublicUser _$PublicUserFromJson(Map json) => $checkedCreate( + 'PublicUser', + json, + ($checkedConvert) { + final val = PublicUser( + id: $checkedConvert('id', (v) => (v as num).toInt()), + email: $checkedConvert('email', (v) => v as String), + displayName: $checkedConvert('display_name', (v) => v as String?), + ); + return val; + }, + fieldKeyMap: const {'displayName': 'display_name'}, + ); + +Map _$PublicUserToJson(PublicUser instance) => + { + 'id': instance.id, + 'email': instance.email, + 'display_name': instance.displayName, + }; diff --git a/packages/shorebird_code_push_protocol/test/src/messages/get_organization_users/get_organization_users_response_test.dart b/packages/shorebird_code_push_protocol/test/src/messages/get_organization_users/get_organization_users_response_test.dart index ca9b77d96..8389ef479 100644 --- a/packages/shorebird_code_push_protocol/test/src/messages/get_organization_users/get_organization_users_response_test.dart +++ b/packages/shorebird_code_push_protocol/test/src/messages/get_organization_users/get_organization_users_response_test.dart @@ -6,7 +6,10 @@ void main() { test('can be (de)serialized', () { final getOrganizationUsersRequest = GetOrganizationUsersResponse( users: [ - OrganizationUser(user: User.forTest(), role: OrganizationRole.owner), + OrganizationUser( + user: PublicUser.fromPrivateUser(PrivateUser.forTest()), + role: OrganizationRole.owner, + ), ], ); expect( diff --git a/packages/shorebird_code_push_protocol/test/src/models/organization_user_test.dart b/packages/shorebird_code_push_protocol/test/src/models/organization_user_test.dart index f14484127..d456681fc 100644 --- a/packages/shorebird_code_push_protocol/test/src/models/organization_user_test.dart +++ b/packages/shorebird_code_push_protocol/test/src/models/organization_user_test.dart @@ -5,7 +5,7 @@ void main() { group(OrganizationUser, () { test('can be (de)serialized', () { final organizationUser = OrganizationUser( - user: User.forTest(), + user: PublicUser.fromPrivateUser(PrivateUser.forTest()), role: OrganizationRole.member, ); expect( diff --git a/packages/shorebird_code_push_protocol/test/src/models/user_test.dart b/packages/shorebird_code_push_protocol/test/src/models/private_user_test.dart similarity index 80% rename from packages/shorebird_code_push_protocol/test/src/models/user_test.dart rename to packages/shorebird_code_push_protocol/test/src/models/private_user_test.dart index 4b6ce1aa8..d764c718e 100644 --- a/packages/shorebird_code_push_protocol/test/src/models/user_test.dart +++ b/packages/shorebird_code_push_protocol/test/src/models/private_user_test.dart @@ -2,9 +2,9 @@ import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart'; import 'package:test/test.dart'; void main() { - group(User, () { + group(PrivateUser, () { test('can be (de)serialized', () { - const user = User( + const user = PrivateUser( id: 1, email: 'test@shorebird.dev', stripeCustomerId: 'test-customer-id', @@ -13,7 +13,7 @@ void main() { patchOverageLimit: 123, ); expect( - User.fromJson(user.toJson()).toJson(), + PrivateUser.fromJson(user.toJson()).toJson(), equals(user.toJson()), ); });