Skip to content

Commit

Permalink
✨ feat: reserveSigningKey (#953)
Browse files Browse the repository at this point in the history
  • Loading branch information
myConsciousness committed Nov 1, 2023
1 parent 6b22eae commit f103639
Show file tree
Hide file tree
Showing 11 changed files with 300 additions and 0 deletions.
2 changes: 2 additions & 0 deletions packages/atproto/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
- Supported `com.atproto.labels.queryLabels` and `LabelsService`. ([#265](https://github.com/myConsciousness/atproto.dart/issues/265))
- Supported `com.atproto.labels.subscribeLabels` on `LabelsService`. ([#340](https://github.com/myConsciousness/atproto.dart/issues/340))
- Added `.deleteSession` function. ([#963](https://github.com/myConsciousness/atproto.dart/issues/963))
- Supported `com.atproto.server.reserveSigningKey` on `ServersService`. ([#953](https://github.com/myConsciousness/atproto.dart/issues/953))
- `.createSigningKey`

## v0.7.1

Expand Down
1 change: 1 addition & 0 deletions packages/atproto/lib/atproto.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export 'package:atproto/src/entities/subscribed_repo_info.dart';
export 'package:atproto/src/entities/subscribed_repo_migrate.dart';
export 'package:atproto/src/entities/subscribed_repo_tombstone.dart';
export 'package:atproto/src/entities/update_action.dart';
export 'package:atproto/src/entities/signing_key.dart';
export 'package:atproto/src/identities/identities_service.dart';
export 'package:atproto/src/moderation/moderation_reason_type.dart';
export 'package:atproto/src/moderation/moderation_service.dart';
Expand Down
26 changes: 26 additions & 0 deletions packages/atproto/lib/src/entities/signing_key.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright 2023 Shinya Kato. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided the conditions.

// πŸ“¦ Package imports:
import 'package:freezed_annotation/freezed_annotation.dart';

part 'signing_key.freezed.dart';
part 'signing_key.g.dart';

/// Represents an issued signing key.
@freezed
class SigningKey with _$SigningKey {
/// Creates a new instance of [SigningKey].
const factory SigningKey({
/// Public signing key in the form of a did:key.
required String signingKey,
}) = _SigningKey;

/// Creates a new instance of [SigningKey] from a JSON object.
///
/// The [json] parameter must be a map with keys and values that can be used
/// to populate an instance of [SigningKey].
factory SigningKey.fromJson(Map<String, Object?> json) =>
_$SigningKeyFromJson(json);
}
156 changes: 156 additions & 0 deletions packages/atproto/lib/src/entities/signing_key.freezed.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark

part of 'signing_key.dart';

// **************************************************************************
// FreezedGenerator
// **************************************************************************

T _$identity<T>(T value) => value;

final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');

SigningKey _$SigningKeyFromJson(Map<String, dynamic> json) {
return _SigningKey.fromJson(json);
}

/// @nodoc
mixin _$SigningKey {
/// Public signing key in the form of a did:key.
String get signingKey => throw _privateConstructorUsedError;

Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$SigningKeyCopyWith<SigningKey> get copyWith =>
throw _privateConstructorUsedError;
}

/// @nodoc
abstract class $SigningKeyCopyWith<$Res> {
factory $SigningKeyCopyWith(
SigningKey value, $Res Function(SigningKey) then) =
_$SigningKeyCopyWithImpl<$Res, SigningKey>;
@useResult
$Res call({String signingKey});
}

/// @nodoc
class _$SigningKeyCopyWithImpl<$Res, $Val extends SigningKey>
implements $SigningKeyCopyWith<$Res> {
_$SigningKeyCopyWithImpl(this._value, this._then);

// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;

@pragma('vm:prefer-inline')
@override
$Res call({
Object? signingKey = null,
}) {
return _then(_value.copyWith(
signingKey: null == signingKey
? _value.signingKey
: signingKey // ignore: cast_nullable_to_non_nullable
as String,
) as $Val);
}
}

/// @nodoc
abstract class _$$_SigningKeyCopyWith<$Res>
implements $SigningKeyCopyWith<$Res> {
factory _$$_SigningKeyCopyWith(
_$_SigningKey value, $Res Function(_$_SigningKey) then) =
__$$_SigningKeyCopyWithImpl<$Res>;
@override
@useResult
$Res call({String signingKey});
}

/// @nodoc
class __$$_SigningKeyCopyWithImpl<$Res>
extends _$SigningKeyCopyWithImpl<$Res, _$_SigningKey>
implements _$$_SigningKeyCopyWith<$Res> {
__$$_SigningKeyCopyWithImpl(
_$_SigningKey _value, $Res Function(_$_SigningKey) _then)
: super(_value, _then);

@pragma('vm:prefer-inline')
@override
$Res call({
Object? signingKey = null,
}) {
return _then(_$_SigningKey(
signingKey: null == signingKey
? _value.signingKey
: signingKey // ignore: cast_nullable_to_non_nullable
as String,
));
}
}

/// @nodoc
@JsonSerializable()
class _$_SigningKey implements _SigningKey {
const _$_SigningKey({required this.signingKey});

factory _$_SigningKey.fromJson(Map<String, dynamic> json) =>
_$$_SigningKeyFromJson(json);

/// Public signing key in the form of a did:key.
@override
final String signingKey;

@override
String toString() {
return 'SigningKey(signingKey: $signingKey)';
}

@override
bool operator ==(dynamic other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$_SigningKey &&
(identical(other.signingKey, signingKey) ||
other.signingKey == signingKey));
}

@JsonKey(ignore: true)
@override
int get hashCode => Object.hash(runtimeType, signingKey);

@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$_SigningKeyCopyWith<_$_SigningKey> get copyWith =>
__$$_SigningKeyCopyWithImpl<_$_SigningKey>(this, _$identity);

@override
Map<String, dynamic> toJson() {
return _$$_SigningKeyToJson(
this,
);
}
}

abstract class _SigningKey implements SigningKey {
const factory _SigningKey({required final String signingKey}) = _$_SigningKey;

factory _SigningKey.fromJson(Map<String, dynamic> json) =
_$_SigningKey.fromJson;

@override

/// Public signing key in the form of a did:key.
String get signingKey;
@override
@JsonKey(ignore: true)
_$$_SigningKeyCopyWith<_$_SigningKey> get copyWith =>
throw _privateConstructorUsedError;
}
25 changes: 25 additions & 0 deletions packages/atproto/lib/src/entities/signing_key.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions packages/atproto/lib/src/servers/servers_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import '../entities/current_session.dart';
import '../entities/email_update.dart';
import '../entities/invite_codes.dart';
import '../entities/server_info.dart';
import '../entities/signing_key.dart';

sealed class ServersService {
/// Returns the new instance of [ServersService].
Expand Down Expand Up @@ -406,6 +407,17 @@ sealed class ServersService {
required String email,
String? token,
});

/// Reserve a repo signing key for account creation.
///
/// ## Lexicon
///
/// - com.atproto.server.reserveSigningKey
///
/// ## Reference
///
/// - https://github.com/bluesky-social/atproto/blob/main/lexicons/com/atproto/server/reserveSigningKey.json
Future<core.XRPCResponse<SigningKey>> createSigningKey();
}

final class _ServersService extends ATProtoBaseService
Expand Down Expand Up @@ -622,6 +634,13 @@ final class _ServersService extends ATProtoBaseService
},
);

@override
Future<core.XRPCResponse<SigningKey>> createSigningKey() async =>
await super.post(
'reserveSigningKey',
to: SigningKey.fromJson,
);

Future<core.XRPCResponse<T>> _findCurrentSession<T>({
core.To<T>? to,
}) async =>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"signingKey": "did:plc:iijrtk7ocored6zuziwmqq3c"
}
63 changes: 63 additions & 0 deletions packages/atproto/test/src/servers/servers_service_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import 'package:atproto/src/entities/current_session.dart';
import 'package:atproto/src/entities/email_update.dart';
import 'package:atproto/src/entities/invite_codes.dart';
import 'package:atproto/src/entities/server_info.dart';
import 'package:atproto/src/entities/signing_key.dart';
import 'package:atproto/src/servers/servers_service.dart';

void main() {
Expand Down Expand Up @@ -1307,4 +1308,66 @@ void main() {
);
});
});

group('.createSigningKey', () {
test('normal case', () async {
final servers = ServersService(
did: 'test',
protocol: core.Protocol.https,
service: 'test',
context: core.ClientContext(
accessJwt: '1234',
timeout: Duration.zero,
),
mockedPostClient: atp_test.createMockedPostClient(
'test/src/servers/data/create_signing_key.json',
),
);

final response = await servers.createSigningKey();

expect(response, isA<core.XRPCResponse>());
expect(response.data, isA<SigningKey>());
});

test('when unauthorized', () async {
final servers = ServersService(
did: 'test',
protocol: core.Protocol.https,
service: 'test',
context: core.ClientContext(
accessJwt: '1234',
timeout: Duration.zero,
),
mockedPostClient: atp_test.createMockedPostClient(
'test/src/data/error.json',
statusCode: 401,
),
);

atp_test.expectUnauthorizedException(
() async => await servers.createSigningKey(),
);
});

test('when rate limit exceeded', () async {
final servers = ServersService(
did: 'test',
protocol: core.Protocol.https,
service: 'test',
context: core.ClientContext(
accessJwt: '1234',
timeout: Duration.zero,
),
mockedPostClient: atp_test.createMockedPostClient(
'test/src/data/error.json',
statusCode: 429,
),
);

atp_test.expectRateLimitExceededException(
() async => await servers.createSigningKey(),
);
});
});
}
2 changes: 2 additions & 0 deletions packages/bluesky/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
- Supported `com.atproto.labels.queryLabels` and `LabelsService`. ([#265](https://github.com/myConsciousness/atproto.dart/issues/265))
- Supported `com.atproto.labels.subscribeLabels` on `LabelsService`. ([#340](https://github.com/myConsciousness/atproto.dart/issues/340))
- Added `.deleteSession` function. ([#963](https://github.com/myConsciousness/atproto.dart/issues/963))
- Supported `com.atproto.server.reserveSigningKey` on `ServersService`. ([#953](https://github.com/myConsciousness/atproto.dart/issues/953))
- `.createSigningKey`

## v0.9.2

Expand Down
2 changes: 2 additions & 0 deletions packages/bluesky/lib/bluesky.dart
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ export 'package:atproto/atproto.dart'
$CreateActionCopyWith,
UpdateAction,
$UpdateActionCopyWith,
SigningKey,
$SigningKeyCopyWith,
RepoLatestCommit,
$RepoLatestCommitCopyWith,
RepoCommits,
Expand Down
1 change: 1 addition & 0 deletions website/docs/api_support_matrix.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ See more details about **[atproto](https://pub.dev/packages/atproto)** in **[Pac
| [POST com.atproto.server.requestEmailConfirmation](https://github.com/bluesky-social/atproto/blob/main/lexicons/com/atproto/server/requestEmailConfirmation.json) | [requestEmailConfirmation](https://pub.dev/documentation/atproto/latest/atproto/ServersService/requestEmailConfirmation.html) | βœ… | ❌ |
| [POST com.atproto.server.confirmEmail](https://github.com/bluesky-social/atproto/blob/main/lexicons/com/atproto/server/confirmEmail.json) | [confirmEmail](https://pub.dev/documentation/atproto/latest/atproto/ServersService/confirmEmail.html) | βœ… | ❌ |
| [POST com.atproto.server.updateEmail](https://github.com/bluesky-social/atproto/blob/main/lexicons/com/atproto/server/updateEmail.json) | [updateEmail](https://pub.dev/documentation/atproto/latest/atproto/ServersService/updateEmail.html) | βœ… | ❌ |
| [POST com.atproto.server.reserveSigningKey](https://github.com/bluesky-social/atproto/blob/main/lexicons/com/atproto/server/reserveSigningKey.json) | [createSigningKey](https://pub.dev/documentation/atproto/latest/atproto/createSigningKey.html) | βœ… | ❌ |

### [Identities Service](https://pub.dev/documentation/atproto/latest/atproto/IdentitiesService-class.html)

Expand Down

0 comments on commit f103639

Please sign in to comment.