R1 cleanup: collAnon and dead code gone, docs current, every peer's scenario in one sweep
Build / Build (push) Successful in 1m7s
Build / Build (push) Successful in 1m7s
Starts the completion program (docs/ROADMAP.md, "Owner decisions on finishing everything", 2026-10-17). - Dead code: the commented-out collAnon blocks (discussions, seeding, admin user lists, HTTP/3, the old signature middleware), the empty PrivaPubWorkersConfiguration, PublicAvatarUsersService and UserPolicyType, unused helpers, the second IPasswordHasher registration, the PasswordGenerator package, SignUpAsync/LoginAsync's unused invitation parameters. "Starting PrivaPub"; a signed-in login is sent to "/", not to "/discussions". - Stored fields nothing read: RootUser.Contacts and ResetPasswordToken*, the local Avatar.AvatarServer, EmailRecovery.RecoveryCode/RequestIP/CreationDate, MongoSettings.LogsDatabase, and AppConfiguration's upload/discussion keys, RequiresFirstTimeSetup and Version (old documents still load: MongoDB.Entities ignores extra elements). DmPost's indexes are no longer made. 49 collAnon keys leave FieldsNameResource in every language. - /clientapi/data/current-version answers the build's ref. UsersIds is a list that can't throw, and the admin routes leave the administrator out without mutating the request. - deploy.yml checks SecureMode on a name no persona can have, and the browser redirect on the directory's first local persona: @thepra is the administrator's own now. - Town: decePub's e2e remnants (expect, client.jsonl, the decePub column) and town/tests go; the dead gaps/load commands too. Mobilizon no longer keeps an event for a deleted test. - tools/pasture/sweep.sh runs every peer's scenario, batch by batch, as CLAUDE.md asks before a change to what PrivaPub sends. - Docs: CLAUDE.md's repo map, route table (every frozen route) and stale lines; ROADMAP's status (setup, v1.25.0, v1.26.0, the program C), the 2026-10-17 decisions, and dated notes where earlier text no longer holds; FEDERATION.md's FEP list (7888, f228, 7628, ae0c and 8967 supported) and the deploy's persona. Verified: dotnet build PrivaPub.sln -c Release (0 errors, no new warnings); bash -n on the touched scripts; py_compile on the town; the pasture's gts, mastodon and lemmy scenarios on this build. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WpVCoDeM1qUTRp4fXQdfof
This commit is contained in:
1 parent
6727e1817a
commit
ff5e635dda
71 files changed
+238
-4767
No files matched your search
@@ -14,8 +14,9 @@ namespace PrivaPub.Services.ClientToServer.Public
|
||||
AppConfigurationService = appConfigurationService;
|
||||
}
|
||||
|
||||
// the build's ref (its tag, or the branch a manual deploy ran from), as /build.json and NodeInfo name it
|
||||
public string GetCurrentVersion() =>
|
||||
AppConfigurationService.AppConfiguration.Version;
|
||||
string.IsNullOrEmpty(BuildInfo.Ref) ? BuildInfo.Commit : BuildInfo.Ref;
|
||||
|
||||
public async Task<IEnumerable<Language>> GetLanguages(CancellationToken cancellationToken)
|
||||
{
|
||||
@@ -23,15 +24,5 @@ namespace PrivaPub.Services.ClientToServer.Public
|
||||
.Match(l => AppConfigurationService.AppConfiguration.SupportedLanguages.Contains(l.International2Code))
|
||||
.ExecuteAsync(cancellationToken)).OrderBy(l => l.NativeName).ToArray();
|
||||
}
|
||||
|
||||
public async Task<bool> IsValidLanguageId(string languageId)
|
||||
{
|
||||
var anyLanguageWithId = await DbEntities.Languages.Match(l => l.ID == languageId).ExecuteAnyAsync();
|
||||
if (!anyLanguageWithId)
|
||||
return false;
|
||||
var language2Code = (await DbEntities.Languages
|
||||
.Match(l => l.ID == languageId).ExecuteFirstAsync())?.International2Code;
|
||||
return AppConfigurationService.AppConfiguration.SupportedLanguages.Contains(language2Code);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,5 @@ namespace PrivaPub.Services.ClientToServer.Public
|
||||
string GetCurrentVersion();
|
||||
|
||||
Task<IEnumerable<Language>> GetLanguages(CancellationToken cancellationToken);
|
||||
|
||||
Task<bool> IsValidLanguageId(string languageId);
|
||||
}
|
||||
}
|
||||
@@ -1,174 +0,0 @@
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
using PrivaPub.ClientModels;
|
||||
using PrivaPub.Models.User;
|
||||
using PrivaPub.Resources;
|
||||
using PrivaPub.StaticServices;
|
||||
|
||||
namespace PrivaPub.Services.ClientToServer.Public
|
||||
{
|
||||
public interface IPublicAvatarUsersService
|
||||
{
|
||||
Task<WebResult> GetLocalAvatar(UserPolicyType userPolicyType, string actor, CancellationToken token);
|
||||
Task<IEnumerable<Avatar>> GetLocalAvatars(UserPolicyType userPolicyType, CancellationToken token);
|
||||
|
||||
Task<WebResult> GetForeignAvatar(UserPolicyType userPolicyType, string actor, CancellationToken token);
|
||||
Task<IEnumerable<ForeignAvatar>> GetForeignAvatars(UserPolicyType userPolicyType, CancellationToken token);
|
||||
|
||||
Task<IEnumerable<Avatar>> GetRootAvatars(string rootUserId, CancellationToken token);
|
||||
}
|
||||
|
||||
public class PublicAvatarUsersService : IPublicAvatarUsersService
|
||||
{
|
||||
readonly DbEntities _dbEntities;
|
||||
readonly IStringLocalizer<GenericRes> _localizer;
|
||||
readonly ILogger<PublicAvatarUsersService> _logger;
|
||||
|
||||
public PublicAvatarUsersService(DbEntities dbEntities,
|
||||
IStringLocalizer<GenericRes> localizer,
|
||||
ILogger<PublicAvatarUsersService> logger)
|
||||
{
|
||||
_dbEntities = dbEntities;
|
||||
_localizer = localizer;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<WebResult> GetLocalAvatar(UserPolicyType userPolicyType, string actor, CancellationToken token)
|
||||
{
|
||||
var result = new WebResult();
|
||||
try
|
||||
{
|
||||
var query = _dbEntities.Avatars;
|
||||
switch (userPolicyType)
|
||||
{
|
||||
case UserPolicyType.IsUser:
|
||||
query.Match(a => !a.DeletionAt.HasValue && a.UserName == actor);
|
||||
break;
|
||||
case UserPolicyType.IsModerator:
|
||||
query.Match(a => !a.DeletionAt.HasValue && a.UserName == actor);
|
||||
break;
|
||||
case UserPolicyType.IsAdmin:
|
||||
query.Match(a => a.UserName == actor);
|
||||
break;
|
||||
}
|
||||
var avatar = await query.ExecuteFirstAsync(token);
|
||||
if (avatar == default)
|
||||
return result.Invalidate(_localizer["User '{0}' not found.", actor], StatusCodes.Status404NotFound);
|
||||
result.Data = avatar;
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, $"{nameof(PublicAvatarUsersService)}.{nameof(GetLocalAvatar)}");
|
||||
return result.Invalidate(_localizer["Error: {0}", ex.ToString()], exception: ex);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<Avatar>> GetLocalAvatars(UserPolicyType userPolicyType, CancellationToken token)
|
||||
{
|
||||
try
|
||||
{
|
||||
var query = _dbEntities.Avatars;
|
||||
switch (userPolicyType)
|
||||
{
|
||||
case UserPolicyType.IsUser:
|
||||
query.Match(a => !a.DeletionAt.HasValue);
|
||||
break;
|
||||
case UserPolicyType.IsModerator:
|
||||
query.Match(a => !a.DeletionAt.HasValue);
|
||||
break;
|
||||
case UserPolicyType.IsAdmin:
|
||||
break;
|
||||
}
|
||||
var avatars = await query.ExecuteAsync(token);
|
||||
return avatars;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, $"{nameof(PublicAvatarUsersService)}.{nameof(GetLocalAvatars)}");
|
||||
return Enumerable.Empty<Avatar>();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<WebResult> GetForeignAvatar(UserPolicyType userPolicyType, string actor, CancellationToken token)
|
||||
{
|
||||
var result = new WebResult();
|
||||
try
|
||||
{
|
||||
var query = _dbEntities.ForeignAvatars;
|
||||
switch (userPolicyType)
|
||||
{
|
||||
case UserPolicyType.IsUser:
|
||||
query.Match(a => !a.DeletionAt.HasValue && a.UserName == actor);
|
||||
break;
|
||||
case UserPolicyType.IsModerator:
|
||||
query.Match(a => !a.DeletionAt.HasValue && a.UserName == actor);
|
||||
break;
|
||||
case UserPolicyType.IsAdmin:
|
||||
query.Match(a => a.UserName == actor);
|
||||
break;
|
||||
}
|
||||
var avatar = await query.ExecuteFirstAsync(token);
|
||||
if (avatar == default)
|
||||
return result.Invalidate(_localizer["User '{0}' not found.", actor], StatusCodes.Status404NotFound);
|
||||
result.Data = avatar;
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, $"{nameof(PublicAvatarUsersService)}.{nameof(GetForeignAvatar)}");
|
||||
return result.Invalidate(_localizer["Error: {0}", ex.ToString()], exception: ex);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<ForeignAvatar>> GetForeignAvatars(UserPolicyType userPolicyType, CancellationToken token)
|
||||
{
|
||||
try
|
||||
{
|
||||
var query = _dbEntities.ForeignAvatars;
|
||||
switch (userPolicyType)
|
||||
{
|
||||
case UserPolicyType.IsUser:
|
||||
query.Match(a => !a.DeletionAt.HasValue);
|
||||
break;
|
||||
case UserPolicyType.IsModerator:
|
||||
query.Match(a => !a.DeletionAt.HasValue);
|
||||
break;
|
||||
case UserPolicyType.IsAdmin:
|
||||
break;
|
||||
}
|
||||
var foreignAvatars = await query.ExecuteAsync(token);
|
||||
return foreignAvatars;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, $"{nameof(PublicAvatarUsersService)}.{nameof(GetForeignAvatars)}");
|
||||
return Enumerable.Empty<ForeignAvatar>();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<Avatar>> GetRootAvatars(string rootUserId, CancellationToken token)
|
||||
{
|
||||
try
|
||||
{
|
||||
var rootUser = await _dbEntities.RootUsers.MatchID(rootUserId).ExecuteFirstAsync(token);
|
||||
if (rootUser == default)
|
||||
return Enumerable.Empty<Avatar>();
|
||||
var rootToAvatars = await _dbEntities.RootToAvatars.Match(ra => ra.RootId == rootUserId).ExecuteAsync(token);
|
||||
if (rootToAvatars.Count == 0)
|
||||
return Enumerable.Empty<Avatar>();
|
||||
var avatarIds = rootToAvatars.Select(ra => ra.AvatarId).ToArray();
|
||||
var avatars = await _dbEntities.Avatars
|
||||
.Match(a => avatarIds.Contains(a.ID))
|
||||
.ProjectExcluding(a => a.Settings)
|
||||
.ExecuteAsync(token);
|
||||
return avatars;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, $"{nameof(PublicAvatarUsersService)}.{nameof(GetRootAvatars)}");
|
||||
return Enumerable.Empty<Avatar>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,6 @@ namespace PrivaPub.Services
|
||||
{
|
||||
public interface IGroupUsersService
|
||||
{
|
||||
Task<WebResult> GetGroup(string actor, CancellationToken token);
|
||||
Task<WebResult> GetGroups(string rootUserId, string avatarId, CancellationToken token);
|
||||
Task<WebResult> InsertGroup(string rootUserId, InsertGroupForm form, CancellationToken token);
|
||||
Task<WebResult> UpdateGroup(string rootUserId, UpdateGroupForm form, CancellationToken token);
|
||||
@@ -58,27 +57,6 @@ namespace PrivaPub.Services
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<WebResult> GetGroup(string actor, CancellationToken token)
|
||||
{
|
||||
var result = new WebResult();
|
||||
try
|
||||
{
|
||||
var userName = actor?.ToLowerInvariant();
|
||||
var group = await _dbEntities.Groups
|
||||
.Match(g => g.UserName == userName && !g.DeletionAt.HasValue)
|
||||
.ExecuteFirstAsync(token);
|
||||
if (group == default)
|
||||
return result.Invalidate(_localizer["Group '{0}' not found.", actor], StatusCodes.Status404NotFound);
|
||||
result.Data = group;
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, $"{nameof(GroupUsersService)}.{nameof(GetGroup)}");
|
||||
return result.Invalidate(_localizer["Something went wrong."], exception: ex);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<WebResult> GetGroups(string rootUserId, string avatarId, CancellationToken token)
|
||||
{
|
||||
var result = new WebResult();
|
||||
|
||||
@@ -7,9 +7,9 @@ namespace PrivaPub.Services
|
||||
{
|
||||
public interface IRootUsersService
|
||||
{
|
||||
Task<WebResult> LoginAsync(LoginForm loginForm, string invitationCode = default, bool isPasswordRequired = false);
|
||||
Task<WebResult> LoginAsync(LoginForm loginForm);
|
||||
|
||||
Task<WebResult> SignUpAsync(LoginForm signUpForm, string invitationCode = default, bool isPasswordRequired = false);
|
||||
Task<WebResult> SignUpAsync(LoginForm signUpForm);
|
||||
|
||||
Task<WebResult> BanUserAsync(UsersIds usersIds);
|
||||
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
using MailKit.Net.Smtp;
|
||||
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
using MimeKit;
|
||||
|
||||
using MongoDB.Driver;
|
||||
using MongoDB.Entities;
|
||||
|
||||
using PasswordGenerator;
|
||||
|
||||
using PrivaPub.ClientModels;
|
||||
using PrivaPub.ClientModels.User;
|
||||
using PrivaPub.Models;
|
||||
@@ -33,7 +27,6 @@ namespace PrivaPub.Services
|
||||
readonly IStringLocalizer Localizer;
|
||||
readonly ILogger<RootUsersService> Logger;
|
||||
readonly AppConfigurationService AppConfigurationService;
|
||||
readonly AuthTokenManager AuthTokenManager;
|
||||
readonly IJobQueue Jobs;
|
||||
readonly IRootSessions Sessions;
|
||||
readonly IRootRemoval Removal;
|
||||
@@ -46,14 +39,12 @@ namespace PrivaPub.Services
|
||||
ILogger<RootUsersService> logger,
|
||||
IPasswordHasher passwordHasher,
|
||||
DbEntities dbEntities,
|
||||
AppConfigurationService appConfigurationService,
|
||||
AuthTokenManager authTokenManager)
|
||||
AppConfigurationService appConfigurationService)
|
||||
{
|
||||
Jobs = jobs;
|
||||
Sessions = sessions;
|
||||
Removal = removal;
|
||||
DbEntities = dbEntities;
|
||||
AuthTokenManager = authTokenManager;
|
||||
PasswordHasher = passwordHasher;
|
||||
Localizer = localizer;
|
||||
Logger = logger;
|
||||
@@ -66,8 +57,7 @@ namespace PrivaPub.Services
|
||||
// a hash nobody's password matches, so an unknown login costs the same hashing as a wrong password
|
||||
string Decoy => _decoy ??= PasswordHasher.Hash(Convert.ToHexString(System.Security.Cryptography.RandomNumberGenerator.GetBytes(16)));
|
||||
|
||||
public async Task<WebResult> SignUpAsync(LoginForm signUpForm, string invitationCode = default,
|
||||
bool isPasswordRequired = false)
|
||||
public async Task<WebResult> SignUpAsync(LoginForm signUpForm)
|
||||
{
|
||||
var result = new WebResult();
|
||||
try
|
||||
@@ -98,23 +88,6 @@ namespace PrivaPub.Services
|
||||
};
|
||||
await DB.Default.SaveAsync(newUser);
|
||||
|
||||
//if (!string.IsNullOrEmpty(invitationCode))
|
||||
//{
|
||||
// if (isPasswordRequired)
|
||||
// result = await DiscussionService.InviteUserToDiscussion(new PwDiscussionPreviewForm
|
||||
// {
|
||||
// InvitationCode = invitationCode,
|
||||
// Password = signUpForm.InvitationPassword
|
||||
// }, newUser.ID);
|
||||
// else
|
||||
// result = await DiscussionService.InviteUserToDiscussion(new NoPwDiscussionPreviewForm
|
||||
// {
|
||||
// InvitationCode = invitationCode,
|
||||
// }, newUser.ID);
|
||||
// if (!result.IsValid)
|
||||
// return result;
|
||||
//}
|
||||
|
||||
result.Data = (newUser, ToViewSettings(newUser.Settings));
|
||||
|
||||
return result;
|
||||
@@ -126,8 +99,7 @@ namespace PrivaPub.Services
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<WebResult> LoginAsync(LoginForm loginForm, string invitationCode = default,
|
||||
bool isPasswordRequired = false)
|
||||
public async Task<WebResult> LoginAsync(LoginForm loginForm)
|
||||
{
|
||||
var result = new WebResult();
|
||||
try
|
||||
@@ -148,23 +120,6 @@ namespace PrivaPub.Services
|
||||
var userSettingsResult = await GetUserSettingsAsync(user.ID, loginForm);
|
||||
var userSettings = (ViewUserSettings)userSettingsResult.Data;
|
||||
|
||||
//if (!string.IsNullOrEmpty(invitationCode))
|
||||
//{
|
||||
// if (isPasswordRequired)
|
||||
// result = await DiscussionService.InviteUserToDiscussion(new PwDiscussionPreviewForm
|
||||
// {
|
||||
// InvitationCode = invitationCode,
|
||||
// Password = loginForm.InvitationPassword
|
||||
// }, user.ID);
|
||||
// else
|
||||
// result = await DiscussionService.InviteUserToDiscussion(new NoPwDiscussionPreviewForm
|
||||
// {
|
||||
// InvitationCode = invitationCode,
|
||||
// }, user.ID);
|
||||
// if (!result.IsValid)
|
||||
// return result;
|
||||
//}
|
||||
|
||||
result.Data = (user, userSettings);
|
||||
|
||||
return result;
|
||||
|
||||
Reference in new issue
Block a user