Commit b74ae0c6 authored by Yousef Sameh's avatar Yousef Sameh

User model and table

parent e22f21a1
using UnityEngine;
/// <summary>
/// Generic singleton base class for MonoBehaviours
/// Usage: public class MyManager : Singleton<MyManager> { }
/// </summary>
public abstract class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
private static T instance;
public static T Instance
{
get
{
if (instance == null)
{
instance = FindObjectOfType<T>();
if (instance == null)
{
var go = new GameObject($"[Singleton] {typeof(T).Name}");
instance = go.AddComponent<T>();
}
}
return instance;
}
}
protected virtual void Awake()
{
if (instance != null && instance != this)
{
Destroy(gameObject);
return;
}
instance = this as T;
DontDestroyOnLoad(gameObject);
}
protected virtual void OnDestroy()
{
if (instance == this)
{
instance = null;
}
}
}
fileFormatVersion: 2
guid: ba464edb6659288189be15ecd083eb20
\ No newline at end of file
fileFormatVersion: 2
guid: c8fbf5ee79d8c6c3a911a303ee221e9c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
......@@ -41,12 +41,13 @@ public class SupabaseAuthentication : MonoBehaviour
}
public async UniTask<OneOf<Success, string>> SignUp(string username, string password)
public async UniTask<OneOf<Success, string>> SignUp(string username, string password, string displayName)
{
try
{
IsLoading = true;
await supabaseManager.Supabase()!.Auth.SignUp(username, password);
await UserService.Instance.CreateUserProfile(displayName);
return new Success();
}
......
fileFormatVersion: 2
guid: 12565bb0d871532dc9fd797710d7d608
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
......@@ -11,7 +11,7 @@ public class SessionListener : MonoBehaviour
[SerializeField] private UnityEvent LoggedIn;
[SerializeField] private UnityEvent LoggedOut;
public void UnityAuthListener(IGotrueClient<User, Session> sender, Constants.AuthState newState)
public void UnityAuthListener(IGotrueClient<Supabase.Gotrue.User, Session> sender, Constants.AuthState newState)
{
switch (newState)
{
......
......@@ -5,10 +5,8 @@ using TMPro;
using UnityEngine;
using Client = Supabase.Client;
public class SupabaseManager : MonoBehaviour
public class SupabaseManager : Singleton<SupabaseManager>
{
public static SupabaseManager Instance { private set; get; }
[SerializeField] private SessionListener SessionListener;
public TMP_Text ErrorText = null!;
......@@ -23,11 +21,6 @@ public class SupabaseManager : MonoBehaviour
private async void Start()
{
if (Instance != null)
Destroy(Instance);
Instance = this;
SupabaseOptions options = new();
// We set an option to refresh the token automatically using a background thread.
options.AutoRefreshToken = true;
......
fileFormatVersion: 2
guid: f8a079eba06894c38a9fcf093076c8b1
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using OneOf;
// enable support for records
namespace System.Runtime.CompilerServices
{
internal static class IsExternalInit
{
}
}
public record UserResult(User User);
public record ErrorResult(string Message);
public static class Result
{
public static OneOf<UserResult, ErrorResult> Success(User user)
=> new UserResult(user);
public static OneOf<UserResult, ErrorResult> Failure(string message)
=> new ErrorResult(message);
}
fileFormatVersion: 2
guid: 983e0490bacfc7305b7d90de5893b3f6
\ No newline at end of file
using Cysharp.Threading.Tasks;
using OneOf;
using Supabase;
using System;
public class UserService : Singleton<UserService>
{
private Client supabase;
protected override void Awake()
{
base.Awake();
supabase = SupabaseManager.Instance.Supabase();
}
public async UniTask<OneOf<UserResult, ErrorResult>> CreateUserProfile(
string displayName,
string? avatarUrl = null)
{
try
{
var authUser = supabase.Auth.CurrentUser;
if (authUser == null)
return new ErrorResult("Not authenticated");
var user = new User
{
Id = authUser.Id.ToString(),
DisplayName = displayName,
AvatarUrl = avatarUrl,
Rank = UserRank.Normal,
Points = 0,
CreatedAt = DateTime.UtcNow,
UpdatedAt = DateTime.UtcNow
};
await supabase.From<User>().Insert(user);
return new UserResult(user);
}
catch (Exception ex)
{
return new ErrorResult(ex.Message);
}
}
public async UniTask<OneOf<UserResult, ErrorResult>> GetCurrentUser()
{
try
{
var authUser = supabase.Auth.CurrentUser;
if (authUser == null)
return new ErrorResult("Not authenticated");
var response = await supabase
.From<User>()
.Where(x => x.Id == authUser.Id.ToString())
.Single();
if (response == null)
return new ErrorResult("User not found");
return new UserResult(response);
}
catch (Exception ex)
{
return new ErrorResult(ex.Message);
}
}
public async UniTask<OneOf<UserResult, ErrorResult>> GetUserById(string userId)
{
try
{
var response = await supabase
.From<User>()
.Where(x => x.Id == userId)
.Single();
if (response == null)
return new ErrorResult("User not found");
return new UserResult(response);
}
catch (Exception ex)
{
return new ErrorResult(ex.Message);
}
}
public async UniTask<OneOf<UserResult, ErrorResult>> UpdateDisplayName(string newDisplayName)
{
try
{
var authUser = supabase.Auth.CurrentUser;
if (authUser == null)
return new ErrorResult("Not authenticated");
await supabase
.From<User>()
.Where(x => x.Id == authUser.Id.ToString())
.Update(new User { DisplayName = newDisplayName });
return await GetCurrentUser();
}
catch (Exception ex)
{
return new ErrorResult(ex.Message);
}
}
public async UniTask<OneOf<UserResult, ErrorResult>> UpdateAvatar(string avatarUrl)
{
try
{
var authUser = supabase.Auth.CurrentUser;
if (authUser == null)
return new ErrorResult("Not authenticated");
await supabase
.From<User>()
.Where(x => x.Id == authUser.Id.ToString())
.Update(new User { AvatarUrl = avatarUrl });
return await GetCurrentUser();
}
catch (Exception ex)
{
return new ErrorResult(ex.Message);
}
}
public async UniTask<OneOf<UserResult, ErrorResult>> DeleteCurrentUser()
{
try
{
var authUser = supabase.Auth.CurrentUser;
if (authUser == null)
return new ErrorResult("Not authenticated");
await supabase
.From<User>()
.Where(x => x.Id == authUser.Id.ToString())
.Delete();
return new UserResult(null);
}
catch (Exception ex)
{
return new ErrorResult(ex.Message);
}
}
}
fileFormatVersion: 2
guid: ef6d4039bfd054597970b347c242a7a1
\ No newline at end of file
fileFormatVersion: 2
guid: b2012fb9921fa45d7b756aba5b9d8d5e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
using System;
using Supabase.Postgrest.Attributes;
using Supabase.Postgrest.Models;
public enum UserRank
{
Normal,
Geek,
Master,
Olympian
}
[Table("users")]
public class User : BaseModel
{
[PrimaryKey("id")]
public string Id { get; set; }
[Column("display_name")]
public string DisplayName { get; set; }
[Column("avatar_url")]
public string? AvatarUrl { get; set; }
[Column("rank")]
public UserRank Rank { get; set; } = UserRank.Normal;
[Column("points")]
public int Points { get; set; } = 0;
[Column("created_at")]
public DateTime CreatedAt { get; set; }
[Column("updated_at")]
public DateTime UpdatedAt { get; set; }
}
fileFormatVersion: 2
guid: 531a6126670858098a085ffad5761df1
\ No newline at end of file
......@@ -14,6 +14,6 @@ public class SupabaseTester : MonoBehaviour
[ContextMenu("Sign Up")]
public void SignUp()
{
supabaseAuthentication.SignUp("test@gmail.com", "test098");
supabaseAuthentication.SignUp("test@gmail.com", "test098", "p0wer");
}
}
This diff is collapsed.
fileFormatVersion: 2
guid: bc43cd6fc169642cab47171d93d9b220
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
<Solution>
<Project Path="Assembly-CSharp.csproj" />
<Project Path="LightSide.UniText.csproj" />
<Project Path="UniTask.csproj" />
<Project Path="Unity.RenderPipelines.Universal.Runtime.csproj" />
<Project Path="FlatKit.Utils.Editor.csproj" />
<Project Path="UniTask.Linq.csproj" />
<Project Path="ExternAttributes.Editor.csproj" />
<Project Path="LightSide.UniText.Editor.csproj" />
<Project Path="NuGetForUnity.csproj" />
<Project Path="Assembly-CSharp-firstpass.csproj" />
<Project Path="Assembly-CSharp-Editor.csproj" />
<Project Path="UniTask.TextMeshPro.csproj" />
<Project Path="UniTask.Editor.csproj" />
<Project Path="UniTask.Addressables.csproj" />
<Project Path="UniTask.DOTween.csproj" />
</Solution>
......@@ -9,34 +9,34 @@ EditorUserSettings:
value: 18134705175a055722080a3115371d4a0d55006876786860616b0471b8b2656eacb72ba5a52a362c3c0ee63201181433fe3e101bf3250b06144ca74c24f1190708e016c213c61a52f91c12cac80fd8edd298e1e4d1fde2cacddeacbcc1fee7eef0e3b6faa69af9ceaeaaec81a6d2c2c8c8c4b2e5dfd5ccd3f8cf
flags: 0
RecentlyUsedSceneGuid-0:
value: 52530450570659030f0b0d751577064441154128742b23692f7d4a61e0b5623d
value: 5a08575f5207595a0f5d59741173094444164f7d7d2a23317c7a4465bbe1646d
flags: 0
RecentlyUsedSceneGuid-1:
value: 5a08575f5207595a0f5d59741173094444164f7d7d2a23317c7a4465bbe1646d
value: 0003525055055d020e0b0a7216755d444215417e787d27362e2f4866b2e1323e
flags: 0
RecentlyUsedSceneGuid-2:
value: 0003525055055d020e0b0a7216755d444215417e787d27362e2f4866b2e1323e
value: 000305555d01595a5c5d082143700911134e1c737b2b7763782c1962b5b3666d
flags: 0
RecentlyUsedSceneGuid-3:
value: 000305555d01595a5c5d082143700911134e1c737b2b7763782c1962b5b3666d
value: 5a550c5151505d080f5a5b21442206444e161d7e2f2c7735297d1f64bab76c61
flags: 0
RecentlyUsedSceneGuid-4:
value: 5a550c5151505d080f5a5b21442206444e161d7e2f2c7735297d1f64bab76c61
value: 5301045250005d095b5e082315710e48474f1a787d2c25622b7e186bb5b4646f
flags: 0
RecentlyUsedSceneGuid-5:
value: 5301045250005d095b5e082315710e48474f1a787d2c25622b7e186bb5b4646f
value: 54035150530d5d580f580e7b16220f4415154e737b2b75367a711f6be0b66c61
flags: 0
RecentlyUsedSceneGuid-6:
value: 54035150530d5d580f580e7b16220f4415154e737b2b75367a711f6be0b66c61
value: 5304575f5c0c51035d5a5e771271594417154e7c2d7b70647b7b4c35bbe1646d
flags: 0
RecentlyUsedSceneGuid-7:
value: 5304575f5c0c51035d5a5e771271594417154e7c2d7b70647b7b4c35bbe1646d
value: 5701055506000a030f5c542744260844404f4d73797975367c2c1e6ab7e2653d
flags: 0
RecentlyUsedSceneGuid-8:
value: 5701055506000a030f5c542744260844404f4d73797975367c2c1e6ab7e2653d
value: 5200570406560d58095e5c75432609124f154e737a2d2432787e4b62b4e1366a
flags: 0
RecentlyUsedSceneGuid-9:
value: 5200570406560d58095e5c75432609124f154e737a2d2432787e4b62b4e1366a
value: 0152005506515f5d0e5f5a7b46770d1317154c7d7d7f7734747a196ae0b26668
flags: 0
UnityEditor.ShaderGraph.Blackboard:
value: 18135939215a0a5004000b0e15254b524c030a3f2964643d120d1230e9e93a3fd6e826abbd2e2d293c4ead313b08042de6030a0afa240c0d020be94c4ba75e435d8715fa32c70d15d11612dacc11fee5d3c5d1fe9ab1bf968e93e2ffcbc3e7e2f0b3ffe0e8b0be9af8ffaeffff8e85dd8390e3949c8899daa7
......
......@@ -24,7 +24,7 @@ MonoBehaviour:
m_MinSize: {x: 300, y: 112}
m_MaxSize: {x: 24288, y: 16192}
vertical: 0
controlID: 3488
controlID: 1397
draggingID: 0
--- !u!114 &2
MonoBehaviour:
......@@ -50,7 +50,7 @@ MonoBehaviour:
x: 355
y: 61
width: 1097
height: 508
height: 652
m_SerializedDataModeController:
m_DataMode: 0
m_PreferredDataMode: 0
......@@ -107,22 +107,22 @@ MonoBehaviour:
x: 0
y: 21
width: 1097
height: 487
m_Scale: {x: 0.20291667, y: 0.20291667}
m_Translation: {x: 548.5, y: 243.5}
height: 631
m_Scale: {x: 0.26291665, y: 0.26291665}
m_Translation: {x: 548.5, y: 315.5}
m_MarginLeft: 0
m_MarginRight: 0
m_MarginTop: 0
m_MarginBottom: 0
m_LastShownAreaInsideMargins:
serializedVersion: 2
x: -2703.08
x: -2086.2124
y: -1200
width: 5406.16
width: 4172.425
height: 2400
m_MinimalGUI: 1
m_defaultScale: 0.20291667
m_LastWindowPixelSize: {x: 1097, y: 508}
m_defaultScale: 0.26291665
m_LastWindowPixelSize: {x: 1097, y: 652}
m_ClearInEditMode: 1
m_NoCameraWarning: 1
m_LowResolutionForAspectRatios: 01000000000000000000
......@@ -153,7 +153,7 @@ MonoBehaviour:
m_MinSize: {x: 200, y: 112}
m_MaxSize: {x: 16192, y: 16192}
vertical: 1
controlID: 3489
controlID: 1398
draggingID: 0
--- !u!114 &4
MonoBehaviour:
......@@ -175,11 +175,11 @@ MonoBehaviour:
x: 0
y: 0
width: 1454
height: 534
height: 678
m_MinSize: {x: 200, y: 56}
m_MaxSize: {x: 16192, y: 8096}
vertical: 0
controlID: 3490
controlID: 1399
draggingID: 0
--- !u!114 &5
MonoBehaviour:
......@@ -199,7 +199,7 @@ MonoBehaviour:
x: 0
y: 0
width: 355
height: 534
height: 678
m_MinSize: {x: 201, y: 226}
m_MaxSize: {x: 4001, y: 4026}
m_ActualView: {fileID: 6}
......@@ -231,7 +231,7 @@ MonoBehaviour:
x: 0
y: 61
width: 354
height: 508
height: 652
m_SerializedDataModeController:
m_DataMode: 0
m_PreferredDataMode: 0
......@@ -249,15 +249,10 @@ MonoBehaviour:
m_TreeViewState:
scrollPos: {x: 0, y: 0}
m_SelectedIDs:
- m_Data: 57490
- m_Data: 31262
m_LastClickedID:
m_Data: 0
m_ExpandedIDs:
- m_Data: -24928
- m_Data: -17046
- m_Data: -8322
- m_Data: -8108
- m_Data: -7906
- m_Data: -1342
m_RenameOverlay:
m_UserAcceptedRename: 0
......@@ -302,9 +297,9 @@ MonoBehaviour:
x: 355
y: 0
width: 1099
height: 534
m_MinSize: {x: 202, y: 226}
m_MaxSize: {x: 4002, y: 4026}
height: 678
m_MinSize: {x: 200, y: 200}
m_MaxSize: {x: 4000, y: 4000}
m_ActualView: {fileID: 2}
m_Panes:
- {fileID: 8}
......@@ -335,7 +330,7 @@ MonoBehaviour:
x: 355
y: 61
width: 1097
height: 508
height: 652
m_SerializedDataModeController:
m_DataMode: 0
m_PreferredDataMode: 0
......@@ -1024,9 +1019,9 @@ MonoBehaviour:
m_Position:
serializedVersion: 2
x: 0
y: 534
y: 678
width: 1454
height: 449
height: 305
m_MinSize: {x: 231, y: 276}
m_MaxSize: {x: 10001, y: 10026}
m_ActualView: {fileID: 10}
......@@ -1059,9 +1054,9 @@ MonoBehaviour:
m_Pos:
serializedVersion: 2
x: 0
y: 595
y: 739
width: 1453
height: 423
height: 279
m_SerializedDataModeController:
m_DataMode: 0
m_PreferredDataMode: 0
......@@ -1086,7 +1081,7 @@ MonoBehaviour:
m_SkipHidden: 0
m_SearchArea: 1
m_Folders:
- Assets/Scenes
- Assets/App/Infrastructure/User
m_Globs: []
m_ProductIds:
m_AnyWithAssetOrigin: 0
......@@ -1096,25 +1091,23 @@ MonoBehaviour:
m_ViewMode: 1
m_StartGridSize: 96
m_LastFolders:
- Assets/Scenes
- Assets/App/Infrastructure/User
m_LastFoldersGridSize: 96
m_LastProjectPath: /home/p0wer/development/ssbookminigames/My project
m_LockTracker:
m_IsLocked: 0
m_LastLocalAssetsSearchArea: 1
m_FolderTreeState:
scrollPos: {x: 0, y: 157}
scrollPos: {x: 0, y: 79}
m_SelectedIDs:
- m_Data: 55598
- m_Data: 55232
m_LastClickedID:
m_Data: 55598
m_Data: 55232
m_ExpandedIDs:
- m_Data: 0
- m_Data: 55228
- m_Data: 55592
- m_Data: 55598
- m_Data: 57020
- m_Data: 57310
- m_Data: 54850
- m_Data: 54982
- m_Data: 55188
- m_Data: 1000000000
- m_Data: 2147483647
m_RenameOverlay:
......@@ -1149,10 +1142,7 @@ MonoBehaviour:
m_Data: 0
m_ExpandedIDs:
- m_Data: 0
- m_Data: 55228
- m_Data: 55592
- m_Data: 57020
- m_Data: 57310
- m_Data: 54850
- m_Data: 1000000000
- m_Data: 2147483647
m_RenameOverlay:
......@@ -1182,9 +1172,9 @@ MonoBehaviour:
m_ResourceFile:
m_ListAreaState:
m_SelectedInstanceIDs:
- m_Data: 57490
m_LastClickedInstanceID: 57490
m_HadKeyboardFocusLastEvent: 1
- m_Data: 31262
m_LastClickedInstanceID: 31262
m_HadKeyboardFocusLastEvent: 0
m_ExpandedInstanceIDs:
- m_Data: 46526
- m_Data: 61214
......@@ -1240,9 +1230,9 @@ MonoBehaviour:
m_Pos:
serializedVersion: 2
x: 0
y: 595
y: 739
width: 1453
height: 423
height: 279
m_SerializedDataModeController:
m_DataMode: 0
m_PreferredDataMode: 0
......@@ -1371,8 +1361,8 @@ MonoBehaviour:
y: 0
width: 450
height: 983
m_MinSize: {x: 276, y: 76}
m_MaxSize: {x: 4001, y: 4026}
m_MinSize: {x: 275, y: 50}
m_MaxSize: {x: 4000, y: 4000}
m_ActualView: {fileID: 15}
m_Panes:
- {fileID: 15}
......
......@@ -1391,7 +1391,7 @@ MonoBehaviour:
m_AudioPlay: 0
m_DebugDrawModesUseInteractiveLightBakingData: 0
m_Position:
m_Target: {x: -0.46512085, y: 5.2452955, z: -1.1591719}
m_Target: {x: 0.3170178, y: 0.01101324, z: -0.0036561592}
speed: 2
m_Value: {x: -0.46512085, y: 5.2452955, z: -1.1591719}
m_RenderMode: 0
......@@ -1443,7 +1443,7 @@ MonoBehaviour:
speed: 2
m_Value: {x: 0, y: 0, z: 0, w: 1}
m_Size:
m_Target: 5.9171705
m_Target: 10.365613
speed: 2
m_Value: 5.9171705
m_Ortho:
......@@ -1552,7 +1552,7 @@ MonoBehaviour:
m_Data: 55710
m_ExpandedIDs:
- m_Data: 0
- m_Data: 55228
- m_Data: 54850
m_RenameOverlay:
m_UserAcceptedRename: 0
m_Name:
......@@ -1585,7 +1585,7 @@ MonoBehaviour:
m_Data: 0
m_ExpandedIDs:
- m_Data: 0
- m_Data: 55228
- m_Data: 54850
m_RenameOverlay:
m_UserAcceptedRename: 0
m_Name:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment