-
Notifications
You must be signed in to change notification settings - Fork 33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add seperate Respone Schema for 2FA #352
base: main
Are you sure you want to change the base?
Add seperate Respone Schema for 2FA #352
Conversation
from #241:
|
Seen that, but i figured that the latest Rust generator is able to do this, it might be worth a try to bump the other languages aswell and see if that functionality exists. |
Rust is a really, really powerful language when it comes to serialization and type constructs. |
Ok, ill just try the python one and see if it works :3 |
Also it would be interesting, if rust supports this without my manual patch or not. |
I checked TS, Python and Rust, all of them can deal with the This indicates to me that there is at least baseline support for this. |
List of generators that are documented to not work with oneOf: |
Not sure what is up with the docs, but java for example generates this code, which looks pretty functional to me: @Override
public GetCurrentUser200Response read(JsonReader in) throws IOException {
Object deserialized = null;
JsonElement jsonElement = elementAdapter.read(in);
int match = 0;
ArrayList<String> errorMessages = new ArrayList<>();
TypeAdapter actualAdapter = elementAdapter;
// deserialize CurrentUser
try {
// validate the JSON object to see if any exception is thrown
CurrentUser.validateJsonElement(jsonElement);
actualAdapter = adapterCurrentUser;
match++;
log.log(Level.FINER, "Input data matches schema 'CurrentUser'");
} catch (Exception e) {
// deserialization failed, continue
errorMessages.add(String.format("Deserialization for CurrentUser failed with `%s`.", e.getMessage()));
log.log(Level.FINER, "Input data does not match schema 'CurrentUser'", e);
}
// deserialize RequiresTwoFactorAuth
try {
// validate the JSON object to see if any exception is thrown
RequiresTwoFactorAuth.validateJsonElement(jsonElement);
actualAdapter = adapterRequiresTwoFactorAuth;
match++;
log.log(Level.FINER, "Input data matches schema 'RequiresTwoFactorAuth'");
} catch (Exception e) {
// deserialization failed, continue
errorMessages.add(String.format("Deserialization for RequiresTwoFactorAuth failed with `%s`.", e.getMessage()));
log.log(Level.FINER, "Input data does not match schema 'RequiresTwoFactorAuth'", e);
}
if (match == 1) {
GetCurrentUser200Response ret = new GetCurrentUser200Response();
ret.setActualInstance(actualAdapter.fromJsonTree(jsonElement));
return ret;
}
throw new IOException(String.format("Failed deserialization for GetCurrentUser200Response: %d classes match result, expected 1. Detailed failure message for oneOf schemas: %s. JSON: %s", match, errorMessages, jsonElement.toString()));
}
}.nullSafe(); Also the javascript library is generated with the typescript generator which seems also seems to say it does not support it, but generates these types just fine: export type GetCurrentUser200Response = CurrentUser | RequiresTwoFactorAuth; To be fair idk what to make of this. |
We rely on the following generators:
Out of these, according to documentation, Only rust & dart-dio support |
|
This is what got generated: GetCurrentUser200Response({
required this.acceptedTOSVersion,
this.acceptedPrivacyVersion,
this.accountDeletionDate,
this.accountDeletionLog,
this.activeFriends,
required this.allowAvatarCopying,
this.badges,
required this.bio,
required this.bioLinks,
required this.currentAvatar,
required this.currentAvatarAssetUrl,
required this.currentAvatarImageUrl,
required this.currentAvatarThumbnailImageUrl,
required this.currentAvatarTags,
required this.dateJoined,
required this.developerType,
required this.displayName,
required this.emailVerified,
this.fallbackAvatar,
required this.friendGroupNames,
required this.friendKey,
required this.friends,
required this.hasBirthday,
this.hideContentFilterSettings,
this.userLanguage,
this.userLanguageCode,
required this.hasEmail,
required this.hasLoggedInFromClient,
required this.hasPendingEmail,
required this.homeLocation,
required this.id,
this.isBoopingEnabled = true,
this.isFriend = false,
this.lastActivity,
required this.lastLogin,
required this.lastMobile,
required this.lastPlatform,
required this.obfuscatedEmail,
required this.obfuscatedPendingEmail,
required this.oculusId,
this.googleId,
this.googleDetails,
this.picoId,
this.viveId,
this.offlineFriends,
this.onlineFriends,
required this.pastDisplayNames,
this.presence,
required this.profilePicOverride,
required this.profilePicOverrideThumbnail,
required this.pronouns,
required this.state,
required this.status,
required this.statusDescription,
required this.statusFirstTime,
required this.statusHistory,
required this.steamDetails,
required this.steamId,
required this.tags,
required this.twoFactorAuthEnabled,
this.twoFactorAuthEnabledDate,
required this.unsubscribe,
this.updatedAt,
required this.userIcon,
this.username,
required this.requiresTwoFactorAuth,
}); It looks like it just combined the fields of both possible responses which definitely will not work |
|
Yes my generate script updates the generator and I double checked it's using |
After long debugging I found the issue - the serilization library is not compatible with //
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// ignore_for_file: unused_element
import 'package:built_collection/built_collection.dart';
import 'package:vrchat_dart_generated/src/model/current_user.dart';
import 'package:vrchat_dart_generated/src/model/requires_two_factor_auth.dart';
import 'package:built_value/built_value.dart';
import 'package:built_value/serializer.dart';
import 'package:one_of/one_of.dart';
part 'get_current_user200_response.g.dart';
/// GetCurrentUser200Response
///
/// Properties:
/// * [id] - A users unique ID, usually in the form of `usr_c1644b5b-3ca4-45b4-97c6-a2a0de70d469`. Legacy players can have old IDs in the form of `8JoV9XEdpo`. The ID can never be changed.
/// * [requiresTwoFactorAuth]
@BuiltValue()
abstract class GetCurrentUser200Response implements Built<GetCurrentUser200Response, GetCurrentUser200ResponseBuilder> {
/// One Of [CurrentUser], [RequiresTwoFactorAuth]
OneOf get oneOf;
GetCurrentUser200Response._();
factory GetCurrentUser200Response([void updates(GetCurrentUser200ResponseBuilder b)]) = _$GetCurrentUser200Response;
@BuiltValueHook(initializeBuilder: true)
static void _defaults(GetCurrentUser200ResponseBuilder b) => b;
@BuiltValueSerializer(custom: true)
static Serializer<GetCurrentUser200Response> get serializer => _$GetCurrentUser200ResponseSerializer();
}
class _$GetCurrentUser200ResponseSerializer implements PrimitiveSerializer<GetCurrentUser200Response> {
@override
final Iterable<Type> types = const [GetCurrentUser200Response, _$GetCurrentUser200Response];
@override
final String wireName = r'GetCurrentUser200Response';
Iterable<Object?> _serializeProperties(
Serializers serializers,
GetCurrentUser200Response object, {
FullType specifiedType = FullType.unspecified,
}) sync* {
}
@override
Object serialize(
Serializers serializers,
GetCurrentUser200Response object, {
FullType specifiedType = FullType.unspecified,
}) {
final oneOf = object.oneOf;
return serializers.serialize(oneOf.value, specifiedType: FullType(oneOf.valueType))!;
}
@override
GetCurrentUser200Response deserialize(
Serializers serializers,
Object serialized, {
FullType specifiedType = FullType.unspecified,
}) {
final result = GetCurrentUser200ResponseBuilder();
Object? oneOfDataSrc;
final targetType = const FullType(OneOf, [FullType(CurrentUser), FullType(RequiresTwoFactorAuth), ]);
oneOfDataSrc = serialized;
result.oneOf = serializers.deserialize(oneOfDataSrc, specifiedType: targetType) as OneOf;
return result.build();
}
} I dont think its a reasonable ask to require a library change, but @Rexios80 let me know what you think. I have no idea how Dart works in detail, so this might not be as an impactful change as I believe. Regardless, as there is clearly inconsistent support for |
@0xkubectl The |
3553a0b
to
cc4a59f
Compare
I am almost positive the dart generator does not like this |
Lets keep this open until we know how to deal with different capabilities of generators. Edit: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Blocked by x-feature
.
Fixes #241 - Based on the work of @C0D3-M4513R from this PR
Adds a new Response schema that is able to encapsulate the 2FA challange/request. This is done via the
oneOf
operator on the CurrentUserLoginResponse.Here are the docs for
oneOf
: https://swagger.io/docs/specification/data-models/oneof-anyof-allof-not/I have tested this with the Rust Generator and have found no issues. I cannot say how other languages' generator would fare with this fix. If someone finds the time to test this on other languages, please go ahead :3
Tested languages
python @ 7.7.0
rust @ 7.7.0
typescript @ 7.7.0
csharp @ ?
java @ 7.7.0
dart @ ?