Skip to content
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

Split into admin and regular client. Minor doc fixes. Lock lang to 9.0 #66

Merged
merged 3 commits into from
Jun 23, 2023
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
107 changes: 107 additions & 0 deletions Gotrue/AdminClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Supabase.Gotrue.Interfaces;
namespace Supabase.Gotrue
{
/// <summary>
/// Admin client for interacting with the Gotrue API. Intended for use on
/// servers or other secure environments.
///
/// This client does NOT manage user sessions or track any other state.
/// </summary>
public class AdminClient : IGotrueAdminClient<User>
{
/// <summary>
/// The initialized client options.
/// </summary>
public ClientOptions Options { get; }

/// <summary>
/// Initialize the client with a service key.
/// </summary>
/// <param name="serviceKey">A valid JWT. Must be a full-access API key (e.g. 'service_role' or 'supabase_admin'). </param>
/// <param name="options"></param>
public AdminClient(string serviceKey, ClientOptions? options = null)
{
_serviceKey = serviceKey;

options ??= new ClientOptions();
Options = options;
_api = new Api(options.Url, options.Headers);
}

/// <summary>
/// Headers sent to the API on every request.
/// </summary>
public Func<Dictionary<string, string>>? GetHeaders
{
get => _api.GetHeaders;
set => _api.GetHeaders = value;
}

/// <summary>
/// The underlying API requests object that sends the requests
/// </summary>
private readonly IGotrueApi<User, Session> _api;

/// <summary>
/// The service key used to authenticate with the API.
/// </summary>
private readonly string _serviceKey;

/// <inheritdoc />
public Task<User?> GetUserById(string userId) => _api.GetUserById(_serviceKey, userId);

/// <inheritdoc />
public Task<User?> GetUser(string jwt) => _api.GetUser(jwt);

/// <inheritdoc />
public async Task<bool> InviteUserByEmail(string email)
{
var response = await _api.InviteUserByEmail(email, _serviceKey);
response.ResponseMessage?.EnsureSuccessStatusCode();
return true;
}

/// <inheritdoc />
public async Task<bool> DeleteUser(string uid)
{
var result = await _api.DeleteUser(uid, _serviceKey);
result.ResponseMessage?.EnsureSuccessStatusCode();
return true;
}

/// <inheritdoc />
public Task<User?> CreateUser(string email, string password, AdminUserAttributes? attributes = null)
{
attributes ??= new AdminUserAttributes();
attributes.Email = email;
attributes.Password = password;

return CreateUser(attributes);
}

/// <inheritdoc />
public Task<User?> CreateUser(AdminUserAttributes attributes) => _api.CreateUser(_serviceKey, attributes);

/// <inheritdoc />
public Task<UserList<User>?> ListUsers(string? filter = null, string? sortBy = null, Constants.SortOrder sortOrder = Constants.SortOrder.Descending, int? page = null, int? perPage = null)
{
return _api.ListUsers(_serviceKey, filter, sortBy, sortOrder, page, perPage);
}

/// <inheritdoc />
public Task<User?> UpdateUserById(string userId, AdminUserAttributes userData)
{
return _api.UpdateUserById(_serviceKey, userId, userData);
}

/// <inheritdoc />
public async Task<User?> Update(UserAttributes attributes)
{
var result = await _api.UpdateUser(_serviceKey, attributes);
return result;
}
}
}
99 changes: 10 additions & 89 deletions Gotrue/Client.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,14 @@ public void SetPersistence(IGotrueSessionPersistence<Session> persistence)
/// </summary>
public ClientOptions Options { get; }

/// <summary>
/// Get User details by JWT. Can be used to validate a JWT.
/// </summary>
/// <param name="jwt">A valid JWT. Must be a JWT that originates from a user.</param>
/// <returns></returns>
public Task<User?> GetUser(string jwt) => _api.GetUser(jwt);


/// <summary>
/// Notifies all listeners that the current user auth state has changed.
///
Expand Down Expand Up @@ -535,95 +543,8 @@ public async Task<bool> Reauthenticate()
return response.ResponseMessage?.IsSuccessStatusCode ?? false;
}

/// <summary>
/// Sends an invite email link to the specified email.
/// </summary>
/// <param name="email"></param>
/// <param name="jwt">this token needs role 'supabase_admin' or 'service_role'</param>
/// <returns></returns>
public async Task<bool> InviteUserByEmail(string email, string jwt)
{
var response = await _api.InviteUserByEmail(email, jwt);
response.ResponseMessage?.EnsureSuccessStatusCode();
return true;
}

/// <summary>
/// Deletes a User.
/// </summary>
/// <param name="uid"></param>
/// <param name="jwt">this token needs role 'supabase_admin' or 'service_role'</param>
/// <returns></returns>
public async Task<bool> DeleteUser(string uid, string jwt)
{
var result = await _api.DeleteUser(uid, jwt);
result.ResponseMessage?.EnsureSuccessStatusCode();
return true;
}

/// <summary>
/// Lists users
/// </summary>
/// <param name="jwt">A valid JWT. Must be a full-access API key (e.g. service_role key).</param>
/// <param name="filter">A string for example part of the email</param>
/// <param name="sortBy">Snake case string of the given key, currently only created_at is supported</param>
/// <param name="sortOrder">asc or desc, if null desc is used</param>
/// <param name="page">page to show for pagination</param>
/// <param name="perPage">items per page for pagination</param>
/// <returns></returns>
public Task<UserList<User>?> ListUsers(string jwt, string? filter = null, string? sortBy = null, SortOrder sortOrder = SortOrder.Descending, int? page = null,
int? perPage = null) => _api.ListUsers(jwt, filter, sortBy, sortOrder, page, perPage);

/// <summary>
/// Get User details by Id
/// </summary>
/// <param name="jwt">A valid JWT. Must be a full-access API key (e.g. service_role key).</param>
/// <param name="userId"></param>
/// <returns></returns>
public Task<User?> GetUserById(string jwt, string userId) => _api.GetUserById(jwt, userId);

/// <summary>
/// Get User details by JWT. Can be used to validate a JWT.
/// </summary>
/// <param name="jwt">A valid JWT. Must be a JWT that originates from a user.</param>
/// <returns></returns>
public Task<User?> GetUser(string jwt) => _api.GetUser(jwt);

/// <summary>
/// Create a user (as a service_role)
/// </summary>
/// <param name="jwt">A valid JWT. Must be a full-access API key (e.g. service_role key).</param>
/// <param name="email"></param>
/// <param name="password"></param>
/// <param name="attributes"></param>
/// <returns></returns>
public Task<User?> CreateUser(string jwt, string email, string password, AdminUserAttributes? attributes = null)
{
attributes ??= new AdminUserAttributes();
attributes.Email = email;
attributes.Password = password;

return CreateUser(jwt, attributes);
}


/// <summary>
/// Create a user (as a service_role)
/// </summary>
/// <param name="jwt">A valid JWT. Must be a full-access API key (e.g. service_role key).</param>
/// <param name="attributes"></param>
/// <returns></returns>
public Task<User?> CreateUser(string jwt, AdminUserAttributes attributes) => _api.CreateUser(jwt, attributes);

/// <summary>
/// Update user by Id
/// </summary>
/// <param name="jwt">A valid JWT. Must be a full-access API key (e.g. service_role key).</param>
/// <param name="userId"></param>
/// <param name="userData"></param>
/// <returns></returns>
public Task<User?> UpdateUserById(string jwt, string userId, AdminUserAttributes userData) => _api.UpdateUserById(jwt, userId, userData);



/// <summary>
/// Sends a reset request to an email address.
/// </summary>
Expand Down
1 change: 1 addition & 0 deletions Gotrue/Constants.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using Supabase.Core.Attributes;
#pragma warning disable CS1591

namespace Supabase.Gotrue
{
Expand Down
1 change: 1 addition & 0 deletions Gotrue/Exceptions/FailureReason.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ 400 when gte.Content.Contains("Email not confirmed") => UserEmailNotConfirmed,
400 when gte.Content.Contains("User already registered") => UserAlreadyRegistered,
400 when gte.Content.Contains("Invalid Refresh Token") => InvalidRefreshToken,
401 when gte.Content.Contains("This endpoint requires a Bearer token") => AdminTokenRequired,
401 when gte.Content.Contains("Invalid token") => AdminTokenRequired,
422 when gte.Content.Contains("Phone") && gte.Content.Contains("Email") => UserBadMultiple,
422 when gte.Content.Contains("email") && gte.Content.Contains("password") => UserBadMultiple,
422 when gte.Content.Contains("Phone") => UserBadPhoneNumber,
Expand Down
2 changes: 1 addition & 1 deletion Gotrue/Gotrue.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
</PropertyGroup>
<PropertyGroup>
<Nullable>enable</Nullable>
<LangVersion>latest</LangVersion>
<LangVersion>9.0</LangVersion>
<WarningsAsErrors>CS8600;CS8602;CS8603</WarningsAsErrors>
</PropertyGroup>
<PropertyGroup>
Expand Down
2 changes: 1 addition & 1 deletion Gotrue/Helpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
namespace Supabase.Gotrue
{
/// <summary>
/// Utility methods to assist with flow. Includes nonce generation & verification.
/// Utility methods to assist with flow. Includes nonce generation and verification.
/// </summary>
public static class Helpers
{
Expand Down
84 changes: 84 additions & 0 deletions Gotrue/Interfaces/IGotrueAdminClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
using System.Threading.Tasks;
using Supabase.Core.Interfaces;
namespace Supabase.Gotrue.Interfaces
{
/// <summary>
/// Interface for the Gotrue Admin Client (auth).
/// </summary>
/// <typeparam name="TUser"></typeparam>
public interface IGotrueAdminClient<TUser> : IGettableHeaders
where TUser : User
{
/// <summary>
/// Creates a user using the admin key (not the anonymous key).
/// Used in trusted server environments, not client apps.
/// </summary>
/// <param name="attributes"></param>
/// <returns></returns>
Task<TUser?> CreateUser(AdminUserAttributes attributes);

/// <summary>
/// Creates a user using the admin key (not the anonymous key).
/// Used in trusted server environments, not client apps.
/// </summary>
/// <param name="email"></param>
/// <param name="password"></param>
/// <param name="attributes"></param>
/// <returns></returns>
Task<TUser?> CreateUser(string email, string password, AdminUserAttributes? attributes = null);

/// <summary>
/// Creates a user using the admin key (not the anonymous key).
/// Used in trusted server environments, not client apps.
/// </summary>
Task<bool> DeleteUser(string uid);

/// <summary>
/// Gets a user from a user's JWT. This is using the GoTrue server to validate a user's JWT.
/// </summary>
/// <param name="jwt"></param>
/// <returns></returns>
Task<TUser?> GetUser(string jwt);

/// <summary>
/// Gets a user by ID from the server using the admin key (not the anonymous key).
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
Task<TUser?> GetUserById(string userId);

/// <summary>
/// Sends an email to the user.
/// </summary>
/// <param name="email"></param>
/// <returns></returns>
Task<bool> InviteUserByEmail(string email);

/// <summary>
/// Lists users
/// </summary>
/// <param name="filter">A string for example part of the email</param>
/// <param name="sortBy">Snake case string of the given key, currently only created_at is supported</param>
/// <param name="sortOrder">asc or desc, if null desc is used</param>
/// <param name="page">page to show for pagination</param>
/// <param name="perPage">items per page for pagination</param>
/// <returns></returns>
Task<UserList<TUser>?> ListUsers(string? filter = null, string? sortBy = null, Constants.SortOrder sortOrder = Constants.SortOrder.Descending, int? page = null,
int? perPage = null);

/// <summary>
/// Updates a User using the service key
/// </summary>
/// <param name="attributes"></param>
/// <returns></returns>
public Task<User?> Update(UserAttributes attributes);

/// <summary>
/// Update user by Id
/// </summary>
/// <param name="userId"></param>
/// <param name="userData"></param>
/// <returns></returns>
public Task<User?> UpdateUserById(string userId, AdminUserAttributes userData);
}
}
1 change: 1 addition & 0 deletions Gotrue/Interfaces/IGotrueApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Supabase.Core.Interfaces;
using Supabase.Gotrue.Responses;
using static Supabase.Gotrue.Constants;
#pragma warning disable CS1591

namespace Supabase.Gotrue.Interfaces
{
Expand Down
Loading
Loading