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
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,26 @@
#include "Immutable/Misc/ImtblLogging.h"


UImtblConnectionAsyncActions* UImtblConnectionAsyncActions::Login(UObject* WorldContextObject, EImmutableDirectLoginMethod DirectLoginMethod)
UImtblConnectionAsyncActions* UImtblConnectionAsyncActions::Login(UObject* WorldContextObject, const FImmutableDirectLoginOptions& DirectLoginOptions)
{
UImtblConnectionAsyncActions* PassportInitBlueprintNode = NewObject<UImtblConnectionAsyncActions>();

PassportInitBlueprintNode->WorldContextObject = WorldContextObject;
PassportInitBlueprintNode->bIsConnectImx = false;
PassportInitBlueprintNode->bIsPKCE = true;
PassportInitBlueprintNode->DirectLoginMethod = DirectLoginMethod;
PassportInitBlueprintNode->DirectLoginOptions = DirectLoginOptions;

return PassportInitBlueprintNode;
}

UImtblConnectionAsyncActions* UImtblConnectionAsyncActions::ConnectImx(UObject* WorldContextObject, EImmutableDirectLoginMethod DirectLoginMethod)
UImtblConnectionAsyncActions* UImtblConnectionAsyncActions::ConnectImx(UObject* WorldContextObject, const FImmutableDirectLoginOptions& DirectLoginOptions)
{
UImtblConnectionAsyncActions* PassportInitBlueprintNode = NewObject<UImtblConnectionAsyncActions>();

PassportInitBlueprintNode->WorldContextObject = WorldContextObject;
PassportInitBlueprintNode->bIsConnectImx = true;
PassportInitBlueprintNode->bIsPKCE = true;
PassportInitBlueprintNode->DirectLoginMethod = DirectLoginMethod;
PassportInitBlueprintNode->DirectLoginOptions = DirectLoginOptions;

return PassportInitBlueprintNode;
}
Expand Down Expand Up @@ -54,7 +54,7 @@ void UImtblConnectionAsyncActions::DoConnect(TWeakObjectPtr<UImtblJSConnector> J
if (bIsPKCE)
{
#if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC | PLATFORM_WINDOWS
Passport->Connect(bIsConnectImx, UImmutablePassport::FImtblPassportResponseDelegate::CreateUObject(this, &UImtblConnectionAsyncActions::OnConnect), DirectLoginMethod);
Passport->Connect(bIsConnectImx, UImmutablePassport::FImtblPassportResponseDelegate::CreateUObject(this, &UImtblConnectionAsyncActions::OnConnect), DirectLoginOptions);
#endif
}
}
Expand Down
22 changes: 20 additions & 2 deletions Source/Immutable/Private/Immutable/ImmutableDataTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ FString FImmutablePassportInitData::ToJsonString() const
return OutString;
}



FString FImmutablePassportZkEvmRequestAccountsData::ToJsonString() const
{
FString OutString;
Expand Down Expand Up @@ -97,4 +95,24 @@ void UImmutablePKCEData::Reset()
#if PLATFORM_WINDOWS
UImmutablePKCEWindows::Reset(this);
#endif
}

bool FImmutableDirectLoginOptions::IsEmailValid() const
{
return DirectLoginMethod == EImmutableDirectLoginMethod::Email && !Email.IsEmpty();
}

TSharedPtr<FJsonObject> FImmutableDirectLoginOptions::ToJsonObject() const
{
TSharedPtr<FJsonObject> JsonObject = MakeShareable(new FJsonObject);
JsonObject->SetStringField(TEXT("directLoginMethod"), StaticEnum<EImmutableDirectLoginMethod>()->GetNameStringByValue(static_cast<int64>(DirectLoginMethod)).ToLower());

if (IsEmailValid())
{
JsonObject->SetStringField(TEXT("email"), Email);
}

JsonObject->SetStringField(TEXT("marketingConsentStatus"), StaticEnum<EImmutableMarketingConsentStatus>()->GetNameStringByValue(static_cast<int64>(MarketingConsentStatus)).ToLower());

return JsonObject;
}
40 changes: 18 additions & 22 deletions Source/Immutable/Private/Immutable/ImmutablePassport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ void UImmutablePassport::Initialize(const FImtblPassportResponseDelegate& Respon
}

#if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC | PLATFORM_WINDOWS
void UImmutablePassport::Connect(bool IsConnectImx, const FImtblPassportResponseDelegate& ResponseDelegate, EImmutableDirectLoginMethod DirectLoginMethod)
void UImmutablePassport::Connect(bool IsConnectImx, const FImtblPassportResponseDelegate& ResponseDelegate, const FImmutableDirectLoginOptions& DirectLoginOptions)
{
SetStateFlags(IPS_CONNECTING | IPS_PKCE);

Expand All @@ -109,31 +109,27 @@ void UImmutablePassport::Connect(bool IsConnectImx, const FImtblPassportResponse
PKCEResponseDelegate = ResponseDelegate;
Analytics->Track(IsConnectImx ? UImmutableAnalytics::EEventName::START_CONNECT_IMX_PKCE : UImmutableAnalytics::EEventName::START_LOGIN_PKCE);

FImmutableGetPKCEAuthUrlRequest PKCERequest;
PKCERequest.isConnectImx = IsConnectImx;
PKCERequest.directLoginMethod = DirectLoginMethod;
TSharedPtr<FJsonObject> RequestObject = MakeShareable(new FJsonObject);
RequestObject->SetBoolField(TEXT("isConnectImx"), IsConnectImx);

// Custom export callback to handle all enums to use lowercase
FJsonObjectConverter::CustomExportCallback CustomCallback;
CustomCallback.BindLambda([](FProperty* Property, const void* Value) -> TSharedPtr<FJsonValue>
TSharedPtr<FJsonObject> DirectLoginOptionsObject = DirectLoginOptions.ToJsonObject();
if (DirectLoginOptionsObject.IsValid())
{
if (FEnumProperty* EnumProperty = CastField<FEnumProperty>(Property))
{
int64 EnumValue = EnumProperty->GetUnderlyingProperty()->GetSignedIntPropertyValue(Value);

if (UEnum* Enum = EnumProperty->GetEnum())
{
FString EnumNameString = Enum->GetNameStringByValue(EnumValue);
return MakeShareable(new FJsonValueString(EnumNameString.ToLower()));
}
}

// Return null to use default serialization for non-enum properties
return TSharedPtr<FJsonValue>();
});
RequestObject->SetObjectField(TEXT("directLoginOptions"), DirectLoginOptionsObject);
}

// Convert to JSON string
FString PKCERequestJson;
FJsonObjectConverter::UStructToJsonObjectString(PKCERequest, PKCERequestJson, 0, 0, 0, &CustomCallback);
TSharedRef<TJsonWriter<>> Writer = TJsonWriterFactory<>::Create(&PKCERequestJson);
if (!FJsonSerializer::Serialize(RequestObject.ToSharedRef(), Writer))
{
IMTBL_ERR("Failed to serialize PKCE request to JSON");
FImmutablePassportResult Result;
Result.Success = false;
Result.Error = TEXT("Failed to serialize authentication request");
ResponseDelegate.ExecuteIfBound(Result);
return;
}

CallJS(ImmutablePassportAction::GetPKCEAuthUrl, PKCERequestJson, PKCEResponseDelegate, FImtblJSResponseDelegate::CreateUObject(this, &UImmutablePassport::OnGetAuthUrlResponse));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,23 @@ class IMMUTABLE_API UImtblConnectionAsyncActions : public UImtblBlueprintAsyncAc
* Log into Passport
*
* @param WorldContextObject World context
* @param DirectLoginMethod Direct login method to use for authentication (defaults to None for standard login page)
* @param DirectLoginOptions Direct login options for authentication (email, google, apple, facebook)
*
* @return A reference to the object represented by this node
*/
UFUNCTION(BlueprintCallable, meta = (WorldContext = "WorldContextObject", BlueprintInternalUseOnly = "true"), Category = "Immutable")
static UImtblConnectionAsyncActions* Login(UObject* WorldContextObject, EImmutableDirectLoginMethod DirectLoginMethod = EImmutableDirectLoginMethod::None);
static UImtblConnectionAsyncActions* Login(UObject* WorldContextObject, const FImmutableDirectLoginOptions& DirectLoginOptions);

/**
* Log into Passport, initialise the gamer's wallet and instantiate the IMX provider.
*
* @param WorldContextObject World context
* @param DirectLoginMethod Direct login method to use for authentication (defaults to None for standard login page)
* @param DirectLoginOptions Direct login options for authentication (email, google, apple, facebook)
*
* @return A reference to the object represented by this node
*/
UFUNCTION(BlueprintCallable, meta = (WorldContext = "WorldContextObject", BlueprintInternalUseOnly = "true"), Category = "Immutable")
static UImtblConnectionAsyncActions* ConnectImx(UObject* WorldContextObject, EImmutableDirectLoginMethod DirectLoginMethod = EImmutableDirectLoginMethod::None);

static UImtblConnectionAsyncActions* ConnectImx(UObject* WorldContextObject, const FImmutableDirectLoginOptions& DirectLoginOptions);

virtual void Activate() override;

Expand All @@ -56,5 +55,5 @@ class IMMUTABLE_API UImtblConnectionAsyncActions : public UImtblBlueprintAsyncAc
bool bUseCachedSession = false;
bool bIsConnectImx = false;
bool bIsPKCE = false;
EImmutableDirectLoginMethod DirectLoginMethod = EImmutableDirectLoginMethod::None;
FImmutableDirectLoginOptions DirectLoginOptions;
};
46 changes: 40 additions & 6 deletions Source/Immutable/Public/Immutable/ImmutableDataTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,54 @@ DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FImmutableDeepLinkDynamicMulticastDe
// This hardcoded value will be updated by a workflow during the release process.
#define ENGINE_SDK_VERSION TEXT("1.11.0")

/**
* Enum representing marketing consent status for authentication
*/
UENUM(BlueprintType)
enum class EImmutableMarketingConsentStatus : uint8
{
Opted_In,
Unsubscribed
};

/**
* Enum representing direct login methods for authentication providers
*/
UENUM(BlueprintType)
enum class EImmutableDirectLoginMethod : uint8
{
None,
Email,
Google,
Apple,
Facebook
};

/**
* Structure representing direct login options for authentication
* Can be used for social login (google, apple, facebook) or email login
*/
USTRUCT(BlueprintType)
struct IMMUTABLE_API FImmutableDirectLoginOptions
{
GENERATED_BODY()

bool IsEmailValid() const;

TSharedPtr<FJsonObject> ToJsonObject() const;

/** Direct login method for authentication */
UPROPERTY(EditAnywhere, BlueprintReadWrite)
EImmutableDirectLoginMethod DirectLoginMethod = EImmutableDirectLoginMethod::Email;

/** Email address for email-based authentication (only used when DirectLoginMethod is Email) */
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FString Email;

/** Marketing consent status for authentication (defaults to opted in) */
UPROPERTY(EditAnywhere, BlueprintReadWrite)
EImmutableMarketingConsentStatus MarketingConsentStatus = EImmutableMarketingConsentStatus::Opted_In;
};

USTRUCT()
struct FImmutableEngineVersionData
{
Expand Down Expand Up @@ -145,8 +181,6 @@ struct IMMUTABLE_API FImmutablePassportZkEvmGetBalanceData
FString ToJsonString() const;
};



USTRUCT()
struct FImmutablePassportConnectData
{
Expand All @@ -171,9 +205,9 @@ struct IMMUTABLE_API FImmutableGetPKCEAuthUrlRequest
UPROPERTY()
bool isConnectImx = false;

/** Direct login method to use for authentication */
/** Direct login options for authentication */
UPROPERTY()
EImmutableDirectLoginMethod directLoginMethod = EImmutableDirectLoginMethod::None;
FImmutableDirectLoginOptions directLoginOptions;
};

USTRUCT()
Expand Down Expand Up @@ -350,4 +384,4 @@ class IMMUTABLE_API UImmutablePKCEData : public UObject
* Handle for the ticker delegate that periodically checks for incoming deep links
*/
FTSTicker::FDelegateHandle TickDelegateHandle;
};
};
4 changes: 2 additions & 2 deletions Source/Immutable/Public/Immutable/ImmutablePassport.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,9 @@ class IMMUTABLE_API UImmutablePassport : public UObject
* @param IsConnectImx If true, player will connect to Immutable X after logging in.
* Else, just perform the login without connecting to Immutable X.
* @param ResponseDelegate Callback delegate.
* @param DirectLoginMethod Direct login method to use for authentication (defaults to None for standard login page).
* @param DirectLoginOptions Direct login options for authentication (email, google, apple, facebook).
*/
void Connect(bool IsConnectImx, const FImtblPassportResponseDelegate& ResponseDelegate, EImmutableDirectLoginMethod DirectLoginMethod = EImmutableDirectLoginMethod::None);
void Connect(bool IsConnectImx, const FImtblPassportResponseDelegate& ResponseDelegate, const FImmutableDirectLoginOptions& DirectLoginOptions);
#endif

/**
Expand Down
4 changes: 2 additions & 2 deletions Web/index.js

Large diffs are not rendered by default.

Loading