No admin by username, no Swagger in production, no exception text to clients
S14 and the privacy items of P0: - signing up as "admin" no longer grants admin; `PrivaPub admin promote <root>` (and `demote`) does, run on the box against the configured database; - Swagger is served in Development only; - every service and controller answers "Something went wrong." where it used to send ex.Message, and the SMTP warnings no longer log the recipient's address; - sign-up and login no longer log the IP, User-Agent and root id together; - invitation sign-up takes the persona's own AvatarUserName (and optional AvatarName) instead of naming the avatar after the private login, and refuses a persona username equal to the login's. Invitation login uses the named persona, creating it if it is new; - recovery mail comes from "PrivaPub", not collAnon's support address name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012CzABvBkbcFqoHdmi8b9WB
This commit is contained in:
1 parent
2eb2a63f1e
commit
0f85030744
11 files changed
+144
-76
No files matched your search
@@ -10,6 +10,7 @@ using PrivaPub.ClientModels.Group;
|
||||
using PrivaPub.ClientModels.User;
|
||||
using PrivaPub.ClientModels.User.Avatar;
|
||||
using PrivaPub.Extensions;
|
||||
using PrivaPub.Federation.Actors;
|
||||
using PrivaPub.Models;
|
||||
using PrivaPub.Models.User;
|
||||
using PrivaPub.Resources;
|
||||
@@ -28,6 +29,7 @@ namespace PrivaPub.Controllers.ClientToServer
|
||||
readonly IRootUsersService UsersService;
|
||||
readonly IGroupUsersService GroupUsersService;
|
||||
readonly IPrivateAvatarUsersService AvatarUsersService;
|
||||
readonly ILocalActorService LocalActors;
|
||||
readonly AuthTokenManager AuthTokenManager;
|
||||
readonly IOptionsMonitor<AppConfiguration> AppConfiguration;
|
||||
readonly ILogger<RootUserController> Logger;
|
||||
@@ -36,6 +38,7 @@ namespace PrivaPub.Controllers.ClientToServer
|
||||
public RootUserController(IRootUsersService usersService,
|
||||
IGroupUsersService groupUsersService,
|
||||
IPrivateAvatarUsersService avatarUsersService,
|
||||
ILocalActorService localActors,
|
||||
AuthTokenManager authTokenManager,
|
||||
IOptionsMonitor<AppConfiguration> appConfiguration,
|
||||
IStringLocalizer<GenericRes> localizer,
|
||||
@@ -44,6 +47,7 @@ namespace PrivaPub.Controllers.ClientToServer
|
||||
UsersService = usersService;
|
||||
GroupUsersService = groupUsersService;
|
||||
AvatarUsersService = avatarUsersService;
|
||||
LocalActors = localActors;
|
||||
AuthTokenManager = authTokenManager;
|
||||
AppConfiguration = appConfiguration;
|
||||
Localizer = localizer;
|
||||
@@ -67,14 +71,12 @@ namespace PrivaPub.Controllers.ClientToServer
|
||||
|
||||
(var user, var userSettings) = ((RootUser, ViewUserSettings))result.Data;
|
||||
var jwtUser = AuthTokenManager.GenerateToken(user, userSettings);
|
||||
Logger.LogInformation(
|
||||
$"{nameof(SignUp)}();IP:[{HttpContext.Connection?.RemoteIpAddress}];\nUser-Agent:[{Request.Headers["User-Agent"]}];\nUserId:[{user.ID}]");
|
||||
return Ok(jwtUser);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, $"{nameof(User)}.{nameof(SignUp)}()");
|
||||
return BadRequest(result.Invalidate(ex.Message));
|
||||
return BadRequest(result.Invalidate(Localizer["Something went wrong."]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,15 +96,13 @@ namespace PrivaPub.Controllers.ClientToServer
|
||||
var (user, userSettings) =
|
||||
((RootUser, ViewUserSettings))result.Data;
|
||||
var jwtUser = AuthTokenManager.GenerateToken(user, userSettings);
|
||||
Logger.LogInformation(
|
||||
$"{nameof(Login)}();IP:[{HttpContext.Connection?.RemoteIpAddress}];\nUser-Agent:[{Request.Headers["User-Agent"]}];\nUserId:[{user.ID}]");
|
||||
|
||||
return Ok(jwtUser);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, $"{nameof(User)}.{nameof(Login)}()");
|
||||
return BadRequest(result.Invalidate(ex.Message));
|
||||
return BadRequest(result.Invalidate(Localizer["Something went wrong."]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,6 +118,11 @@ namespace PrivaPub.Controllers.ClientToServer
|
||||
if (!invitation.IsValid)
|
||||
return StatusCode(invitation.StatusCode, invitation);
|
||||
|
||||
var avatarUserName = signUpForm.AvatarUserName?.Trim().ToLowerInvariant();
|
||||
var personaProblem = await PersonaProblem(avatarUserName, signUpForm.UserName, token);
|
||||
if (personaProblem != default)
|
||||
return BadRequest(result.Invalidate(personaProblem));
|
||||
|
||||
result = await UsersService.SignUpAsync(signUpForm, signUpForm.InvitationCode);
|
||||
if (!result.IsValid)
|
||||
return StatusCode(result.StatusCode, result);
|
||||
@@ -126,8 +131,8 @@ namespace PrivaPub.Controllers.ClientToServer
|
||||
var avatar = await AvatarUsersService.InsertAvatar(new InsertAvatarForm
|
||||
{
|
||||
RootId = user.ID,
|
||||
Name = user.UserName,
|
||||
UserName = user.UserName,
|
||||
Name = string.IsNullOrWhiteSpace(signUpForm.AvatarName) ? avatarUserName : signUpForm.AvatarName.Trim(),
|
||||
UserName = avatarUserName,
|
||||
Biography = string.Empty
|
||||
});
|
||||
if (!avatar.IsValid)
|
||||
@@ -142,14 +147,12 @@ namespace PrivaPub.Controllers.ClientToServer
|
||||
if (!joined.IsValid)
|
||||
return StatusCode(joined.StatusCode, joined);
|
||||
|
||||
Logger.LogInformation(
|
||||
$"{nameof(InvitationSignUp)}();IP:[{HttpContext.Connection?.RemoteIpAddress}];\nUser-Agent:[{Request.Headers["User-Agent"]}];\nUserId:[{user.ID}]");
|
||||
return Ok(AuthTokenManager.GenerateToken(user, userSettings));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, $"{nameof(User)}.{nameof(InvitationSignUp)}()");
|
||||
return BadRequest(result.Invalidate(ex.Message));
|
||||
return BadRequest(result.Invalidate(Localizer["Something went wrong."]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,14 +174,20 @@ namespace PrivaPub.Controllers.ClientToServer
|
||||
var (user, userSettings) = ((RootUser, ViewUserSettings))result.Data;
|
||||
|
||||
var avatars = await AvatarUsersService.GetRootAvatars(user.ID, token);
|
||||
var avatar = (avatars.Data as List<ViewAvatar>)?.FirstOrDefault();
|
||||
var avatarUserName = loginForm.AvatarUserName?.Trim().ToLowerInvariant();
|
||||
var avatar = string.IsNullOrEmpty(avatarUserName)
|
||||
? (avatars.Data as List<ViewAvatar>)?.FirstOrDefault()
|
||||
: (avatars.Data as List<ViewAvatar>)?.FirstOrDefault(a => a.UserName == avatarUserName);
|
||||
if (avatar == default)
|
||||
{
|
||||
var personaProblem = await PersonaProblem(avatarUserName, user.UserName, token);
|
||||
if (personaProblem != default)
|
||||
return BadRequest(new WebResult().Invalidate(personaProblem));
|
||||
var inserted = await AvatarUsersService.InsertAvatar(new InsertAvatarForm
|
||||
{
|
||||
RootId = user.ID,
|
||||
Name = user.UserName,
|
||||
UserName = user.UserName,
|
||||
Name = string.IsNullOrWhiteSpace(loginForm.AvatarName) ? avatarUserName : loginForm.AvatarName.Trim(),
|
||||
UserName = avatarUserName,
|
||||
Biography = string.Empty
|
||||
});
|
||||
if (!inserted.IsValid)
|
||||
@@ -195,17 +204,26 @@ namespace PrivaPub.Controllers.ClientToServer
|
||||
if (!joined.IsValid)
|
||||
return StatusCode(joined.StatusCode, joined);
|
||||
|
||||
Logger.LogInformation(
|
||||
$"{nameof(InvitationLogin)}();IP:[{HttpContext.Connection?.RemoteIpAddress}];\nUser-Agent:[{Request.Headers["User-Agent"]}];\nUserId:[{user.ID}]");
|
||||
return Ok(AuthTokenManager.GenerateToken(user, userSettings));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, $"{nameof(User)}.{nameof(InvitationLogin)}()");
|
||||
return BadRequest(result.Invalidate(ex.Message));
|
||||
return BadRequest(result.Invalidate(Localizer["Something went wrong."]));
|
||||
}
|
||||
}
|
||||
|
||||
async Task<string> PersonaProblem(string avatarUserName, string rootUserName, CancellationToken token)
|
||||
{
|
||||
if (string.IsNullOrEmpty(avatarUserName))
|
||||
return Localizer["Choose a username for your persona."];
|
||||
if (string.Equals(avatarUserName, rootUserName?.Trim(), StringComparison.OrdinalIgnoreCase))
|
||||
return Localizer["Your persona's username must differ from your login."];
|
||||
if (await LocalActors.IsUserNameTaken(avatarUserName, token))
|
||||
return Localizer["The username '{0}' is already take.", avatarUserName];
|
||||
return default;
|
||||
}
|
||||
|
||||
[HttpGet, Route("/clientapi/user/logout"), Authorize(Policy = Policies.IsUser)]
|
||||
public IActionResult Logout()
|
||||
{
|
||||
@@ -217,7 +235,7 @@ namespace PrivaPub.Controllers.ClientToServer
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, $"{nameof(User)}.{nameof(Logout)}()");
|
||||
return BadRequest(result.Invalidate(ex.Message));
|
||||
return BadRequest(result.Invalidate(Localizer["Something went wrong."]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,7 +256,7 @@ namespace PrivaPub.Controllers.ClientToServer
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, $"{nameof(User)}.{nameof(UpdateUser)}()");
|
||||
return BadRequest(result.Invalidate(ex.Message));
|
||||
return BadRequest(result.Invalidate(Localizer["Something went wrong."]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,7 +277,7 @@ namespace PrivaPub.Controllers.ClientToServer
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, $"{nameof(User)}.{nameof(UpdateUserSettings)}()");
|
||||
return BadRequest(result.Invalidate(ex.Message));
|
||||
return BadRequest(result.Invalidate(Localizer["Something went wrong."]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -280,7 +298,7 @@ namespace PrivaPub.Controllers.ClientToServer
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, $"{nameof(User)}.{nameof(UpdatePassword)}()");
|
||||
return BadRequest(result.Invalidate(ex.Message));
|
||||
return BadRequest(result.Invalidate(Localizer["Something went wrong."]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,7 +317,7 @@ namespace PrivaPub.Controllers.ClientToServer
|
||||
// catch (Exception ex)
|
||||
// {
|
||||
// Logger.LogError(ex, $"{nameof(User)}.{nameof(GetUser)}()");
|
||||
// return BadRequest(result.Invalidate(ex.Message));
|
||||
// return BadRequest(result.Invalidate(Localizer["Something went wrong."]));
|
||||
// }
|
||||
//}
|
||||
|
||||
@@ -317,7 +335,7 @@ namespace PrivaPub.Controllers.ClientToServer
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, $"{nameof(User)}.{nameof(GetUserSettings)}()");
|
||||
return BadRequest(result.Invalidate(ex.Message));
|
||||
return BadRequest(result.Invalidate(Localizer["Something went wrong."]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -341,7 +359,7 @@ namespace PrivaPub.Controllers.ClientToServer
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, $"{nameof(User)}.{nameof(RecoverPassword)}()");
|
||||
return BadRequest(result.Invalidate(ex.Message));
|
||||
return BadRequest(result.Invalidate(Localizer["Something went wrong."]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -364,7 +382,7 @@ namespace PrivaPub.Controllers.ClientToServer
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, $"{nameof(User)}.{nameof(IsValidRecoveryCode)}()");
|
||||
return BadRequest(result.Invalidate(ex.Message));
|
||||
return BadRequest(result.Invalidate(Localizer["Something went wrong."]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -385,7 +403,7 @@ namespace PrivaPub.Controllers.ClientToServer
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, $"{nameof(User)}.{nameof(ChangePassword)}()");
|
||||
return BadRequest(result.Invalidate(ex.Message));
|
||||
return BadRequest(result.Invalidate(Localizer["Something went wrong."]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -406,7 +424,7 @@ namespace PrivaPub.Controllers.ClientToServer
|
||||
// catch (Exception ex)
|
||||
// {
|
||||
// Logger.LogError(ex, $"{nameof(User)}.{nameof(RemoveSelf)}()");
|
||||
// return BadRequest(result.Invalidate(ex.Message));
|
||||
// return BadRequest(result.Invalidate(Localizer["Something went wrong."]));
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
Reference in new issue
Block a user