feat: remove auth method
This commit is contained in:
		
							parent
							
								
									201c56c3dd
								
							
						
					
					
						commit
						9160281ea2
					
				
					 7 changed files with 144 additions and 16 deletions
				
			
		| 
						 | 
				
			
			@ -1,3 +1,4 @@
 | 
			
		|||
using System.Net;
 | 
			
		||||
using System.Web;
 | 
			
		||||
using Foxnouns.Backend.Database;
 | 
			
		||||
using Foxnouns.Backend.Database.Models;
 | 
			
		||||
| 
						 | 
				
			
			@ -15,7 +16,7 @@ namespace Foxnouns.Backend.Controllers.Authentication;
 | 
			
		|||
public class AuthController(
 | 
			
		||||
    Config config,
 | 
			
		||||
    DatabaseContext db,
 | 
			
		||||
    KeyCacheService keyCache,
 | 
			
		||||
    KeyCacheService keyCacheService,
 | 
			
		||||
    ILogger logger
 | 
			
		||||
) : ApiControllerBase
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -31,7 +32,7 @@ public class AuthController(
 | 
			
		|||
            config.GoogleAuth.Enabled,
 | 
			
		||||
            config.TumblrAuth.Enabled
 | 
			
		||||
        );
 | 
			
		||||
        var state = HttpUtility.UrlEncode(await keyCache.GenerateAuthStateAsync(ct));
 | 
			
		||||
        var state = HttpUtility.UrlEncode(await keyCacheService.GenerateAuthStateAsync(ct));
 | 
			
		||||
        string? discord = null;
 | 
			
		||||
        if (config.DiscordAuth is { ClientId: not null, ClientSecret: not null })
 | 
			
		||||
            discord =
 | 
			
		||||
| 
						 | 
				
			
			@ -75,6 +76,52 @@ public class AuthController(
 | 
			
		|||
 | 
			
		||||
        return NoContent();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [HttpGet("methods/{id}")]
 | 
			
		||||
    [Authorize("*")]
 | 
			
		||||
    [ProducesResponseType<UserRendererService.AuthMethodResponse>(
 | 
			
		||||
        statusCode: StatusCodes.Status200OK
 | 
			
		||||
    )]
 | 
			
		||||
    public async Task<IActionResult> GetAuthMethodAsync(Snowflake id)
 | 
			
		||||
    {
 | 
			
		||||
        var authMethod = await db
 | 
			
		||||
            .AuthMethods.Include(a => a.FediverseApplication)
 | 
			
		||||
            .FirstOrDefaultAsync(a => a.UserId == CurrentUser!.Id && a.Id == id);
 | 
			
		||||
        if (authMethod == null)
 | 
			
		||||
            throw new ApiError.NotFound("No authentication method with that ID found.");
 | 
			
		||||
 | 
			
		||||
        return Ok(UserRendererService.RenderAuthMethod(authMethod));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [HttpDelete("methods/{id}")]
 | 
			
		||||
    [Authorize("*")]
 | 
			
		||||
    public async Task<IActionResult> DeleteAuthMethodAsync(Snowflake id)
 | 
			
		||||
    {
 | 
			
		||||
        var authMethods = await db
 | 
			
		||||
            .AuthMethods.Where(a => a.UserId == CurrentUser!.Id)
 | 
			
		||||
            .ToListAsync();
 | 
			
		||||
        if (authMethods.Count < 2)
 | 
			
		||||
            throw new ApiError(
 | 
			
		||||
                "You cannot remove your last authentication method.",
 | 
			
		||||
                HttpStatusCode.BadRequest,
 | 
			
		||||
                ErrorCode.LastAuthMethod
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
        var authMethod = authMethods.FirstOrDefault(a => a.Id == id);
 | 
			
		||||
        if (authMethod == null)
 | 
			
		||||
            throw new ApiError.NotFound("No authentication method with that ID found.");
 | 
			
		||||
 | 
			
		||||
        _logger.Debug(
 | 
			
		||||
            "Deleting auth method {AuthMethodId} for user {UserId}",
 | 
			
		||||
            authMethod.Id,
 | 
			
		||||
            CurrentUser!.Id
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        db.Remove(authMethod);
 | 
			
		||||
        await db.SaveChangesAsync();
 | 
			
		||||
 | 
			
		||||
        return NoContent();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
public record CallbackResponse(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -148,6 +148,7 @@ public enum ErrorCode
 | 
			
		|||
    UserNotFound,
 | 
			
		||||
    MemberNotFound,
 | 
			
		||||
    AccountAlreadyLinked,
 | 
			
		||||
    LastAuthMethod,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
public class ValidationError
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -67,22 +67,23 @@ public class UserRendererService(
 | 
			
		|||
            renderMembers
 | 
			
		||||
                ? members.Select(m => memberRenderer.RenderPartialMember(m, tokenHidden))
 | 
			
		||||
                : null,
 | 
			
		||||
            renderAuthMethods
 | 
			
		||||
                ? authMethods.Select(a => new AuthenticationMethodResponse(
 | 
			
		||||
                    a.Id,
 | 
			
		||||
                    a.AuthType,
 | 
			
		||||
                    a.RemoteId,
 | 
			
		||||
                    a.FediverseApplication != null
 | 
			
		||||
                        ? $"@{a.RemoteUsername}@{a.FediverseApplication.Domain}"
 | 
			
		||||
                        : a.RemoteUsername
 | 
			
		||||
                ))
 | 
			
		||||
                : null,
 | 
			
		||||
            renderAuthMethods ? authMethods.Select(RenderAuthMethod) : null,
 | 
			
		||||
            tokenHidden ? user.ListHidden : null,
 | 
			
		||||
            tokenHidden ? user.LastActive : null,
 | 
			
		||||
            tokenHidden ? user.LastSidReroll : null
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static AuthMethodResponse RenderAuthMethod(AuthMethod a) =>
 | 
			
		||||
        new(
 | 
			
		||||
            a.Id,
 | 
			
		||||
            a.AuthType,
 | 
			
		||||
            a.RemoteId,
 | 
			
		||||
            a.FediverseApplication != null
 | 
			
		||||
                ? $"@{a.RemoteUsername}@{a.FediverseApplication.Domain}"
 | 
			
		||||
                : a.RemoteUsername
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
    public PartialUser RenderPartialUser(User user) =>
 | 
			
		||||
        new(
 | 
			
		||||
            user.Id,
 | 
			
		||||
| 
						 | 
				
			
			@ -118,7 +119,7 @@ public class UserRendererService(
 | 
			
		|||
        [property: JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
 | 
			
		||||
            IEnumerable<MemberRendererService.PartialMember>? Members,
 | 
			
		||||
        [property: JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
 | 
			
		||||
            IEnumerable<AuthenticationMethodResponse>? AuthMethods,
 | 
			
		||||
            IEnumerable<AuthMethodResponse>? AuthMethods,
 | 
			
		||||
        [property: JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
 | 
			
		||||
            bool? MemberListHidden,
 | 
			
		||||
        [property: JsonProperty(NullValueHandling = NullValueHandling.Ignore)] Instant? LastActive,
 | 
			
		||||
| 
						 | 
				
			
			@ -126,7 +127,7 @@ public class UserRendererService(
 | 
			
		|||
            Instant? LastSidReroll
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    public record AuthenticationMethodResponse(
 | 
			
		||||
    public record AuthMethodResponse(
 | 
			
		||||
        Snowflake Id,
 | 
			
		||||
        [property: JsonConverter(typeof(ScreamingSnakeCaseEnumConverter))] AuthType Type,
 | 
			
		||||
        string RemoteId,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue