Изменение имен пользователей в обсуждениях
Изменение имен пользователей в обсуждениях¶
Начиная с версии 4.0 в платформе появилась возможность изменять имена пользователей в обсуждениях и уведомлениях по ним. Для этого необходимо переопределить интерфейс IForumUserNamingStrategy
.
Для демонстрации реализуем указанный интерфейс таким образом, чтобы заменялись имена и идентификаторы пользователей с уровнем доступа “Администратор”, при этом обычные пользователи будут видеть измененную информацию, а администраторы - изначальную.
public class ForumUserNamingStrategy :
IForumUserNamingStrategy
{
#region Private static fields and consts
private static readonly Guid AdministratorIDMasked = Guid.Empty;
private const string AdministratorNameMasked = "Администраторы";
private const string MaskAuthorKey = ".maskAuthor";
private const string MaskFormat = "<mask>{0}</mask>";
private const string MaskRegex = LeftBraket + @"[^\s]+" + RightBraket;
private const string LeftBraket = "<mask>";
private const string RightBraket = "</mask>";
#endregion
#region Private Fields
private readonly IDbScope dbScope;
#endregion
#region Constructor
public ForumUserNamingStrategy(IDbScope dbScope)
{
this.dbScope = NotNullOrThrow(dbScope);
}
#endregion
#region IForumUserNamingStrategy Members
public async ValueTask ReplaceAsync(
IReadOnlyList<ITopicNotificationInfo> topicNotificationInfos,
CancellationToken cancellationToken = default)
{
Dictionary<Guid, bool> users = new();
foreach (var info in topicNotificationInfos)
{
if (!users.TryGetValue(info.UserID, out var isAdmin))
{
isAdmin = await this.CheckUserIsAdminAsync(info.UserID, cancellationToken);
users[info.UserID] = isAdmin;
}
if (isAdmin)
{
info.HtmlText = info.HtmlText
.Replace(LeftBraket, string.Empty, StringComparison.OrdinalIgnoreCase)
.Replace(RightBraket, string.Empty, StringComparison.OrdinalIgnoreCase);
}
else
{
info.HtmlText = Regex.Replace(info.HtmlText, MaskRegex, AdministratorNameMasked);
}
if (!isAdmin && info.Info.TryGet<bool>(MaskAuthorKey))
{
info.AuthorName = AdministratorNameMasked;
}
}
}
public ValueTask ReplaceAsync(
Guid userID,
IReadOnlyList<NotificationModel> notificationModels,
CancellationToken cancellationToken = default) =>
this.ReplaceBodyInMessageAsync(
notificationModels,
userID,
cancellationToken);
public ValueTask ReplaceAsync(
Guid cardID,
Guid userID,
IReadOnlyList<MessageModel> messageModels,
CancellationToken cancellationToken = default) =>
this.ReplaceBodyInMessageAsync(
messageModels,
userID,
cancellationToken);
public async ValueTask PrepareForReplaceAsync(
Guid cardID,
MessageModel messageModel,
CancellationToken cancellationToken = default)
{
messageModel.Body.Info[MaskAuthorKey] = BooleanBoxes.Box(
await this.CheckUserIsAdminAsync(messageModel.AuthorID, cancellationToken));
}
public async ValueTask<string> PrepareForReplaceAsync(
Guid cardID,
Guid topicID,
Guid userID,
string userName,
CancellationToken cancellationToken = default)
{
return await this.CheckUserIsAdminAsync(userID, cancellationToken)
? string.Format(MaskFormat, userName)
: userName;
}
#endregion
#region Private Methods
private async ValueTask ReplaceBodyInMessageAsync(
IReadOnlyList<MessageModelBase> messageModels,
Guid userID,
CancellationToken cancellationToken = default)
{
Regex regex = null;
var isAdmin = await this.CheckUserIsAdminAsync(userID, cancellationToken);
foreach (var messageModel in messageModels)
{
if (isAdmin)
{
messageModel.Body.Text = messageModel.Body.Text
.Replace(LeftBraket, string.Empty, StringComparison.OrdinalIgnoreCase)
.Replace(RightBraket, string.Empty, StringComparison.OrdinalIgnoreCase);
}
else
{
regex ??= new Regex(MaskRegex);
messageModel.Body.Text = regex.Replace(messageModel.Body.Text, AdministratorNameMasked);
}
if (!isAdmin && messageModel.Body.Info.TryGet<bool>(MaskAuthorKey))
{
messageModel.AuthorID = AdministratorIDMasked;
messageModel.AuthorName = AdministratorNameMasked;
}
}
}
private async ValueTask<bool> CheckUserIsAdminAsync(
Guid userID,
CancellationToken cancellationToken = default)
{
await using var _ = this.dbScope.Create();
return await this.dbScope.Db
.SetCommand(this.dbScope.BuilderFactory
.Select().V(true)
.From("PersonalRoles").NoLock()
.Where()
.C("ID").Equals().P("ID")
.And().C("AccessLevelID").Equals().P("AccessLevelID")
.Build(),
this.dbScope.Db.Parameter("ID", userID),
this.dbScope.Db.Parameter("AccessLevelID", (int) UserAccessLevel.Administrator))
.LogCommand()
.ExecuteAsync<bool>(cancellationToken);
}
#endregion
}
Также необходимо зарегистрировать данный класс:
[Registrator]
public class Registrator : RegistratorBase
{
#region Base Overrides
public override void RegisterUnity()
{
this.UnityContainer
.RegisterType<IForumUserNamingStrategy, ForumUserNamingStrategy>(new ContainerControlledLifetimeManager());
}
#endregion
}