From d828a58fe11fad37aa461bd92f483faab1208e5f Mon Sep 17 00:00:00 2001 From: SuhorukovAnton Date: Tue, 15 Feb 2022 14:05:43 +0300 Subject: [PATCH 01/28] refactoring: update editorconfig --- .editorconfig | 114 +++++++++++++++++++++++++++----------------------- 1 file changed, 62 insertions(+), 52 deletions(-) diff --git a/.editorconfig b/.editorconfig index 9a74367cef..251a5c60c1 100644 --- a/.editorconfig +++ b/.editorconfig @@ -29,34 +29,30 @@ dotnet_style_qualification_for_method = false:silent dotnet_style_qualification_for_property = false:silent # Language keywords vs BCL types preferences -dotnet_style_predefined_type_for_locals_parameters_members = true:warning -dotnet_style_predefined_type_for_member_access = true:warning +dotnet_style_predefined_type_for_locals_parameters_members = true:silent +dotnet_style_predefined_type_for_member_access = true:silent # Parentheses preferences dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent -dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent +dotnet_style_parentheses_in_other_operators = always_for_clarity:silent dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent # Modifier preferences dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent # Expression-level preferences -dotnet_style_coalesce_expression = true:warning -dotnet_style_collection_initializer = true:warning -dotnet_style_explicit_tuple_names = true:warning -dotnet_style_null_propagation = true:warning -dotnet_style_object_initializer = true:warning -dotnet_style_operator_placement_when_wrapping = beginning_of_line -dotnet_style_prefer_auto_properties = true:warning -dotnet_style_prefer_compound_assignment = true:warning +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent +dotnet_style_prefer_inferred_tuple_names = true:suggestion +dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion +dotnet_style_prefer_auto_properties = true:silent dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion dotnet_style_prefer_conditional_expression_over_return = true:suggestion -dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning -dotnet_style_prefer_inferred_tuple_names = true:warning -dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning -dotnet_style_prefer_simplified_boolean_expressions = true:warning -dotnet_style_prefer_simplified_interpolation = true:suggestion # Field preferences dotnet_style_readonly_field = true:warning @@ -64,6 +60,13 @@ dotnet_style_readonly_field = true:warning # Parameter preferences dotnet_code_quality_unused_parameters = all:warning +# Suppression preferences +dotnet_remove_unnecessary_suppression_exclusions = none + +# New line preferences +dotnet_style_allow_multiple_blank_lines_experimental = false +dotnet_style_allow_statement_immediately_after_block_experimental = false + #### C# Coding Conventions #### # var preferences @@ -72,44 +75,48 @@ csharp_style_var_for_built_in_types = true:warning csharp_style_var_when_type_is_apparent = true:warning # Expression-bodied members -csharp_style_expression_bodied_accessors = when_on_single_line:suggestion +csharp_style_expression_bodied_methods = false:silent csharp_style_expression_bodied_constructors = false:silent -csharp_style_expression_bodied_indexers = when_on_single_line:suggestion -csharp_style_expression_bodied_lambdas = when_on_single_line:suggestion -csharp_style_expression_bodied_local_functions = when_on_single_line:suggestion -csharp_style_expression_bodied_methods = false:suggestion csharp_style_expression_bodied_operators = false:silent -csharp_style_expression_bodied_properties = when_on_single_line:suggestion +csharp_style_expression_bodied_properties = true:silent +csharp_style_expression_bodied_indexers = true:silent +csharp_style_expression_bodied_accessors = true:silent # Pattern matching preferences -csharp_style_pattern_matching_over_as_with_null_check = true:warning -csharp_style_pattern_matching_over_is_with_cast_check = true:warning -csharp_style_prefer_switch_expression = true:suggestion +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion # Null-checking preferences -csharp_style_conditional_delegate_call = true:warning +csharp_style_conditional_delegate_call = true:suggestion # Modifier preferences -csharp_prefer_static_local_function = true:suggestion -csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:silent +csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion # Code-block preferences -csharp_prefer_braces = true:silent -csharp_prefer_simple_using_statement = true:suggestion +csharp_prefer_braces = true:warning +csharp_prefer_simple_using_statement = false:silent +csharp_style_namespace_declarations = file_scoped:warning # Expression-level preferences -csharp_prefer_simple_default_expression = true:warning -csharp_style_deconstructed_variable_declaration = true:warning -csharp_style_inlined_variable_declaration = true:warning -csharp_style_pattern_local_over_anonymous_function = true:warning -csharp_style_prefer_index_operator = true:warning -csharp_style_prefer_range_operator = true:warning -csharp_style_throw_expression = true:warning -csharp_style_unused_value_assignment_preference = discard_variable:suggestion +csharp_prefer_simple_default_expression = false:silent +csharp_style_deconstructed_variable_declaration = true:suggestion +csharp_style_implicit_object_creation_when_type_is_apparent = false +csharp_style_inlined_variable_declaration = true:suggestion +csharp_style_pattern_local_over_anonymous_function = true:suggestion +csharp_style_prefer_index_operator = false +csharp_style_prefer_null_check_over_type_check = true +csharp_style_prefer_range_operator = false +csharp_style_throw_expression = true:suggestion +csharp_style_unused_value_assignment_preference = discard_variable csharp_style_unused_value_expression_statement_preference = discard_variable:suggestion # 'using' directive preferences -csharp_using_directive_placement = outside_namespace:silent +csharp_using_directive_placement = outside_namespace:warning + +# New line preferences +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = false +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false +csharp_style_allow_embedded_statements_on_same_line_experimental = true #### C# Formatting Rules #### @@ -126,8 +133,8 @@ csharp_new_line_between_query_expression_clauses = true csharp_indent_block_contents = true csharp_indent_braces = false csharp_indent_case_contents = true -csharp_indent_case_contents_when_block = false -csharp_indent_labels = one_less_than_current +csharp_indent_case_contents_when_block = true +csharp_indent_labels = one_less_than_current csharp_indent_switch_labels = true # Space preferences @@ -162,32 +169,32 @@ csharp_preserve_single_line_statements = true # Naming rules +dotnet_naming_rule.private_or_internal_field_should_be_begin_with_underscore.severity = warning +dotnet_naming_rule.private_or_internal_field_should_be_begin_with_underscore.symbols = private_or_internal_field +dotnet_naming_rule.private_or_internal_field_should_be_begin_with_underscore.style = begin_with_underscore + dotnet_naming_rule.interface_should_be_begins_with_i.severity = warning dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i -dotnet_naming_rule.types_should_be_pascal_case.severity = warning +dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion dotnet_naming_rule.types_should_be_pascal_case.symbols = types dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case -dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = warning -dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members -dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case - # Symbol specifications dotnet_naming_symbols.interface.applicable_kinds = interface dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected dotnet_naming_symbols.interface.required_modifiers = +dotnet_naming_symbols.private_or_internal_field.applicable_kinds = field +dotnet_naming_symbols.private_or_internal_field.applicable_accessibilities = internal, private, private_protected +dotnet_naming_symbols.private_or_internal_field.required_modifiers = + dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected dotnet_naming_symbols.types.required_modifiers = -dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method -dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected -dotnet_naming_symbols.non_field_members.required_modifiers = - # Naming styles dotnet_naming_style.pascal_case.required_prefix = @@ -200,5 +207,8 @@ dotnet_naming_style.begins_with_i.required_suffix = dotnet_naming_style.begins_with_i.word_separator = dotnet_naming_style.begins_with_i.capitalization = pascal_case -# Default severity for analyzer diagnostics with category 'Style' -dotnet_analyzer_diagnostic.category-Style.severity = silent \ No newline at end of file +dotnet_naming_style.begin_with_underscore.required_prefix = _ +dotnet_naming_style.begin_with_underscore.required_suffix = +dotnet_naming_style.begin_with_underscore.word_separator = +dotnet_naming_style.begin_with_underscore.capitalization = camel_case +csharp_prefer_static_local_function=false:error From c81c9346b52e529ff9c9b475c1a2b7f7858fa41f Mon Sep 17 00:00:00 2001 From: SuhorukovAnton Date: Tue, 15 Feb 2022 14:11:08 +0300 Subject: [PATCH 02/28] refactoring: delete waste --- .editorconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index 251a5c60c1..47dae92c15 100644 --- a/.editorconfig +++ b/.editorconfig @@ -211,4 +211,3 @@ dotnet_naming_style.begin_with_underscore.required_prefix = _ dotnet_naming_style.begin_with_underscore.required_suffix = dotnet_naming_style.begin_with_underscore.word_separator = dotnet_naming_style.begin_with_underscore.capitalization = camel_case -csharp_prefer_static_local_function=false:error From e42e0aa4e564d43131098fc6f7acd44c7161f8ae Mon Sep 17 00:00:00 2001 From: SuhorukovAnton Date: Wed, 16 Feb 2022 17:07:58 +0300 Subject: [PATCH 03/28] refactoring: voipService --- common/ASC.VoipService/Dao/AbstractDao.cs | 19 +- common/ASC.VoipService/Dao/CachedVoipDao.cs | 121 ++-- common/ASC.VoipService/Dao/VoIPCallFilter.cs | 147 +++-- common/ASC.VoipService/Dao/VoipDao.cs | 518 +++++++++--------- common/ASC.VoipService/IVoipProvider.cs | 31 +- common/ASC.VoipService/Twilio/TwilioPhone.cs | 19 +- .../ASC.VoipService/Twilio/TwilioProvider.cs | 65 ++- .../Twilio/TwilioResponseHelper.cs | 302 +++++----- .../Twilio/TwilioVoipSettings.cs | 89 ++- common/ASC.VoipService/VoipCall.cs | 91 ++- common/ASC.VoipService/VoipModel.cs | 259 +++++---- common/ASC.VoipService/VoipPhone.cs | 99 ++-- common/ASC.VoipService/VoipSettings.cs | 275 +++++----- 13 files changed, 1007 insertions(+), 1028 deletions(-) diff --git a/common/ASC.VoipService/Dao/AbstractDao.cs b/common/ASC.VoipService/Dao/AbstractDao.cs index fb74e26a9b..20f00495d5 100644 --- a/common/ASC.VoipService/Dao/AbstractDao.cs +++ b/common/ASC.VoipService/Dao/AbstractDao.cs @@ -28,23 +28,22 @@ namespace ASC.VoipService.Dao { public class AbstractDao { - private readonly string dbid = "default"; - - private Lazy LazyVoipDbContext { get; } - protected VoipDbContext VoipDbContext { get => LazyVoipDbContext.Value; } - - protected AbstractDao(DbContextManager dbOptions, TenantManager tenantManager) - { - LazyVoipDbContext = new Lazy(() => dbOptions.Get(dbid)); - TenantID = tenantManager.GetCurrentTenant().TenantId; - } + private readonly string _dbid = "default"; + private Lazy _lazyVoipDbContext; + protected VoipDbContext VoipDbContext { get => _lazyVoipDbContext.Value; } protected int TenantID { get; private set; } + protected AbstractDao(DbContextManager dbOptions, TenantManager tenantManager) + { + _lazyVoipDbContext = new Lazy(() => dbOptions.Get(_dbid)); + TenantID = tenantManager.GetCurrentTenant().TenantId; + } + protected string GetTenantColumnName(string table) { const string tenant = "tenant_id"; diff --git a/common/ASC.VoipService/Dao/CachedVoipDao.cs b/common/ASC.VoipService/Dao/CachedVoipDao.cs index 3635caeefe..90647a9e48 100644 --- a/common/ASC.VoipService/Dao/CachedVoipDao.cs +++ b/common/ASC.VoipService/Dao/CachedVoipDao.cs @@ -23,78 +23,77 @@ * */ -namespace ASC.VoipService.Dao +namespace ASC.VoipService.Dao; + +[Singletone] +public class VoipDaoCache { - [Singletone] - public class VoipDaoCache + internal readonly ICache _cache; + private readonly ICacheNotify _notify; + + public VoipDaoCache(ICacheNotify notify, ICache cache) { - internal ICache Cache { get; } - private ICacheNotify Notify { get; } - - public VoipDaoCache(ICacheNotify notify, ICache cache) - { - Cache = cache; - Notify = notify; - Notify.Subscribe((c) => Cache.Remove(CachedVoipDao.GetCacheKey(c.Tenant)), Common.Caching.CacheNotifyAction.Any); - } - - public void ResetCache(int tenant) - { - Notify.Publish(new CachedVoipItem { Tenant = tenant }, Common.Caching.CacheNotifyAction.Any); - } + _cache = cache; + _notify = notify; + _notify.Subscribe((c) => _cache.Remove(CachedVoipDao.GetCacheKey(c.Tenant)), Common.Caching.CacheNotifyAction.Any); } - [Scope] - public class CachedVoipDao : VoipDao + public void ResetCache(int tenant) { - private readonly ICache cache; - private static readonly TimeSpan timeout = TimeSpan.FromDays(1); + _notify.Publish(new CachedVoipItem { Tenant = tenant }, Common.Caching.CacheNotifyAction.Any); + } +} - private VoipDaoCache VoipDaoCache { get; } +[Scope] +public class CachedVoipDao : VoipDao +{ + private static readonly TimeSpan timeout = TimeSpan.FromDays(1); + + private readonly ICache _cache; + private readonly VoipDaoCache _voipDaoCache; - public CachedVoipDao( - TenantManager tenantManager, - DbContextManager dbOptions, - AuthContext authContext, - TenantUtil tenantUtil, - SecurityContext securityContext, - BaseCommonLinkUtility baseCommonLinkUtility, - ConsumerFactory consumerFactory, - VoipDaoCache voipDaoCache) - : base(tenantManager, dbOptions, authContext, tenantUtil, securityContext, baseCommonLinkUtility, consumerFactory) - { - cache = voipDaoCache.Cache; - VoipDaoCache = voipDaoCache; - } + public CachedVoipDao( + TenantManager tenantManager, + DbContextManager dbOptions, + AuthContext authContext, + TenantUtil tenantUtil, + SecurityContext securityContext, + BaseCommonLinkUtility baseCommonLinkUtility, + ConsumerFactory consumerFactory, + VoipDaoCache voipDaoCache) + : base(tenantManager, dbOptions, authContext, tenantUtil, securityContext, baseCommonLinkUtility, consumerFactory) + { + _cache = voipDaoCache._cache; + _voipDaoCache = voipDaoCache; + } - public override VoipPhone SaveOrUpdateNumber(VoipPhone phone) + public override VoipPhone SaveOrUpdateNumber(VoipPhone phone) + { + var result = base.SaveOrUpdateNumber(phone); + _voipDaoCache.ResetCache(TenantID); + return result; + } + + public override void DeleteNumber(string phoneId = "") + { + base.DeleteNumber(phoneId); + _voipDaoCache.ResetCache(TenantID); + } + + public override IEnumerable GetNumbers(params string[] ids) + { + var numbers = _cache.Get>(GetCacheKey(TenantID)); + if (numbers == null) { - var result = base.SaveOrUpdateNumber(phone); - VoipDaoCache.ResetCache(TenantID); - return result; + numbers = new List(base.GetAllNumbers()); + _cache.Insert(GetCacheKey(TenantID), numbers, DateTime.UtcNow.Add(timeout)); } - public override void DeleteNumber(string phoneId = "") - { - base.DeleteNumber(phoneId); - VoipDaoCache.ResetCache(TenantID); - } + return ids.Length > 0 ? numbers.Where(r => ids.Contains(r.Id) || ids.Contains(r.Number)).ToList() : numbers; + } - public override IEnumerable GetNumbers(params string[] ids) - { - var numbers = cache.Get>(GetCacheKey(TenantID)); - if (numbers == null) - { - numbers = new List(base.GetAllNumbers()); - cache.Insert(GetCacheKey(TenantID), numbers, DateTime.UtcNow.Add(timeout)); - } - - return ids.Length > 0 ? numbers.Where(r => ids.Contains(r.Id) || ids.Contains(r.Number)).ToList() : numbers; - } - - public static string GetCacheKey(int tenant) - { - return "voip" + tenant.ToString(CultureInfo.InvariantCulture); - } + public static string GetCacheKey(int tenant) + { + return "voip" + tenant.ToString(CultureInfo.InvariantCulture); } } \ No newline at end of file diff --git a/common/ASC.VoipService/Dao/VoIPCallFilter.cs b/common/ASC.VoipService/Dao/VoIPCallFilter.cs index fe0fc3a896..2267d8aa41 100644 --- a/common/ASC.VoipService/Dao/VoIPCallFilter.cs +++ b/common/ASC.VoipService/Dao/VoIPCallFilter.cs @@ -23,92 +23,91 @@ * */ -namespace ASC.VoipService.Dao +namespace ASC.VoipService.Dao; + +public class VoipCallFilter { - public class VoipCallFilter + public string Type { get; set; } + + public DateTime? FromDate { get; set; } + + public DateTime? ToDate { get; set; } + + public Guid? Agent { get; set; } + + public int? Client { get; set; } + + public int? ContactID { get; set; } + + public string Id { get; set; } + + public string ParentId { get; set; } + + public string SortBy { get; set; } + + public bool SortOrder { get; set; } + + public string SearchText { get; set; } + + public long Offset { get; set; } + + public long Max { get; set; } + + public int? TypeStatus { - public string Type { get; set; } - - public DateTime? FromDate { get; set; } - - public DateTime? ToDate { get; set; } - - public Guid? Agent { get; set; } - - public int? Client { get; set; } - - public int? ContactID { get; set; } - - public string Id { get; set; } - - public string ParentId { get; set; } - - public string SortBy { get; set; } - - public bool SortOrder { get; set; } - - public string SearchText { get; set; } - - public long Offset { get; set; } - - public long Max { get; set; } - - public int? TypeStatus + get { - get - { - if (string.IsNullOrWhiteSpace(Type)) return null; - if (TypeStatuses.TryGetValue(Type, out var status)) return status; + if (string.IsNullOrWhiteSpace(Type)) return null; + if (TypeStatuses.TryGetValue(Type, out var status)) return status; - return null; - } + return null; } + } - public string SortByColumn + public string SortByColumn + { + get { - get - { - if (string.IsNullOrWhiteSpace(SortBy)) return null; - return SortColumns.ContainsKey(SortBy) ? SortColumns[SortBy] : null; - } + if (string.IsNullOrWhiteSpace(SortBy)) return null; + return SortColumns.ContainsKey(SortBy) ? SortColumns[SortBy] : null; } + } - private static Dictionary TypeStatuses + private static Dictionary TypeStatuses + { + get { - get - { - return new Dictionary + return new Dictionary + { { - { - "answered", (int)VoipCallStatus.Answered - }, - { - "missed", (int)VoipCallStatus.Missed - }, - { - "outgoing", (int)VoipCallStatus.Outcoming - } - }; - } - } - - private static Dictionary SortColumns - { - get - { - return new Dictionary + "answered", (int)VoipCallStatus.Answered + }, { - { - "date", "dial_date" - }, - { - "duration", "dial_duration" - }, - { - "price", "price" - }, - }; - } + "missed", (int)VoipCallStatus.Missed + }, + { + "outgoing", (int)VoipCallStatus.Outcoming + } + }; + } + } + + private static Dictionary SortColumns + { + get + { + return new Dictionary + { + { + "date", "dial_date" + }, + { + "duration", "dial_duration" + }, + { + "price", "price" + }, + }; } } } \ No newline at end of file diff --git a/common/ASC.VoipService/Dao/VoipDao.cs b/common/ASC.VoipService/Dao/VoipDao.cs index e520fd4814..fa4638e9f3 100644 --- a/common/ASC.VoipService/Dao/VoipDao.cs +++ b/common/ASC.VoipService/Dao/VoipDao.cs @@ -23,342 +23,338 @@ * */ -namespace ASC.VoipService.Dao +namespace ASC.VoipService.Dao; + +[Scope(typeof(CachedVoipDao))] +public class VoipDao : AbstractDao { - [Scope(typeof(CachedVoipDao))] - public class VoipDao : AbstractDao + private readonly AuthContext _authContext; + private readonly TenantUtil _tenantUtil; + private readonly SecurityContext _securityContext; + private readonly BaseCommonLinkUtility _baseCommonLinkUtility; + private readonly ConsumerFactory _consumerFactory; + + public VoipDao( + TenantManager tenantManager, + DbContextManager dbOptions, + AuthContext authContext, + TenantUtil tenantUtil, + SecurityContext securityContext, + BaseCommonLinkUtility baseCommonLinkUtility, + ConsumerFactory consumerFactory) + : base(dbOptions, tenantManager) { - public VoipDao( - TenantManager tenantManager, - DbContextManager dbOptions, - AuthContext authContext, - TenantUtil tenantUtil, - SecurityContext securityContext, - BaseCommonLinkUtility baseCommonLinkUtility, - ConsumerFactory consumerFactory) - : base(dbOptions, tenantManager) + _authContext = authContext; + _tenantUtil = tenantUtil; + _securityContext = securityContext; + _baseCommonLinkUtility = baseCommonLinkUtility; + _consumerFactory = consumerFactory; + } + + public virtual VoipPhone SaveOrUpdateNumber(VoipPhone phone) + { + if (!string.IsNullOrEmpty(phone.Number)) { - AuthContext = authContext; - TenantUtil = tenantUtil; - SecurityContext = securityContext; - BaseCommonLinkUtility = baseCommonLinkUtility; - ConsumerFactory = consumerFactory; + phone.Number = phone.Number.TrimStart('+'); } - public virtual VoipPhone SaveOrUpdateNumber(VoipPhone phone) + var voipNumber = new VoipNumber { - if (!string.IsNullOrEmpty(phone.Number)) - { - phone.Number = phone.Number.TrimStart('+'); - } + Id = phone.Id, + Number = phone.Number, + Alias = phone.Alias, + Settings = phone.Settings.ToString(), + TenantId = TenantID + }; - var voipNumber = new VoipNumber - { - Id = phone.Id, - Number = phone.Number, - Alias = phone.Alias, - Settings = phone.Settings.ToString(), - TenantId = TenantID - }; + VoipDbContext.VoipNumbers.Add(voipNumber); + VoipDbContext.SaveChanges(); - VoipDbContext.VoipNumbers.Add(voipNumber); - VoipDbContext.SaveChanges(); + return phone; + } - return phone; + public virtual void DeleteNumber(string phoneId = "") + { + var number = VoipDbContext.VoipNumbers.Where(r => r.Id == phoneId && r.TenantId == TenantID).FirstOrDefault(); + VoipDbContext.VoipNumbers.Remove(number); + VoipDbContext.SaveChanges(); + } + + public virtual IEnumerable GetAllNumbers() + { + return VoipDbContext.VoipNumbers + .Where(r => r.TenantId == TenantID) + .ToList() + .ConvertAll(ToPhone); + } + + public virtual IEnumerable GetNumbers(params string[] ids) + { + var numbers = VoipDbContext.VoipNumbers.Where(r => r.TenantId == TenantID); + + if (ids.Length > 0) + { + numbers = numbers.Where(r => ids.Any(a => a == r.Number || a == r.Id)); } - public virtual void DeleteNumber(string phoneId = "") + return numbers.ToList().ConvertAll(ToPhone); + } + + public VoipPhone GetNumber(string id) + { + return GetNumbers(id.TrimStart('+')).FirstOrDefault(); + } + + public virtual VoipPhone GetCurrentNumber() + { + return GetNumbers().FirstOrDefault(r => r.Caller != null); + } + + + public VoipCall SaveOrUpdateCall(VoipCall call) + { + var voipCall = new DbVoipCall { - var number = VoipDbContext.VoipNumbers.Where(r => r.Id == phoneId && r.TenantId == TenantID).FirstOrDefault(); - VoipDbContext.VoipNumbers.Remove(number); - VoipDbContext.SaveChanges(); + TenantId = TenantID, + Id = call.Id, + NumberFrom = call.From, + NumberTo = call.To, + ContactId = call.ContactId + }; + + if (!string.IsNullOrEmpty(call.ParentID)) + { + voipCall.ParentCallId = call.ParentID; } - public virtual IEnumerable GetAllNumbers() + if (call.Status.HasValue) { - return VoipDbContext.VoipNumbers - .Where(r => r.TenantId == TenantID) - .ToList() - .ConvertAll(ToPhone); + voipCall.Status = (int)call.Status.Value; } - public virtual IEnumerable GetNumbers(params string[] ids) + if (!call.AnsweredBy.Equals(Guid.Empty)) { - var numbers = VoipDbContext.VoipNumbers.Where(r => r.TenantId == TenantID); - - if (ids.Length > 0) - { - numbers = numbers.Where(r => ids.Any(a => a == r.Number || a == r.Id)); - } - - return numbers.ToList().ConvertAll(ToPhone); + voipCall.AnsweredBy = call.AnsweredBy; } - public VoipPhone GetNumber(string id) + if (call.DialDate == DateTime.MinValue) { - return GetNumbers(id.TrimStart('+')).FirstOrDefault(); + call.DialDate = DateTime.UtcNow; } - public virtual VoipPhone GetCurrentNumber() + voipCall.DialDate = _tenantUtil.DateTimeToUtc(call.DialDate); + + if (call.DialDuration > 0) { - return GetNumbers().FirstOrDefault(r => r.Caller != null); + voipCall.DialDuration = call.DialDuration; } - - public VoipCall SaveOrUpdateCall(VoipCall call) + if (call.Price > decimal.Zero) { - var voipCall = new DbVoipCall - { - TenantId = TenantID, - Id = call.Id, - NumberFrom = call.From, - NumberTo = call.To, - ContactId = call.ContactId - }; + voipCall.Price = call.Price; + } - if (!string.IsNullOrEmpty(call.ParentID)) + if (call.VoipRecord != null) + { + if (!string.IsNullOrEmpty(call.VoipRecord.Id)) { - voipCall.ParentCallId = call.ParentID; + voipCall.RecordSid = call.VoipRecord.Id; } - if (call.Status.HasValue) + if (!string.IsNullOrEmpty(call.VoipRecord.Uri)) { - voipCall.Status = (int)call.Status.Value; + voipCall.RecordUrl = call.VoipRecord.Uri; } - if (!call.AnsweredBy.Equals(Guid.Empty)) + if (call.VoipRecord.Duration != 0) { - voipCall.AnsweredBy = call.AnsweredBy; + voipCall.RecordDuration = call.VoipRecord.Duration; } - if (call.DialDate == DateTime.MinValue) + if (call.VoipRecord.Price != default) { - call.DialDate = DateTime.UtcNow; + voipCall.RecordPrice = call.VoipRecord.Price; } + } - voipCall.DialDate = TenantUtil.DateTimeToUtc(call.DialDate); + VoipDbContext.VoipCalls.Add(voipCall); + VoipDbContext.SaveChanges(); - if (call.DialDuration > 0) - { - voipCall.DialDuration = call.DialDuration; - } + return call; + } - if (call.Price > decimal.Zero) - { - voipCall.Price = call.Price; - } + public IEnumerable GetCalls(VoipCallFilter filter) + { + var query = GetCallsQuery(filter); - if (call.VoipRecord != null) - { - if (!string.IsNullOrEmpty(call.VoipRecord.Id)) - { - voipCall.RecordSid = call.VoipRecord.Id; - } + if (filter.SortByColumn != null) + { + query.OrderBy(filter.SortByColumn, filter.SortOrder); + } - if (!string.IsNullOrEmpty(call.VoipRecord.Uri)) - { - voipCall.RecordUrl = call.VoipRecord.Uri; - } + query = query.Skip((int)filter.Offset); + query = query.Take((int)filter.Max * 3); - if (call.VoipRecord.Duration != 0) - { - voipCall.RecordDuration = call.VoipRecord.Duration; - } - - if (call.VoipRecord.Price != default) - { - voipCall.RecordPrice = call.VoipRecord.Price; - } - } - - VoipDbContext.VoipCalls.Add(voipCall); - VoipDbContext.SaveChanges(); + var calls = query.ToList().ConvertAll(ToCall); + calls = calls.GroupJoin(calls, call => call.Id, h => h.ParentID, (call, h) => + { + call.ChildCalls.AddRange(h); return call; - } + }).Where(r => string.IsNullOrEmpty(r.ParentID)).ToList(); - public IEnumerable GetCalls(VoipCallFilter filter) + return calls; + } + + public VoipCall GetCall(string id) + { + return GetCalls(new VoipCallFilter { Id = id }).FirstOrDefault(); + } + + public int GetCallsCount(VoipCallFilter filter) + { + return GetCallsQuery(filter).Where(r => r.DbVoipCall.ParentCallId == "").Count(); + } + + public IEnumerable GetMissedCalls(Guid agent, long count = 0, DateTime? from = null) + { + var query = GetCallsQuery(new VoipCallFilter { Agent = agent, SortBy = "date", SortOrder = true, Type = "missed" }); + + if (from.HasValue) { - var query = GetCallsQuery(filter); - - if (filter.SortByColumn != null) - { - query.OrderBy(filter.SortByColumn, filter.SortOrder); - } - - query = query.Skip((int)filter.Offset); - query = query.Take((int)filter.Max * 3); - - var calls = query.ToList().ConvertAll(ToCall); - - calls = calls.GroupJoin(calls, call => call.Id, h => h.ParentID, (call, h) => - { - call.ChildCalls.AddRange(h); - return call; - }).Where(r => string.IsNullOrEmpty(r.ParentID)).ToList(); - - return calls; + query = query.Where(r => r.DbVoipCall.DialDate >= _tenantUtil.DateTimeFromUtc(from.Value)); } - public VoipCall GetCall(string id) + if (count != 0) { - return GetCalls(new VoipCallFilter { Id = id }).FirstOrDefault(); + query = query.Take((int)count); } - public int GetCallsCount(VoipCallFilter filter) + var a = query.Select(ca => new { - return GetCallsQuery(filter).Where(r => r.DbVoipCall.ParentCallId == "").Count(); - } + dbVoipCall = ca, + tmpDate = VoipDbContext.VoipCalls + .Where(tmp => tmp.TenantId == ca.DbVoipCall.TenantId) + .Where(tmp => tmp.NumberFrom == ca.DbVoipCall.NumberFrom || tmp.NumberTo == ca.DbVoipCall.NumberFrom) + .Where(tmp => tmp.Status <= (int)VoipCallStatus.Missed) + .Max(tmp => tmp.DialDate) + }).Where(r => r.dbVoipCall.DbVoipCall.DialDate >= r.tmpDate || r.tmpDate == default); - public IEnumerable GetMissedCalls(Guid agent, long count = 0, DateTime? from = null) + return a.ToList().ConvertAll(r => ToCall(r.dbVoipCall)); + } + + private IQueryable GetCallsQuery(VoipCallFilter filter) + { + var q = VoipDbContext.VoipCalls + .Where(r => r.TenantId == TenantID); + + if (!string.IsNullOrEmpty(filter.Id)) { - var query = GetCallsQuery(new VoipCallFilter { Agent = agent, SortBy = "date", SortOrder = true, Type = "missed" }); - - if (from.HasValue) - { - query = query.Where(r => r.DbVoipCall.DialDate >= TenantUtil.DateTimeFromUtc(from.Value)); - } - - if (count != 0) - { - query = query.Take((int)count); - } - - var a = query.Select(ca => new - { - dbVoipCall = ca, - tmpDate = VoipDbContext.VoipCalls - .Where(tmp => tmp.TenantId == ca.DbVoipCall.TenantId) - .Where(tmp => tmp.NumberFrom == ca.DbVoipCall.NumberFrom || tmp.NumberTo == ca.DbVoipCall.NumberFrom) - .Where(tmp => tmp.Status <= (int)VoipCallStatus.Missed) - .Max(tmp => tmp.DialDate) - }).Where(r => r.dbVoipCall.DbVoipCall.DialDate >= r.tmpDate || r.tmpDate == default); - - return a.ToList().ConvertAll(r => ToCall(r.dbVoipCall)); + q = q.Where(r => r.Id == filter.Id || r.ParentCallId == filter.Id); } - private IQueryable GetCallsQuery(VoipCallFilter filter) + if (filter.ContactID.HasValue) { - var q = VoipDbContext.VoipCalls - .Where(r => r.TenantId == TenantID); - - if (!string.IsNullOrEmpty(filter.Id)) - { - q = q.Where(r => r.Id == filter.Id || r.ParentCallId == filter.Id); - } - - if (filter.ContactID.HasValue) - { - q = q.Where(r => r.ContactId == filter.ContactID.Value); - } - - if (!string.IsNullOrWhiteSpace(filter.SearchText)) - { - q = q.Where(r => r.Id.StartsWith(filter.SearchText)); - } - - if (filter.TypeStatus.HasValue) - { - q = q.Where(r => r.Status == filter.TypeStatus.Value); - } - - if (filter.FromDate.HasValue) - { - q = q.Where(r => r.DialDate >= filter.FromDate.Value); - } - - if (filter.ToDate.HasValue) - { - q = q.Where(r => r.DialDate <= filter.ToDate.Value); - } - - if (filter.Agent.HasValue) - { - q = q.Where(r => r.AnsweredBy == filter.Agent.Value); - } - - return q - .GroupBy(r => r.Id, r => r) - .Join( - VoipDbContext.CrmContact.DefaultIfEmpty(), - r => r.FirstOrDefault().ContactId, - c => c.Id, - (call, contact) => new CallContact { DbVoipCall = call.FirstOrDefault(), CrmContact = contact }) - ; + q = q.Where(r => r.ContactId == filter.ContactID.Value); } - class CallContact + if (!string.IsNullOrWhiteSpace(filter.SearchText)) { - public DbVoipCall DbVoipCall { get; set; } - public CrmContact CrmContact { get; set; } + q = q.Where(r => r.Id.StartsWith(filter.SearchText)); } - #region Converters - - private VoipPhone ToPhone(VoipNumber r) + if (filter.TypeStatus.HasValue) { - return GetProvider().GetPhone(r); + q = q.Where(r => r.Status == filter.TypeStatus.Value); } - private VoipCall ToCall(CallContact dbVoipCall) + if (filter.FromDate.HasValue) { - var call = new VoipCall + q = q.Where(r => r.DialDate >= filter.FromDate.Value); + } + + if (filter.ToDate.HasValue) + { + q = q.Where(r => r.DialDate <= filter.ToDate.Value); + } + + if (filter.Agent.HasValue) + { + q = q.Where(r => r.AnsweredBy == filter.Agent.Value); + } + + return q + .GroupBy(r => r.Id, r => r) + .Join( + VoipDbContext.CrmContact.DefaultIfEmpty(), + r => r.FirstOrDefault().ContactId, + c => c.Id, + (call, contact) => new CallContact { DbVoipCall = call.FirstOrDefault(), CrmContact = contact }) + ; + } + + class CallContact + { + public DbVoipCall DbVoipCall { get; set; } + public CrmContact CrmContact { get; set; } + } + + + private VoipPhone ToPhone(VoipNumber r) + { + return GetProvider().GetPhone(r); + } + + private VoipCall ToCall(CallContact dbVoipCall) + { + var call = new VoipCall + { + Id = dbVoipCall.DbVoipCall.Id, + ParentID = dbVoipCall.DbVoipCall.ParentCallId, + From = dbVoipCall.DbVoipCall.NumberFrom, + To = dbVoipCall.DbVoipCall.NumberTo, + AnsweredBy = dbVoipCall.DbVoipCall.AnsweredBy, + DialDate = _tenantUtil.DateTimeFromUtc(dbVoipCall.DbVoipCall.DialDate), + DialDuration = dbVoipCall.DbVoipCall.DialDuration, + Price = dbVoipCall.DbVoipCall.Price, + Status = (VoipCallStatus)dbVoipCall.DbVoipCall.Status, + VoipRecord = new VoipRecord { - Id = dbVoipCall.DbVoipCall.Id, - ParentID = dbVoipCall.DbVoipCall.ParentCallId, - From = dbVoipCall.DbVoipCall.NumberFrom, - To = dbVoipCall.DbVoipCall.NumberTo, - AnsweredBy = dbVoipCall.DbVoipCall.AnsweredBy, - DialDate = TenantUtil.DateTimeFromUtc(dbVoipCall.DbVoipCall.DialDate), - DialDuration = dbVoipCall.DbVoipCall.DialDuration, - Price = dbVoipCall.DbVoipCall.Price, - Status = (VoipCallStatus)dbVoipCall.DbVoipCall.Status, - VoipRecord = new VoipRecord - { - Id = dbVoipCall.DbVoipCall.RecordSid, - Uri = dbVoipCall.DbVoipCall.RecordUrl, - Duration = dbVoipCall.DbVoipCall.RecordDuration, - Price = dbVoipCall.DbVoipCall.RecordPrice - }, - ContactId = dbVoipCall.CrmContact.Id, - ContactIsCompany = dbVoipCall.CrmContact.IsCompany, - }; + Id = dbVoipCall.DbVoipCall.RecordSid, + Uri = dbVoipCall.DbVoipCall.RecordUrl, + Duration = dbVoipCall.DbVoipCall.RecordDuration, + Price = dbVoipCall.DbVoipCall.RecordPrice + }, + ContactId = dbVoipCall.CrmContact.Id, + ContactIsCompany = dbVoipCall.CrmContact.IsCompany, + }; - if (call.ContactId != 0) - { - call.ContactTitle = call.ContactIsCompany - ? dbVoipCall.CrmContact.CompanyName - : dbVoipCall.CrmContact.FirstName == null || dbVoipCall.CrmContact.LastName == null ? null : $"{dbVoipCall.CrmContact.FirstName} {dbVoipCall.CrmContact.LastName}"; - } - - return call; - } - - public Consumer Consumer + if (call.ContactId != 0) { - get { return ConsumerFactory.GetByKey("twilio"); } + call.ContactTitle = call.ContactIsCompany + ? dbVoipCall.CrmContact.CompanyName + : dbVoipCall.CrmContact.FirstName == null || dbVoipCall.CrmContact.LastName == null ? null : $"{dbVoipCall.CrmContact.FirstName} {dbVoipCall.CrmContact.LastName}"; } - public TwilioProvider GetProvider() + return call; + } + + public Consumer Consumer + { + get { return _consumerFactory.GetByKey("twilio"); } + } + + public TwilioProvider GetProvider() + { + return new TwilioProvider(Consumer["twilioAccountSid"], Consumer["twilioAuthToken"], _authContext, _tenantUtil, _securityContext, _baseCommonLinkUtility); + } + + public bool ConfigSettingsExist + { + get { - return new TwilioProvider(Consumer["twilioAccountSid"], Consumer["twilioAuthToken"], AuthContext, TenantUtil, SecurityContext, BaseCommonLinkUtility); + return !string.IsNullOrEmpty(Consumer["twilioAccountSid"]) && + !string.IsNullOrEmpty(Consumer["twilioAuthToken"]); } - - public bool ConfigSettingsExist - { - get - { - return !string.IsNullOrEmpty(Consumer["twilioAccountSid"]) && - !string.IsNullOrEmpty(Consumer["twilioAuthToken"]); - } - } - - private AuthContext AuthContext { get; } - private TenantUtil TenantUtil { get; } - private SecurityContext SecurityContext { get; } - private BaseCommonLinkUtility BaseCommonLinkUtility { get; } - private ConsumerFactory ConsumerFactory { get; } - - #endregion } } \ No newline at end of file diff --git a/common/ASC.VoipService/IVoipProvider.cs b/common/ASC.VoipService/IVoipProvider.cs index fdd2de18ce..06f2c80cf5 100644 --- a/common/ASC.VoipService/IVoipProvider.cs +++ b/common/ASC.VoipService/IVoipProvider.cs @@ -23,32 +23,31 @@ * */ -namespace ASC.VoipService +namespace ASC.VoipService; + +public interface IVoipProvider { - public interface IVoipProvider - { - IEnumerable GetExistingPhoneNumbers(); + IEnumerable GetExistingPhoneNumbers(); - IEnumerable GetAvailablePhoneNumbers(PhoneNumberType phoneNumberType, string isoCountryCode); + IEnumerable GetAvailablePhoneNumbers(PhoneNumberType phoneNumberType, string isoCountryCode); - VoipPhone BuyNumber(string phoneNumber); + VoipPhone BuyNumber(string phoneNumber); - VoipPhone DeleteNumber(VoipPhone phone); + VoipPhone DeleteNumber(VoipPhone phone); - VoipPhone GetPhone(VoipNumber r); + VoipPhone GetPhone(VoipNumber r); - VoipPhone GetPhone(string id); + VoipPhone GetPhone(string id); - VoipCall GetCall(string callId); + VoipCall GetCall(string callId); - string GetToken(Agent agent, int seconds = 60 * 60 * 24); + string GetToken(Agent agent, int seconds = 60 * 60 * 24); - void UpdateSettings(VoipPhone phone); + void UpdateSettings(VoipPhone phone); - VoipRecord GetRecord(string callId, string recordId); + VoipRecord GetRecord(string callId, string recordId); - void CreateQueue(VoipPhone newPhone); + void CreateQueue(VoipPhone newPhone); - void DisablePhone(VoipPhone phone); - } + void DisablePhone(VoipPhone phone); } diff --git a/common/ASC.VoipService/Twilio/TwilioPhone.cs b/common/ASC.VoipService/Twilio/TwilioPhone.cs index 227da4123c..055dc62fd5 100644 --- a/common/ASC.VoipService/Twilio/TwilioPhone.cs +++ b/common/ASC.VoipService/Twilio/TwilioPhone.cs @@ -27,8 +27,7 @@ namespace ASC.VoipService.Twilio { public class TwilioPhone : VoipPhone { - private readonly TwilioRestClient twilio; - + private readonly TwilioRestClient _twilio; public TwilioPhone( TwilioRestClient twilio, AuthContext authContext, @@ -37,7 +36,7 @@ namespace ASC.VoipService.Twilio BaseCommonLinkUtility baseCommonLinkUtility) : base(authContext, tenantUtil, securityContext, baseCommonLinkUtility) { - this.twilio = twilio; + _twilio = twilio; Settings = new TwilioVoipSettings(authContext, tenantUtil, securityContext, baseCommonLinkUtility); } @@ -52,7 +51,7 @@ namespace ASC.VoipService.Twilio SendDigits = number.Length > 1 ? number[1] + "#" : string.Empty, Record = Settings.Caller.Record, Url = new System.Uri(Settings.Connect(contactId: contactId)) - }, twilio); + }, _twilio); return new VoipCall { Id = call.Sid, From = call.From, To = call.To }; } @@ -64,7 +63,7 @@ namespace ASC.VoipService.Twilio public override VoipCall RedirectCall(string callId, string to) { - var call = CallResource.Update(callId, url: new System.Uri(Settings.Redirect(to)), method: HttpMethod.Post, client: twilio); + var call = CallResource.Update(callId, url: new System.Uri(Settings.Redirect(to)), method: HttpMethod.Post, client: _twilio); return new VoipCall { Id = call.Sid, To = to }; } @@ -79,24 +78,24 @@ namespace ASC.VoipService.Twilio public Queue CreateQueue(string name, int size, string waitUrl, int waitTime) { - var queues = QueueResource.Read(new ReadQueueOptions(), twilio); + var queues = QueueResource.Read(new ReadQueueOptions(), _twilio); var queue = queues.FirstOrDefault(r => r.FriendlyName == name); if (queue == null) { - queue = QueueResource.Create(name, client: twilio); + queue = QueueResource.Create(name, client: _twilio); } return new Queue(queue.Sid, name, size, waitUrl, waitTime); } public string GetQueue(string name) { - var queues = QueueResource.Read(new ReadQueueOptions(), twilio); + var queues = QueueResource.Read(new ReadQueueOptions(), _twilio); return queues.First(r => r.FriendlyName == name).Sid; } public IEnumerable QueueCalls(string id) { - var calls = MemberResource.Read(id, client: twilio); + var calls = MemberResource.Read(id, client: _twilio); return calls.Select(r => r.CallSid); } @@ -106,7 +105,7 @@ namespace ASC.VoipService.Twilio if (calls.Contains(callId)) { MemberResource.Update(queueId, callId, new System.Uri(Settings.Dequeue(reject)), HttpMethod.Post, - client: twilio); + client: _twilio); } } diff --git a/common/ASC.VoipService/Twilio/TwilioProvider.cs b/common/ASC.VoipService/Twilio/TwilioProvider.cs index 2423b7ddeb..4f84fe560c 100644 --- a/common/ASC.VoipService/Twilio/TwilioProvider.cs +++ b/common/ASC.VoipService/Twilio/TwilioProvider.cs @@ -31,28 +31,27 @@ namespace ASC.VoipService.Twilio { public class TwilioProvider : IVoipProvider { - private readonly string accountSid; - private readonly string authToken; - private readonly TwilioRestClient client; - - private AuthContext AuthContext { get; } - private TenantUtil TenantUtil { get; } - private SecurityContext SecurityContext { get; } - private BaseCommonLinkUtility BaseCommonLinkUtility { get; } + private readonly string _accountSid; + private readonly string _authToken; + private readonly TwilioRestClient _client; + private readonly AuthContext _authContext; + private readonly TenantUtil _tenantUtil; + private readonly SecurityContext _securityContext; + private readonly BaseCommonLinkUtility _baseCommonLinkUtility; public TwilioProvider(string accountSid, string authToken, AuthContext authContext, TenantUtil tenantUtil, SecurityContext securityContext, BaseCommonLinkUtility baseCommonLinkUtility) { if (string.IsNullOrEmpty(accountSid)) throw new ArgumentNullException(nameof(accountSid)); if (string.IsNullOrEmpty(authToken)) throw new ArgumentNullException(nameof(authToken)); - this.authToken = authToken; - AuthContext = authContext; - TenantUtil = tenantUtil; - SecurityContext = securityContext; - BaseCommonLinkUtility = baseCommonLinkUtility; - this.accountSid = accountSid; + _authToken = authToken; + _authContext = authContext; + _tenantUtil = tenantUtil; + _securityContext = securityContext; + _baseCommonLinkUtility = baseCommonLinkUtility; + _accountSid = accountSid; - client = new TwilioRestClient(accountSid, authToken); + _client = new TwilioRestClient(accountSid, authToken); } #region Call @@ -66,7 +65,7 @@ namespace ASC.VoipService.Twilio { try { - var record = RecordingResource.Fetch(callId, recordSid, client: client); + var record = RecordingResource.Fetch(callId, recordSid, client: _client); if (!record.Price.HasValue) { @@ -108,31 +107,31 @@ namespace ASC.VoipService.Twilio var newNumber = IncomingPhoneNumberResource.Create( new CreateIncomingPhoneNumberOptions { - PathAccountSid = accountSid, + PathAccountSid = _accountSid, PhoneNumber = new PhoneNumber(phoneNumber) - }, client); + }, _client); - return new TwilioPhone(client, AuthContext, TenantUtil, SecurityContext, BaseCommonLinkUtility) { Id = newNumber.Sid, Number = phoneNumber.Substring(1) }; + return new TwilioPhone(_client, _authContext, _tenantUtil, _securityContext, _baseCommonLinkUtility) { Id = newNumber.Sid, Number = phoneNumber.Substring(1) }; } public VoipPhone DeleteNumber(VoipPhone phone) { - IncomingPhoneNumberResource.Delete(phone.Id, client: client); + IncomingPhoneNumberResource.Delete(phone.Id, client: _client); return phone; } public IEnumerable GetExistingPhoneNumbers() { - var result = IncomingPhoneNumberResource.Read(client: client); - return result.Select(r => new TwilioPhone(client, AuthContext, TenantUtil, SecurityContext, BaseCommonLinkUtility) { Id = r.Sid, Number = r.PhoneNumber.ToString() }); + var result = IncomingPhoneNumberResource.Read(client: _client); + return result.Select(r => new TwilioPhone(_client, _authContext, _tenantUtil, _securityContext, _baseCommonLinkUtility) { Id = r.Sid, Number = r.PhoneNumber.ToString() }); } public IEnumerable GetAvailablePhoneNumbers(PhoneNumberType phoneNumberType, string isoCountryCode) { return phoneNumberType switch { - PhoneNumberType.Local => LocalResource.Read(isoCountryCode, voiceEnabled: true, client: client).Select(r => new TwilioPhone(client, AuthContext, TenantUtil, SecurityContext, BaseCommonLinkUtility) { Number = r.PhoneNumber.ToString() }), - PhoneNumberType.TollFree => TollFreeResource.Read(isoCountryCode, voiceEnabled: true, client: client).Select(r => new TwilioPhone(client, AuthContext, TenantUtil, SecurityContext, BaseCommonLinkUtility) { Number = r.PhoneNumber.ToString() }), + PhoneNumberType.Local => LocalResource.Read(isoCountryCode, voiceEnabled: true, client: _client).Select(r => new TwilioPhone(_client, _authContext, _tenantUtil, _securityContext, _baseCommonLinkUtility) { Number = r.PhoneNumber.ToString() }), + PhoneNumberType.TollFree => TollFreeResource.Read(isoCountryCode, voiceEnabled: true, client: _client).Select(r => new TwilioPhone(_client, _authContext, _tenantUtil, _securityContext, _baseCommonLinkUtility) { Number = r.PhoneNumber.ToString() }), _ => new List(), }; @@ -140,13 +139,13 @@ namespace ASC.VoipService.Twilio public VoipPhone GetPhone(string phoneSid) { - var phone = IncomingPhoneNumberResource.Fetch(phoneSid, client: client); + var phone = IncomingPhoneNumberResource.Fetch(phoneSid, client: _client); - var result = new TwilioPhone(client, AuthContext, TenantUtil, SecurityContext, BaseCommonLinkUtility) + var result = new TwilioPhone(_client, _authContext, _tenantUtil, _securityContext, _baseCommonLinkUtility) { Id = phone.Sid, Number = phone.PhoneNumber.ToString(), - Settings = new TwilioVoipSettings(AuthContext, TenantUtil, SecurityContext, BaseCommonLinkUtility) + Settings = new TwilioVoipSettings(_authContext, _tenantUtil, _securityContext, _baseCommonLinkUtility) }; if (phone.VoiceUrl == null) @@ -159,12 +158,12 @@ namespace ASC.VoipService.Twilio public VoipPhone GetPhone(VoipNumber data) { - return new TwilioPhone(client, AuthContext, TenantUtil, SecurityContext, BaseCommonLinkUtility) + return new TwilioPhone(_client, _authContext, _tenantUtil, _securityContext, _baseCommonLinkUtility) { Id = data.Id, Number = data.Number, Alias = data.Alias, - Settings = new TwilioVoipSettings(data.Settings, AuthContext) + Settings = new TwilioVoipSettings(data.Settings, _authContext) }; } @@ -177,7 +176,7 @@ namespace ASC.VoipService.Twilio { try { - var call = CallResource.Fetch(result.Id, client: client); + var call = CallResource.Fetch(result.Id, client: _client); if (!call.Price.HasValue || string.IsNullOrEmpty(call.Duration)) { count--; @@ -205,19 +204,19 @@ namespace ASC.VoipService.Twilio { new IncomingClientScope(agent.ClientID) }; - var capability = new ClientCapability(accountSid, authToken, scopes: scopes); + var capability = new ClientCapability(_accountSid, _authToken, scopes: scopes); return capability.ToJwt(); } public void UpdateSettings(VoipPhone phone) { - IncomingPhoneNumberResource.Update(phone.Id, voiceUrl: new Uri(phone.Settings.Connect(false)), client: client); + IncomingPhoneNumberResource.Update(phone.Id, voiceUrl: new Uri(phone.Settings.Connect(false)), client: _client); } public void DisablePhone(VoipPhone phone) { - IncomingPhoneNumberResource.Update(phone.Id, voiceUrl: new Uri("https://demo.twilio.com/welcome/voice/"), client: client); + IncomingPhoneNumberResource.Update(phone.Id, voiceUrl: new Uri("https://demo.twilio.com/welcome/voice/"), client: _client); } #endregion diff --git a/common/ASC.VoipService/Twilio/TwilioResponseHelper.cs b/common/ASC.VoipService/Twilio/TwilioResponseHelper.cs index 0103b91057..a55e82bf73 100644 --- a/common/ASC.VoipService/Twilio/TwilioResponseHelper.cs +++ b/common/ASC.VoipService/Twilio/TwilioResponseHelper.cs @@ -23,189 +23,187 @@ * */ -namespace ASC.VoipService.Twilio +namespace ASC.VoipService.Twilio; + +public class TwilioResponseHelper { - public class TwilioResponseHelper + private readonly VoipSettings _settings; + private readonly string _baseUrl; + private readonly AuthContext _authContext; + private readonly TenantUtil _tenantUtil; + private readonly SecurityContext _securityContext; + + public TwilioResponseHelper( + VoipSettings settings, + string baseUrl, + AuthContext authContext, + TenantUtil tenantUtil, + SecurityContext securityContext) { - private readonly VoipSettings settings; - private readonly string baseUrl; + _settings = settings; + _authContext = authContext; + _tenantUtil = tenantUtil; + _securityContext = securityContext; + _baseUrl = baseUrl.TrimEnd('/') + "/twilio/"; + } - private AuthContext AuthContext { get; } - private TenantUtil TenantUtil { get; } - private SecurityContext SecurityContext { get; } + public VoiceResponse Inbound(Tuple agentTuple) + { + var agent = agentTuple?.Item1; + var anyOnline = agentTuple != null && agentTuple.Item2; + var response = new VoiceResponse(); - public TwilioResponseHelper( - VoipSettings settings, - string baseUrl, - AuthContext authContext, - TenantUtil tenantUtil, - SecurityContext securityContext) + if (_settings.WorkingHours != null && _settings.WorkingHours.Enabled) { - this.settings = settings; - AuthContext = authContext; - TenantUtil = tenantUtil; - SecurityContext = securityContext; - this.baseUrl = baseUrl.TrimEnd('/') + "/twilio/"; + var now = _tenantUtil.DateTimeFromUtc(DateTime.UtcNow); + if (!(_settings.WorkingHours.From <= now.TimeOfDay && _settings.WorkingHours.To >= now.TimeOfDay)) + { + return AddVoiceMail(response); + } } - public VoiceResponse Inbound(Tuple agentTuple) + if (anyOnline) { - var agent = agentTuple?.Item1; - var anyOnline = agentTuple != null && agentTuple.Item2; - var response = new VoiceResponse(); - - if (settings.WorkingHours != null && settings.WorkingHours.Enabled) + if (!string.IsNullOrEmpty(_settings.GreetingAudio)) { - var now = TenantUtil.DateTimeFromUtc(DateTime.UtcNow); - if (!(settings.WorkingHours.From <= now.TimeOfDay && settings.WorkingHours.To >= now.TimeOfDay)) - { - return AddVoiceMail(response); - } + response.Play(Uri.EscapeDataString(_settings.GreetingAudio)); } - if (anyOnline) - { - if (!string.IsNullOrEmpty(settings.GreetingAudio)) - { - response.Play(Uri.EscapeDataString(settings.GreetingAudio)); - } - - response.Enqueue(settings.Queue.Name, GetEcho("Enqueue", agent != null), "POST", - GetEcho("Wait", agent != null), "POST"); - } - - return AddVoiceMail(response); + response.Enqueue(_settings.Queue.Name, GetEcho("Enqueue", agent != null), "POST", + GetEcho("Wait", agent != null), "POST"); } - public VoiceResponse Outbound() + return AddVoiceMail(response); + } + + public VoiceResponse Outbound() + { + return !_settings.Caller.AllowOutgoingCalls + ? new VoiceResponse() + : AddToResponse(new VoiceResponse(), _settings.Caller); + } + + public VoiceResponse Dial() + { + return new VoiceResponse(); + } + + public VoiceResponse Queue() + { + return new VoiceResponse(); + } + + public VoiceResponse Enqueue(string queueResult) + { + return queueResult == "leave" ? AddVoiceMail(new VoiceResponse()) : new VoiceResponse(); + } + + public VoiceResponse Dequeue() + { + return AddToResponse(new VoiceResponse(), _settings.Caller); + } + + public VoiceResponse Leave() + { + return AddVoiceMail(new VoiceResponse()); + } + + public VoiceResponse Wait(string queueTime, string queueSize) + { + var response = new VoiceResponse(); + var queue = _settings.Queue; + + if (Convert.ToInt32(queueTime) > queue.WaitTime || Convert.ToInt32(queueSize) > queue.Size) return response.Leave(); + + if (!string.IsNullOrEmpty(queue.WaitUrl)) { - return !settings.Caller.AllowOutgoingCalls - ? new VoiceResponse() - : AddToResponse(new VoiceResponse(), settings.Caller); + var gather = new Gather(method: "POST", action: GetEcho("gatherQueue")); + gather.Play(Uri.EscapeDataString(queue.WaitUrl)); + response.Gather(gather); } - - public VoiceResponse Dial() + else { - return new VoiceResponse(); + response.Pause(queue.WaitTime); } - public VoiceResponse Queue() + return response; + } + + public VoiceResponse GatherQueue(string digits, List availableOperators) + { + var response = new VoiceResponse(); + + if (digits == "#") return AddVoiceMail(response); + + var oper = _settings.Operators.Find(r => r.PostFix == digits && availableOperators.Contains(r)) ?? + _settings.Operators.FirstOrDefault(r => availableOperators.Contains(r)); + + return oper != null ? AddToResponse(response, oper) : response; + } + + public VoiceResponse Redirect(string to) + { + if (to == "hold") { - return new VoiceResponse(); + return new VoiceResponse().Play(Uri.EscapeDataString(_settings.HoldAudio), 0); } - public VoiceResponse Enqueue(string queueResult) + + if (Guid.TryParse(to, out var newCallerId)) { - return queueResult == "leave" ? AddVoiceMail(new VoiceResponse()) : new VoiceResponse(); + _securityContext.AuthenticateMeWithoutCookie(newCallerId); } - public VoiceResponse Dequeue() + return new VoiceResponse().Enqueue(_settings.Queue.Name, GetEcho("enqueue"), "POST", + GetEcho("wait") + "&RedirectTo=" + to, "POST"); + } + + public VoiceResponse VoiceMail() + { + return new VoiceResponse(); + } + + private VoiceResponse AddToResponse(VoiceResponse response, Agent agent) + { + var dial = new Dial(method: "POST", action: GetEcho("dial"), timeout: agent.TimeOut, record: agent.Record ? "record-from-answer" : "do-not-record"); + + switch (agent.Answer) { - return AddToResponse(new VoiceResponse(), settings.Caller); + case AnswerType.Number: + response.Dial(dial.Number(agent.PhoneNumber, method: "POST", url: GetEcho("client"))); + break; + case AnswerType.Client: + response.Dial(dial.Client(agent.ClientID, "POST", GetEcho("client"))); + break; + case AnswerType.Sip: + response.Dial(dial.Sip(agent.ClientID, method: "POST", url: GetEcho("client"))); + break; } - public VoiceResponse Leave() + return response; + } + + + private VoiceResponse AddVoiceMail(VoiceResponse response) + { + return string.IsNullOrEmpty(_settings.VoiceMail) + ? response.Say("") + : response.Play(Uri.EscapeDataString(_settings.VoiceMail)).Record(method: "POST", action: GetEcho("voiceMail"), maxLength: 30); + } + + public string GetEcho(string action, bool user = true) + { + var result = _baseUrl.TrimEnd('/'); + + if (!string.IsNullOrEmpty(action)) { - return AddVoiceMail(new VoiceResponse()); + result += "/" + action.TrimStart('/'); } - - public VoiceResponse Wait(string queueTime, string queueSize) + if (user) { - var response = new VoiceResponse(); - var queue = settings.Queue; - - if (Convert.ToInt32(queueTime) > queue.WaitTime || Convert.ToInt32(queueSize) > queue.Size) return response.Leave(); - - if (!string.IsNullOrEmpty(queue.WaitUrl)) - { - var gather = new Gather(method: "POST", action: GetEcho("gatherQueue")); - gather.Play(Uri.EscapeDataString(queue.WaitUrl)); - response.Gather(gather); - } - else - { - response.Pause(queue.WaitTime); - } - - return response; + result += "?CallerId=" + _authContext.CurrentAccount.ID; } - public VoiceResponse GatherQueue(string digits, List availableOperators) - { - var response = new VoiceResponse(); - - if (digits == "#") return AddVoiceMail(response); - - var oper = settings.Operators.Find(r => r.PostFix == digits && availableOperators.Contains(r)) ?? - settings.Operators.FirstOrDefault(r => availableOperators.Contains(r)); - - return oper != null ? AddToResponse(response, oper) : response; - } - - public VoiceResponse Redirect(string to) - { - if (to == "hold") - { - return new VoiceResponse().Play(Uri.EscapeDataString(settings.HoldAudio), 0); - } - - - if (Guid.TryParse(to, out var newCallerId)) - { - SecurityContext.AuthenticateMeWithoutCookie(newCallerId); - } - - return new VoiceResponse().Enqueue(settings.Queue.Name, GetEcho("enqueue"), "POST", - GetEcho("wait") + "&RedirectTo=" + to, "POST"); - } - - public VoiceResponse VoiceMail() - { - return new VoiceResponse(); - } - - private VoiceResponse AddToResponse(VoiceResponse response, Agent agent) - { - var dial = new Dial(method: "POST", action: GetEcho("dial"), timeout: agent.TimeOut, record: agent.Record ? "record-from-answer" : "do-not-record"); - - switch (agent.Answer) - { - case AnswerType.Number: - response.Dial(dial.Number(agent.PhoneNumber, method: "POST", url: GetEcho("client"))); - break; - case AnswerType.Client: - response.Dial(dial.Client(agent.ClientID, "POST", GetEcho("client"))); - break; - case AnswerType.Sip: - response.Dial(dial.Sip(agent.ClientID, method: "POST", url: GetEcho("client"))); - break; - } - - return response; - } - - - private VoiceResponse AddVoiceMail(VoiceResponse response) - { - return string.IsNullOrEmpty(settings.VoiceMail) - ? response.Say("") - : response.Play(Uri.EscapeDataString(settings.VoiceMail)).Record(method: "POST", action: GetEcho("voiceMail"), maxLength: 30); - } - - public string GetEcho(string action, bool user = true) - { - var result = baseUrl.TrimEnd('/'); - - if (!string.IsNullOrEmpty(action)) - { - result += "/" + action.TrimStart('/'); - } - if (user) - { - result += "?CallerId=" + AuthContext.CurrentAccount.ID; - } - - return result; - } + return result; } } diff --git a/common/ASC.VoipService/Twilio/TwilioVoipSettings.cs b/common/ASC.VoipService/Twilio/TwilioVoipSettings.cs index e7b930c427..98055764a6 100644 --- a/common/ASC.VoipService/Twilio/TwilioVoipSettings.cs +++ b/common/ASC.VoipService/Twilio/TwilioVoipSettings.cs @@ -26,58 +26,57 @@ using Uri = System.Uri; -namespace ASC.VoipService.Twilio +namespace ASC.VoipService.Twilio; + +public class TwilioVoipSettings : VoipSettings { - public class TwilioVoipSettings : VoipSettings + public TwilioVoipSettings( + AuthContext authContext, + TenantUtil tenantUtil, + SecurityContext securityContext, + BaseCommonLinkUtility baseCommonLinkUtility) : + base(authContext, tenantUtil, securityContext, baseCommonLinkUtility) + { } + + public TwilioVoipSettings( + Uri voiceUrl, + AuthContext authContext, + TenantUtil tenantUtil, + SecurityContext securityContext, + BaseCommonLinkUtility baseCommonLinkUtility) : + this(authContext, tenantUtil, securityContext, baseCommonLinkUtility) { - public TwilioVoipSettings( - AuthContext authContext, - TenantUtil tenantUtil, - SecurityContext securityContext, - BaseCommonLinkUtility baseCommonLinkUtility) : - base(authContext, tenantUtil, securityContext, baseCommonLinkUtility) - { } + if (string.IsNullOrEmpty(voiceUrl.Query)) return; - public TwilioVoipSettings( - Uri voiceUrl, - AuthContext authContext, - TenantUtil tenantUtil, - SecurityContext securityContext, - BaseCommonLinkUtility baseCommonLinkUtility) : - this(authContext, tenantUtil, securityContext, baseCommonLinkUtility) + JsonSettings = Encoding.UTF8.GetString(Convert.FromBase64String(HttpUtility.UrlDecode(HttpUtility.ParseQueryString(voiceUrl.Query)["settings"]))); + } + + public TwilioVoipSettings(string settings, AuthContext authContext) : base(settings, authContext) + { + } + + public override string Connect(bool user = true, string contactId = null) + { + var result = GetEcho("", user); + if (!string.IsNullOrEmpty(contactId)) { - if (string.IsNullOrEmpty(voiceUrl.Query)) return; - - JsonSettings = Encoding.UTF8.GetString(Convert.FromBase64String(HttpUtility.UrlDecode(HttpUtility.ParseQueryString(voiceUrl.Query)["settings"]))); + result += "&ContactId=" + contactId; } + return result; + } - public TwilioVoipSettings(string settings, AuthContext authContext) : base(settings, authContext) - { - } + public override string Redirect(string to) + { + return GetEcho("redirect") + "&RedirectTo=" + to; + } - public override string Connect(bool user = true, string contactId = null) - { - var result = GetEcho("", user); - if (!string.IsNullOrEmpty(contactId)) - { - result += "&ContactId=" + contactId; - } - return result; - } + public override string Dequeue(bool reject) + { + return GetEcho("dequeue") + "&Reject=" + reject; + } - public override string Redirect(string to) - { - return GetEcho("redirect") + "&RedirectTo=" + to; - } - - public override string Dequeue(bool reject) - { - return GetEcho("dequeue") + "&Reject=" + reject; - } - - private string GetEcho(string method, bool user = true) - { - return new TwilioResponseHelper(this, BaseCommonLinkUtility.GetFullAbsolutePath(""), AuthContext, TenantUtil, SecurityContext).GetEcho(method, user); - } + private string GetEcho(string method, bool user = true) + { + return new TwilioResponseHelper(this, BaseCommonLinkUtility.GetFullAbsolutePath(""), AuthContext, TenantUtil, SecurityContext).GetEcho(method, user); } } diff --git a/common/ASC.VoipService/VoipCall.cs b/common/ASC.VoipService/VoipCall.cs index 322aba1c05..59d1f84bfc 100644 --- a/common/ASC.VoipService/VoipCall.cs +++ b/common/ASC.VoipService/VoipCall.cs @@ -23,54 +23,53 @@ * */ -namespace ASC.VoipService +namespace ASC.VoipService; + +public class VoipCall { - public class VoipCall + public string Id { get; set; } + + public string ParentID { get; set; } + + public string From { get; set; } + + public string To { get; set; } + + public Guid AnsweredBy { get; set; } + + public DateTime DialDate { get; set; } + + public int DialDuration { get; set; } + + public VoipCallStatus? Status { get; set; } + + public decimal Price { get; set; } + + public int ContactId { get; set; } + + public bool ContactIsCompany { get; set; } + + public string ContactTitle { get; set; } + + public DateTime Date { get; set; } + + public DateTime EndDialDate { get; set; } + + public VoipRecord VoipRecord { get; set; } + + public List ChildCalls { get; set; } + + public VoipCall() { - public string Id { get; set; } - - public string ParentID { get; set; } - - public string From { get; set; } - - public string To { get; set; } - - public Guid AnsweredBy { get; set; } - - public DateTime DialDate { get; set; } - - public int DialDuration { get; set; } - - public VoipCallStatus? Status { get; set; } - - public decimal Price { get; set; } - - public int ContactId { get; set; } - - public bool ContactIsCompany { get; set; } - - public string ContactTitle { get; set; } - - public DateTime Date { get; set; } - - public DateTime EndDialDate { get; set; } - - public VoipRecord VoipRecord { get; set; } - - public List ChildCalls { get; set; } - - public VoipCall() - { - ChildCalls = new List(); - VoipRecord = new VoipRecord(); - } + ChildCalls = new List(); + VoipRecord = new VoipRecord(); } +} - public enum VoipCallStatus - { - Incoming, - Outcoming, - Answered, - Missed - } +public enum VoipCallStatus +{ + Incoming, + Outcoming, + Answered, + Missed } \ No newline at end of file diff --git a/common/ASC.VoipService/VoipModel.cs b/common/ASC.VoipService/VoipModel.cs index 72ca08eda0..5d27c214bb 100644 --- a/common/ASC.VoipService/VoipModel.cs +++ b/common/ASC.VoipService/VoipModel.cs @@ -23,142 +23,137 @@ * */ -namespace ASC.VoipService +namespace ASC.VoipService; + +public class Agent { - public class Agent + public Guid Id { get; set; } + + public AnswerType Answer { get; set; } + + public string ClientID { get { return PhoneNumber + PostFix; } } + + public bool Record { get; set; } + + public int TimeOut { get; set; } + + public AgentStatus Status { get; set; } + + public bool AllowOutgoingCalls { get; set; } + + public string PostFix { get; set; } + + public string PhoneNumber { get; set; } + + public string RedirectToNumber { get; set; } + + public Agent() { - public Guid Id { get; set; } - - public AnswerType Answer { get; set; } - - public string ClientID { get { return PhoneNumber + PostFix; } } - - public bool Record { get; set; } - - public int TimeOut { get; set; } - - public AgentStatus Status { get; set; } - - public bool AllowOutgoingCalls { get; set; } - - public string PostFix { get; set; } - - public string PhoneNumber { get; set; } - - public string RedirectToNumber { get; set; } - - public Agent() - { - Status = AgentStatus.Offline; - TimeOut = 30; - AllowOutgoingCalls = true; - Record = true; - } - - public Agent(Guid id, AnswerType answer, VoipPhone phone, string postFix) - : this() - { - Id = id; - Answer = answer; - PhoneNumber = phone.Number; - AllowOutgoingCalls = phone.Settings.AllowOutgoingCalls; - Record = phone.Settings.Record; - PostFix = postFix; - } + Status = AgentStatus.Offline; + TimeOut = 30; + AllowOutgoingCalls = true; + Record = true; } - public class Queue + public Agent(Guid id, AnswerType answer, VoipPhone phone, string postFix) + : this() { - public string Id { get; set; } - public string Name { get; set; } - public int Size { get; set; } - public string WaitUrl { get; set; } - public int WaitTime { get; set; } - - public Queue() { } - - public Queue(string id, string name, int size, string waitUrl, int waitTime) - { - Id = id; - Name = name; - WaitUrl = waitUrl; - WaitTime = waitTime; - Size = size; - } + Id = id; + Answer = answer; + PhoneNumber = phone.Number; + AllowOutgoingCalls = phone.Settings.AllowOutgoingCalls; + Record = phone.Settings.Record; + PostFix = postFix; } - - public sealed class WorkingHours - { - public bool Enabled { get; set; } - public TimeSpan? From { get; set; } - public TimeSpan? To { get; set; } - - public WorkingHours() { } - - public WorkingHours(TimeSpan from, TimeSpan to) - { - From = from; - To = to; - } - - - private bool Equals(WorkingHours other) - { - return Enabled.Equals(other.Enabled) && From.Equals(other.From) && To.Equals(other.To); - } - - public override bool Equals(object obj) - { - if (obj is null) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != GetType()) return false; - return Equals((WorkingHours)obj); - } - - public override int GetHashCode() - { - return HashCode.Combine(Enabled, From, To); - } - } - - public class VoipUpload - { - public string Name { get; set; } - public string Path { get; set; } - public AudioType AudioType { get; set; } - public bool IsDefault { get; set; } - } - - #region Enum - - public enum AnswerType - { - Number, - Sip, - Client - } - - public enum GreetingMessageVoice - { - Man, - Woman, - Alice - } - - public enum AgentStatus - { - Online, - Paused, - Offline - } - - public enum AudioType - { - Greeting, - HoldUp, - VoiceMail, - Queue - } - - #endregion } + +public class Queue +{ + public string Id { get; set; } + public string Name { get; set; } + public int Size { get; set; } + public string WaitUrl { get; set; } + public int WaitTime { get; set; } + + public Queue() { } + + public Queue(string id, string name, int size, string waitUrl, int waitTime) + { + Id = id; + Name = name; + WaitUrl = waitUrl; + WaitTime = waitTime; + Size = size; + } +} + +public sealed class WorkingHours +{ + public bool Enabled { get; set; } + public TimeSpan? From { get; set; } + public TimeSpan? To { get; set; } + + public WorkingHours() { } + + public WorkingHours(TimeSpan from, TimeSpan to) + { + From = from; + To = to; + } + + + private bool Equals(WorkingHours other) + { + return Enabled.Equals(other.Enabled) && From.Equals(other.From) && To.Equals(other.To); + } + + public override bool Equals(object obj) + { + if (obj is null) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != GetType()) return false; + return Equals((WorkingHours)obj); + } + + public override int GetHashCode() + { + return HashCode.Combine(Enabled, From, To); + } +} + +public class VoipUpload +{ + public string Name { get; set; } + public string Path { get; set; } + public AudioType AudioType { get; set; } + public bool IsDefault { get; set; } +} + +public enum AnswerType +{ + Number, + Sip, + Client +} + +public enum GreetingMessageVoice +{ + Man, + Woman, + Alice +} + +public enum AgentStatus +{ + Online, + Paused, + Offline +} + +public enum AudioType +{ + Greeting, + HoldUp, + VoiceMail, + Queue +} \ No newline at end of file diff --git a/common/ASC.VoipService/VoipPhone.cs b/common/ASC.VoipService/VoipPhone.cs index 492b85c7f4..3b725d01bf 100644 --- a/common/ASC.VoipService/VoipPhone.cs +++ b/common/ASC.VoipService/VoipPhone.cs @@ -23,63 +23,62 @@ * */ -namespace ASC.VoipService +namespace ASC.VoipService; + +public class VoipPhone { - public class VoipPhone + public string Id { get; set; } + public string Number { get; set; } + public string Alias { get; set; } + public VoipSettings Settings { get; set; } + public Agent Caller { - public string Id { get; set; } - public string Number { get; set; } - public string Alias { get; set; } - public VoipSettings Settings { get; set; } - public Agent Caller - { - get { return Settings.Caller; } - } - - public VoipPhone(AuthContext authContext, TenantUtil tenantUtil, SecurityContext securityContext, BaseCommonLinkUtility baseCommonLinkUtility) - { - Settings = new VoipSettings(authContext, tenantUtil, securityContext, baseCommonLinkUtility); - } - - public virtual VoipCall Call(string to, string contactId = null) - { - throw new NotImplementedException(); - } - - public virtual VoipCall LocalCall(string to) - { - throw new NotImplementedException(); - } - - public virtual VoipCall RedirectCall(string callId, string to) - { - throw new NotImplementedException(); - } - - public virtual VoipCall HoldUp(string callId) - { - throw new NotImplementedException(); - } - - public virtual void AnswerQueueCall(string callId) - { - throw new NotImplementedException(); - } - - public virtual void RejectQueueCall(string callId) - { - throw new NotImplementedException(); - } + get { return Settings.Caller; } } - public class VoipRecord + public VoipPhone(AuthContext authContext, TenantUtil tenantUtil, SecurityContext securityContext, BaseCommonLinkUtility baseCommonLinkUtility) { - public string Id { get; set; } + Settings = new VoipSettings(authContext, tenantUtil, securityContext, baseCommonLinkUtility); + } - public string Uri { get; set; } + public virtual VoipCall Call(string to, string contactId = null) + { + throw new NotImplementedException(); + } - public int Duration { get; set; } + public virtual VoipCall LocalCall(string to) + { + throw new NotImplementedException(); + } - public decimal Price { get; set; } + public virtual VoipCall RedirectCall(string callId, string to) + { + throw new NotImplementedException(); + } + + public virtual VoipCall HoldUp(string callId) + { + throw new NotImplementedException(); + } + + public virtual void AnswerQueueCall(string callId) + { + throw new NotImplementedException(); + } + + public virtual void RejectQueueCall(string callId) + { + throw new NotImplementedException(); } } + +public class VoipRecord +{ + public string Id { get; set; } + + public string Uri { get; set; } + + public int Duration { get; set; } + + public decimal Price { get; set; } +} \ No newline at end of file diff --git a/common/ASC.VoipService/VoipSettings.cs b/common/ASC.VoipService/VoipSettings.cs index b688cea3bb..36ebf034b2 100644 --- a/common/ASC.VoipService/VoipSettings.cs +++ b/common/ASC.VoipService/VoipSettings.cs @@ -23,165 +23,164 @@ * */ -namespace ASC.VoipService +namespace ASC.VoipService; + +public class VoipSettings { - public class VoipSettings + public string VoiceUrl { get; set; } + + public string Name { get; set; } + + public List Operators { get; set; } + + public Queue Queue { get; set; } + + public Agent Caller { get { return Operators.FirstOrDefault(r => r.Id == AuthContext.CurrentAccount.ID); } } + + public WorkingHours WorkingHours { get; set; } + + public string VoiceMail { get; set; } + + public string GreetingAudio { get; set; } + + public string HoldAudio { get; set; } + + public bool AllowOutgoingCalls { get; set; } + + public bool Pause { get; set; } + + public bool Record { get; set; } + + internal string JsonSettings { - public string VoiceUrl { get; set; } - - public string Name { get; set; } - - public List Operators { get; set; } - - public Queue Queue { get; set; } - - public Agent Caller { get { return Operators.FirstOrDefault(r => r.Id == AuthContext.CurrentAccount.ID); } } - - public WorkingHours WorkingHours { get; set; } - - public string VoiceMail { get; set; } - - public string GreetingAudio { get; set; } - - public string HoldAudio { get; set; } - - public bool AllowOutgoingCalls { get; set; } - - public bool Pause { get; set; } - - public bool Record { get; set; } - - internal string JsonSettings + get { - get + return JsonConvert.SerializeObject( + new + { + Operators, + GreetingAudio, + Name, + Queue, + WorkingHours, + VoiceMail, + HoldAudio, + AllowOutgoingCalls, + Pause, + Record + }, + new JsonSerializerSettings { ContractResolver = CustomSerializeContractResolver.Instance }); + } + set + { + try { - return JsonConvert.SerializeObject( - new - { - Operators, - GreetingAudio, - Name, - Queue, - WorkingHours, - VoiceMail, - HoldAudio, - AllowOutgoingCalls, - Pause, - Record - }, - new JsonSerializerSettings { ContractResolver = CustomSerializeContractResolver.Instance }); + var settings = JsonConvert.DeserializeObject(value, new JsonSerializerSettings { ContractResolver = CustomSerializeContractResolver.Instance }); + + Operators = settings.Operators ?? new List(); + Name = settings.Name; + Queue = settings.Queue; + WorkingHours = settings.WorkingHours; + GreetingAudio = settings.GreetingAudio; + VoiceMail = settings.VoiceMail; + HoldAudio = settings.HoldAudio; + AllowOutgoingCalls = settings.AllowOutgoingCalls; + Pause = settings.Pause; + Record = settings.Record; } - set + catch (Exception) { - try - { - var settings = JsonConvert.DeserializeObject(value, new JsonSerializerSettings { ContractResolver = CustomSerializeContractResolver.Instance }); - - Operators = settings.Operators ?? new List(); - Name = settings.Name; - Queue = settings.Queue; - WorkingHours = settings.WorkingHours; - GreetingAudio = settings.GreetingAudio; - VoiceMail = settings.VoiceMail; - HoldAudio = settings.HoldAudio; - AllowOutgoingCalls = settings.AllowOutgoingCalls; - Pause = settings.Pause; - Record = settings.Record; - } - catch (Exception) - { - - } } - } - protected AuthContext AuthContext { get; } - protected TenantUtil TenantUtil { get; } - protected SecurityContext SecurityContext { get; } - protected BaseCommonLinkUtility BaseCommonLinkUtility { get; } - - public VoipSettings(AuthContext authContext, TenantUtil tenantUtil, SecurityContext securityContext, BaseCommonLinkUtility baseCommonLinkUtility) - { - Operators = new List(); - AuthContext = authContext; - TenantUtil = tenantUtil; - SecurityContext = securityContext; - BaseCommonLinkUtility = baseCommonLinkUtility; - } - - public VoipSettings(string settings, AuthContext authContext) - { - JsonSettings = settings; - AuthContext = authContext; - } - - public virtual string Connect(bool user = true, string contactId = null) - { - throw new NotImplementedException(); - } - - public virtual string Redirect(string to) - { - throw new NotImplementedException(); - } - - public virtual string Dequeue(bool reject) - { - throw new NotImplementedException(); - } - - public override string ToString() - { - return JsonSettings; - } - - public VoipSettings GetSettings(string settings) - { - return new VoipSettings(AuthContext, TenantUtil, SecurityContext, BaseCommonLinkUtility) { JsonSettings = settings }; } } - class CustomSerializeContractResolver : CamelCasePropertyNamesContractResolver + protected AuthContext AuthContext { get; } + protected TenantUtil TenantUtil { get; } + protected SecurityContext SecurityContext { get; } + protected BaseCommonLinkUtility BaseCommonLinkUtility { get; } + + public VoipSettings(AuthContext authContext, TenantUtil tenantUtil, SecurityContext securityContext, BaseCommonLinkUtility baseCommonLinkUtility) { - public static readonly CustomSerializeContractResolver Instance = new CustomSerializeContractResolver(); - - protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) - { - var property = base.CreateProperty(member, memberSerialization); - - if (property.PropertyName == "voiceMail") - { - property.Converter = new VoiceMailConverter(); - } - - return property; - } + Operators = new List(); + AuthContext = authContext; + TenantUtil = tenantUtil; + SecurityContext = securityContext; + BaseCommonLinkUtility = baseCommonLinkUtility; } - class VoiceMailConverter : JsonConverter + public VoipSettings(string settings, AuthContext authContext) { - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + JsonSettings = settings; + AuthContext = authContext; + } + + public virtual string Connect(bool user = true, string contactId = null) + { + throw new NotImplementedException(); + } + + public virtual string Redirect(string to) + { + throw new NotImplementedException(); + } + + public virtual string Dequeue(bool reject) + { + throw new NotImplementedException(); + } + + public override string ToString() + { + return JsonSettings; + } + + public VoipSettings GetSettings(string settings) + { + return new VoipSettings(AuthContext, TenantUtil, SecurityContext, BaseCommonLinkUtility) { JsonSettings = settings }; + } +} + +class CustomSerializeContractResolver : CamelCasePropertyNamesContractResolver +{ + public static readonly CustomSerializeContractResolver Instance = new CustomSerializeContractResolver(); + + protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) + { + var property = base.CreateProperty(member, memberSerialization); + + if (property.PropertyName == "voiceMail") { - serializer.Serialize(writer, value); + property.Converter = new VoiceMailConverter(); } - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + return property; + } +} + +class VoiceMailConverter : JsonConverter +{ + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + serializer.Serialize(writer, value); + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + if (reader.ValueType != null && reader.ValueType.Name == "String") { - if (reader.ValueType != null && reader.ValueType.Name == "String") - { - return reader.Value; - } - - var jObject = JObject.Load(reader); - var url = jObject.Value("url"); - - return !string.IsNullOrEmpty(url) ? url : ""; + return reader.Value; } - public override bool CanConvert(Type objectType) - { - return true; - } + var jObject = JObject.Load(reader); + var url = jObject.Value("url"); + + return !string.IsNullOrEmpty(url) ? url : ""; + } + + public override bool CanConvert(Type objectType) + { + return true; } } \ No newline at end of file From 0e2feb0a35d0fddc8216859eed47376d45e18104 Mon Sep 17 00:00:00 2001 From: SuhorukovAnton Date: Thu, 17 Feb 2022 12:08:01 +0300 Subject: [PATCH 04/28] refactoring: texttile --- common/ASC.Textile/BlockModifier.cs | 25 +- common/ASC.Textile/BlockModifierAttribute.cs | 11 +- .../Blocks/BlockAttributesParser.cs | 235 +++++++------- .../Blocks/BoldPhraseBlockModifier.cs | 11 +- .../Blocks/CapitalsBlockModifier.cs | 27 +- .../Blocks/CitePhraseBlockModifier.cs | 11 +- .../ASC.Textile/Blocks/CodeBlockModifier.cs | 81 +++-- .../Blocks/DeletedPhraseBlockModifier.cs | 11 +- .../Blocks/EmphasisPhraseBlockModifier.cs | 11 +- .../Blocks/FootNoteReferenceBlockModifier.cs | 11 +- .../ASC.Textile/Blocks/GlyphBlockModifier.cs | 135 ++++---- .../Blocks/HyperLinkBlockModifier.cs | 73 +++-- .../ASC.Textile/Blocks/ImageBlockModifier.cs | 99 +++--- .../Blocks/InsertedPhraseBlockModifier.cs | 11 +- .../Blocks/ItalicPhraseBlockModifier.cs | 11 +- .../Blocks/NoTextileBlockModifier.cs | 31 +- common/ASC.Textile/Blocks/NoTextileEncoder.cs | 131 ++++---- .../ASC.Textile/Blocks/PhraseBlockModifier.cs | 123 ++++--- common/ASC.Textile/Blocks/PreBlockModifier.cs | 43 ++- .../Blocks/SpanPhraseBlockModifier.cs | 11 +- .../Blocks/StrongPhraseBlockModifier.cs | 13 +- .../Blocks/SubScriptPhraseBlockModifier.cs | 13 +- .../Blocks/SuperScriptPhraseBlockModifier.cs | 11 +- common/ASC.Textile/FormatterState.cs | 229 +++++++------ common/ASC.Textile/FormatterStateAttribute.cs | 31 +- common/ASC.Textile/Globals.cs | 131 ++++---- common/ASC.Textile/IOutputter.cs | 63 ++-- .../States/BlockQuoteFormatterState.cs | 59 ++-- .../ASC.Textile/States/CodeFormatterState.cs | 149 +++++---- .../States/FootNoteFormatterState.cs | 75 +++-- .../States/HeaderFormatterState.cs | 157 +++++---- .../ASC.Textile/States/ListFormatterState.cs | 34 +- .../States/NoTextileFormatterState.cs | 99 +++--- .../States/OrderedListFormatterState.cs | 51 ++- .../States/ParagraphFormatterState.cs | 65 ++-- .../States/PassthroughFormatterState.cs | 59 ++-- .../States/PreCodeFormatterState.cs | 93 +++--- .../ASC.Textile/States/PreFormatterState.cs | 143 +++++---- .../States/SimpleBlockFormatterState.cs | 121 ++++--- common/ASC.Textile/States/TableCellParser.cs | 83 +++-- .../ASC.Textile/States/TableFormatterState.cs | 103 +++--- .../States/TableRowFormatterState.cs | 139 ++++---- .../States/UnorderedListFormatterState.cs | 61 ++-- .../StringBuilderTextileFormatter.cs | 69 ++-- common/ASC.Textile/StyleReader.cs | 37 ++- common/ASC.Textile/TextileFormatter.cs | 301 +++++++++--------- common/ASC.Textile/TextileFormatterBlocks.cs | 65 ++-- .../ASC.Textile/TextileFormatterFormatting.cs | 189 ++++++----- common/ASC.Textile/TextileFormatterStates.cs | 266 ++++++++-------- 49 files changed, 1979 insertions(+), 2032 deletions(-) diff --git a/common/ASC.Textile/BlockModifier.cs b/common/ASC.Textile/BlockModifier.cs index 4a0d63174e..f0cb398ba1 100644 --- a/common/ASC.Textile/BlockModifier.cs +++ b/common/ASC.Textile/BlockModifier.cs @@ -1,19 +1,18 @@ -namespace Textile +namespace Textile; + +public class BlockModifier { - public class BlockModifier + protected BlockModifier() { - protected BlockModifier() - { - } + } - public virtual string ModifyLine(string line) - { - return line; - } + public virtual string ModifyLine(string line) + { + return line; + } - public virtual string Conclude(string line) - { - return line; - } + public virtual string Conclude(string line) + { + return line; } } diff --git a/common/ASC.Textile/BlockModifierAttribute.cs b/common/ASC.Textile/BlockModifierAttribute.cs index 0d28eb6f02..f516e9b6ca 100644 --- a/common/ASC.Textile/BlockModifierAttribute.cs +++ b/common/ASC.Textile/BlockModifierAttribute.cs @@ -1,10 +1,9 @@ -namespace Textile +namespace Textile; + +[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] +public sealed class BlockModifierAttribute : Attribute { - [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] - public sealed class BlockModifierAttribute : Attribute + public BlockModifierAttribute() { - public BlockModifierAttribute() - { - } } } diff --git a/common/ASC.Textile/Blocks/BlockAttributesParser.cs b/common/ASC.Textile/Blocks/BlockAttributesParser.cs index 2946471efd..8315925a23 100644 --- a/common/ASC.Textile/Blocks/BlockAttributesParser.cs +++ b/common/ASC.Textile/Blocks/BlockAttributesParser.cs @@ -10,142 +10,141 @@ // You must not remove this notice, or any other, from this software. #endregion -namespace Textile.Blocks -{ - public static class BlockAttributesParser - { - public static StyleReader Styler { get; set; } +namespace Textile.Blocks; - /// - /// - /// - /// - /// - static public string ParseBlockAttributes(string input) +public static class BlockAttributesParser +{ + public static StyleReader Styler { get; set; } + + /// + /// + /// + /// + /// + static public string ParseBlockAttributes(string input) + { + return ParseBlockAttributes(input, ""); + } + + /// + /// + /// + /// + /// + /// + static public string ParseBlockAttributes(string input, string element) + { + var style = string.Empty; + var cssClass = string.Empty; + var lang = string.Empty; + var colspan = string.Empty; + var rowspan = string.Empty; + var id = string.Empty; + + if (Styler != null) { - return ParseBlockAttributes(input, ""); + style = GetStyle(element, style); } - /// - /// - /// - /// - /// - /// - static public string ParseBlockAttributes(string input, string element) + if (input.Length == 0) + return style.Length > 0 ? " style=\"" + style + "\"" : ""; + + + Match m; + var matched = input; + if (element == "td") { - var style = string.Empty; - var cssClass = string.Empty; - var lang = string.Empty; - var colspan = string.Empty; - var rowspan = string.Empty; - var id = string.Empty; - - if (Styler != null) - { - style = GetStyle(element, style); - } - - if (input.Length == 0) - return style.Length > 0 ? " style=\"" + style + "\"" : ""; - - - Match m; - var matched = input; - if (element == "td") - { - // column span - m = Regex.Match(matched, @"\\(\d+)"); - if (m.Success) - colspan = m.Groups[1].Value; - // row span - m = Regex.Match(matched, @"/(\d+)"); - if (m.Success) - rowspan = m.Groups[1].Value; - // vertical align - m = Regex.Match(matched, @"(" + Globals.VerticalAlignPattern + @")"); - if (m.Success) - style += "vertical-align:" + Globals.VerticalAlign[m.Captures[0].Value] + ";"; - } - - // First, match custom styles - m = Regex.Match(matched, @"\{([^}]*)\}"); + // column span + m = Regex.Match(matched, @"\\(\d+)"); if (m.Success) - { - style += m.Groups[1].Value + ";"; - matched = matched.Replace(m.ToString(), ""); - } - - // Then match the language - m = Regex.Match(matched, @"\[([^()]+)\]"); + colspan = m.Groups[1].Value; + // row span + m = Regex.Match(matched, @"/(\d+)"); if (m.Success) - { - lang = m.Groups[1].Value; - matched = matched.Replace(m.ToString(), ""); - } + rowspan = m.Groups[1].Value; + // vertical align + m = Regex.Match(matched, @"(" + Globals.VerticalAlignPattern + @")"); + if (m.Success) + style += "vertical-align:" + Globals.VerticalAlign[m.Captures[0].Value] + ";"; + } - // Match classes and IDs after that - m = Regex.Match(matched, @"\(([^()]+)\)"); + // First, match custom styles + m = Regex.Match(matched, @"\{([^}]*)\}"); + if (m.Success) + { + style += m.Groups[1].Value + ";"; + matched = matched.Replace(m.ToString(), ""); + } + + // Then match the language + m = Regex.Match(matched, @"\[([^()]+)\]"); + if (m.Success) + { + lang = m.Groups[1].Value; + matched = matched.Replace(m.ToString(), ""); + } + + // Match classes and IDs after that + m = Regex.Match(matched, @"\(([^()]+)\)"); + if (m.Success) + { + cssClass = m.Groups[1].Value; + matched = matched.Replace(m.ToString(), ""); + + // Separate the public class and the ID + m = Regex.Match(cssClass, @"^(.*)#(.*)$"); if (m.Success) { cssClass = m.Groups[1].Value; - matched = matched.Replace(m.ToString(), ""); - - // Separate the public class and the ID - m = Regex.Match(cssClass, @"^(.*)#(.*)$"); - if (m.Success) - { - cssClass = m.Groups[1].Value; - id = m.Groups[2].Value; - } - if (Styler != null && !string.IsNullOrEmpty(cssClass)) - { - style = GetStyle("." + cssClass, style); - } - + id = m.Groups[2].Value; } - - // Get the padding on the left - m = Regex.Match(matched, @"([(]+)"); - if (m.Success) + if (Styler != null && !string.IsNullOrEmpty(cssClass)) { - style += "padding-left:" + m.Groups[1].Length + "em;"; - matched = matched.Replace(m.ToString(), ""); + style = GetStyle("." + cssClass, style); } - // Get the padding on the right - m = Regex.Match(matched, @"([)]+)"); - if (m.Success) - { - style += "padding-right:" + m.Groups[1].Length + "em;"; - matched = matched.Replace(m.ToString(), ""); - } - - // Get the text alignment - m = Regex.Match(matched, "(" + Globals.HorizontalAlignPattern + ")"); - if (m.Success) - style += "text-align:" + Globals.HorizontalAlign[m.Groups[1].Value] + ";"; - - - - return - (style.Length > 0 ? " style=\"" + style + "\"" : "") + - (cssClass.Length > 0 ? " class=\"" + cssClass + "\"" : "") + - (lang.Length > 0 ? " lang=\"" + lang + "\"" : "") + - (id.Length > 0 ? " id=\"" + id + "\"" : "") + - (colspan.Length > 0 ? " colspan=\"" + colspan + "\"" : "") + - (rowspan.Length > 0 ? " rowspan=\"" + rowspan + "\"" : "") - ; } - private static string GetStyle(string element, string style) + // Get the padding on the left + m = Regex.Match(matched, @"([(]+)"); + if (m.Success) { - var styled = Styler.GetStyle(element); - if (!string.IsNullOrEmpty(styled)) - { - style += styled; - } - return style; + style += "padding-left:" + m.Groups[1].Length + "em;"; + matched = matched.Replace(m.ToString(), ""); } + + // Get the padding on the right + m = Regex.Match(matched, @"([)]+)"); + if (m.Success) + { + style += "padding-right:" + m.Groups[1].Length + "em;"; + matched = matched.Replace(m.ToString(), ""); + } + + // Get the text alignment + m = Regex.Match(matched, "(" + Globals.HorizontalAlignPattern + ")"); + if (m.Success) + style += "text-align:" + Globals.HorizontalAlign[m.Groups[1].Value] + ";"; + + + + return + (style.Length > 0 ? " style=\"" + style + "\"" : "") + + (cssClass.Length > 0 ? " class=\"" + cssClass + "\"" : "") + + (lang.Length > 0 ? " lang=\"" + lang + "\"" : "") + + (id.Length > 0 ? " id=\"" + id + "\"" : "") + + (colspan.Length > 0 ? " colspan=\"" + colspan + "\"" : "") + + (rowspan.Length > 0 ? " rowspan=\"" + rowspan + "\"" : "") + ; + } + + private static string GetStyle(string element, string style) + { + var styled = Styler.GetStyle(element); + if (!string.IsNullOrEmpty(styled)) + { + style += styled; + } + return style; } } diff --git a/common/ASC.Textile/Blocks/BoldPhraseBlockModifier.cs b/common/ASC.Textile/Blocks/BoldPhraseBlockModifier.cs index 9d195736a2..abf1eca805 100644 --- a/common/ASC.Textile/Blocks/BoldPhraseBlockModifier.cs +++ b/common/ASC.Textile/Blocks/BoldPhraseBlockModifier.cs @@ -1,10 +1,9 @@ -namespace Textile.Blocks +namespace Textile.Blocks; + +public class BoldPhraseBlockModifier : PhraseBlockModifier { - public class BoldPhraseBlockModifier : PhraseBlockModifier + public override string ModifyLine(string line) { - public override string ModifyLine(string line) - { - return PhraseModifierFormat(line, @"\*\*", "b"); - } + return PhraseModifierFormat(line, @"\*\*", "b"); } } diff --git a/common/ASC.Textile/Blocks/CapitalsBlockModifier.cs b/common/ASC.Textile/Blocks/CapitalsBlockModifier.cs index 7a7963ea10..3a4d8804bb 100644 --- a/common/ASC.Textile/Blocks/CapitalsBlockModifier.cs +++ b/common/ASC.Textile/Blocks/CapitalsBlockModifier.cs @@ -1,17 +1,16 @@ -namespace Textile.Blocks -{ - public class CapitalsBlockModifier : BlockModifier - { - public override string ModifyLine(string line) - { - var me = new MatchEvaluator(CapitalsFormatMatchEvaluator); - line = Regex.Replace(line, @"(?<=^|\s|" + Globals.PunctuationPattern + @")(?[A-Z][A-Z0-9]+)(?=$|\s|" + Globals.PunctuationPattern + @")", me); - return line; - } +namespace Textile.Blocks; - private string CapitalsFormatMatchEvaluator(Match m) - { - return @"" + m.Groups["caps"].Value + @""; - } +public class CapitalsBlockModifier : BlockModifier +{ + public override string ModifyLine(string line) + { + var me = new MatchEvaluator(CapitalsFormatMatchEvaluator); + line = Regex.Replace(line, @"(?<=^|\s|" + Globals.PunctuationPattern + @")(?[A-Z][A-Z0-9]+)(?=$|\s|" + Globals.PunctuationPattern + @")", me); + return line; + } + + private string CapitalsFormatMatchEvaluator(Match m) + { + return @"" + m.Groups["caps"].Value + @""; } } diff --git a/common/ASC.Textile/Blocks/CitePhraseBlockModifier.cs b/common/ASC.Textile/Blocks/CitePhraseBlockModifier.cs index e91b0eea4c..b39671e4fb 100644 --- a/common/ASC.Textile/Blocks/CitePhraseBlockModifier.cs +++ b/common/ASC.Textile/Blocks/CitePhraseBlockModifier.cs @@ -1,10 +1,9 @@ -namespace Textile.Blocks +namespace Textile.Blocks; + +public class CitePhraseBlockModifier : PhraseBlockModifier { - public class CitePhraseBlockModifier : PhraseBlockModifier + public override string ModifyLine(string line) { - public override string ModifyLine(string line) - { - return PhraseModifierFormat(line, @"\?\?", "cite"); - } + return PhraseModifierFormat(line, @"\?\?", "cite"); } } diff --git a/common/ASC.Textile/Blocks/CodeBlockModifier.cs b/common/ASC.Textile/Blocks/CodeBlockModifier.cs index 2c825aef81..5d7b26ec35 100644 --- a/common/ASC.Textile/Blocks/CodeBlockModifier.cs +++ b/common/ASC.Textile/Blocks/CodeBlockModifier.cs @@ -10,47 +10,46 @@ // You must not remove this notice, or any other, from this software. #endregion -namespace Textile.Blocks +namespace Textile.Blocks; + +public class CodeBlockModifier : BlockModifier { - public class CodeBlockModifier : BlockModifier + public override string ModifyLine(string line) { - public override string ModifyLine(string line) - { - // Replace "@...@" zones with "" tags. - var me = new MatchEvaluator(CodeFormatMatchEvaluator); - line = Regex.Replace(line, - @"(?^|([\s\([{]))" + // before - "@" + - @"(\|(?\w+)\|)?" + // lang - "(?[^@]+)" + // code - "@" + - @"(?$|([\]}])|(?=" + Globals.PunctuationPattern + @"{1,2}|\s|$))", // after - me); - // Encode the contents of the "" tags so that we don't - // generate formatting out of it. - line = NoTextileEncoder.EncodeNoTextileZones(line, - @"(?<=(^|\s))", - @"(?=)"); - return line; - } - - public override string Conclude(string line) - { - // Recode everything except "<" and ">"; - line = NoTextileEncoder.DecodeNoTextileZones(line, - @"(?<=(^|\s))", - @"(?=)", - new string[] { "<", ">" }); - return line; - } - - public string CodeFormatMatchEvaluator(Match m) - { - var res = m.Groups["before"].Value + " 0) - res += " language=\"" + m.Groups["lang"].Value + "\""; - res += ">" + m.Groups["code"].Value + "" + m.Groups["after"].Value; - return res; - } + // Replace "@...@" zones with "" tags. + var me = new MatchEvaluator(CodeFormatMatchEvaluator); + line = Regex.Replace(line, + @"(?^|([\s\([{]))" + // before + "@" + + @"(\|(?\w+)\|)?" + // lang + "(?[^@]+)" + // code + "@" + + @"(?$|([\]}])|(?=" + Globals.PunctuationPattern + @"{1,2}|\s|$))", // after + me); + // Encode the contents of the "" tags so that we don't + // generate formatting out of it. + line = NoTextileEncoder.EncodeNoTextileZones(line, + @"(?<=(^|\s))", + @"(?=)"); + return line; } -} + + public override string Conclude(string line) + { + // Recode everything except "<" and ">"; + line = NoTextileEncoder.DecodeNoTextileZones(line, + @"(?<=(^|\s))", + @"(?=)", + new string[] { "<", ">" }); + return line; + } + + public string CodeFormatMatchEvaluator(Match m) + { + var res = m.Groups["before"].Value + " 0) + res += " language=\"" + m.Groups["lang"].Value + "\""; + res += ">" + m.Groups["code"].Value + "" + m.Groups["after"].Value; + return res; + } +} \ No newline at end of file diff --git a/common/ASC.Textile/Blocks/DeletedPhraseBlockModifier.cs b/common/ASC.Textile/Blocks/DeletedPhraseBlockModifier.cs index a8c4ac2916..f0c7816918 100644 --- a/common/ASC.Textile/Blocks/DeletedPhraseBlockModifier.cs +++ b/common/ASC.Textile/Blocks/DeletedPhraseBlockModifier.cs @@ -1,10 +1,9 @@ -namespace Textile.Blocks +namespace Textile.Blocks; + +public class DeletedPhraseBlockModifier : PhraseBlockModifier { - public class DeletedPhraseBlockModifier : PhraseBlockModifier + public override string ModifyLine(string line) { - public override string ModifyLine(string line) - { - return PhraseModifierFormat(line, @"\-", "del"); - } + return PhraseModifierFormat(line, @"\-", "del"); } } diff --git a/common/ASC.Textile/Blocks/EmphasisPhraseBlockModifier.cs b/common/ASC.Textile/Blocks/EmphasisPhraseBlockModifier.cs index 96ce7210f6..ee2b49d44c 100644 --- a/common/ASC.Textile/Blocks/EmphasisPhraseBlockModifier.cs +++ b/common/ASC.Textile/Blocks/EmphasisPhraseBlockModifier.cs @@ -1,10 +1,9 @@ -namespace Textile.Blocks +namespace Textile.Blocks; + +public class EmphasisPhraseBlockModifier : PhraseBlockModifier { - public class EmphasisPhraseBlockModifier : PhraseBlockModifier + public override string ModifyLine(string line) { - public override string ModifyLine(string line) - { - return PhraseModifierFormat(line, @"_", "em"); - } + return PhraseModifierFormat(line, @"_", "em"); } } diff --git a/common/ASC.Textile/Blocks/FootNoteReferenceBlockModifier.cs b/common/ASC.Textile/Blocks/FootNoteReferenceBlockModifier.cs index bafc735672..787416329a 100644 --- a/common/ASC.Textile/Blocks/FootNoteReferenceBlockModifier.cs +++ b/common/ASC.Textile/Blocks/FootNoteReferenceBlockModifier.cs @@ -10,13 +10,12 @@ // You must not remove this notice, or any other, from this software. #endregion -namespace Textile.Blocks +namespace Textile.Blocks; + +public class FootNoteReferenceBlockModifier : BlockModifier { - public class FootNoteReferenceBlockModifier : BlockModifier + public override string ModifyLine(string line) { - public override string ModifyLine(string line) - { - return Regex.Replace(line, @"\b\[([0-9]+)\](\W)", "$1$2"); - } + return Regex.Replace(line, @"\b\[([0-9]+)\](\W)", "$1$2"); } } diff --git a/common/ASC.Textile/Blocks/GlyphBlockModifier.cs b/common/ASC.Textile/Blocks/GlyphBlockModifier.cs index 93b16f8855..1509d0b74d 100644 --- a/common/ASC.Textile/Blocks/GlyphBlockModifier.cs +++ b/common/ASC.Textile/Blocks/GlyphBlockModifier.cs @@ -10,79 +10,78 @@ // You must not remove this notice, or any other, from this software. #endregion -namespace Textile.Blocks +namespace Textile.Blocks; + +public class GlyphBlockModifier : BlockModifier { - public class GlyphBlockModifier : BlockModifier + public override string ModifyLine(string line) { - public override string ModifyLine(string line) + line = Regex.Replace(line, "\"\\z", "\" "); + + // fix: hackish + string[,] glyphs = { + { @"([^\s[{(>_*])?\'(?(1)|(\s|s\b|" + Globals.PunctuationPattern + @"))", "$1’$2" }, // single closing + { @"\'", "‘" }, // single opening + { @"([^\s[{(>_*])?""(?(1)|(\s|" + Globals.PunctuationPattern + @"))", "$1”$2" }, // double closing + { @"""", "“" }, // double opening + { @"\b( )?\.{3}", "$1…" }, // ellipsis + { @"\b([A-Z][A-Z0-9]{2,})\b(?:[(]([^)]*)[)])", "$1" }, // 3+ uppercase acronym + { @"(\s)?--(\s)?", "$1—$2" }, // em dash + { @"\s-\s", " – " }, // en dash + { @"(\d+)( )?x( )?(\d+)", "$1$2×$3$4" }, // dimension sign + { @"\b ?[([](TM|tm)[])]", "™" }, // trademark + { @"\b ?[([](R|r)[])]", "®" }, // registered + { @"\b ?[([](C|c)[])]", "©" } // copyright + }; + + var sb = new StringBuilder(); + + if (!Regex.IsMatch(line, "<.*>")) { - line = Regex.Replace(line, "\"\\z", "\" "); - - // fix: hackish - string[,] glyphs = { - { @"([^\s[{(>_*])?\'(?(1)|(\s|s\b|" + Globals.PunctuationPattern + @"))", "$1’$2" }, // single closing - { @"\'", "‘" }, // single opening - { @"([^\s[{(>_*])?""(?(1)|(\s|" + Globals.PunctuationPattern + @"))", "$1”$2" }, // double closing - { @"""", "“" }, // double opening - { @"\b( )?\.{3}", "$1…" }, // ellipsis - { @"\b([A-Z][A-Z0-9]{2,})\b(?:[(]([^)]*)[)])", "$1" }, // 3+ uppercase acronym - { @"(\s)?--(\s)?", "$1—$2" }, // em dash - { @"\s-\s", " – " }, // en dash - { @"(\d+)( )?x( )?(\d+)", "$1$2×$3$4" }, // dimension sign - { @"\b ?[([](TM|tm)[])]", "™" }, // trademark - { @"\b ?[([](R|r)[])]", "®" }, // registered - { @"\b ?[([](C|c)[])]", "©" } // copyright - }; - - var sb = new StringBuilder(); - - if (!Regex.IsMatch(line, "<.*>")) + // If no HTML, do a simple search & replace. + for (var i = 0; i < glyphs.GetLength(0); ++i) { - // If no HTML, do a simple search & replace. - for (var i = 0; i < glyphs.GetLength(0); ++i) - { - line = Regex.Replace(line, glyphs[i, 0], glyphs[i, 1]); - } - sb.Append(line); + line = Regex.Replace(line, glyphs[i, 0], glyphs[i, 1]); } - else - { - var splits = Regex.Split(line, "(<.*?>)"); - var offtags = "code|pre|notextile"; - var codepre = false; - - foreach (var split in splits) - { - var modifiedSplit = split; - if (modifiedSplit.Length == 0) - continue; - - if (Regex.IsMatch(modifiedSplit, @"<(" + offtags + ")>")) - codepre = true; - if (Regex.IsMatch(modifiedSplit, @"<\/(" + offtags + ")>")) - codepre = false; - - if (!Regex.IsMatch(modifiedSplit, "<.*>") && !codepre) - { - for (var i = 0; i < glyphs.GetLength(0); ++i) - { - modifiedSplit = Regex.Replace(modifiedSplit, glyphs[i, 0], glyphs[i, 1]); - } - } - - // do htmlspecial if between - if (codepre) - { - //TODO: htmlspecialchars(line) - //line = Regex.Replace(line, @"<(\/?" + offtags + ")>", "<$1>"); - //line = line.Replace("&#", "&#"); - } - - sb.Append(modifiedSplit); - } - } - - return sb.ToString(); + sb.Append(line); } + else + { + var splits = Regex.Split(line, "(<.*?>)"); + var offtags = "code|pre|notextile"; + var codepre = false; + + foreach (var split in splits) + { + var modifiedSplit = split; + if (modifiedSplit.Length == 0) + continue; + + if (Regex.IsMatch(modifiedSplit, @"<(" + offtags + ")>")) + codepre = true; + if (Regex.IsMatch(modifiedSplit, @"<\/(" + offtags + ")>")) + codepre = false; + + if (!Regex.IsMatch(modifiedSplit, "<.*>") && !codepre) + { + for (var i = 0; i < glyphs.GetLength(0); ++i) + { + modifiedSplit = Regex.Replace(modifiedSplit, glyphs[i, 0], glyphs[i, 1]); + } + } + + // do htmlspecial if between + if (codepre) + { + //TODO: htmlspecialchars(line) + //line = Regex.Replace(line, @"<(\/?" + offtags + ")>", "<$1>"); + //line = line.Replace("&#", "&#"); + } + + sb.Append(modifiedSplit); + } + } + + return sb.ToString(); } } diff --git a/common/ASC.Textile/Blocks/HyperLinkBlockModifier.cs b/common/ASC.Textile/Blocks/HyperLinkBlockModifier.cs index c7fa26bb61..b4bdcf1408 100644 --- a/common/ASC.Textile/Blocks/HyperLinkBlockModifier.cs +++ b/common/ASC.Textile/Blocks/HyperLinkBlockModifier.cs @@ -11,46 +11,45 @@ #endregion -namespace Textile.Blocks +namespace Textile.Blocks; + +public class HyperLinkBlockModifier : BlockModifier { - public class HyperLinkBlockModifier : BlockModifier + private readonly string _rel = string.Empty; + + public override string ModifyLine(string line) { - private readonly string m_rel = string.Empty; + line = Regex.Replace(line, + @"(?
[\s[{(]|" + Globals.PunctuationPattern + @")?" +       // $pre
+                                "\"" +									// start
+                                Globals.BlockModifiersPattern +			// attributes
+                                "(?[\\w\\W]+?)" +					// text
+                                @"\s?" +
+                                @"(?:\((?[^)]+)\)(?=""))?" +		// title
+                                "\":" +
+                                @"""(?<url>\S+[^""]+)""" +						// url
+                                @"(?<slash>\/)?" +						// slash
+                                @"(?<post>[^\w\/;]*)" +					// post
+                                @"(?=\s|$)",
+                                new MatchEvaluator(HyperLinksFormatMatchEvaluator));
+        return line;
+    }
 
-        public override string ModifyLine(string line)
-        {
-            line = Regex.Replace(line,
-                                    @"(?<pre>[\s[{(]|" + Globals.PunctuationPattern + @")?" +       // $pre
-                                    "\"" +									// start
-                                    Globals.BlockModifiersPattern +			// attributes
-                                    "(?<text>[\\w\\W]+?)" +					// text
-                                    @"\s?" +
-                                    @"(?:\((?<title>[^)]+)\)(?=""))?" +		// title
-                                    "\":" +
-                                    @"""(?<url>\S+[^""]+)""" +						// url
-                                    @"(?<slash>\/)?" +						// slash
-                                    @"(?<post>[^\w\/;]*)" +					// post
-                                    @"(?=\s|$)",
-                                   new MatchEvaluator(HyperLinksFormatMatchEvaluator));
-            return line;
-        }
+    private string HyperLinksFormatMatchEvaluator(Match m)
+    {
+        //TODO: check the URL
+        var atts = BlockAttributesParser.ParseBlockAttributes(m.Groups["atts"].Value, "a");
+        if (m.Groups["title"].Length > 0)
+            atts += " title=\"" + m.Groups["title"].Value + "\"";
+        var linkText = m.Groups["text"].Value.Trim(' ');
 
-        private string HyperLinksFormatMatchEvaluator(Match m)
-        {
-            //TODO: check the URL
-            var atts = BlockAttributesParser.ParseBlockAttributes(m.Groups["atts"].Value, "a");
-            if (m.Groups["title"].Length > 0)
-                atts += " title=\"" + m.Groups["title"].Value + "\"";
-            var linkText = m.Groups["text"].Value.Trim(' ');
-
-            var str = m.Groups["pre"].Value + "<a ";
-            if (!string.IsNullOrEmpty(m_rel))
-                str += "ref=\"" + m_rel + "\" ";
-            str += "href=\"" +
-                  m.Groups["url"].Value + m.Groups["slash"].Value + "\"" +
-                  atts +
-                  ">" + linkText + "</a>" + m.Groups["post"].Value;
-            return str;
-        }
+        var str = m.Groups["pre"].Value + "<a ";
+        if (!string.IsNullOrEmpty(_rel))
+            str += "ref=\"" + _rel + "\" ";
+        str += "href=\"" +
+                m.Groups["url"].Value + m.Groups["slash"].Value + "\"" +
+                atts +
+                ">" + linkText + "</a>" + m.Groups["post"].Value;
+        return str;
     }
 }
diff --git a/common/ASC.Textile/Blocks/ImageBlockModifier.cs b/common/ASC.Textile/Blocks/ImageBlockModifier.cs
index 73cba25946..24518fa017 100644
--- a/common/ASC.Textile/Blocks/ImageBlockModifier.cs
+++ b/common/ASC.Textile/Blocks/ImageBlockModifier.cs
@@ -10,60 +10,59 @@
 // You must not remove this notice, or any other, from this software.
 #endregion
 
-namespace Textile.Blocks
+namespace Textile.Blocks;
+
+public class ImageBlockModifier : BlockModifier
 {
-    public class ImageBlockModifier : BlockModifier
+    public override string ModifyLine(string line)
     {
-        public override string ModifyLine(string line)
+        line = Regex.Replace(line,
+                                @"\!" +                   // opening !
+                                @"(?<algn>\<|\=|\>)?" +   // optional alignment atts
+                                Globals.BlockModifiersPattern + // optional style, public class atts
+                                @"(?:\. )?" +             // optional dot-space
+                                @"(?<url>[^\s(!]+)" +     // presume this is the src
+                                @"\s?" +                  // optional space
+                                @"(?:\((?<title>([^\)]+))\))?" +// optional title
+                                @"\!" +                   // closing
+                                @"(?::(?<href>(\S+)))?" +     // optional href
+                                @"(?=\s|\.|,|;|\)|\||$)",               // lookahead: space or simple punctuation or end of string
+                            new MatchEvaluator(ImageFormatMatchEvaluator)
+                            );
+        return line;
+    }
+
+    string ImageFormatMatchEvaluator(Match m)
+    {
+        var atts = BlockAttributesParser.ParseBlockAttributes(m.Groups["atts"].Value, "img");
+        if (m.Groups["algn"].Length > 0)
+            atts += " align=\"" + Globals.ImageAlign[m.Groups["algn"].Value] + "\"";
+        if (m.Groups["title"].Length > 0)
         {
-            line = Regex.Replace(line,
-                                    @"\!" +                   // opening !
-                                    @"(?<algn>\<|\=|\>)?" +   // optional alignment atts
-                                    Globals.BlockModifiersPattern + // optional style, public class atts
-                                    @"(?:\. )?" +             // optional dot-space
-                                    @"(?<url>[^\s(!]+)" +     // presume this is the src
-                                    @"\s?" +                  // optional space
-                                    @"(?:\((?<title>([^\)]+))\))?" +// optional title
-                                    @"\!" +                   // closing
-                                    @"(?::(?<href>(\S+)))?" +     // optional href
-                                    @"(?=\s|\.|,|;|\)|\||$)",               // lookahead: space or simple punctuation or end of string
-                                new MatchEvaluator(ImageFormatMatchEvaluator)
-                                );
-            return line;
+            atts += " title=\"" + m.Groups["title"].Value + "\"";
+            atts += " alt=\"" + m.Groups["title"].Value + "\"";
+        }
+        else
+        {
+            atts += " alt=\"\"";
+        }
+        // Get Image Size?
+
+        var res = "<img src=\"" + m.Groups["url"].Value + "\"" + atts + " />";
+
+        if (m.Groups["href"].Length > 0)
+        {
+            var href = m.Groups["href"].Value;
+            var end = string.Empty;
+            var endMatch = Regex.Match(href, @"(.*)(?<end>\.|,|;|\))$");
+            if (m.Success && !string.IsNullOrEmpty(endMatch.Groups["end"].Value))
+            {
+                href = href[0..^1];
+                end = endMatch.Groups["end"].Value;
+            }
+            res = "<a href=\"" + Globals.EncodeHTMLLink(href) + "\">" + res + "</a>" + end;
         }
 
-        string ImageFormatMatchEvaluator(Match m)
-        {
-            var atts = BlockAttributesParser.ParseBlockAttributes(m.Groups["atts"].Value, "img");
-            if (m.Groups["algn"].Length > 0)
-                atts += " align=\"" + Globals.ImageAlign[m.Groups["algn"].Value] + "\"";
-            if (m.Groups["title"].Length > 0)
-            {
-                atts += " title=\"" + m.Groups["title"].Value + "\"";
-                atts += " alt=\"" + m.Groups["title"].Value + "\"";
-            }
-            else
-            {
-                atts += " alt=\"\"";
-            }
-            // Get Image Size?
-
-            var res = "<img src=\"" + m.Groups["url"].Value + "\"" + atts + " />";
-
-            if (m.Groups["href"].Length > 0)
-            {
-                var href = m.Groups["href"].Value;
-                var end = string.Empty;
-                var endMatch = Regex.Match(href, @"(.*)(?<end>\.|,|;|\))$");
-                if (m.Success && !string.IsNullOrEmpty(endMatch.Groups["end"].Value))
-                {
-                    href = href[0..^1];
-                    end = endMatch.Groups["end"].Value;
-                }
-                res = "<a href=\"" + Globals.EncodeHTMLLink(href) + "\">" + res + "</a>" + end;
-            }
-
-            return res;
-        }
+        return res;
     }
 }
diff --git a/common/ASC.Textile/Blocks/InsertedPhraseBlockModifier.cs b/common/ASC.Textile/Blocks/InsertedPhraseBlockModifier.cs
index 2e16731d28..ba3cda8e33 100644
--- a/common/ASC.Textile/Blocks/InsertedPhraseBlockModifier.cs
+++ b/common/ASC.Textile/Blocks/InsertedPhraseBlockModifier.cs
@@ -1,10 +1,9 @@
-namespace Textile.Blocks
+namespace Textile.Blocks;
+
+public class InsertedPhraseBlockModifier : PhraseBlockModifier
 {
-    public class InsertedPhraseBlockModifier : PhraseBlockModifier
+    public override string ModifyLine(string line)
     {
-        public override string ModifyLine(string line)
-        {
-            return PhraseModifierFormat(line, @"\+", "ins");
-        }
+        return PhraseModifierFormat(line, @"\+", "ins");
     }
 }
diff --git a/common/ASC.Textile/Blocks/ItalicPhraseBlockModifier.cs b/common/ASC.Textile/Blocks/ItalicPhraseBlockModifier.cs
index be69e9f9ce..6aa882d39f 100644
--- a/common/ASC.Textile/Blocks/ItalicPhraseBlockModifier.cs
+++ b/common/ASC.Textile/Blocks/ItalicPhraseBlockModifier.cs
@@ -1,10 +1,9 @@
-namespace Textile.Blocks
+namespace Textile.Blocks;
+
+public class ItalicPhraseBlockModifier : PhraseBlockModifier
 {
-    public class ItalicPhraseBlockModifier : PhraseBlockModifier
+    public override string ModifyLine(string line)
     {
-        public override string ModifyLine(string line)
-        {
-            return PhraseModifierFormat(line, @"__", "i");
-        }
+        return PhraseModifierFormat(line, @"__", "i");
     }
 }
diff --git a/common/ASC.Textile/Blocks/NoTextileBlockModifier.cs b/common/ASC.Textile/Blocks/NoTextileBlockModifier.cs
index b242d47a7e..af695396fe 100644
--- a/common/ASC.Textile/Blocks/NoTextileBlockModifier.cs
+++ b/common/ASC.Textile/Blocks/NoTextileBlockModifier.cs
@@ -11,22 +11,21 @@
 #endregion
 
 
-namespace Textile.Blocks
-{
-    public class NoTextileBlockModifier : BlockModifier
-    {
-        public override string ModifyLine(string line)
-        {
-            line = NoTextileEncoder.EncodeNoTextileZones(line, @"(?<=^|\s)<notextile>", @"</notextile>(?=(\s|$)?)");
-            line = NoTextileEncoder.EncodeNoTextileZones(line, @"==", @"==");
-            return line;
-        }
+namespace Textile.Blocks;
 
-        public override string Conclude(string line)
-        {
-            line = NoTextileEncoder.DecodeNoTextileZones(line, @"(?<=^|\s)<notextile>", @"</notextile>(?=(\s|$)?)");
-            line = NoTextileEncoder.DecodeNoTextileZones(line, @"==", @"==");
-            return line;
-        }
+public class NoTextileBlockModifier : BlockModifier
+{
+    public override string ModifyLine(string line)
+    {
+        line = NoTextileEncoder.EncodeNoTextileZones(line, @"(?<=^|\s)<notextile>", @"</notextile>(?=(\s|$)?)");
+        line = NoTextileEncoder.EncodeNoTextileZones(line, @"==", @"==");
+        return line;
+    }
+
+    public override string Conclude(string line)
+    {
+        line = NoTextileEncoder.DecodeNoTextileZones(line, @"(?<=^|\s)<notextile>", @"</notextile>(?=(\s|$)?)");
+        line = NoTextileEncoder.DecodeNoTextileZones(line, @"==", @"==");
+        return line;
     }
 }
diff --git a/common/ASC.Textile/Blocks/NoTextileEncoder.cs b/common/ASC.Textile/Blocks/NoTextileEncoder.cs
index 83391866d9..d6aa40e436 100644
--- a/common/ASC.Textile/Blocks/NoTextileEncoder.cs
+++ b/common/ASC.Textile/Blocks/NoTextileEncoder.cs
@@ -1,79 +1,78 @@
-namespace Textile.Blocks
+namespace Textile.Blocks;
+
+public static class NoTextileEncoder
 {
-    public static class NoTextileEncoder
+    private static readonly string[,] TextileModifiers = {
+                            { "\"", """ },
+                            { "%", "%" },
+                            { "*", "*" },
+                            { "+", "+" },
+                            { "-", "-" },
+                            { "<", "<" },   // or "<"
+            				{ "=", "=" },
+                            { ">", ">" },   // or ">"
+            				{ "?", "?" },
+                            { "^", "^" },
+                            { "_", "_" },
+                            { "~", "~" },
+                            { "@", "@" },
+                            { "'", "'" },
+                            { "|", "|" },
+                            { "!", "!" },
+                            { "(", "(" },
+                            { ")", ")" },
+                            { ".", "." },
+                            { "x", "x" }
+                        };
+
+
+    public static string EncodeNoTextileZones(string tmp, string patternPrefix, string patternSuffix)
     {
-        private static readonly string[,] TextileModifiers = {
-                                { "\"", """ },
-                                { "%", "%" },
-                                { "*", "*" },
-                                { "+", "+" },
-                                { "-", "-" },
-                                { "<", "<" },   // or "<"
-            					{ "=", "=" },
-                                { ">", ">" },   // or ">"
-            					{ "?", "?" },
-                                { "^", "^" },
-                                { "_", "_" },
-                                { "~", "~" },
-                                { "@", "@" },
-                                { "'", "'" },
-                                { "|", "|" },
-                                { "!", "!" },
-                                { "(", "(" },
-                                { ")", ")" },
-                                { ".", "." },
-                                { "x", "x" }
-                            };
+        return EncodeNoTextileZones(tmp, patternPrefix, patternSuffix, null);
+    }
 
-
-        public static string EncodeNoTextileZones(string tmp, string patternPrefix, string patternSuffix)
+    public static string EncodeNoTextileZones(string tmp, string patternPrefix, string patternSuffix, string[] exceptions)
+    {
+        string evaluator(Match m)
         {
-            return EncodeNoTextileZones(tmp, patternPrefix, patternSuffix, null);
-        }
-
-        public static string EncodeNoTextileZones(string tmp, string patternPrefix, string patternSuffix, string[] exceptions)
-        {
-            string evaluator(Match m)
+            var toEncode = m.Groups["notex"].Value;
+            if (toEncode.Length == 0)
             {
-                var toEncode = m.Groups["notex"].Value;
-                if (toEncode.Length == 0)
-                {
-                    return string.Empty;
-                }
-                for (var i = 0; i < TextileModifiers.GetLength(0); ++i)
-                {
-                    if (exceptions == null || Array.IndexOf(exceptions, TextileModifiers[i, 0]) < 0)
-                    {
-                        toEncode = toEncode.Replace(TextileModifiers[i, 0], TextileModifiers[i, 1]);
-                    }
-                }
-                return patternPrefix + toEncode + patternSuffix;
+                return string.Empty;
             }
-            tmp = Regex.Replace(tmp, "("+ patternPrefix + "(?<notex>.+?)" + patternSuffix + ")*", new MatchEvaluator(evaluator));
-            return tmp;
-        }
-
-        public static string DecodeNoTextileZones(string tmp, string patternPrefix, string patternSuffix)
-        {
-            return DecodeNoTextileZones(tmp, patternPrefix, patternSuffix, null);
-        }
-
-        public static string DecodeNoTextileZones(string tmp, string patternPrefix, string patternSuffix, string[] exceptions)
-        {
-            string evaluator(Match m)
+            for (var i = 0; i < TextileModifiers.GetLength(0); ++i)
             {
-                var toEncode = m.Groups["notex"].Value;
-                for (var i = 0; i < TextileModifiers.GetLength(0); ++i)
+                if (exceptions == null || Array.IndexOf(exceptions, TextileModifiers[i, 0]) < 0)
                 {
-                    if (exceptions == null || Array.IndexOf(exceptions, TextileModifiers[i, 0]) < 0)
-                    {
-                        toEncode = toEncode.Replace(TextileModifiers[i, 1], TextileModifiers[i, 0]);
-                    }
+                    toEncode = toEncode.Replace(TextileModifiers[i, 0], TextileModifiers[i, 1]);
                 }
-                return toEncode;
             }
-            tmp = Regex.Replace(tmp, "(" + patternPrefix + "(?<notex>.+?)" + patternSuffix + ")*", new MatchEvaluator(evaluator));
-            return tmp;
+            return patternPrefix + toEncode + patternSuffix;
         }
+        tmp = Regex.Replace(tmp, "("+ patternPrefix + "(?<notex>.+?)" + patternSuffix + ")*", new MatchEvaluator(evaluator));
+        return tmp;
+    }
+
+    public static string DecodeNoTextileZones(string tmp, string patternPrefix, string patternSuffix)
+    {
+        return DecodeNoTextileZones(tmp, patternPrefix, patternSuffix, null);
+    }
+
+    public static string DecodeNoTextileZones(string tmp, string patternPrefix, string patternSuffix, string[] exceptions)
+    {
+        string evaluator(Match m)
+        {
+            var toEncode = m.Groups["notex"].Value;
+            for (var i = 0; i < TextileModifiers.GetLength(0); ++i)
+            {
+                if (exceptions == null || Array.IndexOf(exceptions, TextileModifiers[i, 0]) < 0)
+                {
+                    toEncode = toEncode.Replace(TextileModifiers[i, 1], TextileModifiers[i, 0]);
+                }
+            }
+            return toEncode;
+        }
+        tmp = Regex.Replace(tmp, "(" + patternPrefix + "(?<notex>.+?)" + patternSuffix + ")*", new MatchEvaluator(evaluator));
+        return tmp;
     }
 }
diff --git a/common/ASC.Textile/Blocks/PhraseBlockModifier.cs b/common/ASC.Textile/Blocks/PhraseBlockModifier.cs
index afbe0c160c..bb08630a15 100644
--- a/common/ASC.Textile/Blocks/PhraseBlockModifier.cs
+++ b/common/ASC.Textile/Blocks/PhraseBlockModifier.cs
@@ -10,82 +10,81 @@
 // You must not remove this notice, or any other, from this software.
 #endregion
 
-namespace Textile.Blocks
+namespace Textile.Blocks;
+
+public abstract class PhraseBlockModifier : BlockModifier
 {
-    public abstract class PhraseBlockModifier : BlockModifier
+    protected PhraseBlockModifier()
     {
-        protected PhraseBlockModifier()
-        {
-        }
+    }
 
-        protected string PhraseModifierFormat(string input, string modifier, string tag)
+    protected string PhraseModifierFormat(string input, string modifier, string tag)
+    {
+        // All phrase modifiers are one character, or a double character. Sometimes,
+        // there's an additional escape character for the regex ('\').
+        var compressedModifier = modifier;
+        if (modifier.Length == 4)
         {
-            // All phrase modifiers are one character, or a double character. Sometimes,
-            // there's an additional escape character for the regex ('\').
-            var compressedModifier = modifier;
-            if (modifier.Length == 4)
-            {
-                compressedModifier = modifier.Substring(0, 2);
-            }
-            else if (modifier.Length == 2)
-            {
-                if (modifier[0] != '\\')
-                    compressedModifier = modifier[0].ToString();
-                //else: compressedModifier = modifier;
-            }
+            compressedModifier = modifier.Substring(0, 2);
+        }
+        else if (modifier.Length == 2)
+        {
+            if (modifier[0] != '\\')
+                compressedModifier = modifier[0].ToString();
             //else: compressedModifier = modifier;
+        }
+        //else: compressedModifier = modifier;
 
-            // We try to remove the Textile tag used for the formatting from
-            // the punctuation pattern, so that we match the end of the formatted
-            // zone correctly.
-            var punctuationPattern = Globals.PunctuationPattern.Replace(compressedModifier, "");
+        // We try to remove the Textile tag used for the formatting from
+        // the punctuation pattern, so that we match the end of the formatted
+        // zone correctly.
+        var punctuationPattern = Globals.PunctuationPattern.Replace(compressedModifier, "");
 
-            // Now we can do the replacement.
-            var pmme = new PhraseModifierMatchEvaluator(tag);
-            var res = Regex.Replace(input,
-                                            @"(?<=\s|" + punctuationPattern + @"|[{\(\[]|^)" +
-                                            modifier +
-                                            Globals.BlockModifiersPattern +
-                                            @"(:(?<cite>(\S+)))?" +
-                                            @"(?<content>[^" + compressedModifier + "]*)" +
-                                            @"(?<end>" + punctuationPattern + @"*)" +
-                                            modifier +
-                                            @"(?=[\]\)}]|" + punctuationPattern + @"+|\s|$)",
-                                       new MatchEvaluator(pmme.MatchEvaluator)
-                                      );
-            return res;
+        // Now we can do the replacement.
+        var pmme = new PhraseModifierMatchEvaluator(tag);
+        var res = Regex.Replace(input,
+                                        @"(?<=\s|" + punctuationPattern + @"|[{\(\[]|^)" +
+                                        modifier +
+                                        Globals.BlockModifiersPattern +
+                                        @"(:(?<cite>(\S+)))?" +
+                                        @"(?<content>[^" + compressedModifier + "]*)" +
+                                        @"(?<end>" + punctuationPattern + @"*)" +
+                                        modifier +
+                                        @"(?=[\]\)}]|" + punctuationPattern + @"+|\s|$)",
+                                    new MatchEvaluator(pmme.MatchEvaluator)
+                                    );
+        return res;
+    }
+
+    private sealed class PhraseModifierMatchEvaluator
+    {
+        private readonly string _tag;
+
+        public PhraseModifierMatchEvaluator(string tag)
+        {
+            _tag = tag;
         }
 
-        private sealed class PhraseModifierMatchEvaluator
+        public string MatchEvaluator(Match m)
         {
-            readonly string m_tag;
-
-            public PhraseModifierMatchEvaluator(string tag)
+            if (m.Groups["content"].Length == 0)
             {
-                m_tag = tag;
+                // It's possible that the "atts" match groups eats the contents
+                // when the user didn't want to give block attributes, but the content
+                // happens to match the syntax. For example: "*(blah)*".
+                if (m.Groups["atts"].Length == 0)
+                    return m.ToString();
+                return "<" + _tag + ">" + m.Groups["atts"].Value + m.Groups["end"].Value + "</" + _tag + ">";
             }
 
-            public string MatchEvaluator(Match m)
-            {
-                if (m.Groups["content"].Length == 0)
-                {
-                    // It's possible that the "atts" match groups eats the contents
-                    // when the user didn't want to give block attributes, but the content
-                    // happens to match the syntax. For example: "*(blah)*".
-                    if (m.Groups["atts"].Length == 0)
-                        return m.ToString();
-                    return "<" + m_tag + ">" + m.Groups["atts"].Value + m.Groups["end"].Value + "</" + m_tag + ">";
-                }
+            var atts = BlockAttributesParser.ParseBlockAttributes(m.Groups["atts"].Value, _tag);
+            if (m.Groups["cite"].Length > 0)
+                atts += " cite=\"" + m.Groups["cite"] + "\"";
 
-                var atts = BlockAttributesParser.ParseBlockAttributes(m.Groups["atts"].Value, m_tag);
-                if (m.Groups["cite"].Length > 0)
-                    atts += " cite=\"" + m.Groups["cite"] + "\"";
-
-                var res = "<" + m_tag + atts + ">" +
-                             m.Groups["content"].Value + m.Groups["end"].Value +
-                             "</" + m_tag + ">";
-                return res;
-            }
+            var res = "<" + _tag + atts + ">" +
+                            m.Groups["content"].Value + m.Groups["end"].Value +
+                            "</" + _tag + ">";
+            return res;
         }
     }
 }
diff --git a/common/ASC.Textile/Blocks/PreBlockModifier.cs b/common/ASC.Textile/Blocks/PreBlockModifier.cs
index 2003e58492..63da6c16cb 100644
--- a/common/ASC.Textile/Blocks/PreBlockModifier.cs
+++ b/common/ASC.Textile/Blocks/PreBlockModifier.cs
@@ -10,28 +10,27 @@
 // You must not remove this notice, or any other, from this software.
 #endregion
 
-namespace Textile.Blocks
-{
-    public class PreBlockModifier : BlockModifier
-    {
-        public override string ModifyLine(string line)
-        {
-            // Encode the contents of the "<pre>" tags so that we don't
-            // generate formatting out of it.
-            line = NoTextileEncoder.EncodeNoTextileZones(line,
-                                  @"(?<=(^|\s)<pre(" + Globals.HtmlAttributesPattern + @")>)",
-                                  @"(?=</pre>)");
-            return line;
-        }
+namespace Textile.Blocks;
 
-        public override string Conclude(string line)
-        {
-            // Recode everything.
-            line = NoTextileEncoder.DecodeNoTextileZones(line,
-                                    @"(?<=(^|\s)<pre(" + Globals.HtmlAttributesPattern + @")>)",
-                                    @"(?=</pre>)",
-                                    new string[] { "<", ">" });
-            return line;
-        }
+public class PreBlockModifier : BlockModifier
+{
+    public override string ModifyLine(string line)
+    {
+        // Encode the contents of the "<pre>" tags so that we don't
+        // generate formatting out of it.
+        line = NoTextileEncoder.EncodeNoTextileZones(line,
+                                @"(?<=(^|\s)<pre(" + Globals.HtmlAttributesPattern + @")>)",
+                                @"(?=</pre>)");
+        return line;
+    }
+
+    public override string Conclude(string line)
+    {
+        // Recode everything.
+        line = NoTextileEncoder.DecodeNoTextileZones(line,
+                                @"(?<=(^|\s)<pre(" + Globals.HtmlAttributesPattern + @")>)",
+                                @"(?=</pre>)",
+                                new string[] { "<", ">" });
+        return line;
     }
 }
diff --git a/common/ASC.Textile/Blocks/SpanPhraseBlockModifier.cs b/common/ASC.Textile/Blocks/SpanPhraseBlockModifier.cs
index e3ed75850b..c6c564056f 100644
--- a/common/ASC.Textile/Blocks/SpanPhraseBlockModifier.cs
+++ b/common/ASC.Textile/Blocks/SpanPhraseBlockModifier.cs
@@ -1,10 +1,9 @@
-namespace Textile.Blocks
+namespace Textile.Blocks;
+
+public class SpanPhraseBlockModifier : PhraseBlockModifier
 {
-    public class SpanPhraseBlockModifier : PhraseBlockModifier
+    public override string ModifyLine(string line)
     {
-        public override string ModifyLine(string line)
-        {
-            return PhraseModifierFormat(line, @"%", "span");
-        }
+        return PhraseModifierFormat(line, @"%", "span");
     }
 }
diff --git a/common/ASC.Textile/Blocks/StrongPhraseBlockModifier.cs b/common/ASC.Textile/Blocks/StrongPhraseBlockModifier.cs
index 342402827b..9bae9abffe 100644
--- a/common/ASC.Textile/Blocks/StrongPhraseBlockModifier.cs
+++ b/common/ASC.Textile/Blocks/StrongPhraseBlockModifier.cs
@@ -1,10 +1,9 @@
-namespace Textile.Blocks
+namespace Textile.Blocks;
+
+public class StrongPhraseBlockModifier : PhraseBlockModifier
 {
-    public class StrongPhraseBlockModifier : PhraseBlockModifier
+    public override string ModifyLine(string line)
     {
-        public override string ModifyLine(string line)
-        {
-            return PhraseModifierFormat(line, @"\*", "strong");
-        }
+        return PhraseModifierFormat(line, @"\*", "strong");
     }
-}
+}
\ No newline at end of file
diff --git a/common/ASC.Textile/Blocks/SubScriptPhraseBlockModifier.cs b/common/ASC.Textile/Blocks/SubScriptPhraseBlockModifier.cs
index 3a6cb68c39..68e25faa70 100644
--- a/common/ASC.Textile/Blocks/SubScriptPhraseBlockModifier.cs
+++ b/common/ASC.Textile/Blocks/SubScriptPhraseBlockModifier.cs
@@ -1,10 +1,9 @@
-namespace Textile.Blocks
+namespace Textile.Blocks;
+
+public class SubScriptPhraseBlockModifier : PhraseBlockModifier
 {
-    public class SubScriptPhraseBlockModifier : PhraseBlockModifier
+    public override string ModifyLine(string line)
     {
-        public override string ModifyLine(string line)
-        {
-            return PhraseModifierFormat(line, @"~", "sub");
-        }
+        return PhraseModifierFormat(line, @"~", "sub");
     }
-}
+}
\ No newline at end of file
diff --git a/common/ASC.Textile/Blocks/SuperScriptPhraseBlockModifier.cs b/common/ASC.Textile/Blocks/SuperScriptPhraseBlockModifier.cs
index 77c92d3cc1..08c782d5c6 100644
--- a/common/ASC.Textile/Blocks/SuperScriptPhraseBlockModifier.cs
+++ b/common/ASC.Textile/Blocks/SuperScriptPhraseBlockModifier.cs
@@ -1,10 +1,9 @@
-namespace Textile.Blocks
+namespace Textile.Blocks;
+
+public class SuperScriptPhraseBlockModifier : PhraseBlockModifier
 {
-    public class SuperScriptPhraseBlockModifier : PhraseBlockModifier
+    public override string ModifyLine(string line)
     {
-        public override string ModifyLine(string line)
-        {
-            return PhraseModifierFormat(line, @"\^", "sup");
-        }
+        return PhraseModifierFormat(line, @"\^", "sup");
     }
 }
diff --git a/common/ASC.Textile/FormatterState.cs b/common/ASC.Textile/FormatterState.cs
index 769dad3e16..df4b9e2158 100644
--- a/common/ASC.Textile/FormatterState.cs
+++ b/common/ASC.Textile/FormatterState.cs
@@ -10,126 +10,125 @@
 // You must not remove this notice, or any other, from this software.
 #endregion
 
-namespace Textile
+namespace Textile;
+
+/// <summary>
+/// Base class for formatter states.
+/// </summary>
+/// A formatter state describes the current situation
+/// of the text being currently processed. A state can
+/// write HTML code when entered, exited, and can modify
+/// each line of text it receives.
+public abstract class FormatterState
 {
     /// <summary>
-    /// Base class for formatter states.
+    /// The formatter this state belongs to.
     /// </summary>
-    /// A formatter state describes the current situation
-    /// of the text being currently processed. A state can
-    /// write HTML code when entered, exited, and can modify
-    /// each line of text it receives.
-    public abstract class FormatterState
+    public TextileFormatter Formatter { get; }
+
+    /// <summary>
+    /// Public constructor.
+    /// </summary>
+    /// <param name="f">The parent formatter.</param>
+    protected FormatterState(TextileFormatter formatter)
     {
-        /// <summary>
-        /// The formatter this state belongs to.
-        /// </summary>
-        public TextileFormatter Formatter { get; }
+        Formatter = formatter;
+    }
 
-        /// <summary>
-        /// Public constructor.
-        /// </summary>
-        /// <param name="f">The parent formatter.</param>
-        protected FormatterState(TextileFormatter formatter)
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="input"></param>
+    /// <param name="m"></param>
+    /// <returns></returns>
+    public abstract string Consume(string input, Match m);
+
+    /// <summary>
+    /// Method called when the state is entered.
+    /// </summary>
+    public abstract void Enter();
+    /// <summary>
+    /// Method called when the state is exited.
+    /// </summary>
+    public abstract void Exit();
+    /// <summary>
+    /// Method called when a line of text should be written
+    /// to the web form.
+    /// </summary>
+    /// <param name="input">The line of text.</param>
+    public abstract void FormatLine(string input);
+
+    /// <summary>
+    /// Returns whether this state can last for more than one line.
+    /// </summary>
+    /// <returns>A boolean value stating whether this state is only for one line.</returns>
+    /// This method should return true only if this state is genuinely
+    /// multi-line. For example, a header text is only one line long. You can
+    /// have several consecutive lines of header texts, but they are not the same
+    /// header - just several headers one after the other.
+    /// Bulleted and numbered lists are good examples of multi-line states.
+    //abstract public bool IsOneLineOnly();
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="input"></param>
+    /// <returns></returns>
+    public abstract bool ShouldExit(string input);
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="actualTag"></param>
+    /// <param name="alignNfo"></param>
+    /// <param name="attNfo"></param>
+    /// <returns></returns>
+    public virtual bool ShouldNestState(FormatterState other)
+    {
+        return false;
+    }
+
+    /// <summary>
+    /// Returns whether block formatting (quick phrase modifiers, etc.) should be
+    /// applied to this line.
+    /// </summary>
+    /// <param name="input">The line of text</param>
+    /// <returns>Whether the line should be formatted for blocks</returns>
+    public virtual bool ShouldFormatBlocks(string input)
+    {
+        return true;
+    }
+
+    /// <summary>
+    /// Returns whether the current state accepts being superceded by another one
+    /// we would possibly find by parsing the input line of text.
+    /// </summary>
+    /// <param name="input"></param>
+    /// <returns></returns>
+    public virtual bool ShouldParseForNewFormatterState(string input)
+    {
+        return true;
+    }
+
+    /// <summary>
+    /// Gets the formatting state we should fallback to if we don't find anything
+    /// relevant in a line of text.
+    /// </summary>
+    public virtual Type FallbackFormattingState
+    {
+        get
         {
-            Formatter = formatter;
-        }
-
-        /// <summary>
-        /// 
-        /// </summary>
-        /// <param name="input"></param>
-        /// <param name="m"></param>
-        /// <returns></returns>
-        public abstract string Consume(string input, Match m);
-
-        /// <summary>
-        /// Method called when the state is entered.
-        /// </summary>
-        public abstract void Enter();
-        /// <summary>
-        /// Method called when the state is exited.
-        /// </summary>
-        public abstract void Exit();
-        /// <summary>
-        /// Method called when a line of text should be written
-        /// to the web form.
-        /// </summary>
-        /// <param name="input">The line of text.</param>
-        public abstract void FormatLine(string input);
-
-        /// <summary>
-        /// Returns whether this state can last for more than one line.
-        /// </summary>
-        /// <returns>A boolean value stating whether this state is only for one line.</returns>
-        /// This method should return true only if this state is genuinely
-        /// multi-line. For example, a header text is only one line long. You can
-        /// have several consecutive lines of header texts, but they are not the same
-        /// header - just several headers one after the other.
-        /// Bulleted and numbered lists are good examples of multi-line states.
-        //abstract public bool IsOneLineOnly();
-
-        /// <summary>
-        /// 
-        /// </summary>
-        /// <param name="input"></param>
-        /// <returns></returns>
-        public abstract bool ShouldExit(string input);
-
-        /// <summary>
-        /// 
-        /// </summary>
-        /// <param name="actualTag"></param>
-        /// <param name="alignNfo"></param>
-        /// <param name="attNfo"></param>
-        /// <returns></returns>
-        public virtual bool ShouldNestState(FormatterState other)
-        {
-            return false;
-        }
-
-        /// <summary>
-        /// Returns whether block formatting (quick phrase modifiers, etc.) should be
-        /// applied to this line.
-        /// </summary>
-        /// <param name="input">The line of text</param>
-        /// <returns>Whether the line should be formatted for blocks</returns>
-        public virtual bool ShouldFormatBlocks(string input)
-        {
-            return true;
-        }
-
-        /// <summary>
-        /// Returns whether the current state accepts being superceded by another one
-        /// we would possibly find by parsing the input line of text.
-        /// </summary>
-        /// <param name="input"></param>
-        /// <returns></returns>
-        public virtual bool ShouldParseForNewFormatterState(string input)
-        {
-            return true;
-        }
-
-        /// <summary>
-        /// Gets the formatting state we should fallback to if we don't find anything
-        /// relevant in a line of text.
-        /// </summary>
-        public virtual Type FallbackFormattingState
-        {
-            get
-            {
-                return typeof(States.ParagraphFormatterState);
-            }
-        }
-
-        protected FormatterState CurrentFormatterState
-        {
-            get { return this.Formatter.CurrentState; }
-        }
-
-        protected void ChangeFormatterState(FormatterState formatterState)
-        {
-            this.Formatter.ChangeState(formatterState);
+            return typeof(States.ParagraphFormatterState);
         }
     }
-}
+
+    protected FormatterState CurrentFormatterState
+    {
+        get { return this.Formatter.CurrentState; }
+    }
+
+    protected void ChangeFormatterState(FormatterState formatterState)
+    {
+        this.Formatter.ChangeState(formatterState);
+    }
+}
\ No newline at end of file
diff --git a/common/ASC.Textile/FormatterStateAttribute.cs b/common/ASC.Textile/FormatterStateAttribute.cs
index e50ea55458..ab9bdd15e3 100644
--- a/common/ASC.Textile/FormatterStateAttribute.cs
+++ b/common/ASC.Textile/FormatterStateAttribute.cs
@@ -1,21 +1,20 @@
-namespace Textile
+namespace Textile;
+
+[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
+public sealed class FormatterStateAttribute : Attribute
 {
-    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
-    public sealed class FormatterStateAttribute : Attribute
+    public string Pattern { get; }
+
+    public FormatterStateAttribute(string pattern)
     {
-        public string Pattern { get; }
+        Pattern = pattern;
+    }
 
-        public FormatterStateAttribute(string pattern)
-        {
-            Pattern = pattern;
-        }
-
-        public static FormatterStateAttribute Get(Type type)
-        {
-            var atts = type.GetCustomAttributes(typeof(FormatterStateAttribute), false);
-            if (atts.Length == 0)
-                return null;
-            return (FormatterStateAttribute)atts[0];
-        }
+    public static FormatterStateAttribute Get(Type type)
+    {
+        var atts = type.GetCustomAttributes(typeof(FormatterStateAttribute), false);
+        if (atts.Length == 0)
+            return null;
+        return (FormatterStateAttribute)atts[0];
     }
 }
diff --git a/common/ASC.Textile/Globals.cs b/common/ASC.Textile/Globals.cs
index ccf120123f..257a55867f 100644
--- a/common/ASC.Textile/Globals.cs
+++ b/common/ASC.Textile/Globals.cs
@@ -11,78 +11,77 @@
 #endregion
 
 
-namespace Textile
+namespace Textile;
+
+/// <summary>
+/// A utility class for global things used by the TextileFormatter.
+/// </summary>
+static class Globals
 {
+    #region Global Regex Patterns
+
+    public const string HorizontalAlignPattern = @"(?:[()]*(\<(?!>)|(?<!<)\>|\<\>|=)[()]*)";
+    public const string VerticalAlignPattern = @"[\-^~]";
+    public const string CssClassPattern = @"(?:\([^)]+\))";
+    public const string LanguagePattern = @"(?:\[[^]]+\])";
+    public const string CssStylePattern = @"(?:\{[^}]+\})";
+    public const string ColumnSpanPattern = @"(?:\\\d+)";
+    public const string RowSpanPattern = @"(?:/\d+)";
+
+    public const string AlignPattern = "(?<align>" + HorizontalAlignPattern + "?" + VerticalAlignPattern + "?|" + VerticalAlignPattern + "?" + HorizontalAlignPattern + "?)";
+    public const string SpanPattern = @"(?<span>" + ColumnSpanPattern + "?" + RowSpanPattern + "?|" + RowSpanPattern + "?" + ColumnSpanPattern + "?)";
+    public const string BlockModifiersPattern = @"(?<atts>" + CssClassPattern + "?" + CssStylePattern + "?" + LanguagePattern + "?|" +
+                                                    CssStylePattern + "?" + LanguagePattern + "?" + CssClassPattern + "?|" +
+                                                    LanguagePattern + "?" + CssStylePattern + "?" + CssClassPattern + "?)";
+
+    public const string PunctuationPattern = @"[\!""#\$%&'()\*\+,\-\./:;<=>\?@\[\\\]\^_`{}~]";
+
+    public const string HtmlAttributesPattern = @"(\s+\w+=((""[^""]+"")|('[^']+')))*";
+
+    #endregion
+
     /// <summary>
-    /// A utility class for global things used by the TextileFormatter.
+    /// Image alignment tags, mapped to their HTML meanings.
     /// </summary>
-    static class Globals
+    public static Dictionary<string, string> ImageAlign { get; set; }
+    /// <summary>
+    /// Horizontal text alignment tags, mapped to their HTML meanings.
+    /// </summary>
+    public static Dictionary<string, string> HorizontalAlign { get; set; }
+    /// <summary>
+    /// Vertical text alignment tags, mapped to their HTML meanings.
+    /// </summary>
+    public static Dictionary<string, string> VerticalAlign { get; set;}
+
+    static Globals()
     {
-        #region Global Regex Patterns
-
-        public const string HorizontalAlignPattern = @"(?:[()]*(\<(?!>)|(?<!<)\>|\<\>|=)[()]*)";
-        public const string VerticalAlignPattern = @"[\-^~]";
-        public const string CssClassPattern = @"(?:\([^)]+\))";
-        public const string LanguagePattern = @"(?:\[[^]]+\])";
-        public const string CssStylePattern = @"(?:\{[^}]+\})";
-        public const string ColumnSpanPattern = @"(?:\\\d+)";
-        public const string RowSpanPattern = @"(?:/\d+)";
-
-        public const string AlignPattern = "(?<align>" + HorizontalAlignPattern + "?" + VerticalAlignPattern + "?|" + VerticalAlignPattern + "?" + HorizontalAlignPattern + "?)";
-        public const string SpanPattern = @"(?<span>" + ColumnSpanPattern + "?" + RowSpanPattern + "?|" + RowSpanPattern + "?" + ColumnSpanPattern + "?)";
-        public const string BlockModifiersPattern = @"(?<atts>" + CssClassPattern + "?" + CssStylePattern + "?" + LanguagePattern + "?|" +
-                                                        CssStylePattern + "?" + LanguagePattern + "?" + CssClassPattern + "?|" +
-                                                        LanguagePattern + "?" + CssStylePattern + "?" + CssClassPattern + "?)";
-
-        public const string PunctuationPattern = @"[\!""#\$%&'()\*\+,\-\./:;<=>\?@\[\\\]\^_`{}~]";
-
-        public const string HtmlAttributesPattern = @"(\s+\w+=((""[^""]+"")|('[^']+')))*";
-
-        #endregion
-
-        /// <summary>
-        /// Image alignment tags, mapped to their HTML meanings.
-        /// </summary>
-        public static Dictionary<string, string> ImageAlign { get; set; }
-        /// <summary>
-        /// Horizontal text alignment tags, mapped to their HTML meanings.
-        /// </summary>
-        public static Dictionary<string, string> HorizontalAlign { get; set; }
-        /// <summary>
-        /// Vertical text alignment tags, mapped to their HTML meanings.
-        /// </summary>
-        public static Dictionary<string, string> VerticalAlign { get; set;}
-
-        static Globals()
+        ImageAlign = new Dictionary<string, string>
         {
-            ImageAlign = new Dictionary<string, string>
-            {
-                ["<"] = "left",
-                ["="] = "center",
-                [">"] = "right"
-            };
+            ["<"] = "left",
+            ["="] = "center",
+            [">"] = "right"
+        };
 
-            HorizontalAlign = new Dictionary<string, string>
-            {
-                ["<"] = "left",
-                ["="] = "center",
-                [">"] = "right",
-                ["<>"] = "justify"
-            };
-
-            VerticalAlign = new Dictionary<string, string>
-            {
-                ["^"] = "top",
-                ["-"] = "middle",
-                ["~"] = "bottom"
-            };
-        }
-
-        public static string EncodeHTMLLink(string url)
+        HorizontalAlign = new Dictionary<string, string>
         {
-            url = url.Replace("&", "&");
-            url = System.Text.RegularExpressions.Regex.Replace(url, "&(?=[^#])", "&");
-            return url;
-        }
+            ["<"] = "left",
+            ["="] = "center",
+            [">"] = "right",
+            ["<>"] = "justify"
+        };
+
+        VerticalAlign = new Dictionary<string, string>
+        {
+            ["^"] = "top",
+            ["-"] = "middle",
+            ["~"] = "bottom"
+        };
+    }
+
+    public static string EncodeHTMLLink(string url)
+    {
+        url = url.Replace("&", "&");
+        url = System.Text.RegularExpressions.Regex.Replace(url, "&(?=[^#])", "&");
+        return url;
     }
 }
diff --git a/common/ASC.Textile/IOutputter.cs b/common/ASC.Textile/IOutputter.cs
index f77c87e717..45d71d5f54 100644
--- a/common/ASC.Textile/IOutputter.cs
+++ b/common/ASC.Textile/IOutputter.cs
@@ -10,44 +10,39 @@
 // You must not remove this notice, or any other, from this software.
 #endregion
 
-#region Using Statements
-#endregion
+namespace Textile;
 
-
-namespace Textile
+/// <summary>
+/// Interface through which the HTML formatted text
+/// will be sent.
+/// </summary>
+/// Clients of the TextileFormatter class will have to provide
+/// an outputter that implements this interface. Most of the
+/// time, it'll be the WebForm itself.
+public interface IOutputter
 {
     /// <summary>
-    /// Interface through which the HTML formatted text
-    /// will be sent.
+    /// Method called just before the formatted text
+    /// is sent to the outputter.
     /// </summary>
-    /// Clients of the TextileFormatter class will have to provide
-    /// an outputter that implements this interface. Most of the
-    /// time, it'll be the WebForm itself.
-    public interface IOutputter
-    {
-        /// <summary>
-        /// Method called just before the formatted text
-        /// is sent to the outputter.
-        /// </summary>
-        void Begin();
+    void Begin();
 
-        /// <summary>
-        /// Metohd called whenever the TextileFormatter wants to
-        /// print some text.
-        /// </summary>
-        /// <param name="text">The formatted HTML text.</param>
-        void Write(string text);
-        /// <summary>
-        /// Metohd called whenever the TextileFormatter wants to
-        /// print some text. This should automatically print an
-        /// additionnal end of line character.
-        /// </summary>
-        /// <param name="line">The formatted HTML text.</param>
-        void WriteLine(string line);
+    /// <summary>
+    /// Metohd called whenever the TextileFormatter wants to
+    /// print some text.
+    /// </summary>
+    /// <param name="text">The formatted HTML text.</param>
+    void Write(string text);
+    /// <summary>
+    /// Metohd called whenever the TextileFormatter wants to
+    /// print some text. This should automatically print an
+    /// additionnal end of line character.
+    /// </summary>
+    /// <param name="line">The formatted HTML text.</param>
+    void WriteLine(string line);
 
-        /// <summary>
-        /// Method called at the end of the formatting.
-        /// </summary>
-        void End();
-    }
+    /// <summary>
+    /// Method called at the end of the formatting.
+    /// </summary>
+    void End();
 }
diff --git a/common/ASC.Textile/States/BlockQuoteFormatterState.cs b/common/ASC.Textile/States/BlockQuoteFormatterState.cs
index eba43a15a9..cdfbcbf877 100644
--- a/common/ASC.Textile/States/BlockQuoteFormatterState.cs
+++ b/common/ASC.Textile/States/BlockQuoteFormatterState.cs
@@ -10,42 +10,41 @@
 // You must not remove this notice, or any other, from this software.
 #endregion
 
-namespace Textile.States
+namespace Textile.States;
+
+[FormatterState(SimpleBlockFormatterState.PatternBegin + @"bq" + SimpleBlockFormatterState.PatternEnd)]
+public class BlockQuoteFormatterState : SimpleBlockFormatterState
 {
-    [FormatterState(SimpleBlockFormatterState.PatternBegin + @"bq" + SimpleBlockFormatterState.PatternEnd)]
-    public class BlockQuoteFormatterState : SimpleBlockFormatterState
+    public BlockQuoteFormatterState(TextileFormatter f)
+        : base(f)
     {
-        public BlockQuoteFormatterState(TextileFormatter f)
-            : base(f)
-        {
-        }
+    }
 
-        public override void Enter()
-        {
-            Formatter.Output.Write("<blockquote" + FormattedStylesAndAlignment("blockquote") + "><p>");
-        }
+    public override void Enter()
+    {
+        Formatter.Output.Write("<blockquote" + FormattedStylesAndAlignment("blockquote") + "><p>");
+    }
 
-        public override void Exit()
-        {
-            Formatter.Output.WriteLine("</p></blockquote>");
-        }
+    public override void Exit()
+    {
+        Formatter.Output.WriteLine("</p></blockquote>");
+    }
 
-        public override void FormatLine(string input)
-        {
-            Formatter.Output.Write(input);
-        }
+    public override void FormatLine(string input)
+    {
+        Formatter.Output.Write(input);
+    }
 
-        public override bool ShouldExit(string input)
-        {
-            if (Regex.IsMatch(input, @"^\s*$"))
-                return true;
-            Formatter.Output.WriteLine("<br />");
-            return false;
-        }
+    public override bool ShouldExit(string input)
+    {
+        if (Regex.IsMatch(input, @"^\s*$"))
+            return true;
+        Formatter.Output.WriteLine("<br />");
+        return false;
+    }
 
-        public override Type FallbackFormattingState
-        {
-            get { return null; }
-        }
+    public override Type FallbackFormattingState
+    {
+        get { return null; }
     }
 }
diff --git a/common/ASC.Textile/States/CodeFormatterState.cs b/common/ASC.Textile/States/CodeFormatterState.cs
index 70c9a88f79..0dc1a447af 100644
--- a/common/ASC.Textile/States/CodeFormatterState.cs
+++ b/common/ASC.Textile/States/CodeFormatterState.cs
@@ -1,78 +1,77 @@
-namespace Textile.States
+namespace Textile.States;
+
+[FormatterState(@"^\s*<code" + Globals.HtmlAttributesPattern + ">")]
+public class CodeFormatterState : FormatterState
 {
-    [FormatterState(@"^\s*<code" + Globals.HtmlAttributesPattern + ">")]
-    public class CodeFormatterState : FormatterState
+    private bool _shouldExitNextTime = false;
+    private bool _shouldFixHtmlEntities = false;
+
+    public CodeFormatterState(TextileFormatter f)
+        : base(f)
     {
-        bool m_shouldExitNextTime = false;
-        bool m_shouldFixHtmlEntities = false;
-
-        public CodeFormatterState(TextileFormatter f)
-            : base(f)
-        {
-        }
-
-        public override string Consume(string input, Match m)
-        {
-            if (!Regex.IsMatch(input, "</code>"))
-            {
-                this.Formatter.ChangeState(this);
-            }
-            else
-            {
-                this.Formatter.ChangeState(new PassthroughFormatterState(this.Formatter));
-            }
-            return input;
-        }
-
-        public override bool ShouldNestState(FormatterState other)
-        {
-            return true;
-        }
-
-        public override void Enter()
-        {
-            m_shouldFixHtmlEntities = false;
-        }
-
-        public override void Exit()
-        {
-        }
-
-        public override void FormatLine(string input)
-        {
-            if (m_shouldFixHtmlEntities)
-                input = FixEntities(input);
-            Formatter.Output.WriteLine(input);
-            m_shouldFixHtmlEntities = true;
-        }
-
-        public override bool ShouldExit(string input)
-        {
-            if (m_shouldExitNextTime)
-                return true;
-            m_shouldExitNextTime = Regex.IsMatch(input, @"</code>");
-            m_shouldFixHtmlEntities = !m_shouldExitNextTime;
-            return false;
-        }
-
-        public override bool ShouldFormatBlocks(string input)
-        {
-            return false;
-        }
-
-        public override bool ShouldParseForNewFormatterState(string input)
-        {
-            return false;
-        }
-
-        private string FixEntities(string text)
-        {
-            // de-entify any remaining angle brackets or ampersands
-            text = text.Replace("&", "&");
-            text = text.Replace(">", ">");
-            text = text.Replace("<", "<");
-            //Regex.Replace(text, @"\b&([#a-z0-9]+;)", "x%x%");
-            return text;
-        }
     }
-}
+
+    public override string Consume(string input, Match m)
+    {
+        if (!Regex.IsMatch(input, "</code>"))
+        {
+            this.Formatter.ChangeState(this);
+        }
+        else
+        {
+            this.Formatter.ChangeState(new PassthroughFormatterState(this.Formatter));
+        }
+        return input;
+    }
+
+    public override bool ShouldNestState(FormatterState other)
+    {
+        return true;
+    }
+
+    public override void Enter()
+    {
+        _shouldFixHtmlEntities = false;
+    }
+
+    public override void Exit()
+    {
+    }
+
+    public override void FormatLine(string input)
+    {
+        if (_shouldFixHtmlEntities)
+            input = FixEntities(input);
+        Formatter.Output.WriteLine(input);
+        _shouldFixHtmlEntities = true;
+    }
+
+    public override bool ShouldExit(string input)
+    {
+        if (_shouldExitNextTime)
+            return true;
+        _shouldExitNextTime = Regex.IsMatch(input, @"</code>");
+        _shouldFixHtmlEntities = !_shouldExitNextTime;
+        return false;
+    }
+
+    public override bool ShouldFormatBlocks(string input)
+    {
+        return false;
+    }
+
+    public override bool ShouldParseForNewFormatterState(string input)
+    {
+        return false;
+    }
+
+    private string FixEntities(string text)
+    {
+        // de-entify any remaining angle brackets or ampersands
+        text = text.Replace("&", "&");
+        text = text.Replace(">", ">");
+        text = text.Replace("<", "<");
+        //Regex.Replace(text, @"\b&([#a-z0-9]+;)", "x%x%");
+        return text;
+    }
+}
\ No newline at end of file
diff --git a/common/ASC.Textile/States/FootNoteFormatterState.cs b/common/ASC.Textile/States/FootNoteFormatterState.cs
index 9726501888..161e1c93e4 100644
--- a/common/ASC.Textile/States/FootNoteFormatterState.cs
+++ b/common/ASC.Textile/States/FootNoteFormatterState.cs
@@ -11,50 +11,49 @@
 #endregion
 
 
-namespace Textile.States
+namespace Textile.States;
+
+[FormatterState(SimpleBlockFormatterState.PatternBegin + @"fn[0-9]+" + SimpleBlockFormatterState.PatternEnd)]
+public class FootNoteFormatterState : SimpleBlockFormatterState
 {
-    [FormatterState(SimpleBlockFormatterState.PatternBegin + @"fn[0-9]+" + SimpleBlockFormatterState.PatternEnd)]
-    public class FootNoteFormatterState : SimpleBlockFormatterState
+    private int _noteID = 0;
+
+    public FootNoteFormatterState(TextileFormatter f)
+        : base(f)
     {
-        int m_noteID = 0;
+    }
 
-        public FootNoteFormatterState(TextileFormatter f)
-            : base(f)
-        {
-        }
+    public override void Enter()
+    {
+        Formatter.Output.Write(
+            string.Format("<p id=\"fn{0}\"{1}><sup>{2}</sup> ",
+                _noteID,
+                FormattedStylesAndAlignment("p"),
+                _noteID));
+    }
 
-        public override void Enter()
-        {
-            Formatter.Output.Write(
-                string.Format("<p id=\"fn{0}\"{1}><sup>{2}</sup> ",
-                    m_noteID,
-                    FormattedStylesAndAlignment("p"),
-                    m_noteID));
-        }
+    public override void Exit()
+    {
+        Formatter.Output.WriteLine("</p>");
+    }
 
-        public override void Exit()
-        {
-            Formatter.Output.WriteLine("</p>");
-        }
+    public override void FormatLine(string input)
+    {
+        Formatter.Output.Write(input);
+    }
 
-        public override void FormatLine(string input)
-        {
-            Formatter.Output.Write(input);
-        }
+    public override bool ShouldExit(string input)
+    {
+        return true;
+    }
+    protected override void OnContextAcquired()
+    {
+        var m = Regex.Match(Tag, @"^fn(?<id>[0-9]+)");
+        _noteID = int.Parse(m.Groups["id"].Value);
+    }
 
-        public override bool ShouldExit(string input)
-        {
-            return true;
-        }
-        protected override void OnContextAcquired()
-        {
-            var m = Regex.Match(Tag, @"^fn(?<id>[0-9]+)");
-            m_noteID = int.Parse(m.Groups["id"].Value);
-        }
-
-        public override bool ShouldNestState(FormatterState other)
-        {
-            return false;
-        }
+    public override bool ShouldNestState(FormatterState other)
+    {
+        return false;
     }
 }
diff --git a/common/ASC.Textile/States/HeaderFormatterState.cs b/common/ASC.Textile/States/HeaderFormatterState.cs
index 35dfa12ba1..6536c09c1a 100644
--- a/common/ASC.Textile/States/HeaderFormatterState.cs
+++ b/common/ASC.Textile/States/HeaderFormatterState.cs
@@ -11,95 +11,94 @@
 #endregion
 
 
-namespace Textile.States
+namespace Textile.States;
+
+[FormatterState(SimpleBlockFormatterState.PatternBegin + @"pad[0-9]+" + SimpleBlockFormatterState.PatternEnd)]
+public class PaddingFormatterState : SimpleBlockFormatterState
 {
-    [FormatterState(SimpleBlockFormatterState.PatternBegin + @"pad[0-9]+" + SimpleBlockFormatterState.PatternEnd)]
-    public class PaddingFormatterState : SimpleBlockFormatterState
+    public PaddingFormatterState(TextileFormatter formatter)
+        : base(formatter)
     {
-        public PaddingFormatterState(TextileFormatter formatter)
-            : base(formatter)
+    }
+
+    public int HeaderLevel { get; private set; } = 0;
+
+
+    public override void Enter()
+    {
+        for (var i = 0; i < HeaderLevel; i++)
         {
-        }
-
-        public int HeaderLevel { get; private set; } = 0;
-
-
-        public override void Enter()
-        {
-            for (var i = 0; i < HeaderLevel; i++)
-            {
-                Formatter.Output.Write($"<br {FormattedStylesAndAlignment("br")}/>");
-            }
-        }
-
-        public override void Exit()
-        {
-        }
-
-        protected override void OnContextAcquired()
-        {
-            var m = Regex.Match(Tag, @"^pad(?<lvl>[0-9]+)");
-            HeaderLevel = int.Parse(m.Groups["lvl"].Value);
-        }
-
-        public override void FormatLine(string input)
-        {
-            Formatter.Output.Write(input);
-        }
-
-        public override bool ShouldExit(string intput)
-        {
-            return true;
-        }
-
-        public override bool ShouldNestState(FormatterState other)
-        {
-            return false;
+            Formatter.Output.Write($"<br {FormattedStylesAndAlignment("br")}/>");
         }
     }
 
-    /// <summary>
-    /// Formatting state for headers and titles.
-    /// </summary>
-    [FormatterState(SimpleBlockFormatterState.PatternBegin + @"h[0-9]+" + SimpleBlockFormatterState.PatternEnd)]
-    public class HeaderFormatterState : SimpleBlockFormatterState
+    public override void Exit()
     {
-        public int HeaderLevel { get; private set; } = 0;
+    }
 
-        public HeaderFormatterState(TextileFormatter f)
-            : base(f)
-        {
-        }
+    protected override void OnContextAcquired()
+    {
+        var m = Regex.Match(Tag, @"^pad(?<lvl>[0-9]+)");
+        HeaderLevel = int.Parse(m.Groups["lvl"].Value);
+    }
 
-        public override void Enter()
-        {
-            Formatter.Output.Write("<h" + HeaderLevel + FormattedStylesAndAlignment("h" + HeaderLevel) + ">");
-        }
+    public override void FormatLine(string input)
+    {
+        Formatter.Output.Write(input);
+    }
 
-        public override void Exit()
-        {
-            Formatter.Output.WriteLine("</h" + HeaderLevel + ">");
-        }
+    public override bool ShouldExit(string intput)
+    {
+        return true;
+    }
 
-        protected override void OnContextAcquired()
-        {
-            var m = Regex.Match(Tag, @"^h(?<lvl>[0-9]+)");
-            HeaderLevel = int.Parse(m.Groups["lvl"].Value);
-        }
-
-        public override void FormatLine(string input)
-        {
-            Formatter.Output.Write(input);
-        }
-
-        public override bool ShouldExit(string intput)
-        {
-            return true;
-        }
-
-        public override bool ShouldNestState(FormatterState other)
-        {
-            return false;
-        }
+    public override bool ShouldNestState(FormatterState other)
+    {
+        return false;
     }
 }
+
+/// <summary>
+/// Formatting state for headers and titles.
+/// </summary>
+[FormatterState(SimpleBlockFormatterState.PatternBegin + @"h[0-9]+" + SimpleBlockFormatterState.PatternEnd)]
+public class HeaderFormatterState : SimpleBlockFormatterState
+{
+    public int HeaderLevel { get; private set; } = 0;
+
+    public HeaderFormatterState(TextileFormatter f)
+        : base(f)
+    {
+    }
+
+    public override void Enter()
+    {
+        Formatter.Output.Write("<h" + HeaderLevel + FormattedStylesAndAlignment("h" + HeaderLevel) + ">");
+    }
+
+    public override void Exit()
+    {
+        Formatter.Output.WriteLine("</h" + HeaderLevel + ">");
+    }
+
+    protected override void OnContextAcquired()
+    {
+        var m = Regex.Match(Tag, @"^h(?<lvl>[0-9]+)");
+        HeaderLevel = int.Parse(m.Groups["lvl"].Value);
+    }
+
+    public override void FormatLine(string input)
+    {
+        Formatter.Output.Write(input);
+    }
+
+    public override bool ShouldExit(string intput)
+    {
+        return true;
+    }
+
+    public override bool ShouldNestState(FormatterState other)
+    {
+        return false;
+    }
+}
\ No newline at end of file
diff --git a/common/ASC.Textile/States/ListFormatterState.cs b/common/ASC.Textile/States/ListFormatterState.cs
index 2c2bca6d79..2a1190b291 100644
--- a/common/ASC.Textile/States/ListFormatterState.cs
+++ b/common/ASC.Textile/States/ListFormatterState.cs
@@ -21,15 +21,15 @@ namespace Textile.States
         internal const string PatternBegin = @"^\s*(?<tag>";
         internal const string PatternEnd = @")" + Globals.BlockModifiersPattern + @"(?:\s+)? (?<content>.*)$";
 
-        private bool m_firstItem = true;
-        private bool m_firstItemLine = true;
-        private string m_tag;
-        private string m_attsInfo;
-        private string m_alignInfo;
+        private bool _firstItem = true;
+        private bool _firstItemLine = true;
+        private string _tag;
+        private string _attsInfo;
+        private string _alignInfo;
 
         protected int NestingDepth
         {
-            get { return m_tag.Length; }
+            get { return _tag.Length; }
         }
 
         protected ListFormatterState(TextileFormatter formatter)
@@ -39,9 +39,9 @@ namespace Textile.States
 
         public override string Consume(string input, Match m)
         {
-            m_tag = m.Groups["tag"].Value;
-            m_alignInfo = m.Groups["align"].Value;
-            m_attsInfo = m.Groups["atts"].Value;
+            _tag = m.Groups["tag"].Value;
+            _alignInfo = m.Groups["align"].Value;
+            _attsInfo = m.Groups["atts"].Value;
             input = m.Groups["content"].Value;
 
             this.Formatter.ChangeState(this);
@@ -51,8 +51,8 @@ namespace Textile.States
 
         public sealed override void Enter()
         {
-            m_firstItem = true;
-            m_firstItemLine = true;
+            _firstItem = true;
+            _firstItemLine = true;
             WriteIndent();
         }
 
@@ -64,19 +64,19 @@ namespace Textile.States
 
         public sealed override void FormatLine(string input)
         {
-            if (m_firstItemLine)
+            if (_firstItemLine)
             {
-                if (!m_firstItem)
+                if (!_firstItem)
                     Formatter.Output.WriteLine("</li>");
                 Formatter.Output.Write("<li " + FormattedStylesAndAlignment("li") + ">");
-                m_firstItemLine = false;
+                _firstItemLine = false;
             }
             else
             {
                 Formatter.Output.WriteLine("<br />");
             }
             Formatter.Output.Write(input);
-            m_firstItem = false;
+            _firstItem = false;
         }
 
         public sealed override bool ShouldNestState(FormatterState other)
@@ -109,7 +109,7 @@ namespace Textile.States
             // previously (no "**" or "##" tags), or if it's
             // a new list item.
             if (IsMatchForMe(input, NestingDepth, NestingDepth))
-                m_firstItemLine = true;
+                _firstItemLine = true;
 
             return false;
         }
@@ -131,7 +131,7 @@ namespace Textile.States
 
         protected string FormattedStylesAndAlignment(string element)
         {
-            return Blocks.BlockAttributesParser.ParseBlockAttributes(m_alignInfo + m_attsInfo, element);
+            return Blocks.BlockAttributesParser.ParseBlockAttributes(_alignInfo + _attsInfo, element);
         }
     }
 }
diff --git a/common/ASC.Textile/States/NoTextileFormatterState.cs b/common/ASC.Textile/States/NoTextileFormatterState.cs
index 0353a2d0ea..05b84237f6 100644
--- a/common/ASC.Textile/States/NoTextileFormatterState.cs
+++ b/common/ASC.Textile/States/NoTextileFormatterState.cs
@@ -1,64 +1,63 @@
-namespace Textile.States
+namespace Textile.States;
+
+[FormatterState(@"^\s*<notextile>\s*$")]
+public class NoTextileFormatterState : FormatterState
 {
-    [FormatterState(@"^\s*<notextile>\s*$")]
-    public class NoTextileFormatterState : FormatterState
+    private bool _shouldExitNextTime = false;
+
+    public NoTextileFormatterState(TextileFormatter f)
+        : base(f)
     {
-        bool m_shouldExitNextTime = false;
+    }
 
-        public NoTextileFormatterState(TextileFormatter f)
-            : base(f)
-        {
-        }
+    public override string Consume(string input, Match m)
+    {
+        this.Formatter.ChangeState(this);
+        return string.Empty;
+    }
 
-        public override string Consume(string input, Match m)
-        {
-            this.Formatter.ChangeState(this);
-            return string.Empty;
-        }
+    public override bool ShouldNestState(FormatterState other)
+    {
+        return false;
+    }
 
-        public override bool ShouldNestState(FormatterState other)
-        {
-            return false;
-        }
+    public override void Enter()
+    {
+    }
 
-        public override void Enter()
-        {
-        }
+    public override void Exit()
+    {
+    }
 
-        public override void Exit()
-        {
-        }
+    public override void FormatLine(string input)
+    {
+        if (!_shouldExitNextTime)
+            Formatter.Output.WriteLine(input);
+    }
 
-        public override void FormatLine(string input)
-        {
-            if (!m_shouldExitNextTime)
-                Formatter.Output.WriteLine(input);
-        }
+    public override bool ShouldExit(string input)
+    {
+        if (_shouldExitNextTime)
+            return true;
+        _shouldExitNextTime = Regex.IsMatch(input, @"^\s*</notextile>\s*$");
+        return false;
+    }
 
-        public override bool ShouldExit(string input)
-        {
-            if (m_shouldExitNextTime)
-                return true;
-            m_shouldExitNextTime = Regex.IsMatch(input, @"^\s*</notextile>\s*$");
-            return false;
-        }
+    public override bool ShouldFormatBlocks(string input)
+    {
+        return false;
+    }
 
-        public override bool ShouldFormatBlocks(string input)
-        {
-            return false;
-        }
+    public override bool ShouldParseForNewFormatterState(string input)
+    {
+        return false;
+    }
 
-        public override bool ShouldParseForNewFormatterState(string input)
+    public override Type FallbackFormattingState
+    {
+        get
         {
-            return false;
-        }
-
-        public override Type FallbackFormattingState
-        {
-            get
-            {
-                return null;
-            }
+            return null;
         }
     }
-}
+}
\ No newline at end of file
diff --git a/common/ASC.Textile/States/OrderedListFormatterState.cs b/common/ASC.Textile/States/OrderedListFormatterState.cs
index 5a28d7c72d..942d6ec85b 100644
--- a/common/ASC.Textile/States/OrderedListFormatterState.cs
+++ b/common/ASC.Textile/States/OrderedListFormatterState.cs
@@ -11,37 +11,36 @@
 #endregion
 
 
-namespace Textile.States
+namespace Textile.States;
+
+/// <summary>
+/// Formatting state for a numbered list.
+/// </summary>
+[FormatterState(ListFormatterState.PatternBegin + @"#+" + ListFormatterState.PatternEnd)]
+public class OrderedListFormatterState : ListFormatterState
 {
-    /// <summary>
-    /// Formatting state for a numbered list.
-    /// </summary>
-    [FormatterState(ListFormatterState.PatternBegin + @"#+" + ListFormatterState.PatternEnd)]
-    public class OrderedListFormatterState : ListFormatterState
+    public OrderedListFormatterState(TextileFormatter formatter)
+        : base(formatter)
     {
-        public OrderedListFormatterState(TextileFormatter formatter)
-            : base(formatter)
-        {
-        }
+    }
 
-        protected override void WriteIndent()
-        {
-            Formatter.Output.WriteLine("<ol" + FormattedStylesAndAlignment("ol") + ">");
-        }
+    protected override void WriteIndent()
+    {
+        Formatter.Output.WriteLine("<ol" + FormattedStylesAndAlignment("ol") + ">");
+    }
 
-        protected override void WriteOutdent()
-        {
-            Formatter.Output.WriteLine("</ol>");
-        }
+    protected override void WriteOutdent()
+    {
+        Formatter.Output.WriteLine("</ol>");
+    }
 
-        protected override bool IsMatchForMe(string input, int minNestingDepth, int maxNestingDepth)
-        {
-            return Regex.IsMatch(input, @"^\s*([\*#]{" + (minNestingDepth - 1) + @"," + (maxNestingDepth - 1) + @"})#" + Globals.BlockModifiersPattern + @"\s");
-        }
+    protected override bool IsMatchForMe(string input, int minNestingDepth, int maxNestingDepth)
+    {
+        return Regex.IsMatch(input, @"^\s*([\*#]{" + (minNestingDepth - 1) + @"," + (maxNestingDepth - 1) + @"})#" + Globals.BlockModifiersPattern + @"\s");
+    }
 
-        protected override bool IsMatchForOthers(string input, int minNestingDepth, int maxNestingDepth)
-        {
-            return Regex.IsMatch(input, @"^\s*([\*#]{" + (minNestingDepth - 1) + @"," + (maxNestingDepth - 1) + @"})\*" + Globals.BlockModifiersPattern + @"\s");
-        }
+    protected override bool IsMatchForOthers(string input, int minNestingDepth, int maxNestingDepth)
+    {
+        return Regex.IsMatch(input, @"^\s*([\*#]{" + (minNestingDepth - 1) + @"," + (maxNestingDepth - 1) + @"})\*" + Globals.BlockModifiersPattern + @"\s");
     }
 }
diff --git a/common/ASC.Textile/States/ParagraphFormatterState.cs b/common/ASC.Textile/States/ParagraphFormatterState.cs
index 88acd5ed5e..d08a2b7a82 100644
--- a/common/ASC.Textile/States/ParagraphFormatterState.cs
+++ b/common/ASC.Textile/States/ParagraphFormatterState.cs
@@ -10,45 +10,44 @@
 // You must not remove this notice, or any other, from this software.
 #endregion
 
-namespace Textile.States
+namespace Textile.States;
+
+/// <summary>
+/// Formatting state for a standard text (i.e. just paragraphs).
+/// </summary>
+[FormatterState(SimpleBlockFormatterState.PatternBegin + @"p" + SimpleBlockFormatterState.PatternEnd)]
+public class ParagraphFormatterState : SimpleBlockFormatterState
 {
-    /// <summary>
-    /// Formatting state for a standard text (i.e. just paragraphs).
-    /// </summary>
-    [FormatterState(SimpleBlockFormatterState.PatternBegin + @"p" + SimpleBlockFormatterState.PatternEnd)]
-    public class ParagraphFormatterState : SimpleBlockFormatterState
+    public ParagraphFormatterState(TextileFormatter f)
+        : base(f)
     {
-        public ParagraphFormatterState(TextileFormatter f)
-            : base(f)
-        {
-        }
+    }
 
-        public override void Enter()
-        {
-            Formatter.Output.Write("<p" + FormattedStylesAndAlignment("p") + ">");
-        }
+    public override void Enter()
+    {
+        Formatter.Output.Write("<p" + FormattedStylesAndAlignment("p") + ">");
+    }
 
-        public override void Exit()
-        {
-            Formatter.Output.WriteLine("</p>");
-        }
+    public override void Exit()
+    {
+        Formatter.Output.WriteLine("</p>");
+    }
 
-        public override void FormatLine(string input)
-        {
-            Formatter.Output.Write(input);
-        }
+    public override void FormatLine(string input)
+    {
+        Formatter.Output.Write(input);
+    }
 
-        public override bool ShouldExit(string input)
-        {
-            if (Regex.IsMatch(input, @"^\s*$"))
-                return true;
-            Formatter.Output.WriteLine("<br />");
-            return false;
-        }
+    public override bool ShouldExit(string input)
+    {
+        if (Regex.IsMatch(input, @"^\s*$"))
+            return true;
+        Formatter.Output.WriteLine("<br />");
+        return false;
+    }
 
-        public override bool ShouldNestState(FormatterState other)
-        {
-            return false;
-        }
+    public override bool ShouldNestState(FormatterState other)
+    {
+        return false;
     }
 }
diff --git a/common/ASC.Textile/States/PassthroughFormatterState.cs b/common/ASC.Textile/States/PassthroughFormatterState.cs
index e56c1ba3ed..173c310a52 100644
--- a/common/ASC.Textile/States/PassthroughFormatterState.cs
+++ b/common/ASC.Textile/States/PassthroughFormatterState.cs
@@ -1,40 +1,39 @@
-namespace Textile.States
+namespace Textile.States;
+
+[FormatterState(@"^\s*<(h[0-9]|p|pre|blockquote)" + Globals.HtmlAttributesPattern + ">")]
+public class PassthroughFormatterState : FormatterState
 {
-    [FormatterState(@"^\s*<(h[0-9]|p|pre|blockquote)" + Globals.HtmlAttributesPattern + ">")]
-    public class PassthroughFormatterState : FormatterState
+    public PassthroughFormatterState(TextileFormatter f)
+        : base(f)
     {
-        public PassthroughFormatterState(TextileFormatter f)
-            : base(f)
-        {
-        }
+    }
 
-        public override string Consume(string input, Match m)
-        {
-            this.Formatter.ChangeState(this);
-            return input;
-        }
+    public override string Consume(string input, Match m)
+    {
+        this.Formatter.ChangeState(this);
+        return input;
+    }
 
-        public override bool ShouldNestState(FormatterState other)
-        {
-            return false;
-        }
+    public override bool ShouldNestState(FormatterState other)
+    {
+        return false;
+    }
 
-        public override void Enter()
-        {
-        }
+    public override void Enter()
+    {
+    }
 
-        public override void Exit()
-        {
-        }
+    public override void Exit()
+    {
+    }
 
-        public override void FormatLine(string input)
-        {
-            Formatter.Output.WriteLine(input);
-        }
+    public override void FormatLine(string input)
+    {
+        Formatter.Output.WriteLine(input);
+    }
 
-        public override bool ShouldExit(string input)
-        {
-            return true;
-        }
+    public override bool ShouldExit(string input)
+    {
+        return true;
     }
 }
diff --git a/common/ASC.Textile/States/PreCodeFormatterState.cs b/common/ASC.Textile/States/PreCodeFormatterState.cs
index 9d86e8de4a..15a2fe97d0 100644
--- a/common/ASC.Textile/States/PreCodeFormatterState.cs
+++ b/common/ASC.Textile/States/PreCodeFormatterState.cs
@@ -1,59 +1,58 @@
-namespace Textile.States
+namespace Textile.States;
+
+[FormatterState(SimpleBlockFormatterState.PatternBegin + @"bc" + SimpleBlockFormatterState.PatternEnd)]
+public class PreCodeFormatterState : SimpleBlockFormatterState
 {
-    [FormatterState(SimpleBlockFormatterState.PatternBegin + @"bc" + SimpleBlockFormatterState.PatternEnd)]
-    public class PreCodeFormatterState : SimpleBlockFormatterState
+    public PreCodeFormatterState(TextileFormatter formatter)
+        : base(formatter)
     {
-        public PreCodeFormatterState(TextileFormatter formatter)
-            : base(formatter)
-        {
-        }
+    }
 
-        public override void Enter()
-        {
-            Formatter.Output.Write("<pre><code>");
-        }
+    public override void Enter()
+    {
+        Formatter.Output.Write("<pre><code>");
+    }
 
-        public override void Exit()
-        {
-            Formatter.Output.WriteLine("</code></pre>");
-        }
+    public override void Exit()
+    {
+        Formatter.Output.WriteLine("</code></pre>");
+    }
 
-        public override void FormatLine(string input)
-        {
-            Formatter.Output.WriteLine(FixEntities(input));
-        }
+    public override void FormatLine(string input)
+    {
+        Formatter.Output.WriteLine(FixEntities(input));
+    }
 
-        public override bool ShouldExit(string input)
-        {
-            if (Regex.IsMatch(input, @"^\s*$"))
-                return true;
-            Formatter.Output.WriteLine("<br />");
-            return false;
-        }
+    public override bool ShouldExit(string input)
+    {
+        if (Regex.IsMatch(input, @"^\s*$"))
+            return true;
+        Formatter.Output.WriteLine("<br />");
+        return false;
+    }
 
-        public override bool ShouldFormatBlocks(string input)
-        {
-            return false;
-        }
+    public override bool ShouldFormatBlocks(string input)
+    {
+        return false;
+    }
 
-        public override bool ShouldNestState(FormatterState other)
-        {
-            return false;
-        }
+    public override bool ShouldNestState(FormatterState other)
+    {
+        return false;
+    }
 
-        public override bool ShouldParseForNewFormatterState(string input)
-        {
-            return false;
-        }
+    public override bool ShouldParseForNewFormatterState(string input)
+    {
+        return false;
+    }
 
-        private string FixEntities(string text)
-        {
-            // de-entify any remaining angle brackets or ampersands
-            text = text.Replace("&", "&");
-            text = text.Replace(">", ">");
-            text = text.Replace("<", "<");
-            //Regex.Replace(text, @"\b&([#a-z0-9]+;)", "x%x%");
-            return text;
-        }
+    private string FixEntities(string text)
+    {
+        // de-entify any remaining angle brackets or ampersands
+        text = text.Replace("&", "&");
+        text = text.Replace(">", ">");
+        text = text.Replace("<", "<");
+        //Regex.Replace(text, @"\b&([#a-z0-9]+;)", "x%x%");
+        return text;
     }
 }
diff --git a/common/ASC.Textile/States/PreFormatterState.cs b/common/ASC.Textile/States/PreFormatterState.cs
index afbeeffb63..cff68cdb7e 100644
--- a/common/ASC.Textile/States/PreFormatterState.cs
+++ b/common/ASC.Textile/States/PreFormatterState.cs
@@ -1,75 +1,74 @@
-namespace Textile.States
+namespace Textile.States;
+
+[FormatterState(@"^\s*<pre" + Globals.HtmlAttributesPattern + ">")]
+public class PreFormatterState : FormatterState
 {
-    [FormatterState(@"^\s*<pre" + Globals.HtmlAttributesPattern + ">")]
-    public class PreFormatterState : FormatterState
+    private bool _shouldExitNextTime = false;
+    private int _fakeNestingDepth = 0;
+
+    public PreFormatterState(TextileFormatter f)
+        : base(f)
     {
-        bool m_shouldExitNextTime = false;
-        int m_fakeNestingDepth = 0;
-
-        public PreFormatterState(TextileFormatter f)
-            : base(f)
-        {
-        }
-
-        public override string Consume(string input, Match m)
-        {
-            if (!Regex.IsMatch(input, "</pre>"))
-            {
-                this.Formatter.ChangeState(this);
-            }
-            else
-            {
-                this.Formatter.ChangeState(new PassthroughFormatterState(this.Formatter));
-            }
-            return input;
-        }
-
-        public override bool ShouldNestState(FormatterState other)
-        {
-            return false;
-        }
-
-        public override void Enter()
-        {
-        }
-
-        public override void Exit()
-        {
-        }
-
-        public override void FormatLine(string input)
-        {
-            if (Regex.IsMatch(input, "<pre>"))
-                m_fakeNestingDepth++;
-
-            Formatter.Output.WriteLine(input);
-        }
-
-        public override bool ShouldExit(string input)
-        {
-            if (m_shouldExitNextTime)
-                return true;
-            if (Regex.IsMatch(input, @"</pre>"))
-                m_fakeNestingDepth--;
-            if (m_fakeNestingDepth <= 0)
-                m_shouldExitNextTime = true;
-            return false;
-        }
-
-        public override bool ShouldFormatBlocks(string input)
-        {
-            return false;
-        }
-
-        public override bool ShouldParseForNewFormatterState(string input)
-        {
-            // Only allow a child formatting state for <code> tag.
-            return Regex.IsMatch(input, @"^\s*<code");
-        }
-
-        public override Type FallbackFormattingState
-        {
-            get { return null; }
-        }
     }
-}
+
+    public override string Consume(string input, Match m)
+    {
+        if (!Regex.IsMatch(input, "</pre>"))
+        {
+            this.Formatter.ChangeState(this);
+        }
+        else
+        {
+            this.Formatter.ChangeState(new PassthroughFormatterState(this.Formatter));
+        }
+        return input;
+    }
+
+    public override bool ShouldNestState(FormatterState other)
+    {
+        return false;
+    }
+
+    public override void Enter()
+    {
+    }
+
+    public override void Exit()
+    {
+    }
+
+    public override void FormatLine(string input)
+    {
+        if (Regex.IsMatch(input, "<pre>"))
+            _fakeNestingDepth++;
+
+        Formatter.Output.WriteLine(input);
+    }
+
+    public override bool ShouldExit(string input)
+    {
+        if (_shouldExitNextTime)
+            return true;
+        if (Regex.IsMatch(input, @"</pre>"))
+            _fakeNestingDepth--;
+        if (_fakeNestingDepth <= 0)
+            _shouldExitNextTime = true;
+        return false;
+    }
+
+    public override bool ShouldFormatBlocks(string input)
+    {
+        return false;
+    }
+
+    public override bool ShouldParseForNewFormatterState(string input)
+    {
+        // Only allow a child formatting state for <code> tag.
+        return Regex.IsMatch(input, @"^\s*<code");
+    }
+
+    public override Type FallbackFormattingState
+    {
+        get { return null; }
+    }
+}
\ No newline at end of file
diff --git a/common/ASC.Textile/States/SimpleBlockFormatterState.cs b/common/ASC.Textile/States/SimpleBlockFormatterState.cs
index 6716ef60dd..9350719c26 100644
--- a/common/ASC.Textile/States/SimpleBlockFormatterState.cs
+++ b/common/ASC.Textile/States/SimpleBlockFormatterState.cs
@@ -1,64 +1,63 @@
-namespace Textile.States
+namespace Textile.States;
+
+public abstract class SimpleBlockFormatterState : FormatterState
 {
-    public abstract class SimpleBlockFormatterState : FormatterState
+    internal const string PatternBegin = @"^\s*(?<tag>";
+    internal const string PatternEnd = @")" + Globals.AlignPattern + Globals.BlockModifiersPattern + @"\.(?:\s+)?(?<content>.*)$";
+
+    public string Tag { get; private set; } = null;
+
+    public string AlignInfo { get; private set; } = null;
+
+    public string AttInfo { get; private set; } = null;
+
+    protected SimpleBlockFormatterState(TextileFormatter formatter)
+        : base(formatter)
     {
-        internal const string PatternBegin = @"^\s*(?<tag>";
-        internal const string PatternEnd = @")" + Globals.AlignPattern + Globals.BlockModifiersPattern + @"\.(?:\s+)?(?<content>.*)$";
-
-        public string Tag { get; private set; } = null;
-
-        public string AlignInfo { get; private set; } = null;
-
-        public string AttInfo { get; private set; } = null;
-
-        protected SimpleBlockFormatterState(TextileFormatter formatter)
-            : base(formatter)
-        {
-        }
-
-        public override string Consume(string input, Match m)
-        {
-            Tag = m.Groups["tag"].Value;
-            AlignInfo = m.Groups["align"].Value;
-            AttInfo = m.Groups["atts"].Value;
-            input = m.Groups["content"].Value;
-
-            OnContextAcquired();
-
-            this.Formatter.ChangeState(this);
-
-            return input;
-        }
-
-        public override bool ShouldNestState(FormatterState other)
-        {
-            var blockFormatterState = (SimpleBlockFormatterState)other;
-            return blockFormatterState.Tag != Tag ||
-                    blockFormatterState.AlignInfo != AlignInfo ||
-                    blockFormatterState.AttInfo != AttInfo;
-        }
-
-        protected virtual void OnContextAcquired()
-        {
-        }
-
-        /// <summary>
-        /// 
-        /// </summary>
-        /// <returns></returns>
-        protected string FormattedAlignment()
-        {
-            return Blocks.BlockAttributesParser.ParseBlockAttributes(AlignInfo);
-        }
-
-        protected string FormattedStyles(string element)
-        {
-            return Blocks.BlockAttributesParser.ParseBlockAttributes(AttInfo, element);
-        }
-
-        protected string FormattedStylesAndAlignment(string element)
-        {
-            return Blocks.BlockAttributesParser.ParseBlockAttributes(AlignInfo + AttInfo, element);
-        }
     }
-}
+
+    public override string Consume(string input, Match m)
+    {
+        Tag = m.Groups["tag"].Value;
+        AlignInfo = m.Groups["align"].Value;
+        AttInfo = m.Groups["atts"].Value;
+        input = m.Groups["content"].Value;
+
+        OnContextAcquired();
+
+        this.Formatter.ChangeState(this);
+
+        return input;
+    }
+
+    public override bool ShouldNestState(FormatterState other)
+    {
+        var blockFormatterState = (SimpleBlockFormatterState)other;
+        return blockFormatterState.Tag != Tag ||
+                blockFormatterState.AlignInfo != AlignInfo ||
+                blockFormatterState.AttInfo != AttInfo;
+    }
+
+    protected virtual void OnContextAcquired()
+    {
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    protected string FormattedAlignment()
+    {
+        return Blocks.BlockAttributesParser.ParseBlockAttributes(AlignInfo);
+    }
+
+    protected string FormattedStyles(string element)
+    {
+        return Blocks.BlockAttributesParser.ParseBlockAttributes(AttInfo, element);
+    }
+
+    protected string FormattedStylesAndAlignment(string element)
+    {
+        return Blocks.BlockAttributesParser.ParseBlockAttributes(AlignInfo + AttInfo, element);
+    }
+}
\ No newline at end of file
diff --git a/common/ASC.Textile/States/TableCellParser.cs b/common/ASC.Textile/States/TableCellParser.cs
index 0450c27a99..5021b71238 100644
--- a/common/ASC.Textile/States/TableCellParser.cs
+++ b/common/ASC.Textile/States/TableCellParser.cs
@@ -1,45 +1,44 @@
-namespace Textile.States
+namespace Textile.States;
+
+public class TableCellParser
 {
-    public class TableCellParser
+    readonly string _lineFragment;
+
+    public TableCellParser(string input)
     {
-        readonly string m_lineFragment;
-
-        public TableCellParser(string input)
-        {
-            m_lineFragment = input;
-        }
-
-        public string GetLineFragmentFormatting()
-        {
-            var htmlTag = "td";
-
-            var m = Regex.Match(m_lineFragment,
-                                   @"^((?<head>_?)" +
-                                   Globals.SpanPattern +
-                                   Globals.AlignPattern +
-                                   Globals.BlockModifiersPattern +
-                                   @"(?<dot>\.)\s?)?" +
-                                   @"(?<content>.*)"
-                                  );
-            if (!m.Success)
-                throw new Exception("Couldn't parse table cell.");
-
-            if (m.Groups["head"].Value == "_")
-                htmlTag = "th";
-            //string opts = BlockAttributesParser.ParseBlockAttributes(m.Groups["span"].Value, "td") +
-            //              BlockAttributesParser.ParseBlockAttributes(m.Groups["align"].Value, "td") +
-            //              BlockAttributesParser.ParseBlockAttributes(m.Groups["atts"].Value, "td");
-            var opts = Blocks.BlockAttributesParser.ParseBlockAttributes(m.Groups["span"].Value + m.Groups["align"].Value + m.Groups["atts"].Value, "td");
-
-            var res = "<" + htmlTag + opts + ">";
-            // It may be possible the user actually intended to have a dot at the beginning of
-            // this cell's text, without any formatting (header tag or options).
-            if (string.IsNullOrEmpty(opts) && htmlTag == "td" && !string.IsNullOrEmpty(m.Groups["dot"].Value))
-                res += ".";
-            res += m.Groups["content"].Value;
-            res += "</" + htmlTag + ">";
-
-            return res;
-        }
+        _lineFragment = input;
     }
-}
+
+    public string GetLineFragmentFormatting()
+    {
+        var htmlTag = "td";
+
+        var m = Regex.Match(_lineFragment,
+                                @"^((?<head>_?)" +
+                                Globals.SpanPattern +
+                                Globals.AlignPattern +
+                                Globals.BlockModifiersPattern +
+                                @"(?<dot>\.)\s?)?" +
+                                @"(?<content>.*)"
+                                );
+        if (!m.Success)
+            throw new Exception("Couldn't parse table cell.");
+
+        if (m.Groups["head"].Value == "_")
+            htmlTag = "th";
+        //string opts = BlockAttributesParser.ParseBlockAttributes(m.Groups["span"].Value, "td") +
+        //              BlockAttributesParser.ParseBlockAttributes(m.Groups["align"].Value, "td") +
+        //              BlockAttributesParser.ParseBlockAttributes(m.Groups["atts"].Value, "td");
+        var opts = Blocks.BlockAttributesParser.ParseBlockAttributes(m.Groups["span"].Value + m.Groups["align"].Value + m.Groups["atts"].Value, "td");
+
+        var res = "<" + htmlTag + opts + ">";
+        // It may be possible the user actually intended to have a dot at the beginning of
+        // this cell's text, without any formatting (header tag or options).
+        if (string.IsNullOrEmpty(opts) && htmlTag == "td" && !string.IsNullOrEmpty(m.Groups["dot"].Value))
+            res += ".";
+        res += m.Groups["content"].Value;
+        res += "</" + htmlTag + ">";
+
+        return res;
+    }
+}
\ No newline at end of file
diff --git a/common/ASC.Textile/States/TableFormatterState.cs b/common/ASC.Textile/States/TableFormatterState.cs
index cbb0ff0fe5..34c18ec0be 100644
--- a/common/ASC.Textile/States/TableFormatterState.cs
+++ b/common/ASC.Textile/States/TableFormatterState.cs
@@ -1,65 +1,64 @@
-namespace Textile.States
+namespace Textile.States;
+
+[FormatterState(@"^\s*(?<tag>table)" +
+                Globals.SpanPattern +
+                Globals.AlignPattern +
+                Globals.BlockModifiersPattern +
+                @"\.\s*$")]
+public class TableFormatterState : FormatterState
 {
-    [FormatterState(@"^\s*(?<tag>table)" +
-                   Globals.SpanPattern +
-                   Globals.AlignPattern +
-                   Globals.BlockModifiersPattern +
-                   @"\.\s*$")]
-    public class TableFormatterState : FormatterState
+    private string _attsInfo;
+    private string _alignInfo;
+
+    public TableFormatterState(TextileFormatter f)
+        : base(f)
     {
-        private string m_attsInfo;
-        private string m_alignInfo;
+    }
 
-        public TableFormatterState(TextileFormatter f)
-            : base(f)
-        {
-        }
+    public override string Consume(string input, Match m)
+    {
+        _alignInfo = m.Groups["align"].Value;
+        _attsInfo = m.Groups["atts"].Value;
 
-        public override string Consume(string input, Match m)
-        {
-            m_alignInfo = m.Groups["align"].Value;
-            m_attsInfo = m.Groups["atts"].Value;
+        //TODO: check the state (it could already be a table!)
+        this.Formatter.ChangeState(this);
 
-            //TODO: check the state (it could already be a table!)
-            this.Formatter.ChangeState(this);
+        return string.Empty;
+    }
 
-            return string.Empty;
-        }
+    public override bool ShouldNestState(FormatterState other)
+    {
+        return false;
+    }
 
-        public override bool ShouldNestState(FormatterState other)
-        {
-            return false;
-        }
+    public override void Enter()
+    {
+        Formatter.Output.WriteLine("<table" + FormattedStylesAndAlignment() + ">");
+    }
 
-        public override void Enter()
-        {
-            Formatter.Output.WriteLine("<table" + FormattedStylesAndAlignment() + ">");
-        }
+    public override void Exit()
+    {
+        Formatter.Output.WriteLine("</table>");
+    }
 
-        public override void Exit()
-        {
-            Formatter.Output.WriteLine("</table>");
-        }
+    public override void FormatLine(string input)
+    {
+        if (input.Length > 0)
+            throw new Exception("The TableFormatter state is not supposed to format any lines!");
+    }
 
-        public override void FormatLine(string input)
-        {
-            if (input.Length > 0)
-                throw new Exception("The TableFormatter state is not supposed to format any lines!");
-        }
+    public override bool ShouldExit(string input)
+    {
+        var m = Regex.Match(input,
+                                @"^\s*" + Globals.AlignPattern + Globals.BlockModifiersPattern +
+                                @"(\.\s?)?(?<tag>\|)" +
+                                @"(?<content>.*)(?=\|)"
+                                );
+        return !m.Success;
+    }
 
-        public override bool ShouldExit(string input)
-        {
-            var m = Regex.Match(input,
-                                   @"^\s*" + Globals.AlignPattern + Globals.BlockModifiersPattern +
-                                   @"(\.\s?)?(?<tag>\|)" +
-                                   @"(?<content>.*)(?=\|)"
-                                  );
-            return !m.Success;
-        }
-
-        protected string FormattedStylesAndAlignment()
-        {
-            return Blocks.BlockAttributesParser.ParseBlockAttributes(m_alignInfo + m_attsInfo);
-        }
+    protected string FormattedStylesAndAlignment()
+    {
+        return Blocks.BlockAttributesParser.ParseBlockAttributes(_alignInfo + _attsInfo);
     }
 }
diff --git a/common/ASC.Textile/States/TableRowFormatterState.cs b/common/ASC.Textile/States/TableRowFormatterState.cs
index 9793568396..2048ef8939 100644
--- a/common/ASC.Textile/States/TableRowFormatterState.cs
+++ b/common/ASC.Textile/States/TableRowFormatterState.cs
@@ -1,73 +1,72 @@
-namespace Textile.States
+namespace Textile.States;
+
+[FormatterState(@"^\s*(" + Globals.AlignPattern + Globals.BlockModifiersPattern + @"\.\s?)?" +
+                                @"\|(?<content>.*)\|\s*$")]
+public class TableRowFormatterState : FormatterState
 {
-    [FormatterState(@"^\s*(" + Globals.AlignPattern + Globals.BlockModifiersPattern + @"\.\s?)?" +
-                                   @"\|(?<content>.*)\|\s*$")]
-    public class TableRowFormatterState : FormatterState
+    private string _attsInfo;
+    private string _alignInfo;
+
+    public TableRowFormatterState(TextileFormatter f)
+        : base(f)
     {
-        private string m_attsInfo;
-        private string m_alignInfo;
-
-        public TableRowFormatterState(TextileFormatter f)
-            : base(f)
-        {
-        }
-
-        public override string Consume(string input, Match m)
-        {
-            m_alignInfo = m.Groups["align"].Value;
-            m_attsInfo = m.Groups["atts"].Value;
-            input = "|" + m.Groups["content"].Value + "|";
-
-            if (!(this.Formatter.CurrentState is TableFormatterState))
-            {
-                var s = new TableFormatterState(this.Formatter);
-                this.Formatter.ChangeState(s);
-            }
-
-            this.Formatter.ChangeState(this);
-
-            return input;
-        }
-
-        public override bool ShouldNestState(FormatterState other)
-        {
-            return false;
-        }
-
-        public override void Enter()
-        {
-            Formatter.Output.WriteLine("<tr" + FormattedStylesAndAlignment() + ">");
-        }
-
-        public override void Exit()
-        {
-            Formatter.Output.WriteLine("</tr>");
-        }
-
-        public override void FormatLine(string input)
-        {
-            // can get: Align & Classes
-
-            var sb = new StringBuilder();
-            var cellsInput = input.Split('|');
-            for (var i = 1; i < cellsInput.Length - 1; i++)
-            {
-                var cellInput = cellsInput[i];
-                var tcp = new TableCellParser(cellInput);
-                sb.Append(tcp.GetLineFragmentFormatting());
-            }
-
-            Formatter.Output.WriteLine(sb.ToString());
-        }
-
-        public override bool ShouldExit(string input)
-        {
-            return true;
-        }
-
-        protected string FormattedStylesAndAlignment()
-        {
-            return Blocks.BlockAttributesParser.ParseBlockAttributes(m_alignInfo + m_attsInfo);
-        }
     }
-}
+
+    public override string Consume(string input, Match m)
+    {
+        _alignInfo = m.Groups["align"].Value;
+        _attsInfo = m.Groups["atts"].Value;
+        input = "|" + m.Groups["content"].Value + "|";
+
+        if (!(this.Formatter.CurrentState is TableFormatterState))
+        {
+            var s = new TableFormatterState(this.Formatter);
+            this.Formatter.ChangeState(s);
+        }
+
+        this.Formatter.ChangeState(this);
+
+        return input;
+    }
+
+    public override bool ShouldNestState(FormatterState other)
+    {
+        return false;
+    }
+
+    public override void Enter()
+    {
+        Formatter.Output.WriteLine("<tr" + FormattedStylesAndAlignment() + ">");
+    }
+
+    public override void Exit()
+    {
+        Formatter.Output.WriteLine("</tr>");
+    }
+
+    public override void FormatLine(string input)
+    {
+        // can get: Align & Classes
+
+        var sb = new StringBuilder();
+        var cellsInput = input.Split('|');
+        for (var i = 1; i < cellsInput.Length - 1; i++)
+        {
+            var cellInput = cellsInput[i];
+            var tcp = new TableCellParser(cellInput);
+            sb.Append(tcp.GetLineFragmentFormatting());
+        }
+
+        Formatter.Output.WriteLine(sb.ToString());
+    }
+
+    public override bool ShouldExit(string input)
+    {
+        return true;
+    }
+
+    protected string FormattedStylesAndAlignment()
+    {
+        return Blocks.BlockAttributesParser.ParseBlockAttributes(_alignInfo + _attsInfo);
+    }
+}
\ No newline at end of file
diff --git a/common/ASC.Textile/States/UnorderedListFormatterState.cs b/common/ASC.Textile/States/UnorderedListFormatterState.cs
index 96eaf79909..a809f1bf52 100644
--- a/common/ASC.Textile/States/UnorderedListFormatterState.cs
+++ b/common/ASC.Textile/States/UnorderedListFormatterState.cs
@@ -10,37 +10,36 @@
 // You must not remove this notice, or any other, from this software.
 #endregion
 
-namespace Textile.States
+namespace Textile.States;
+
+/// <summary>
+/// Formatting state for a bulleted list.
+/// </summary>
+[FormatterState(ListFormatterState.PatternBegin + @"\*+" + ListFormatterState.PatternEnd)]
+public class UnorderedListFormatterState : ListFormatterState
 {
-    /// <summary>
-    /// Formatting state for a bulleted list.
-    /// </summary>
-    [FormatterState(ListFormatterState.PatternBegin + @"\*+" + ListFormatterState.PatternEnd)]
-    public class UnorderedListFormatterState : ListFormatterState
+    public UnorderedListFormatterState(TextileFormatter formatter)
+        : base(formatter)
     {
-        public UnorderedListFormatterState(TextileFormatter formatter)
-            : base(formatter)
-        {
-        }
-
-        protected override void WriteIndent()
-        {
-            Formatter.Output.WriteLine("<ul" + FormattedStylesAndAlignment("ul") + ">");
-        }
-
-        protected override void WriteOutdent()
-        {
-            Formatter.Output.WriteLine("</ul>");
-        }
-
-        protected override bool IsMatchForMe(string input, int minNestingDepth, int maxNestingDepth)
-        {
-            return Regex.IsMatch(input, @"^\s*[\*]{" + minNestingDepth + @"," + maxNestingDepth + @"}" + Globals.BlockModifiersPattern + @"\s");
-        }
-
-        protected override bool IsMatchForOthers(string input, int minNestingDepth, int maxNestingDepth)
-        {
-            return Regex.IsMatch(input, @"^\s*[#]{" + minNestingDepth + @"," + maxNestingDepth + @"}" + Globals.BlockModifiersPattern + @"\s");
-        }
     }
-}
+
+    protected override void WriteIndent()
+    {
+        Formatter.Output.WriteLine("<ul" + FormattedStylesAndAlignment("ul") + ">");
+    }
+
+    protected override void WriteOutdent()
+    {
+        Formatter.Output.WriteLine("</ul>");
+    }
+
+    protected override bool IsMatchForMe(string input, int minNestingDepth, int maxNestingDepth)
+    {
+        return Regex.IsMatch(input, @"^\s*[\*]{" + minNestingDepth + @"," + maxNestingDepth + @"}" + Globals.BlockModifiersPattern + @"\s");
+    }
+
+    protected override bool IsMatchForOthers(string input, int minNestingDepth, int maxNestingDepth)
+    {
+        return Regex.IsMatch(input, @"^\s*[#]{" + minNestingDepth + @"," + maxNestingDepth + @"}" + Globals.BlockModifiersPattern + @"\s");
+    }
+}
\ No newline at end of file
diff --git a/common/ASC.Textile/StringBuilderTextileFormatter.cs b/common/ASC.Textile/StringBuilderTextileFormatter.cs
index ca5f33810a..1ab090d209 100644
--- a/common/ASC.Textile/StringBuilderTextileFormatter.cs
+++ b/common/ASC.Textile/StringBuilderTextileFormatter.cs
@@ -11,42 +11,41 @@
 #endregion
 
 
-namespace Textile
+namespace Textile;
+
+public class StringBuilderTextileFormatter : IOutputter
 {
-    public class StringBuilderTextileFormatter : IOutputter
+    private StringBuilder _stringBuilder = null;
+
+    public StringBuilderTextileFormatter()
     {
-        StringBuilder m_stringBuilder = null;
-
-        public StringBuilderTextileFormatter()
-        {
-        }
-
-        public string GetFormattedText()
-        {
-            return m_stringBuilder.ToString();
-        }
-
-        #region IOutputter Members
-
-        public void Begin()
-        {
-            m_stringBuilder = new StringBuilder();
-        }
-
-        public void End()
-        {
-        }
-
-        public void Write(string text)
-        {
-            m_stringBuilder.Append(text);
-        }
-
-        public void WriteLine(string line)
-        {
-            m_stringBuilder.AppendLine(line);
-        }
-
-        #endregion
     }
+
+    public string GetFormattedText()
+    {
+        return _stringBuilder.ToString();
+    }
+
+    #region IOutputter Members
+
+    public void Begin()
+    {
+        _stringBuilder = new StringBuilder();
+    }
+
+    public void End()
+    {
+    }
+
+    public void Write(string text)
+    {
+        _stringBuilder.Append(text);
+    }
+
+    public void WriteLine(string line)
+    {
+        _stringBuilder.AppendLine(line);
+    }
+
+    #endregion
 }
diff --git a/common/ASC.Textile/StyleReader.cs b/common/ASC.Textile/StyleReader.cs
index 66c9cabbd0..28be943a6f 100644
--- a/common/ASC.Textile/StyleReader.cs
+++ b/common/ASC.Textile/StyleReader.cs
@@ -1,28 +1,27 @@
-namespace Textile
+namespace Textile;
+
+public class StyleReader
 {
-    public class StyleReader
+    private readonly Regex _styleParser = new Regex(@"(?<selector>[^\{]+)(?<style>[^\}]+)");
+    private readonly Regex _minimizer = new Regex(@";\s+");
+
+    private readonly System.Collections.Specialized.StringDictionary _tagStyler = new System.Collections.Specialized.StringDictionary();
+
+    public StyleReader(string styles)
     {
-        private readonly Regex _styleParser = new Regex(@"(?<selector>[^\{]+)(?<style>[^\}]+)");
-        private readonly Regex _minimizer = new Regex(@";\s+");
-
-        private readonly System.Collections.Specialized.StringDictionary _tagStyler = new System.Collections.Specialized.StringDictionary();
-
-        public StyleReader(string styles)
+        //Read it
+        var matches = _styleParser.Matches(styles.Replace(System.Environment.NewLine, ""));
+        foreach (Match match in matches)
         {
-            //Read it
-            var matches = _styleParser.Matches(styles.Replace(System.Environment.NewLine, ""));
-            foreach (Match match in matches)
+            if (match.Success)
             {
-                if (match.Success)
-                {
-                    _tagStyler.Add(match.Groups["selector"].Value.Trim('{', '}', ' '), _minimizer.Replace(match.Groups["style"].Value.Trim('{', '}', ' '), ";"));
-                }
+                _tagStyler.Add(match.Groups["selector"].Value.Trim('{', '}', ' '), _minimizer.Replace(match.Groups["style"].Value.Trim('{', '}', ' '), ";"));
             }
         }
+    }
 
-        public string GetStyle(string tag)
-        {
-            return _tagStyler[tag];
-        }
+    public string GetStyle(string tag)
+    {
+        return _tagStyler[tag];
     }
 }
\ No newline at end of file
diff --git a/common/ASC.Textile/TextileFormatter.cs b/common/ASC.Textile/TextileFormatter.cs
index 61539a064b..c812a9a6fb 100644
--- a/common/ASC.Textile/TextileFormatter.cs
+++ b/common/ASC.Textile/TextileFormatter.cs
@@ -12,160 +12,159 @@
 
 
 
-namespace Textile
+namespace Textile;
+
+/// <summary>
+/// Class for formatting Textile input into HTML.
+/// </summary>
+/// This class takes raw Textile text and sends the
+/// formatted, ready to display HTML string to the
+/// outputter defined in the constructor of the
+/// class.
+public partial class TextileFormatter
 {
-    /// <summary>
-    /// Class for formatting Textile input into HTML.
-    /// </summary>
-    /// This class takes raw Textile text and sends the
-    /// formatted, ready to display HTML string to the
-    /// outputter defined in the constructor of the
-    /// class.
-    public partial class TextileFormatter
+    static TextileFormatter()
     {
-        static TextileFormatter()
-        {
-            RegisterFormatterState(typeof(HeaderFormatterState));
-            RegisterFormatterState(typeof(PaddingFormatterState));
-            RegisterFormatterState(typeof(BlockQuoteFormatterState));
-            RegisterFormatterState(typeof(ParagraphFormatterState));
-            RegisterFormatterState(typeof(FootNoteFormatterState));
-            RegisterFormatterState(typeof(OrderedListFormatterState));
-            RegisterFormatterState(typeof(UnorderedListFormatterState));
-            RegisterFormatterState(typeof(TableFormatterState));
-            RegisterFormatterState(typeof(TableRowFormatterState));
-            RegisterFormatterState(typeof(CodeFormatterState));
-            RegisterFormatterState(typeof(PreFormatterState));
-            RegisterFormatterState(typeof(PreCodeFormatterState));
-            RegisterFormatterState(typeof(NoTextileFormatterState));
+        RegisterFormatterState(typeof(HeaderFormatterState));
+        RegisterFormatterState(typeof(PaddingFormatterState));
+        RegisterFormatterState(typeof(BlockQuoteFormatterState));
+        RegisterFormatterState(typeof(ParagraphFormatterState));
+        RegisterFormatterState(typeof(FootNoteFormatterState));
+        RegisterFormatterState(typeof(OrderedListFormatterState));
+        RegisterFormatterState(typeof(UnorderedListFormatterState));
+        RegisterFormatterState(typeof(TableFormatterState));
+        RegisterFormatterState(typeof(TableRowFormatterState));
+        RegisterFormatterState(typeof(CodeFormatterState));
+        RegisterFormatterState(typeof(PreFormatterState));
+        RegisterFormatterState(typeof(PreCodeFormatterState));
+        RegisterFormatterState(typeof(NoTextileFormatterState));
 
-            RegisterBlockModifier(new NoTextileBlockModifier());
-            RegisterBlockModifier(new CodeBlockModifier());
-            RegisterBlockModifier(new PreBlockModifier());
-            RegisterBlockModifier(new HyperLinkBlockModifier());
-            RegisterBlockModifier(new ImageBlockModifier());
-            RegisterBlockModifier(new GlyphBlockModifier());
-            RegisterBlockModifier(new EmphasisPhraseBlockModifier());
-            RegisterBlockModifier(new StrongPhraseBlockModifier());
-            RegisterBlockModifier(new ItalicPhraseBlockModifier());
-            RegisterBlockModifier(new BoldPhraseBlockModifier());
-            RegisterBlockModifier(new CitePhraseBlockModifier());
-            RegisterBlockModifier(new DeletedPhraseBlockModifier());
-            RegisterBlockModifier(new InsertedPhraseBlockModifier());
-            RegisterBlockModifier(new SuperScriptPhraseBlockModifier());
-            RegisterBlockModifier(new SubScriptPhraseBlockModifier());
-            RegisterBlockModifier(new SpanPhraseBlockModifier());
-            RegisterBlockModifier(new FootNoteReferenceBlockModifier());
+        RegisterBlockModifier(new NoTextileBlockModifier());
+        RegisterBlockModifier(new CodeBlockModifier());
+        RegisterBlockModifier(new PreBlockModifier());
+        RegisterBlockModifier(new HyperLinkBlockModifier());
+        RegisterBlockModifier(new ImageBlockModifier());
+        RegisterBlockModifier(new GlyphBlockModifier());
+        RegisterBlockModifier(new EmphasisPhraseBlockModifier());
+        RegisterBlockModifier(new StrongPhraseBlockModifier());
+        RegisterBlockModifier(new ItalicPhraseBlockModifier());
+        RegisterBlockModifier(new BoldPhraseBlockModifier());
+        RegisterBlockModifier(new CitePhraseBlockModifier());
+        RegisterBlockModifier(new DeletedPhraseBlockModifier());
+        RegisterBlockModifier(new InsertedPhraseBlockModifier());
+        RegisterBlockModifier(new SuperScriptPhraseBlockModifier());
+        RegisterBlockModifier(new SubScriptPhraseBlockModifier());
+        RegisterBlockModifier(new SpanPhraseBlockModifier());
+        RegisterBlockModifier(new FootNoteReferenceBlockModifier());
 
-            //TODO: capitals block modifier
-        }
-
-        /// <summary>
-        /// Public constructor, where the formatter is hooked up
-        /// to an outputter.
-        /// </summary>
-        /// <param name="output">The outputter to be used.</param>
-        public TextileFormatter(IOutputter output)
-        {
-            Output = output;
-        }
-
-        #region Properties for Output
-
-        /// <summary>
-        /// The ouputter to which the formatted text
-        /// is sent to.
-        /// </summary>
-        public IOutputter Output { get; } = null;
-
-        /// <summary>
-        /// The offset for the header tags.
-        /// </summary>
-        /// When the formatted text is inserted into another page
-        /// there might be a need to offset all headers (h1 becomes
-        /// h4, for instance). The header offset allows this.
-        public int HeaderOffset { get; set; } = 0;
-
-        #endregion
-
-        #region Properties for Conversion
-
-        public bool FormatImages
-        {
-            get { return IsBlockModifierEnabled(typeof(ImageBlockModifier)); }
-            set { SwitchBlockModifier(typeof(ImageBlockModifier), value); }
-        }
-
-        public bool FormatLinks
-        {
-            get { return IsBlockModifierEnabled(typeof(HyperLinkBlockModifier)); }
-            set { SwitchBlockModifier(typeof(HyperLinkBlockModifier), value); }
-        }
-
-        public bool FormatLists
-        {
-            get { return IsBlockModifierEnabled(typeof(OrderedListFormatterState)); }
-            set
-            {
-                SwitchBlockModifier(typeof(OrderedListFormatterState), value);
-                SwitchBlockModifier(typeof(UnorderedListFormatterState), value);
-            }
-        }
-
-        public bool FormatFootNotes
-        {
-            get { return IsBlockModifierEnabled(typeof(FootNoteReferenceBlockModifier)); }
-            set
-            {
-                SwitchBlockModifier(typeof(FootNoteReferenceBlockModifier), value);
-                SwitchFormatterState(typeof(FootNoteFormatterState), value);
-            }
-        }
-
-        public bool FormatTables
-        {
-            get { return IsFormatterStateEnabled(typeof(TableFormatterState)); }
-            set
-            {
-                SwitchFormatterState(typeof(TableFormatterState), value);
-                SwitchFormatterState(typeof(TableRowFormatterState), value);
-            }
-        }
-
-        /// <summary>
-        /// Attribute to add to all links.
-        /// </summary>
-        public string Rel { get; set; } = string.Empty;
-
-        #endregion
-
-        #region Utility Methods
-
-        /// <summary>
-        /// Utility method for quickly formatting a text without having
-        /// to create a TextileFormatter with an IOutputter.
-        /// </summary>
-        /// <param name="input">The string to format</param>
-        /// <returns>The formatted version of the string</returns>
-        public static string FormatString(string input)
-        {
-            var s = new StringBuilderTextileFormatter();
-            var f = new TextileFormatter(s);
-            f.Format(input);
-            return s.GetFormattedText();
-        }
-
-        /// <summary>
-        /// Utility method for formatting a text with a given outputter.
-        /// </summary>
-        /// <param name="input">The string to format</param>
-        /// <param name="outputter">The IOutputter to use</param>
-        public static void FormatString(string input, IOutputter outputter)
-        {
-            var f = new TextileFormatter(outputter);
-            f.Format(input);
-        }
-
-        #endregion
+        //TODO: capitals block modifier
     }
+
+    /// <summary>
+    /// Public constructor, where the formatter is hooked up
+    /// to an outputter.
+    /// </summary>
+    /// <param name="output">The outputter to be used.</param>
+    public TextileFormatter(IOutputter output)
+    {
+        Output = output;
+    }
+
+    #region Properties for Output
+
+    /// <summary>
+    /// The ouputter to which the formatted text
+    /// is sent to.
+    /// </summary>
+    public IOutputter Output { get; } = null;
+
+    /// <summary>
+    /// The offset for the header tags.
+    /// </summary>
+    /// When the formatted text is inserted into another page
+    /// there might be a need to offset all headers (h1 becomes
+    /// h4, for instance). The header offset allows this.
+    public int HeaderOffset { get; set; } = 0;
+
+    #endregion
+
+    #region Properties for Conversion
+
+    public bool FormatImages
+    {
+        get { return IsBlockModifierEnabled(typeof(ImageBlockModifier)); }
+        set { SwitchBlockModifier(typeof(ImageBlockModifier), value); }
+    }
+
+    public bool FormatLinks
+    {
+        get { return IsBlockModifierEnabled(typeof(HyperLinkBlockModifier)); }
+        set { SwitchBlockModifier(typeof(HyperLinkBlockModifier), value); }
+    }
+
+    public bool FormatLists
+    {
+        get { return IsBlockModifierEnabled(typeof(OrderedListFormatterState)); }
+        set
+        {
+            SwitchBlockModifier(typeof(OrderedListFormatterState), value);
+            SwitchBlockModifier(typeof(UnorderedListFormatterState), value);
+        }
+    }
+
+    public bool FormatFootNotes
+    {
+        get { return IsBlockModifierEnabled(typeof(FootNoteReferenceBlockModifier)); }
+        set
+        {
+            SwitchBlockModifier(typeof(FootNoteReferenceBlockModifier), value);
+            SwitchFormatterState(typeof(FootNoteFormatterState), value);
+        }
+    }
+
+    public bool FormatTables
+    {
+        get { return IsFormatterStateEnabled(typeof(TableFormatterState)); }
+        set
+        {
+            SwitchFormatterState(typeof(TableFormatterState), value);
+            SwitchFormatterState(typeof(TableRowFormatterState), value);
+        }
+    }
+
+    /// <summary>
+    /// Attribute to add to all links.
+    /// </summary>
+    public string Rel { get; set; } = string.Empty;
+
+    #endregion
+
+    #region Utility Methods
+
+    /// <summary>
+    /// Utility method for quickly formatting a text without having
+    /// to create a TextileFormatter with an IOutputter.
+    /// </summary>
+    /// <param name="input">The string to format</param>
+    /// <returns>The formatted version of the string</returns>
+    public static string FormatString(string input)
+    {
+        var s = new StringBuilderTextileFormatter();
+        var f = new TextileFormatter(s);
+        f.Format(input);
+        return s.GetFormattedText();
+    }
+
+    /// <summary>
+    /// Utility method for formatting a text with a given outputter.
+    /// </summary>
+    /// <param name="input">The string to format</param>
+    /// <param name="outputter">The IOutputter to use</param>
+    public static void FormatString(string input, IOutputter outputter)
+    {
+        var f = new TextileFormatter(outputter);
+        f.Format(input);
+    }
+
+    #endregion
 }
diff --git a/common/ASC.Textile/TextileFormatterBlocks.cs b/common/ASC.Textile/TextileFormatterBlocks.cs
index d6cfd0eb54..f2e095d1b8 100644
--- a/common/ASC.Textile/TextileFormatterBlocks.cs
+++ b/common/ASC.Textile/TextileFormatterBlocks.cs
@@ -11,40 +11,39 @@
 #endregion
 
 
-namespace Textile
+namespace Textile;
+
+public partial class TextileFormatter
 {
-    public partial class TextileFormatter
+    #region Block Modifiers Registration
+
+    private static readonly List<BlockModifier> s_blockModifiers = new List<BlockModifier>();
+    private static readonly List<Type> s_blockModifiersTypes = new List<Type>();
+
+    public static void RegisterBlockModifier(BlockModifier blockModifer)
     {
-        #region Block Modifiers Registration
-
-        private static readonly List<BlockModifier> s_blockModifiers = new List<BlockModifier>();
-        private static readonly List<Type> s_blockModifiersTypes = new List<Type>();
-
-        public static void RegisterBlockModifier(BlockModifier blockModifer)
-        {
-            s_blockModifiers.Add(blockModifer);
-            s_blockModifiersTypes.Add(blockModifer.GetType());
-        }
-
-        #endregion
-
-        #region Block Modifiers Management
-
-        private readonly List<Type> m_disabledBlockModifiers = new List<Type>();
-
-        public bool IsBlockModifierEnabled(Type type)
-        {
-            return !m_disabledBlockModifiers.Contains(type);
-        }
-
-        public void SwitchBlockModifier(Type type, bool onOff)
-        {
-            if (onOff)
-                m_disabledBlockModifiers.Remove(type);
-            else if (!m_disabledBlockModifiers.Contains(type))
-                m_disabledBlockModifiers.Add(type);
-        }
-
-        #endregion
+        s_blockModifiers.Add(blockModifer);
+        s_blockModifiersTypes.Add(blockModifer.GetType());
     }
+
+    #endregion
+
+    #region Block Modifiers Management
+
+    private readonly List<Type> _disabledBlockModifiers = new List<Type>();
+
+    public bool IsBlockModifierEnabled(Type type)
+    {
+        return !_disabledBlockModifiers.Contains(type);
+    }
+
+    public void SwitchBlockModifier(Type type, bool onOff)
+    {
+        if (onOff)
+            _disabledBlockModifiers.Remove(type);
+        else if (!_disabledBlockModifiers.Contains(type))
+            _disabledBlockModifiers.Add(type);
+    }
+
+    #endregion
 }
diff --git a/common/ASC.Textile/TextileFormatterFormatting.cs b/common/ASC.Textile/TextileFormatterFormatting.cs
index d5e5c72063..0dbbe338f1 100644
--- a/common/ASC.Textile/TextileFormatterFormatting.cs
+++ b/common/ASC.Textile/TextileFormatterFormatting.cs
@@ -11,108 +11,107 @@
 #endregion
 
 
-namespace Textile
+namespace Textile;
+
+public partial class TextileFormatter
 {
-    public partial class TextileFormatter
+    private readonly Regex _velocityArguments =
+        new Regex("nostyle(?<arg>.*?)/nostyle", RegexOptions.IgnoreCase | RegexOptions.Singleline);
+
+    private string ArgMatchReplace(Match match)
     {
-        private readonly Regex VelocityArguments =
-            new Regex("nostyle(?<arg>.*?)/nostyle", RegexOptions.IgnoreCase | RegexOptions.Singleline);
+        return match.Result("${arg}");
+    }
 
-        private string ArgMatchReplace(Match match)
+    #region Formatting Methods
+
+    /// <summary>
+    /// Formats the given text.
+    /// </summary>
+    /// <param name="input">The text to format.</param>
+    public void Format(string input)
+    {
+        Output.Begin();
+
+        // Clean the text...
+        var str = PrepareInputForFormatting(input);
+        // ...and format each line.
+        foreach (var line in str.Split('\n'))
         {
-            return match.Result("${arg}");
-        }
+            var tmp = line;
 
-        #region Formatting Methods
-
-        /// <summary>
-        /// Formats the given text.
-        /// </summary>
-        /// <param name="input">The text to format.</param>
-        public void Format(string input)
-        {
-            Output.Begin();
-
-            // Clean the text...
-            var str = PrepareInputForFormatting(input);
-            // ...and format each line.
-            foreach (var line in str.Split('\n'))
-            {
-                var tmp = line;
-
-                // Let's see if the current state(s) is(are) finished...
-                while (CurrentState != null && CurrentState.ShouldExit(tmp))
-                    PopState();
-
-                if (!Regex.IsMatch(tmp, @"^\s*$"))
-                {
-                    // Figure out the new state for this text line, if possible.
-                    if (CurrentState == null || CurrentState.ShouldParseForNewFormatterState(tmp))
-                    {
-                        tmp = HandleFormattingState(tmp);
-                    }
-                    // else, the current state doesn't want to be superceded by
-                    // a new one. We'll leave him be.
-
-                    // Modify the line with our block modifiers.
-                    if (CurrentState == null || CurrentState.ShouldFormatBlocks(tmp))
-                    {
-                        foreach (var blockModifier in s_blockModifiers)
-                        {
-                            //TODO: if not disabled...
-                            tmp = blockModifier.ModifyLine(tmp);
-                        }
-
-                        for (var i = s_blockModifiers.Count - 1; i >= 0; i--)
-                        {
-                            var blockModifier = s_blockModifiers[i];
-                            tmp = blockModifier.Conclude(tmp);
-                        }
-                    }
-
-                    tmp = VelocityArguments.Replace(tmp, ArgMatchReplace);
-
-                    // Format the current line.
-                    CurrentState.FormatLine(tmp);
-                }
-            }
-            // We're done. There might be a few states still on
-            // the stack (for example if the text ends with a nested
-            // list), so we must pop them all so that they have
-            // their "Exit" method called correctly.
-            while (m_stackOfStates.Count > 0)
+            // Let's see if the current state(s) is(are) finished...
+            while (CurrentState != null && CurrentState.ShouldExit(tmp))
                 PopState();
 
-            Output.End();
+            if (!Regex.IsMatch(tmp, @"^\s*$"))
+            {
+                // Figure out the new state for this text line, if possible.
+                if (CurrentState == null || CurrentState.ShouldParseForNewFormatterState(tmp))
+                {
+                    tmp = HandleFormattingState(tmp);
+                }
+                // else, the current state doesn't want to be superceded by
+                // a new one. We'll leave him be.
+
+                // Modify the line with our block modifiers.
+                if (CurrentState == null || CurrentState.ShouldFormatBlocks(tmp))
+                {
+                    foreach (var blockModifier in s_blockModifiers)
+                    {
+                        //TODO: if not disabled...
+                        tmp = blockModifier.ModifyLine(tmp);
+                    }
+
+                    for (var i = s_blockModifiers.Count - 1; i >= 0; i--)
+                    {
+                        var blockModifier = s_blockModifiers[i];
+                        tmp = blockModifier.Conclude(tmp);
+                    }
+                }
+
+                tmp = _velocityArguments.Replace(tmp, ArgMatchReplace);
+
+                // Format the current line.
+                CurrentState.FormatLine(tmp);
+            }
         }
+        // We're done. There might be a few states still on
+        // the stack (for example if the text ends with a nested
+        // list), so we must pop them all so that they have
+        // their "Exit" method called correctly.
+        while (_stackOfStates.Count > 0)
+            PopState();
 
-        #endregion
-
-        #region Preparation Methods
-
-        /// <summary>
-        /// Cleans up a text before formatting.
-        /// </summary>
-        /// <param name="input">The text to clean up.</param>
-        /// <returns>The clean text.</returns>
-        /// This method cleans stuff like line endings, so that
-        /// we don't have to bother with it while formatting.
-        private string PrepareInputForFormatting(string input)
-        {
-            input = CleanWhiteSpace(input);
-            return input;
-        }
-
-        private string CleanWhiteSpace(string text)
-        {
-            text = text.Replace("\r\n", "\n");
-            text = text.Replace("\t", "");
-            text = Regex.Replace(text, @"\n{3,}", "\n\n");
-            text = Regex.Replace(text, @"\n *\n", "\n\n");
-            text = Regex.Replace(text, "\"$", "\" ");
-            return text;
-        }
-
-        #endregion
+        Output.End();
     }
-}
+
+    #endregion
+
+    #region Preparation Methods
+
+    /// <summary>
+    /// Cleans up a text before formatting.
+    /// </summary>
+    /// <param name="input">The text to clean up.</param>
+    /// <returns>The clean text.</returns>
+    /// This method cleans stuff like line endings, so that
+    /// we don't have to bother with it while formatting.
+    private string PrepareInputForFormatting(string input)
+    {
+        input = CleanWhiteSpace(input);
+        return input;
+    }
+
+    private string CleanWhiteSpace(string text)
+    {
+        text = text.Replace("\r\n", "\n");
+        text = text.Replace("\t", "");
+        text = Regex.Replace(text, @"\n{3,}", "\n\n");
+        text = Regex.Replace(text, @"\n *\n", "\n\n");
+        text = Regex.Replace(text, "\"$", "\" ");
+        return text;
+    }
+
+    #endregion
+}
\ No newline at end of file
diff --git a/common/ASC.Textile/TextileFormatterStates.cs b/common/ASC.Textile/TextileFormatterStates.cs
index 166ffc7ce6..d60e1f428f 100644
--- a/common/ASC.Textile/TextileFormatterStates.cs
+++ b/common/ASC.Textile/TextileFormatterStates.cs
@@ -10,144 +10,142 @@
 // You must not remove this notice, or any other, from this software.
 #endregion
 
-namespace Textile
+namespace Textile;
+public partial class TextileFormatter
 {
-    public partial class TextileFormatter
+    #region State Registration
+
+    private static readonly List<Type> s_registeredStates = new List<Type>();
+    private static readonly List<FormatterStateAttribute> s_registeredStatesAttributes = new List<FormatterStateAttribute>();
+
+    public static void RegisterFormatterState(Type formatterStateType)
     {
-        #region State Registration
+        if (!formatterStateType.IsSubclassOf(typeof(FormatterState)))
+            throw new ArgumentException("The formatter state must be a sub-public class of FormatterStateBase.");
 
-        private static readonly List<Type> s_registeredStates = new List<Type>();
-        private static readonly List<FormatterStateAttribute> s_registeredStatesAttributes = new List<FormatterStateAttribute>();
+        if (formatterStateType.GetConstructor(new Type[] { typeof(TextileFormatter) }) == null)
+            throw new ArgumentException("The formatter state must have a constructor that takes a TextileFormatter reference.");
 
-        public static void RegisterFormatterState(Type formatterStateType)
-        {
-            if (!formatterStateType.IsSubclassOf(typeof(FormatterState)))
-                throw new ArgumentException("The formatter state must be a sub-public class of FormatterStateBase.");
+        var att = FormatterStateAttribute.Get(formatterStateType);
+        if (att == null)
+            throw new ArgumentException("The formatter state must have the FormatterStateAttribute.");
 
-            if (formatterStateType.GetConstructor(new Type[] { typeof(TextileFormatter) }) == null)
-                throw new ArgumentException("The formatter state must have a constructor that takes a TextileFormatter reference.");
-
-            var att = FormatterStateAttribute.Get(formatterStateType);
-            if (att == null)
-                throw new ArgumentException("The formatter state must have the FormatterStateAttribute.");
-
-            s_registeredStates.Add(formatterStateType);
-            s_registeredStatesAttributes.Add(att);
-        }
-
-        #endregion
-
-        #region State Management
-
-        private readonly List<Type> m_disabledFormatterStates = new List<Type>();
-        private readonly Stack<FormatterState> m_stackOfStates = new Stack<FormatterState>();
-
-        private bool IsFormatterStateEnabled(Type type)
-        {
-            return !m_disabledFormatterStates.Contains(type);
-        }
-
-        private void SwitchFormatterState(Type type, bool onOff)
-        {
-            if (onOff)
-                m_disabledFormatterStates.Remove(type);
-            else if (!m_disabledFormatterStates.Contains(type))
-                m_disabledFormatterStates.Add(type);
-        }
-
-        /// <summary>
-        /// Pushes a new state on the stack.
-        /// </summary>
-        /// <param name="s">The state to push.</param>
-        /// The state will be entered automatically.
-        private void PushState(FormatterState s)
-        {
-            m_stackOfStates.Push(s);
-            s.Enter();
-        }
-
-        /// <summary>
-        /// Removes the last state from the stack.
-        /// </summary>
-        /// The state will be exited automatically.
-        private void PopState()
-        {
-            m_stackOfStates.Peek().Exit();
-            m_stackOfStates.Pop();
-        }
-
-        /// <summary>
-        /// The current state, if any.
-        /// </summary>
-        internal FormatterState CurrentState
-        {
-            get
-            {
-                if (m_stackOfStates.Count > 0)
-                    return m_stackOfStates.Peek();
-                else
-                    return null;
-            }
-        }
-
-        internal void ChangeState(FormatterState formatterState)
-        {
-            if (CurrentState != null && CurrentState.GetType() == formatterState.GetType())
-            {
-                if (!CurrentState.ShouldNestState(formatterState))
-                    return;
-            }
-            PushState(formatterState);
-        }
-
-        #endregion
-
-        #region State Handling
-
-        /// <summary>
-        /// Parses the string and updates the state accordingly.
-        /// </summary>
-        /// <param name="input">The text to process.</param>
-        /// <returns>The text, ready for formatting.</returns>
-        /// This method modifies the text because it removes some
-        /// syntax stuff. Maybe the states themselves should handle
-        /// their own syntax and remove it?
-        private string HandleFormattingState(string input)
-        {
-            for (var i = 0; i < s_registeredStates.Count; i++)
-            {
-                var type = s_registeredStates[i];
-                if (IsFormatterStateEnabled(type))
-                {
-                    var att = s_registeredStatesAttributes[i];
-                    var m = Regex.Match(input, att.Pattern);
-                    if (m.Success)
-                    {
-                        var formatterState = (FormatterState)Activator.CreateInstance(type, this);
-                        return formatterState.Consume(input, m);
-                    }
-                }
-            }
-
-            // Default, when no block is specified, we ask the current state, or
-            // use the paragraph state.
-            if (CurrentState != null)
-            {
-                if (CurrentState.FallbackFormattingState != null)
-                {
-                    var formatterState = (FormatterState)Activator.CreateInstance(CurrentState.FallbackFormattingState, this);
-                    ChangeState(formatterState);
-                }
-                // else, the current state doesn't want to be superceded by
-                // a new one. We'll leave him be.
-            }
-            else
-            {
-                ChangeState(new States.ParagraphFormatterState(this));
-            }
-            return input;
-        }
-
-        #endregion
+        s_registeredStates.Add(formatterStateType);
+        s_registeredStatesAttributes.Add(att);
     }
+
+    #endregion
+
+    #region State Management
+
+    private readonly List<Type> _disabledFormatterStates = new List<Type>();
+    private readonly Stack<FormatterState> _stackOfStates = new Stack<FormatterState>();
+
+    private bool IsFormatterStateEnabled(Type type)
+    {
+        return !_disabledFormatterStates.Contains(type);
+    }
+
+    private void SwitchFormatterState(Type type, bool onOff)
+    {
+        if (onOff)
+            _disabledFormatterStates.Remove(type);
+        else if (!_disabledFormatterStates.Contains(type))
+            _disabledFormatterStates.Add(type);
+    }
+
+    /// <summary>
+    /// Pushes a new state on the stack.
+    /// </summary>
+    /// <param name="s">The state to push.</param>
+    /// The state will be entered automatically.
+    private void PushState(FormatterState s)
+    {
+        _stackOfStates.Push(s);
+        s.Enter();
+    }
+
+    /// <summary>
+    /// Removes the last state from the stack.
+    /// </summary>
+    /// The state will be exited automatically.
+    private void PopState()
+    {
+        _stackOfStates.Peek().Exit();
+        _stackOfStates.Pop();
+    }
+
+    /// <summary>
+    /// The current state, if any.
+    /// </summary>
+    internal FormatterState CurrentState
+    {
+        get
+        {
+            if (_stackOfStates.Count > 0)
+                return _stackOfStates.Peek();
+            else
+                return null;
+        }
+    }
+
+    internal void ChangeState(FormatterState formatterState)
+    {
+        if (CurrentState != null && CurrentState.GetType() == formatterState.GetType())
+        {
+            if (!CurrentState.ShouldNestState(formatterState))
+                return;
+        }
+        PushState(formatterState);
+    }
+
+    #endregion
+
+    #region State Handling
+
+    /// <summary>
+    /// Parses the string and updates the state accordingly.
+    /// </summary>
+    /// <param name="input">The text to process.</param>
+    /// <returns>The text, ready for formatting.</returns>
+    /// This method modifies the text because it removes some
+    /// syntax stuff. Maybe the states themselves should handle
+    /// their own syntax and remove it?
+    private string HandleFormattingState(string input)
+    {
+        for (var i = 0; i < s_registeredStates.Count; i++)
+        {
+            var type = s_registeredStates[i];
+            if (IsFormatterStateEnabled(type))
+            {
+                var att = s_registeredStatesAttributes[i];
+                var m = Regex.Match(input, att.Pattern);
+                if (m.Success)
+                {
+                    var formatterState = (FormatterState)Activator.CreateInstance(type, this);
+                    return formatterState.Consume(input, m);
+                }
+            }
+        }
+
+        // Default, when no block is specified, we ask the current state, or
+        // use the paragraph state.
+        if (CurrentState != null)
+        {
+            if (CurrentState.FallbackFormattingState != null)
+            {
+                var formatterState = (FormatterState)Activator.CreateInstance(CurrentState.FallbackFormattingState, this);
+                ChangeState(formatterState);
+            }
+            // else, the current state doesn't want to be superceded by
+            // a new one. We'll leave him be.
+        }
+        else
+        {
+            ChangeState(new States.ParagraphFormatterState(this));
+        }
+        return input;
+    }
+
+    #endregion
 }

From bc78804ac64017ce3caf62ce5c90642d3e90e0a9 Mon Sep 17 00:00:00 2001
From: SuhorukovAnton <anton.sukhorukov@onlyoffice.com>
Date: Fri, 25 Feb 2022 15:50:00 +0300
Subject: [PATCH 05/28] refactoring: voipService

---
 common/ASC.VoipService/ASC.VoipService.csproj |  1 +
 common/ASC.VoipService/Dao/CachedVoipDao.cs   | 99 -------------------
 common/ASC.VoipService/Dao/VoipDao.cs         |  2 +-
 common/ASC.VoipService/GlobalUsings.cs        |  3 -
 common/ASC.VoipService/Twilio/TwilioPhone.cs  |  2 +
 common/ASC.VoipService/VoipModel.cs           |  9 --
 6 files changed, 4 insertions(+), 112 deletions(-)
 delete mode 100644 common/ASC.VoipService/Dao/CachedVoipDao.cs

diff --git a/common/ASC.VoipService/ASC.VoipService.csproj b/common/ASC.VoipService/ASC.VoipService.csproj
index 6ae1aad4a2..db00ded797 100644
--- a/common/ASC.VoipService/ASC.VoipService.csproj
+++ b/common/ASC.VoipService/ASC.VoipService.csproj
@@ -5,6 +5,7 @@
     <ApplicationIcon />
     <OutputType>Library</OutputType>
     <StartupObject />
+    <ImplicitUsings>enable</ImplicitUsings>
   </PropertyGroup>
 
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
diff --git a/common/ASC.VoipService/Dao/CachedVoipDao.cs b/common/ASC.VoipService/Dao/CachedVoipDao.cs
deleted file mode 100644
index 90647a9e48..0000000000
--- a/common/ASC.VoipService/Dao/CachedVoipDao.cs
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- *
- * (c) Copyright Ascensio System Limited 2010-2018
- *
- * This program is freeware. You can redistribute it and/or modify it under the terms of the GNU 
- * General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html). 
- * In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that 
- * Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
- *
- * THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
- * FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
- *
- * You can contact Ascensio System SIA by email at sales@onlyoffice.com
- *
- * The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display 
- * Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
- *
- * Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains 
- * relevant author attributions when distributing the software. If the display of the logo in its graphic 
- * form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE" 
- * in every copy of the program you distribute. 
- * Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
- *
-*/
-
-namespace ASC.VoipService.Dao;
-
-[Singletone]
-public class VoipDaoCache
-{
-    internal readonly ICache _cache;
-    private readonly ICacheNotify<CachedVoipItem> _notify;
-
-    public VoipDaoCache(ICacheNotify<CachedVoipItem> notify, ICache cache)
-    {
-        _cache = cache;
-        _notify = notify;
-        _notify.Subscribe((c) => _cache.Remove(CachedVoipDao.GetCacheKey(c.Tenant)), Common.Caching.CacheNotifyAction.Any);
-    }
-
-    public void ResetCache(int tenant)
-    {
-        _notify.Publish(new CachedVoipItem { Tenant = tenant }, Common.Caching.CacheNotifyAction.Any);
-    }
-}
-
-[Scope]
-public class CachedVoipDao : VoipDao
-{
-    private static readonly TimeSpan timeout = TimeSpan.FromDays(1);
-
-    private readonly ICache _cache;
-    private readonly VoipDaoCache _voipDaoCache;
-
-    public CachedVoipDao(
-        TenantManager tenantManager,
-        DbContextManager<VoipDbContext> dbOptions,
-        AuthContext authContext,
-        TenantUtil tenantUtil,
-        SecurityContext securityContext,
-        BaseCommonLinkUtility baseCommonLinkUtility,
-        ConsumerFactory consumerFactory,
-        VoipDaoCache voipDaoCache)
-        : base(tenantManager, dbOptions, authContext, tenantUtil, securityContext, baseCommonLinkUtility, consumerFactory)
-    {
-        _cache = voipDaoCache._cache;
-        _voipDaoCache = voipDaoCache;
-    }
-
-    public override VoipPhone SaveOrUpdateNumber(VoipPhone phone)
-    {
-        var result = base.SaveOrUpdateNumber(phone);
-        _voipDaoCache.ResetCache(TenantID);
-        return result;
-    }
-
-    public override void DeleteNumber(string phoneId = "")
-    {
-        base.DeleteNumber(phoneId);
-        _voipDaoCache.ResetCache(TenantID);
-    }
-
-    public override IEnumerable<VoipPhone> GetNumbers(params string[] ids)
-    {
-        var numbers = _cache.Get<List<VoipPhone>>(GetCacheKey(TenantID));
-        if (numbers == null)
-        {
-            numbers = new List<VoipPhone>(base.GetAllNumbers());
-            _cache.Insert(GetCacheKey(TenantID), numbers, DateTime.UtcNow.Add(timeout));
-        }
-
-        return ids.Length > 0 ? numbers.Where(r => ids.Contains(r.Id) || ids.Contains(r.Number)).ToList() : numbers;
-    }
-
-    public static string GetCacheKey(int tenant)
-    {
-        return "voip" + tenant.ToString(CultureInfo.InvariantCulture);
-    }
-}
\ No newline at end of file
diff --git a/common/ASC.VoipService/Dao/VoipDao.cs b/common/ASC.VoipService/Dao/VoipDao.cs
index fa4638e9f3..fecb757713 100644
--- a/common/ASC.VoipService/Dao/VoipDao.cs
+++ b/common/ASC.VoipService/Dao/VoipDao.cs
@@ -25,7 +25,7 @@
 
 namespace ASC.VoipService.Dao;
 
-[Scope(typeof(CachedVoipDao))]
+[Scope]
 public class VoipDao : AbstractDao
 {
     private readonly AuthContext _authContext;
diff --git a/common/ASC.VoipService/GlobalUsings.cs b/common/ASC.VoipService/GlobalUsings.cs
index 7af4a611f6..208296c4ea 100644
--- a/common/ASC.VoipService/GlobalUsings.cs
+++ b/common/ASC.VoipService/GlobalUsings.cs
@@ -1,6 +1,5 @@
 global using System;
 global using System.Collections.Generic;
-global using System.Globalization;
 global using System.Linq;
 global using System.Reflection;
 global using System.Text;
@@ -8,7 +7,6 @@ global using System.Threading;
 global using System.Web;
 
 global using ASC.Common;
-global using ASC.Common.Caching;
 global using ASC.Core;
 global using ASC.Core.Common;
 global using ASC.Core.Common.Configuration;
@@ -24,7 +22,6 @@ global using Newtonsoft.Json.Serialization;
 
 global using Twilio.Clients;
 global using Twilio.Exceptions;
-global using Twilio.Http;
 global using Twilio.Jwt;
 global using Twilio.Jwt.Client;
 global using Twilio.Rest.Api.V2010.Account;
diff --git a/common/ASC.VoipService/Twilio/TwilioPhone.cs b/common/ASC.VoipService/Twilio/TwilioPhone.cs
index 055dc62fd5..554c8fd231 100644
--- a/common/ASC.VoipService/Twilio/TwilioPhone.cs
+++ b/common/ASC.VoipService/Twilio/TwilioPhone.cs
@@ -23,6 +23,8 @@
  *
 */
 
+using HttpMethod = Twilio.Http.HttpMethod;
+
 namespace ASC.VoipService.Twilio
 {
     public class TwilioPhone : VoipPhone
diff --git a/common/ASC.VoipService/VoipModel.cs b/common/ASC.VoipService/VoipModel.cs
index 5d27c214bb..5b306e615d 100644
--- a/common/ASC.VoipService/VoipModel.cs
+++ b/common/ASC.VoipService/VoipModel.cs
@@ -28,23 +28,14 @@ namespace ASC.VoipService;
 public class Agent
 {
     public Guid Id { get; set; }
-
     public AnswerType Answer { get; set; }
-
     public string ClientID { get { return PhoneNumber + PostFix; } }
-
     public bool Record { get; set; }
-
     public int TimeOut { get; set; }
-
     public AgentStatus Status { get; set; }
-
     public bool AllowOutgoingCalls { get; set; }
-
     public string PostFix { get; set; }
-
     public string PhoneNumber { get; set; }
-
     public string RedirectToNumber { get; set; }
 
     public Agent()

From d7d7d18ec88efb981193b957a8d247eba497f5ea Mon Sep 17 00:00:00 2001
From: SuhorukovAnton <anton.sukhorukov@onlyoffice.com>
Date: Mon, 28 Feb 2022 15:43:20 +0300
Subject: [PATCH 06/28] voipService: add autoMapper and fix method
 "GetCallsQuery"

---
 .../EF/Model/CRM/DbVoipCall.cs                |  2 -
 common/ASC.VoipService/Dao/VoipDao.cs         | 55 ++++++++++---------
 common/ASC.VoipService/GlobalUsings.cs        |  5 ++
 .../ASC.VoipService/Mappings/CallConverter.cs | 42 ++++++++++++++
 4 files changed, 76 insertions(+), 28 deletions(-)
 create mode 100644 common/ASC.VoipService/Mappings/CallConverter.cs

diff --git a/common/ASC.Core.Common/EF/Model/CRM/DbVoipCall.cs b/common/ASC.Core.Common/EF/Model/CRM/DbVoipCall.cs
index d64e081165..c372b356af 100644
--- a/common/ASC.Core.Common/EF/Model/CRM/DbVoipCall.cs
+++ b/common/ASC.Core.Common/EF/Model/CRM/DbVoipCall.cs
@@ -17,8 +17,6 @@
         public int ContactId { get; set; }
         public decimal Price { get; set; }
         public int TenantId { get; set; }
-
-        public CrmContact CrmContact { get; set; }
     }
     public static class DbVoipCallExtension
     {
diff --git a/common/ASC.VoipService/Dao/VoipDao.cs b/common/ASC.VoipService/Dao/VoipDao.cs
index fecb757713..8a5afb629c 100644
--- a/common/ASC.VoipService/Dao/VoipDao.cs
+++ b/common/ASC.VoipService/Dao/VoipDao.cs
@@ -25,7 +25,7 @@
 
 namespace ASC.VoipService.Dao;
 
-[Scope]
+[Scope(Additional = typeof(EventTypeConverterExtension))]
 public class VoipDao : AbstractDao
 {
     private readonly AuthContext _authContext;
@@ -33,6 +33,7 @@ public class VoipDao : AbstractDao
     private readonly SecurityContext _securityContext;
     private readonly BaseCommonLinkUtility _baseCommonLinkUtility;
     private readonly ConsumerFactory _consumerFactory;
+    private readonly IMapper _mapper;
 
     public VoipDao(
         TenantManager tenantManager,
@@ -41,7 +42,8 @@ public class VoipDao : AbstractDao
         TenantUtil tenantUtil,
         SecurityContext securityContext,
         BaseCommonLinkUtility baseCommonLinkUtility,
-        ConsumerFactory consumerFactory)
+        ConsumerFactory consumerFactory,
+        IMapper mapper)
         : base(dbOptions, tenantManager)
     {
         _authContext = authContext;
@@ -49,6 +51,7 @@ public class VoipDao : AbstractDao
         _securityContext = securityContext;
         _baseCommonLinkUtility = baseCommonLinkUtility;
         _consumerFactory = consumerFactory;
+        _mapper = mapper;
     }
 
     public virtual VoipPhone SaveOrUpdateNumber(VoipPhone phone)
@@ -195,7 +198,7 @@ public class VoipDao : AbstractDao
         query = query.Skip((int)filter.Offset);
         query = query.Take((int)filter.Max * 3);
 
-        var calls = query.ToList().ConvertAll(ToCall);
+        var calls = _mapper.Map<List<CallContact>, IEnumerable<VoipCall>>(query.ToList());
 
         calls = calls.GroupJoin(calls, call => call.Id, h => h.ParentID, (call, h) =>
         {
@@ -230,7 +233,7 @@ public class VoipDao : AbstractDao
             query = query.Take((int)count);
         }
 
-        var a = query.Select(ca => new
+        query = query.Select(ca => new
         {
             dbVoipCall = ca,
             tmpDate = VoipDbContext.VoipCalls
@@ -238,9 +241,10 @@ public class VoipDao : AbstractDao
             .Where(tmp => tmp.NumberFrom == ca.DbVoipCall.NumberFrom || tmp.NumberTo == ca.DbVoipCall.NumberFrom)
             .Where(tmp => tmp.Status <= (int)VoipCallStatus.Missed)
             .Max(tmp => tmp.DialDate)
-        }).Where(r => r.dbVoipCall.DbVoipCall.DialDate >= r.tmpDate || r.tmpDate == default);
+        }).Where(r => r.dbVoipCall.DbVoipCall.DialDate >= r.tmpDate || r.tmpDate == default)
+        .Select(q=> q.dbVoipCall);
 
-        return a.ToList().ConvertAll(r => ToCall(r.dbVoipCall));
+        return _mapper.Map<List<CallContact>, IEnumerable<VoipCall>>(query.ToList());
     }
 
     private IQueryable<CallContact> GetCallsQuery(VoipCallFilter filter)
@@ -282,24 +286,13 @@ public class VoipDao : AbstractDao
         {
             q = q.Where(r => r.AnsweredBy == filter.Agent.Value);
         }
-
-        return q
-            .GroupBy(r => r.Id, r => r)
-            .Join(
-                VoipDbContext.CrmContact.DefaultIfEmpty(),
-                r => r.FirstOrDefault().ContactId,
-                c => c.Id,
-                (call, contact) => new CallContact { DbVoipCall = call.FirstOrDefault(), CrmContact = contact })
-            ;
+        
+        return from voipCalls in q
+               join crmContact in VoipDbContext.CrmContact on voipCalls.ContactId equals crmContact.Id into grouping
+               from g in grouping.DefaultIfEmpty()
+               select new CallContact { DbVoipCall = voipCalls, CrmContact = g };
     }
 
-    class CallContact
-    {
-        public DbVoipCall DbVoipCall { get; set; }
-        public CrmContact CrmContact { get; set; }
-    }
-
-
     private VoipPhone ToPhone(VoipNumber r)
     {
         return GetProvider().GetPhone(r);
@@ -324,17 +317,21 @@ public class VoipDao : AbstractDao
                 Uri = dbVoipCall.DbVoipCall.RecordUrl,
                 Duration = dbVoipCall.DbVoipCall.RecordDuration,
                 Price = dbVoipCall.DbVoipCall.RecordPrice
-            },
-            ContactId = dbVoipCall.CrmContact.Id,
-            ContactIsCompany = dbVoipCall.CrmContact.IsCompany,
+            }
         };
 
-        if (call.ContactId != 0)
+        if (dbVoipCall.CrmContact != null)
         {
+            call.ContactId = dbVoipCall.CrmContact.Id;
+            call.ContactIsCompany = dbVoipCall.CrmContact.IsCompany;
             call.ContactTitle = call.ContactIsCompany
                                     ? dbVoipCall.CrmContact.CompanyName
                                     : dbVoipCall.CrmContact.FirstName == null || dbVoipCall.CrmContact.LastName == null ? null : $"{dbVoipCall.CrmContact.FirstName} {dbVoipCall.CrmContact.LastName}";
         }
+        else
+        {
+            call.ContactId = 0;
+        }
 
         return call;
     }
@@ -357,4 +354,10 @@ public class VoipDao : AbstractDao
                     !string.IsNullOrEmpty(Consumer["twilioAuthToken"]);
         }
     }
+}
+
+public class CallContact
+{
+    public DbVoipCall DbVoipCall { get; set; }
+    public CrmContact CrmContact { get; set; }
 }
\ No newline at end of file
diff --git a/common/ASC.VoipService/GlobalUsings.cs b/common/ASC.VoipService/GlobalUsings.cs
index 208296c4ea..121f767fbe 100644
--- a/common/ASC.VoipService/GlobalUsings.cs
+++ b/common/ASC.VoipService/GlobalUsings.cs
@@ -7,6 +7,7 @@ global using System.Threading;
 global using System.Web;
 
 global using ASC.Common;
+global using ASC.Common.Mapping;
 global using ASC.Core;
 global using ASC.Core.Common;
 global using ASC.Core.Common.Configuration;
@@ -14,8 +15,12 @@ global using ASC.Core.Common.EF;
 global using ASC.Core.Common.EF.Context;
 global using ASC.Core.Common.EF.Model;
 global using ASC.Core.Tenants;
+global using ASC.VoipService.Dao;
+global using ASC.VoipService.Mappings;
 global using ASC.VoipService.Twilio;
 
+global using AutoMapper;
+
 global using Newtonsoft.Json;
 global using Newtonsoft.Json.Linq;
 global using Newtonsoft.Json.Serialization;
diff --git a/common/ASC.VoipService/Mappings/CallConverter.cs b/common/ASC.VoipService/Mappings/CallConverter.cs
new file mode 100644
index 0000000000..a5fde09da1
--- /dev/null
+++ b/common/ASC.VoipService/Mappings/CallConverter.cs
@@ -0,0 +1,42 @@
+namespace ASC.VoipService.Mappings;
+
+[Scope]
+public class CallConverter : ITypeConverter<CallContact, VoipCall>
+{
+    public VoipCall Convert(CallContact source, VoipCall destination, ResolutionContext context)
+    {
+        var result = context.Mapper.Map<VoipCall>(source.DbVoipCall);
+        result.ParentID = source.DbVoipCall.ParentCallId;
+        result.To = source.DbVoipCall.NumberTo;
+        result.VoipRecord = new VoipRecord
+        {
+            Id = source.DbVoipCall.RecordSid,
+            Uri = source.DbVoipCall.RecordUrl,
+            Duration = source.DbVoipCall.RecordDuration,
+            Price = source.DbVoipCall.RecordPrice
+        };
+
+        if (source.CrmContact != null)
+        {
+            result.ContactId = source.CrmContact.Id;
+            result.ContactIsCompany = source.CrmContact.IsCompany;
+            result.ContactTitle = result.ContactIsCompany
+                                    ? source.CrmContact.CompanyName
+                                    : source.CrmContact.FirstName == null || source.CrmContact.LastName == null ? null : $"{source.CrmContact.FirstName} {source.CrmContact.LastName}";
+        }
+        else
+        {
+            result.ContactId = 0;
+        }
+
+        return result;
+    }
+}
+
+public class EventTypeConverterExtension
+{
+    public static void Register(DIHelper services)
+    {
+        services.TryAdd<CallConverter>();
+    }
+}
\ No newline at end of file

From 34a9067aec086190d28022f95838550a5ed22a20 Mon Sep 17 00:00:00 2001
From: SuhorukovAnton <anton.sukhorukov@onlyoffice.com>
Date: Mon, 28 Feb 2022 15:45:01 +0300
Subject: [PATCH 07/28] refactoring: remove whitespace

---
 common/ASC.VoipService/Dao/VoIPCallFilter.cs | 12 ----------
 common/ASC.VoipService/VoipCall.cs           | 25 +++++++-------------
 common/ASC.VoipService/VoipPhone.cs          |  3 ---
 common/ASC.VoipService/VoipSettings.cs       | 12 ----------
 4 files changed, 9 insertions(+), 43 deletions(-)

diff --git a/common/ASC.VoipService/Dao/VoIPCallFilter.cs b/common/ASC.VoipService/Dao/VoIPCallFilter.cs
index 2267d8aa41..35408516dd 100644
--- a/common/ASC.VoipService/Dao/VoIPCallFilter.cs
+++ b/common/ASC.VoipService/Dao/VoIPCallFilter.cs
@@ -28,29 +28,17 @@ namespace ASC.VoipService.Dao;
 public class VoipCallFilter
 {
     public string Type { get; set; }
-
     public DateTime? FromDate { get; set; }
-
     public DateTime? ToDate { get; set; }
-
     public Guid? Agent { get; set; }
-
     public int? Client { get; set; }
-
     public int? ContactID { get; set; }
-
     public string Id { get; set; }
-
     public string ParentId { get; set; }
-
     public string SortBy { get; set; }
-
     public bool SortOrder { get; set; }
-
     public string SearchText { get; set; }
-
     public long Offset { get; set; }
-
     public long Max { get; set; }
 
     public int? TypeStatus
diff --git a/common/ASC.VoipService/VoipCall.cs b/common/ASC.VoipService/VoipCall.cs
index 59d1f84bfc..bf72d2b5ce 100644
--- a/common/ASC.VoipService/VoipCall.cs
+++ b/common/ASC.VoipService/VoipCall.cs
@@ -25,38 +25,23 @@
 
 namespace ASC.VoipService;
 
-public class VoipCall
+public class VoipCall : IMapFrom<CallContact>
 {
     public string Id { get; set; }
-
     public string ParentID { get; set; }
-
     public string From { get; set; }
-
     public string To { get; set; }
-
     public Guid AnsweredBy { get; set; }
-
     public DateTime DialDate { get; set; }
-
     public int DialDuration { get; set; }
-
     public VoipCallStatus? Status { get; set; }
-
     public decimal Price { get; set; }
-
     public int ContactId { get; set; }
-
     public bool ContactIsCompany { get; set; }
-
     public string ContactTitle { get; set; }
-
     public DateTime Date { get; set; }
-
     public DateTime EndDialDate { get; set; }
-
     public VoipRecord VoipRecord { get; set; }
-
     public List<VoipCall> ChildCalls { get; set; }
 
     public VoipCall()
@@ -64,6 +49,14 @@ public class VoipCall
         ChildCalls = new List<VoipCall>();
         VoipRecord = new VoipRecord();
     }
+
+    public void Mapping(Profile profile)
+    {
+        profile.CreateMap<DbVoipCall, VoipCall>();
+
+        profile.CreateMap<CallContact, VoipCall>()
+            .ConvertUsing<CallConverter>();
+    }
 }
 
 public enum VoipCallStatus
diff --git a/common/ASC.VoipService/VoipPhone.cs b/common/ASC.VoipService/VoipPhone.cs
index 3b725d01bf..dbcc586160 100644
--- a/common/ASC.VoipService/VoipPhone.cs
+++ b/common/ASC.VoipService/VoipPhone.cs
@@ -75,10 +75,7 @@ public class VoipPhone
 public class VoipRecord
 {
     public string Id { get; set; }
-
     public string Uri { get; set; }
-
     public int Duration { get; set; }
-
     public decimal Price { get; set; }
 }
\ No newline at end of file
diff --git a/common/ASC.VoipService/VoipSettings.cs b/common/ASC.VoipService/VoipSettings.cs
index 36ebf034b2..ef8374889b 100644
--- a/common/ASC.VoipService/VoipSettings.cs
+++ b/common/ASC.VoipService/VoipSettings.cs
@@ -28,29 +28,17 @@ namespace ASC.VoipService;
 public class VoipSettings
 {
     public string VoiceUrl { get; set; }
-
     public string Name { get; set; }
-
     public List<Agent> Operators { get; set; }
-
     public Queue Queue { get; set; }
-
     public Agent Caller { get { return Operators.FirstOrDefault(r => r.Id == AuthContext.CurrentAccount.ID); } }
-
     public WorkingHours WorkingHours { get; set; }
-
     public string VoiceMail { get; set; }
-
     public string GreetingAudio { get; set; }
-
     public string HoldAudio { get; set; }
-
     public bool AllowOutgoingCalls { get; set; }
-
     public bool Pause { get; set; }
-
     public bool Record { get; set; }
-
     internal string JsonSettings
     {
         get

From d0b7bd63b689493a8fbab9cdc41670e8d59e5089 Mon Sep 17 00:00:00 2001
From: SuhorukovAnton <anton.sukhorukov@onlyoffice.com>
Date: Mon, 28 Feb 2022 18:12:10 +0300
Subject: [PATCH 08/28] textile: delete prefix "s" and ImplicitUsings

---
 common/ASC.Textile/ASC.Textile.csproj            |  1 +
 common/ASC.Textile/GlobalUsings.cs               |  4 +---
 common/ASC.Textile/StyleReader.cs                |  1 -
 common/ASC.Textile/TextileFormatterBlocks.cs     |  8 ++++----
 common/ASC.Textile/TextileFormatterFormatting.cs |  6 +++---
 common/ASC.Textile/TextileFormatterStates.cs     | 14 +++++++-------
 6 files changed, 16 insertions(+), 18 deletions(-)

diff --git a/common/ASC.Textile/ASC.Textile.csproj b/common/ASC.Textile/ASC.Textile.csproj
index eb75aeae25..4e41d5767f 100644
--- a/common/ASC.Textile/ASC.Textile.csproj
+++ b/common/ASC.Textile/ASC.Textile.csproj
@@ -12,6 +12,7 @@
     <Copyright>(c) Ascensio System SIA. All rights reserved</Copyright>
     <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
     <ProduceReferenceAssembly>false</ProduceReferenceAssembly>
+    <ImplicitUsings>enable</ImplicitUsings>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugType>full</DebugType>
diff --git a/common/ASC.Textile/GlobalUsings.cs b/common/ASC.Textile/GlobalUsings.cs
index 1b57fda786..865389f2f3 100644
--- a/common/ASC.Textile/GlobalUsings.cs
+++ b/common/ASC.Textile/GlobalUsings.cs
@@ -1,6 +1,4 @@
-global using System;
-global using System.Collections.Generic;
-global using System.Text;
+global using System.Text;
 global using System.Text.RegularExpressions;
 
 global using Textile.Blocks;
diff --git a/common/ASC.Textile/StyleReader.cs b/common/ASC.Textile/StyleReader.cs
index 28be943a6f..8acfce4f2b 100644
--- a/common/ASC.Textile/StyleReader.cs
+++ b/common/ASC.Textile/StyleReader.cs
@@ -4,7 +4,6 @@ public class StyleReader
 {
     private readonly Regex _styleParser = new Regex(@"(?<selector>[^\{]+)(?<style>[^\}]+)");
     private readonly Regex _minimizer = new Regex(@";\s+");
-
     private readonly System.Collections.Specialized.StringDictionary _tagStyler = new System.Collections.Specialized.StringDictionary();
 
     public StyleReader(string styles)
diff --git a/common/ASC.Textile/TextileFormatterBlocks.cs b/common/ASC.Textile/TextileFormatterBlocks.cs
index f2e095d1b8..1ab4d48f8f 100644
--- a/common/ASC.Textile/TextileFormatterBlocks.cs
+++ b/common/ASC.Textile/TextileFormatterBlocks.cs
@@ -17,13 +17,13 @@ public partial class TextileFormatter
 {
     #region Block Modifiers Registration
 
-    private static readonly List<BlockModifier> s_blockModifiers = new List<BlockModifier>();
-    private static readonly List<Type> s_blockModifiersTypes = new List<Type>();
+    private static readonly List<BlockModifier> _blockModifiers = new List<BlockModifier>();
+    private static readonly List<Type> _blockModifiersTypes = new List<Type>();
 
     public static void RegisterBlockModifier(BlockModifier blockModifer)
     {
-        s_blockModifiers.Add(blockModifer);
-        s_blockModifiersTypes.Add(blockModifer.GetType());
+        _blockModifiers.Add(blockModifer);
+        _blockModifiersTypes.Add(blockModifer.GetType());
     }
 
     #endregion
diff --git a/common/ASC.Textile/TextileFormatterFormatting.cs b/common/ASC.Textile/TextileFormatterFormatting.cs
index 0dbbe338f1..cabe05b270 100644
--- a/common/ASC.Textile/TextileFormatterFormatting.cs
+++ b/common/ASC.Textile/TextileFormatterFormatting.cs
@@ -57,15 +57,15 @@ public partial class TextileFormatter
                 // Modify the line with our block modifiers.
                 if (CurrentState == null || CurrentState.ShouldFormatBlocks(tmp))
                 {
-                    foreach (var blockModifier in s_blockModifiers)
+                    foreach (var blockModifier in _blockModifiers)
                     {
                         //TODO: if not disabled...
                         tmp = blockModifier.ModifyLine(tmp);
                     }
 
-                    for (var i = s_blockModifiers.Count - 1; i >= 0; i--)
+                    for (var i = _blockModifiers.Count - 1; i >= 0; i--)
                     {
-                        var blockModifier = s_blockModifiers[i];
+                        var blockModifier = _blockModifiers[i];
                         tmp = blockModifier.Conclude(tmp);
                     }
                 }
diff --git a/common/ASC.Textile/TextileFormatterStates.cs b/common/ASC.Textile/TextileFormatterStates.cs
index d60e1f428f..dc197e8377 100644
--- a/common/ASC.Textile/TextileFormatterStates.cs
+++ b/common/ASC.Textile/TextileFormatterStates.cs
@@ -15,8 +15,8 @@ public partial class TextileFormatter
 {
     #region State Registration
 
-    private static readonly List<Type> s_registeredStates = new List<Type>();
-    private static readonly List<FormatterStateAttribute> s_registeredStatesAttributes = new List<FormatterStateAttribute>();
+    private static readonly List<Type> _registeredStates = new List<Type>();
+    private static readonly List<FormatterStateAttribute> _registeredStatesAttributes = new List<FormatterStateAttribute>();
 
     public static void RegisterFormatterState(Type formatterStateType)
     {
@@ -30,8 +30,8 @@ public partial class TextileFormatter
         if (att == null)
             throw new ArgumentException("The formatter state must have the FormatterStateAttribute.");
 
-        s_registeredStates.Add(formatterStateType);
-        s_registeredStatesAttributes.Add(att);
+        _registeredStates.Add(formatterStateType);
+        _registeredStatesAttributes.Add(att);
     }
 
     #endregion
@@ -113,12 +113,12 @@ public partial class TextileFormatter
     /// their own syntax and remove it?
     private string HandleFormattingState(string input)
     {
-        for (var i = 0; i < s_registeredStates.Count; i++)
+        for (var i = 0; i < _registeredStates.Count; i++)
         {
-            var type = s_registeredStates[i];
+            var type = _registeredStates[i];
             if (IsFormatterStateEnabled(type))
             {
-                var att = s_registeredStatesAttributes[i];
+                var att = _registeredStatesAttributes[i];
                 var m = Regex.Match(input, att.Pattern);
                 if (m.Success)
                 {

From 1097d5e246be3ee6980ec86953d154d549a1f80a Mon Sep 17 00:00:00 2001
From: MaksimChegulov <maksim.chegulov@onlyoffice.com>
Date: Mon, 28 Feb 2022 20:56:05 +0300
Subject: [PATCH 09/28] People: Controllers to ApiControllers, Models to
 ApiModels

---
 .../Server/{Controllers => ApiControllers}/GroupController.cs     | 0
 .../Server/{Controllers => ApiControllers}/PeopleController.cs    | 0
 products/ASC.People/Server/{Models => ApiModels}/AccountInfo.cs   | 0
 products/ASC.People/Server/{Models => ApiModels}/GroupModel.cs    | 0
 .../ASC.People/Server/{Models => ApiModels}/GroupWrapperFull.cs   | 0
 .../ASC.People/Server/{Models => ApiModels}/LinkAccountModel.cs   | 0
 products/ASC.People/Server/{Models => ApiModels}/MemberModel.cs   | 0
 .../Server/{Models => ApiModels}/RegisterPersonalUserModel.cs     | 0
 .../ASC.People/Server/{Models => ApiModels}/SetManagerModel.cs    | 0
 .../ASC.People/Server/{Models => ApiModels}/StartReassignModel.cs | 0
 .../ASC.People/Server/{Models => ApiModels}/TerminateModel.cs     | 0
 .../Server/{Models => ApiModels}/ThumbnailsDataWrapper.cs         | 0
 .../ASC.People/Server/{Models => ApiModels}/ThumbnailsModel.cs    | 0
 .../Server/{Models => ApiModels}/TransferGroupMembersModel.cs     | 0
 .../ASC.People/Server/{Models => ApiModels}/UpdateMembersModel.cs | 0
 .../ASC.People/Server/{Models => ApiModels}/UploadPhotoModel.cs   | 0
 16 files changed, 0 insertions(+), 0 deletions(-)
 rename products/ASC.People/Server/{Controllers => ApiControllers}/GroupController.cs (100%)
 rename products/ASC.People/Server/{Controllers => ApiControllers}/PeopleController.cs (100%)
 rename products/ASC.People/Server/{Models => ApiModels}/AccountInfo.cs (100%)
 rename products/ASC.People/Server/{Models => ApiModels}/GroupModel.cs (100%)
 rename products/ASC.People/Server/{Models => ApiModels}/GroupWrapperFull.cs (100%)
 rename products/ASC.People/Server/{Models => ApiModels}/LinkAccountModel.cs (100%)
 rename products/ASC.People/Server/{Models => ApiModels}/MemberModel.cs (100%)
 rename products/ASC.People/Server/{Models => ApiModels}/RegisterPersonalUserModel.cs (100%)
 rename products/ASC.People/Server/{Models => ApiModels}/SetManagerModel.cs (100%)
 rename products/ASC.People/Server/{Models => ApiModels}/StartReassignModel.cs (100%)
 rename products/ASC.People/Server/{Models => ApiModels}/TerminateModel.cs (100%)
 rename products/ASC.People/Server/{Models => ApiModels}/ThumbnailsDataWrapper.cs (100%)
 rename products/ASC.People/Server/{Models => ApiModels}/ThumbnailsModel.cs (100%)
 rename products/ASC.People/Server/{Models => ApiModels}/TransferGroupMembersModel.cs (100%)
 rename products/ASC.People/Server/{Models => ApiModels}/UpdateMembersModel.cs (100%)
 rename products/ASC.People/Server/{Models => ApiModels}/UploadPhotoModel.cs (100%)

diff --git a/products/ASC.People/Server/Controllers/GroupController.cs b/products/ASC.People/Server/ApiControllers/GroupController.cs
similarity index 100%
rename from products/ASC.People/Server/Controllers/GroupController.cs
rename to products/ASC.People/Server/ApiControllers/GroupController.cs
diff --git a/products/ASC.People/Server/Controllers/PeopleController.cs b/products/ASC.People/Server/ApiControllers/PeopleController.cs
similarity index 100%
rename from products/ASC.People/Server/Controllers/PeopleController.cs
rename to products/ASC.People/Server/ApiControllers/PeopleController.cs
diff --git a/products/ASC.People/Server/Models/AccountInfo.cs b/products/ASC.People/Server/ApiModels/AccountInfo.cs
similarity index 100%
rename from products/ASC.People/Server/Models/AccountInfo.cs
rename to products/ASC.People/Server/ApiModels/AccountInfo.cs
diff --git a/products/ASC.People/Server/Models/GroupModel.cs b/products/ASC.People/Server/ApiModels/GroupModel.cs
similarity index 100%
rename from products/ASC.People/Server/Models/GroupModel.cs
rename to products/ASC.People/Server/ApiModels/GroupModel.cs
diff --git a/products/ASC.People/Server/Models/GroupWrapperFull.cs b/products/ASC.People/Server/ApiModels/GroupWrapperFull.cs
similarity index 100%
rename from products/ASC.People/Server/Models/GroupWrapperFull.cs
rename to products/ASC.People/Server/ApiModels/GroupWrapperFull.cs
diff --git a/products/ASC.People/Server/Models/LinkAccountModel.cs b/products/ASC.People/Server/ApiModels/LinkAccountModel.cs
similarity index 100%
rename from products/ASC.People/Server/Models/LinkAccountModel.cs
rename to products/ASC.People/Server/ApiModels/LinkAccountModel.cs
diff --git a/products/ASC.People/Server/Models/MemberModel.cs b/products/ASC.People/Server/ApiModels/MemberModel.cs
similarity index 100%
rename from products/ASC.People/Server/Models/MemberModel.cs
rename to products/ASC.People/Server/ApiModels/MemberModel.cs
diff --git a/products/ASC.People/Server/Models/RegisterPersonalUserModel.cs b/products/ASC.People/Server/ApiModels/RegisterPersonalUserModel.cs
similarity index 100%
rename from products/ASC.People/Server/Models/RegisterPersonalUserModel.cs
rename to products/ASC.People/Server/ApiModels/RegisterPersonalUserModel.cs
diff --git a/products/ASC.People/Server/Models/SetManagerModel.cs b/products/ASC.People/Server/ApiModels/SetManagerModel.cs
similarity index 100%
rename from products/ASC.People/Server/Models/SetManagerModel.cs
rename to products/ASC.People/Server/ApiModels/SetManagerModel.cs
diff --git a/products/ASC.People/Server/Models/StartReassignModel.cs b/products/ASC.People/Server/ApiModels/StartReassignModel.cs
similarity index 100%
rename from products/ASC.People/Server/Models/StartReassignModel.cs
rename to products/ASC.People/Server/ApiModels/StartReassignModel.cs
diff --git a/products/ASC.People/Server/Models/TerminateModel.cs b/products/ASC.People/Server/ApiModels/TerminateModel.cs
similarity index 100%
rename from products/ASC.People/Server/Models/TerminateModel.cs
rename to products/ASC.People/Server/ApiModels/TerminateModel.cs
diff --git a/products/ASC.People/Server/Models/ThumbnailsDataWrapper.cs b/products/ASC.People/Server/ApiModels/ThumbnailsDataWrapper.cs
similarity index 100%
rename from products/ASC.People/Server/Models/ThumbnailsDataWrapper.cs
rename to products/ASC.People/Server/ApiModels/ThumbnailsDataWrapper.cs
diff --git a/products/ASC.People/Server/Models/ThumbnailsModel.cs b/products/ASC.People/Server/ApiModels/ThumbnailsModel.cs
similarity index 100%
rename from products/ASC.People/Server/Models/ThumbnailsModel.cs
rename to products/ASC.People/Server/ApiModels/ThumbnailsModel.cs
diff --git a/products/ASC.People/Server/Models/TransferGroupMembersModel.cs b/products/ASC.People/Server/ApiModels/TransferGroupMembersModel.cs
similarity index 100%
rename from products/ASC.People/Server/Models/TransferGroupMembersModel.cs
rename to products/ASC.People/Server/ApiModels/TransferGroupMembersModel.cs
diff --git a/products/ASC.People/Server/Models/UpdateMembersModel.cs b/products/ASC.People/Server/ApiModels/UpdateMembersModel.cs
similarity index 100%
rename from products/ASC.People/Server/Models/UpdateMembersModel.cs
rename to products/ASC.People/Server/ApiModels/UpdateMembersModel.cs
diff --git a/products/ASC.People/Server/Models/UploadPhotoModel.cs b/products/ASC.People/Server/ApiModels/UploadPhotoModel.cs
similarity index 100%
rename from products/ASC.People/Server/Models/UploadPhotoModel.cs
rename to products/ASC.People/Server/ApiModels/UploadPhotoModel.cs

From f8d3d46e2877c18e911428fc0cf150b802842ff6 Mon Sep 17 00:00:00 2001
From: MaksimChegulov <maksim.chegulov@onlyoffice.com>
Date: Mon, 28 Feb 2022 20:58:24 +0300
Subject: [PATCH 10/28] People: rename

---
 .../ASC.People/Server/{ApiControllers => Api}/GroupController.cs  | 0
 .../ASC.People/Server/{ApiControllers => Api}/PeopleController.cs | 0
 2 files changed, 0 insertions(+), 0 deletions(-)
 rename products/ASC.People/Server/{ApiControllers => Api}/GroupController.cs (100%)
 rename products/ASC.People/Server/{ApiControllers => Api}/PeopleController.cs (100%)

diff --git a/products/ASC.People/Server/ApiControllers/GroupController.cs b/products/ASC.People/Server/Api/GroupController.cs
similarity index 100%
rename from products/ASC.People/Server/ApiControllers/GroupController.cs
rename to products/ASC.People/Server/Api/GroupController.cs
diff --git a/products/ASC.People/Server/ApiControllers/PeopleController.cs b/products/ASC.People/Server/Api/PeopleController.cs
similarity index 100%
rename from products/ASC.People/Server/ApiControllers/PeopleController.cs
rename to products/ASC.People/Server/Api/PeopleController.cs

From 6be380656f199a242a74f8b8a365bd31107db57f Mon Sep 17 00:00:00 2001
From: MaksimChegulov <maksim.chegulov@onlyoffice.com>
Date: Mon, 28 Feb 2022 21:12:18 +0300
Subject: [PATCH 11/28] People: model to dto

---
 .../ASC.People/Server/Api/PeopleController.cs     |  6 +++---
 .../{AccountInfo.cs => AccountInfoDto.cs}         |  2 +-
 .../Server/ApiModels/FileUploadResultDto.cs       |  8 ++++++++
 .../{GroupWrapperFull.cs => GroupDto.cs}          |  0
 .../{GroupModel.cs => GroupRequestDto.cs}         |  0
 ...nkAccountModel.cs => LinkAccountRequestDto.cs} |  0
 .../{MemberModel.cs => MemberRequestDto.cs}       |  0
 ...Model.cs => RegisterPersonalUserRequestDto.cs} |  0
 ...SetManagerModel.cs => SetManagerRequestDto.cs} |  0
 ...eassignModel.cs => StartReassignRequestDto.cs} |  0
 .../{TerminateModel.cs => TerminateRequestDto.cs} |  0
 ...mbnailsDataWrapper.cs => ThumbnailsDataDto.cs} |  0
 ...ThumbnailsModel.cs => ThumbnailsRequestDto.cs} |  0
 ...Model.cs => TransferGroupMembersRequestDto.cs} |  0
 ...MembersModel.cs => UpdateMembersRequestDto.cs} |  0
 .../Server/ApiModels/UploadPhotoModel.cs          | 15 ---------------
 .../Server/ApiModels/UploadPhotoRequestDto.cs     |  8 ++++++++
 17 files changed, 20 insertions(+), 19 deletions(-)
 rename products/ASC.People/Server/ApiModels/{AccountInfo.cs => AccountInfoDto.cs} (83%)
 create mode 100644 products/ASC.People/Server/ApiModels/FileUploadResultDto.cs
 rename products/ASC.People/Server/ApiModels/{GroupWrapperFull.cs => GroupDto.cs} (100%)
 rename products/ASC.People/Server/ApiModels/{GroupModel.cs => GroupRequestDto.cs} (100%)
 rename products/ASC.People/Server/ApiModels/{LinkAccountModel.cs => LinkAccountRequestDto.cs} (100%)
 rename products/ASC.People/Server/ApiModels/{MemberModel.cs => MemberRequestDto.cs} (100%)
 rename products/ASC.People/Server/ApiModels/{RegisterPersonalUserModel.cs => RegisterPersonalUserRequestDto.cs} (100%)
 rename products/ASC.People/Server/ApiModels/{SetManagerModel.cs => SetManagerRequestDto.cs} (100%)
 rename products/ASC.People/Server/ApiModels/{StartReassignModel.cs => StartReassignRequestDto.cs} (100%)
 rename products/ASC.People/Server/ApiModels/{TerminateModel.cs => TerminateRequestDto.cs} (100%)
 rename products/ASC.People/Server/ApiModels/{ThumbnailsDataWrapper.cs => ThumbnailsDataDto.cs} (100%)
 rename products/ASC.People/Server/ApiModels/{ThumbnailsModel.cs => ThumbnailsRequestDto.cs} (100%)
 rename products/ASC.People/Server/ApiModels/{TransferGroupMembersModel.cs => TransferGroupMembersRequestDto.cs} (100%)
 rename products/ASC.People/Server/ApiModels/{UpdateMembersModel.cs => UpdateMembersRequestDto.cs} (100%)
 delete mode 100644 products/ASC.People/Server/ApiModels/UploadPhotoModel.cs
 create mode 100644 products/ASC.People/Server/ApiModels/UploadPhotoRequestDto.cs

diff --git a/products/ASC.People/Server/Api/PeopleController.cs b/products/ASC.People/Server/Api/PeopleController.cs
index 4b13f5bde1..49fe4852a5 100644
--- a/products/ASC.People/Server/Api/PeopleController.cs
+++ b/products/ASC.People/Server/Api/PeopleController.cs
@@ -1547,9 +1547,9 @@ namespace ASC.Employee.Core.Controllers
 
         [AllowAnonymous]
         [Read("thirdparty/providers")]
-        public ICollection<AccountInfo> GetAuthProviders(bool inviteView, bool settingsView, string clientCallback, string fromOnly)
+        public ICollection<AccountInfoDto> GetAuthProviders(bool inviteView, bool settingsView, string clientCallback, string fromOnly)
         {
-            ICollection<AccountInfo> infos = new List<AccountInfo>();
+            ICollection<AccountInfoDto> infos = new List<AccountInfoDto>();
             IEnumerable<LoginProfile> linkedAccounts = new List<LoginProfile>();
 
             if (AuthContext.IsAuthenticated)
@@ -1572,7 +1572,7 @@ namespace ASC.Employee.Core.Controllers
                             ? $"&mode=popup&callback={clientCallback}"
                             : "&mode=Redirect&desktop=true";
 
-                    infos.Add(new AccountInfo
+                    infos.Add(new AccountInfoDto
                     {
                         Linked = linkedAccounts.Any(x => x.Provider == provider),
                         Provider = provider,
diff --git a/products/ASC.People/Server/ApiModels/AccountInfo.cs b/products/ASC.People/Server/ApiModels/AccountInfoDto.cs
similarity index 83%
rename from products/ASC.People/Server/ApiModels/AccountInfo.cs
rename to products/ASC.People/Server/ApiModels/AccountInfoDto.cs
index 9f33f77e31..73a835be66 100644
--- a/products/ASC.People/Server/ApiModels/AccountInfo.cs
+++ b/products/ASC.People/Server/ApiModels/AccountInfoDto.cs
@@ -1,6 +1,6 @@
 namespace ASC.People.Models
 {
-    public class AccountInfo
+    public class AccountInfoDto
     {
         public string Provider { get; set; }
         public string Url { get; set; }
diff --git a/products/ASC.People/Server/ApiModels/FileUploadResultDto.cs b/products/ASC.People/Server/ApiModels/FileUploadResultDto.cs
new file mode 100644
index 0000000000..711e560635
--- /dev/null
+++ b/products/ASC.People/Server/ApiModels/FileUploadResultDto.cs
@@ -0,0 +1,8 @@
+namespace ASC.People.ApiModels;
+
+public class FileUploadResultDto
+{
+    public bool Success { get; set; }
+    public object Data { get; set; }
+    public string Message { get; set; }
+}
diff --git a/products/ASC.People/Server/ApiModels/GroupWrapperFull.cs b/products/ASC.People/Server/ApiModels/GroupDto.cs
similarity index 100%
rename from products/ASC.People/Server/ApiModels/GroupWrapperFull.cs
rename to products/ASC.People/Server/ApiModels/GroupDto.cs
diff --git a/products/ASC.People/Server/ApiModels/GroupModel.cs b/products/ASC.People/Server/ApiModels/GroupRequestDto.cs
similarity index 100%
rename from products/ASC.People/Server/ApiModels/GroupModel.cs
rename to products/ASC.People/Server/ApiModels/GroupRequestDto.cs
diff --git a/products/ASC.People/Server/ApiModels/LinkAccountModel.cs b/products/ASC.People/Server/ApiModels/LinkAccountRequestDto.cs
similarity index 100%
rename from products/ASC.People/Server/ApiModels/LinkAccountModel.cs
rename to products/ASC.People/Server/ApiModels/LinkAccountRequestDto.cs
diff --git a/products/ASC.People/Server/ApiModels/MemberModel.cs b/products/ASC.People/Server/ApiModels/MemberRequestDto.cs
similarity index 100%
rename from products/ASC.People/Server/ApiModels/MemberModel.cs
rename to products/ASC.People/Server/ApiModels/MemberRequestDto.cs
diff --git a/products/ASC.People/Server/ApiModels/RegisterPersonalUserModel.cs b/products/ASC.People/Server/ApiModels/RegisterPersonalUserRequestDto.cs
similarity index 100%
rename from products/ASC.People/Server/ApiModels/RegisterPersonalUserModel.cs
rename to products/ASC.People/Server/ApiModels/RegisterPersonalUserRequestDto.cs
diff --git a/products/ASC.People/Server/ApiModels/SetManagerModel.cs b/products/ASC.People/Server/ApiModels/SetManagerRequestDto.cs
similarity index 100%
rename from products/ASC.People/Server/ApiModels/SetManagerModel.cs
rename to products/ASC.People/Server/ApiModels/SetManagerRequestDto.cs
diff --git a/products/ASC.People/Server/ApiModels/StartReassignModel.cs b/products/ASC.People/Server/ApiModels/StartReassignRequestDto.cs
similarity index 100%
rename from products/ASC.People/Server/ApiModels/StartReassignModel.cs
rename to products/ASC.People/Server/ApiModels/StartReassignRequestDto.cs
diff --git a/products/ASC.People/Server/ApiModels/TerminateModel.cs b/products/ASC.People/Server/ApiModels/TerminateRequestDto.cs
similarity index 100%
rename from products/ASC.People/Server/ApiModels/TerminateModel.cs
rename to products/ASC.People/Server/ApiModels/TerminateRequestDto.cs
diff --git a/products/ASC.People/Server/ApiModels/ThumbnailsDataWrapper.cs b/products/ASC.People/Server/ApiModels/ThumbnailsDataDto.cs
similarity index 100%
rename from products/ASC.People/Server/ApiModels/ThumbnailsDataWrapper.cs
rename to products/ASC.People/Server/ApiModels/ThumbnailsDataDto.cs
diff --git a/products/ASC.People/Server/ApiModels/ThumbnailsModel.cs b/products/ASC.People/Server/ApiModels/ThumbnailsRequestDto.cs
similarity index 100%
rename from products/ASC.People/Server/ApiModels/ThumbnailsModel.cs
rename to products/ASC.People/Server/ApiModels/ThumbnailsRequestDto.cs
diff --git a/products/ASC.People/Server/ApiModels/TransferGroupMembersModel.cs b/products/ASC.People/Server/ApiModels/TransferGroupMembersRequestDto.cs
similarity index 100%
rename from products/ASC.People/Server/ApiModels/TransferGroupMembersModel.cs
rename to products/ASC.People/Server/ApiModels/TransferGroupMembersRequestDto.cs
diff --git a/products/ASC.People/Server/ApiModels/UpdateMembersModel.cs b/products/ASC.People/Server/ApiModels/UpdateMembersRequestDto.cs
similarity index 100%
rename from products/ASC.People/Server/ApiModels/UpdateMembersModel.cs
rename to products/ASC.People/Server/ApiModels/UpdateMembersRequestDto.cs
diff --git a/products/ASC.People/Server/ApiModels/UploadPhotoModel.cs b/products/ASC.People/Server/ApiModels/UploadPhotoModel.cs
deleted file mode 100644
index 28fd93d24c..0000000000
--- a/products/ASC.People/Server/ApiModels/UploadPhotoModel.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-namespace ASC.People.Models
-{
-    public class UploadPhotoModel
-    {
-        public List<IFormFile> Files { get; set; }
-        public bool Autosave { get; set; }
-    }
-
-    public class FileUploadResult
-    {
-        public bool Success { get; set; }
-        public object Data { get; set; }
-        public string Message { get; set; }
-    }
-}
diff --git a/products/ASC.People/Server/ApiModels/UploadPhotoRequestDto.cs b/products/ASC.People/Server/ApiModels/UploadPhotoRequestDto.cs
new file mode 100644
index 0000000000..e39d1447b7
--- /dev/null
+++ b/products/ASC.People/Server/ApiModels/UploadPhotoRequestDto.cs
@@ -0,0 +1,8 @@
+namespace ASC.People.Models
+{
+    public class UploadPhotoModel
+    {
+        public List<IFormFile> Files { get; set; }
+        public bool Autosave { get; set; }
+    }
+}

From 542ce9c4144737222c8d057f7622dc00491bda30 Mon Sep 17 00:00:00 2001
From: MaksimChegulov <maksim.chegulov@onlyoffice.com>
Date: Mon, 28 Feb 2022 21:36:40 +0300
Subject: [PATCH 12/28] People: rename

---
 .../ASC.People/Server/Api/GroupController.cs  |  48 ++---
 .../ASC.People/Server/Api/PeopleController.cs | 166 +++++++++---------
 .../ASC.People/Server/ApiModels/GroupDto.cs   |  10 +-
 .../Server/ApiModels/GroupRequestDto.cs       |   2 +-
 .../Server/ApiModels/LinkAccountRequestDto.cs |   4 +-
 .../Server/ApiModels/MemberRequestDto.cs      |   4 +-
 .../RegisterPersonalUserRequestDto.cs         |   2 +-
 .../Server/ApiModels/SetManagerRequestDto.cs  |   2 +-
 .../ApiModels/StartReassignRequestDto.cs      |   2 +-
 .../Server/ApiModels/TerminateRequestDto.cs   |   2 +-
 .../Server/ApiModels/ThumbnailsDataDto.cs     |  10 +-
 .../Server/ApiModels/ThumbnailsRequestDto.cs  |   2 +-
 .../TransferGroupMembersRequestDto.cs         |   2 +-
 .../ApiModels/UpdateMembersRequestDto.cs      |   2 +-
 .../Server/ApiModels/UploadPhotoRequestDto.cs |   2 +-
 15 files changed, 130 insertions(+), 130 deletions(-)

diff --git a/products/ASC.People/Server/Api/GroupController.cs b/products/ASC.People/Server/Api/GroupController.cs
index c55b8d3a22..511e23a68b 100644
--- a/products/ASC.People/Server/Api/GroupController.cs
+++ b/products/ASC.People/Server/Api/GroupController.cs
@@ -41,7 +41,7 @@
         }
 
         [Read("full")]
-        public IEnumerable<GroupWrapperFull> GetAllWithMembers()
+        public IEnumerable<GroupDto> GetAllWithMembers()
         {
             var result = UserManager.GetDepartments().Select(r => r);
             if (!string.IsNullOrEmpty(ApiContext.FilterValue))
@@ -52,7 +52,7 @@
         }
 
         [Read("{groupid}")]
-        public GroupWrapperFull GetById(Guid groupid)
+        public GroupDto GetById(Guid groupid)
         {
             return GroupWraperFullHelper.Get(GetGroupInfo(groupid), true);
         }
@@ -64,19 +64,19 @@
         }
 
         [Create]
-        public GroupWrapperFull AddGroupFromBody([FromBody]GroupModel groupModel)
+        public GroupDto AddGroupFromBody([FromBody]GroupRequestDto groupModel)
         {
             return AddGroup(groupModel);
         }
 
         [Create]
         [Consumes("application/x-www-form-urlencoded")]
-        public GroupWrapperFull AddGroupFromForm([FromForm] GroupModel groupModel)
+        public GroupDto AddGroupFromForm([FromForm] GroupRequestDto groupModel)
         {
             return AddGroup(groupModel);
         }
 
-        private GroupWrapperFull AddGroup(GroupModel groupModel)
+        private GroupDto AddGroup(GroupRequestDto groupModel)
         {
             PermissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
 
@@ -97,19 +97,19 @@
         }
 
         [Update("{groupid}")]
-        public GroupWrapperFull UpdateGroupFromBody(Guid groupid, [FromBody]GroupModel groupModel)
+        public GroupDto UpdateGroupFromBody(Guid groupid, [FromBody]GroupRequestDto groupModel)
         {
             return UpdateGroup(groupid, groupModel);
         }
 
         [Update("{groupid}")]
         [Consumes("application/x-www-form-urlencoded")]
-        public GroupWrapperFull UpdateGroupFromForm(Guid groupid, [FromForm] GroupModel groupModel)
+        public GroupDto UpdateGroupFromForm(Guid groupid, [FromForm] GroupRequestDto groupModel)
         {
             return UpdateGroup(groupid, groupModel);
         }
 
-        private GroupWrapperFull UpdateGroup(Guid groupid, GroupModel groupModel)
+        private GroupDto UpdateGroup(Guid groupid, GroupRequestDto groupModel)
         {
             PermissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
             var group = UserManager.GetGroups().SingleOrDefault(x => x.ID == groupid).NotFoundIfNull("group not found");
@@ -121,7 +121,7 @@
             group.Name = groupModel.GroupName ?? group.Name;
             UserManager.SaveGroupInfo(group);
 
-            RemoveMembersFrom(groupid, new GroupModel {Members = UserManager.GetUsersByGroup(groupid, EmployeeStatus.All).Select(u => u.ID).Where(id => !groupModel.Members.Contains(id)) });
+            RemoveMembersFrom(groupid, new GroupRequestDto {Members = UserManager.GetUsersByGroup(groupid, EmployeeStatus.All).Select(u => u.ID).Where(id => !groupModel.Members.Contains(id)) });
 
             TransferUserToDepartment(groupModel.GroupManager, @group, true);
             if (groupModel.Members != null)
@@ -138,7 +138,7 @@
         }
 
         [Delete("{groupid}")]
-        public GroupWrapperFull DeleteGroup(Guid groupid)
+        public GroupDto DeleteGroup(Guid groupid)
         {
             PermissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
             var @group = GetGroupInfo(groupid);
@@ -160,7 +160,7 @@
         }
 
         [Update("{groupid}/members/{newgroupid}")]
-        public GroupWrapperFull TransferMembersTo(Guid groupid, Guid newgroupid)
+        public GroupDto TransferMembersTo(Guid groupid, Guid newgroupid)
         {
             PermissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
             var oldgroup = GetGroupInfo(groupid);
@@ -176,39 +176,39 @@
         }
 
         [Create("{groupid}/members")]
-        public GroupWrapperFull SetMembersToFromBody(Guid groupid, [FromBody]GroupModel groupModel)
+        public GroupDto SetMembersToFromBody(Guid groupid, [FromBody]GroupRequestDto groupModel)
         {
             return SetMembersTo(groupid, groupModel);
         }
 
         [Create("{groupid}/members")]
         [Consumes("application/x-www-form-urlencoded")]
-        public GroupWrapperFull SetMembersToFromForm(Guid groupid, [FromForm] GroupModel groupModel)
+        public GroupDto SetMembersToFromForm(Guid groupid, [FromForm] GroupRequestDto groupModel)
         {
             return SetMembersTo(groupid, groupModel);
         }
 
-        private GroupWrapperFull SetMembersTo(Guid groupid, GroupModel groupModel)
+        private GroupDto SetMembersTo(Guid groupid, GroupRequestDto groupModel)
         {
-            RemoveMembersFrom(groupid, new GroupModel {Members = UserManager.GetUsersByGroup(groupid).Select(x => x.ID) });
+            RemoveMembersFrom(groupid, new GroupRequestDto {Members = UserManager.GetUsersByGroup(groupid).Select(x => x.ID) });
             AddMembersTo(groupid, groupModel);
             return GetById(groupid);
         }
 
         [Update("{groupid}/members")]
-        public GroupWrapperFull AddMembersToFromBody(Guid groupid, [FromBody]GroupModel groupModel)
+        public GroupDto AddMembersToFromBody(Guid groupid, [FromBody]GroupRequestDto groupModel)
         {
             return AddMembersTo(groupid, groupModel);
         }
 
         [Update("{groupid}/members")]
         [Consumes("application/x-www-form-urlencoded")]
-        public GroupWrapperFull AddMembersToFromForm(Guid groupid, [FromForm] GroupModel groupModel)
+        public GroupDto AddMembersToFromForm(Guid groupid, [FromForm] GroupRequestDto groupModel)
         {
             return AddMembersTo(groupid, groupModel);
         }
 
-        private GroupWrapperFull AddMembersTo(Guid groupid, GroupModel groupModel)
+        private GroupDto AddMembersTo(Guid groupid, GroupRequestDto groupModel)
         {
             PermissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
             var group = GetGroupInfo(groupid);
@@ -221,19 +221,19 @@
         }
 
         [Update("{groupid}/manager")]
-        public GroupWrapperFull SetManagerFromBody(Guid groupid, [FromBody]SetManagerModel setManagerModel)
+        public GroupDto SetManagerFromBody(Guid groupid, [FromBody]SetManagerRequestDto setManagerModel)
         {
             return SetManager(groupid, setManagerModel);
         }
 
         [Update("{groupid}/manager")]
         [Consumes("application/x-www-form-urlencoded")]
-        public GroupWrapperFull SetManagerFromForm(Guid groupid, [FromForm] SetManagerModel setManagerModel)
+        public GroupDto SetManagerFromForm(Guid groupid, [FromForm] SetManagerRequestDto setManagerModel)
         {
             return SetManager(groupid, setManagerModel);
         }
 
-        private GroupWrapperFull SetManager(Guid groupid, SetManagerModel setManagerModel)
+        private GroupDto SetManager(Guid groupid, SetManagerRequestDto setManagerModel)
         {
             var group = GetGroupInfo(groupid);
             if (UserManager.UserExists(setManagerModel.UserId))
@@ -248,19 +248,19 @@
         }
 
         [Delete("{groupid}/members")]
-        public GroupWrapperFull RemoveMembersFromFromBody(Guid groupid, [FromBody]GroupModel groupModel)
+        public GroupDto RemoveMembersFromFromBody(Guid groupid, [FromBody]GroupRequestDto groupModel)
         {
             return RemoveMembersFrom(groupid, groupModel);
         }
 
         [Delete("{groupid}/members")]
         [Consumes("application/x-www-form-urlencoded")]
-        public GroupWrapperFull RemoveMembersFromFromForm(Guid groupid, [FromForm] GroupModel groupModel)
+        public GroupDto RemoveMembersFromFromForm(Guid groupid, [FromForm] GroupRequestDto groupModel)
         {
             return RemoveMembersFrom(groupid, groupModel);
         }
 
-        private GroupWrapperFull RemoveMembersFrom(Guid groupid, GroupModel groupModel)
+        private GroupDto RemoveMembersFrom(Guid groupid, GroupRequestDto groupModel)
         {
             PermissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
             var group = GetGroupInfo(groupid);
diff --git a/products/ASC.People/Server/Api/PeopleController.cs b/products/ASC.People/Server/Api/PeopleController.cs
index 49fe4852a5..34a9029bc9 100644
--- a/products/ASC.People/Server/Api/PeopleController.cs
+++ b/products/ASC.People/Server/Api/PeopleController.cs
@@ -380,14 +380,14 @@ namespace ASC.Employee.Core.Controllers
 
         [AllowAnonymous]
         [Create(@"register")]
-        public Task<string> RegisterUserOnPersonalAsync(RegisterPersonalUserModel model)
+        public Task<string> RegisterUserOnPersonalAsync(RegisterPersonalUserRequestDto model)
         {
             if (!CoreBaseSettings.Personal) throw new MethodAccessException("Method is only available on personal.onlyoffice.com");
 
             return InternalRegisterUserOnPersonalAsync(model);
         }
 
-        private async Task<string> InternalRegisterUserOnPersonalAsync(RegisterPersonalUserModel model)
+        private async Task<string> InternalRegisterUserOnPersonalAsync(RegisterPersonalUserRequestDto model)
         {
             try
             {
@@ -468,7 +468,7 @@ namespace ASC.Employee.Core.Controllers
 
         [Create]
         [Authorize(AuthenticationSchemes = "confirm", Roles = "LinkInvite,Everyone")]
-        public EmployeeWraperFull AddMemberFromBody([FromBody] MemberModel memberModel)
+        public EmployeeWraperFull AddMemberFromBody([FromBody] MemberRequestDto memberModel)
         {
             return AddMember(memberModel);
         }
@@ -476,12 +476,12 @@ namespace ASC.Employee.Core.Controllers
         [Create]
         [Authorize(AuthenticationSchemes = "confirm", Roles = "LinkInvite,Everyone")]
         [Consumes("application/x-www-form-urlencoded")]
-        public EmployeeWraperFull AddMemberFromForm([FromForm] MemberModel memberModel)
+        public EmployeeWraperFull AddMemberFromForm([FromForm] MemberRequestDto memberModel)
         {
             return AddMember(memberModel);
         }
 
-        private EmployeeWraperFull AddMember(MemberModel memberModel)
+        private EmployeeWraperFull AddMember(MemberRequestDto memberModel)
         {
             ApiContext.AuthByClaim();
 
@@ -540,19 +540,19 @@ namespace ASC.Employee.Core.Controllers
         }
 
         [Create("active")]
-        public EmployeeWraperFull AddMemberAsActivatedFromBody([FromBody] MemberModel memberModel)
+        public EmployeeWraperFull AddMemberAsActivatedFromBody([FromBody] MemberRequestDto memberModel)
         {
             return AddMemberAsActivated(memberModel);
         }
 
         [Create("active")]
         [Consumes("application/x-www-form-urlencoded")]
-        public EmployeeWraperFull AddMemberAsActivatedFromForm([FromForm] MemberModel memberModel)
+        public EmployeeWraperFull AddMemberAsActivatedFromForm([FromForm] MemberRequestDto memberModel)
         {
             return AddMemberAsActivated(memberModel);
         }
 
-        private EmployeeWraperFull AddMemberAsActivated(MemberModel memberModel)
+        private EmployeeWraperFull AddMemberAsActivated(MemberRequestDto memberModel)
         {
             PermissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
 
@@ -608,19 +608,19 @@ namespace ASC.Employee.Core.Controllers
         }
 
         [Update("{userid}/culture")]
-        public EmployeeWraperFull UpdateMemberCultureFromBody(string userid, [FromBody] UpdateMemberModel memberModel)
+        public EmployeeWraperFull UpdateMemberCultureFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
         {
             return UpdateMemberCulture(userid, memberModel);
         }
 
         [Update("{userid}/culture")]
         [Consumes("application/x-www-form-urlencoded")]
-        public EmployeeWraperFull UpdateMemberCultureFromForm(string userid, [FromForm] UpdateMemberModel memberModel)
+        public EmployeeWraperFull UpdateMemberCultureFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
         {
             return UpdateMemberCulture(userid, memberModel);
         }
 
-        private EmployeeWraperFull UpdateMemberCulture(string userid, UpdateMemberModel memberModel)
+        private EmployeeWraperFull UpdateMemberCulture(string userid, UpdateMemberRequestDto memberModel)
         {
             var user = GetUserInfo(userid);
 
@@ -656,19 +656,19 @@ namespace ASC.Employee.Core.Controllers
         }
 
         [Update("{userid}")]
-        public EmployeeWraperFull UpdateMemberFromBody(string userid, [FromBody] UpdateMemberModel memberModel)
+        public EmployeeWraperFull UpdateMemberFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
         {
             return UpdateMember(userid, memberModel);
         }
 
         [Update("{userid}")]
         [Consumes("application/x-www-form-urlencoded")]
-        public EmployeeWraperFull UpdateMemberFromForm(string userid, [FromForm] UpdateMemberModel memberModel)
+        public EmployeeWraperFull UpdateMemberFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
         {
             return UpdateMember(userid, memberModel);
         }
 
-        private EmployeeWraperFull UpdateMember(string userid, UpdateMemberModel memberModel)
+        private EmployeeWraperFull UpdateMember(string userid, UpdateMemberRequestDto memberModel)
         {
             var user = GetUserInfo(userid);
 
@@ -847,19 +847,19 @@ namespace ASC.Employee.Core.Controllers
         }
 
         [Update("{userid}/contacts")]
-        public EmployeeWraperFull UpdateMemberContactsFromBody(string userid, [FromBody] UpdateMemberModel memberModel)
+        public EmployeeWraperFull UpdateMemberContactsFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
         {
             return UpdateMemberContacts(userid, memberModel);
         }
 
         [Update("{userid}/contacts")]
         [Consumes("application/x-www-form-urlencoded")]
-        public EmployeeWraperFull UpdateMemberContactsFromForm(string userid, [FromForm] UpdateMemberModel memberModel)
+        public EmployeeWraperFull UpdateMemberContactsFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
         {
             return UpdateMemberContacts(userid, memberModel);
         }
 
-        private EmployeeWraperFull UpdateMemberContacts(string userid, UpdateMemberModel memberModel)
+        private EmployeeWraperFull UpdateMemberContacts(string userid, UpdateMemberRequestDto memberModel)
         {
             var user = GetUserInfo(userid);
 
@@ -872,19 +872,19 @@ namespace ASC.Employee.Core.Controllers
         }
 
         [Create("{userid}/contacts")]
-        public EmployeeWraperFull SetMemberContactsFromBody(string userid, [FromBody] UpdateMemberModel memberModel)
+        public EmployeeWraperFull SetMemberContactsFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
         {
             return SetMemberContacts(userid, memberModel);
         }
 
         [Create("{userid}/contacts")]
         [Consumes("application/x-www-form-urlencoded")]
-        public EmployeeWraperFull SetMemberContactsFromForm(string userid, [FromForm] UpdateMemberModel memberModel)
+        public EmployeeWraperFull SetMemberContactsFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
         {
             return SetMemberContacts(userid, memberModel);
         }
 
-        private EmployeeWraperFull SetMemberContacts(string userid, UpdateMemberModel memberModel)
+        private EmployeeWraperFull SetMemberContacts(string userid, UpdateMemberRequestDto memberModel)
         {
             var user = GetUserInfo(userid);
 
@@ -898,19 +898,19 @@ namespace ASC.Employee.Core.Controllers
         }
 
         [Delete("{userid}/contacts")]
-        public EmployeeWraperFull DeleteMemberContactsFromBody(string userid, [FromBody] UpdateMemberModel memberModel)
+        public EmployeeWraperFull DeleteMemberContactsFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
         {
             return DeleteMemberContacts(userid, memberModel);
         }
 
         [Delete("{userid}/contacts")]
         [Consumes("application/x-www-form-urlencoded")]
-        public EmployeeWraperFull DeleteMemberContactsFromForm(string userid, [FromForm] UpdateMemberModel memberModel)
+        public EmployeeWraperFull DeleteMemberContactsFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
         {
             return DeleteMemberContacts(userid, memberModel);
         }
 
-        private EmployeeWraperFull DeleteMemberContacts(string userid, UpdateMemberModel memberModel)
+        private EmployeeWraperFull DeleteMemberContacts(string userid, UpdateMemberRequestDto memberModel)
         {
             var user = GetUserInfo(userid);
 
@@ -923,14 +923,14 @@ namespace ASC.Employee.Core.Controllers
         }
 
         [Read("{userid}/photo")]
-        public ThumbnailsDataWrapper GetMemberPhoto(string userid)
+        public ThumbnailsDataDto GetMemberPhoto(string userid)
         {
             var user = GetUserInfo(userid);
 
             if (UserManager.IsSystemUser(user.ID))
                 throw new SecurityException();
 
-            return new ThumbnailsDataWrapper(user.ID, UserPhotoManager);
+            return new ThumbnailsDataDto(user.ID, UserPhotoManager);
         }
 
         [Create("{userid}/photo")]
@@ -1030,19 +1030,19 @@ namespace ASC.Employee.Core.Controllers
         }
 
         [Update("{userid}/photo")]
-        public ThumbnailsDataWrapper UpdateMemberPhotoFromBody(string userid, [FromBody] UpdateMemberModel model)
+        public ThumbnailsDataDto UpdateMemberPhotoFromBody(string userid, [FromBody] UpdateMemberRequestDto model)
         {
             return UpdateMemberPhoto(userid, model);
         }
 
         [Update("{userid}/photo")]
         [Consumes("application/x-www-form-urlencoded")]
-        public ThumbnailsDataWrapper UpdateMemberPhotoFromForm(string userid, [FromForm] UpdateMemberModel model)
+        public ThumbnailsDataDto UpdateMemberPhotoFromForm(string userid, [FromForm] UpdateMemberRequestDto model)
         {
             return UpdateMemberPhoto(userid, model);
         }
 
-        private ThumbnailsDataWrapper UpdateMemberPhoto(string userid, UpdateMemberModel model)
+        private ThumbnailsDataDto UpdateMemberPhoto(string userid, UpdateMemberRequestDto model)
         {
             var user = GetUserInfo(userid);
 
@@ -1057,11 +1057,11 @@ namespace ASC.Employee.Core.Controllers
             UserManager.SaveUserInfo(user);
             MessageService.Send(MessageAction.UserAddedAvatar, MessageTarget.Create(user.ID), user.DisplayUserName(false, DisplayUserSettingsHelper));
 
-            return new ThumbnailsDataWrapper(user.ID, UserPhotoManager);
+            return new ThumbnailsDataDto(user.ID, UserPhotoManager);
         }
 
         [Delete("{userid}/photo")]
-        public ThumbnailsDataWrapper DeleteMemberPhoto(string userid)
+        public ThumbnailsDataDto DeleteMemberPhoto(string userid)
         {
             var user = GetUserInfo(userid);
 
@@ -1075,24 +1075,24 @@ namespace ASC.Employee.Core.Controllers
             UserManager.SaveUserInfo(user);
             MessageService.Send(MessageAction.UserDeletedAvatar, MessageTarget.Create(user.ID), user.DisplayUserName(false, DisplayUserSettingsHelper));
 
-            return new ThumbnailsDataWrapper(user.ID, UserPhotoManager);
+            return new ThumbnailsDataDto(user.ID, UserPhotoManager);
         }
 
 
         [Create("{userid}/photo/thumbnails")]
-        public ThumbnailsDataWrapper CreateMemberPhotoThumbnailsFromBody(string userid, [FromBody] ThumbnailsModel thumbnailsModel)
+        public ThumbnailsDataDto CreateMemberPhotoThumbnailsFromBody(string userid, [FromBody] ThumbnailsRequestDto thumbnailsModel)
         {
             return CreateMemberPhotoThumbnails(userid, thumbnailsModel);
         }
 
         [Create("{userid}/photo/thumbnails")]
         [Consumes("application/x-www-form-urlencoded")]
-        public ThumbnailsDataWrapper CreateMemberPhotoThumbnailsFromForm(string userid, [FromForm] ThumbnailsModel thumbnailsModel)
+        public ThumbnailsDataDto CreateMemberPhotoThumbnailsFromForm(string userid, [FromForm] ThumbnailsRequestDto thumbnailsModel)
         {
             return CreateMemberPhotoThumbnails(userid, thumbnailsModel);
         }
 
-        private ThumbnailsDataWrapper CreateMemberPhotoThumbnails(string userid, ThumbnailsModel thumbnailsModel)
+        private ThumbnailsDataDto CreateMemberPhotoThumbnails(string userid, ThumbnailsRequestDto thumbnailsModel)
         {
             var user = GetUserInfo(userid);
 
@@ -1121,13 +1121,13 @@ namespace ASC.Employee.Core.Controllers
             UserManager.SaveUserInfo(user);
             MessageService.Send(MessageAction.UserUpdatedAvatarThumbnails, MessageTarget.Create(user.ID), user.DisplayUserName(false, DisplayUserSettingsHelper));
 
-            return new ThumbnailsDataWrapper(user.ID, UserPhotoManager);
+            return new ThumbnailsDataDto(user.ID, UserPhotoManager);
         }
 
 
         [AllowAnonymous]
         [Create("password", false)]
-        public object SendUserPasswordFromBody([FromBody] MemberModel memberModel)
+        public object SendUserPasswordFromBody([FromBody] MemberRequestDto memberModel)
         {
             return SendUserPassword(memberModel);
         }
@@ -1135,12 +1135,12 @@ namespace ASC.Employee.Core.Controllers
         [AllowAnonymous]
         [Create("password", false)]
         [Consumes("application/x-www-form-urlencoded")]
-        public object SendUserPasswordFromForm([FromForm] MemberModel memberModel)
+        public object SendUserPasswordFromForm([FromForm] MemberRequestDto memberModel)
         {
             return SendUserPassword(memberModel);
         }
 
-        private object SendUserPassword(MemberModel memberModel)
+        private object SendUserPassword(MemberRequestDto memberModel)
         {
             string error = UserManagerWrapper.SendUserPassword(memberModel.Email);
             if (!string.IsNullOrEmpty(error))
@@ -1153,7 +1153,7 @@ namespace ASC.Employee.Core.Controllers
 
         [Update("{userid}/password")]
         [Authorize(AuthenticationSchemes = "confirm", Roles = "PasswordChange,EmailChange,Activation,EmailActivation,Everyone")]
-        public EmployeeWraperFull ChangeUserPasswordFromBody(Guid userid, [FromBody] MemberModel memberModel)
+        public EmployeeWraperFull ChangeUserPasswordFromBody(Guid userid, [FromBody] MemberRequestDto memberModel)
         {
             return ChangeUserPassword(userid, memberModel);
         }
@@ -1161,12 +1161,12 @@ namespace ASC.Employee.Core.Controllers
         [Update("{userid}/password")]
         [Authorize(AuthenticationSchemes = "confirm", Roles = "PasswordChange,EmailChange,Activation,EmailActivation,Everyone")]
         [Consumes("application/x-www-form-urlencoded")]
-        public EmployeeWraperFull ChangeUserPasswordFromForm(Guid userid, [FromForm] MemberModel memberModel)
+        public EmployeeWraperFull ChangeUserPasswordFromForm(Guid userid, [FromForm] MemberRequestDto memberModel)
         {
             return ChangeUserPassword(userid, memberModel);
         }
 
-        private EmployeeWraperFull ChangeUserPassword(Guid userid, MemberModel memberModel)
+        private EmployeeWraperFull ChangeUserPassword(Guid userid, MemberRequestDto memberModel)
         {
             ApiContext.AuthByClaim();
             PermissionContext.DemandPermissions(new UserSecurityProvider(userid), Constants.Action_EditUser);
@@ -1214,19 +1214,19 @@ namespace ASC.Employee.Core.Controllers
 
 
         [Create("email", false)]
-        public object SendEmailChangeInstructionsFromBody([FromBody] UpdateMemberModel model)
+        public object SendEmailChangeInstructionsFromBody([FromBody] UpdateMemberRequestDto model)
         {
             return SendEmailChangeInstructions(model);
         }
 
         [Create("email", false)]
         [Consumes("application/x-www-form-urlencoded")]
-        public object SendEmailChangeInstructionsFromForm([FromForm] UpdateMemberModel model)
+        public object SendEmailChangeInstructionsFromForm([FromForm] UpdateMemberRequestDto model)
         {
             return SendEmailChangeInstructions(model);
         }
 
-        private object SendEmailChangeInstructions(UpdateMemberModel model)
+        private object SendEmailChangeInstructions(UpdateMemberRequestDto model)
         {
             Guid.TryParse(model.UserId, out var userid);
 
@@ -1291,7 +1291,7 @@ namespace ASC.Employee.Core.Controllers
 
         [Update("activationstatus/{activationstatus}")]
         [Authorize(AuthenticationSchemes = "confirm", Roles = "Activation,Everyone")]
-        public IEnumerable<EmployeeWraperFull> UpdateEmployeeActivationStatusFromBody(EmployeeActivationStatus activationstatus, [FromBody] UpdateMembersModel model)
+        public IEnumerable<EmployeeWraperFull> UpdateEmployeeActivationStatusFromBody(EmployeeActivationStatus activationstatus, [FromBody] UpdateMembersRequestDto model)
         {
             return UpdateEmployeeActivationStatus(activationstatus, model);
         }
@@ -1299,12 +1299,12 @@ namespace ASC.Employee.Core.Controllers
         [Update("activationstatus/{activationstatus}")]
         [Authorize(AuthenticationSchemes = "confirm", Roles = "Activation,Everyone")]
         [Consumes("application/x-www-form-urlencoded")]
-        public IEnumerable<EmployeeWraperFull> UpdateEmployeeActivationStatusFromForm(EmployeeActivationStatus activationstatus, [FromForm] UpdateMembersModel model)
+        public IEnumerable<EmployeeWraperFull> UpdateEmployeeActivationStatusFromForm(EmployeeActivationStatus activationstatus, [FromForm] UpdateMembersRequestDto model)
         {
             return UpdateEmployeeActivationStatus(activationstatus, model);
         }
 
-        private IEnumerable<EmployeeWraperFull> UpdateEmployeeActivationStatus(EmployeeActivationStatus activationstatus, UpdateMembersModel model)
+        private IEnumerable<EmployeeWraperFull> UpdateEmployeeActivationStatus(EmployeeActivationStatus activationstatus, UpdateMembersRequestDto model)
         {
             ApiContext.AuthByClaim();
 
@@ -1324,19 +1324,19 @@ namespace ASC.Employee.Core.Controllers
         }
 
         [Update("type/{type}")]
-        public IEnumerable<EmployeeWraperFull> UpdateUserTypeFromBody(EmployeeType type, [FromBody] UpdateMembersModel model)
+        public IEnumerable<EmployeeWraperFull> UpdateUserTypeFromBody(EmployeeType type, [FromBody] UpdateMembersRequestDto model)
         {
             return UpdateUserType(type, model);
         }
 
         [Update("type/{type}")]
         [Consumes("application/x-www-form-urlencoded")]
-        public IEnumerable<EmployeeWraperFull> UpdateUserTypeFromForm(EmployeeType type, [FromForm] UpdateMembersModel model)
+        public IEnumerable<EmployeeWraperFull> UpdateUserTypeFromForm(EmployeeType type, [FromForm] UpdateMembersRequestDto model)
         {
             return UpdateUserType(type, model);
         }
 
-        private IEnumerable<EmployeeWraperFull> UpdateUserType(EmployeeType type, UpdateMembersModel model)
+        private IEnumerable<EmployeeWraperFull> UpdateUserType(EmployeeType type, UpdateMembersRequestDto model)
         {
             var users = model.UserIds
                 .Where(userId => !UserManager.IsSystemUser(userId))
@@ -1376,19 +1376,19 @@ namespace ASC.Employee.Core.Controllers
         }
 
         [Update("status/{status}")]
-        public IEnumerable<EmployeeWraperFull> UpdateUserStatusFromBody(EmployeeStatus status, [FromBody] UpdateMembersModel model)
+        public IEnumerable<EmployeeWraperFull> UpdateUserStatusFromBody(EmployeeStatus status, [FromBody] UpdateMembersRequestDto model)
         {
             return UpdateUserStatus(status, model);
         }
 
         [Update("status/{status}")]
         [Consumes("application/x-www-form-urlencoded")]
-        public IEnumerable<EmployeeWraperFull> UpdateUserStatusFromForm(EmployeeStatus status, [FromForm] UpdateMembersModel model)
+        public IEnumerable<EmployeeWraperFull> UpdateUserStatusFromForm(EmployeeStatus status, [FromForm] UpdateMembersRequestDto model)
         {
             return UpdateUserStatus(status, model);
         }
 
-        private IEnumerable<EmployeeWraperFull> UpdateUserStatus(EmployeeStatus status, UpdateMembersModel model)
+        private IEnumerable<EmployeeWraperFull> UpdateUserStatus(EmployeeStatus status, UpdateMembersRequestDto model)
         {
             PermissionContext.DemandPermissions(Constants.Action_EditUser);
 
@@ -1430,19 +1430,19 @@ namespace ASC.Employee.Core.Controllers
 
 
         [Update("invite")]
-        public IEnumerable<EmployeeWraperFull> ResendUserInvitesFromBody([FromBody] UpdateMembersModel model)
+        public IEnumerable<EmployeeWraperFull> ResendUserInvitesFromBody([FromBody] UpdateMembersRequestDto model)
         {
             return ResendUserInvites(model);
         }
 
         [Update("invite")]
         [Consumes("application/x-www-form-urlencoded")]
-        public IEnumerable<EmployeeWraperFull> ResendUserInvitesFromForm([FromForm] UpdateMembersModel model)
+        public IEnumerable<EmployeeWraperFull> ResendUserInvitesFromForm([FromForm] UpdateMembersRequestDto model)
         {
             return ResendUserInvites(model);
         }
 
-        private IEnumerable<EmployeeWraperFull> ResendUserInvites(UpdateMembersModel model)
+        private IEnumerable<EmployeeWraperFull> ResendUserInvites(UpdateMembersRequestDto model)
         {
             var users = model.UserIds
                 .Where(userId => !UserManager.IsSystemUser(userId))
@@ -1492,19 +1492,19 @@ namespace ASC.Employee.Core.Controllers
         }
 
         [Update("delete", Order = -1)]
-        public IEnumerable<EmployeeWraperFull> RemoveUsersFromBody([FromBody] UpdateMembersModel model)
+        public IEnumerable<EmployeeWraperFull> RemoveUsersFromBody([FromBody] UpdateMembersRequestDto model)
         {
             return RemoveUsers(model);
         }
 
         [Update("delete", Order = -1)]
         [Consumes("application/x-www-form-urlencoded")]
-        public IEnumerable<EmployeeWraperFull> RemoveUsersFromForm([FromForm] UpdateMembersModel model)
+        public IEnumerable<EmployeeWraperFull> RemoveUsersFromForm([FromForm] UpdateMembersRequestDto model)
         {
             return RemoveUsers(model);
         }
 
-        private IEnumerable<EmployeeWraperFull> RemoveUsers(UpdateMembersModel model)
+        private IEnumerable<EmployeeWraperFull> RemoveUsers(UpdateMembersRequestDto model)
         {
             PermissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
 
@@ -1586,19 +1586,19 @@ namespace ASC.Employee.Core.Controllers
 
 
         [Update("thirdparty/linkaccount")]
-        public void LinkAccountFromBody([FromBody] LinkAccountModel model)
+        public void LinkAccountFromBody([FromBody] LinkAccountRequestDto model)
         {
             LinkAccount(model);
         }
 
         [Update("thirdparty/linkaccount")]
         [Consumes("application/x-www-form-urlencoded")]
-        public void LinkAccountFromForm([FromForm] LinkAccountModel model)
+        public void LinkAccountFromForm([FromForm] LinkAccountRequestDto model)
         {
             LinkAccount(model);
         }
 
-        public void LinkAccount(LinkAccountModel model)
+        public void LinkAccount(LinkAccountRequestDto model)
         {
             var profile = new LoginProfile(Signature, InstanceCrypto, model.SerializedProfile);
 
@@ -1631,7 +1631,7 @@ namespace ASC.Employee.Core.Controllers
 
         [AllowAnonymous]
         [Create("thirdparty/signup")]
-        public void SignupAccountFromBody([FromBody] SignupAccountModel model)
+        public void SignupAccountFromBody([FromBody] SignupAccountRequestDto model)
         {
             SignupAccount(model);
         }
@@ -1639,12 +1639,12 @@ namespace ASC.Employee.Core.Controllers
         [AllowAnonymous]
         [Create("thirdparty/signup")]
         [Consumes("application/x-www-form-urlencoded")]
-        public void SignupAccountFromForm([FromForm] SignupAccountModel model)
+        public void SignupAccountFromForm([FromForm] SignupAccountRequestDto model)
         {
             SignupAccount(model);
         }
 
-        public void SignupAccount(SignupAccountModel model)
+        public void SignupAccount(SignupAccountRequestDto model)
         {
             var employeeType = model.EmplType ?? EmployeeType.User;
             var passwordHash = model.PasswordHash;
@@ -1711,14 +1711,14 @@ namespace ASC.Employee.Core.Controllers
         }
 
         [Create("phone")]
-        public object SendNotificationToChangeFromBody([FromBody] UpdateMemberModel model)
+        public object SendNotificationToChangeFromBody([FromBody] UpdateMemberRequestDto model)
         {
             return SendNotificationToChange(model.UserId);
         }
 
         [Create("phone")]
         [Consumes("application/x-www-form-urlencoded")]
-        public object SendNotificationToChangeFromForm([FromForm] UpdateMemberModel model)
+        public object SendNotificationToChangeFromForm([FromForm] UpdateMemberRequestDto model)
         {
             return SendNotificationToChange(model.UserId);
         }
@@ -1749,7 +1749,7 @@ namespace ASC.Employee.Core.Controllers
             return string.Empty;
         }
 
-        protected string GetEmailAddress(SignupAccountModel model)
+        protected string GetEmailAddress(SignupAccountRequestDto model)
         {
             if (!string.IsNullOrEmpty(model.Email))
                 return model.Email.Trim();
@@ -1757,33 +1757,33 @@ namespace ASC.Employee.Core.Controllers
             return string.Empty;
         }
 
-        private string GetEmailAddress(SignupAccountModel model, LoginProfile account)
+        private string GetEmailAddress(SignupAccountRequestDto model, LoginProfile account)
         {
             var value = GetEmailAddress(model);
             return string.IsNullOrEmpty(value) ? account.EMail : value;
         }
 
-        protected string GetFirstName(SignupAccountModel model)
+        protected string GetFirstName(SignupAccountRequestDto model)
         {
             var value = string.Empty;
             if (!string.IsNullOrEmpty(model.FirstName)) value = model.FirstName.Trim();
             return HtmlUtil.GetText(value);
         }
 
-        private string GetFirstName(SignupAccountModel model, LoginProfile account)
+        private string GetFirstName(SignupAccountRequestDto model, LoginProfile account)
         {
             var value = GetFirstName(model);
             return string.IsNullOrEmpty(value) ? account.FirstName : value;
         }
 
-        protected string GetLastName(SignupAccountModel model)
+        protected string GetLastName(SignupAccountRequestDto model)
         {
             var value = string.Empty;
             if (!string.IsNullOrEmpty(model.LastName)) value = model.LastName.Trim();
             return HtmlUtil.GetText(value);
         }
 
-        private string GetLastName(SignupAccountModel model, LoginProfile account)
+        private string GetLastName(SignupAccountRequestDto model, LoginProfile account)
         {
             var value = GetLastName(model);
             return string.IsNullOrEmpty(value) ? account.LastName : value;
@@ -1869,7 +1869,7 @@ namespace ASC.Employee.Core.Controllers
         }
 
         [Update(@"reassign/terminate")]
-        public void TerminateReassignFromBody([FromBody] TerminateModel model)
+        public void TerminateReassignFromBody([FromBody] TerminateRequestDto model)
         {
             PermissionContext.DemandPermissions(Constants.Action_EditUser);
 
@@ -1878,7 +1878,7 @@ namespace ASC.Employee.Core.Controllers
 
         [Update(@"reassign/terminate")]
         [Consumes("application/x-www-form-urlencoded")]
-        public void TerminateReassignFromForm([FromForm] TerminateModel model)
+        public void TerminateReassignFromForm([FromForm] TerminateRequestDto model)
         {
             PermissionContext.DemandPermissions(Constants.Action_EditUser);
 
@@ -1886,19 +1886,19 @@ namespace ASC.Employee.Core.Controllers
         }
 
         [Create(@"reassign/start")]
-        public ReassignProgressItem StartReassignFromBody([FromBody] StartReassignModel model)
+        public ReassignProgressItem StartReassignFromBody([FromBody] StartReassignRequestDto model)
         {
             return StartReassign(model);
         }
 
         [Create(@"reassign/start")]
         [Consumes("application/x-www-form-urlencoded")]
-        public ReassignProgressItem StartReassignFromForm([FromForm] StartReassignModel model)
+        public ReassignProgressItem StartReassignFromForm([FromForm] StartReassignRequestDto model)
         {
             return StartReassign(model);
         }
 
-        private ReassignProgressItem StartReassign(StartReassignModel model)
+        private ReassignProgressItem StartReassign(StartReassignRequestDto model)
         {
             PermissionContext.DemandPermissions(Constants.Action_EditUser);
 
@@ -1948,7 +1948,7 @@ namespace ASC.Employee.Core.Controllers
         }
 
         [Update(@"remove/terminate")]
-        public void TerminateRemoveFromBody([FromBody] TerminateModel model)
+        public void TerminateRemoveFromBody([FromBody] TerminateRequestDto model)
         {
             PermissionContext.DemandPermissions(Constants.Action_EditUser);
 
@@ -1957,7 +1957,7 @@ namespace ASC.Employee.Core.Controllers
 
         [Update(@"remove/terminate")]
         [Consumes("application/x-www-form-urlencoded")]
-        public void TerminateRemoveFromForm([FromForm] TerminateModel model)
+        public void TerminateRemoveFromForm([FromForm] TerminateRequestDto model)
         {
             PermissionContext.DemandPermissions(Constants.Action_EditUser);
 
@@ -1965,19 +1965,19 @@ namespace ASC.Employee.Core.Controllers
         }
 
         [Create(@"remove/start")]
-        public RemoveProgressItem StartRemoveFromBody([FromBody] TerminateModel model)
+        public RemoveProgressItem StartRemoveFromBody([FromBody] TerminateRequestDto model)
         {
             return StartRemove(model);
         }
 
         [Create(@"remove/start")]
         [Consumes("application/x-www-form-urlencoded")]
-        public RemoveProgressItem StartRemoveFromForm([FromForm] TerminateModel model)
+        public RemoveProgressItem StartRemoveFromForm([FromForm] TerminateRequestDto model)
         {
             return StartRemove(model);
         }
 
-        private RemoveProgressItem StartRemove(TerminateModel model)
+        private RemoveProgressItem StartRemove(TerminateRequestDto model)
         {
             PermissionContext.DemandPermissions(Constants.Action_EditUser);
 
diff --git a/products/ASC.People/Server/ApiModels/GroupDto.cs b/products/ASC.People/Server/ApiModels/GroupDto.cs
index fe7dfe1bd9..54f2c3a73c 100644
--- a/products/ASC.People/Server/ApiModels/GroupDto.cs
+++ b/products/ASC.People/Server/ApiModels/GroupDto.cs
@@ -25,7 +25,7 @@
 
 namespace ASC.Web.Api.Models
 {
-    public class GroupWrapperFull
+    public class GroupDto
     {
         public string Description { get; set; }
 
@@ -41,9 +41,9 @@ namespace ASC.Web.Api.Models
 
         public List<EmployeeWraper> Members { get; set; }
 
-        public static GroupWrapperFull GetSample()
+        public static GroupDto GetSample()
         {
-            return new GroupWrapperFull
+            return new GroupDto
             {
                 Id = Guid.NewGuid(),
                 Manager = EmployeeWraper.GetSample(),
@@ -67,9 +67,9 @@ namespace ASC.Web.Api.Models
             EmployeeWraperHelper = employeeWraperHelper;
         }
 
-        public GroupWrapperFull Get(GroupInfo group, bool includeMembers)
+        public GroupDto Get(GroupInfo group, bool includeMembers)
         {
-            var result = new GroupWrapperFull
+            var result = new GroupDto
             {
                 Id = group.ID,
                 Category = group.CategoryID,
diff --git a/products/ASC.People/Server/ApiModels/GroupRequestDto.cs b/products/ASC.People/Server/ApiModels/GroupRequestDto.cs
index 5ef7823258..6053768964 100644
--- a/products/ASC.People/Server/ApiModels/GroupRequestDto.cs
+++ b/products/ASC.People/Server/ApiModels/GroupRequestDto.cs
@@ -1,6 +1,6 @@
 namespace ASC.People.Models
 {
-    public class GroupModel
+    public class GroupRequestDto
     {
         public Guid GroupManager { get; set; }
         public string GroupName { get; set; }
diff --git a/products/ASC.People/Server/ApiModels/LinkAccountRequestDto.cs b/products/ASC.People/Server/ApiModels/LinkAccountRequestDto.cs
index 16c3cfcb8a..b53dd01c40 100644
--- a/products/ASC.People/Server/ApiModels/LinkAccountRequestDto.cs
+++ b/products/ASC.People/Server/ApiModels/LinkAccountRequestDto.cs
@@ -1,11 +1,11 @@
 namespace ASC.People.Models
 {
-    public class LinkAccountModel
+    public class LinkAccountRequestDto
     {
         public string SerializedProfile { get; set; }
     }
 
-    public class SignupAccountModel: LinkAccountModel
+    public class SignupAccountRequestDto: LinkAccountRequestDto
     {
         public EmployeeType? EmplType { get; set; }
         public string FirstName { get; set; }
diff --git a/products/ASC.People/Server/ApiModels/MemberRequestDto.cs b/products/ASC.People/Server/ApiModels/MemberRequestDto.cs
index 7116e98bba..f152bfc1d3 100644
--- a/products/ASC.People/Server/ApiModels/MemberRequestDto.cs
+++ b/products/ASC.People/Server/ApiModels/MemberRequestDto.cs
@@ -1,6 +1,6 @@
 namespace ASC.People.Models
 {
-    public class MemberModel
+    public class MemberRequestDto
     {
         public bool IsVisitor { get; set; }
         public string Email { get; set; }
@@ -21,7 +21,7 @@
         public bool FromInviteLink { get; set; }
     }
 
-    public class UpdateMemberModel : MemberModel
+    public class UpdateMemberRequestDto : MemberRequestDto
     {
         public string UserId { get; set; }
         public bool? Disable { get; set; }
diff --git a/products/ASC.People/Server/ApiModels/RegisterPersonalUserRequestDto.cs b/products/ASC.People/Server/ApiModels/RegisterPersonalUserRequestDto.cs
index 64e8d8d068..93152cfc04 100644
--- a/products/ASC.People/Server/ApiModels/RegisterPersonalUserRequestDto.cs
+++ b/products/ASC.People/Server/ApiModels/RegisterPersonalUserRequestDto.cs
@@ -1,6 +1,6 @@
 namespace ASC.People.Models
 {
-    public class RegisterPersonalUserModel
+    public class RegisterPersonalUserRequestDto
     {
         public string Email { get; set; }
         public string Lang { get; set; }
diff --git a/products/ASC.People/Server/ApiModels/SetManagerRequestDto.cs b/products/ASC.People/Server/ApiModels/SetManagerRequestDto.cs
index 7422851c6b..8cd17494cc 100644
--- a/products/ASC.People/Server/ApiModels/SetManagerRequestDto.cs
+++ b/products/ASC.People/Server/ApiModels/SetManagerRequestDto.cs
@@ -1,6 +1,6 @@
 namespace ASC.People.Models
 {
-    public class SetManagerModel
+    public class SetManagerRequestDto
     {
         public Guid UserId { get; set; }
     }
diff --git a/products/ASC.People/Server/ApiModels/StartReassignRequestDto.cs b/products/ASC.People/Server/ApiModels/StartReassignRequestDto.cs
index c7e9c8a5ad..70bdcb635a 100644
--- a/products/ASC.People/Server/ApiModels/StartReassignRequestDto.cs
+++ b/products/ASC.People/Server/ApiModels/StartReassignRequestDto.cs
@@ -1,6 +1,6 @@
 namespace ASC.People.Models
 {
-    public class StartReassignModel
+    public class StartReassignRequestDto
     {
         public Guid FromUserId { get; set; }
         public Guid ToUserId { get; set; }
diff --git a/products/ASC.People/Server/ApiModels/TerminateRequestDto.cs b/products/ASC.People/Server/ApiModels/TerminateRequestDto.cs
index dcd3a792da..8abda99faa 100644
--- a/products/ASC.People/Server/ApiModels/TerminateRequestDto.cs
+++ b/products/ASC.People/Server/ApiModels/TerminateRequestDto.cs
@@ -1,6 +1,6 @@
 namespace ASC.People.Models
 {
-    public class TerminateModel
+    public class TerminateRequestDto
     {
         public Guid UserId { get; set; }
     }
diff --git a/products/ASC.People/Server/ApiModels/ThumbnailsDataDto.cs b/products/ASC.People/Server/ApiModels/ThumbnailsDataDto.cs
index f91986cc64..be73b4a7c0 100644
--- a/products/ASC.People/Server/ApiModels/ThumbnailsDataDto.cs
+++ b/products/ASC.People/Server/ApiModels/ThumbnailsDataDto.cs
@@ -25,9 +25,9 @@
 
 namespace ASC.Web.Api.Models
 {
-    public class ThumbnailsDataWrapper
+    public class ThumbnailsDataDto
     {
-        public ThumbnailsDataWrapper(Guid userId, UserPhotoManager userPhotoManager)
+        public ThumbnailsDataDto(Guid userId, UserPhotoManager userPhotoManager)
         {
             Original = userPhotoManager.GetPhotoAbsoluteWebPath(userId);
             Retina = userPhotoManager.GetRetinaPhotoURL(userId);
@@ -37,7 +37,7 @@ namespace ASC.Web.Api.Models
             Small = userPhotoManager.GetSmallPhotoURL(userId);
         }
 
-        private ThumbnailsDataWrapper()
+        private ThumbnailsDataDto()
         {
         }
 
@@ -54,9 +54,9 @@ namespace ASC.Web.Api.Models
         public string Small { get; set; }
 
 
-        public static ThumbnailsDataWrapper GetSample()
+        public static ThumbnailsDataDto GetSample()
         {
-            return new ThumbnailsDataWrapper
+            return new ThumbnailsDataDto
             {
                 Original = "default_user_photo_size_1280-1280.png",
                 Retina = "default_user_photo_size_360-360.png",
diff --git a/products/ASC.People/Server/ApiModels/ThumbnailsRequestDto.cs b/products/ASC.People/Server/ApiModels/ThumbnailsRequestDto.cs
index 02a6d94bca..0b652cff08 100644
--- a/products/ASC.People/Server/ApiModels/ThumbnailsRequestDto.cs
+++ b/products/ASC.People/Server/ApiModels/ThumbnailsRequestDto.cs
@@ -1,6 +1,6 @@
 namespace ASC.People.Models
 {
-    public class ThumbnailsModel
+    public class ThumbnailsRequestDto
     {
         public string TmpFile { get; set; }
         public int X { get; set; }
diff --git a/products/ASC.People/Server/ApiModels/TransferGroupMembersRequestDto.cs b/products/ASC.People/Server/ApiModels/TransferGroupMembersRequestDto.cs
index 5e811a7fa4..8a0037de9c 100644
--- a/products/ASC.People/Server/ApiModels/TransferGroupMembersRequestDto.cs
+++ b/products/ASC.People/Server/ApiModels/TransferGroupMembersRequestDto.cs
@@ -1,6 +1,6 @@
 namespace ASC.People.Models
 {
-    public class TransferGroupMembersModel
+    public class TransferGroupMembersRequestDto
     {
         public Guid GroupId { get; set; }
         public Guid NewGroupId { get; set; }
diff --git a/products/ASC.People/Server/ApiModels/UpdateMembersRequestDto.cs b/products/ASC.People/Server/ApiModels/UpdateMembersRequestDto.cs
index 33892c3ea4..1fcd772a9d 100644
--- a/products/ASC.People/Server/ApiModels/UpdateMembersRequestDto.cs
+++ b/products/ASC.People/Server/ApiModels/UpdateMembersRequestDto.cs
@@ -1,6 +1,6 @@
 namespace ASC.People.Models
 {
-    public class UpdateMembersModel
+    public class UpdateMembersRequestDto
     {
         public IEnumerable<Guid> UserIds { get; set; }
     }
diff --git a/products/ASC.People/Server/ApiModels/UploadPhotoRequestDto.cs b/products/ASC.People/Server/ApiModels/UploadPhotoRequestDto.cs
index e39d1447b7..ea943915ce 100644
--- a/products/ASC.People/Server/ApiModels/UploadPhotoRequestDto.cs
+++ b/products/ASC.People/Server/ApiModels/UploadPhotoRequestDto.cs
@@ -1,6 +1,6 @@
 namespace ASC.People.Models
 {
-    public class UploadPhotoModel
+    public class UploadPhotoRequestDto
     {
         public List<IFormFile> Files { get; set; }
         public bool Autosave { get; set; }

From c252b940604d83eba2a70963a3ef04d5c25cc14b Mon Sep 17 00:00:00 2001
From: MaksimChegulov <maksim.chegulov@onlyoffice.com>
Date: Mon, 28 Feb 2022 21:38:25 +0300
Subject: [PATCH 13/28] People: reorganize

---
 .../Server/ApiModels/{ => RequestDto}/GroupRequestDto.cs          | 0
 .../Server/ApiModels/{ => RequestDto}/LinkAccountRequestDto.cs    | 0
 .../Server/ApiModels/{ => RequestDto}/MemberRequestDto.cs         | 0
 .../ApiModels/{ => RequestDto}/RegisterPersonalUserRequestDto.cs  | 0
 .../Server/ApiModels/{ => RequestDto}/SetManagerRequestDto.cs     | 0
 .../Server/ApiModels/{ => RequestDto}/StartReassignRequestDto.cs  | 0
 .../Server/ApiModels/{ => RequestDto}/TerminateRequestDto.cs      | 0
 .../Server/ApiModels/{ => RequestDto}/ThumbnailsRequestDto.cs     | 0
 .../ApiModels/{ => RequestDto}/TransferGroupMembersRequestDto.cs  | 0
 .../Server/ApiModels/{ => RequestDto}/UpdateMembersRequestDto.cs  | 0
 .../Server/ApiModels/{ => RequestDto}/UploadPhotoRequestDto.cs    | 0
 .../Server/ApiModels/{ => ResponseDto}/AccountInfoDto.cs          | 0
 .../Server/ApiModels/{ => ResponseDto}/FileUploadResultDto.cs     | 0
 .../ASC.People/Server/ApiModels/{ => ResponseDto}/GroupDto.cs     | 0
 .../Server/ApiModels/{ => ResponseDto}/ThumbnailsDataDto.cs       | 0
 15 files changed, 0 insertions(+), 0 deletions(-)
 rename products/ASC.People/Server/ApiModels/{ => RequestDto}/GroupRequestDto.cs (100%)
 rename products/ASC.People/Server/ApiModels/{ => RequestDto}/LinkAccountRequestDto.cs (100%)
 rename products/ASC.People/Server/ApiModels/{ => RequestDto}/MemberRequestDto.cs (100%)
 rename products/ASC.People/Server/ApiModels/{ => RequestDto}/RegisterPersonalUserRequestDto.cs (100%)
 rename products/ASC.People/Server/ApiModels/{ => RequestDto}/SetManagerRequestDto.cs (100%)
 rename products/ASC.People/Server/ApiModels/{ => RequestDto}/StartReassignRequestDto.cs (100%)
 rename products/ASC.People/Server/ApiModels/{ => RequestDto}/TerminateRequestDto.cs (100%)
 rename products/ASC.People/Server/ApiModels/{ => RequestDto}/ThumbnailsRequestDto.cs (100%)
 rename products/ASC.People/Server/ApiModels/{ => RequestDto}/TransferGroupMembersRequestDto.cs (100%)
 rename products/ASC.People/Server/ApiModels/{ => RequestDto}/UpdateMembersRequestDto.cs (100%)
 rename products/ASC.People/Server/ApiModels/{ => RequestDto}/UploadPhotoRequestDto.cs (100%)
 rename products/ASC.People/Server/ApiModels/{ => ResponseDto}/AccountInfoDto.cs (100%)
 rename products/ASC.People/Server/ApiModels/{ => ResponseDto}/FileUploadResultDto.cs (100%)
 rename products/ASC.People/Server/ApiModels/{ => ResponseDto}/GroupDto.cs (100%)
 rename products/ASC.People/Server/ApiModels/{ => ResponseDto}/ThumbnailsDataDto.cs (100%)

diff --git a/products/ASC.People/Server/ApiModels/GroupRequestDto.cs b/products/ASC.People/Server/ApiModels/RequestDto/GroupRequestDto.cs
similarity index 100%
rename from products/ASC.People/Server/ApiModels/GroupRequestDto.cs
rename to products/ASC.People/Server/ApiModels/RequestDto/GroupRequestDto.cs
diff --git a/products/ASC.People/Server/ApiModels/LinkAccountRequestDto.cs b/products/ASC.People/Server/ApiModels/RequestDto/LinkAccountRequestDto.cs
similarity index 100%
rename from products/ASC.People/Server/ApiModels/LinkAccountRequestDto.cs
rename to products/ASC.People/Server/ApiModels/RequestDto/LinkAccountRequestDto.cs
diff --git a/products/ASC.People/Server/ApiModels/MemberRequestDto.cs b/products/ASC.People/Server/ApiModels/RequestDto/MemberRequestDto.cs
similarity index 100%
rename from products/ASC.People/Server/ApiModels/MemberRequestDto.cs
rename to products/ASC.People/Server/ApiModels/RequestDto/MemberRequestDto.cs
diff --git a/products/ASC.People/Server/ApiModels/RegisterPersonalUserRequestDto.cs b/products/ASC.People/Server/ApiModels/RequestDto/RegisterPersonalUserRequestDto.cs
similarity index 100%
rename from products/ASC.People/Server/ApiModels/RegisterPersonalUserRequestDto.cs
rename to products/ASC.People/Server/ApiModels/RequestDto/RegisterPersonalUserRequestDto.cs
diff --git a/products/ASC.People/Server/ApiModels/SetManagerRequestDto.cs b/products/ASC.People/Server/ApiModels/RequestDto/SetManagerRequestDto.cs
similarity index 100%
rename from products/ASC.People/Server/ApiModels/SetManagerRequestDto.cs
rename to products/ASC.People/Server/ApiModels/RequestDto/SetManagerRequestDto.cs
diff --git a/products/ASC.People/Server/ApiModels/StartReassignRequestDto.cs b/products/ASC.People/Server/ApiModels/RequestDto/StartReassignRequestDto.cs
similarity index 100%
rename from products/ASC.People/Server/ApiModels/StartReassignRequestDto.cs
rename to products/ASC.People/Server/ApiModels/RequestDto/StartReassignRequestDto.cs
diff --git a/products/ASC.People/Server/ApiModels/TerminateRequestDto.cs b/products/ASC.People/Server/ApiModels/RequestDto/TerminateRequestDto.cs
similarity index 100%
rename from products/ASC.People/Server/ApiModels/TerminateRequestDto.cs
rename to products/ASC.People/Server/ApiModels/RequestDto/TerminateRequestDto.cs
diff --git a/products/ASC.People/Server/ApiModels/ThumbnailsRequestDto.cs b/products/ASC.People/Server/ApiModels/RequestDto/ThumbnailsRequestDto.cs
similarity index 100%
rename from products/ASC.People/Server/ApiModels/ThumbnailsRequestDto.cs
rename to products/ASC.People/Server/ApiModels/RequestDto/ThumbnailsRequestDto.cs
diff --git a/products/ASC.People/Server/ApiModels/TransferGroupMembersRequestDto.cs b/products/ASC.People/Server/ApiModels/RequestDto/TransferGroupMembersRequestDto.cs
similarity index 100%
rename from products/ASC.People/Server/ApiModels/TransferGroupMembersRequestDto.cs
rename to products/ASC.People/Server/ApiModels/RequestDto/TransferGroupMembersRequestDto.cs
diff --git a/products/ASC.People/Server/ApiModels/UpdateMembersRequestDto.cs b/products/ASC.People/Server/ApiModels/RequestDto/UpdateMembersRequestDto.cs
similarity index 100%
rename from products/ASC.People/Server/ApiModels/UpdateMembersRequestDto.cs
rename to products/ASC.People/Server/ApiModels/RequestDto/UpdateMembersRequestDto.cs
diff --git a/products/ASC.People/Server/ApiModels/UploadPhotoRequestDto.cs b/products/ASC.People/Server/ApiModels/RequestDto/UploadPhotoRequestDto.cs
similarity index 100%
rename from products/ASC.People/Server/ApiModels/UploadPhotoRequestDto.cs
rename to products/ASC.People/Server/ApiModels/RequestDto/UploadPhotoRequestDto.cs
diff --git a/products/ASC.People/Server/ApiModels/AccountInfoDto.cs b/products/ASC.People/Server/ApiModels/ResponseDto/AccountInfoDto.cs
similarity index 100%
rename from products/ASC.People/Server/ApiModels/AccountInfoDto.cs
rename to products/ASC.People/Server/ApiModels/ResponseDto/AccountInfoDto.cs
diff --git a/products/ASC.People/Server/ApiModels/FileUploadResultDto.cs b/products/ASC.People/Server/ApiModels/ResponseDto/FileUploadResultDto.cs
similarity index 100%
rename from products/ASC.People/Server/ApiModels/FileUploadResultDto.cs
rename to products/ASC.People/Server/ApiModels/ResponseDto/FileUploadResultDto.cs
diff --git a/products/ASC.People/Server/ApiModels/GroupDto.cs b/products/ASC.People/Server/ApiModels/ResponseDto/GroupDto.cs
similarity index 100%
rename from products/ASC.People/Server/ApiModels/GroupDto.cs
rename to products/ASC.People/Server/ApiModels/ResponseDto/GroupDto.cs
diff --git a/products/ASC.People/Server/ApiModels/ThumbnailsDataDto.cs b/products/ASC.People/Server/ApiModels/ResponseDto/ThumbnailsDataDto.cs
similarity index 100%
rename from products/ASC.People/Server/ApiModels/ThumbnailsDataDto.cs
rename to products/ASC.People/Server/ApiModels/ResponseDto/ThumbnailsDataDto.cs

From 1665fe7bf69422660e9278f85d9791955d1c55cb Mon Sep 17 00:00:00 2001
From: MaksimChegulov <maksim.chegulov@onlyoffice.com>
Date: Mon, 28 Feb 2022 21:54:08 +0300
Subject: [PATCH 14/28] People: refactor

---
 .../ASC.Api.Core/Model/EmployeeWraperFull.cs  |   6 +-
 ...upWrapperSummary.cs => GroupSummaryDto.cs} | 106 +++++++++---------
 .../ASC.Files/Core/Model/FileShareWrapper.cs  |   2 +-
 .../ASC.People/Server/Api/GroupController.cs  |   8 +-
 .../ApiModels/RequestDto/GroupRequestDto.cs   |  13 +--
 .../RequestDto/LinkAccountRequestDto.cs       |  29 +++--
 .../ApiModels/RequestDto/MemberRequestDto.cs  |  54 +++++----
 .../RegisterPersonalUserRequestDto.cs         |  15 ++-
 .../RequestDto/SetManagerRequestDto.cs        |   9 +-
 .../RequestDto/StartReassignRequestDto.cs     |  13 +--
 .../RequestDto/TerminateRequestDto.cs         |   9 +-
 .../RequestDto/ThumbnailsRequestDto.cs        |  17 ++-
 .../TransferGroupMembersRequestDto.cs         |  11 +-
 .../RequestDto/UpdateMembersRequestDto.cs     |   9 +-
 .../RequestDto/UploadPhotoRequestDto.cs       |  11 +-
 .../ApiModels/ResponseDto/AccountInfoDto.cs   |  15 ++-
 .../ResponseDto/FileUploadResultDto.cs        |   2 +-
 .../Server/ApiModels/ResponseDto/GroupDto.cs  | 101 ++++++++---------
 .../ResponseDto/ThumbnailsDataDto.cs          |  81 ++++++-------
 products/ASC.People/Server/GlobalUsings.cs    |   3 +-
 .../Controllers/SettingsController.cs         |   2 +-
 web/ASC.Web.Api/Models/SecurityWrapper.cs     |   6 +-
 22 files changed, 247 insertions(+), 275 deletions(-)
 rename common/ASC.Api.Core/Model/{GroupWrapperSummary.cs => GroupSummaryDto.cs} (87%)

diff --git a/common/ASC.Api.Core/Model/EmployeeWraperFull.cs b/common/ASC.Api.Core/Model/EmployeeWraperFull.cs
index 5884eb4be3..9fb59741d6 100644
--- a/common/ASC.Api.Core/Model/EmployeeWraperFull.cs
+++ b/common/ASC.Api.Core/Model/EmployeeWraperFull.cs
@@ -39,7 +39,7 @@ public class EmployeeWraperFull : EmployeeWraper
     public ApiDateTime Terminated { get; set; }
     public string Department { get; set; }
     public ApiDateTime WorkFrom { get; set; }
-    public List<GroupWrapperSummary> Groups { get; set; }
+    public List<GroupSummaryDto> Groups { get; set; }
     public string Location { get; set; }
     public string Notes { get; set; }
     public string AvatarMax { get; set; }
@@ -71,7 +71,7 @@ public class EmployeeWraperFull : EmployeeWraper
             UserName = "Mike.Zanyatski",
             LastName = "Zanyatski",
             Title = "Manager",
-            Groups = new List<GroupWrapperSummary> { GroupWrapperSummary.GetSample() },
+            Groups = new List<GroupSummaryDto> { GroupSummaryDto.GetSample() },
             AvatarMedium = "url to medium avatar",
             Birthday = ApiDateTime.GetSample(),
             Department = "Marketing",
@@ -189,7 +189,7 @@ public class EmployeeWraperFullHelper : EmployeeWraperHelper
         if (_context.Check("groups") || _context.Check("department"))
         {
             var groups = UserManager.GetUserGroups(userInfo.ID)
-                .Select(x => new GroupWrapperSummary(x, UserManager))
+                .Select(x => new GroupSummaryDto(x, UserManager))
                 .ToList();
 
             if (groups.Count > 0)
diff --git a/common/ASC.Api.Core/Model/GroupWrapperSummary.cs b/common/ASC.Api.Core/Model/GroupSummaryDto.cs
similarity index 87%
rename from common/ASC.Api.Core/Model/GroupWrapperSummary.cs
rename to common/ASC.Api.Core/Model/GroupSummaryDto.cs
index e3d57de3b9..522b119358 100644
--- a/common/ASC.Api.Core/Model/GroupWrapperSummary.cs
+++ b/common/ASC.Api.Core/Model/GroupSummaryDto.cs
@@ -1,54 +1,54 @@
-/*
- *
- * (c) Copyright Ascensio System Limited 2010-2018
- *
- * This program is freeware. You can redistribute it and/or modify it under the terms of the GNU 
- * General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html). 
- * In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that 
- * Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
- *
- * THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
- * FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
- *
- * You can contact Ascensio System SIA by email at sales@onlyoffice.com
- *
- * The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display 
- * Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
- *
- * Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains 
- * relevant author attributions when distributing the software. If the display of the logo in its graphic 
- * form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE" 
- * in every copy of the program you distribute. 
- * Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
- *
-*/
-
-using GroupInfo = ASC.Core.Users.GroupInfo;
-
-namespace ASC.Web.Api.Models;
-
-public class GroupWrapperSummary
-{
-    public Guid Id { get; set; }
-    public string Name { get; set; }
-    public string Manager { get; set; }
-
-    protected GroupWrapperSummary() { }
-
-    public GroupWrapperSummary(GroupInfo group, UserManager userManager)
-    {
-        Id = group.ID;
-        Name = group.Name;
-        Manager = userManager.GetUsers(userManager.GetDepartmentManager(group.ID)).UserName;
-    }
-
-    public static GroupWrapperSummary GetSample()
-    {
-        return new GroupWrapperSummary 
-        {
-            Id = Guid.Empty, 
-            Manager = "Jake.Zazhitski", 
-            Name = "Group Name" 
-        };
-    }
+/*
+ *
+ * (c) Copyright Ascensio System Limited 2010-2018
+ *
+ * This program is freeware. You can redistribute it and/or modify it under the terms of the GNU 
+ * General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html). 
+ * In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that 
+ * Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
+ *
+ * THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
+ * FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
+ *
+ * You can contact Ascensio System SIA by email at sales@onlyoffice.com
+ *
+ * The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display 
+ * Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
+ *
+ * Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains 
+ * relevant author attributions when distributing the software. If the display of the logo in its graphic 
+ * form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE" 
+ * in every copy of the program you distribute. 
+ * Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
+ *
+*/
+
+using GroupInfo = ASC.Core.Users.GroupInfo;
+
+namespace ASC.Web.Api.Models;
+
+public class GroupSummaryDto
+{
+    public Guid Id { get; set; }
+    public string Name { get; set; }
+    public string Manager { get; set; }
+
+    protected GroupSummaryDto() { }
+
+    public GroupSummaryDto(GroupInfo group, UserManager userManager)
+    {
+        Id = group.ID;
+        Name = group.Name;
+        Manager = userManager.GetUsers(userManager.GetDepartmentManager(group.ID)).UserName;
+    }
+
+    public static GroupSummaryDto GetSample()
+    {
+        return new GroupSummaryDto 
+        {
+            Id = Guid.Empty, 
+            Manager = "Jake.Zazhitski", 
+            Name = "Group Name" 
+        };
+    }
 }
\ No newline at end of file
diff --git a/products/ASC.Files/Core/Model/FileShareWrapper.cs b/products/ASC.Files/Core/Model/FileShareWrapper.cs
index e36eba0f5f..7b77a8793a 100644
--- a/products/ASC.Files/Core/Model/FileShareWrapper.cs
+++ b/products/ASC.Files/Core/Model/FileShareWrapper.cs
@@ -117,7 +117,7 @@ namespace ASC.Api.Documents
                 else
                 {
                     //Shared to group
-                    result.SharedTo = new GroupWrapperSummary(UserManager.GetGroupInfo(aceWrapper.SubjectId), UserManager);
+                    result.SharedTo = new GroupSummaryDto(UserManager.GetGroupInfo(aceWrapper.SubjectId), UserManager);
                 }
             }
             else
diff --git a/products/ASC.People/Server/Api/GroupController.cs b/products/ASC.People/Server/Api/GroupController.cs
index 511e23a68b..9382b6594b 100644
--- a/products/ASC.People/Server/Api/GroupController.cs
+++ b/products/ASC.People/Server/Api/GroupController.cs
@@ -30,14 +30,14 @@
         }
 
         [Read]
-        public IEnumerable<GroupWrapperSummary> GetAll()
+        public IEnumerable<GroupSummaryDto> GetAll()
         {
             var result = UserManager.GetDepartments().Select(r => r);
             if (!string.IsNullOrEmpty(ApiContext.FilterValue))
             {
                 result = result.Where(r => r.Name.Contains(ApiContext.FilterValue, StringComparison.InvariantCultureIgnoreCase));
             }
-            return result.Select(x => new GroupWrapperSummary(x, UserManager));
+            return result.Select(x => new GroupSummaryDto(x, UserManager));
         }
 
         [Read("full")]
@@ -58,9 +58,9 @@
         }
 
         [Read("user/{userid}")]
-        public IEnumerable<GroupWrapperSummary> GetByUserId(Guid userid)
+        public IEnumerable<GroupSummaryDto> GetByUserId(Guid userid)
         {
-            return UserManager.GetUserGroups(userid).Select(x => new GroupWrapperSummary(x, UserManager));
+            return UserManager.GetUserGroups(userid).Select(x => new GroupSummaryDto(x, UserManager));
         }
 
         [Create]
diff --git a/products/ASC.People/Server/ApiModels/RequestDto/GroupRequestDto.cs b/products/ASC.People/Server/ApiModels/RequestDto/GroupRequestDto.cs
index 6053768964..703c8bf530 100644
--- a/products/ASC.People/Server/ApiModels/RequestDto/GroupRequestDto.cs
+++ b/products/ASC.People/Server/ApiModels/RequestDto/GroupRequestDto.cs
@@ -1,9 +1,8 @@
-namespace ASC.People.Models
+namespace ASC.People.ApiModels.RequestDto;
+
+public class GroupRequestDto
 {
-    public class GroupRequestDto
-    {
-        public Guid GroupManager { get; set; }
-        public string GroupName { get; set; }
-        public IEnumerable<Guid> Members { get; set; }
-    }
+    public Guid GroupManager { get; set; }
+    public string GroupName { get; set; }
+    public IEnumerable<Guid> Members { get; set; }
 }
diff --git a/products/ASC.People/Server/ApiModels/RequestDto/LinkAccountRequestDto.cs b/products/ASC.People/Server/ApiModels/RequestDto/LinkAccountRequestDto.cs
index b53dd01c40..056d6b2d37 100644
--- a/products/ASC.People/Server/ApiModels/RequestDto/LinkAccountRequestDto.cs
+++ b/products/ASC.People/Server/ApiModels/RequestDto/LinkAccountRequestDto.cs
@@ -1,16 +1,15 @@
-namespace ASC.People.Models
-{
-    public class LinkAccountRequestDto
-    {
-        public string SerializedProfile { get; set; }
-    }
-
-    public class SignupAccountRequestDto: LinkAccountRequestDto
-    {
-        public EmployeeType? EmplType { get; set; }
-        public string FirstName { get; set; }
-        public string LastName { get; set; }
-        public string Email { get; set; }
-        public string PasswordHash { get; set; }
-    }
+namespace ASC.People.ApiModels.RequestDto;
+
+public class LinkAccountRequestDto
+{
+    public string SerializedProfile { get; set; }
+}
+
+public class SignupAccountRequestDto : LinkAccountRequestDto
+{
+    public EmployeeType? EmplType { get; set; }
+    public string FirstName { get; set; }
+    public string LastName { get; set; }
+    public string Email { get; set; }
+    public string PasswordHash { get; set; }
 }
diff --git a/products/ASC.People/Server/ApiModels/RequestDto/MemberRequestDto.cs b/products/ASC.People/Server/ApiModels/RequestDto/MemberRequestDto.cs
index f152bfc1d3..d2e118eb51 100644
--- a/products/ASC.People/Server/ApiModels/RequestDto/MemberRequestDto.cs
+++ b/products/ASC.People/Server/ApiModels/RequestDto/MemberRequestDto.cs
@@ -1,30 +1,28 @@
-namespace ASC.People.Models
+namespace ASC.People.ApiModels.RequestDto;
+
+public class MemberRequestDto
 {
-    public class MemberRequestDto
-    {
-        public bool IsVisitor { get; set; }
-        public string Email { get; set; }
-        public string Firstname { get; set; }
-
-        public string Lastname { get; set; }
-        public Guid[] Department { get; set; }
-        public string Title { get; set; }
-        public string Location { get; set; }
-        public string Sex { get; set; }
-        public ApiDateTime Birthday { get; set; }
-        public ApiDateTime Worksfrom { get; set; }
-        public string Comment { get; set; }
-        public IEnumerable<Contact> Contacts { get; set; }
-        public string Files { get; set; }
-        public string Password { get; set; }
-        public string PasswordHash { get; set; }
-        public bool FromInviteLink { get; set; }
-    }
-
-    public class UpdateMemberRequestDto : MemberRequestDto
-    {
-        public string UserId { get; set; }
-        public bool? Disable { get; set; }
-        public string CultureName { get; set; }
-    }
+    public bool IsVisitor { get; set; }
+    public string Email { get; set; }
+    public string Firstname { get; set; }
+    public string Lastname { get; set; }
+    public Guid[] Department { get; set; }
+    public string Title { get; set; }
+    public string Location { get; set; }
+    public string Sex { get; set; }
+    public ApiDateTime Birthday { get; set; }
+    public ApiDateTime Worksfrom { get; set; }
+    public string Comment { get; set; }
+    public IEnumerable<Contact> Contacts { get; set; }
+    public string Files { get; set; }
+    public string Password { get; set; }
+    public string PasswordHash { get; set; }
+    public bool FromInviteLink { get; set; }
+}
+
+public class UpdateMemberRequestDto : MemberRequestDto
+{
+    public string UserId { get; set; }
+    public bool? Disable { get; set; }
+    public string CultureName { get; set; }
 }
diff --git a/products/ASC.People/Server/ApiModels/RequestDto/RegisterPersonalUserRequestDto.cs b/products/ASC.People/Server/ApiModels/RequestDto/RegisterPersonalUserRequestDto.cs
index 93152cfc04..cf6886cfbe 100644
--- a/products/ASC.People/Server/ApiModels/RequestDto/RegisterPersonalUserRequestDto.cs
+++ b/products/ASC.People/Server/ApiModels/RequestDto/RegisterPersonalUserRequestDto.cs
@@ -1,10 +1,9 @@
-namespace ASC.People.Models
+namespace ASC.People.ApiModels.RequestDto;
+
+public class RegisterPersonalUserRequestDto
 {
-    public class RegisterPersonalUserRequestDto
-    {
-        public string Email { get; set; }
-        public string Lang { get; set; }
-        public bool Spam { get; set; }
-        public string RecaptchaResponse { get; set; }
-    }
+    public string Email { get; set; }
+    public string Lang { get; set; }
+    public bool Spam { get; set; }
+    public string RecaptchaResponse { get; set; }
 }
diff --git a/products/ASC.People/Server/ApiModels/RequestDto/SetManagerRequestDto.cs b/products/ASC.People/Server/ApiModels/RequestDto/SetManagerRequestDto.cs
index 8cd17494cc..a5806ee572 100644
--- a/products/ASC.People/Server/ApiModels/RequestDto/SetManagerRequestDto.cs
+++ b/products/ASC.People/Server/ApiModels/RequestDto/SetManagerRequestDto.cs
@@ -1,7 +1,6 @@
-namespace ASC.People.Models
+namespace ASC.People.ApiModels.RequestDto;
+
+public class SetManagerRequestDto
 {
-    public class SetManagerRequestDto
-    {
-        public Guid UserId { get; set; }
-    }
+    public Guid UserId { get; set; }
 }
diff --git a/products/ASC.People/Server/ApiModels/RequestDto/StartReassignRequestDto.cs b/products/ASC.People/Server/ApiModels/RequestDto/StartReassignRequestDto.cs
index 70bdcb635a..ea747ebd10 100644
--- a/products/ASC.People/Server/ApiModels/RequestDto/StartReassignRequestDto.cs
+++ b/products/ASC.People/Server/ApiModels/RequestDto/StartReassignRequestDto.cs
@@ -1,9 +1,8 @@
-namespace ASC.People.Models
+namespace ASC.People.ApiModels.RequestDto;
+
+public class StartReassignRequestDto
 {
-    public class StartReassignRequestDto
-    {
-        public Guid FromUserId { get; set; }
-        public Guid ToUserId { get; set; }
-        public bool DeleteProfile { get; set; }
-    }
+    public Guid FromUserId { get; set; }
+    public Guid ToUserId { get; set; }
+    public bool DeleteProfile { get; set; }
 }
diff --git a/products/ASC.People/Server/ApiModels/RequestDto/TerminateRequestDto.cs b/products/ASC.People/Server/ApiModels/RequestDto/TerminateRequestDto.cs
index 8abda99faa..877afecce8 100644
--- a/products/ASC.People/Server/ApiModels/RequestDto/TerminateRequestDto.cs
+++ b/products/ASC.People/Server/ApiModels/RequestDto/TerminateRequestDto.cs
@@ -1,7 +1,6 @@
-namespace ASC.People.Models
+namespace ASC.People.ApiModels.RequestDto;
+
+public class TerminateRequestDto
 {
-    public class TerminateRequestDto
-    {
-        public Guid UserId { get; set; }
-    }
+    public Guid UserId { get; set; }
 }
diff --git a/products/ASC.People/Server/ApiModels/RequestDto/ThumbnailsRequestDto.cs b/products/ASC.People/Server/ApiModels/RequestDto/ThumbnailsRequestDto.cs
index 0b652cff08..1acdb3ef18 100644
--- a/products/ASC.People/Server/ApiModels/RequestDto/ThumbnailsRequestDto.cs
+++ b/products/ASC.People/Server/ApiModels/RequestDto/ThumbnailsRequestDto.cs
@@ -1,11 +1,10 @@
-namespace ASC.People.Models
+namespace ASC.People.ApiModels.RequestDto;
+
+public class ThumbnailsRequestDto
 {
-    public class ThumbnailsRequestDto
-    {
-        public string TmpFile { get; set; }
-        public int X { get; set; }
-        public int Y { get; set; }
-        public int Width { get; set; }
-        public int Height { get; set; }
-    }
+    public string TmpFile { get; set; }
+    public int X { get; set; }
+    public int Y { get; set; }
+    public int Width { get; set; }
+    public int Height { get; set; }
 }
diff --git a/products/ASC.People/Server/ApiModels/RequestDto/TransferGroupMembersRequestDto.cs b/products/ASC.People/Server/ApiModels/RequestDto/TransferGroupMembersRequestDto.cs
index 8a0037de9c..32b080c638 100644
--- a/products/ASC.People/Server/ApiModels/RequestDto/TransferGroupMembersRequestDto.cs
+++ b/products/ASC.People/Server/ApiModels/RequestDto/TransferGroupMembersRequestDto.cs
@@ -1,8 +1,7 @@
-namespace ASC.People.Models
+namespace ASC.People.ApiModels.RequestDto;
+
+public class TransferGroupMembersRequestDto
 {
-    public class TransferGroupMembersRequestDto
-    {
-        public Guid GroupId { get; set; }
-        public Guid NewGroupId { get; set; }
-    }
+    public Guid GroupId { get; set; }
+    public Guid NewGroupId { get; set; }
 }
diff --git a/products/ASC.People/Server/ApiModels/RequestDto/UpdateMembersRequestDto.cs b/products/ASC.People/Server/ApiModels/RequestDto/UpdateMembersRequestDto.cs
index 1fcd772a9d..6022c0f76a 100644
--- a/products/ASC.People/Server/ApiModels/RequestDto/UpdateMembersRequestDto.cs
+++ b/products/ASC.People/Server/ApiModels/RequestDto/UpdateMembersRequestDto.cs
@@ -1,7 +1,6 @@
-namespace ASC.People.Models
+namespace ASC.People.ApiModels.RequestDto;
+
+public class UpdateMembersRequestDto
 {
-    public class UpdateMembersRequestDto
-    {
-        public IEnumerable<Guid> UserIds { get; set; }
-    }
+    public IEnumerable<Guid> UserIds { get; set; }
 }
diff --git a/products/ASC.People/Server/ApiModels/RequestDto/UploadPhotoRequestDto.cs b/products/ASC.People/Server/ApiModels/RequestDto/UploadPhotoRequestDto.cs
index ea943915ce..b9266cfa10 100644
--- a/products/ASC.People/Server/ApiModels/RequestDto/UploadPhotoRequestDto.cs
+++ b/products/ASC.People/Server/ApiModels/RequestDto/UploadPhotoRequestDto.cs
@@ -1,8 +1,7 @@
-namespace ASC.People.Models
+namespace ASC.People.ApiModels.RequestDto;
+
+public class UploadPhotoRequestDto
 {
-    public class UploadPhotoRequestDto
-    {
-        public List<IFormFile> Files { get; set; }
-        public bool Autosave { get; set; }
-    }
+    public List<IFormFile> Files { get; set; }
+    public bool Autosave { get; set; }
 }
diff --git a/products/ASC.People/Server/ApiModels/ResponseDto/AccountInfoDto.cs b/products/ASC.People/Server/ApiModels/ResponseDto/AccountInfoDto.cs
index 73a835be66..3b36c78ad7 100644
--- a/products/ASC.People/Server/ApiModels/ResponseDto/AccountInfoDto.cs
+++ b/products/ASC.People/Server/ApiModels/ResponseDto/AccountInfoDto.cs
@@ -1,10 +1,9 @@
-namespace ASC.People.Models
+namespace ASC.People.ApiModels.ResponseDto;
+
+public class AccountInfoDto
 {
-    public class AccountInfoDto
-    {
-        public string Provider { get; set; }
-        public string Url { get; set; }
-        public bool Linked { get; set; }
-        public string Class { get; set; }
-    }
+    public string Provider { get; set; }
+    public string Url { get; set; }
+    public bool Linked { get; set; }
+    public string Class { get; set; }
 }
diff --git a/products/ASC.People/Server/ApiModels/ResponseDto/FileUploadResultDto.cs b/products/ASC.People/Server/ApiModels/ResponseDto/FileUploadResultDto.cs
index 711e560635..94eb6074ab 100644
--- a/products/ASC.People/Server/ApiModels/ResponseDto/FileUploadResultDto.cs
+++ b/products/ASC.People/Server/ApiModels/ResponseDto/FileUploadResultDto.cs
@@ -1,4 +1,4 @@
-namespace ASC.People.ApiModels;
+namespace ASC.People.ApiModels.ResponseDto;
 
 public class FileUploadResultDto
 {
diff --git a/products/ASC.People/Server/ApiModels/ResponseDto/GroupDto.cs b/products/ASC.People/Server/ApiModels/ResponseDto/GroupDto.cs
index 54f2c3a73c..55e47a6990 100644
--- a/products/ASC.People/Server/ApiModels/ResponseDto/GroupDto.cs
+++ b/products/ASC.People/Server/ApiModels/ResponseDto/GroupDto.cs
@@ -23,67 +23,60 @@
  *
 */
 
-namespace ASC.Web.Api.Models
+namespace ASC.People.ApiModels.ResponseDto;
+
+public class GroupDto
 {
-    public class GroupDto
+    public string Description { get; set; }
+    public string Name { get; set; }
+    public Guid? Parent { get; set; }
+    public Guid Category { get; set; }
+    public Guid Id { get; set; }
+    public EmployeeWraper Manager { get; set; }
+    public List<EmployeeWraper> Members { get; set; }
+
+    public static GroupDto GetSample()
     {
-        public string Description { get; set; }
-
-        public string Name { get; set; }
-
-        public Guid? Parent { get; set; }
-
-        public Guid Category { get; set; }
-
-        public Guid Id { get; set; }
-
-        public EmployeeWraper Manager { get; set; }
-
-        public List<EmployeeWraper> Members { get; set; }
-
-        public static GroupDto GetSample()
+        return new GroupDto
         {
-            return new GroupDto
-            {
-                Id = Guid.NewGuid(),
-                Manager = EmployeeWraper.GetSample(),
-                Category = Guid.NewGuid(),
-                Name = "Sample group",
-                Parent = Guid.NewGuid(),
-                Members = new List<EmployeeWraper> { EmployeeWraper.GetSample() }
-            };
-        }
+            Id = Guid.NewGuid(),
+            Manager = EmployeeWraper.GetSample(),
+            Category = Guid.NewGuid(),
+            Name = "Sample group",
+            Parent = Guid.NewGuid(),
+            Members = new List<EmployeeWraper> { EmployeeWraper.GetSample() }
+        };
+    }
+}
+
+[Scope]
+public class GroupWraperFullHelper
+{
+    private UserManager UserManager { get; }
+    private EmployeeWraperHelper EmployeeWraperHelper { get; }
+
+    public GroupWraperFullHelper(UserManager userManager, EmployeeWraperHelper employeeWraperHelper)
+    {
+        UserManager = userManager;
+        EmployeeWraperHelper = employeeWraperHelper;
     }
 
-    [Scope]
-    public class GroupWraperFullHelper
+    public GroupDto Get(GroupInfo group, bool includeMembers)
     {
-        private UserManager UserManager { get; }
-        private EmployeeWraperHelper EmployeeWraperHelper { get; }
-
-        public GroupWraperFullHelper(UserManager userManager, EmployeeWraperHelper employeeWraperHelper)
+        var result = new GroupDto
         {
-            UserManager = userManager;
-            EmployeeWraperHelper = employeeWraperHelper;
+            Id = group.ID,
+            Category = group.CategoryID,
+            Parent = group.Parent != null ? group.Parent.ID : Guid.Empty,
+            Name = group.Name,
+            Manager = EmployeeWraperHelper.Get(UserManager.GetUsers(UserManager.GetDepartmentManager(group.ID)))
+        };
+
+        if (includeMembers)
+        {
+            result.Members = new List<EmployeeWraper>(UserManager.GetUsersByGroup(group.ID).Select(EmployeeWraperHelper.Get));
         }
 
-        public GroupDto Get(GroupInfo group, bool includeMembers)
-        {
-            var result = new GroupDto
-            {
-                Id = group.ID,
-                Category = group.CategoryID,
-                Parent = group.Parent != null ? group.Parent.ID : Guid.Empty,
-                Name = group.Name,
-                Manager = EmployeeWraperHelper.Get(UserManager.GetUsers(UserManager.GetDepartmentManager(group.ID)))
-            };
-
-            if (includeMembers)
-            {
-                result.Members = new List<EmployeeWraper>(UserManager.GetUsersByGroup(group.ID).Select(EmployeeWraperHelper.Get));
-            }
-
-            return result;
-        }
+        return result;
     }
-}
\ No newline at end of file
+}
diff --git a/products/ASC.People/Server/ApiModels/ResponseDto/ThumbnailsDataDto.cs b/products/ASC.People/Server/ApiModels/ResponseDto/ThumbnailsDataDto.cs
index be73b4a7c0..e76a4480f5 100644
--- a/products/ASC.People/Server/ApiModels/ResponseDto/ThumbnailsDataDto.cs
+++ b/products/ASC.People/Server/ApiModels/ResponseDto/ThumbnailsDataDto.cs
@@ -23,48 +23,39 @@
  *
 */
 
-namespace ASC.Web.Api.Models
-{
-    public class ThumbnailsDataDto
-    {
-        public ThumbnailsDataDto(Guid userId, UserPhotoManager userPhotoManager)
-        {
-            Original = userPhotoManager.GetPhotoAbsoluteWebPath(userId);
-            Retina = userPhotoManager.GetRetinaPhotoURL(userId);
-            Max = userPhotoManager.GetMaxPhotoURL(userId);
-            Big = userPhotoManager.GetBigPhotoURL(userId);
-            Medium = userPhotoManager.GetMediumPhotoURL(userId);
-            Small = userPhotoManager.GetSmallPhotoURL(userId);
-        }
-
-        private ThumbnailsDataDto()
-        {
-        }
-
-        public string Original { get; set; }
-
-        public string Retina { get; set; }
-
-        public string Max { get; set; }
-
-        public string Big { get; set; }
-
-        public string Medium { get; set; }
-
-        public string Small { get; set; }
-
-
-        public static ThumbnailsDataDto GetSample()
-        {
-            return new ThumbnailsDataDto
-            {
-                Original = "default_user_photo_size_1280-1280.png",
-                Retina = "default_user_photo_size_360-360.png",
-                Max = "default_user_photo_size_200-200.png",
-                Big = "default_user_photo_size_82-82.png",
-                Medium = "default_user_photo_size_48-48.png",
-                Small = "default_user_photo_size_32-32.png",
-            };
-        }
-    }
-}
\ No newline at end of file
+namespace ASC.People.ApiModels.ResponseDto;
+
+public class ThumbnailsDataDto
+{
+    public ThumbnailsDataDto(Guid userId, UserPhotoManager userPhotoManager)
+    {
+        Original = userPhotoManager.GetPhotoAbsoluteWebPath(userId);
+        Retina = userPhotoManager.GetRetinaPhotoURL(userId);
+        Max = userPhotoManager.GetMaxPhotoURL(userId);
+        Big = userPhotoManager.GetBigPhotoURL(userId);
+        Medium = userPhotoManager.GetMediumPhotoURL(userId);
+        Small = userPhotoManager.GetSmallPhotoURL(userId);
+    }
+
+    private ThumbnailsDataDto() { }
+
+    public string Original { get; set; }
+    public string Retina { get; set; }
+    public string Max { get; set; }
+    public string Big { get; set; }
+    public string Medium { get; set; }
+    public string Small { get; set; }
+
+    public static ThumbnailsDataDto GetSample()
+    {
+        return new ThumbnailsDataDto
+        {
+            Original = "default_user_photo_size_1280-1280.png",
+            Retina = "default_user_photo_size_360-360.png",
+            Max = "default_user_photo_size_200-200.png",
+            Big = "default_user_photo_size_82-82.png",
+            Medium = "default_user_photo_size_48-48.png",
+            Small = "default_user_photo_size_32-32.png",
+        };
+    }
+}
diff --git a/products/ASC.People/Server/GlobalUsings.cs b/products/ASC.People/Server/GlobalUsings.cs
index 1a920c070a..ea02bd72cf 100644
--- a/products/ASC.People/Server/GlobalUsings.cs
+++ b/products/ASC.People/Server/GlobalUsings.cs
@@ -29,7 +29,8 @@ global using ASC.FederatedLogin.Profile;
 global using ASC.MessagingSystem.Core;
 global using ASC.MessagingSystem.Models;
 global using ASC.People;
-global using ASC.People.Models;
+global using ASC.People.ApiModels.RequestDto;
+global using ASC.People.ApiModels.ResponseDto;
 global using ASC.People.Resources;
 global using ASC.Security.Cryptography;
 global using ASC.Web.Api.Models;
diff --git a/web/ASC.Web.Api/Controllers/SettingsController.cs b/web/ASC.Web.Api/Controllers/SettingsController.cs
index dbbf010764..d5d788225d 100644
--- a/web/ASC.Web.Api/Controllers/SettingsController.cs
+++ b/web/ASC.Web.Api/Controllers/SettingsController.cs
@@ -789,7 +789,7 @@ namespace ASC.Api.Settings
                           WebItemId = i.WebItemId,
                           Enabled = i.Enabled,
                           Users = i.Users.Select(EmployeeWraperHelper.Get),
-                          Groups = i.Groups.Select(g => new GroupWrapperSummary(g, UserManager)),
+                          Groups = i.Groups.Select(g => new GroupSummaryDto(g, UserManager)),
                           IsSubItem = subItemList.Contains(i.WebItemId),
                       }).ToList();
         }
diff --git a/web/ASC.Web.Api/Models/SecurityWrapper.cs b/web/ASC.Web.Api/Models/SecurityWrapper.cs
index 510ed28392..9a04ef52fd 100644
--- a/web/ASC.Web.Api/Models/SecurityWrapper.cs
+++ b/web/ASC.Web.Api/Models/SecurityWrapper.cs
@@ -31,7 +31,7 @@ namespace ASC.Api.Settings
 
         public IEnumerable<EmployeeWraper> Users { get; set; }
 
-        public IEnumerable<GroupWrapperSummary> Groups { get; set; }
+        public IEnumerable<GroupSummaryDto> Groups { get; set; }
 
         public bool Enabled { get; set; }
 
@@ -44,9 +44,9 @@ namespace ASC.Api.Settings
                 WebItemId = Guid.Empty.ToString(),
                 Enabled = true,
                 IsSubItem = false,
-                Groups = new List<GroupWrapperSummary>
+                Groups = new List<GroupSummaryDto>
                         {
-                            GroupWrapperSummary.GetSample()
+                            GroupSummaryDto.GetSample()
                         },
                 Users = new List<EmployeeWraper>
                         {

From c887362ea3f1ab0e9148d669d36494680b7503e3 Mon Sep 17 00:00:00 2001
From: MaksimChegulov <maksim.chegulov@onlyoffice.com>
Date: Mon, 28 Feb 2022 22:23:39 +0300
Subject: [PATCH 15/28] People: separated people controller

---
 .../{EmployeeWraper.cs => EmployeeDto.cs}     |  230 +--
 ...ployeeWraperFull.cs => EmployeeFullDto.cs} |  512 +++----
 .../ASC.CRM/Server/Api/ContactsController.cs  |    4 +-
 .../Server/ApiModels/ResponsesDto/CasesDto.cs |    6 +-
 .../ApiModels/ResponsesDto/ContactDto.cs      |    8 +-
 .../ApiModels/ResponsesDto/InvoiceDto.cs      |    4 +-
 .../ApiModels/ResponsesDto/InvoiceItemDto.cs  |    2 +-
 .../ApiModels/ResponsesDto/InvoiceTaxDto.cs   |    2 +-
 .../ApiModels/ResponsesDto/OpportunityDto.cs  |   10 +-
 .../ResponsesDto/RelationshipEventDto.cs      |    4 +-
 .../Server/ApiModels/ResponsesDto/TaskDto.cs  |   12 +-
 .../ResponsesDto/TaskTemplateContainerDto.cs  |    4 +-
 .../ApiModels/ResponsesDto/VoipCallDto.cs     |    2 +-
 .../ASC.Files/Core/Model/FileEntryWrapper.cs  |    4 +-
 .../Server/Api/BaseApiController.cs           |   41 +
 .../Server/Api/BasePeopleController.cs        |   93 ++
 .../Server/Api/ContactsController.cs          |  138 ++
 .../Server/Api/NotificationController.cs      |   71 +
 .../ASC.People/Server/Api/PeopleController.cs |  108 +-
 .../ASC.People/Server/Api/PhotoController.cs  |  270 ++++
 .../Server/Api/ReassignController.cs          |  100 ++
 .../Server/Api/RemoveUserDataController.cs    |  103 ++
 .../Server/Api/ThirdpartyController.cs        |  363 +++++
 .../ASC.People/Server/Api/UserController.cs   | 1312 +++++++++++++++++
 .../Server/ApiModels/ResponseDto/GroupDto.cs  |   10 +-
 products/ASC.People/Server/GlobalUsings.cs    |    8 +-
 .../Controllers/SettingsController.cs         |    2 +-
 web/ASC.Web.Api/Models/SecurityWrapper.cs     |    6 +-
 28 files changed, 2960 insertions(+), 469 deletions(-)
 rename common/ASC.Api.Core/Model/{EmployeeWraper.cs => EmployeeDto.cs} (89%)
 rename common/ASC.Api.Core/Model/{EmployeeWraperFull.cs => EmployeeFullDto.cs} (93%)
 create mode 100644 products/ASC.People/Server/Api/BaseApiController.cs
 create mode 100644 products/ASC.People/Server/Api/BasePeopleController.cs
 create mode 100644 products/ASC.People/Server/Api/ContactsController.cs
 create mode 100644 products/ASC.People/Server/Api/NotificationController.cs
 create mode 100644 products/ASC.People/Server/Api/PhotoController.cs
 create mode 100644 products/ASC.People/Server/Api/ReassignController.cs
 create mode 100644 products/ASC.People/Server/Api/RemoveUserDataController.cs
 create mode 100644 products/ASC.People/Server/Api/ThirdpartyController.cs
 create mode 100644 products/ASC.People/Server/Api/UserController.cs

diff --git a/common/ASC.Api.Core/Model/EmployeeWraper.cs b/common/ASC.Api.Core/Model/EmployeeDto.cs
similarity index 89%
rename from common/ASC.Api.Core/Model/EmployeeWraper.cs
rename to common/ASC.Api.Core/Model/EmployeeDto.cs
index be55d466de..d3f368b108 100644
--- a/common/ASC.Api.Core/Model/EmployeeWraper.cs
+++ b/common/ASC.Api.Core/Model/EmployeeDto.cs
@@ -1,116 +1,116 @@
-/*
- *
- * (c) Copyright Ascensio System Limited 2010-2018
- *
- * This program is freeware. You can redistribute it and/or modify it under the terms of the GNU 
- * General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html). 
- * In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that 
- * Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
- *
- * THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
- * FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
- *
- * You can contact Ascensio System SIA by email at sales@onlyoffice.com
- *
- * The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display 
- * Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
- *
- * Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains 
- * relevant author attributions when distributing the software. If the display of the logo in its graphic 
- * form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE" 
- * in every copy of the program you distribute. 
- * Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
- *
-*/
-
-namespace ASC.Web.Api.Models;
-
-public class EmployeeWraper
-{
-    public Guid Id { get; set; }
-    public string DisplayName { get; set; }
-    public string Title { get; set; }
-    public string AvatarSmall { get; set; }
-    public string ProfileUrl { get; set; }
-
-    public static EmployeeWraper GetSample()
-    {
-        return new EmployeeWraper
-        {
-            Id = Guid.Empty,
-            DisplayName = "Mike Zanyatski",
-            Title = "Manager",
-            AvatarSmall = "url to small avatar",
-        };
-    }
-}
-
-[Scope]
-public class EmployeeWraperHelper
-{
-    protected UserPhotoManager UserPhotoManager { get; }
-    protected UserManager UserManager { get; }
-
-    private readonly ApiContext _httpContext;
-    private readonly DisplayUserSettingsHelper _displayUserSettingsHelper;
-    private readonly CommonLinkUtility _commonLinkUtility;
-
-    public EmployeeWraperHelper(
-        ApiContext httpContext,
-        DisplayUserSettingsHelper displayUserSettingsHelper,
-        UserPhotoManager userPhotoManager,
-        CommonLinkUtility commonLinkUtility,
-        UserManager userManager)
-    {
-        UserPhotoManager = userPhotoManager;
-        UserManager = userManager;
-        _httpContext = httpContext;
-        _displayUserSettingsHelper = displayUserSettingsHelper;
-        _commonLinkUtility = commonLinkUtility;
-
-    }
-
-    public EmployeeWraper Get(UserInfo userInfo)
-    {
-        return Init(new EmployeeWraper(), userInfo);
-    }
-
-    public EmployeeWraper Get(Guid userId)
-    {
-        try
-        {
-            return Get(UserManager.GetUsers(userId));
-        }
-        catch (Exception)
-        {
-            return Get(Constants.LostUser);
-        }
-    }
-
-    protected EmployeeWraper Init(EmployeeWraper result, UserInfo userInfo)
-    {
-        result.Id = userInfo.ID;
-        result.DisplayName = _displayUserSettingsHelper.GetFullUserName(userInfo);
-
-        if (!string.IsNullOrEmpty(userInfo.Title))
-        {
-            result.Title = userInfo.Title;
-        }
-
-        var userInfoLM = userInfo.LastModified.GetHashCode();
-
-        if (_httpContext.Check("avatarSmall"))
-        {
-            result.AvatarSmall = UserPhotoManager.GetSmallPhotoURL(userInfo.ID, out var isdef) 
-                + (isdef ? "" : $"?_={userInfoLM}");
-        }     
-
-        if (result.Id != Guid.Empty)
-        {
-            var profileUrl = _commonLinkUtility.GetUserProfile(userInfo, false);
-            result.ProfileUrl = _commonLinkUtility.GetFullAbsolutePath(profileUrl);
-        }
-
-        return result;
-    }
+/*
+ *
+ * (c) Copyright Ascensio System Limited 2010-2018
+ *
+ * This program is freeware. You can redistribute it and/or modify it under the terms of the GNU 
+ * General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html). 
+ * In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that 
+ * Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
+ *
+ * THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
+ * FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
+ *
+ * You can contact Ascensio System SIA by email at sales@onlyoffice.com
+ *
+ * The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display 
+ * Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
+ *
+ * Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains 
+ * relevant author attributions when distributing the software. If the display of the logo in its graphic 
+ * form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE" 
+ * in every copy of the program you distribute. 
+ * Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
+ *
+*/
+
+namespace ASC.Web.Api.Models;
+
+public class EmployeeDto
+{
+    public Guid Id { get; set; }
+    public string DisplayName { get; set; }
+    public string Title { get; set; }
+    public string AvatarSmall { get; set; }
+    public string ProfileUrl { get; set; }
+
+    public static EmployeeDto GetSample()
+    {
+        return new EmployeeDto
+        {
+            Id = Guid.Empty,
+            DisplayName = "Mike Zanyatski",
+            Title = "Manager",
+            AvatarSmall = "url to small avatar",
+        };
+    }
+}
+
+[Scope]
+public class EmployeeWraperHelper
+{
+    protected UserPhotoManager UserPhotoManager { get; }
+    protected UserManager UserManager { get; }
+
+    private readonly ApiContext _httpContext;
+    private readonly DisplayUserSettingsHelper _displayUserSettingsHelper;
+    private readonly CommonLinkUtility _commonLinkUtility;
+
+    public EmployeeWraperHelper(
+        ApiContext httpContext,
+        DisplayUserSettingsHelper displayUserSettingsHelper,
+        UserPhotoManager userPhotoManager,
+        CommonLinkUtility commonLinkUtility,
+        UserManager userManager)
+    {
+        UserPhotoManager = userPhotoManager;
+        UserManager = userManager;
+        _httpContext = httpContext;
+        _displayUserSettingsHelper = displayUserSettingsHelper;
+        _commonLinkUtility = commonLinkUtility;
+
+    }
+
+    public EmployeeDto Get(UserInfo userInfo)
+    {
+        return Init(new EmployeeDto(), userInfo);
+    }
+
+    public EmployeeDto Get(Guid userId)
+    {
+        try
+        {
+            return Get(UserManager.GetUsers(userId));
+        }
+        catch (Exception)
+        {
+            return Get(Constants.LostUser);
+        }
+    }
+
+    protected EmployeeDto Init(EmployeeDto result, UserInfo userInfo)
+    {
+        result.Id = userInfo.ID;
+        result.DisplayName = _displayUserSettingsHelper.GetFullUserName(userInfo);
+
+        if (!string.IsNullOrEmpty(userInfo.Title))
+        {
+            result.Title = userInfo.Title;
+        }
+
+        var userInfoLM = userInfo.LastModified.GetHashCode();
+
+        if (_httpContext.Check("avatarSmall"))
+        {
+            result.AvatarSmall = UserPhotoManager.GetSmallPhotoURL(userInfo.ID, out var isdef) 
+                + (isdef ? "" : $"?_={userInfoLM}");
+        }     
+
+        if (result.Id != Guid.Empty)
+        {
+            var profileUrl = _commonLinkUtility.GetUserProfile(userInfo, false);
+            result.ProfileUrl = _commonLinkUtility.GetFullAbsolutePath(profileUrl);
+        }
+
+        return result;
+    }
 }
\ No newline at end of file
diff --git a/common/ASC.Api.Core/Model/EmployeeWraperFull.cs b/common/ASC.Api.Core/Model/EmployeeFullDto.cs
similarity index 93%
rename from common/ASC.Api.Core/Model/EmployeeWraperFull.cs
rename to common/ASC.Api.Core/Model/EmployeeFullDto.cs
index 9fb59741d6..2d3356b7f2 100644
--- a/common/ASC.Api.Core/Model/EmployeeWraperFull.cs
+++ b/common/ASC.Api.Core/Model/EmployeeFullDto.cs
@@ -1,257 +1,257 @@
-/*
- *
- * (c) Copyright Ascensio System Limited 2010-2018
- *
- * This program is freeware. You can redistribute it and/or modify it under the terms of the GNU 
- * General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html). 
- * In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that 
- * Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
- *
- * THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
- * FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
- *
- * You can contact Ascensio System SIA by email at sales@onlyoffice.com
- *
- * The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display 
- * Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
- *
- * Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains 
- * relevant author attributions when distributing the software. If the display of the logo in its graphic 
- * form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE" 
- * in every copy of the program you distribute. 
- * Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
- *
-*/
-
-namespace ASC.Web.Api.Models;
-
-public class EmployeeWraperFull : EmployeeWraper
-{
-    public string FirstName { get; set; }
-    public string LastName { get; set; }
-    public string UserName { get; set; }
-    public string Email { get; set; }
-    public List<Contact> Contacts { get; set; }
-    public ApiDateTime Birthday { get; set; }
-    public string Sex { get; set; }
-    public EmployeeStatus Status { get; set; }
-    public EmployeeActivationStatus ActivationStatus { get; set; }
-    public ApiDateTime Terminated { get; set; }
-    public string Department { get; set; }
-    public ApiDateTime WorkFrom { get; set; }
-    public List<GroupSummaryDto> Groups { get; set; }
-    public string Location { get; set; }
-    public string Notes { get; set; }
-    public string AvatarMax { get; set; }
-    public string AvatarMedium { get; set; }
-    public string Avatar { get; set; }
-    public bool IsAdmin { get; set; }
-    public bool IsLDAP { get; set; }
-    public List<string> ListAdminModules { get; set; }
-    public bool IsOwner { get; set; }
-    public bool IsVisitor { get; set; }
-    public string CultureName { get; set; }
-    public string MobilePhone { get; set; }
-    public MobilePhoneActivationStatus MobilePhoneActivationStatus { get; set; }
-    public bool IsSSO { get; set; }
-
-    public new static EmployeeWraperFull GetSample()
-    {
-        return new EmployeeWraperFull
-        {
-            Avatar = "url to big avatar",
-            AvatarSmall = "url to small avatar",
-            AvatarMax = "url to max avatar",
-            Contacts = new List<Contact> { Contact.GetSample() },
-            Email = "my@gmail.com",
-            FirstName = "Mike",
-            Id = Guid.Empty,
-            IsAdmin = false,
-            ListAdminModules = new List<string> { "projects", "crm" },
-            UserName = "Mike.Zanyatski",
-            LastName = "Zanyatski",
-            Title = "Manager",
-            Groups = new List<GroupSummaryDto> { GroupSummaryDto.GetSample() },
-            AvatarMedium = "url to medium avatar",
-            Birthday = ApiDateTime.GetSample(),
-            Department = "Marketing",
-            Location = "Palo Alto",
-            Notes = "Notes to worker",
-            Sex = "male",
-            Status = EmployeeStatus.Active,
-            WorkFrom = ApiDateTime.GetSample(),
-            Terminated = ApiDateTime.GetSample(),
-            CultureName = "en-EN",
-            IsLDAP = false,
-            IsSSO = false
-        };
-    }
-}
-
-[Scope]
-public class EmployeeWraperFullHelper : EmployeeWraperHelper
-{
-    private readonly ApiContext _context;
-    private readonly WebItemSecurity _webItemSecurity;
-    private readonly ApiDateTimeHelper _apiDateTimeHelper;
-
-    public EmployeeWraperFullHelper(
-        ApiContext context,
-        UserManager userManager,
-        UserPhotoManager userPhotoManager,
-        WebItemSecurity webItemSecurity,
-        CommonLinkUtility commonLinkUtility,
-        DisplayUserSettingsHelper displayUserSettingsHelper,
-        ApiDateTimeHelper apiDateTimeHelper)
-    : base(context, displayUserSettingsHelper, userPhotoManager, commonLinkUtility, userManager)
-    {
-        _context = context;
-        _webItemSecurity = webItemSecurity;
-        _apiDateTimeHelper = apiDateTimeHelper;
-    }
-
-    public static Expression<Func<User, UserInfo>> GetExpression(ApiContext apiContext)
-    {
-        if (apiContext?.Fields == null)
-        {
-            return null;
-        }
-
-        var newExpr = Expression.New(typeof(UserInfo));
-
-        //i => new UserInfo { ID = i.id } 
-        var parameter = Expression.Parameter(typeof(User), "i");
-        var bindExprs = new List<MemberAssignment>();
-
-        if (apiContext.Check("Id"))
-        {
-            bindExprs.Add(Expression.Bind(typeof(UserInfo).GetProperty("ID"), 
-                Expression.Property(parameter, typeof(User).GetProperty("Id"))));
-        }
-
-        var body = Expression.MemberInit(newExpr, bindExprs);
-        var lambda = Expression.Lambda<Func<User, UserInfo>>(body, parameter);
-
-        return lambda;
-    }
-
-    public EmployeeWraperFull GetFull(UserInfo userInfo)
-    {
-        var result = new EmployeeWraperFull
-        {
-            UserName = userInfo.UserName,
-            FirstName = userInfo.FirstName,
-            LastName = userInfo.LastName,
-            Birthday = _apiDateTimeHelper.Get(userInfo.BirthDate),
-            Status = userInfo.Status,
-            ActivationStatus = userInfo.ActivationStatus & ~EmployeeActivationStatus.AutoGenerated,
-            Terminated = _apiDateTimeHelper.Get(userInfo.TerminatedDate),
-            WorkFrom = _apiDateTimeHelper.Get(userInfo.WorkFromDate),
-            Email = userInfo.Email,
-            IsVisitor = userInfo.IsVisitor(UserManager),
-            IsAdmin = userInfo.IsAdmin(UserManager),
-            IsOwner = userInfo.IsOwner(_context.Tenant),
-            IsLDAP = userInfo.IsLDAP(),
-            IsSSO = userInfo.IsSSO()
-        };
-
-        Init(result, userInfo);
-
-        if (userInfo.Sex.HasValue)
-        {
-            result.Sex = userInfo.Sex.Value ? "male" : "female";
-        }
-
-        if (!string.IsNullOrEmpty(userInfo.Location))
-        {
-            result.Location = userInfo.Location;
-        }
-
-        if (!string.IsNullOrEmpty(userInfo.Notes))
-        {
-            result.Notes = userInfo.Notes;
-        }
-
-        if (!string.IsNullOrEmpty(userInfo.MobilePhone))
-        {
-            result.MobilePhone = userInfo.MobilePhone;
-        }
-
-        result.MobilePhoneActivationStatus = userInfo.MobilePhoneActivationStatus;
-
-        if (!string.IsNullOrEmpty(userInfo.CultureName))
-        {
-            result.CultureName = userInfo.CultureName;
-        }
-
-        FillConacts(result, userInfo);
-
-        if (_context.Check("groups") || _context.Check("department"))
-        {
-            var groups = UserManager.GetUserGroups(userInfo.ID)
-                .Select(x => new GroupSummaryDto(x, UserManager))
-                .ToList();
-
-            if (groups.Count > 0)
-            {
-                result.Groups = groups;
-                result.Department = string.Join(", ", result.Groups.Select(d => d.Name.HtmlEncode()));
-            }
-            else
-            {
-                result.Department = "";
-            }
-        }
-
-        var userInfoLM = userInfo.LastModified.GetHashCode();
-
-        if (_context.Check("avatarMax"))
-        {
-            result.AvatarMax = UserPhotoManager.GetMaxPhotoURL(userInfo.ID, out var isdef) + (isdef ? "" : $"?_={userInfoLM}");
-        }
-
-        if (_context.Check("avatarMedium"))
-        {
-            result.AvatarMedium = UserPhotoManager.GetMediumPhotoURL(userInfo.ID, out var isdef) + (isdef ? "" : $"?_={userInfoLM}");
-        }
-
-        if (_context.Check("avatar"))
-        {
-            result.Avatar = UserPhotoManager.GetBigPhotoURL(userInfo.ID, out var isdef) + (isdef ? "" : $"?_={userInfoLM}");
-        }
-
-        if (_context.Check("listAdminModules"))
-        {
-            var listAdminModules = userInfo.GetListAdminModules(_webItemSecurity);
-                if (listAdminModules.Count > 0)
-            {
-                result.ListAdminModules = listAdminModules;
-            }
-        }
-
-        return result;
-    }
-
-    private void FillConacts(EmployeeWraperFull employeeWraperFull, UserInfo userInfo)
-    {
-        if (userInfo.ContactsList == null)
-        {
-            return;
-        }
-
-        var contacts = new List<Contact>();
-
-        for (var i = 0; i < userInfo.ContactsList.Count; i += 2)
-        {
-            if (i + 1 < userInfo.ContactsList.Count)
-            {
-                contacts.Add(new Contact(userInfo.ContactsList[i], userInfo.ContactsList[i + 1]));
-            }
-        }
-
-            if (contacts.Count > 0)
-        {
-            employeeWraperFull.Contacts = contacts;
-        }
-    }
+/*
+ *
+ * (c) Copyright Ascensio System Limited 2010-2018
+ *
+ * This program is freeware. You can redistribute it and/or modify it under the terms of the GNU 
+ * General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html). 
+ * In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that 
+ * Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
+ *
+ * THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
+ * FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
+ *
+ * You can contact Ascensio System SIA by email at sales@onlyoffice.com
+ *
+ * The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display 
+ * Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
+ *
+ * Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains 
+ * relevant author attributions when distributing the software. If the display of the logo in its graphic 
+ * form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE" 
+ * in every copy of the program you distribute. 
+ * Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
+ *
+*/
+
+namespace ASC.Web.Api.Models;
+
+public class EmployeeFullDto : EmployeeDto
+{
+    public string FirstName { get; set; }
+    public string LastName { get; set; }
+    public string UserName { get; set; }
+    public string Email { get; set; }
+    public List<Contact> Contacts { get; set; }
+    public ApiDateTime Birthday { get; set; }
+    public string Sex { get; set; }
+    public EmployeeStatus Status { get; set; }
+    public EmployeeActivationStatus ActivationStatus { get; set; }
+    public ApiDateTime Terminated { get; set; }
+    public string Department { get; set; }
+    public ApiDateTime WorkFrom { get; set; }
+    public List<GroupSummaryDto> Groups { get; set; }
+    public string Location { get; set; }
+    public string Notes { get; set; }
+    public string AvatarMax { get; set; }
+    public string AvatarMedium { get; set; }
+    public string Avatar { get; set; }
+    public bool IsAdmin { get; set; }
+    public bool IsLDAP { get; set; }
+    public List<string> ListAdminModules { get; set; }
+    public bool IsOwner { get; set; }
+    public bool IsVisitor { get; set; }
+    public string CultureName { get; set; }
+    public string MobilePhone { get; set; }
+    public MobilePhoneActivationStatus MobilePhoneActivationStatus { get; set; }
+    public bool IsSSO { get; set; }
+
+    public new static EmployeeFullDto GetSample()
+    {
+        return new EmployeeFullDto
+        {
+            Avatar = "url to big avatar",
+            AvatarSmall = "url to small avatar",
+            AvatarMax = "url to max avatar",
+            Contacts = new List<Contact> { Contact.GetSample() },
+            Email = "my@gmail.com",
+            FirstName = "Mike",
+            Id = Guid.Empty,
+            IsAdmin = false,
+            ListAdminModules = new List<string> { "projects", "crm" },
+            UserName = "Mike.Zanyatski",
+            LastName = "Zanyatski",
+            Title = "Manager",
+            Groups = new List<GroupSummaryDto> { GroupSummaryDto.GetSample() },
+            AvatarMedium = "url to medium avatar",
+            Birthday = ApiDateTime.GetSample(),
+            Department = "Marketing",
+            Location = "Palo Alto",
+            Notes = "Notes to worker",
+            Sex = "male",
+            Status = EmployeeStatus.Active,
+            WorkFrom = ApiDateTime.GetSample(),
+            Terminated = ApiDateTime.GetSample(),
+            CultureName = "en-EN",
+            IsLDAP = false,
+            IsSSO = false
+        };
+    }
+}
+
+[Scope]
+public class EmployeeWraperFullHelper : EmployeeWraperHelper
+{
+    private readonly ApiContext _context;
+    private readonly WebItemSecurity _webItemSecurity;
+    private readonly ApiDateTimeHelper _apiDateTimeHelper;
+
+    public EmployeeWraperFullHelper(
+        ApiContext context,
+        UserManager userManager,
+        UserPhotoManager userPhotoManager,
+        WebItemSecurity webItemSecurity,
+        CommonLinkUtility commonLinkUtility,
+        DisplayUserSettingsHelper displayUserSettingsHelper,
+        ApiDateTimeHelper apiDateTimeHelper)
+    : base(context, displayUserSettingsHelper, userPhotoManager, commonLinkUtility, userManager)
+    {
+        _context = context;
+        _webItemSecurity = webItemSecurity;
+        _apiDateTimeHelper = apiDateTimeHelper;
+    }
+
+    public static Expression<Func<User, UserInfo>> GetExpression(ApiContext apiContext)
+    {
+        if (apiContext?.Fields == null)
+        {
+            return null;
+        }
+
+        var newExpr = Expression.New(typeof(UserInfo));
+
+        //i => new UserInfo { ID = i.id } 
+        var parameter = Expression.Parameter(typeof(User), "i");
+        var bindExprs = new List<MemberAssignment>();
+
+        if (apiContext.Check("Id"))
+        {
+            bindExprs.Add(Expression.Bind(typeof(UserInfo).GetProperty("ID"), 
+                Expression.Property(parameter, typeof(User).GetProperty("Id"))));
+        }
+
+        var body = Expression.MemberInit(newExpr, bindExprs);
+        var lambda = Expression.Lambda<Func<User, UserInfo>>(body, parameter);
+
+        return lambda;
+    }
+
+    public EmployeeFullDto GetFull(UserInfo userInfo)
+    {
+        var result = new EmployeeFullDto
+        {
+            UserName = userInfo.UserName,
+            FirstName = userInfo.FirstName,
+            LastName = userInfo.LastName,
+            Birthday = _apiDateTimeHelper.Get(userInfo.BirthDate),
+            Status = userInfo.Status,
+            ActivationStatus = userInfo.ActivationStatus & ~EmployeeActivationStatus.AutoGenerated,
+            Terminated = _apiDateTimeHelper.Get(userInfo.TerminatedDate),
+            WorkFrom = _apiDateTimeHelper.Get(userInfo.WorkFromDate),
+            Email = userInfo.Email,
+            IsVisitor = userInfo.IsVisitor(UserManager),
+            IsAdmin = userInfo.IsAdmin(UserManager),
+            IsOwner = userInfo.IsOwner(_context.Tenant),
+            IsLDAP = userInfo.IsLDAP(),
+            IsSSO = userInfo.IsSSO()
+        };
+
+        Init(result, userInfo);
+
+        if (userInfo.Sex.HasValue)
+        {
+            result.Sex = userInfo.Sex.Value ? "male" : "female";
+        }
+
+        if (!string.IsNullOrEmpty(userInfo.Location))
+        {
+            result.Location = userInfo.Location;
+        }
+
+        if (!string.IsNullOrEmpty(userInfo.Notes))
+        {
+            result.Notes = userInfo.Notes;
+        }
+
+        if (!string.IsNullOrEmpty(userInfo.MobilePhone))
+        {
+            result.MobilePhone = userInfo.MobilePhone;
+        }
+
+        result.MobilePhoneActivationStatus = userInfo.MobilePhoneActivationStatus;
+
+        if (!string.IsNullOrEmpty(userInfo.CultureName))
+        {
+            result.CultureName = userInfo.CultureName;
+        }
+
+        FillConacts(result, userInfo);
+
+        if (_context.Check("groups") || _context.Check("department"))
+        {
+            var groups = UserManager.GetUserGroups(userInfo.ID)
+                .Select(x => new GroupSummaryDto(x, UserManager))
+                .ToList();
+
+            if (groups.Count > 0)
+            {
+                result.Groups = groups;
+                result.Department = string.Join(", ", result.Groups.Select(d => d.Name.HtmlEncode()));
+            }
+            else
+            {
+                result.Department = "";
+            }
+        }
+
+        var userInfoLM = userInfo.LastModified.GetHashCode();
+
+        if (_context.Check("avatarMax"))
+        {
+            result.AvatarMax = UserPhotoManager.GetMaxPhotoURL(userInfo.ID, out var isdef) + (isdef ? "" : $"?_={userInfoLM}");
+        }
+
+        if (_context.Check("avatarMedium"))
+        {
+            result.AvatarMedium = UserPhotoManager.GetMediumPhotoURL(userInfo.ID, out var isdef) + (isdef ? "" : $"?_={userInfoLM}");
+        }
+
+        if (_context.Check("avatar"))
+        {
+            result.Avatar = UserPhotoManager.GetBigPhotoURL(userInfo.ID, out var isdef) + (isdef ? "" : $"?_={userInfoLM}");
+        }
+
+        if (_context.Check("listAdminModules"))
+        {
+            var listAdminModules = userInfo.GetListAdminModules(_webItemSecurity);
+                if (listAdminModules.Count > 0)
+            {
+                result.ListAdminModules = listAdminModules;
+            }
+        }
+
+        return result;
+    }
+
+    private void FillConacts(EmployeeFullDto employeeWraperFull, UserInfo userInfo)
+    {
+        if (userInfo.ContactsList == null)
+        {
+            return;
+        }
+
+        var contacts = new List<Contact>();
+
+        for (var i = 0; i < userInfo.ContactsList.Count; i += 2)
+        {
+            if (i + 1 < userInfo.ContactsList.Count)
+            {
+                contacts.Add(new Contact(userInfo.ContactsList[i], userInfo.ContactsList[i + 1]));
+            }
+        }
+
+            if (contacts.Count > 0)
+        {
+            employeeWraperFull.Contacts = contacts;
+        }
+    }
 }
\ No newline at end of file
diff --git a/products/ASC.CRM/Server/Api/ContactsController.cs b/products/ASC.CRM/Server/Api/ContactsController.cs
index 3fa3d7876b..b2801c179a 100644
--- a/products/ASC.CRM/Server/Api/ContactsController.cs
+++ b/products/ASC.CRM/Server/Api/ContactsController.cs
@@ -1409,7 +1409,7 @@ namespace ASC.CRM.Api
         ///<exception cref="SecurityException"></exception>
         /// <returns>User list</returns>
         [Read(@"contact/{contactid:int}/access")]
-        public IEnumerable<EmployeeWraper> GetContactAccessList(int contactid)
+        public IEnumerable<EmployeeDto> GetContactAccessList(int contactid)
         {
             if (contactid <= 0) throw new ArgumentException();
 
@@ -1422,7 +1422,7 @@ namespace ASC.CRM.Api
             return _crmSecurity.IsPrivate(contact)
                        ? _crmSecurity.GetAccessSubjectTo(contact)
                                     .Select(item => _employeeWraperHelper.Get(item.Key))
-                       : new List<EmployeeWraper>();
+                       : new List<EmployeeDto>();
         }
 
         /// <summary>
diff --git a/products/ASC.CRM/Server/ApiModels/ResponsesDto/CasesDto.cs b/products/ASC.CRM/Server/ApiModels/ResponsesDto/CasesDto.cs
index e284215a22..bca1f4610a 100644
--- a/products/ASC.CRM/Server/ApiModels/ResponsesDto/CasesDto.cs
+++ b/products/ASC.CRM/Server/ApiModels/ResponsesDto/CasesDto.cs
@@ -46,12 +46,12 @@ namespace ASC.CRM.ApiModels
 
         public int Id { get; set; }
         public IEnumerable<ContactBaseDto> Members { get; set; }
-        public EmployeeWraper CreateBy { get; set; }
+        public EmployeeDto CreateBy { get; set; }
         public ApiDateTime Created { get; set; }
         public String Title { get; set; }
         public bool IsClosed { get; set; }
         public bool IsPrivate { get; set; }
-        public IEnumerable<EmployeeWraper> AccessList { get; set; }
+        public IEnumerable<EmployeeDto> AccessList { get; set; }
         public bool CanEdit { get; set; }
         public IEnumerable<CustomFieldBaseDto> CustomFields { get; set; }
         public static CasesDto GetSample()
@@ -61,7 +61,7 @@ namespace ASC.CRM.ApiModels
                 IsClosed = false,
                 Title = "Exhibition organization",
                 Created = ApiDateTime.GetSample(),
-                CreateBy = EmployeeWraper.GetSample(),
+                CreateBy = EmployeeDto.GetSample(),
                 IsPrivate = false,
                 CustomFields = new[] { CustomFieldBaseDto.GetSample() },
                 CanEdit = true
diff --git a/products/ASC.CRM/Server/ApiModels/ResponsesDto/ContactDto.cs b/products/ASC.CRM/Server/ApiModels/ResponsesDto/ContactDto.cs
index ffa3dc7f06..3f65497480 100644
--- a/products/ASC.CRM/Server/ApiModels/ResponsesDto/ContactDto.cs
+++ b/products/ASC.CRM/Server/ApiModels/ResponsesDto/ContactDto.cs
@@ -61,7 +61,7 @@ namespace ASC.CRM.ApiModels
                 Title = "Programmer",
                 About = "",
                 Created = ApiDateTime.GetSample(),
-                CreateBy = EmployeeWraper.GetSample(),
+                CreateBy = EmployeeDto.GetSample(),
                 ShareType = ShareType.None
             };
         }
@@ -118,7 +118,7 @@ namespace ASC.CRM.ApiModels
         }
 
         public IEnumerable<Address> Addresses { get; set; }
-        public EmployeeWraper CreateBy { get; set; }
+        public EmployeeDto CreateBy { get; set; }
         public ApiDateTime Created { get; set; }
         public String About { get; set; }
         public String Industry { get; set; }
@@ -142,7 +142,7 @@ namespace ASC.CRM.ApiModels
                 Title = "Programmer",
                 About = "",
                 Created = ApiDateTime.GetSample(),
-                CreateBy = EmployeeWraper.GetSample(),
+                CreateBy = EmployeeDto.GetSample(),
                 CommonData = new List<ContactInfoDto>() { ContactInfoDto.GetSample() },
                 CustomFields = new List<CustomFieldBaseDto>() { CustomFieldBaseDto.GetSample() },
                 ShareType = ShareType.None,
@@ -226,7 +226,7 @@ namespace ASC.CRM.ApiModels
         public String MediumFotoUrl { get; set; }
         public String DisplayName { get; set; }
         public bool IsCompany { get; set; }
-        public IEnumerable<EmployeeWraper> AccessList { get; set; }
+        public IEnumerable<EmployeeDto> AccessList { get; set; }
         public bool IsPrivate { get; set; }
         public bool IsShared { get; set; }
         public ShareType ShareType { get; set; }
diff --git a/products/ASC.CRM/Server/ApiModels/ResponsesDto/InvoiceDto.cs b/products/ASC.CRM/Server/ApiModels/ResponsesDto/InvoiceDto.cs
index f8c9a02983..de063d5727 100644
--- a/products/ASC.CRM/Server/ApiModels/ResponsesDto/InvoiceDto.cs
+++ b/products/ASC.CRM/Server/ApiModels/ResponsesDto/InvoiceDto.cs
@@ -59,7 +59,7 @@ namespace ASC.CRM.ApiModels
         public string Description { get; set; }
         public int FileID { get; set; }
         public ApiDateTime CreateOn { get; set; }
-        public EmployeeWraper CreateBy { get; set; }
+        public EmployeeDto CreateBy { get; set; }
         public decimal Cost { get; set; }
         public bool CanEdit { get; set; }
         public bool CanDelete { get; set; }
@@ -94,7 +94,7 @@ namespace ASC.CRM.ApiModels
                 Description = string.Empty,
                 FileID = -1,
                 CreateOn = ApiDateTime.GetSample(),
-                CreateBy = EmployeeWraper.GetSample(),
+                CreateBy = EmployeeDto.GetSample(),
                 CanEdit = true,
                 CanDelete = true,
                 Cost = 0,
diff --git a/products/ASC.CRM/Server/ApiModels/ResponsesDto/InvoiceItemDto.cs b/products/ASC.CRM/Server/ApiModels/ResponsesDto/InvoiceItemDto.cs
index fadf9a6fcb..d5b92accee 100644
--- a/products/ASC.CRM/Server/ApiModels/ResponsesDto/InvoiceItemDto.cs
+++ b/products/ASC.CRM/Server/ApiModels/ResponsesDto/InvoiceItemDto.cs
@@ -50,7 +50,7 @@ namespace ASC.CRM.ApiModels
         public InvoiceTaxDto InvoiceTax1 { get; set; }
         public InvoiceTaxDto InvoiceTax2 { get; set; }
         public ApiDateTime CreateOn { get; set; }
-        public EmployeeWraper CreateBy { get; set; }
+        public EmployeeDto CreateBy { get; set; }
         public bool CanEdit { get; set; }
         public bool CanDelete { get; set; }
 
diff --git a/products/ASC.CRM/Server/ApiModels/ResponsesDto/InvoiceTaxDto.cs b/products/ASC.CRM/Server/ApiModels/ResponsesDto/InvoiceTaxDto.cs
index c76812501b..b48e1141ff 100644
--- a/products/ASC.CRM/Server/ApiModels/ResponsesDto/InvoiceTaxDto.cs
+++ b/products/ASC.CRM/Server/ApiModels/ResponsesDto/InvoiceTaxDto.cs
@@ -58,7 +58,7 @@ namespace ASC.CRM.ApiModels
         public string Description { get; set; }
         public decimal Rate { get; set; }
         public ApiDateTime CreateOn { get; set; }
-        public EmployeeWraper CreateBy { get; set; }
+        public EmployeeDto CreateBy { get; set; }
         public bool CanEdit { get; set; }
         public bool CanDelete { get; set; }
 
diff --git a/products/ASC.CRM/Server/ApiModels/ResponsesDto/OpportunityDto.cs b/products/ASC.CRM/Server/ApiModels/ResponsesDto/OpportunityDto.cs
index f04d8c47f1..d5ae73ce6b 100644
--- a/products/ASC.CRM/Server/ApiModels/ResponsesDto/OpportunityDto.cs
+++ b/products/ASC.CRM/Server/ApiModels/ResponsesDto/OpportunityDto.cs
@@ -50,13 +50,13 @@ namespace ASC.CRM.ApiModels
         }
 
         public int Id { get; set; }
-        public EmployeeWraper CreateBy { get; set; }
+        public EmployeeDto CreateBy { get; set; }
         public ApiDateTime Created { get; set; }
         public IEnumerable<ContactBaseDto> Members { get; set; }
         public ContactBaseDto Contact { get; set; }
         public String Title { get; set; }
         public String Description { get; set; }
-        public EmployeeWraper Responsible { get; set; }
+        public EmployeeDto Responsible { get; set; }
         public BidType BidType { get; set; }
         public decimal BidValue { get; set; }
         public CurrencyInfoDto BidCurrency { get; set; }
@@ -67,7 +67,7 @@ namespace ASC.CRM.ApiModels
         public ApiDateTime ExpectedCloseDate { get; set; }
 
         public bool IsPrivate { get; set; }
-        public IEnumerable<EmployeeWraper> AccessList { get; set; }
+        public IEnumerable<EmployeeDto> AccessList { get; set; }
         public bool CanEdit { get; set; }
         public IEnumerable<CustomFieldBaseDto> CustomFields { get; set; }
 
@@ -75,9 +75,9 @@ namespace ASC.CRM.ApiModels
         {
             return new OpportunityDto
             {
-                CreateBy = EmployeeWraper.GetSample(),
+                CreateBy = EmployeeDto.GetSample(),
                 Created = ApiDateTime.GetSample(),
-                Responsible = EmployeeWraper.GetSample(),
+                Responsible = EmployeeDto.GetSample(),
                 Title = "Hotel catalogue",
                 Description = "",
                 ExpectedCloseDate = ApiDateTime.GetSample(),
diff --git a/products/ASC.CRM/Server/ApiModels/ResponsesDto/RelationshipEventDto.cs b/products/ASC.CRM/Server/ApiModels/ResponsesDto/RelationshipEventDto.cs
index 1e14183460..711e5cb6ca 100644
--- a/products/ASC.CRM/Server/ApiModels/ResponsesDto/RelationshipEventDto.cs
+++ b/products/ASC.CRM/Server/ApiModels/ResponsesDto/RelationshipEventDto.cs
@@ -113,7 +113,7 @@ namespace ASC.CRM.ApiModels
         }
 
         public int Id { get; set; }
-        public EmployeeWraper CreateBy { get; set; }
+        public EmployeeDto CreateBy { get; set; }
 
         public ApiDateTime Created { get; set; }
         public String Content { get; set; }
@@ -131,7 +131,7 @@ namespace ASC.CRM.ApiModels
                 Entity = EntityDto.GetSample(),
                 Contact = ContactBaseDto.GetSample(),
                 Created = ApiDateTime.GetSample(),
-                CreateBy = EmployeeWraper.GetSample(),
+                CreateBy = EmployeeDto.GetSample(),
                 Files = new[] { FileWrapper<int>.GetSample() },
                 Content = @"Agreed to meet at lunch and discuss the client commercial offer"
             };
diff --git a/products/ASC.CRM/Server/ApiModels/ResponsesDto/TaskDto.cs b/products/ASC.CRM/Server/ApiModels/ResponsesDto/TaskDto.cs
index 69c095f77a..8de34e58d8 100644
--- a/products/ASC.CRM/Server/ApiModels/ResponsesDto/TaskDto.cs
+++ b/products/ASC.CRM/Server/ApiModels/ResponsesDto/TaskDto.cs
@@ -44,14 +44,14 @@ namespace ASC.CRM.ApiModels
     public class TaskDto : IMapFrom<Task>
     {
         public int Id { get; set; }
-        public EmployeeWraper CreateBy { get; set; }
+        public EmployeeDto CreateBy { get; set; }
         public ApiDateTime Created { get; set; }
         public ContactBaseWithEmailDto Contact { get; set; }
         public string Title { get; set; }
         public string Description { get; set; }
         public ApiDateTime DeadLine { get; set; }
         public int AlertValue { get; set; }
-        public EmployeeWraper Responsible { get; set; }
+        public EmployeeDto Responsible { get; set; }
         public bool IsClosed { get; set; }
         public TaskCategoryBaseDto Category { get; set; }
         public EntityDto Entity { get; set; }
@@ -61,10 +61,10 @@ namespace ASC.CRM.ApiModels
             return new TaskDto
             {
                 Created = ApiDateTime.GetSample(),
-                CreateBy = EmployeeWraper.GetSample(),
+                CreateBy = EmployeeDto.GetSample(),
                 DeadLine = ApiDateTime.GetSample(),
                 IsClosed = false,
-                Responsible = EmployeeWraper.GetSample(),
+                Responsible = EmployeeDto.GetSample(),
                 //                 Category = TaskCategoryBaseDto.GetSample(),
                 CanEdit = true,
                 Title = "Send a commercial offer",
@@ -84,7 +84,7 @@ namespace ASC.CRM.ApiModels
         public String Description { get; set; }
         public ApiDateTime DeadLine { get; set; }
         public int AlertValue { get; set; }
-        public EmployeeWraper Responsible { get; set; }
+        public EmployeeDto Responsible { get; set; }
         public bool IsClosed { get; set; }
         public TaskCategoryBaseDto Category { get; set; }
         public EntityDto Entity { get; set; }
@@ -95,7 +95,7 @@ namespace ASC.CRM.ApiModels
             {
                 DeadLine = ApiDateTime.GetSample(),
                 IsClosed = false,
-                Responsible = EmployeeWraper.GetSample(),
+                Responsible = EmployeeDto.GetSample(),
                 Category = TaskCategoryBaseDto.GetSample(),
                 CanEdit = true,
                 Title = "Send a commercial offer",
diff --git a/products/ASC.CRM/Server/ApiModels/ResponsesDto/TaskTemplateContainerDto.cs b/products/ASC.CRM/Server/ApiModels/ResponsesDto/TaskTemplateContainerDto.cs
index c1b8dd6080..3f4db1945d 100644
--- a/products/ASC.CRM/Server/ApiModels/ResponsesDto/TaskTemplateContainerDto.cs
+++ b/products/ASC.CRM/Server/ApiModels/ResponsesDto/TaskTemplateContainerDto.cs
@@ -68,7 +68,7 @@ namespace ASC.CRM.ApiModels
         public int ContainerID { get; set; }
         public String Title { get; set; }
         public String Description { get; set; }
-        public EmployeeWraper Responsible { get; set; }
+        public EmployeeDto Responsible { get; set; }
         public TaskCategoryDto Category { get; set; }
         public bool isNotify { get; set; }
         public long OffsetTicks { get; set; }
@@ -81,7 +81,7 @@ namespace ASC.CRM.ApiModels
                 Title = "Send an Email",
                 Category = TaskCategoryDto.GetSample(),
                 isNotify = true,
-                Responsible = EmployeeWraper.GetSample(),
+                Responsible = EmployeeDto.GetSample(),
                 ContainerID = 12,
                 DeadLineIsFixed = false,
                 OffsetTicks = TimeSpan.FromDays(10).Ticks,
diff --git a/products/ASC.CRM/Server/ApiModels/ResponsesDto/VoipCallDto.cs b/products/ASC.CRM/Server/ApiModels/ResponsesDto/VoipCallDto.cs
index c59c04e12c..2253ae8932 100644
--- a/products/ASC.CRM/Server/ApiModels/ResponsesDto/VoipCallDto.cs
+++ b/products/ASC.CRM/Server/ApiModels/ResponsesDto/VoipCallDto.cs
@@ -40,7 +40,7 @@ namespace ASC.CRM.ApiModels
         public string From { get; set; }
         public string To { get; set; }
         public VoipCallStatus? Status { get; set; }
-        public EmployeeWraper AnsweredBy { get; set; }
+        public EmployeeDto AnsweredBy { get; set; }
         public ApiDateTime DialDate { get; set; }
         public int DialDuration { get; set; }
         public decimal Cost { get; set; }
diff --git a/products/ASC.Files/Core/Model/FileEntryWrapper.cs b/products/ASC.Files/Core/Model/FileEntryWrapper.cs
index 83bc0dd91e..978886d461 100644
--- a/products/ASC.Files/Core/Model/FileEntryWrapper.cs
+++ b/products/ASC.Files/Core/Model/FileEntryWrapper.cs
@@ -47,7 +47,7 @@ namespace ASC.Api.Documents
 
         /// <summary>
         /// </summary>
-        public EmployeeWraper CreatedBy { get; set; }
+        public EmployeeDto CreatedBy { get; set; }
 
         private ApiDateTime _updated;
 
@@ -68,7 +68,7 @@ namespace ASC.Api.Documents
 
         /// <summary>
         /// </summary>
-        public EmployeeWraper UpdatedBy { get; set; }
+        public EmployeeDto UpdatedBy { get; set; }
 
         /// <summary>
         /// </summary>
diff --git a/products/ASC.People/Server/Api/BaseApiController.cs b/products/ASC.People/Server/Api/BaseApiController.cs
new file mode 100644
index 0000000000..23f2027757
--- /dev/null
+++ b/products/ASC.People/Server/Api/BaseApiController.cs
@@ -0,0 +1,41 @@
+using SecurityContext = ASC.Core.SecurityContext;
+
+namespace ASC.People.Api;
+
+[Scope(Additional = typeof(BaseLoginProviderExtension))]
+[DefaultRoute]
+[ApiController]
+[ControllerName("people")]
+public class BaseApiController : ControllerBase
+{
+    protected Tenant Tenant => ApiContext.Tenant;
+
+    protected readonly UserManager UserManager;
+    protected readonly AuthContext AuthContext;
+    protected readonly ApiContext ApiContext;
+    protected readonly PermissionContext PermissionContext;
+    protected readonly SecurityContext SecurityContext;
+    protected readonly MessageService MessageService;
+    protected readonly MessageTarget MessageTarget;
+    protected readonly StudioNotifyService StudioNotifyService;
+
+    protected BaseApiController(
+        UserManager userManager,
+        AuthContext authContext,
+        ApiContext apiContext,
+        PermissionContext permissionContext,
+        SecurityContext securityContext,
+        MessageService messageService,
+        MessageTarget messageTarget,
+        StudioNotifyService studioNotifyService)
+    {
+        UserManager = userManager;
+        AuthContext = authContext;
+        ApiContext = apiContext;
+        PermissionContext = permissionContext;
+        SecurityContext = securityContext;
+        MessageService = messageService;
+        MessageTarget = messageTarget;
+        StudioNotifyService = studioNotifyService;
+    }
+}
\ No newline at end of file
diff --git a/products/ASC.People/Server/Api/BasePeopleController.cs b/products/ASC.People/Server/Api/BasePeopleController.cs
new file mode 100644
index 0000000000..bd69bdd97f
--- /dev/null
+++ b/products/ASC.People/Server/Api/BasePeopleController.cs
@@ -0,0 +1,93 @@
+using AutoMapper;
+
+namespace ASC.People.Api;
+
+public class BasePeopleController : BaseApiController
+{
+    protected readonly UserPhotoManager UserPhotoManager;
+    protected readonly IHttpClientFactory HttpClientFactory;
+    protected readonly DisplayUserSettingsHelper DisplayUserSettingsHelper;
+    protected readonly SetupInfo SetupInfo;
+    protected readonly IMapper Mapper;
+
+    protected BasePeopleController(
+        UserManager userManager,
+        AuthContext authContext,
+        ApiContext apiContext,
+        PermissionContext permissionContext,
+        Core.SecurityContext securityContext,
+        MessageService messageService,
+        MessageTarget messageTarget,
+        StudioNotifyService studioNotifyService,
+        IMapper mapper)
+        : base(
+            userManager,
+            authContext,
+            apiContext,
+            permissionContext,
+            securityContext,
+            messageService,
+            messageTarget,
+            studioNotifyService)
+    {
+        Mapper = mapper;
+    }
+
+    protected UserInfo GetUserInfo(string userNameOrId)
+    {
+        UserInfo user;
+        try
+        {
+            var userId = new Guid(userNameOrId);
+            user = UserManager.GetUsers(userId);
+        }
+        catch (FormatException)
+        {
+            user = UserManager.GetUserByUserName(userNameOrId);
+        }
+
+        if (user == null || user.ID == Constants.LostUser.ID)
+        {
+            throw new ItemNotFoundException("user not found");
+        }
+
+        return user;
+    }
+
+    protected void UpdateContacts(IEnumerable<Contact> contacts, UserInfo user)
+    {
+        PermissionContext.DemandPermissions(new UserSecurityProvider(user.ID), Constants.Action_EditUser);
+
+        if (contacts == null)
+        {
+            return;
+        }
+
+        var values = contacts.Where(r => !string.IsNullOrEmpty(r.Value)).Select(r => $"{r.Type}|{r.Value}");
+        user.Contacts = string.Join('|', values);
+    }
+
+    protected void UpdatePhotoUrl(string files, UserInfo user)
+    {
+        if (string.IsNullOrEmpty(files))
+        {
+            return;
+        }
+
+        PermissionContext.DemandPermissions(new UserSecurityProvider(user.ID), Constants.Action_EditUser);
+
+        if (!files.StartsWith("http://") && !files.StartsWith("https://"))
+        {
+            files = new Uri(ApiContext.HttpContextAccessor.HttpContext.Request.GetDisplayUrl()).GetLeftPart(UriPartial.Authority) + "/" + files.TrimStart('/');
+        }
+        var request = new HttpRequestMessage();
+        request.RequestUri = new Uri(files);
+
+        var httpClient = HttpClientFactory.CreateClient();
+        using var response = httpClient.Send(request);
+        using var inputStream = response.Content.ReadAsStream();
+        using var br = new BinaryReader(inputStream);
+        var imageByteArray = br.ReadBytes((int)inputStream.Length);
+        UserPhotoManager.SaveOrUpdatePhoto(user.ID, imageByteArray);
+    }
+}
diff --git a/products/ASC.People/Server/Api/ContactsController.cs b/products/ASC.People/Server/Api/ContactsController.cs
new file mode 100644
index 0000000000..c6874bf38c
--- /dev/null
+++ b/products/ASC.People/Server/Api/ContactsController.cs
@@ -0,0 +1,138 @@
+using SecurityContext = ASC.Core.SecurityContext;
+
+namespace ASC.People.Api;
+
+public class ContactsController : BasePeopleController
+{
+    public ContactsController(
+        UserManager userManager,
+        AuthContext authContext,
+        ApiContext apiContext,
+        PermissionContext permissionContext,
+        SecurityContext securityContext,
+        MessageService messageService,
+        MessageTarget messageTarget,
+        StudioNotifyService studioNotifyService,
+        IMapper mapper)
+        : base(
+            userManager,
+            authContext,
+            apiContext,
+            permissionContext,
+            securityContext,
+            messageService,
+            messageTarget,
+            studioNotifyService,
+            mapper)
+    {
+    }
+
+    [Delete("{userid}/contacts")]
+    public EmployeeFullDto DeleteMemberContactsFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
+    {
+        return DeleteMemberContacts(userid, memberModel);
+    }
+
+    [Delete("{userid}/contacts")]
+    [Consumes("application/x-www-form-urlencoded")]
+    public EmployeeFullDto DeleteMemberContactsFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
+    {
+        return DeleteMemberContacts(userid, memberModel);
+    }
+
+    [Create("{userid}/contacts")]
+    public EmployeeFullDto SetMemberContactsFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
+    {
+        return SetMemberContacts(userid, memberModel);
+    }
+
+    [Create("{userid}/contacts")]
+    [Consumes("application/x-www-form-urlencoded")]
+    public EmployeeFullDto SetMemberContactsFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
+    {
+        return SetMemberContacts(userid, memberModel);
+    }
+
+    [Update("{userid}/contacts")]
+    public EmployeeFullDto UpdateMemberContactsFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
+    {
+        return UpdateMemberContacts(userid, memberModel);
+    }
+
+    [Update("{userid}/contacts")]
+    [Consumes("application/x-www-form-urlencoded")]
+    public EmployeeFullDto UpdateMemberContactsFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
+    {
+        return UpdateMemberContacts(userid, memberModel);
+    }
+
+    private void DeleteContacts(IEnumerable<Contact> contacts, UserInfo user)
+    {
+        PermissionContext.DemandPermissions(new UserSecurityProvider(user.ID), Constants.Action_EditUser);
+        if (contacts == null)
+        {
+            return;
+        }
+
+        if (user.ContactsList == null)
+        {
+            user.ContactsList = new List<string>();
+        }
+
+        foreach (var contact in contacts)
+        {
+            var index = user.ContactsList.IndexOf(contact.Type);
+            if (index != -1)
+            {
+                //Remove existing
+                user.ContactsList.RemoveRange(index, 2);
+            }
+        }
+    }
+
+    private EmployeeFullDto DeleteMemberContacts(string userid, UpdateMemberRequestDto memberModel)
+    {
+        var user = GetUserInfo(userid);
+
+        if (UserManager.IsSystemUser(user.ID))
+        {
+            throw new SecurityException();
+        }
+
+        DeleteContacts(memberModel.Contacts, user);
+        UserManager.SaveUserInfo(user);
+
+        return Mapper.Map<UserInfo, EmployeeFullDto>(user);
+    }
+
+    private EmployeeFullDto SetMemberContacts(string userid, UpdateMemberRequestDto memberModel)
+    {
+        var user = GetUserInfo(userid);
+
+        if (UserManager.IsSystemUser(user.ID))
+        {
+            throw new SecurityException();
+        }
+
+        user.ContactsList.Clear();
+        UpdateContacts(memberModel.Contacts, user);
+        UserManager.SaveUserInfo(user);
+
+        return Mapper.Map<UserInfo, EmployeeFullDto>(user);
+    }
+
+    private EmployeeFullDto UpdateMemberContacts(string userid, UpdateMemberRequestDto memberModel)
+    {
+        var user = GetUserInfo(userid);
+
+        if (UserManager.IsSystemUser(user.ID))
+        {
+            throw new SecurityException();
+        }
+
+        UpdateContacts(memberModel.Contacts, user);
+        UserManager.SaveUserInfo(user);
+
+        return Mapper.Map<UserInfo, EmployeeFullDto>(user);
+    }
+}
diff --git a/products/ASC.People/Server/Api/NotificationController.cs b/products/ASC.People/Server/Api/NotificationController.cs
new file mode 100644
index 0000000000..17e2d599e9
--- /dev/null
+++ b/products/ASC.People/Server/Api/NotificationController.cs
@@ -0,0 +1,71 @@
+using SecurityContext = ASC.Core.SecurityContext;
+
+namespace ASC.People.Api;
+
+public class NotificationController : BaseApiController
+{
+    private readonly CommonLinkUtility _commonLinkUtility;
+
+    public NotificationController(
+        UserManager userManager,
+        AuthContext authContext,
+        ApiContext apiContext,
+        PermissionContext permissionContext,
+        SecurityContext securityContext,
+        MessageService messageService,
+        MessageTarget messageTarget,
+        StudioNotifyService studioNotifyService,
+        CommonLinkUtility commonLinkUtility)
+        : base(
+            userManager,
+            authContext,
+            apiContext,
+            permissionContext,
+            securityContext,
+            messageService,
+            messageTarget,
+            studioNotifyService)
+    {
+        _commonLinkUtility = commonLinkUtility;
+    }
+
+    [Create("phone")]
+    public object SendNotificationToChangeFromBody([FromBody] UpdateMemberRequestDto model)
+    {
+        return SendNotificationToChange(model.UserId);
+    }
+
+    [Create("phone")]
+    [Consumes("application/x-www-form-urlencoded")]
+    public object SendNotificationToChangeFromForm([FromForm] UpdateMemberRequestDto model)
+    {
+        return SendNotificationToChange(model.UserId);
+    }
+
+    private object SendNotificationToChange(string userId)
+    {
+        var user = UserManager.GetUsers(
+            string.IsNullOrEmpty(userId)
+                ? SecurityContext.CurrentAccount.ID
+                : new Guid(userId));
+        var canChange =
+        user.IsMe(AuthContext)
+                    || PermissionContext.CheckPermissions(new UserSecurityProvider(user.ID), Constants.Action_EditUser);
+
+        if (!canChange)
+        {
+            throw new SecurityAccessDeniedException(Resource.ErrorAccessDenied);
+        }
+
+        user.MobilePhoneActivationStatus = MobilePhoneActivationStatus.NotActivated;
+        UserManager.SaveUserInfo(user);
+        if (user.IsMe(AuthContext))
+        {
+            return _commonLinkUtility.GetConfirmationUrl(user.Email, ConfirmType.PhoneActivation);
+        }
+
+        StudioNotifyService.SendMsgMobilePhoneChange(user);
+
+        return string.Empty;
+    }
+}
diff --git a/products/ASC.People/Server/Api/PeopleController.cs b/products/ASC.People/Server/Api/PeopleController.cs
index 34a9029bc9..d9dc544f82 100644
--- a/products/ASC.People/Server/Api/PeopleController.cs
+++ b/products/ASC.People/Server/Api/PeopleController.cs
@@ -146,13 +146,13 @@ namespace ASC.Employee.Core.Controllers
         }
 
         [Read]
-        public IQueryable<EmployeeWraper> GetAll()
+        public IQueryable<EmployeeDto> GetAll()
         {
             return GetByStatus(EmployeeStatus.Active);
         }
 
         [Read("status/{status}")]
-        public IQueryable<EmployeeWraper> GetByStatus(EmployeeStatus status)
+        public IQueryable<EmployeeDto> GetByStatus(EmployeeStatus status)
         {
             if (CoreBaseSettings.Personal) throw new Exception("Method not available");
             Guid? groupId = null;
@@ -165,13 +165,13 @@ namespace ASC.Employee.Core.Controllers
         }
 
         [Read("@self")]
-        public EmployeeWraper Self()
+        public EmployeeDto Self()
         {
             return EmployeeWraperFullHelper.GetFull(UserManager.GetUser(SecurityContext.CurrentAccount.ID, EmployeeWraperFullHelper.GetExpression(ApiContext)));
         }
 
         [Read("email")]
-        public EmployeeWraperFull GetByEmail([FromQuery] string email)
+        public EmployeeFullDto GetByEmail([FromQuery] string email)
         {
             if (CoreBaseSettings.Personal && !UserManager.GetUsers(SecurityContext.CurrentAccount.ID).IsOwner(Tenant))
                 throw new MethodAccessException("Method not available");
@@ -185,7 +185,7 @@ namespace ASC.Employee.Core.Controllers
         }
 
         [Read("{username}", order: int.MaxValue)]
-        public EmployeeWraperFull GetById(string username)
+        public EmployeeFullDto GetById(string username)
         {
             if (CoreBaseSettings.Personal) throw new MethodAccessException("Method not available");
             var user = UserManager.GetUserByUserName(username);
@@ -210,7 +210,7 @@ namespace ASC.Employee.Core.Controllers
         }
 
         [Read("@search/{query}")]
-        public IEnumerable<EmployeeWraperFull> GetSearch(string query)
+        public IEnumerable<EmployeeFullDto> GetSearch(string query)
         {
             if (CoreBaseSettings.Personal) throw new MethodAccessException("Method not available");
             try
@@ -231,13 +231,13 @@ namespace ASC.Employee.Core.Controllers
         }
 
         [Read("search")]
-        public IEnumerable<EmployeeWraperFull> GetPeopleSearch([FromQuery] string query)
+        public IEnumerable<EmployeeFullDto> GetPeopleSearch([FromQuery] string query)
         {
             return GetSearch(query);
         }
 
         [Read("status/{status}/search")]
-        public IEnumerable<EmployeeWraperFull> GetAdvanced(EmployeeStatus status, [FromQuery] string query)
+        public IEnumerable<EmployeeFullDto> GetAdvanced(EmployeeStatus status, [FromQuery] string query)
         {
             if (CoreBaseSettings.Personal) throw new MethodAccessException("Method not available");
             try
@@ -318,14 +318,14 @@ namespace ASC.Employee.Core.Controllers
 
 
         [Read("filter")]
-        public IQueryable<EmployeeWraperFull> GetFullByFilter(EmployeeStatus? employeeStatus, Guid? groupId, EmployeeActivationStatus? activationStatus, EmployeeType? employeeType, bool? isAdministrator)
+        public IQueryable<EmployeeFullDto> GetFullByFilter(EmployeeStatus? employeeStatus, Guid? groupId, EmployeeActivationStatus? activationStatus, EmployeeType? employeeType, bool? isAdministrator)
         {
             var users = GetByFilter(employeeStatus, groupId, activationStatus, employeeType, isAdministrator);
             return users.Select(r => EmployeeWraperFullHelper.GetFull(r));
         }
 
         [Read("simple/filter")]
-        public IEnumerable<EmployeeWraper> GetSimpleByFilter(EmployeeStatus? employeeStatus, Guid? groupId, EmployeeActivationStatus? activationStatus, EmployeeType? employeeType, bool? isAdministrator)
+        public IEnumerable<EmployeeDto> GetSimpleByFilter(EmployeeStatus? employeeStatus, Guid? groupId, EmployeeActivationStatus? activationStatus, EmployeeType? employeeType, bool? isAdministrator)
         {
             var users = GetByFilter(employeeStatus, groupId, activationStatus, employeeType, isAdministrator);
             return users.Select(EmployeeWraperHelper.Get);
@@ -468,7 +468,7 @@ namespace ASC.Employee.Core.Controllers
 
         [Create]
         [Authorize(AuthenticationSchemes = "confirm", Roles = "LinkInvite,Everyone")]
-        public EmployeeWraperFull AddMemberFromBody([FromBody] MemberRequestDto memberModel)
+        public EmployeeFullDto AddMemberFromBody([FromBody] MemberRequestDto memberModel)
         {
             return AddMember(memberModel);
         }
@@ -476,12 +476,12 @@ namespace ASC.Employee.Core.Controllers
         [Create]
         [Authorize(AuthenticationSchemes = "confirm", Roles = "LinkInvite,Everyone")]
         [Consumes("application/x-www-form-urlencoded")]
-        public EmployeeWraperFull AddMemberFromForm([FromForm] MemberRequestDto memberModel)
+        public EmployeeFullDto AddMemberFromForm([FromForm] MemberRequestDto memberModel)
         {
             return AddMember(memberModel);
         }
 
-        private EmployeeWraperFull AddMember(MemberRequestDto memberModel)
+        private EmployeeFullDto AddMember(MemberRequestDto memberModel)
         {
             ApiContext.AuthByClaim();
 
@@ -540,19 +540,19 @@ namespace ASC.Employee.Core.Controllers
         }
 
         [Create("active")]
-        public EmployeeWraperFull AddMemberAsActivatedFromBody([FromBody] MemberRequestDto memberModel)
+        public EmployeeFullDto AddMemberAsActivatedFromBody([FromBody] MemberRequestDto memberModel)
         {
             return AddMemberAsActivated(memberModel);
         }
 
         [Create("active")]
         [Consumes("application/x-www-form-urlencoded")]
-        public EmployeeWraperFull AddMemberAsActivatedFromForm([FromForm] MemberRequestDto memberModel)
+        public EmployeeFullDto AddMemberAsActivatedFromForm([FromForm] MemberRequestDto memberModel)
         {
             return AddMemberAsActivated(memberModel);
         }
 
-        private EmployeeWraperFull AddMemberAsActivated(MemberRequestDto memberModel)
+        private EmployeeFullDto AddMemberAsActivated(MemberRequestDto memberModel)
         {
             PermissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
 
@@ -608,19 +608,19 @@ namespace ASC.Employee.Core.Controllers
         }
 
         [Update("{userid}/culture")]
-        public EmployeeWraperFull UpdateMemberCultureFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
+        public EmployeeFullDto UpdateMemberCultureFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
         {
             return UpdateMemberCulture(userid, memberModel);
         }
 
         [Update("{userid}/culture")]
         [Consumes("application/x-www-form-urlencoded")]
-        public EmployeeWraperFull UpdateMemberCultureFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
+        public EmployeeFullDto UpdateMemberCultureFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
         {
             return UpdateMemberCulture(userid, memberModel);
         }
 
-        private EmployeeWraperFull UpdateMemberCulture(string userid, UpdateMemberRequestDto memberModel)
+        private EmployeeFullDto UpdateMemberCulture(string userid, UpdateMemberRequestDto memberModel)
         {
             var user = GetUserInfo(userid);
 
@@ -656,19 +656,19 @@ namespace ASC.Employee.Core.Controllers
         }
 
         [Update("{userid}")]
-        public EmployeeWraperFull UpdateMemberFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
+        public EmployeeFullDto UpdateMemberFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
         {
             return UpdateMember(userid, memberModel);
         }
 
         [Update("{userid}")]
         [Consumes("application/x-www-form-urlencoded")]
-        public EmployeeWraperFull UpdateMemberFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
+        public EmployeeFullDto UpdateMemberFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
         {
             return UpdateMember(userid, memberModel);
         }
 
-        private EmployeeWraperFull UpdateMember(string userid, UpdateMemberRequestDto memberModel)
+        private EmployeeFullDto UpdateMember(string userid, UpdateMemberRequestDto memberModel)
         {
             var user = GetUserInfo(userid);
 
@@ -777,7 +777,7 @@ namespace ASC.Employee.Core.Controllers
         }
 
         [Delete("{userid}")]
-        public EmployeeWraperFull DeleteMember(string userid)
+        public EmployeeFullDto DeleteMember(string userid)
         {
             PermissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
 
@@ -804,7 +804,7 @@ namespace ASC.Employee.Core.Controllers
 
         [Delete("@self")]
         [Authorize(AuthenticationSchemes = "confirm", Roles = "ProfileRemove")]
-        public EmployeeWraperFull DeleteProfile()
+        public EmployeeFullDto DeleteProfile()
         {
             ApiContext.AuthByClaim();
 
@@ -847,19 +847,19 @@ namespace ASC.Employee.Core.Controllers
         }
 
         [Update("{userid}/contacts")]
-        public EmployeeWraperFull UpdateMemberContactsFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
+        public EmployeeFullDto UpdateMemberContactsFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
         {
             return UpdateMemberContacts(userid, memberModel);
         }
 
         [Update("{userid}/contacts")]
         [Consumes("application/x-www-form-urlencoded")]
-        public EmployeeWraperFull UpdateMemberContactsFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
+        public EmployeeFullDto UpdateMemberContactsFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
         {
             return UpdateMemberContacts(userid, memberModel);
         }
 
-        private EmployeeWraperFull UpdateMemberContacts(string userid, UpdateMemberRequestDto memberModel)
+        private EmployeeFullDto UpdateMemberContacts(string userid, UpdateMemberRequestDto memberModel)
         {
             var user = GetUserInfo(userid);
 
@@ -872,19 +872,19 @@ namespace ASC.Employee.Core.Controllers
         }
 
         [Create("{userid}/contacts")]
-        public EmployeeWraperFull SetMemberContactsFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
+        public EmployeeFullDto SetMemberContactsFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
         {
             return SetMemberContacts(userid, memberModel);
         }
 
         [Create("{userid}/contacts")]
         [Consumes("application/x-www-form-urlencoded")]
-        public EmployeeWraperFull SetMemberContactsFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
+        public EmployeeFullDto SetMemberContactsFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
         {
             return SetMemberContacts(userid, memberModel);
         }
 
-        private EmployeeWraperFull SetMemberContacts(string userid, UpdateMemberRequestDto memberModel)
+        private EmployeeFullDto SetMemberContacts(string userid, UpdateMemberRequestDto memberModel)
         {
             var user = GetUserInfo(userid);
 
@@ -898,19 +898,19 @@ namespace ASC.Employee.Core.Controllers
         }
 
         [Delete("{userid}/contacts")]
-        public EmployeeWraperFull DeleteMemberContactsFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
+        public EmployeeFullDto DeleteMemberContactsFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
         {
             return DeleteMemberContacts(userid, memberModel);
         }
 
         [Delete("{userid}/contacts")]
         [Consumes("application/x-www-form-urlencoded")]
-        public EmployeeWraperFull DeleteMemberContactsFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
+        public EmployeeFullDto DeleteMemberContactsFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
         {
             return DeleteMemberContacts(userid, memberModel);
         }
 
-        private EmployeeWraperFull DeleteMemberContacts(string userid, UpdateMemberRequestDto memberModel)
+        private EmployeeFullDto DeleteMemberContacts(string userid, UpdateMemberRequestDto memberModel)
         {
             var user = GetUserInfo(userid);
 
@@ -934,9 +934,9 @@ namespace ASC.Employee.Core.Controllers
         }
 
         [Create("{userid}/photo")]
-        public FileUploadResult UploadMemberPhoto(string userid, IFormCollection model)
+        public FileUploadResultDto UploadMemberPhoto(string userid, IFormCollection model)
         {
-            var result = new People.Models.FileUploadResult();
+            var result = new FileUploadResultDto();
             var autosave = bool.Parse(model["Autosave"]);
 
             try
@@ -1153,7 +1153,7 @@ namespace ASC.Employee.Core.Controllers
 
         [Update("{userid}/password")]
         [Authorize(AuthenticationSchemes = "confirm", Roles = "PasswordChange,EmailChange,Activation,EmailActivation,Everyone")]
-        public EmployeeWraperFull ChangeUserPasswordFromBody(Guid userid, [FromBody] MemberRequestDto memberModel)
+        public EmployeeFullDto ChangeUserPasswordFromBody(Guid userid, [FromBody] MemberRequestDto memberModel)
         {
             return ChangeUserPassword(userid, memberModel);
         }
@@ -1161,12 +1161,12 @@ namespace ASC.Employee.Core.Controllers
         [Update("{userid}/password")]
         [Authorize(AuthenticationSchemes = "confirm", Roles = "PasswordChange,EmailChange,Activation,EmailActivation,Everyone")]
         [Consumes("application/x-www-form-urlencoded")]
-        public EmployeeWraperFull ChangeUserPasswordFromForm(Guid userid, [FromForm] MemberRequestDto memberModel)
+        public EmployeeFullDto ChangeUserPasswordFromForm(Guid userid, [FromForm] MemberRequestDto memberModel)
         {
             return ChangeUserPassword(userid, memberModel);
         }
 
-        private EmployeeWraperFull ChangeUserPassword(Guid userid, MemberRequestDto memberModel)
+        private EmployeeFullDto ChangeUserPassword(Guid userid, MemberRequestDto memberModel)
         {
             ApiContext.AuthByClaim();
             PermissionContext.DemandPermissions(new UserSecurityProvider(userid), Constants.Action_EditUser);
@@ -1291,7 +1291,7 @@ namespace ASC.Employee.Core.Controllers
 
         [Update("activationstatus/{activationstatus}")]
         [Authorize(AuthenticationSchemes = "confirm", Roles = "Activation,Everyone")]
-        public IEnumerable<EmployeeWraperFull> UpdateEmployeeActivationStatusFromBody(EmployeeActivationStatus activationstatus, [FromBody] UpdateMembersRequestDto model)
+        public IEnumerable<EmployeeFullDto> UpdateEmployeeActivationStatusFromBody(EmployeeActivationStatus activationstatus, [FromBody] UpdateMembersRequestDto model)
         {
             return UpdateEmployeeActivationStatus(activationstatus, model);
         }
@@ -1299,16 +1299,16 @@ namespace ASC.Employee.Core.Controllers
         [Update("activationstatus/{activationstatus}")]
         [Authorize(AuthenticationSchemes = "confirm", Roles = "Activation,Everyone")]
         [Consumes("application/x-www-form-urlencoded")]
-        public IEnumerable<EmployeeWraperFull> UpdateEmployeeActivationStatusFromForm(EmployeeActivationStatus activationstatus, [FromForm] UpdateMembersRequestDto model)
+        public IEnumerable<EmployeeFullDto> UpdateEmployeeActivationStatusFromForm(EmployeeActivationStatus activationstatus, [FromForm] UpdateMembersRequestDto model)
         {
             return UpdateEmployeeActivationStatus(activationstatus, model);
         }
 
-        private IEnumerable<EmployeeWraperFull> UpdateEmployeeActivationStatus(EmployeeActivationStatus activationstatus, UpdateMembersRequestDto model)
+        private IEnumerable<EmployeeFullDto> UpdateEmployeeActivationStatus(EmployeeActivationStatus activationstatus, UpdateMembersRequestDto model)
         {
             ApiContext.AuthByClaim();
 
-            var retuls = new List<EmployeeWraperFull>();
+            var retuls = new List<EmployeeFullDto>();
             foreach (var id in model.UserIds.Where(userId => !UserManager.IsSystemUser(userId)))
             {
                 PermissionContext.DemandPermissions(new UserSecurityProvider(id), Constants.Action_EditUser);
@@ -1324,19 +1324,19 @@ namespace ASC.Employee.Core.Controllers
         }
 
         [Update("type/{type}")]
-        public IEnumerable<EmployeeWraperFull> UpdateUserTypeFromBody(EmployeeType type, [FromBody] UpdateMembersRequestDto model)
+        public IEnumerable<EmployeeFullDto> UpdateUserTypeFromBody(EmployeeType type, [FromBody] UpdateMembersRequestDto model)
         {
             return UpdateUserType(type, model);
         }
 
         [Update("type/{type}")]
         [Consumes("application/x-www-form-urlencoded")]
-        public IEnumerable<EmployeeWraperFull> UpdateUserTypeFromForm(EmployeeType type, [FromForm] UpdateMembersRequestDto model)
+        public IEnumerable<EmployeeFullDto> UpdateUserTypeFromForm(EmployeeType type, [FromForm] UpdateMembersRequestDto model)
         {
             return UpdateUserType(type, model);
         }
 
-        private IEnumerable<EmployeeWraperFull> UpdateUserType(EmployeeType type, UpdateMembersRequestDto model)
+        private IEnumerable<EmployeeFullDto> UpdateUserType(EmployeeType type, UpdateMembersRequestDto model)
         {
             var users = model.UserIds
                 .Where(userId => !UserManager.IsSystemUser(userId))
@@ -1376,19 +1376,19 @@ namespace ASC.Employee.Core.Controllers
         }
 
         [Update("status/{status}")]
-        public IEnumerable<EmployeeWraperFull> UpdateUserStatusFromBody(EmployeeStatus status, [FromBody] UpdateMembersRequestDto model)
+        public IEnumerable<EmployeeFullDto> UpdateUserStatusFromBody(EmployeeStatus status, [FromBody] UpdateMembersRequestDto model)
         {
             return UpdateUserStatus(status, model);
         }
 
         [Update("status/{status}")]
         [Consumes("application/x-www-form-urlencoded")]
-        public IEnumerable<EmployeeWraperFull> UpdateUserStatusFromForm(EmployeeStatus status, [FromForm] UpdateMembersRequestDto model)
+        public IEnumerable<EmployeeFullDto> UpdateUserStatusFromForm(EmployeeStatus status, [FromForm] UpdateMembersRequestDto model)
         {
             return UpdateUserStatus(status, model);
         }
 
-        private IEnumerable<EmployeeWraperFull> UpdateUserStatus(EmployeeStatus status, UpdateMembersRequestDto model)
+        private IEnumerable<EmployeeFullDto> UpdateUserStatus(EmployeeStatus status, UpdateMembersRequestDto model)
         {
             PermissionContext.DemandPermissions(Constants.Action_EditUser);
 
@@ -1430,19 +1430,19 @@ namespace ASC.Employee.Core.Controllers
 
 
         [Update("invite")]
-        public IEnumerable<EmployeeWraperFull> ResendUserInvitesFromBody([FromBody] UpdateMembersRequestDto model)
+        public IEnumerable<EmployeeFullDto> ResendUserInvitesFromBody([FromBody] UpdateMembersRequestDto model)
         {
             return ResendUserInvites(model);
         }
 
         [Update("invite")]
         [Consumes("application/x-www-form-urlencoded")]
-        public IEnumerable<EmployeeWraperFull> ResendUserInvitesFromForm([FromForm] UpdateMembersRequestDto model)
+        public IEnumerable<EmployeeFullDto> ResendUserInvitesFromForm([FromForm] UpdateMembersRequestDto model)
         {
             return ResendUserInvites(model);
         }
 
-        private IEnumerable<EmployeeWraperFull> ResendUserInvites(UpdateMembersRequestDto model)
+        private IEnumerable<EmployeeFullDto> ResendUserInvites(UpdateMembersRequestDto model)
         {
             var users = model.UserIds
                 .Where(userId => !UserManager.IsSystemUser(userId))
@@ -1492,19 +1492,19 @@ namespace ASC.Employee.Core.Controllers
         }
 
         [Update("delete", Order = -1)]
-        public IEnumerable<EmployeeWraperFull> RemoveUsersFromBody([FromBody] UpdateMembersRequestDto model)
+        public IEnumerable<EmployeeFullDto> RemoveUsersFromBody([FromBody] UpdateMembersRequestDto model)
         {
             return RemoveUsers(model);
         }
 
         [Update("delete", Order = -1)]
         [Consumes("application/x-www-form-urlencoded")]
-        public IEnumerable<EmployeeWraperFull> RemoveUsersFromForm([FromForm] UpdateMembersRequestDto model)
+        public IEnumerable<EmployeeFullDto> RemoveUsersFromForm([FromForm] UpdateMembersRequestDto model)
         {
             return RemoveUsers(model);
         }
 
-        private IEnumerable<EmployeeWraperFull> RemoveUsers(UpdateMembersRequestDto model)
+        private IEnumerable<EmployeeFullDto> RemoveUsers(UpdateMembersRequestDto model)
         {
             PermissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
 
diff --git a/products/ASC.People/Server/Api/PhotoController.cs b/products/ASC.People/Server/Api/PhotoController.cs
new file mode 100644
index 0000000000..200428f78d
--- /dev/null
+++ b/products/ASC.People/Server/Api/PhotoController.cs
@@ -0,0 +1,270 @@
+using SecurityContext = ASC.Core.SecurityContext;
+
+namespace ASC.People.Api;
+
+public class PhotoController : BasePeopleController
+{
+    private readonly FileSizeComment _fileSizeComment;
+    private readonly SettingsManager _settingsManager;
+
+    public PhotoController(
+        UserManager userManager,
+        AuthContext authContext,
+        ApiContext apiContext,
+        PermissionContext permissionContext,
+        SecurityContext securityContext,
+        MessageService messageService,
+        MessageTarget messageTarget,
+        StudioNotifyService studioNotifyService,
+        FileSizeComment fileSizeComment,
+        SettingsManager settingsManager,
+        IMapper mapper)
+        : base(
+            userManager,
+            authContext,
+            apiContext,
+            permissionContext,
+            securityContext,
+            messageService,
+            messageTarget,
+            studioNotifyService,
+            mapper)
+    {
+        _fileSizeComment = fileSizeComment;
+        _settingsManager = settingsManager;
+    }
+
+    [Create("{userid}/photo/thumbnails")]
+    public ThumbnailsDataDto CreateMemberPhotoThumbnailsFromBody(string userid, [FromBody] ThumbnailsRequestDto thumbnailsModel)
+    {
+        return CreateMemberPhotoThumbnails(userid, thumbnailsModel);
+    }
+
+    [Create("{userid}/photo/thumbnails")]
+    [Consumes("application/x-www-form-urlencoded")]
+    public ThumbnailsDataDto CreateMemberPhotoThumbnailsFromForm(string userid, [FromForm] ThumbnailsRequestDto thumbnailsModel)
+    {
+        return CreateMemberPhotoThumbnails(userid, thumbnailsModel);
+    }
+
+    [Delete("{userid}/photo")]
+    public ThumbnailsDataDto DeleteMemberPhoto(string userid)
+    {
+        var user = GetUserInfo(userid);
+
+        if (UserManager.IsSystemUser(user.ID))
+        {
+            throw new SecurityException();
+        }
+
+        PermissionContext.DemandPermissions(new UserSecurityProvider(user.ID), Constants.Action_EditUser);
+
+        UserPhotoManager.RemovePhoto(user.ID);
+        UserManager.SaveUserInfo(user);
+        MessageService.Send(MessageAction.UserDeletedAvatar, MessageTarget.Create(user.ID), user.DisplayUserName(false, DisplayUserSettingsHelper));
+
+        return new ThumbnailsDataDto(user.ID, UserPhotoManager);
+    }
+
+    [Read("{userid}/photo")]
+    public ThumbnailsDataDto GetMemberPhoto(string userid)
+    {
+        var user = GetUserInfo(userid);
+
+        if (UserManager.IsSystemUser(user.ID))
+        {
+            throw new SecurityException();
+        }
+
+        return new ThumbnailsDataDto(user.ID, UserPhotoManager);
+    }
+
+
+    [Update("{userid}/photo")]
+    public ThumbnailsDataDto UpdateMemberPhotoFromBody(string userid, [FromBody] UpdateMemberRequestDto model)
+    {
+        return UpdateMemberPhoto(userid, model);
+    }
+
+    [Update("{userid}/photo")]
+    [Consumes("application/x-www-form-urlencoded")]
+    public ThumbnailsDataDto UpdateMemberPhotoFromForm(string userid, [FromForm] UpdateMemberRequestDto model)
+    {
+        return UpdateMemberPhoto(userid, model);
+    }
+
+    [Create("{userid}/photo")]
+    public FileUploadResultDto UploadMemberPhoto(string userid, IFormCollection model)
+    {
+        var result = new FileUploadResultDto();
+        var autosave = bool.Parse(model["Autosave"]);
+
+        try
+        {
+            if (model.Files.Count != 0)
+            {
+                Guid userId;
+                try
+                {
+                    userId = new Guid(userid);
+                }
+                catch
+                {
+                    userId = SecurityContext.CurrentAccount.ID;
+                }
+
+                PermissionContext.DemandPermissions(new UserSecurityProvider(userId), Constants.Action_EditUser);
+
+                var userPhoto = model.Files[0];
+
+                if (userPhoto.Length > SetupInfo.MaxImageUploadSize)
+                {
+                    result.Success = false;
+                    result.Message = _fileSizeComment.FileImageSizeExceptionString;
+
+                    return result;
+                }
+
+                var data = new byte[userPhoto.Length];
+                using var inputStream = userPhoto.OpenReadStream();
+
+                var br = new BinaryReader(inputStream);
+                br.Read(data, 0, (int)userPhoto.Length);
+                br.Close();
+
+                CheckImgFormat(data);
+
+                if (autosave)
+                {
+                    if (data.Length > SetupInfo.MaxImageUploadSize)
+                    {
+                        throw new ImageSizeLimitException();
+                    }
+
+                    var mainPhoto = UserPhotoManager.SaveOrUpdatePhoto(userId, data);
+
+                    result.Data =
+                        new
+                        {
+                            main = mainPhoto,
+                            retina = UserPhotoManager.GetRetinaPhotoURL(userId),
+                            max = UserPhotoManager.GetMaxPhotoURL(userId),
+                            big = UserPhotoManager.GetBigPhotoURL(userId),
+                            medium = UserPhotoManager.GetMediumPhotoURL(userId),
+                            small = UserPhotoManager.GetSmallPhotoURL(userId),
+                        };
+                }
+                else
+                {
+                    result.Data = UserPhotoManager.SaveTempPhoto(data, SetupInfo.MaxImageUploadSize, UserPhotoManager.OriginalFotoSize.Width, UserPhotoManager.OriginalFotoSize.Height);
+                }
+
+                result.Success = true;
+            }
+            else
+            {
+                result.Success = false;
+                result.Message = PeopleResource.ErrorEmptyUploadFileSelected;
+            }
+
+        }
+        catch (Web.Core.Users.UnknownImageFormatException)
+        {
+            result.Success = false;
+            result.Message = PeopleResource.ErrorUnknownFileImageType;
+        }
+        catch (ImageWeightLimitException)
+        {
+            result.Success = false;
+            result.Message = PeopleResource.ErrorImageWeightLimit;
+        }
+        catch (ImageSizeLimitException)
+        {
+            result.Success = false;
+            result.Message = PeopleResource.ErrorImageSizetLimit;
+        }
+        catch (Exception ex)
+        {
+            result.Success = false;
+            result.Message = ex.Message.HtmlEncode();
+        }
+
+        return result;
+    }
+
+    private static void CheckImgFormat(byte[] data)
+    {
+        IImageFormat imgFormat;
+        try
+        {
+            using var img = Image.Load(data, out var format);
+            imgFormat = format;
+        }
+        catch (OutOfMemoryException)
+        {
+            throw new ImageSizeLimitException();
+        }
+        catch (ArgumentException error)
+        {
+            throw new Web.Core.Users.UnknownImageFormatException(error);
+        }
+
+        if (imgFormat.Name != "PNG" && imgFormat.Name != "JPEG")
+        {
+            throw new Web.Core.Users.UnknownImageFormatException();
+        }
+    }
+
+    private ThumbnailsDataDto CreateMemberPhotoThumbnails(string userid, ThumbnailsRequestDto thumbnailsModel)
+    {
+        var user = GetUserInfo(userid);
+
+        if (UserManager.IsSystemUser(user.ID))
+        {
+            throw new SecurityException();
+        }
+
+        PermissionContext.DemandPermissions(new UserSecurityProvider(user.ID), Constants.Action_EditUser);
+
+        if (!string.IsNullOrEmpty(thumbnailsModel.TmpFile))
+        {
+            var fileName = Path.GetFileName(thumbnailsModel.TmpFile);
+            var data = UserPhotoManager.GetTempPhotoData(fileName);
+
+            var settings = new UserPhotoThumbnailSettings(thumbnailsModel.X, thumbnailsModel.Y, thumbnailsModel.Width, thumbnailsModel.Height);
+            _settingsManager.SaveForUser(settings, user.ID);
+            UserPhotoManager.RemovePhoto(user.ID);
+            UserPhotoManager.SaveOrUpdatePhoto(user.ID, data);
+            UserPhotoManager.RemoveTempPhoto(fileName);
+        }
+        else
+        {
+            UserPhotoThumbnailManager.SaveThumbnails(UserPhotoManager, _settingsManager, thumbnailsModel.X, thumbnailsModel.Y, thumbnailsModel.Width, thumbnailsModel.Height, user.ID);
+        }
+
+        UserManager.SaveUserInfo(user);
+        MessageService.Send(MessageAction.UserUpdatedAvatarThumbnails, MessageTarget.Create(user.ID), user.DisplayUserName(false, DisplayUserSettingsHelper));
+
+        return new ThumbnailsDataDto(user.ID, UserPhotoManager);
+    }
+
+    private ThumbnailsDataDto UpdateMemberPhoto(string userid, UpdateMemberRequestDto model)
+    {
+        var user = GetUserInfo(userid);
+
+        if (UserManager.IsSystemUser(user.ID))
+        {
+            throw new SecurityException();
+        }
+
+        if (model.Files != UserPhotoManager.GetPhotoAbsoluteWebPath(user.ID))
+        {
+            UpdatePhotoUrl(model.Files, user);
+        }
+
+        UserManager.SaveUserInfo(user);
+        MessageService.Send(MessageAction.UserAddedAvatar, MessageTarget.Create(user.ID), user.DisplayUserName(false, DisplayUserSettingsHelper));
+
+        return new ThumbnailsDataDto(user.ID, UserPhotoManager);
+    }
+}
diff --git a/products/ASC.People/Server/Api/ReassignController.cs b/products/ASC.People/Server/Api/ReassignController.cs
new file mode 100644
index 0000000000..a0d37e7ec9
--- /dev/null
+++ b/products/ASC.People/Server/Api/ReassignController.cs
@@ -0,0 +1,100 @@
+using SecurityContext = ASC.Core.SecurityContext;
+
+namespace ASC.People.Api;
+
+public class ReassignController : BaseApiController
+{
+    private readonly QueueWorkerReassign _queueWorkerReassign;
+
+    public ReassignController(
+        UserManager userManager,
+        AuthContext authContext,
+        ApiContext apiContext,
+        PermissionContext permissionContext,
+        SecurityContext securityContext,
+        MessageService messageService,
+        MessageTarget messageTarget,
+        StudioNotifyService studioNotifyService,
+        QueueWorkerReassign queueWorkerReassign)
+        : base(
+            userManager,
+            authContext,
+            apiContext,
+            permissionContext,
+            securityContext,
+            messageService,
+            messageTarget,
+            studioNotifyService)
+    {
+        _queueWorkerReassign = queueWorkerReassign;
+    }
+
+    [Read(@"reassign/progress")]
+    public ReassignProgressItem GetReassignProgress(Guid userId)
+    {
+        PermissionContext.DemandPermissions(Constants.Action_EditUser);
+
+        return _queueWorkerReassign.GetProgressItemStatus(Tenant.TenantId, userId);
+    }
+
+    [Create(@"reassign/start")]
+    public ReassignProgressItem StartReassignFromBody([FromBody] StartReassignRequestDto model)
+    {
+        return StartReassign(model);
+    }
+
+    [Create(@"reassign/start")]
+    [Consumes("application/x-www-form-urlencoded")]
+    public ReassignProgressItem StartReassignFromForm([FromForm] StartReassignRequestDto model)
+    {
+        return StartReassign(model);
+    }
+
+    [Update(@"reassign/terminate")]
+    public void TerminateReassignFromBody([FromBody] TerminateRequestDto model)
+    {
+        PermissionContext.DemandPermissions(Constants.Action_EditUser);
+
+        _queueWorkerReassign.Terminate(Tenant.TenantId, model.UserId);
+    }
+
+    [Update(@"reassign/terminate")]
+    [Consumes("application/x-www-form-urlencoded")]
+    public void TerminateReassignFromForm([FromForm] TerminateRequestDto model)
+    {
+        PermissionContext.DemandPermissions(Constants.Action_EditUser);
+
+        _queueWorkerReassign.Terminate(Tenant.TenantId, model.UserId);
+    }
+
+    private ReassignProgressItem StartReassign(StartReassignRequestDto model)
+    {
+        PermissionContext.DemandPermissions(Constants.Action_EditUser);
+
+        var fromUser = UserManager.GetUsers(model.FromUserId);
+
+        if (fromUser == null || fromUser.ID == Constants.LostUser.ID)
+        {
+            throw new ArgumentException("User with id = " + model.FromUserId + " not found");
+        }
+
+        if (fromUser.IsOwner(Tenant) || fromUser.IsMe(AuthContext) || fromUser.Status != EmployeeStatus.Terminated)
+        {
+            throw new ArgumentException("Can not delete user with id = " + model.FromUserId);
+        }
+
+        var toUser = UserManager.GetUsers(model.ToUserId);
+
+        if (toUser == null || toUser.ID == Constants.LostUser.ID)
+        {
+            throw new ArgumentException("User with id = " + model.ToUserId + " not found");
+        }
+
+        if (toUser.IsVisitor(UserManager) || toUser.Status == EmployeeStatus.Terminated)
+        {
+            throw new ArgumentException("Can not reassign data to user with id = " + model.ToUserId);
+        }
+
+        return _queueWorkerReassign.Start(Tenant.TenantId, model.FromUserId, model.ToUserId, SecurityContext.CurrentAccount.ID, model.DeleteProfile);
+    }
+}
diff --git a/products/ASC.People/Server/Api/RemoveUserDataController.cs b/products/ASC.People/Server/Api/RemoveUserDataController.cs
new file mode 100644
index 0000000000..3a6acc85ff
--- /dev/null
+++ b/products/ASC.People/Server/Api/RemoveUserDataController.cs
@@ -0,0 +1,103 @@
+using SecurityContext = ASC.Core.SecurityContext;
+
+namespace ASC.People.Api;
+
+public class RemoveUserDataController : BaseApiController
+{
+    private readonly QueueWorkerRemove _queueWorkerRemove;
+
+    public RemoveUserDataController(
+        UserManager userManager,
+        AuthContext authContext,
+        ApiContext apiContext,
+        PermissionContext permissionContext,
+        SecurityContext securityContext,
+        MessageService messageService,
+        MessageTarget messageTarget,
+        StudioNotifyService studioNotifyService,
+        QueueWorkerRemove queueWorkerRemove)
+        : base(userManager,
+               authContext,
+               apiContext,
+               permissionContext,
+               securityContext,
+               messageService,
+               messageTarget,
+               studioNotifyService)
+    {
+        _queueWorkerRemove = queueWorkerRemove;
+    }
+
+    [Read(@"remove/progress")]
+    public RemoveProgressItem GetRemoveProgress(Guid userId)
+    {
+        PermissionContext.DemandPermissions(Constants.Action_EditUser);
+
+        return _queueWorkerRemove.GetProgressItemStatus(Tenant.TenantId, userId);
+    }
+
+    [Update("self/delete")]
+    public object SendInstructionsToDelete()
+    {
+        var user = UserManager.GetUsers(SecurityContext.CurrentAccount.ID);
+
+        if (user.IsLDAP())
+        {
+            throw new SecurityException();
+        }
+
+        StudioNotifyService.SendMsgProfileDeletion(user);
+        MessageService.Send(MessageAction.UserSentDeleteInstructions);
+
+        return string.Format(Resource.SuccessfullySentNotificationDeleteUserInfoMessage, "<b>" + user.Email + "</b>");
+    }
+
+    [Create(@"remove/start")]
+    public RemoveProgressItem StartRemoveFromBody([FromBody] TerminateRequestDto model)
+    {
+        return StartRemove(model);
+    }
+
+    [Create(@"remove/start")]
+    [Consumes("application/x-www-form-urlencoded")]
+    public RemoveProgressItem StartRemoveFromForm([FromForm] TerminateRequestDto model)
+    {
+        return StartRemove(model);
+    }
+
+    [Update(@"remove/terminate")]
+    public void TerminateRemoveFromBody([FromBody] TerminateRequestDto model)
+    {
+        PermissionContext.DemandPermissions(Constants.Action_EditUser);
+
+        _queueWorkerRemove.Terminate(Tenant.TenantId, model.UserId);
+    }
+
+    [Update(@"remove/terminate")]
+    [Consumes("application/x-www-form-urlencoded")]
+    public void TerminateRemoveFromForm([FromForm] TerminateRequestDto model)
+    {
+        PermissionContext.DemandPermissions(Constants.Action_EditUser);
+
+        _queueWorkerRemove.Terminate(Tenant.TenantId, model.UserId);
+    }
+
+    private RemoveProgressItem StartRemove(TerminateRequestDto model)
+    {
+        PermissionContext.DemandPermissions(Constants.Action_EditUser);
+
+        var user = UserManager.GetUsers(model.UserId);
+
+        if (user == null || user.ID == Constants.LostUser.ID)
+        {
+            throw new ArgumentException("User with id = " + model.UserId + " not found");
+        }
+
+        if (user.IsOwner(Tenant) || user.IsMe(AuthContext) || user.Status != EmployeeStatus.Terminated)
+        {
+            throw new ArgumentException("Can not delete user with id = " + model.UserId);
+        }
+
+        return _queueWorkerRemove.Start(Tenant.TenantId, user, SecurityContext.CurrentAccount.ID, true);
+    }
+}
diff --git a/products/ASC.People/Server/Api/ThirdpartyController.cs b/products/ASC.People/Server/Api/ThirdpartyController.cs
new file mode 100644
index 0000000000..24a951cdda
--- /dev/null
+++ b/products/ASC.People/Server/Api/ThirdpartyController.cs
@@ -0,0 +1,363 @@
+using SecurityContext = ASC.Core.SecurityContext;
+
+namespace ASC.People.Api;
+
+public class ThirdpartyController : BaseApiController
+{
+    private readonly IOptionsSnapshot<AccountLinker> _accountLinker;
+    private readonly CookiesManager _cookiesManager;
+    private readonly CoreBaseSettings _coreBaseSettings;
+    private readonly DisplayUserSettingsHelper _displayUserSettingsHelper;
+    private readonly IHttpClientFactory _httpClientFactory;
+    private readonly InstanceCrypto _instanceCrypto;
+    private readonly MobileDetector _mobileDetector;
+    private readonly PersonalSettingsHelper _personalSettingsHelper;
+    private readonly ProviderManager _providerManager;
+    private readonly Signature _signature;
+    private readonly TenantExtra _tenantExtra;
+    private readonly UserHelpTourHelper _userHelpTourHelper;
+    private readonly UserManagerWrapper _userManagerWrapper;
+    private readonly UserPhotoManager _userPhotoManager;
+
+    public ThirdpartyController(
+        UserManager userManager,
+        AuthContext authContext,
+        ApiContext apiContext,
+        PermissionContext permissionContext,
+        SecurityContext securityContext,
+        MessageService messageService,
+        MessageTarget messageTarget,
+        StudioNotifyService studioNotifyService,
+        IOptionsSnapshot<AccountLinker> optionsSnapshot,
+        CookiesManager cookiesManager,
+        CoreBaseSettings coreBaseSettings,
+        DisplayUserSettingsHelper displayUserSettingsHelper,
+        IHttpClientFactory httpClientFactory,
+        InstanceCrypto instanceCrypto,
+        MobileDetector mobileDetector,
+        PersonalSettingsHelper personalSettingsHelper,
+        ProviderManager providerManager,
+        Signature signature,
+        TenantExtra tenantExtra,
+        UserHelpTourHelper userHelpTourHelper,
+        UserManagerWrapper userManagerWrapper,
+        UserPhotoManager userPhotoManager
+        )
+        : base(
+            userManager,
+            authContext,
+            apiContext,
+            permissionContext,
+            securityContext,
+            messageService,
+            messageTarget,
+            studioNotifyService)
+    {
+        _accountLinker = optionsSnapshot;
+        _cookiesManager = cookiesManager;
+        _coreBaseSettings = coreBaseSettings;
+        _displayUserSettingsHelper = displayUserSettingsHelper;
+        _httpClientFactory = httpClientFactory;
+        _instanceCrypto = instanceCrypto;
+        _mobileDetector = mobileDetector;
+        _personalSettingsHelper = personalSettingsHelper;
+        _providerManager = providerManager;
+        _signature = signature;
+        _tenantExtra = tenantExtra;
+        _userHelpTourHelper = userHelpTourHelper;
+        _userManagerWrapper = userManagerWrapper;
+        _userPhotoManager = userPhotoManager;
+    }
+
+    [AllowAnonymous]
+    [Read("thirdparty/providers")]
+    public ICollection<AccountInfoDto> GetAuthProviders(bool inviteView, bool settingsView, string clientCallback, string fromOnly)
+    {
+        ICollection<AccountInfoDto> infos = new List<AccountInfoDto>();
+        IEnumerable<LoginProfile> linkedAccounts = new List<LoginProfile>();
+
+        if (AuthContext.IsAuthenticated)
+        {
+            linkedAccounts = _accountLinker.Get("webstudio").GetLinkedProfiles(AuthContext.CurrentAccount.ID.ToString());
+        }
+
+        fromOnly = string.IsNullOrWhiteSpace(fromOnly) ? string.Empty : fromOnly.ToLower();
+
+        foreach (var provider in ProviderManager.AuthProviders.Where(provider => string.IsNullOrEmpty(fromOnly) || fromOnly == provider || (provider == "google" && fromOnly == "openid")))
+        {
+            if (inviteView && provider.Equals("twitter", StringComparison.OrdinalIgnoreCase))
+            {
+                continue;
+            }
+            var loginProvider = _providerManager.GetLoginProvider(provider);
+            if (loginProvider != null && loginProvider.IsEnabled)
+            {
+
+                var url = VirtualPathUtility.ToAbsolute("~/login.ashx") + $"?auth={provider}";
+                var mode = settingsView || inviteView || (!_mobileDetector.IsMobile() && !Request.DesktopApp())
+                        ? $"&mode=popup&callback={clientCallback}"
+                        : "&mode=Redirect&desktop=true";
+
+                infos.Add(new AccountInfoDto
+                {
+                    Linked = linkedAccounts.Any(x => x.Provider == provider),
+                    Provider = provider,
+                    Url = url + mode
+                });
+            }
+        }
+
+        return infos;
+    }
+
+    [Update("thirdparty/linkaccount")]
+    public void LinkAccountFromBody([FromBody] LinkAccountRequestDto model)
+    {
+        LinkAccount(model);
+    }
+
+    [Update("thirdparty/linkaccount")]
+    [Consumes("application/x-www-form-urlencoded")]
+    public void LinkAccountFromForm([FromForm] LinkAccountRequestDto model)
+    {
+        LinkAccount(model);
+    }
+
+    [AllowAnonymous]
+    [Create("thirdparty/signup")]
+    public void SignupAccountFromBody([FromBody] SignupAccountRequestDto model)
+    {
+        SignupAccount(model);
+    }
+
+    [AllowAnonymous]
+    [Create("thirdparty/signup")]
+    [Consumes("application/x-www-form-urlencoded")]
+    public void SignupAccountFromForm([FromForm] SignupAccountRequestDto model)
+    {
+        SignupAccount(model);
+    }
+
+    [Delete("thirdparty/unlinkaccount")]
+    public void UnlinkAccount(string provider)
+    {
+        GetLinker().RemoveProvider(SecurityContext.CurrentAccount.ID.ToString(), provider);
+        MessageService.Send(MessageAction.UserUnlinkedSocialAccount, GetMeaningfulProviderName(provider));
+    }
+
+    private static string GetMeaningfulProviderName(string providerName)
+    {
+        switch (providerName)
+        {
+            case "google":
+            case "openid":
+                return "Google";
+            case "facebook":
+                return "Facebook";
+            case "twitter":
+                return "Twitter";
+            case "linkedin":
+                return "LinkedIn";
+            default:
+                return "Unknown Provider";
+        }
+    }
+
+    private UserInfo CreateNewUser(string firstName, string lastName, string email, string passwordHash, EmployeeType employeeType, bool fromInviteLink)
+    {
+        var isVisitor = employeeType == EmployeeType.Visitor;
+
+        if (SetupInfo.IsSecretEmail(email))
+        {
+            fromInviteLink = false;
+        }
+
+        var userInfo = new UserInfo
+        {
+            FirstName = string.IsNullOrEmpty(firstName) ? UserControlsCommonResource.UnknownFirstName : firstName,
+            LastName = string.IsNullOrEmpty(lastName) ? UserControlsCommonResource.UnknownLastName : lastName,
+            Email = email,
+        };
+
+        if (_coreBaseSettings.Personal)
+        {
+            userInfo.ActivationStatus = EmployeeActivationStatus.Activated;
+            userInfo.CultureName = _coreBaseSettings.CustomMode ? "ru-RU" : Thread.CurrentThread.CurrentUICulture.Name;
+        }
+
+        return _userManagerWrapper.AddUser(userInfo, passwordHash, true, true, isVisitor, fromInviteLink);
+    }
+
+    private string GetEmailAddress(SignupAccountRequestDto model)
+    {
+        if (!string.IsNullOrEmpty(model.Email))
+        {
+            return model.Email.Trim();
+        }
+
+        return string.Empty;
+    }
+
+    private string GetEmailAddress(SignupAccountRequestDto model, LoginProfile account)
+    {
+        var value = GetEmailAddress(model);
+
+        return string.IsNullOrEmpty(value) ? account.EMail : value;
+    }
+
+    private string GetFirstName(SignupAccountRequestDto model)
+    {
+        var value = string.Empty;
+        if (!string.IsNullOrEmpty(model.FirstName))
+        {
+            value = model.FirstName.Trim();
+        }
+
+        return HtmlUtil.GetText(value);
+    }
+
+    private string GetFirstName(SignupAccountRequestDto model, LoginProfile account)
+    {
+        var value = GetFirstName(model);
+
+        return string.IsNullOrEmpty(value) ? account.FirstName : value;
+    }
+
+    private string GetLastName(SignupAccountRequestDto model)
+    {
+        var value = string.Empty;
+        if (!string.IsNullOrEmpty(model.LastName))
+        {
+            value = model.LastName.Trim();
+        }
+
+        return HtmlUtil.GetText(value);
+    }
+
+    private string GetLastName(SignupAccountRequestDto model, LoginProfile account)
+    {
+        var value = GetLastName(model);
+
+        return string.IsNullOrEmpty(value) ? account.LastName : value;
+    }
+
+    private AccountLinker GetLinker()
+    {
+        return _accountLinker.Get("webstudio");
+    }
+
+    private void LinkAccount(LinkAccountRequestDto model)
+    {
+        var profile = new LoginProfile(_signature, _instanceCrypto, model.SerializedProfile);
+
+        if (!(_coreBaseSettings.Standalone || _tenantExtra.GetTenantQuota().Oauth))
+        {
+            throw new Exception("ErrorNotAllowedOption");
+        }
+
+        if (string.IsNullOrEmpty(profile.AuthorizationError))
+        {
+            GetLinker().AddLink(SecurityContext.CurrentAccount.ID.ToString(), profile);
+            MessageService.Send(MessageAction.UserLinkedSocialAccount, GetMeaningfulProviderName(profile.Provider));
+        }
+        else
+        {
+            // ignore cancellation
+            if (profile.AuthorizationError != "Canceled at provider")
+            {
+                throw new Exception(profile.AuthorizationError);
+            }
+        }
+    }
+
+    private void SaveContactImage(Guid userID, string url)
+    {
+        using (var memstream = new MemoryStream())
+        {
+            var request = new HttpRequestMessage();
+            request.RequestUri = new Uri(url);
+
+            var httpClient = _httpClientFactory.CreateClient();
+            using (var response = httpClient.Send(request))
+            using (var stream = response.Content.ReadAsStream())
+            {
+                var buffer = new byte[512];
+                int bytesRead;
+                while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
+                {
+                    memstream.Write(buffer, 0, bytesRead);
+                }
+
+                var bytes = memstream.ToArray();
+
+                _userPhotoManager.SaveOrUpdatePhoto(userID, bytes);
+            }
+        }
+    }
+
+    private void SignupAccount(SignupAccountRequestDto model)
+    {
+        var employeeType = model.EmplType ?? EmployeeType.User;
+        var passwordHash = model.PasswordHash;
+        var mustChangePassword = false;
+        if (string.IsNullOrEmpty(passwordHash))
+        {
+            passwordHash = UserManagerWrapper.GeneratePassword();
+            mustChangePassword = true;
+        }
+
+        var thirdPartyProfile = new LoginProfile(_signature, _instanceCrypto, model.SerializedProfile);
+        if (!string.IsNullOrEmpty(thirdPartyProfile.AuthorizationError))
+        {
+            // ignore cancellation
+            if (thirdPartyProfile.AuthorizationError != "Canceled at provider")
+            {
+                throw new Exception(thirdPartyProfile.AuthorizationError);
+            }
+
+            return;
+        }
+
+        if (string.IsNullOrEmpty(thirdPartyProfile.EMail))
+        {
+            throw new Exception(Resource.ErrorNotCorrectEmail);
+        }
+
+        var userID = Guid.Empty;
+        try
+        {
+            SecurityContext.AuthenticateMeWithoutCookie(ASC.Core.Configuration.Constants.CoreSystem);
+            var newUser = CreateNewUser(GetFirstName(model, thirdPartyProfile), GetLastName(model, thirdPartyProfile), GetEmailAddress(model, thirdPartyProfile), passwordHash, employeeType, false);
+            var messageAction = employeeType == EmployeeType.User ? MessageAction.UserCreatedViaInvite : MessageAction.GuestCreatedViaInvite;
+            MessageService.Send(MessageInitiator.System, messageAction, MessageTarget.Create(newUser.ID), newUser.DisplayUserName(false, _displayUserSettingsHelper));
+            userID = newUser.ID;
+            if (!string.IsNullOrEmpty(thirdPartyProfile.Avatar))
+            {
+                SaveContactImage(userID, thirdPartyProfile.Avatar);
+            }
+
+            GetLinker().AddLink(userID.ToString(), thirdPartyProfile);
+        }
+        finally
+        {
+            SecurityContext.Logout();
+        }
+
+        var user = UserManager.GetUsers(userID);
+        var cookiesKey = SecurityContext.AuthenticateMe(user.Email, passwordHash);
+        _cookiesManager.SetCookies(CookiesType.AuthKey, cookiesKey);
+        MessageService.Send(MessageAction.LoginSuccess);
+        StudioNotifyService.UserHasJoin();
+
+        if (mustChangePassword)
+        {
+            StudioNotifyService.UserPasswordChange(user);
+        }
+
+        _userHelpTourHelper.IsNewUser = true;
+        if (_coreBaseSettings.Personal)
+        {
+            _personalSettingsHelper.IsNewUser = true;
+        }
+    }
+}
diff --git a/products/ASC.People/Server/Api/UserController.cs b/products/ASC.People/Server/Api/UserController.cs
new file mode 100644
index 0000000000..8920dcd7b2
--- /dev/null
+++ b/products/ASC.People/Server/Api/UserController.cs
@@ -0,0 +1,1312 @@
+using SecurityContext = ASC.Core.SecurityContext;
+using Module = ASC.Api.Core.Module;
+
+namespace ASC.People.Api;
+
+public class UserController : BasePeopleController
+{
+    private readonly Constants _constants;
+    private readonly CookiesManager _cookiesManager;
+    private readonly CoreBaseSettings _coreBaseSettings;
+    private readonly CustomNamingPeople _customNamingPeople;
+    private readonly ILog _logger;
+    private readonly PasswordHasher _passwordHasher;
+    private readonly QueueWorkerReassign _queueWorkerReassign;
+    private readonly QueueWorkerRemove _queueWorkerRemove;
+    private readonly Recaptcha _recaptcha;
+    private readonly TenantExtra _tenantExtra;
+    private readonly TenantStatisticsProvider _tenantStatisticsProvider;
+    private readonly TenantUtil _tenantUtil;
+    private readonly UserFormatter _userFormatter;
+    private readonly UserManagerWrapper _userManagerWrapper;
+    private readonly UserPhotoManager _userPhotoManager;
+    private readonly WebItemManager _webItemManager;
+    private readonly WebItemSecurity _webItemSecurity;
+    private readonly WebItemSecurityCache _webItemSecurityCache;
+
+    public UserController(
+        UserManager userManager,
+        AuthContext authContext,
+        ApiContext apiContext,
+        PermissionContext permissionContext,
+        SecurityContext securityContext,
+        MessageService messageService,
+        MessageTarget messageTarget,
+        StudioNotifyService studioNotifyService,
+        Constants constants,
+        CookiesManager cookiesManager,
+        CoreBaseSettings coreBaseSettings,
+        CustomNamingPeople customNamingPeople,
+        ILog logger,
+        PasswordHasher passwordHasher,
+        QueueWorkerReassign queueWorkerReassign,
+        QueueWorkerRemove queueWorkerRemove,
+        Recaptcha recaptcha,
+        TenantExtra tenantExtra,
+        TenantStatisticsProvider tenantStatisticsProvider,
+        TenantUtil tenantUtil,
+        UserFormatter userFormatter,
+        UserManagerWrapper userManagerWrapper,
+        UserPhotoManager userPhotoManager,
+        WebItemManager webItemManager,
+        WebItemSecurity webItemSecurity,
+        WebItemSecurityCache webItemSecurityCache,
+        IMapper mapper
+        )
+        : base(
+            userManager,
+            authContext,
+            apiContext,
+            permissionContext,
+            securityContext,
+            messageService,
+            messageTarget,
+            studioNotifyService,
+            mapper)
+    {
+        _constants = constants;
+        _cookiesManager = cookiesManager;
+        _coreBaseSettings = coreBaseSettings;
+        _customNamingPeople = customNamingPeople;
+        _logger = logger;
+        _passwordHasher = passwordHasher;
+        _queueWorkerReassign = queueWorkerReassign;
+        _queueWorkerRemove = queueWorkerRemove;
+        _recaptcha = recaptcha;
+        _tenantExtra = tenantExtra;
+        _tenantStatisticsProvider = tenantStatisticsProvider;
+        _tenantUtil = tenantUtil;
+        _userFormatter = userFormatter;
+        _userManagerWrapper = userManagerWrapper;
+        _userPhotoManager = userPhotoManager;
+        _webItemManager = webItemManager;
+        _webItemSecurity = webItemSecurity;
+        _webItemSecurityCache = webItemSecurityCache;
+    }
+
+    [Create("active")]
+    public EmployeeFullDto AddMemberAsActivatedFromBody([FromBody] MemberRequestDto memberModel)
+    {
+        return AddMemberAsActivated(memberModel);
+    }
+
+    [Create("active")]
+    [Consumes("application/x-www-form-urlencoded")]
+    public EmployeeFullDto AddMemberAsActivatedFromForm([FromForm] MemberRequestDto memberModel)
+    {
+        return AddMemberAsActivated(memberModel);
+    }
+
+    [Create]
+    [Authorize(AuthenticationSchemes = "confirm", Roles = "LinkInvite,Everyone")]
+    public EmployeeFullDto AddMemberFromBody([FromBody] MemberRequestDto memberModel)
+    {
+        return AddMember(memberModel);
+    }
+
+    [Create]
+    [Authorize(AuthenticationSchemes = "confirm", Roles = "LinkInvite,Everyone")]
+    [Consumes("application/x-www-form-urlencoded")]
+    public EmployeeFullDto AddMemberFromForm([FromForm] MemberRequestDto memberModel)
+    {
+        return AddMember(memberModel);
+    }
+
+    [Update("{userid}/password")]
+    [Authorize(AuthenticationSchemes = "confirm", Roles = "PasswordChange,EmailChange,Activation,EmailActivation,Everyone")]
+    public EmployeeFullDto ChangeUserPasswordFromBody(Guid userid, [FromBody] MemberRequestDto memberModel)
+    {
+        return ChangeUserPassword(userid, memberModel);
+    }
+
+    [Update("{userid}/password")]
+    [Authorize(AuthenticationSchemes = "confirm", Roles = "PasswordChange,EmailChange,Activation,EmailActivation,Everyone")]
+    [Consumes("application/x-www-form-urlencoded")]
+    public EmployeeFullDto ChangeUserPasswordFromForm(Guid userid, [FromForm] MemberRequestDto memberModel)
+    {
+        return ChangeUserPassword(userid, memberModel);
+    }
+
+    [Delete("{userid}")]
+    public EmployeeFullDto DeleteMember(string userid)
+    {
+        PermissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
+
+        var user = GetUserInfo(userid);
+
+        if (UserManager.IsSystemUser(user.ID) || user.IsLDAP())
+        {
+            throw new SecurityException();
+        }
+
+        if (user.Status != EmployeeStatus.Terminated)
+        {
+            throw new Exception("The user is not suspended");
+        }
+
+        CheckReassignProccess(new[] { user.ID });
+
+        var userName = user.DisplayUserName(false, DisplayUserSettingsHelper);
+        _userPhotoManager.RemovePhoto(user.ID);
+        UserManager.DeleteUser(user.ID);
+        _queueWorkerRemove.Start(Tenant.TenantId, user, SecurityContext.CurrentAccount.ID, false);
+
+        MessageService.Send(MessageAction.UserDeleted, MessageTarget.Create(user.ID), userName);
+
+        return Mapper.Map<UserInfo, EmployeeFullDto>(user);
+    }
+
+    [Delete("@self")]
+    [Authorize(AuthenticationSchemes = "confirm", Roles = "ProfileRemove")]
+    public EmployeeFullDto DeleteProfile()
+    {
+        ApiContext.AuthByClaim();
+
+        if (UserManager.IsSystemUser(SecurityContext.CurrentAccount.ID))
+        {
+            throw new SecurityException();
+        }
+
+        var user = GetUserInfo(SecurityContext.CurrentAccount.ID.ToString());
+
+        if (!UserManager.UserExists(user))
+        {
+            throw new Exception(Resource.ErrorUserNotFound);
+        }
+
+        if (user.IsLDAP())
+        {
+            throw new SecurityException();
+        }
+
+        SecurityContext.AuthenticateMeWithoutCookie(ASC.Core.Configuration.Constants.CoreSystem);
+        user.Status = EmployeeStatus.Terminated;
+
+        UserManager.SaveUserInfo(user);
+        var userName = user.DisplayUserName(false, DisplayUserSettingsHelper);
+        MessageService.Send(MessageAction.UsersUpdatedStatus, MessageTarget.Create(user.ID), userName);
+
+        _cookiesManager.ResetUserCookie(user.ID);
+        MessageService.Send(MessageAction.CookieSettingsUpdated);
+
+        if (_coreBaseSettings.Personal)
+        {
+            _userPhotoManager.RemovePhoto(user.ID);
+            UserManager.DeleteUser(user.ID);
+            MessageService.Send(MessageAction.UserDeleted, MessageTarget.Create(user.ID), userName);
+        }
+        else
+        {
+            //StudioNotifyService.Instance.SendMsgProfileHasDeletedItself(user);
+            //StudioNotifyService.SendMsgProfileDeletion(Tenant.TenantId, user);
+        }
+
+        return Mapper.Map<UserInfo, EmployeeFullDto>(user);
+    }
+
+    [Read("status/{status}/search")]
+    public IEnumerable<EmployeeFullDto> GetAdvanced(EmployeeStatus status, [FromQuery] string query)
+    {
+        if (_coreBaseSettings.Personal)
+        {
+            throw new MethodAccessException("Method not available");
+        }
+        try
+        {
+            var list = UserManager.GetUsers(status).AsEnumerable();
+
+            if ("group".Equals(ApiContext.FilterBy, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(ApiContext.FilterValue))
+            {
+                var groupId = new Guid(ApiContext.FilterValue);
+                //Filter by group
+                list = list.Where(x => UserManager.IsUserInGroup(x.ID, groupId));
+                ApiContext.SetDataFiltered();
+            }
+
+            list = list.Where(x => x.FirstName != null && x.FirstName.IndexOf(query, StringComparison.OrdinalIgnoreCase) > -1 || (x.LastName != null && x.LastName.IndexOf(query, StringComparison.OrdinalIgnoreCase) != -1) ||
+                                   (x.UserName != null && x.UserName.IndexOf(query, StringComparison.OrdinalIgnoreCase) != -1) || (x.Email != null && x.Email.IndexOf(query, StringComparison.OrdinalIgnoreCase) != -1) || (x.ContactsList != null && x.ContactsList.Any(y => y.IndexOf(query, StringComparison.OrdinalIgnoreCase) != -1)));
+
+            return Mapper.Map<IEnumerable<UserInfo>, IEnumerable<EmployeeFullDto>>(list);
+        }
+        catch (Exception error)
+        {
+            _logger.Error(error);
+        }
+
+        return null;
+    }
+
+    [Read]
+    public IEnumerable<EmployeeDto> GetAll()
+    {
+        return GetByStatus(EmployeeStatus.Active);
+    }
+
+    [Read("email")]
+    public EmployeeFullDto GetByEmail([FromQuery] string email)
+    {
+        if (_coreBaseSettings.Personal && !UserManager.GetUsers(SecurityContext.CurrentAccount.ID).IsOwner(Tenant))
+        {
+            throw new MethodAccessException("Method not available");
+        }
+
+        var user = UserManager.GetUserByEmail(email);
+        if (user.ID == Constants.LostUser.ID)
+        {
+            throw new ItemNotFoundException("User not found");
+        }
+
+        return Mapper.Map<UserInfo, EmployeeFullDto>(user);
+    }
+
+    [Read("{username}", order: int.MaxValue)]
+    public EmployeeFullDto GetById(string username)
+    {
+        if (_coreBaseSettings.Personal)
+        {
+            throw new MethodAccessException("Method not available");
+        }
+
+        var user = UserManager.GetUserByUserName(username);
+        if (user.ID == Constants.LostUser.ID)
+        {
+            if (Guid.TryParse(username, out var userId))
+            {
+                user = UserManager.GetUsers(userId);
+            }
+            else
+            {
+                _logger.Error(string.Format("Account {0} сould not get user by name {1}", SecurityContext.CurrentAccount.ID, username));
+            }
+        }
+
+        if (user.ID == Constants.LostUser.ID)
+        {
+            throw new ItemNotFoundException("User not found");
+        }
+
+        return Mapper.Map<UserInfo, EmployeeFullDto>(user);
+    }
+
+    [Read("status/{status}")]
+    public IEnumerable<EmployeeDto> GetByStatus(EmployeeStatus status)
+    {
+        if (_coreBaseSettings.Personal)
+        {
+            throw new Exception("Method not available");
+        }
+
+        Guid? groupId = null;
+        if ("group".Equals(ApiContext.FilterBy, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(ApiContext.FilterValue))
+        {
+            groupId = new Guid(ApiContext.FilterValue);
+            ApiContext.SetDataFiltered();
+        }
+
+        return GetFullByFilter(status, groupId, null, null, null);
+    }
+
+    [Read("filter")]
+    public IEnumerable<EmployeeFullDto> GetFullByFilter(EmployeeStatus? employeeStatus, Guid? groupId, EmployeeActivationStatus? activationStatus, EmployeeType? employeeType, bool? isAdministrator)
+    {
+        var users = GetByFilter(employeeStatus, groupId, activationStatus, employeeType, isAdministrator).AsEnumerable();
+
+        return Mapper.Map<IEnumerable<UserInfo>, IEnumerable<EmployeeFullDto>>(users);
+    }
+
+    [Read("info")]
+    public Module GetModule()
+    {
+        var product = new PeopleProduct();
+        product.Init();
+
+        return new Module(product);
+    }
+    [Read("search")]
+    public IEnumerable<EmployeeFullDto> GetPeopleSearch([FromQuery] string query)
+    {
+        return GetSearch(query);
+    }
+
+    [Read("@search/{query}")]
+    public IEnumerable<EmployeeFullDto> GetSearch(string query)
+    {
+        if (_coreBaseSettings.Personal)
+        {
+            throw new MethodAccessException("Method not available");
+        }
+
+        try
+        {
+            var groupId = Guid.Empty;
+            if ("group".Equals(ApiContext.FilterBy, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(ApiContext.FilterValue))
+            {
+                groupId = new Guid(ApiContext.FilterValue);
+            }
+
+            var users = UserManager.Search(query, EmployeeStatus.Active, groupId);
+
+            return Mapper.Map<IEnumerable<UserInfo>, IEnumerable<EmployeeFullDto>>(users);
+        }
+        catch (Exception error)
+        {
+            _logger.Error(error);
+        }
+
+        return null;
+    }
+
+    [Read("simple/filter")]
+    public IEnumerable<EmployeeDto> GetSimpleByFilter(EmployeeStatus? employeeStatus, Guid? groupId, EmployeeActivationStatus? activationStatus, EmployeeType? employeeType, bool? isAdministrator)
+    {
+        var users = GetByFilter(employeeStatus, groupId, activationStatus, employeeType, isAdministrator);
+
+        return Mapper.Map<IEnumerable<UserInfo>, IEnumerable<EmployeeDto>>(users);
+    }
+
+    [AllowAnonymous]
+    [Create(@"register")]
+    public Task<string> RegisterUserOnPersonalAsync(RegisterPersonalUserRequestDto model)
+    {
+        if (!_coreBaseSettings.Personal) throw new MethodAccessException("Method is only available on personal.onlyoffice.com");
+
+        return InternalRegisterUserOnPersonalAsync(model);
+    }
+
+    [Update("delete", Order = -1)]
+    public IEnumerable<EmployeeFullDto> RemoveUsersFromBody([FromBody] UpdateMembersRequestDto model)
+    {
+        return RemoveUsers(model);
+    }
+
+    [Update("delete", Order = -1)]
+    [Consumes("application/x-www-form-urlencoded")]
+    public IEnumerable<EmployeeFullDto> RemoveUsersFromForm([FromForm] UpdateMembersRequestDto model)
+    {
+        return RemoveUsers(model);
+    }
+
+    [Update("invite")]
+    public IEnumerable<EmployeeFullDto> ResendUserInvitesFromBody([FromBody] UpdateMembersRequestDto model)
+    {
+        return ResendUserInvites(model);
+    }
+
+    [Update("invite")]
+    [Consumes("application/x-www-form-urlencoded")]
+    public IEnumerable<EmployeeFullDto> ResendUserInvitesFromForm([FromForm] UpdateMembersRequestDto model)
+    {
+        return ResendUserInvites(model);
+    }
+
+    [Read("@self")]
+    public EmployeeDto Self()
+    {
+        var user = UserManager.GetUser(SecurityContext.CurrentAccount.ID, EmployeeWraperFullHelper.GetExpression(ApiContext));
+
+        return Mapper.Map<UserInfo, EmployeeFullDto>(user);
+    }
+
+    [Create("email", false)]
+    public object SendEmailChangeInstructionsFromBody([FromBody] UpdateMemberRequestDto model)
+    {
+        return SendEmailChangeInstructions(model);
+    }
+
+    [Create("email", false)]
+    [Consumes("application/x-www-form-urlencoded")]
+    public object SendEmailChangeInstructionsFromForm([FromForm] UpdateMemberRequestDto model)
+    {
+        return SendEmailChangeInstructions(model);
+    }
+
+    [AllowAnonymous]
+    [Create("password", false)]
+    public object SendUserPasswordFromBody([FromBody] MemberRequestDto memberModel)
+    {
+        return SendUserPassword(memberModel);
+    }
+
+    [AllowAnonymous]
+    [Create("password", false)]
+    [Consumes("application/x-www-form-urlencoded")]
+    public object SendUserPasswordFromForm([FromForm] MemberRequestDto memberModel)
+    {
+        return SendUserPassword(memberModel);
+    }
+
+    [Update("activationstatus/{activationstatus}")]
+    [Authorize(AuthenticationSchemes = "confirm", Roles = "Activation,Everyone")]
+    public IEnumerable<EmployeeFullDto> UpdateEmployeeActivationStatusFromBody(EmployeeActivationStatus activationstatus, [FromBody] UpdateMembersRequestDto model)
+    {
+        return UpdateEmployeeActivationStatus(activationstatus, model);
+    }
+
+    [Update("activationstatus/{activationstatus}")]
+    [Authorize(AuthenticationSchemes = "confirm", Roles = "Activation,Everyone")]
+    [Consumes("application/x-www-form-urlencoded")]
+    public IEnumerable<EmployeeFullDto> UpdateEmployeeActivationStatusFromForm(EmployeeActivationStatus activationstatus, [FromForm] UpdateMembersRequestDto model)
+    {
+        return UpdateEmployeeActivationStatus(activationstatus, model);
+    }
+
+    [Update("{userid}/culture")]
+    public EmployeeFullDto UpdateMemberCultureFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
+    {
+        return UpdateMemberCulture(userid, memberModel);
+    }
+
+    [Update("{userid}/culture")]
+    [Consumes("application/x-www-form-urlencoded")]
+    public EmployeeFullDto UpdateMemberCultureFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
+    {
+        return UpdateMemberCulture(userid, memberModel);
+    }
+
+    [Update("{userid}")]
+    public EmployeeFullDto UpdateMemberFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
+    {
+        return UpdateMember(userid, memberModel);
+    }
+
+    [Update("{userid}")]
+    [Consumes("application/x-www-form-urlencoded")]
+    public EmployeeFullDto UpdateMemberFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
+    {
+        return UpdateMember(userid, memberModel);
+    }
+
+    [Update("status/{status}")]
+    public IEnumerable<EmployeeFullDto> UpdateUserStatusFromBody(EmployeeStatus status, [FromBody] UpdateMembersRequestDto model)
+    {
+        return UpdateUserStatus(status, model);
+    }
+
+    [Update("status/{status}")]
+    [Consumes("application/x-www-form-urlencoded")]
+    public IEnumerable<EmployeeFullDto> UpdateUserStatusFromForm(EmployeeStatus status, [FromForm] UpdateMembersRequestDto model)
+    {
+        return UpdateUserStatus(status, model);
+    }
+
+    [Update("type/{type}")]
+    public IEnumerable<EmployeeFullDto> UpdateUserTypeFromBody(EmployeeType type, [FromBody] UpdateMembersRequestDto model)
+    {
+        return UpdateUserType(type, model);
+    }
+
+    [Update("type/{type}")]
+    [Consumes("application/x-www-form-urlencoded")]
+    public IEnumerable<EmployeeFullDto> UpdateUserTypeFromForm(EmployeeType type, [FromForm] UpdateMembersRequestDto model)
+    {
+        return UpdateUserType(type, model);
+    }
+
+    private EmployeeFullDto AddMember(MemberRequestDto memberModel)
+    {
+        ApiContext.AuthByClaim();
+
+        PermissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
+
+        memberModel.PasswordHash = (memberModel.PasswordHash ?? "").Trim();
+        if (string.IsNullOrEmpty(memberModel.PasswordHash))
+        {
+            memberModel.Password = (memberModel.Password ?? "").Trim();
+
+            if (string.IsNullOrEmpty(memberModel.Password))
+            {
+                memberModel.Password = UserManagerWrapper.GeneratePassword();
+            }
+            else
+            {
+                _userManagerWrapper.CheckPasswordPolicy(memberModel.Password);
+            }
+            memberModel.PasswordHash = _passwordHasher.GetClientPassword(memberModel.Password);
+        }
+
+        var user = new UserInfo();
+
+        //Validate email
+        var address = new MailAddress(memberModel.Email);
+        user.Email = address.Address;
+        //Set common fields
+        user.FirstName = memberModel.Firstname;
+        user.LastName = memberModel.Lastname;
+        user.Title = memberModel.Title;
+        user.Location = memberModel.Location;
+        user.Notes = memberModel.Comment;
+        user.Sex = "male".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase)
+                       ? true
+                       : ("female".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase) ? (bool?)false : null);
+
+        user.BirthDate = memberModel.Birthday != null && memberModel.Birthday != DateTime.MinValue ? _tenantUtil.DateTimeFromUtc(memberModel.Birthday) : null;
+        user.WorkFromDate = memberModel.Worksfrom != null && memberModel.Worksfrom != DateTime.MinValue ? _tenantUtil.DateTimeFromUtc(memberModel.Worksfrom) : DateTime.UtcNow.Date;
+
+        UpdateContacts(memberModel.Contacts, user);
+
+        user = _userManagerWrapper.AddUser(user, memberModel.PasswordHash, memberModel.FromInviteLink, true, memberModel.IsVisitor, memberModel.FromInviteLink);
+
+        var messageAction = memberModel.IsVisitor ? MessageAction.GuestCreated : MessageAction.UserCreated;
+        MessageService.Send(messageAction, MessageTarget.Create(user.ID), user.DisplayUserName(false, DisplayUserSettingsHelper));
+
+        UpdateDepartments(memberModel.Department, user);
+
+        if (memberModel.Files != _userPhotoManager.GetDefaultPhotoAbsoluteWebPath())
+        {
+            UpdatePhotoUrl(memberModel.Files, user);
+        }
+
+        return Mapper.Map<UserInfo, EmployeeFullDto>(user);
+    }
+
+    private EmployeeFullDto AddMemberAsActivated(MemberRequestDto memberModel)
+    {
+        PermissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
+
+        var user = new UserInfo();
+
+        memberModel.PasswordHash = (memberModel.PasswordHash ?? "").Trim();
+        if (string.IsNullOrEmpty(memberModel.PasswordHash))
+        {
+            memberModel.Password = (memberModel.Password ?? "").Trim();
+
+            if (string.IsNullOrEmpty(memberModel.Password))
+            {
+                memberModel.Password = UserManagerWrapper.GeneratePassword();
+            }
+            else
+            {
+                _userManagerWrapper.CheckPasswordPolicy(memberModel.Password);
+            }
+
+            memberModel.PasswordHash = _passwordHasher.GetClientPassword(memberModel.Password);
+        }
+
+        //Validate email
+        var address = new MailAddress(memberModel.Email);
+        user.Email = address.Address;
+        //Set common fields
+        user.FirstName = memberModel.Firstname;
+        user.LastName = memberModel.Lastname;
+        user.Title = memberModel.Title;
+        user.Location = memberModel.Location;
+        user.Notes = memberModel.Comment;
+        user.Sex = "male".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase)
+                       ? true
+                       : ("female".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase) ? (bool?)false : null);
+
+        user.BirthDate = memberModel.Birthday != null ? _tenantUtil.DateTimeFromUtc(memberModel.Birthday) : null;
+        user.WorkFromDate = memberModel.Worksfrom != null ? _tenantUtil.DateTimeFromUtc(memberModel.Worksfrom) : DateTime.UtcNow.Date;
+
+        UpdateContacts(memberModel.Contacts, user);
+
+        user = _userManagerWrapper.AddUser(user, memberModel.PasswordHash, false, false, memberModel.IsVisitor);
+
+        user.ActivationStatus = EmployeeActivationStatus.Activated;
+
+        UpdateDepartments(memberModel.Department, user);
+
+        if (memberModel.Files != _userPhotoManager.GetDefaultPhotoAbsoluteWebPath())
+        {
+            UpdatePhotoUrl(memberModel.Files, user);
+        }
+
+        return Mapper.Map<UserInfo, EmployeeFullDto>(user);
+    }
+
+    private EmployeeFullDto ChangeUserPassword(Guid userid, MemberRequestDto memberModel)
+    {
+        ApiContext.AuthByClaim();
+        PermissionContext.DemandPermissions(new UserSecurityProvider(userid), Constants.Action_EditUser);
+
+        var user = UserManager.GetUsers(userid);
+
+        if (!UserManager.UserExists(user))
+        {
+            return null;
+        }
+
+        if (UserManager.IsSystemUser(user.ID))
+        {
+            throw new SecurityException();
+        }
+
+        if (!string.IsNullOrEmpty(memberModel.Email))
+        {
+            var address = new MailAddress(memberModel.Email);
+            if (!string.Equals(address.Address, user.Email, StringComparison.OrdinalIgnoreCase))
+            {
+                user.Email = address.Address.ToLowerInvariant();
+                user.ActivationStatus = EmployeeActivationStatus.Activated;
+                UserManager.SaveUserInfo(user);
+            }
+        }
+
+        memberModel.PasswordHash = (memberModel.PasswordHash ?? "").Trim();
+        if (string.IsNullOrEmpty(memberModel.PasswordHash))
+        {
+            memberModel.Password = (memberModel.Password ?? "").Trim();
+
+            if (!string.IsNullOrEmpty(memberModel.Password))
+            {
+                memberModel.PasswordHash = _passwordHasher.GetClientPassword(memberModel.Password);
+            }
+        }
+
+        if (!string.IsNullOrEmpty(memberModel.PasswordHash))
+        {
+            SecurityContext.SetUserPasswordHash(userid, memberModel.PasswordHash);
+            MessageService.Send(MessageAction.UserUpdatedPassword);
+
+            _cookiesManager.ResetUserCookie(userid);
+            MessageService.Send(MessageAction.CookieSettingsUpdated);
+        }
+
+        return Mapper.Map<UserInfo, EmployeeFullDto>(GetUserInfo(userid.ToString()));
+    }
+
+    private void CheckReassignProccess(IEnumerable<Guid> userIds)
+    {
+        foreach (var userId in userIds)
+        {
+            var reassignStatus = _queueWorkerReassign.GetProgressItemStatus(Tenant.TenantId, userId);
+            if (reassignStatus == null || reassignStatus.IsCompleted)
+            {
+                continue;
+            }
+
+            var userName = UserManager.GetUsers(userId).DisplayUserName(DisplayUserSettingsHelper);
+
+            throw new Exception(string.Format(Resource.ReassignDataRemoveUserError, userName));
+        }
+    }
+
+    private IQueryable<UserInfo> GetByFilter(EmployeeStatus? employeeStatus, Guid? groupId, EmployeeActivationStatus? activationStatus, EmployeeType? employeeType, bool? isAdministrator)
+    {
+        if (_coreBaseSettings.Personal)
+        {
+            throw new MethodAccessException("Method not available");
+        }
+
+        var isAdmin = UserManager.GetUsers(SecurityContext.CurrentAccount.ID).IsAdmin(UserManager) ||
+                      _webItemSecurity.IsProductAdministrator(WebItemManager.PeopleProductID, SecurityContext.CurrentAccount.ID);
+
+        var includeGroups = new List<List<Guid>>();
+        if (groupId.HasValue)
+        {
+            includeGroups.Add(new List<Guid> { groupId.Value });
+        }
+
+        var excludeGroups = new List<Guid>();
+
+        if (employeeType != null)
+        {
+            switch (employeeType)
+            {
+                case EmployeeType.User:
+                    excludeGroups.Add(Constants.GroupVisitor.ID);
+                    break;
+                case EmployeeType.Visitor:
+                    includeGroups.Add(new List<Guid> { Constants.GroupVisitor.ID });
+                    break;
+            }
+        }
+
+        if (isAdministrator.HasValue && isAdministrator.Value)
+        {
+            var adminGroups = new List<Guid>
+            {
+                    Constants.GroupAdmin.ID
+            };
+            var products = _webItemManager.GetItemsAll().Where(i => i is IProduct || i.ID == WebItemManager.MailProductID);
+            adminGroups.AddRange(products.Select(r => r.ID));
+
+            includeGroups.Add(adminGroups);
+        }
+
+        var users = UserManager.GetUsers(isAdmin, employeeStatus, includeGroups, excludeGroups, activationStatus, ApiContext.FilterValue, ApiContext.SortBy, !ApiContext.SortDescending, ApiContext.Count, ApiContext.StartIndex, out var total, out var count);
+
+        ApiContext.SetTotalCount(total).SetCount(count);
+
+        return users;
+    }
+
+    private async Task<string> InternalRegisterUserOnPersonalAsync(RegisterPersonalUserRequestDto model)
+    {
+        try
+        {
+            if (_coreBaseSettings.CustomMode) model.Lang = "ru-RU";
+
+            var cultureInfo = SetupInfo.GetPersonalCulture(model.Lang).Value;
+
+            if (cultureInfo != null)
+            {
+                Thread.CurrentThread.CurrentUICulture = cultureInfo;
+            }
+
+            model.Email.ThrowIfNull(new ArgumentException(Resource.ErrorEmailEmpty, "email"));
+
+            if (!model.Email.TestEmailRegex()) throw new ArgumentException(Resource.ErrorNotCorrectEmail, "email");
+
+            if (!SetupInfo.IsSecretEmail(model.Email)
+                && !string.IsNullOrEmpty(SetupInfo.RecaptchaPublicKey) && !string.IsNullOrEmpty(SetupInfo.RecaptchaPrivateKey))
+            {
+                var ip = Request.Headers["X-Forwarded-For"].ToString() ?? Request.GetUserHostAddress();
+
+                if (string.IsNullOrEmpty(model.RecaptchaResponse)
+                    || !await _recaptcha.ValidateRecaptchaAsync(model.RecaptchaResponse, ip))
+                {
+                    throw new RecaptchaException(Resource.RecaptchaInvalid);
+                }
+            }
+
+            var newUserInfo = UserManager.GetUserByEmail(model.Email);
+
+            if (UserManager.UserExists(newUserInfo.ID))
+            {
+                if (!SetupInfo.IsSecretEmail(model.Email) || SecurityContext.IsAuthenticated)
+                {
+                    StudioNotifyService.SendAlreadyExist(model.Email);
+                    return string.Empty;
+                }
+
+                try
+                {
+                    SecurityContext.AuthenticateMe(ASC.Core.Configuration.Constants.CoreSystem);
+                    UserManager.DeleteUser(newUserInfo.ID);
+                }
+                finally
+                {
+                    SecurityContext.Logout();
+                }
+            }
+            if (!model.Spam)
+            {
+                try
+                {
+                    //TODO
+                    //const string _databaseID = "com";
+                    //using (var db = DbManager.FromHttpContext(_databaseID))
+                    //{
+                    //    db.ExecuteNonQuery(new SqlInsert("template_unsubscribe", false)
+                    //                           .InColumnValue("email", email.ToLowerInvariant())
+                    //                           .InColumnValue("reason", "personal")
+                    //        );
+                    //    Log.Debug(String.Format("Write to template_unsubscribe {0}", email.ToLowerInvariant()));
+                    //}
+                }
+                catch (Exception ex)
+                {
+                    _logger.Debug($"ERROR write to template_unsubscribe {ex.Message}, email:{model.Email.ToLowerInvariant()}");
+                }
+            }
+
+            StudioNotifyService.SendInvitePersonal(model.Email);
+        }
+        catch (Exception ex)
+        {
+            return ex.Message;
+        }
+
+        return string.Empty;
+    }
+    private IEnumerable<EmployeeFullDto> RemoveUsers(UpdateMembersRequestDto model)
+    {
+        PermissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
+
+        CheckReassignProccess(model.UserIds);
+
+        var users = model.UserIds.Select(userId => UserManager.GetUsers(userId))
+            .Where(u => !UserManager.IsSystemUser(u.ID) && !u.IsLDAP())
+            .ToList();
+
+        var userNames = users.Select(x => x.DisplayUserName(false, DisplayUserSettingsHelper)).ToList();
+
+        foreach (var user in users)
+        {
+            if (user.Status != EmployeeStatus.Terminated)
+            {
+                continue;
+            }
+
+            _userPhotoManager.RemovePhoto(user.ID);
+            UserManager.DeleteUser(user.ID);
+            _queueWorkerRemove.Start(Tenant.TenantId, user, SecurityContext.CurrentAccount.ID, false);
+        }
+
+        MessageService.Send(MessageAction.UsersDeleted, MessageTarget.Create(users.Select(x => x.ID)), userNames);
+
+        return Mapper.Map<IEnumerable<UserInfo>, IEnumerable<EmployeeFullDto>>(users);
+    }
+
+    private IEnumerable<EmployeeFullDto> ResendUserInvites(UpdateMembersRequestDto model)
+    {
+        var users = model.UserIds
+            .Where(userId => !UserManager.IsSystemUser(userId))
+            .Select(userId => UserManager.GetUsers(userId))
+            .ToList();
+
+        foreach (var user in users)
+        {
+            if (user.IsActive)
+            {
+                continue;
+            }
+
+            var viewer = UserManager.GetUsers(SecurityContext.CurrentAccount.ID);
+
+            if (viewer == null)
+            {
+                throw new Exception(Resource.ErrorAccessDenied);
+            }
+
+            if (viewer.IsAdmin(UserManager) || viewer.ID == user.ID)
+            {
+                if (user.ActivationStatus == EmployeeActivationStatus.Activated)
+                {
+                    user.ActivationStatus = EmployeeActivationStatus.NotActivated;
+                }
+                if (user.ActivationStatus == (EmployeeActivationStatus.AutoGenerated | EmployeeActivationStatus.Activated))
+                {
+                    user.ActivationStatus = EmployeeActivationStatus.AutoGenerated;
+                }
+
+                UserManager.SaveUserInfo(user);
+            }
+
+            if (user.ActivationStatus == EmployeeActivationStatus.Pending)
+            {
+                if (user.IsVisitor(UserManager))
+                {
+                    StudioNotifyService.GuestInfoActivation(user);
+                }
+                else
+                {
+                    StudioNotifyService.UserInfoActivation(user);
+                }
+            }
+            else
+            {
+                StudioNotifyService.SendEmailActivationInstructions(user, user.Email);
+            }
+        }
+
+        MessageService.Send(MessageAction.UsersSentActivationInstructions, MessageTarget.Create(users.Select(x => x.ID)), users.Select(x => x.DisplayUserName(false, DisplayUserSettingsHelper)));
+
+        return Mapper.Map<IEnumerable<UserInfo>, IEnumerable<EmployeeFullDto>>(users);
+    }
+
+    private object SendEmailChangeInstructions(UpdateMemberRequestDto model)
+    {
+        Guid.TryParse(model.UserId, out var userid);
+
+        if (userid == Guid.Empty)
+        {
+            throw new ArgumentNullException("userid");
+        }
+
+        var email = (model.Email ?? "").Trim();
+
+        if (string.IsNullOrEmpty(email))
+        {
+            throw new Exception(Resource.ErrorEmailEmpty);
+        }
+
+        if (!email.TestEmailRegex())
+        {
+            throw new Exception(Resource.ErrorNotCorrectEmail);
+        }
+
+        var viewer = UserManager.GetUsers(SecurityContext.CurrentAccount.ID);
+        var user = UserManager.GetUsers(userid);
+
+        if (user == null)
+        {
+            throw new Exception(Resource.ErrorUserNotFound);
+        }
+
+        if (viewer == null || (user.IsOwner(Tenant) && viewer.ID != user.ID))
+        {
+            throw new Exception(Resource.ErrorAccessDenied);
+        }
+
+        var existentUser = UserManager.GetUserByEmail(email);
+
+        if (existentUser.ID != Constants.LostUser.ID)
+        {
+            throw new Exception(_customNamingPeople.Substitute<Resource>("ErrorEmailAlreadyExists"));
+        }
+
+        if (!viewer.IsAdmin(UserManager))
+        {
+            StudioNotifyService.SendEmailChangeInstructions(user, email);
+        }
+        else
+        {
+            if (email == user.Email)
+            {
+                throw new Exception(Resource.ErrorEmailsAreTheSame);
+            }
+
+            user.Email = email;
+            user.ActivationStatus = EmployeeActivationStatus.NotActivated;
+            UserManager.SaveUserInfo(user);
+            StudioNotifyService.SendEmailActivationInstructions(user, email);
+        }
+
+        MessageService.Send(MessageAction.UserSentEmailChangeInstructions, user.DisplayUserName(false, DisplayUserSettingsHelper));
+
+        return string.Format(Resource.MessageEmailChangeInstuctionsSentOnEmail, email);
+    }
+
+    private object SendUserPassword(MemberRequestDto memberModel)
+    {
+        string error = _userManagerWrapper.SendUserPassword(memberModel.Email);
+        if (!string.IsNullOrEmpty(error))
+        {
+            _logger.ErrorFormat("Password recovery ({0}): {1}", memberModel.Email, error);
+        }
+
+        return string.Format(Resource.MessageYourPasswordSendedToEmail, memberModel.Email);
+    }
+
+    private void UpdateDepartments(IEnumerable<Guid> department, UserInfo user)
+    {
+        if (!PermissionContext.CheckPermissions(Constants.Action_EditGroups))
+        {
+            return;
+        }
+
+        if (department == null)
+        {
+            return;
+        }
+
+        var groups = UserManager.GetUserGroups(user.ID);
+        var managerGroups = new List<Guid>();
+        foreach (var groupInfo in groups)
+        {
+            UserManager.RemoveUserFromGroup(user.ID, groupInfo.ID);
+            var managerId = UserManager.GetDepartmentManager(groupInfo.ID);
+            if (managerId == user.ID)
+            {
+                managerGroups.Add(groupInfo.ID);
+                UserManager.SetDepartmentManager(groupInfo.ID, Guid.Empty);
+            }
+        }
+        foreach (var guid in department)
+        {
+            var userDepartment = UserManager.GetGroupInfo(guid);
+            if (userDepartment != Constants.LostGroupInfo)
+            {
+                UserManager.AddUserIntoGroup(user.ID, guid);
+                if (managerGroups.Contains(guid))
+                {
+                    UserManager.SetDepartmentManager(guid, user.ID);
+                }
+            }
+        }
+    }
+
+    private IEnumerable<EmployeeFullDto> UpdateEmployeeActivationStatus(EmployeeActivationStatus activationstatus, UpdateMembersRequestDto model)
+    {
+        ApiContext.AuthByClaim();
+
+        var retuls = new List<EmployeeFullDto>();
+        foreach (var id in model.UserIds.Where(userId => !UserManager.IsSystemUser(userId)))
+        {
+            PermissionContext.DemandPermissions(new UserSecurityProvider(id), Constants.Action_EditUser);
+            var u = UserManager.GetUsers(id);
+            if (u.ID == Constants.LostUser.ID || u.IsLDAP())
+            {
+                continue;
+            }
+
+            u.ActivationStatus = activationstatus;
+            UserManager.SaveUserInfo(u);
+            retuls.Add(Mapper.Map<UserInfo, EmployeeFullDto>(u));
+        }
+
+        return retuls;
+    }
+
+    private EmployeeFullDto UpdateMember(string userid, UpdateMemberRequestDto memberModel)
+    {
+        var user = GetUserInfo(userid);
+
+        if (UserManager.IsSystemUser(user.ID))
+        {
+            throw new SecurityException();
+        }
+
+        PermissionContext.DemandPermissions(new UserSecurityProvider(user.ID), Constants.Action_EditUser);
+        var self = SecurityContext.CurrentAccount.ID.Equals(user.ID);
+        var resetDate = new DateTime(1900, 01, 01);
+
+        //Update it
+
+        var isLdap = user.IsLDAP();
+        var isSso = user.IsSSO();
+        var isAdmin = _webItemSecurity.IsProductAdministrator(WebItemManager.PeopleProductID, SecurityContext.CurrentAccount.ID);
+
+        if (!isLdap && !isSso)
+        {
+            //Set common fields
+
+            user.FirstName = memberModel.Firstname ?? user.FirstName;
+            user.LastName = memberModel.Lastname ?? user.LastName;
+            user.Location = memberModel.Location ?? user.Location;
+
+            if (isAdmin)
+            {
+                user.Title = memberModel.Title ?? user.Title;
+            }
+        }
+
+        if (!_userFormatter.IsValidUserName(user.FirstName, user.LastName))
+        {
+            throw new Exception(Resource.ErrorIncorrectUserName);
+        }
+
+        user.Notes = memberModel.Comment ?? user.Notes;
+        user.Sex = ("male".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase)
+            ? true
+            : ("female".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase) ? (bool?)false : null)) ?? user.Sex;
+
+        user.BirthDate = memberModel.Birthday != null ? _tenantUtil.DateTimeFromUtc(memberModel.Birthday) : user.BirthDate;
+
+        if (user.BirthDate == resetDate)
+        {
+            user.BirthDate = null;
+        }
+
+        user.WorkFromDate = memberModel.Worksfrom != null ? _tenantUtil.DateTimeFromUtc(memberModel.Worksfrom) : user.WorkFromDate;
+
+        if (user.WorkFromDate == resetDate)
+        {
+            user.WorkFromDate = null;
+        }
+
+        //Update contacts
+        UpdateContacts(memberModel.Contacts, user);
+        UpdateDepartments(memberModel.Department, user);
+
+        if (memberModel.Files != _userPhotoManager.GetPhotoAbsoluteWebPath(user.ID))
+        {
+            UpdatePhotoUrl(memberModel.Files, user);
+        }
+        if (memberModel.Disable.HasValue)
+        {
+            user.Status = memberModel.Disable.Value ? EmployeeStatus.Terminated : EmployeeStatus.Active;
+            user.TerminatedDate = memberModel.Disable.Value ? DateTime.UtcNow : null;
+        }
+        if (self && !isAdmin)
+        {
+            StudioNotifyService.SendMsgToAdminAboutProfileUpdated();
+        }
+
+        // change user type
+        var canBeGuestFlag = !user.IsOwner(Tenant) && !user.IsAdmin(UserManager) && user.GetListAdminModules(_webItemSecurity).Count == 0 && !user.IsMe(AuthContext);
+
+        if (memberModel.IsVisitor && !user.IsVisitor(UserManager) && canBeGuestFlag)
+        {
+            UserManager.AddUserIntoGroup(user.ID, Constants.GroupVisitor.ID);
+            _webItemSecurityCache.ClearCache(Tenant.TenantId);
+        }
+
+        if (!self && !memberModel.IsVisitor && user.IsVisitor(UserManager))
+        {
+            var usersQuota = _tenantExtra.GetTenantQuota().ActiveUsers;
+            if (_tenantStatisticsProvider.GetUsersCount() < usersQuota)
+            {
+                UserManager.RemoveUserFromGroup(user.ID, Constants.GroupVisitor.ID);
+                _webItemSecurityCache.ClearCache(Tenant.TenantId);
+            }
+            else
+            {
+                throw new TenantQuotaException(string.Format("Exceeds the maximum active users ({0})", usersQuota));
+            }
+        }
+
+        UserManager.SaveUserInfo(user);
+        MessageService.Send(MessageAction.UserUpdated, MessageTarget.Create(user.ID), user.DisplayUserName(false, DisplayUserSettingsHelper));
+
+        if (memberModel.Disable.HasValue && memberModel.Disable.Value)
+        {
+            _cookiesManager.ResetUserCookie(user.ID);
+            MessageService.Send(MessageAction.CookieSettingsUpdated);
+        }
+
+        return Mapper.Map<UserInfo, EmployeeFullDto>(user);
+    }
+    private EmployeeFullDto UpdateMemberCulture(string userid, UpdateMemberRequestDto memberModel)
+    {
+        var user = GetUserInfo(userid);
+
+        if (UserManager.IsSystemUser(user.ID))
+        {
+            throw new SecurityException();
+        }
+
+        PermissionContext.DemandPermissions(new UserSecurityProvider(user.ID), Constants.Action_EditUser);
+
+        var curLng = user.CultureName;
+
+        if (SetupInfo.EnabledCultures.Find(c => string.Equals(c.Name, memberModel.CultureName, StringComparison.InvariantCultureIgnoreCase)) != null)
+        {
+            if (curLng != memberModel.CultureName)
+            {
+                user.CultureName = memberModel.CultureName;
+
+                try
+                {
+                    UserManager.SaveUserInfo(user);
+                }
+                catch
+                {
+                    user.CultureName = curLng;
+                    throw;
+                }
+
+                MessageService.Send(MessageAction.UserUpdatedLanguage, MessageTarget.Create(user.ID), user.DisplayUserName(false, DisplayUserSettingsHelper));
+
+            }
+        }
+
+        return Mapper.Map<UserInfo, EmployeeFullDto>(user);
+    }
+    private IEnumerable<EmployeeFullDto> UpdateUserStatus(EmployeeStatus status, UpdateMembersRequestDto model)
+    {
+        PermissionContext.DemandPermissions(Constants.Action_EditUser);
+
+        var users = model.UserIds.Select(userId => UserManager.GetUsers(userId))
+            .Where(u => !UserManager.IsSystemUser(u.ID) && !u.IsLDAP())
+            .ToList();
+
+        foreach (var user in users)
+        {
+            if (user.IsOwner(Tenant) || user.IsMe(AuthContext))
+            {
+                continue;
+            }
+
+            switch (status)
+            {
+                case EmployeeStatus.Active:
+                    if (user.Status == EmployeeStatus.Terminated)
+                    {
+                        if (_tenantStatisticsProvider.GetUsersCount() < _tenantExtra.GetTenantQuota().ActiveUsers || user.IsVisitor(UserManager))
+                        {
+                            user.Status = EmployeeStatus.Active;
+                            UserManager.SaveUserInfo(user);
+                        }
+                    }
+                    break;
+                case EmployeeStatus.Terminated:
+                    user.Status = EmployeeStatus.Terminated;
+                    UserManager.SaveUserInfo(user);
+
+                    _cookiesManager.ResetUserCookie(user.ID);
+                    MessageService.Send(MessageAction.CookieSettingsUpdated);
+                    break;
+            }
+        }
+
+        MessageService.Send(MessageAction.UsersUpdatedStatus, MessageTarget.Create(users.Select(x => x.ID)), users.Select(x => x.DisplayUserName(false, DisplayUserSettingsHelper)));
+
+        return Mapper.Map<IEnumerable<UserInfo>, IEnumerable<EmployeeFullDto>>(users);
+    }
+
+    private IEnumerable<EmployeeFullDto> UpdateUserType(EmployeeType type, UpdateMembersRequestDto model)
+    {
+        var users = model.UserIds
+            .Where(userId => !UserManager.IsSystemUser(userId))
+            .Select(userId => UserManager.GetUsers(userId))
+            .ToList();
+
+        foreach (var user in users)
+        {
+            if (user.IsOwner(Tenant) || user.IsAdmin(UserManager)
+                || user.IsMe(AuthContext) || user.GetListAdminModules(_webItemSecurity).Count > 0)
+            {
+                continue;
+            }
+
+            switch (type)
+            {
+                case EmployeeType.User:
+                    if (user.IsVisitor(UserManager))
+                    {
+                        if (_tenantStatisticsProvider.GetUsersCount() < _tenantExtra.GetTenantQuota().ActiveUsers)
+                        {
+                            UserManager.RemoveUserFromGroup(user.ID, Constants.GroupVisitor.ID);
+                            _webItemSecurityCache.ClearCache(Tenant.TenantId);
+                        }
+                    }
+                    break;
+                case EmployeeType.Visitor:
+                    if (_coreBaseSettings.Standalone || _tenantStatisticsProvider.GetVisitorsCount() < _tenantExtra.GetTenantQuota().ActiveUsers * _constants.CoefficientOfVisitors)
+                    {
+                        UserManager.AddUserIntoGroup(user.ID, Constants.GroupVisitor.ID);
+                        _webItemSecurityCache.ClearCache(Tenant.TenantId);
+                    }
+                    break;
+            }
+        }
+
+        MessageService.Send(MessageAction.UsersUpdatedType, MessageTarget.Create(users.Select(x => x.ID)), users.Select(x => x.DisplayUserName(false, DisplayUserSettingsHelper)));
+
+        return Mapper.Map<IEnumerable<UserInfo>, IEnumerable<EmployeeFullDto>>(users);
+    }
+    ///// <summary>
+    ///// Adds a new portal user from import with the first and last name, email address
+    ///// </summary>
+    ///// <short>
+    ///// Add new import user
+    ///// </short>
+    ///// <param name="userList">The list of users to add</param>
+    ///// <param name="importUsersAsCollaborators" optional="true">Add users as guests (bool type: false|true)</param>
+    ///// <returns>Newly created users</returns>
+    //[Create("import/save")]
+    //public void SaveUsers(string userList, bool importUsersAsCollaborators)
+    //{
+    //    lock (progressQueue.SynchRoot)
+    //    {
+    //        var task = progressQueue.GetItems().OfType<ImportUsersTask>().FirstOrDefault(t => (int)t.Id == TenantProvider.CurrentTenantID);
+    //        if (task != null && task.IsCompleted)
+    //        {
+    //            progressQueue.Remove(task);
+    //            task = null;
+    //        }
+    //        if (task == null)
+    //        {
+    //            progressQueue.Add(new ImportUsersTask(userList, importUsersAsCollaborators, GetHttpHeaders(HttpContext.Current.Request))
+    //            {
+    //                Id = TenantProvider.CurrentTenantID,
+    //                UserId = SecurityContext.CurrentAccount.ID,
+    //                Percentage = 0
+    //            });
+    //        }
+    //    }
+    //}
+
+    //[Read("import/status")]
+    //public object GetStatus()
+    //{
+    //    lock (progressQueue.SynchRoot)
+    //    {
+    //        var task = progressQueue.GetItems().OfType<ImportUsersTask>().FirstOrDefault(t => (int)t.Id == TenantProvider.CurrentTenantID);
+    //        if (task == null) return null;
+
+    //        return new
+    //        {
+    //            Completed = task.IsCompleted,
+    //            Percents = (int)task.Percentage,
+    //            UserCounter = task.GetUserCounter,
+    //            Status = (int)task.Status,
+    //            Error = (string)task.Error,
+    //            task.Data
+    //        };
+    //    }
+    //}
+}
diff --git a/products/ASC.People/Server/ApiModels/ResponseDto/GroupDto.cs b/products/ASC.People/Server/ApiModels/ResponseDto/GroupDto.cs
index 55e47a6990..3dd5de6ce3 100644
--- a/products/ASC.People/Server/ApiModels/ResponseDto/GroupDto.cs
+++ b/products/ASC.People/Server/ApiModels/ResponseDto/GroupDto.cs
@@ -32,19 +32,19 @@ public class GroupDto
     public Guid? Parent { get; set; }
     public Guid Category { get; set; }
     public Guid Id { get; set; }
-    public EmployeeWraper Manager { get; set; }
-    public List<EmployeeWraper> Members { get; set; }
+    public EmployeeDto Manager { get; set; }
+    public List<EmployeeDto> Members { get; set; }
 
     public static GroupDto GetSample()
     {
         return new GroupDto
         {
             Id = Guid.NewGuid(),
-            Manager = EmployeeWraper.GetSample(),
+            Manager = EmployeeDto.GetSample(),
             Category = Guid.NewGuid(),
             Name = "Sample group",
             Parent = Guid.NewGuid(),
-            Members = new List<EmployeeWraper> { EmployeeWraper.GetSample() }
+            Members = new List<EmployeeDto> { EmployeeDto.GetSample() }
         };
     }
 }
@@ -74,7 +74,7 @@ public class GroupWraperFullHelper
 
         if (includeMembers)
         {
-            result.Members = new List<EmployeeWraper>(UserManager.GetUsersByGroup(group.ID).Select(EmployeeWraperHelper.Get));
+            result.Members = new List<EmployeeDto>(UserManager.GetUsersByGroup(group.ID).Select(EmployeeWraperHelper.Get));
         }
 
         return result;
diff --git a/products/ASC.People/Server/GlobalUsings.cs b/products/ASC.People/Server/GlobalUsings.cs
index ea02bd72cf..4dc21a15b7 100644
--- a/products/ASC.People/Server/GlobalUsings.cs
+++ b/products/ASC.People/Server/GlobalUsings.cs
@@ -12,6 +12,7 @@ global using System.Threading.Tasks;
 global using System.Web;
 
 global using ASC.Api.Core;
+global using ASC.Api.Core.Convention;
 global using ASC.Api.Utils;
 global using ASC.Common;
 global using ASC.Common.Logging;
@@ -44,6 +45,8 @@ global using ASC.Web.Studio.Core.Notify;
 global using ASC.Web.Studio.UserControls.Statistics;
 global using ASC.Web.Studio.Utility;
 
+global using AutoMapper;
+
 global using Autofac.Extensions.DependencyInjection;
 
 global using Microsoft.AspNetCore.Authorization;
@@ -57,7 +60,4 @@ global using Microsoft.Extensions.Hosting;
 global using Microsoft.Extensions.Options;
 
 global using SixLabors.ImageSharp;
-global using SixLabors.ImageSharp.Formats;
-
-global using StackExchange.Redis.Extensions.Core.Configuration;
-global using StackExchange.Redis.Extensions.Newtonsoft;
+global using SixLabors.ImageSharp.Formats;
\ No newline at end of file
diff --git a/web/ASC.Web.Api/Controllers/SettingsController.cs b/web/ASC.Web.Api/Controllers/SettingsController.cs
index d5d788225d..2c0ba318d0 100644
--- a/web/ASC.Web.Api/Controllers/SettingsController.cs
+++ b/web/ASC.Web.Api/Controllers/SettingsController.cs
@@ -931,7 +931,7 @@ namespace ASC.Api.Settings
         }
 
         [Read("security/administrator/{productid}")]
-        public IEnumerable<EmployeeWraper> GetProductAdministrators(Guid productid)
+        public IEnumerable<EmployeeDto> GetProductAdministrators(Guid productid)
         {
             return WebItemSecurity.GetProductAdministrators(productid)
                                   .Select(EmployeeWraperHelper.Get)
diff --git a/web/ASC.Web.Api/Models/SecurityWrapper.cs b/web/ASC.Web.Api/Models/SecurityWrapper.cs
index 9a04ef52fd..28a112f53d 100644
--- a/web/ASC.Web.Api/Models/SecurityWrapper.cs
+++ b/web/ASC.Web.Api/Models/SecurityWrapper.cs
@@ -29,7 +29,7 @@ namespace ASC.Api.Settings
     {
         public string WebItemId { get; set; }
 
-        public IEnumerable<EmployeeWraper> Users { get; set; }
+        public IEnumerable<EmployeeDto> Users { get; set; }
 
         public IEnumerable<GroupSummaryDto> Groups { get; set; }
 
@@ -48,9 +48,9 @@ namespace ASC.Api.Settings
                         {
                             GroupSummaryDto.GetSample()
                         },
-                Users = new List<EmployeeWraper>
+                Users = new List<EmployeeDto>
                         {
-                            EmployeeWraper.GetSample()
+                            EmployeeDto.GetSample()
                         }
             };
         }

From 8474cb8d37e8d70b2d81f4406bc878d9d3fcac22 Mon Sep 17 00:00:00 2001
From: MaksimChegulov <maksim.chegulov@onlyoffice.com>
Date: Mon, 28 Feb 2022 23:25:25 +0300
Subject: [PATCH 16/28] refactor

---
 common/ASC.Api.Core/Model/EmployeeDto.cs      |   9 +-
 common/ASC.Api.Core/Model/EmployeeFullDto.cs  |  10 +-
 .../ASC.Files/Core/Model/FileEntryWrapper.cs  |   8 +-
 .../ASC.Files/Core/Model/FileShareWrapper.cs  |   4 +-
 products/ASC.Files/Core/Model/FileWrapper.cs  |   2 +-
 .../ASC.Files/Core/Model/FolderWrapper.cs     |   2 +-
 .../Server/Api/BasePeopleController.cs        |  20 +-
 .../Server/Api/ContactsController.cs          |  20 +-
 .../ASC.People/Server/Api/GroupController.cs  | 598 +++++++++---------
 .../ASC.People/Server/Api/PeopleController.cs |  30 +-
 .../ASC.People/Server/Api/PhotoController.cs  |  11 +-
 .../ASC.People/Server/Api/UserController.cs   |  72 ++-
 .../Server/ApiModels/ResponseDto/GroupDto.cs  |  16 +-
 products/ASC.People/Server/GlobalUsings.cs    |   4 +
 products/ASC.People/Server/Program.cs         | 132 ++--
 products/ASC.People/Server/Startup.cs         |  37 +-
 .../Controllers/SettingsController.cs         |   4 +-
 17 files changed, 517 insertions(+), 462 deletions(-)

diff --git a/common/ASC.Api.Core/Model/EmployeeDto.cs b/common/ASC.Api.Core/Model/EmployeeDto.cs
index d3f368b108..35aad8620b 100644
--- a/common/ASC.Api.Core/Model/EmployeeDto.cs
+++ b/common/ASC.Api.Core/Model/EmployeeDto.cs
@@ -46,16 +46,16 @@ public class EmployeeDto
 }
 
 [Scope]
-public class EmployeeWraperHelper
+public class EmployeeDtoHelper
 {
-    protected UserPhotoManager UserPhotoManager { get; }
-    protected UserManager UserManager { get; }
+    protected readonly UserPhotoManager UserPhotoManager;
+    protected readonly UserManager UserManager;
 
     private readonly ApiContext _httpContext;
     private readonly DisplayUserSettingsHelper _displayUserSettingsHelper;
     private readonly CommonLinkUtility _commonLinkUtility;
 
-    public EmployeeWraperHelper(
+    public EmployeeDtoHelper(
         ApiContext httpContext,
         DisplayUserSettingsHelper displayUserSettingsHelper,
         UserPhotoManager userPhotoManager,
@@ -67,7 +67,6 @@ public class EmployeeWraperHelper
         _httpContext = httpContext;
         _displayUserSettingsHelper = displayUserSettingsHelper;
         _commonLinkUtility = commonLinkUtility;
-
     }
 
     public EmployeeDto Get(UserInfo userInfo)
diff --git a/common/ASC.Api.Core/Model/EmployeeFullDto.cs b/common/ASC.Api.Core/Model/EmployeeFullDto.cs
index 2d3356b7f2..d659e7a9d8 100644
--- a/common/ASC.Api.Core/Model/EmployeeFullDto.cs
+++ b/common/ASC.Api.Core/Model/EmployeeFullDto.cs
@@ -89,13 +89,13 @@ public class EmployeeFullDto : EmployeeDto
 }
 
 [Scope]
-public class EmployeeWraperFullHelper : EmployeeWraperHelper
+public class EmployeeFullDtoHelper : EmployeeDtoHelper
 {
     private readonly ApiContext _context;
     private readonly WebItemSecurity _webItemSecurity;
     private readonly ApiDateTimeHelper _apiDateTimeHelper;
 
-    public EmployeeWraperFullHelper(
+    public EmployeeFullDtoHelper(
         ApiContext context,
         UserManager userManager,
         UserPhotoManager userPhotoManager,
@@ -126,7 +126,7 @@ public class EmployeeWraperFullHelper : EmployeeWraperHelper
         if (apiContext.Check("Id"))
         {
             bindExprs.Add(Expression.Bind(typeof(UserInfo).GetProperty("ID"), 
-                Expression.Property(parameter, typeof(User).GetProperty("Id"))));
+            Expression.Property(parameter, typeof(User).GetProperty("Id"))));
         }
 
         var body = Expression.MemberInit(newExpr, bindExprs);
@@ -223,7 +223,7 @@ public class EmployeeWraperFullHelper : EmployeeWraperHelper
         if (_context.Check("listAdminModules"))
         {
             var listAdminModules = userInfo.GetListAdminModules(_webItemSecurity);
-                if (listAdminModules.Count > 0)
+            if (listAdminModules.Count > 0)
             {
                 result.ListAdminModules = listAdminModules;
             }
@@ -249,7 +249,7 @@ public class EmployeeWraperFullHelper : EmployeeWraperHelper
             }
         }
 
-            if (contacts.Count > 0)
+        if (contacts.Count > 0)
         {
             employeeWraperFull.Contacts = contacts;
         }
diff --git a/products/ASC.Files/Core/Model/FileEntryWrapper.cs b/products/ASC.Files/Core/Model/FileEntryWrapper.cs
index 978886d461..607ea55988 100644
--- a/products/ASC.Files/Core/Model/FileEntryWrapper.cs
+++ b/products/ASC.Files/Core/Model/FileEntryWrapper.cs
@@ -87,7 +87,7 @@ namespace ASC.Api.Documents
         /// 
         /// </summary>
         /// <param name="entry"></param>
-        protected FileEntryWrapper(FileEntry entry, EmployeeWraperHelper employeeWraperHelper, ApiDateTimeHelper apiDateTimeHelper)
+        protected FileEntryWrapper(FileEntry entry, EmployeeDtoHelper employeeWraperHelper, ApiDateTimeHelper apiDateTimeHelper)
         {
             Title = entry.Title;
             Access = entry.Access;
@@ -129,7 +129,7 @@ namespace ASC.Api.Documents
         /// 
         /// </summary>
         /// <param name="entry"></param>
-        protected FileEntryWrapper(FileEntry<T> entry, EmployeeWraperHelper employeeWraperHelper, ApiDateTimeHelper apiDateTimeHelper)
+        protected FileEntryWrapper(FileEntry<T> entry, EmployeeDtoHelper employeeWraperHelper, ApiDateTimeHelper apiDateTimeHelper)
             : base(entry, employeeWraperHelper, apiDateTimeHelper)
         {
             Id = entry.ID;
@@ -149,13 +149,13 @@ namespace ASC.Api.Documents
     public class FileEntryWrapperHelper
     {
         private ApiDateTimeHelper ApiDateTimeHelper { get; }
-        private EmployeeWraperHelper EmployeeWraperHelper { get; }
+        private EmployeeDtoHelper EmployeeWraperHelper { get; }
         public FileSharingHelper FileSharingHelper { get; }
         public FileSecurity FileSecurity { get; }
 
         public FileEntryWrapperHelper(
             ApiDateTimeHelper apiDateTimeHelper,
-            EmployeeWraperHelper employeeWraperHelper,
+            EmployeeDtoHelper employeeWraperHelper,
             FileSharingHelper fileSharingHelper, FileSecurity fileSecurity
             )
         {
diff --git a/products/ASC.Files/Core/Model/FileShareWrapper.cs b/products/ASC.Files/Core/Model/FileShareWrapper.cs
index 7b77a8793a..9a8e6d49f6 100644
--- a/products/ASC.Files/Core/Model/FileShareWrapper.cs
+++ b/products/ASC.Files/Core/Model/FileShareWrapper.cs
@@ -86,11 +86,11 @@ namespace ASC.Api.Documents
     public class FileShareWrapperHelper
     {
         private UserManager UserManager { get; }
-        private EmployeeWraperFullHelper EmployeeWraperFullHelper { get; }
+        private EmployeeFullDtoHelper EmployeeWraperFullHelper { get; }
 
         public FileShareWrapperHelper(
             UserManager userManager,
-            EmployeeWraperFullHelper employeeWraperFullHelper)
+            EmployeeFullDtoHelper employeeWraperFullHelper)
         {
             UserManager = userManager;
             EmployeeWraperFullHelper = employeeWraperFullHelper;
diff --git a/products/ASC.Files/Core/Model/FileWrapper.cs b/products/ASC.Files/Core/Model/FileWrapper.cs
index 61d660b66b..b0458be56f 100644
--- a/products/ASC.Files/Core/Model/FileWrapper.cs
+++ b/products/ASC.Files/Core/Model/FileWrapper.cs
@@ -149,7 +149,7 @@ namespace ASC.Api.Documents
 
         public FileWrapperHelper(
             ApiDateTimeHelper apiDateTimeHelper,
-            EmployeeWraperHelper employeeWrapperHelper,
+            EmployeeDtoHelper employeeWrapperHelper,
             AuthContext authContext,
             IDaoFactory daoFactory,
             FileSecurity fileSecurity,
diff --git a/products/ASC.Files/Core/Model/FolderWrapper.cs b/products/ASC.Files/Core/Model/FolderWrapper.cs
index 7aa8715d69..7c9023c4d1 100644
--- a/products/ASC.Files/Core/Model/FolderWrapper.cs
+++ b/products/ASC.Files/Core/Model/FolderWrapper.cs
@@ -87,7 +87,7 @@ namespace ASC.Api.Documents
 
         public FolderWrapperHelper(
             ApiDateTimeHelper apiDateTimeHelper,
-            EmployeeWraperHelper employeeWrapperHelper,
+            EmployeeDtoHelper employeeWrapperHelper,
             AuthContext authContext,
             IDaoFactory daoFactory,
             FileSecurity fileSecurity,
diff --git a/products/ASC.People/Server/Api/BasePeopleController.cs b/products/ASC.People/Server/Api/BasePeopleController.cs
index bd69bdd97f..df294964a7 100644
--- a/products/ASC.People/Server/Api/BasePeopleController.cs
+++ b/products/ASC.People/Server/Api/BasePeopleController.cs
@@ -1,25 +1,28 @@
-using AutoMapper;
+using SecurityContext = ASC.Core.SecurityContext;
 
 namespace ASC.People.Api;
 
 public class BasePeopleController : BaseApiController
 {
     protected readonly UserPhotoManager UserPhotoManager;
-    protected readonly IHttpClientFactory HttpClientFactory;
     protected readonly DisplayUserSettingsHelper DisplayUserSettingsHelper;
     protected readonly SetupInfo SetupInfo;
-    protected readonly IMapper Mapper;
+
+    private readonly IHttpClientFactory _httpClientFactory;
 
     protected BasePeopleController(
         UserManager userManager,
         AuthContext authContext,
         ApiContext apiContext,
         PermissionContext permissionContext,
-        Core.SecurityContext securityContext,
+        SecurityContext securityContext,
         MessageService messageService,
         MessageTarget messageTarget,
         StudioNotifyService studioNotifyService,
-        IMapper mapper)
+        UserPhotoManager userPhotoManager,
+        IHttpClientFactory httpClientFactory,
+        DisplayUserSettingsHelper displayUserSettingsHelper,
+        SetupInfo setupInfo)
         : base(
             userManager,
             authContext,
@@ -30,7 +33,10 @@ public class BasePeopleController : BaseApiController
             messageTarget,
             studioNotifyService)
     {
-        Mapper = mapper;
+        UserPhotoManager = userPhotoManager;
+        _httpClientFactory = httpClientFactory;
+        DisplayUserSettingsHelper = displayUserSettingsHelper;
+        SetupInfo = setupInfo;
     }
 
     protected UserInfo GetUserInfo(string userNameOrId)
@@ -83,7 +89,7 @@ public class BasePeopleController : BaseApiController
         var request = new HttpRequestMessage();
         request.RequestUri = new Uri(files);
 
-        var httpClient = HttpClientFactory.CreateClient();
+        var httpClient = _httpClientFactory.CreateClient();
         using var response = httpClient.Send(request);
         using var inputStream = response.Content.ReadAsStream();
         using var br = new BinaryReader(inputStream);
diff --git a/products/ASC.People/Server/Api/ContactsController.cs b/products/ASC.People/Server/Api/ContactsController.cs
index c6874bf38c..e746014996 100644
--- a/products/ASC.People/Server/Api/ContactsController.cs
+++ b/products/ASC.People/Server/Api/ContactsController.cs
@@ -4,6 +4,8 @@ namespace ASC.People.Api;
 
 public class ContactsController : BasePeopleController
 {
+    private readonly EmployeeFullDtoHelper _employeeFullDtoHelper;
+
     public ContactsController(
         UserManager userManager,
         AuthContext authContext,
@@ -13,7 +15,11 @@ public class ContactsController : BasePeopleController
         MessageService messageService,
         MessageTarget messageTarget,
         StudioNotifyService studioNotifyService,
-        IMapper mapper)
+        UserPhotoManager userPhotoManager,
+        IHttpClientFactory httpClientFactory,
+        DisplayUserSettingsHelper displayUserSettingsHelper,
+        SetupInfo setupInfo,
+        EmployeeFullDtoHelper employeeFullDtoHelper)
         : base(
             userManager,
             authContext,
@@ -23,8 +29,12 @@ public class ContactsController : BasePeopleController
             messageService,
             messageTarget,
             studioNotifyService,
-            mapper)
+            userPhotoManager, 
+            httpClientFactory, 
+            displayUserSettingsHelper,
+            setupInfo)
     {
+        _employeeFullDtoHelper = employeeFullDtoHelper;
     }
 
     [Delete("{userid}/contacts")]
@@ -102,7 +112,7 @@ public class ContactsController : BasePeopleController
         DeleteContacts(memberModel.Contacts, user);
         UserManager.SaveUserInfo(user);
 
-        return Mapper.Map<UserInfo, EmployeeFullDto>(user);
+        return _employeeFullDtoHelper.GetFull(user);
     }
 
     private EmployeeFullDto SetMemberContacts(string userid, UpdateMemberRequestDto memberModel)
@@ -118,7 +128,7 @@ public class ContactsController : BasePeopleController
         UpdateContacts(memberModel.Contacts, user);
         UserManager.SaveUserInfo(user);
 
-        return Mapper.Map<UserInfo, EmployeeFullDto>(user);
+        return _employeeFullDtoHelper.GetFull(user);
     }
 
     private EmployeeFullDto UpdateMemberContacts(string userid, UpdateMemberRequestDto memberModel)
@@ -133,6 +143,6 @@ public class ContactsController : BasePeopleController
         UpdateContacts(memberModel.Contacts, user);
         UserManager.SaveUserInfo(user);
 
-        return Mapper.Map<UserInfo, EmployeeFullDto>(user);
+        return _employeeFullDtoHelper.GetFull(user);
     }
 }
diff --git a/products/ASC.People/Server/Api/GroupController.cs b/products/ASC.People/Server/Api/GroupController.cs
index 9382b6594b..a150c461d1 100644
--- a/products/ASC.People/Server/Api/GroupController.cs
+++ b/products/ASC.People/Server/Api/GroupController.cs
@@ -1,295 +1,309 @@
-namespace ASC.Employee.Core.Controllers
+namespace ASC.Employee.Core.Controllers;
+
+[Scope]
+[DefaultRoute]
+[ApiController]
+public class GroupController : ControllerBase
 {
-    [Scope]
-    [DefaultRoute]
-    [ApiController]
-    public class GroupController : ControllerBase
+    private readonly ApiContext _apiContext;
+    private readonly MessageService _messageService;
+    private readonly UserManager _userManager;
+    private readonly PermissionContext _permissionContext;
+    private readonly MessageTarget _messageTarget;
+    private readonly GroupFullDtoHelper _groupWraperFullHelper;
+
+    public GroupController(
+        ApiContext apiContext,
+        MessageService messageService,
+        UserManager userManager,
+        PermissionContext permissionContext,
+        MessageTarget messageTarget,
+        GroupFullDtoHelper groupWraperFullHelper)
     {
-        public ApiContext ApiContext { get; }
-        private MessageService MessageService { get; }
-
-        private UserManager UserManager { get; }
-        private PermissionContext PermissionContext { get; }
-        private MessageTarget MessageTarget { get; }
-        private GroupWraperFullHelper GroupWraperFullHelper { get; }
-
-        public GroupController(
-            ApiContext apiContext,
-            MessageService messageService,
-            UserManager userManager,
-            PermissionContext permissionContext,
-            MessageTarget messageTarget,
-            GroupWraperFullHelper groupWraperFullHelper)
-        {
-            ApiContext = apiContext;
-            MessageService = messageService;
-            UserManager = userManager;
-            PermissionContext = permissionContext;
-            MessageTarget = messageTarget;
-            GroupWraperFullHelper = groupWraperFullHelper;
-        }
-
-        [Read]
-        public IEnumerable<GroupSummaryDto> GetAll()
-        {
-            var result = UserManager.GetDepartments().Select(r => r);
-            if (!string.IsNullOrEmpty(ApiContext.FilterValue))
-            {
-                result = result.Where(r => r.Name.Contains(ApiContext.FilterValue, StringComparison.InvariantCultureIgnoreCase));
-            }
-            return result.Select(x => new GroupSummaryDto(x, UserManager));
-        }
-
-        [Read("full")]
-        public IEnumerable<GroupDto> GetAllWithMembers()
-        {
-            var result = UserManager.GetDepartments().Select(r => r);
-            if (!string.IsNullOrEmpty(ApiContext.FilterValue))
-            {
-                result = result.Where(r => r.Name.Contains(ApiContext.FilterValue, StringComparison.InvariantCultureIgnoreCase));
-            }
-            return result.Select(r=> GroupWraperFullHelper.Get(r, true));
-        }
-
-        [Read("{groupid}")]
-        public GroupDto GetById(Guid groupid)
-        {
-            return GroupWraperFullHelper.Get(GetGroupInfo(groupid), true);
-        }
-
-        [Read("user/{userid}")]
-        public IEnumerable<GroupSummaryDto> GetByUserId(Guid userid)
-        {
-            return UserManager.GetUserGroups(userid).Select(x => new GroupSummaryDto(x, UserManager));
-        }
-
-        [Create]
-        public GroupDto AddGroupFromBody([FromBody]GroupRequestDto groupModel)
-        {
-            return AddGroup(groupModel);
-        }
-
-        [Create]
-        [Consumes("application/x-www-form-urlencoded")]
-        public GroupDto AddGroupFromForm([FromForm] GroupRequestDto groupModel)
-        {
-            return AddGroup(groupModel);
-        }
-
-        private GroupDto AddGroup(GroupRequestDto groupModel)
-        {
-            PermissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
-
-            var group = UserManager.SaveGroupInfo(new GroupInfo { Name = groupModel.GroupName });
-
-            TransferUserToDepartment(groupModel.GroupManager, @group, true);
-            if (groupModel.Members != null)
-            {
-                foreach (var member in groupModel.Members)
-                {
-                    TransferUserToDepartment(member, group, false);
-                }
-            }
-
-            MessageService.Send(MessageAction.GroupCreated, MessageTarget.Create(group.ID), group.Name);
-
-            return GroupWraperFullHelper.Get(group, true);
-        }
-
-        [Update("{groupid}")]
-        public GroupDto UpdateGroupFromBody(Guid groupid, [FromBody]GroupRequestDto groupModel)
-        {
-            return UpdateGroup(groupid, groupModel);
-        }
-
-        [Update("{groupid}")]
-        [Consumes("application/x-www-form-urlencoded")]
-        public GroupDto UpdateGroupFromForm(Guid groupid, [FromForm] GroupRequestDto groupModel)
-        {
-            return UpdateGroup(groupid, groupModel);
-        }
-
-        private GroupDto UpdateGroup(Guid groupid, GroupRequestDto groupModel)
-        {
-            PermissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
-            var group = UserManager.GetGroups().SingleOrDefault(x => x.ID == groupid).NotFoundIfNull("group not found");
-            if (groupid == Constants.LostGroupInfo.ID)
-            {
-                throw new ItemNotFoundException("group not found");
-            }
-
-            group.Name = groupModel.GroupName ?? group.Name;
-            UserManager.SaveGroupInfo(group);
-
-            RemoveMembersFrom(groupid, new GroupRequestDto {Members = UserManager.GetUsersByGroup(groupid, EmployeeStatus.All).Select(u => u.ID).Where(id => !groupModel.Members.Contains(id)) });
-
-            TransferUserToDepartment(groupModel.GroupManager, @group, true);
-            if (groupModel.Members != null)
-            {
-                foreach (var member in groupModel.Members)
-                {
-                    TransferUserToDepartment(member, group, false);
-                }
-            }
-
-            MessageService.Send(MessageAction.GroupUpdated, MessageTarget.Create(groupid), group.Name);
-
-            return GetById(groupid);
-        }
-
-        [Delete("{groupid}")]
-        public GroupDto DeleteGroup(Guid groupid)
-        {
-            PermissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
-            var @group = GetGroupInfo(groupid);
-            var groupWrapperFull = GroupWraperFullHelper.Get(group, false);
-
-            UserManager.DeleteGroup(groupid);
-
-            MessageService.Send(MessageAction.GroupDeleted, MessageTarget.Create(group.ID), group.Name);
-
-            return groupWrapperFull;
-        }
-
-        private GroupInfo GetGroupInfo(Guid groupid)
-        {
-            var group = UserManager.GetGroups().SingleOrDefault(x => x.ID == groupid).NotFoundIfNull("group not found");
-            if (group.ID == Constants.LostGroupInfo.ID)
-                throw new ItemNotFoundException("group not found");
-            return @group;
-        }
-
-        [Update("{groupid}/members/{newgroupid}")]
-        public GroupDto TransferMembersTo(Guid groupid, Guid newgroupid)
-        {
-            PermissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
-            var oldgroup = GetGroupInfo(groupid);
-
-            var newgroup = GetGroupInfo(newgroupid);
-
-            var users = UserManager.GetUsersByGroup(oldgroup.ID);
-            foreach (var userInfo in users)
-            {
-                TransferUserToDepartment(userInfo.ID, newgroup, false);
-            }
-            return GetById(newgroupid);
-        }
-
-        [Create("{groupid}/members")]
-        public GroupDto SetMembersToFromBody(Guid groupid, [FromBody]GroupRequestDto groupModel)
-        {
-            return SetMembersTo(groupid, groupModel);
-        }
-
-        [Create("{groupid}/members")]
-        [Consumes("application/x-www-form-urlencoded")]
-        public GroupDto SetMembersToFromForm(Guid groupid, [FromForm] GroupRequestDto groupModel)
-        {
-            return SetMembersTo(groupid, groupModel);
-        }
-
-        private GroupDto SetMembersTo(Guid groupid, GroupRequestDto groupModel)
-        {
-            RemoveMembersFrom(groupid, new GroupRequestDto {Members = UserManager.GetUsersByGroup(groupid).Select(x => x.ID) });
-            AddMembersTo(groupid, groupModel);
-            return GetById(groupid);
-        }
-
-        [Update("{groupid}/members")]
-        public GroupDto AddMembersToFromBody(Guid groupid, [FromBody]GroupRequestDto groupModel)
-        {
-            return AddMembersTo(groupid, groupModel);
-        }
-
-        [Update("{groupid}/members")]
-        [Consumes("application/x-www-form-urlencoded")]
-        public GroupDto AddMembersToFromForm(Guid groupid, [FromForm] GroupRequestDto groupModel)
-        {
-            return AddMembersTo(groupid, groupModel);
-        }
-
-        private GroupDto AddMembersTo(Guid groupid, GroupRequestDto groupModel)
-        {
-            PermissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
-            var group = GetGroupInfo(groupid);
-
-            foreach (var userId in groupModel.Members)
-            {
-                TransferUserToDepartment(userId, group, false);
-            }
-            return GetById(group.ID);
-        }
-
-        [Update("{groupid}/manager")]
-        public GroupDto SetManagerFromBody(Guid groupid, [FromBody]SetManagerRequestDto setManagerModel)
-        {
-            return SetManager(groupid, setManagerModel);
-        }
-
-        [Update("{groupid}/manager")]
-        [Consumes("application/x-www-form-urlencoded")]
-        public GroupDto SetManagerFromForm(Guid groupid, [FromForm] SetManagerRequestDto setManagerModel)
-        {
-            return SetManager(groupid, setManagerModel);
-        }
-
-        private GroupDto SetManager(Guid groupid, SetManagerRequestDto setManagerModel)
-        {
-            var group = GetGroupInfo(groupid);
-            if (UserManager.UserExists(setManagerModel.UserId))
-            {
-                UserManager.SetDepartmentManager(group.ID, setManagerModel.UserId);
-            }
-            else
-            {
-                throw new ItemNotFoundException("user not found");
-            }
-            return GetById(groupid);
-        }
-
-        [Delete("{groupid}/members")]
-        public GroupDto RemoveMembersFromFromBody(Guid groupid, [FromBody]GroupRequestDto groupModel)
-        {
-            return RemoveMembersFrom(groupid, groupModel);
-        }
-
-        [Delete("{groupid}/members")]
-        [Consumes("application/x-www-form-urlencoded")]
-        public GroupDto RemoveMembersFromFromForm(Guid groupid, [FromForm] GroupRequestDto groupModel)
-        {
-            return RemoveMembersFrom(groupid, groupModel);
-        }
-
-        private GroupDto RemoveMembersFrom(Guid groupid, GroupRequestDto groupModel)
-        {
-            PermissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
-            var group = GetGroupInfo(groupid);
-
-            foreach (var userId in groupModel.Members)
-            {
-                RemoveUserFromDepartment(userId, group);
-            }
-            return GetById(group.ID);
-        }
-
-        private void RemoveUserFromDepartment(Guid userId, GroupInfo @group)
-        {
-            if (!UserManager.UserExists(userId)) return;
-
-            var user = UserManager.GetUsers(userId);
-            UserManager.RemoveUserFromGroup(user.ID, @group.ID);
-            UserManager.SaveUserInfo(user);
-        }
-
-        private void TransferUserToDepartment(Guid userId, GroupInfo group, bool setAsManager)
-        {
-            if (!UserManager.UserExists(userId) && userId != Guid.Empty) return;
-
-            if (setAsManager)
-            {
-                UserManager.SetDepartmentManager(@group.ID, userId);
-            }
-            UserManager.AddUserIntoGroup(userId, @group.ID);
-        }
+        _apiContext = apiContext;
+        _messageService = messageService;
+        _userManager = userManager;
+        _permissionContext = permissionContext;
+        _messageTarget = messageTarget;
+        _groupWraperFullHelper = groupWraperFullHelper;
     }
-}
\ No newline at end of file
+
+    [Read]
+    public IEnumerable<GroupSummaryDto> GetAll()
+    {
+        var result = _userManager.GetDepartments().Select(r => r);
+        if (!string.IsNullOrEmpty(_apiContext.FilterValue))
+        {
+            result = result.Where(r => r.Name.Contains(_apiContext.FilterValue, StringComparison.InvariantCultureIgnoreCase));
+        }
+
+        return result.Select(x => new GroupSummaryDto(x, _userManager));
+    }
+
+    [Read("full")]
+    public IEnumerable<GroupDto> GetAllWithMembers()
+    {
+        var result = _userManager.GetDepartments().Select(r => r);
+        if (!string.IsNullOrEmpty(_apiContext.FilterValue))
+        {
+            result = result.Where(r => r.Name.Contains(_apiContext.FilterValue, StringComparison.InvariantCultureIgnoreCase));
+        }
+
+        return result.Select(r => _groupWraperFullHelper.Get(r, true));
+    }
+
+    [Read("{groupid}")]
+    public GroupDto GetById(Guid groupid)
+    {
+        return _groupWraperFullHelper.Get(GetGroupInfo(groupid), true);
+    }
+
+    [Read("user/{userid}")]
+    public IEnumerable<GroupSummaryDto> GetByUserId(Guid userid)
+    {
+        return _userManager.GetUserGroups(userid).Select(x => new GroupSummaryDto(x, _userManager));
+    }
+
+    [Create]
+    public GroupDto AddGroupFromBody([FromBody] GroupRequestDto groupModel)
+    {
+        return AddGroup(groupModel);
+    }
+
+    [Create]
+    [Consumes("application/x-www-form-urlencoded")]
+    public GroupDto AddGroupFromForm([FromForm] GroupRequestDto groupModel)
+    {
+        return AddGroup(groupModel);
+    }
+
+    private GroupDto AddGroup(GroupRequestDto groupModel)
+    {
+        _permissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
+
+        var group = _userManager.SaveGroupInfo(new GroupInfo { Name = groupModel.GroupName });
+
+        TransferUserToDepartment(groupModel.GroupManager, @group, true);
+        if (groupModel.Members != null)
+        {
+            foreach (var member in groupModel.Members)
+            {
+                TransferUserToDepartment(member, group, false);
+            }
+        }
+
+        _messageService.Send(MessageAction.GroupCreated, _messageTarget.Create(group.ID), group.Name);
+
+        return _groupWraperFullHelper.Get(group, true);
+    }
+
+    [Update("{groupid}")]
+    public GroupDto UpdateGroupFromBody(Guid groupid, [FromBody] GroupRequestDto groupModel)
+    {
+        return UpdateGroup(groupid, groupModel);
+    }
+
+    [Update("{groupid}")]
+    [Consumes("application/x-www-form-urlencoded")]
+    public GroupDto UpdateGroupFromForm(Guid groupid, [FromForm] GroupRequestDto groupModel)
+    {
+        return UpdateGroup(groupid, groupModel);
+    }
+
+    private GroupDto UpdateGroup(Guid groupid, GroupRequestDto groupModel)
+    {
+        _permissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
+        var group = _userManager.GetGroups().SingleOrDefault(x => x.ID == groupid).NotFoundIfNull("group not found");
+        if (groupid == Constants.LostGroupInfo.ID)
+        {
+            throw new ItemNotFoundException("group not found");
+        }
+
+        group.Name = groupModel.GroupName ?? group.Name;
+        _userManager.SaveGroupInfo(group);
+
+        RemoveMembersFrom(groupid, new GroupRequestDto { Members = _userManager.GetUsersByGroup(groupid, EmployeeStatus.All).Select(u => u.ID).Where(id => !groupModel.Members.Contains(id)) });
+
+        TransferUserToDepartment(groupModel.GroupManager, @group, true);
+        if (groupModel.Members != null)
+        {
+            foreach (var member in groupModel.Members)
+            {
+                TransferUserToDepartment(member, group, false);
+            }
+        }
+
+        _messageService.Send(MessageAction.GroupUpdated, _messageTarget.Create(groupid), group.Name);
+
+        return GetById(groupid);
+    }
+
+    [Delete("{groupid}")]
+    public GroupDto DeleteGroup(Guid groupid)
+    {
+        _permissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
+        var @group = GetGroupInfo(groupid);
+        var groupWrapperFull = _groupWraperFullHelper.Get(group, false);
+
+        _userManager.DeleteGroup(groupid);
+
+        _messageService.Send(MessageAction.GroupDeleted, _messageTarget.Create(group.ID), group.Name);
+
+        return groupWrapperFull;
+    }
+
+    private GroupInfo GetGroupInfo(Guid groupid)
+    {
+        var group = _userManager.GetGroups().SingleOrDefault(x => x.ID == groupid).NotFoundIfNull("group not found");
+        if (group.ID == Constants.LostGroupInfo.ID)
+        {
+            throw new ItemNotFoundException("group not found");
+        }
+
+        return @group;
+    }
+
+    [Update("{groupid}/members/{newgroupid}")]
+    public GroupDto TransferMembersTo(Guid groupid, Guid newgroupid)
+    {
+        _permissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
+        var oldgroup = GetGroupInfo(groupid);
+
+        var newgroup = GetGroupInfo(newgroupid);
+
+        var users = _userManager.GetUsersByGroup(oldgroup.ID);
+        foreach (var userInfo in users)
+        {
+            TransferUserToDepartment(userInfo.ID, newgroup, false);
+        }
+
+        return GetById(newgroupid);
+    }
+
+    [Create("{groupid}/members")]
+    public GroupDto SetMembersToFromBody(Guid groupid, [FromBody] GroupRequestDto groupModel)
+    {
+        return SetMembersTo(groupid, groupModel);
+    }
+
+    [Create("{groupid}/members")]
+    [Consumes("application/x-www-form-urlencoded")]
+    public GroupDto SetMembersToFromForm(Guid groupid, [FromForm] GroupRequestDto groupModel)
+    {
+        return SetMembersTo(groupid, groupModel);
+    }
+
+    private GroupDto SetMembersTo(Guid groupid, GroupRequestDto groupModel)
+    {
+        RemoveMembersFrom(groupid, new GroupRequestDto { Members = _userManager.GetUsersByGroup(groupid).Select(x => x.ID) });
+        AddMembersTo(groupid, groupModel);
+
+        return GetById(groupid);
+    }
+
+    [Update("{groupid}/members")]
+    public GroupDto AddMembersToFromBody(Guid groupid, [FromBody] GroupRequestDto groupModel)
+    {
+        return AddMembersTo(groupid, groupModel);
+    }
+
+    [Update("{groupid}/members")]
+    [Consumes("application/x-www-form-urlencoded")]
+    public GroupDto AddMembersToFromForm(Guid groupid, [FromForm] GroupRequestDto groupModel)
+    {
+        return AddMembersTo(groupid, groupModel);
+    }
+
+    private GroupDto AddMembersTo(Guid groupid, GroupRequestDto groupModel)
+    {
+        _permissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
+        var group = GetGroupInfo(groupid);
+
+        foreach (var userId in groupModel.Members)
+        {
+            TransferUserToDepartment(userId, group, false);
+        }
+
+        return GetById(group.ID);
+    }
+
+    [Update("{groupid}/manager")]
+    public GroupDto SetManagerFromBody(Guid groupid, [FromBody] SetManagerRequestDto setManagerModel)
+    {
+        return SetManager(groupid, setManagerModel);
+    }
+
+    [Update("{groupid}/manager")]
+    [Consumes("application/x-www-form-urlencoded")]
+    public GroupDto SetManagerFromForm(Guid groupid, [FromForm] SetManagerRequestDto setManagerModel)
+    {
+        return SetManager(groupid, setManagerModel);
+    }
+
+    private GroupDto SetManager(Guid groupid, SetManagerRequestDto setManagerModel)
+    {
+        var group = GetGroupInfo(groupid);
+        if (_userManager.UserExists(setManagerModel.UserId))
+        {
+            _userManager.SetDepartmentManager(group.ID, setManagerModel.UserId);
+        }
+        else
+        {
+            throw new ItemNotFoundException("user not found");
+        }
+
+        return GetById(groupid);
+    }
+
+    [Delete("{groupid}/members")]
+    public GroupDto RemoveMembersFromFromBody(Guid groupid, [FromBody] GroupRequestDto groupModel)
+    {
+        return RemoveMembersFrom(groupid, groupModel);
+    }
+
+    [Delete("{groupid}/members")]
+    [Consumes("application/x-www-form-urlencoded")]
+    public GroupDto RemoveMembersFromFromForm(Guid groupid, [FromForm] GroupRequestDto groupModel)
+    {
+        return RemoveMembersFrom(groupid, groupModel);
+    }
+
+    private GroupDto RemoveMembersFrom(Guid groupid, GroupRequestDto groupModel)
+    {
+        _permissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
+        var group = GetGroupInfo(groupid);
+
+        foreach (var userId in groupModel.Members)
+        {
+            RemoveUserFromDepartment(userId, group);
+        }
+
+        return GetById(group.ID);
+    }
+
+    private void RemoveUserFromDepartment(Guid userId, GroupInfo @group)
+    {
+        if (!_userManager.UserExists(userId))
+        {
+            return;
+        }
+
+        var user = _userManager.GetUsers(userId);
+        _userManager.RemoveUserFromGroup(user.ID, @group.ID);
+        _userManager.SaveUserInfo(user);
+    }
+
+    private void TransferUserToDepartment(Guid userId, GroupInfo group, bool setAsManager)
+    {
+        if (!_userManager.UserExists(userId) && userId != Guid.Empty)
+        {
+            return;
+        }
+
+        if (setAsManager)
+        {
+            _userManager.SetDepartmentManager(@group.ID, userId);
+        }
+        _userManager.AddUserIntoGroup(userId, @group.ID);
+    }
+}
diff --git a/products/ASC.People/Server/Api/PeopleController.cs b/products/ASC.People/Server/Api/PeopleController.cs
index d9dc544f82..179edde540 100644
--- a/products/ASC.People/Server/Api/PeopleController.cs
+++ b/products/ASC.People/Server/Api/PeopleController.cs
@@ -2,9 +2,9 @@
 
 namespace ASC.Employee.Core.Controllers
 {
-    [Scope(Additional = typeof(BaseLoginProviderExtension))]
-    [DefaultRoute]
-    [ApiController]
+    //[Scope(Additional = typeof(BaseLoginProviderExtension))]
+    //[DefaultRoute]
+    //[ApiController]
     public class PeopleController : ControllerBase
     {
         public Tenant Tenant { get { return ApiContext.Tenant; } }
@@ -36,8 +36,8 @@ namespace ASC.Employee.Core.Controllers
         private MessageTarget MessageTarget { get; }
         private SettingsManager SettingsManager { get; }
         private IOptionsSnapshot<AccountLinker> AccountLinker { get; }
-        private EmployeeWraperFullHelper EmployeeWraperFullHelper { get; }
-        private EmployeeWraperHelper EmployeeWraperHelper { get; }
+        private EmployeeFullDtoHelper EmployeeWraperFullHelper { get; }
+        private EmployeeDtoHelper EmployeeWraperHelper { get; }
         private UserFormatter UserFormatter { get; }
         private PasswordHasher PasswordHasher { get; }
         private UserHelpTourHelper UserHelpTourHelper { get; }
@@ -80,8 +80,8 @@ namespace ASC.Employee.Core.Controllers
             SettingsManager settingsManager,
             IOptionsMonitor<ILog> option,
             IOptionsSnapshot<AccountLinker> accountLinker,
-            EmployeeWraperFullHelper employeeWraperFullHelper,
-            EmployeeWraperHelper employeeWraperHelper,
+            EmployeeFullDtoHelper employeeWraperFullHelper,
+            EmployeeDtoHelper employeeWraperHelper,
             UserFormatter userFormatter,
             PasswordHasher passwordHasher,
             UserHelpTourHelper userHelpTourHelper,
@@ -137,13 +137,13 @@ namespace ASC.Employee.Core.Controllers
             ClientFactory = clientFactory;
         }
 
-        [Read("info")]
-        public Module GetModule()
-        {
-            var product = new PeopleProduct();
-            product.Init();
-            return new Module(product);
-        }
+        //[Read("info")]
+        //public Module GetModule()
+        //{
+        //    var product = new PeopleProduct();
+        //    product.Init();
+        //    return new Module(product);
+        //}
 
         [Read]
         public IQueryable<EmployeeDto> GetAll()
@@ -167,7 +167,7 @@ namespace ASC.Employee.Core.Controllers
         [Read("@self")]
         public EmployeeDto Self()
         {
-            return EmployeeWraperFullHelper.GetFull(UserManager.GetUser(SecurityContext.CurrentAccount.ID, EmployeeWraperFullHelper.GetExpression(ApiContext)));
+            return EmployeeWraperFullHelper.GetFull(UserManager.GetUser(SecurityContext.CurrentAccount.ID, EmployeeFullDtoHelper.GetExpression(ApiContext)));
         }
 
         [Read("email")]
diff --git a/products/ASC.People/Server/Api/PhotoController.cs b/products/ASC.People/Server/Api/PhotoController.cs
index 200428f78d..cd101274a0 100644
--- a/products/ASC.People/Server/Api/PhotoController.cs
+++ b/products/ASC.People/Server/Api/PhotoController.cs
@@ -18,7 +18,10 @@ public class PhotoController : BasePeopleController
         StudioNotifyService studioNotifyService,
         FileSizeComment fileSizeComment,
         SettingsManager settingsManager,
-        IMapper mapper)
+        UserPhotoManager userPhotoManager,
+        IHttpClientFactory httpClientFactory,
+        DisplayUserSettingsHelper displayUserSettingsHelper,
+        SetupInfo setupInfo)
         : base(
             userManager,
             authContext,
@@ -28,7 +31,10 @@ public class PhotoController : BasePeopleController
             messageService,
             messageTarget,
             studioNotifyService,
-            mapper)
+            userPhotoManager,
+            httpClientFactory,
+            displayUserSettingsHelper,
+            setupInfo)
     {
         _fileSizeComment = fileSizeComment;
         _settingsManager = settingsManager;
@@ -79,7 +85,6 @@ public class PhotoController : BasePeopleController
         return new ThumbnailsDataDto(user.ID, UserPhotoManager);
     }
 
-
     [Update("{userid}/photo")]
     public ThumbnailsDataDto UpdateMemberPhotoFromBody(string userid, [FromBody] UpdateMemberRequestDto model)
     {
diff --git a/products/ASC.People/Server/Api/UserController.cs b/products/ASC.People/Server/Api/UserController.cs
index 8920dcd7b2..1cf8bddc14 100644
--- a/products/ASC.People/Server/Api/UserController.cs
+++ b/products/ASC.People/Server/Api/UserController.cs
@@ -19,10 +19,11 @@ public class UserController : BasePeopleController
     private readonly TenantUtil _tenantUtil;
     private readonly UserFormatter _userFormatter;
     private readonly UserManagerWrapper _userManagerWrapper;
-    private readonly UserPhotoManager _userPhotoManager;
     private readonly WebItemManager _webItemManager;
     private readonly WebItemSecurity _webItemSecurity;
     private readonly WebItemSecurityCache _webItemSecurityCache;
+    private readonly EmployeeFullDtoHelper _employeeFullDtoHelper;
+    private readonly EmployeeDtoHelper _employeeDtoHelper;
 
     public UserController(
         UserManager userManager,
@@ -47,12 +48,15 @@ public class UserController : BasePeopleController
         TenantUtil tenantUtil,
         UserFormatter userFormatter,
         UserManagerWrapper userManagerWrapper,
-        UserPhotoManager userPhotoManager,
         WebItemManager webItemManager,
         WebItemSecurity webItemSecurity,
         WebItemSecurityCache webItemSecurityCache,
-        IMapper mapper
-        )
+        UserPhotoManager userPhotoManager,
+        IHttpClientFactory httpClientFactory,
+        DisplayUserSettingsHelper displayUserSettingsHelper,
+        SetupInfo setupInfo,
+        EmployeeFullDtoHelper employeeFullDtoHelper,
+        EmployeeDtoHelper employeeDtoHelper)
         : base(
             userManager,
             authContext,
@@ -62,7 +66,10 @@ public class UserController : BasePeopleController
             messageService,
             messageTarget,
             studioNotifyService,
-            mapper)
+            userPhotoManager,
+            httpClientFactory,
+            displayUserSettingsHelper,
+            setupInfo)
     {
         _constants = constants;
         _cookiesManager = cookiesManager;
@@ -78,10 +85,11 @@ public class UserController : BasePeopleController
         _tenantUtil = tenantUtil;
         _userFormatter = userFormatter;
         _userManagerWrapper = userManagerWrapper;
-        _userPhotoManager = userPhotoManager;
         _webItemManager = webItemManager;
         _webItemSecurity = webItemSecurity;
         _webItemSecurityCache = webItemSecurityCache;
+        _employeeDtoHelper = employeeDtoHelper;
+        _employeeFullDtoHelper = employeeFullDtoHelper;
     }
 
     [Create("active")]
@@ -147,13 +155,13 @@ public class UserController : BasePeopleController
         CheckReassignProccess(new[] { user.ID });
 
         var userName = user.DisplayUserName(false, DisplayUserSettingsHelper);
-        _userPhotoManager.RemovePhoto(user.ID);
+        UserPhotoManager.RemovePhoto(user.ID);
         UserManager.DeleteUser(user.ID);
         _queueWorkerRemove.Start(Tenant.TenantId, user, SecurityContext.CurrentAccount.ID, false);
 
         MessageService.Send(MessageAction.UserDeleted, MessageTarget.Create(user.ID), userName);
 
-        return Mapper.Map<UserInfo, EmployeeFullDto>(user);
+        return _employeeFullDtoHelper.GetFull(user);
     }
 
     [Delete("@self")]
@@ -191,7 +199,7 @@ public class UserController : BasePeopleController
 
         if (_coreBaseSettings.Personal)
         {
-            _userPhotoManager.RemovePhoto(user.ID);
+            UserPhotoManager.RemovePhoto(user.ID);
             UserManager.DeleteUser(user.ID);
             MessageService.Send(MessageAction.UserDeleted, MessageTarget.Create(user.ID), userName);
         }
@@ -201,7 +209,7 @@ public class UserController : BasePeopleController
             //StudioNotifyService.SendMsgProfileDeletion(Tenant.TenantId, user);
         }
 
-        return Mapper.Map<UserInfo, EmployeeFullDto>(user);
+        return _employeeFullDtoHelper.GetFull(user);
     }
 
     [Read("status/{status}/search")]
@@ -226,7 +234,7 @@ public class UserController : BasePeopleController
             list = list.Where(x => x.FirstName != null && x.FirstName.IndexOf(query, StringComparison.OrdinalIgnoreCase) > -1 || (x.LastName != null && x.LastName.IndexOf(query, StringComparison.OrdinalIgnoreCase) != -1) ||
                                    (x.UserName != null && x.UserName.IndexOf(query, StringComparison.OrdinalIgnoreCase) != -1) || (x.Email != null && x.Email.IndexOf(query, StringComparison.OrdinalIgnoreCase) != -1) || (x.ContactsList != null && x.ContactsList.Any(y => y.IndexOf(query, StringComparison.OrdinalIgnoreCase) != -1)));
 
-            return Mapper.Map<IEnumerable<UserInfo>, IEnumerable<EmployeeFullDto>>(list);
+            return list.Select(u => _employeeFullDtoHelper.GetFull(u));
         }
         catch (Exception error)
         {
@@ -256,7 +264,7 @@ public class UserController : BasePeopleController
             throw new ItemNotFoundException("User not found");
         }
 
-        return Mapper.Map<UserInfo, EmployeeFullDto>(user);
+        return _employeeFullDtoHelper.GetFull(user);
     }
 
     [Read("{username}", order: int.MaxValue)]
@@ -285,7 +293,7 @@ public class UserController : BasePeopleController
             throw new ItemNotFoundException("User not found");
         }
 
-        return Mapper.Map<UserInfo, EmployeeFullDto>(user);
+        return _employeeFullDtoHelper.GetFull(user);
     }
 
     [Read("status/{status}")]
@@ -311,7 +319,7 @@ public class UserController : BasePeopleController
     {
         var users = GetByFilter(employeeStatus, groupId, activationStatus, employeeType, isAdministrator).AsEnumerable();
 
-        return Mapper.Map<IEnumerable<UserInfo>, IEnumerable<EmployeeFullDto>>(users);
+        return users.Select(u => _employeeFullDtoHelper.GetFull(u));
     }
 
     [Read("info")]
@@ -346,7 +354,7 @@ public class UserController : BasePeopleController
 
             var users = UserManager.Search(query, EmployeeStatus.Active, groupId);
 
-            return Mapper.Map<IEnumerable<UserInfo>, IEnumerable<EmployeeFullDto>>(users);
+            return users.Select(u => _employeeFullDtoHelper.GetFull(u));
         }
         catch (Exception error)
         {
@@ -361,7 +369,7 @@ public class UserController : BasePeopleController
     {
         var users = GetByFilter(employeeStatus, groupId, activationStatus, employeeType, isAdministrator);
 
-        return Mapper.Map<IEnumerable<UserInfo>, IEnumerable<EmployeeDto>>(users);
+        return users.Select(u => _employeeDtoHelper.Get(u));
     }
 
     [AllowAnonymous]
@@ -402,9 +410,9 @@ public class UserController : BasePeopleController
     [Read("@self")]
     public EmployeeDto Self()
     {
-        var user = UserManager.GetUser(SecurityContext.CurrentAccount.ID, EmployeeWraperFullHelper.GetExpression(ApiContext));
+        var user = UserManager.GetUser(SecurityContext.CurrentAccount.ID, EmployeeFullDtoHelper.GetExpression(ApiContext));
 
-        return Mapper.Map<UserInfo, EmployeeFullDto>(user);
+        return _employeeFullDtoHelper.GetFull(user);
     }
 
     [Create("email", false)]
@@ -551,12 +559,12 @@ public class UserController : BasePeopleController
 
         UpdateDepartments(memberModel.Department, user);
 
-        if (memberModel.Files != _userPhotoManager.GetDefaultPhotoAbsoluteWebPath())
+        if (memberModel.Files != UserPhotoManager.GetDefaultPhotoAbsoluteWebPath())
         {
             UpdatePhotoUrl(memberModel.Files, user);
         }
 
-        return Mapper.Map<UserInfo, EmployeeFullDto>(user);
+        return _employeeFullDtoHelper.GetFull(user);
     }
 
     private EmployeeFullDto AddMemberAsActivated(MemberRequestDto memberModel)
@@ -606,12 +614,12 @@ public class UserController : BasePeopleController
 
         UpdateDepartments(memberModel.Department, user);
 
-        if (memberModel.Files != _userPhotoManager.GetDefaultPhotoAbsoluteWebPath())
+        if (memberModel.Files != UserPhotoManager.GetDefaultPhotoAbsoluteWebPath())
         {
             UpdatePhotoUrl(memberModel.Files, user);
         }
 
-        return Mapper.Map<UserInfo, EmployeeFullDto>(user);
+        return _employeeFullDtoHelper.GetFull(user);
     }
 
     private EmployeeFullDto ChangeUserPassword(Guid userid, MemberRequestDto memberModel)
@@ -662,7 +670,7 @@ public class UserController : BasePeopleController
             MessageService.Send(MessageAction.CookieSettingsUpdated);
         }
 
-        return Mapper.Map<UserInfo, EmployeeFullDto>(GetUserInfo(userid.ToString()));
+        return _employeeFullDtoHelper.GetFull(GetUserInfo(userid.ToString()));
     }
 
     private void CheckReassignProccess(IEnumerable<Guid> userIds)
@@ -829,14 +837,14 @@ public class UserController : BasePeopleController
                 continue;
             }
 
-            _userPhotoManager.RemovePhoto(user.ID);
+            UserPhotoManager.RemovePhoto(user.ID);
             UserManager.DeleteUser(user.ID);
             _queueWorkerRemove.Start(Tenant.TenantId, user, SecurityContext.CurrentAccount.ID, false);
         }
 
         MessageService.Send(MessageAction.UsersDeleted, MessageTarget.Create(users.Select(x => x.ID)), userNames);
 
-        return Mapper.Map<IEnumerable<UserInfo>, IEnumerable<EmployeeFullDto>>(users);
+        return users.Select(u => _employeeFullDtoHelper.GetFull(u));
     }
 
     private IEnumerable<EmployeeFullDto> ResendUserInvites(UpdateMembersRequestDto model)
@@ -893,7 +901,7 @@ public class UserController : BasePeopleController
 
         MessageService.Send(MessageAction.UsersSentActivationInstructions, MessageTarget.Create(users.Select(x => x.ID)), users.Select(x => x.DisplayUserName(false, DisplayUserSettingsHelper)));
 
-        return Mapper.Map<IEnumerable<UserInfo>, IEnumerable<EmployeeFullDto>>(users);
+        return users.Select(u => _employeeFullDtoHelper.GetFull(u));
     }
 
     private object SendEmailChangeInstructions(UpdateMemberRequestDto model)
@@ -1024,7 +1032,7 @@ public class UserController : BasePeopleController
 
             u.ActivationStatus = activationstatus;
             UserManager.SaveUserInfo(u);
-            retuls.Add(Mapper.Map<UserInfo, EmployeeFullDto>(u));
+            retuls.Add(_employeeFullDtoHelper.GetFull(u));
         }
 
         return retuls;
@@ -1091,7 +1099,7 @@ public class UserController : BasePeopleController
         UpdateContacts(memberModel.Contacts, user);
         UpdateDepartments(memberModel.Department, user);
 
-        if (memberModel.Files != _userPhotoManager.GetPhotoAbsoluteWebPath(user.ID))
+        if (memberModel.Files != UserPhotoManager.GetPhotoAbsoluteWebPath(user.ID))
         {
             UpdatePhotoUrl(memberModel.Files, user);
         }
@@ -1137,7 +1145,7 @@ public class UserController : BasePeopleController
             MessageService.Send(MessageAction.CookieSettingsUpdated);
         }
 
-        return Mapper.Map<UserInfo, EmployeeFullDto>(user);
+        return _employeeFullDtoHelper.GetFull(user);
     }
     private EmployeeFullDto UpdateMemberCulture(string userid, UpdateMemberRequestDto memberModel)
     {
@@ -1173,7 +1181,7 @@ public class UserController : BasePeopleController
             }
         }
 
-        return Mapper.Map<UserInfo, EmployeeFullDto>(user);
+        return _employeeFullDtoHelper.GetFull(user);
     }
     private IEnumerable<EmployeeFullDto> UpdateUserStatus(EmployeeStatus status, UpdateMembersRequestDto model)
     {
@@ -1214,7 +1222,7 @@ public class UserController : BasePeopleController
 
         MessageService.Send(MessageAction.UsersUpdatedStatus, MessageTarget.Create(users.Select(x => x.ID)), users.Select(x => x.DisplayUserName(false, DisplayUserSettingsHelper)));
 
-        return Mapper.Map<IEnumerable<UserInfo>, IEnumerable<EmployeeFullDto>>(users);
+        return users.Select(u => _employeeFullDtoHelper.GetFull(u));
     }
 
     private IEnumerable<EmployeeFullDto> UpdateUserType(EmployeeType type, UpdateMembersRequestDto model)
@@ -1256,7 +1264,7 @@ public class UserController : BasePeopleController
 
         MessageService.Send(MessageAction.UsersUpdatedType, MessageTarget.Create(users.Select(x => x.ID)), users.Select(x => x.DisplayUserName(false, DisplayUserSettingsHelper)));
 
-        return Mapper.Map<IEnumerable<UserInfo>, IEnumerable<EmployeeFullDto>>(users);
+        return users.Select(u => _employeeFullDtoHelper.GetFull(u));
     }
     ///// <summary>
     ///// Adds a new portal user from import with the first and last name, email address
diff --git a/products/ASC.People/Server/ApiModels/ResponseDto/GroupDto.cs b/products/ASC.People/Server/ApiModels/ResponseDto/GroupDto.cs
index 3dd5de6ce3..8dc396209c 100644
--- a/products/ASC.People/Server/ApiModels/ResponseDto/GroupDto.cs
+++ b/products/ASC.People/Server/ApiModels/ResponseDto/GroupDto.cs
@@ -50,15 +50,15 @@ public class GroupDto
 }
 
 [Scope]
-public class GroupWraperFullHelper
+public class GroupFullDtoHelper
 {
-    private UserManager UserManager { get; }
-    private EmployeeWraperHelper EmployeeWraperHelper { get; }
+    private readonly UserManager _userManager;
+    private readonly EmployeeDtoHelper _employeeWraperHelper;
 
-    public GroupWraperFullHelper(UserManager userManager, EmployeeWraperHelper employeeWraperHelper)
+    public GroupFullDtoHelper(UserManager userManager, EmployeeDtoHelper employeeWraperHelper)
     {
-        UserManager = userManager;
-        EmployeeWraperHelper = employeeWraperHelper;
+        _userManager = userManager;
+        _employeeWraperHelper = employeeWraperHelper;
     }
 
     public GroupDto Get(GroupInfo group, bool includeMembers)
@@ -69,12 +69,12 @@ public class GroupWraperFullHelper
             Category = group.CategoryID,
             Parent = group.Parent != null ? group.Parent.ID : Guid.Empty,
             Name = group.Name,
-            Manager = EmployeeWraperHelper.Get(UserManager.GetUsers(UserManager.GetDepartmentManager(group.ID)))
+            Manager = _employeeWraperHelper.Get(_userManager.GetUsers(_userManager.GetDepartmentManager(group.ID)))
         };
 
         if (includeMembers)
         {
-            result.Members = new List<EmployeeDto>(UserManager.GetUsersByGroup(group.ID).Select(EmployeeWraperHelper.Get));
+            result.Members = new List<EmployeeDto>(_userManager.GetUsersByGroup(group.ID).Select(_employeeWraperHelper.Get));
         }
 
         return result;
diff --git a/products/ASC.People/Server/GlobalUsings.cs b/products/ASC.People/Server/GlobalUsings.cs
index 4dc21a15b7..de1d92052c 100644
--- a/products/ASC.People/Server/GlobalUsings.cs
+++ b/products/ASC.People/Server/GlobalUsings.cs
@@ -30,6 +30,7 @@ global using ASC.FederatedLogin.Profile;
 global using ASC.MessagingSystem.Core;
 global using ASC.MessagingSystem.Models;
 global using ASC.People;
+global using ASC.People.Api;
 global using ASC.People.ApiModels.RequestDto;
 global using ASC.People.ApiModels.ResponseDto;
 global using ASC.People.Resources;
@@ -47,9 +48,11 @@ global using ASC.Web.Studio.Utility;
 
 global using AutoMapper;
 
+global using Autofac;
 global using Autofac.Extensions.DependencyInjection;
 
 global using Microsoft.AspNetCore.Authorization;
+global using Microsoft.AspNetCore.Builder;
 global using Microsoft.AspNetCore.Hosting;
 global using Microsoft.AspNetCore.Http;
 global using Microsoft.AspNetCore.Http.Extensions;
@@ -58,6 +61,7 @@ global using Microsoft.Extensions.Configuration;
 global using Microsoft.Extensions.DependencyInjection;
 global using Microsoft.Extensions.Hosting;
 global using Microsoft.Extensions.Options;
+global using Microsoft.Extensions.Hosting.WindowsServices;
 
 global using SixLabors.ImageSharp;
 global using SixLabors.ImageSharp.Formats;
\ No newline at end of file
diff --git a/products/ASC.People/Server/Program.cs b/products/ASC.People/Server/Program.cs
index 35899a2ba7..7120d76a37 100644
--- a/products/ASC.People/Server/Program.cs
+++ b/products/ASC.People/Server/Program.cs
@@ -1,70 +1,74 @@
-namespace ASC.People
+var options = new WebApplicationOptions
 {
-    public static class Program
+    Args = args,
+    ContentRootPath = WindowsServiceHelpers.IsWindowsService() ? AppContext.BaseDirectory : default
+};
+
+var builder = WebApplication.CreateBuilder(options);
+var startup = new Startup(builder.Configuration, builder.Environment);
+
+builder.Host.UseSystemd();
+builder.Host.UseWindowsService();
+builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
+
+builder.WebHost.ConfigureKestrel((hostingContext, serverOptions) =>
+{
+    var kestrelConfig = hostingContext.Configuration.GetSection("Kestrel");
+
+    if (!kestrelConfig.Exists())
     {
-        public async static Task Main(string[] args)
+        return;
+    }
+
+    var unixSocket = kestrelConfig.GetValue<string>("ListenUnixSocket");
+
+    if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
+    {
+        if (!string.IsNullOrWhiteSpace(unixSocket))
         {
-            var host = CreateHostBuilder(args).Build();
+            unixSocket = string.Format(unixSocket, hostingContext.HostingEnvironment.ApplicationName.Replace("ASC.", "").Replace(".", ""));
 
-            await host.RunAsync();
-        }
-
-        public static IHostBuilder CreateHostBuilder(string[] args)
-        {
-            return Host.CreateDefaultBuilder(args)
-                .UseSystemd()
-                .UseWindowsService()
-                .UseServiceProviderFactory(new AutofacServiceProviderFactory())
-                .ConfigureWebHostDefaults(webBuilder =>
-                {
-                    var builder = webBuilder.UseStartup<Startup>();
-
-                    builder.ConfigureKestrel((hostingContext, serverOptions) =>
-                    {
-                        var kestrelConfig = hostingContext.Configuration.GetSection("Kestrel");
-
-                        if (!kestrelConfig.Exists()) return;
-
-                        var unixSocket = kestrelConfig.GetValue<string>("ListenUnixSocket");
-
-                        if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
-                        {
-                            if (!String.IsNullOrWhiteSpace(unixSocket))
-                            {
-                                unixSocket = String.Format(unixSocket, hostingContext.HostingEnvironment.ApplicationName.Replace("ASC.", "").Replace(".", ""));
-
-                                serverOptions.ListenUnixSocket(unixSocket);
-                            }
-                        }
-                    });
-                })
-                .ConfigureAppConfiguration((hostingContext, config) =>
-                {
-                    var buided = config.Build();
-                    var path = buided["pathToConf"];
-                    if (!Path.IsPathRooted(path))
-                    {
-                        path = Path.GetFullPath(CrossPlatform.PathCombine(hostingContext.HostingEnvironment.ContentRootPath, path));
-                    }
-
-                    config.SetBasePath(path);
-                    config
-                    .AddJsonFile("appsettings.json")
-                    .AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true)
-                    .AddJsonFile("storage.json")
-                    .AddJsonFile("kafka.json")
-                    .AddJsonFile($"kafka.{hostingContext.HostingEnvironment.EnvironmentName}.json", true)
-                    .AddJsonFile("redis.json")
-                    .AddJsonFile($"redis.{hostingContext.HostingEnvironment.EnvironmentName}.json", true)
-                    .AddEnvironmentVariables()
-                    .AddCommandLine(args)
-                    .AddInMemoryCollection(new Dictionary<string, string>
-                            {
-                                {"pathToConf", path }
-                            }
-                        );
-                })
-            .ConfigureNLogLogging();
+            serverOptions.ListenUnixSocket(unixSocket);
         }
     }
-}
\ No newline at end of file
+});
+
+builder.Host.ConfigureAppConfiguration((hostingContext, config) =>
+{
+    var buided = config.Build();
+    var path = buided["pathToConf"];
+    if (!Path.IsPathRooted(path))
+    {
+        path = Path.GetFullPath(CrossPlatform.PathCombine(hostingContext.HostingEnvironment.ContentRootPath, path));
+    }
+
+    config.SetBasePath(path);
+    config.AddJsonFile("appsettings.json")
+          .AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true)
+          .AddJsonFile("storage.json")
+          .AddJsonFile("kafka.json")
+          .AddJsonFile($"kafka.{hostingContext.HostingEnvironment.EnvironmentName}.json", true)
+          .AddJsonFile("redis.json")
+          .AddJsonFile($"redis.{hostingContext.HostingEnvironment.EnvironmentName}.json", true)
+          .AddEnvironmentVariables()
+          .AddCommandLine(args)
+          .AddInMemoryCollection(new Dictionary<string, string>
+          {
+              {"pathToConf", path }
+          });
+});
+
+startup.ConfigureServices(builder.Services);
+
+builder.Host.ConfigureContainer<ContainerBuilder>(containerBuilder =>
+{
+    startup.ConfigureContainer(containerBuilder);
+});
+
+builder.Host.ConfigureNLogLogging();
+
+var app = builder.Build();
+
+startup.Configure(app, app.Environment);
+
+await app.RunAsync();
\ No newline at end of file
diff --git a/products/ASC.People/Server/Startup.cs b/products/ASC.People/Server/Startup.cs
index 95cb5d0bf3..43ff7771bb 100644
--- a/products/ASC.People/Server/Startup.cs
+++ b/products/ASC.People/Server/Startup.cs
@@ -1,19 +1,24 @@
-namespace ASC.People
+namespace ASC.People;
+
+public class Startup : BaseStartup
 {
-    public class Startup : BaseStartup
+    public override bool ConfirmAddScheme => true;
+
+    public Startup(IConfiguration configuration, IHostEnvironment hostEnvironment) : base(configuration, hostEnvironment)
     {
-        public override bool ConfirmAddScheme { get => true; }
-
-        public Startup(IConfiguration configuration, IHostEnvironment hostEnvironment) : base(configuration, hostEnvironment)
-        {
-        }
-
-        public override void ConfigureServices(IServiceCollection services)
-        {
-            base.ConfigureServices(services);
-
-            DIHelper.TryAdd<PeopleController>();
-            DIHelper.TryAdd<GroupController>();
-        }
-    }
+    }
+
+    public override void ConfigureServices(IServiceCollection services)
+    {
+        base.ConfigureServices(services);
+
+        DIHelper.TryAdd<UserController>();
+        DIHelper.TryAdd<ContactsController>();
+        DIHelper.TryAdd<NotificationController>();
+        DIHelper.TryAdd<PhotoController>();
+        DIHelper.TryAdd<ReassignController>();
+        DIHelper.TryAdd<RemoveUserDataController>();
+        DIHelper.TryAdd<ThirdpartyController>();
+        DIHelper.TryAdd<GroupController>();
+    }
 }
\ No newline at end of file
diff --git a/web/ASC.Web.Api/Controllers/SettingsController.cs b/web/ASC.Web.Api/Controllers/SettingsController.cs
index 2c0ba318d0..2a4cef5456 100644
--- a/web/ASC.Web.Api/Controllers/SettingsController.cs
+++ b/web/ASC.Web.Api/Controllers/SettingsController.cs
@@ -43,7 +43,7 @@ namespace ASC.Api.Settings
         private StudioNotifyService StudioNotifyService { get; }
         private IWebHostEnvironment WebHostEnvironment { get; }
         private IServiceProvider ServiceProvider { get; }
-        private EmployeeWraperHelper EmployeeWraperHelper { get; }
+        private EmployeeDtoHelper EmployeeWraperHelper { get; }
         private ConsumerFactory ConsumerFactory { get; }
         private SmsProviderManager SmsProviderManager { get; }
         private TimeZoneConverter TimeZoneConverter { get; }
@@ -143,7 +143,7 @@ namespace ASC.Api.Settings
             StorageSettingsHelper storageSettingsHelper,
             IWebHostEnvironment webHostEnvironment,
             IServiceProvider serviceProvider,
-            EmployeeWraperHelper employeeWraperHelper,
+            EmployeeDtoHelper employeeWraperHelper,
             ConsumerFactory consumerFactory,
             SmsProviderManager smsProviderManager,
             TimeZoneConverter timeZoneConverter,

From 0a51cf1cd525622950ad7e04186257ef3f8c8533 Mon Sep 17 00:00:00 2001
From: MaksimChegulov <maksim.chegulov@onlyoffice.com>
Date: Mon, 28 Feb 2022 23:30:49 +0300
Subject: [PATCH 17/28] remove unnecessary

---
 .../ASC.People/Server/Api/PeopleController.cs | 2105 -----------------
 1 file changed, 2105 deletions(-)
 delete mode 100644 products/ASC.People/Server/Api/PeopleController.cs

diff --git a/products/ASC.People/Server/Api/PeopleController.cs b/products/ASC.People/Server/Api/PeopleController.cs
deleted file mode 100644
index 179edde540..0000000000
--- a/products/ASC.People/Server/Api/PeopleController.cs
+++ /dev/null
@@ -1,2105 +0,0 @@
-using SecurityContext = ASC.Core.SecurityContext;
-
-namespace ASC.Employee.Core.Controllers
-{
-    //[Scope(Additional = typeof(BaseLoginProviderExtension))]
-    //[DefaultRoute]
-    //[ApiController]
-    public class PeopleController : ControllerBase
-    {
-        public Tenant Tenant { get { return ApiContext.Tenant; } }
-        private ApiContext ApiContext { get; }
-        private MessageService MessageService { get; }
-        private QueueWorkerReassign QueueWorkerReassign { get; }
-        private QueueWorkerRemove QueueWorkerRemove { get; }
-        private StudioNotifyService StudioNotifyService { get; }
-        private UserManagerWrapper UserManagerWrapper { get; }
-        private UserManager UserManager { get; }
-        private TenantExtra TenantExtra { get; }
-        private TenantStatisticsProvider TenantStatisticsProvider { get; }
-        private UserPhotoManager UserPhotoManager { get; }
-        private SecurityContext SecurityContext { get; }
-        private CookiesManager CookiesManager { get; }
-        private WebItemSecurity WebItemSecurity { get; }
-        private PermissionContext PermissionContext { get; }
-        private AuthContext AuthContext { get; }
-        private WebItemManager WebItemManager { get; }
-        private CustomNamingPeople CustomNamingPeople { get; }
-        private TenantUtil TenantUtil { get; }
-        private CoreBaseSettings CoreBaseSettings { get; }
-        private SetupInfo SetupInfo { get; }
-        private FileSizeComment FileSizeComment { get; }
-        private DisplayUserSettingsHelper DisplayUserSettingsHelper { get; }
-        private Signature Signature { get; }
-        private InstanceCrypto InstanceCrypto { get; }
-        private WebItemSecurityCache WebItemSecurityCache { get; }
-        private MessageTarget MessageTarget { get; }
-        private SettingsManager SettingsManager { get; }
-        private IOptionsSnapshot<AccountLinker> AccountLinker { get; }
-        private EmployeeFullDtoHelper EmployeeWraperFullHelper { get; }
-        private EmployeeDtoHelper EmployeeWraperHelper { get; }
-        private UserFormatter UserFormatter { get; }
-        private PasswordHasher PasswordHasher { get; }
-        private UserHelpTourHelper UserHelpTourHelper { get; }
-        private PersonalSettingsHelper PersonalSettingsHelper { get; }
-        private CommonLinkUtility CommonLinkUtility { get; }
-        private MobileDetector MobileDetector { get; }
-        private ProviderManager ProviderManager { get; }
-        private Constants Constants { get; }
-        private Recaptcha Recaptcha { get; }
-        private ILog Log { get; }
-        private IHttpClientFactory ClientFactory { get; }
-
-        public PeopleController(
-            MessageService messageService,
-            QueueWorkerReassign queueWorkerReassign,
-            QueueWorkerRemove queueWorkerRemove,
-            StudioNotifyService studioNotifyService,
-            UserManagerWrapper userManagerWrapper,
-            ApiContext apiContext,
-            UserManager userManager,
-            TenantExtra tenantExtra,
-            TenantStatisticsProvider tenantStatisticsProvider,
-            UserPhotoManager userPhotoManager,
-            SecurityContext securityContext,
-            CookiesManager cookiesManager,
-            WebItemSecurity webItemSecurity,
-            PermissionContext permissionContext,
-            AuthContext authContext,
-            WebItemManager webItemManager,
-            CustomNamingPeople customNamingPeople,
-            TenantUtil tenantUtil,
-            CoreBaseSettings coreBaseSettings,
-            SetupInfo setupInfo,
-            FileSizeComment fileSizeComment,
-            DisplayUserSettingsHelper displayUserSettingsHelper,
-            Signature signature,
-            InstanceCrypto instanceCrypto,
-            WebItemSecurityCache webItemSecurityCache,
-            MessageTarget messageTarget,
-            SettingsManager settingsManager,
-            IOptionsMonitor<ILog> option,
-            IOptionsSnapshot<AccountLinker> accountLinker,
-            EmployeeFullDtoHelper employeeWraperFullHelper,
-            EmployeeDtoHelper employeeWraperHelper,
-            UserFormatter userFormatter,
-            PasswordHasher passwordHasher,
-            UserHelpTourHelper userHelpTourHelper,
-            PersonalSettingsHelper personalSettingsHelper,
-            CommonLinkUtility commonLinkUtility,
-            MobileDetector mobileDetector,
-            ProviderManager providerManager,
-            Constants constants,
-            Recaptcha recaptcha,
-            IHttpClientFactory clientFactory
-            )
-        {
-            Log = option.Get("ASC.Api");
-            MessageService = messageService;
-            QueueWorkerReassign = queueWorkerReassign;
-            QueueWorkerRemove = queueWorkerRemove;
-            StudioNotifyService = studioNotifyService;
-            UserManagerWrapper = userManagerWrapper;
-            ApiContext = apiContext;
-            UserManager = userManager;
-            TenantExtra = tenantExtra;
-            TenantStatisticsProvider = tenantStatisticsProvider;
-            UserPhotoManager = userPhotoManager;
-            SecurityContext = securityContext;
-            CookiesManager = cookiesManager;
-            WebItemSecurity = webItemSecurity;
-            PermissionContext = permissionContext;
-            AuthContext = authContext;
-            WebItemManager = webItemManager;
-            CustomNamingPeople = customNamingPeople;
-            TenantUtil = tenantUtil;
-            CoreBaseSettings = coreBaseSettings;
-            SetupInfo = setupInfo;
-            FileSizeComment = fileSizeComment;
-            DisplayUserSettingsHelper = displayUserSettingsHelper;
-            Signature = signature;
-            InstanceCrypto = instanceCrypto;
-            WebItemSecurityCache = webItemSecurityCache;
-            MessageTarget = messageTarget;
-            SettingsManager = settingsManager;
-            AccountLinker = accountLinker;
-            EmployeeWraperFullHelper = employeeWraperFullHelper;
-            EmployeeWraperHelper = employeeWraperHelper;
-            UserFormatter = userFormatter;
-            PasswordHasher = passwordHasher;
-            UserHelpTourHelper = userHelpTourHelper;
-            PersonalSettingsHelper = personalSettingsHelper;
-            CommonLinkUtility = commonLinkUtility;
-            MobileDetector = mobileDetector;
-            ProviderManager = providerManager;
-            Constants = constants;
-            Recaptcha = recaptcha;
-            ClientFactory = clientFactory;
-        }
-
-        //[Read("info")]
-        //public Module GetModule()
-        //{
-        //    var product = new PeopleProduct();
-        //    product.Init();
-        //    return new Module(product);
-        //}
-
-        [Read]
-        public IQueryable<EmployeeDto> GetAll()
-        {
-            return GetByStatus(EmployeeStatus.Active);
-        }
-
-        [Read("status/{status}")]
-        public IQueryable<EmployeeDto> GetByStatus(EmployeeStatus status)
-        {
-            if (CoreBaseSettings.Personal) throw new Exception("Method not available");
-            Guid? groupId = null;
-            if ("group".Equals(ApiContext.FilterBy, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(ApiContext.FilterValue))
-            {
-                groupId = new Guid(ApiContext.FilterValue);
-                ApiContext.SetDataFiltered();
-            }
-            return GetFullByFilter(status, groupId, null, null, null);
-        }
-
-        [Read("@self")]
-        public EmployeeDto Self()
-        {
-            return EmployeeWraperFullHelper.GetFull(UserManager.GetUser(SecurityContext.CurrentAccount.ID, EmployeeFullDtoHelper.GetExpression(ApiContext)));
-        }
-
-        [Read("email")]
-        public EmployeeFullDto GetByEmail([FromQuery] string email)
-        {
-            if (CoreBaseSettings.Personal && !UserManager.GetUsers(SecurityContext.CurrentAccount.ID).IsOwner(Tenant))
-                throw new MethodAccessException("Method not available");
-            var user = UserManager.GetUserByEmail(email);
-            if (user.ID == Constants.LostUser.ID)
-            {
-                throw new ItemNotFoundException("User not found");
-            }
-
-            return EmployeeWraperFullHelper.GetFull(user);
-        }
-
-        [Read("{username}", order: int.MaxValue)]
-        public EmployeeFullDto GetById(string username)
-        {
-            if (CoreBaseSettings.Personal) throw new MethodAccessException("Method not available");
-            var user = UserManager.GetUserByUserName(username);
-            if (user.ID == Constants.LostUser.ID)
-            {
-                if (Guid.TryParse(username, out var userId))
-                {
-                    user = UserManager.GetUsers(userId);
-                }
-                else
-                {
-                    Log.Error(string.Format("Account {0} сould not get user by name {1}", SecurityContext.CurrentAccount.ID, username));
-                }
-            }
-
-            if (user.ID == Constants.LostUser.ID)
-            {
-                throw new ItemNotFoundException("User not found");
-            }
-
-            return EmployeeWraperFullHelper.GetFull(user);
-        }
-
-        [Read("@search/{query}")]
-        public IEnumerable<EmployeeFullDto> GetSearch(string query)
-        {
-            if (CoreBaseSettings.Personal) throw new MethodAccessException("Method not available");
-            try
-            {
-                var groupId = Guid.Empty;
-                if ("group".Equals(ApiContext.FilterBy, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(ApiContext.FilterValue))
-                {
-                    groupId = new Guid(ApiContext.FilterValue);
-                }
-
-                return UserManager.Search(query, EmployeeStatus.Active, groupId).Select(EmployeeWraperFullHelper.GetFull);
-            }
-            catch (Exception error)
-            {
-                Log.Error(error);
-            }
-            return null;
-        }
-
-        [Read("search")]
-        public IEnumerable<EmployeeFullDto> GetPeopleSearch([FromQuery] string query)
-        {
-            return GetSearch(query);
-        }
-
-        [Read("status/{status}/search")]
-        public IEnumerable<EmployeeFullDto> GetAdvanced(EmployeeStatus status, [FromQuery] string query)
-        {
-            if (CoreBaseSettings.Personal) throw new MethodAccessException("Method not available");
-            try
-            {
-                var list = UserManager.GetUsers(status).AsEnumerable();
-
-                if ("group".Equals(ApiContext.FilterBy, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(ApiContext.FilterValue))
-                {
-                    var groupId = new Guid(ApiContext.FilterValue);
-                    //Filter by group
-                    list = list.Where(x => UserManager.IsUserInGroup(x.ID, groupId));
-                    ApiContext.SetDataFiltered();
-                }
-
-                list = list.Where(x => x.FirstName != null && x.FirstName.IndexOf(query, StringComparison.OrdinalIgnoreCase) > -1 || (x.LastName != null && x.LastName.IndexOf(query, StringComparison.OrdinalIgnoreCase) != -1) ||
-                                       (x.UserName != null && x.UserName.IndexOf(query, StringComparison.OrdinalIgnoreCase) != -1) || (x.Email != null && x.Email.IndexOf(query, StringComparison.OrdinalIgnoreCase) != -1) || (x.ContactsList != null && x.ContactsList.Any(y => y.IndexOf(query, StringComparison.OrdinalIgnoreCase) != -1)));
-
-                return list.Select(EmployeeWraperFullHelper.GetFull);
-            }
-            catch (Exception error)
-            {
-                Log.Error(error);
-            }
-            return null;
-        }
-
-        ///// <summary>
-        ///// Adds a new portal user from import with the first and last name, email address
-        ///// </summary>
-        ///// <short>
-        ///// Add new import user
-        ///// </short>
-        ///// <param name="userList">The list of users to add</param>
-        ///// <param name="importUsersAsCollaborators" optional="true">Add users as guests (bool type: false|true)</param>
-        ///// <returns>Newly created users</returns>
-        //[Create("import/save")]
-        //public void SaveUsers(string userList, bool importUsersAsCollaborators)
-        //{
-        //    lock (progressQueue.SynchRoot)
-        //    {
-        //        var task = progressQueue.GetItems().OfType<ImportUsersTask>().FirstOrDefault(t => (int)t.Id == TenantProvider.CurrentTenantID);
-        //        if (task != null && task.IsCompleted)
-        //        {
-        //            progressQueue.Remove(task);
-        //            task = null;
-        //        }
-        //        if (task == null)
-        //        {
-        //            progressQueue.Add(new ImportUsersTask(userList, importUsersAsCollaborators, GetHttpHeaders(HttpContext.Current.Request))
-        //            {
-        //                Id = TenantProvider.CurrentTenantID,
-        //                UserId = SecurityContext.CurrentAccount.ID,
-        //                Percentage = 0
-        //            });
-        //        }
-        //    }
-        //}
-
-        //[Read("import/status")]
-        //public object GetStatus()
-        //{
-        //    lock (progressQueue.SynchRoot)
-        //    {
-        //        var task = progressQueue.GetItems().OfType<ImportUsersTask>().FirstOrDefault(t => (int)t.Id == TenantProvider.CurrentTenantID);
-        //        if (task == null) return null;
-
-        //        return new
-        //        {
-        //            Completed = task.IsCompleted,
-        //            Percents = (int)task.Percentage,
-        //            UserCounter = task.GetUserCounter,
-        //            Status = (int)task.Status,
-        //            Error = (string)task.Error,
-        //            task.Data
-        //        };
-        //    }
-        //}
-
-
-        [Read("filter")]
-        public IQueryable<EmployeeFullDto> GetFullByFilter(EmployeeStatus? employeeStatus, Guid? groupId, EmployeeActivationStatus? activationStatus, EmployeeType? employeeType, bool? isAdministrator)
-        {
-            var users = GetByFilter(employeeStatus, groupId, activationStatus, employeeType, isAdministrator);
-            return users.Select(r => EmployeeWraperFullHelper.GetFull(r));
-        }
-
-        [Read("simple/filter")]
-        public IEnumerable<EmployeeDto> GetSimpleByFilter(EmployeeStatus? employeeStatus, Guid? groupId, EmployeeActivationStatus? activationStatus, EmployeeType? employeeType, bool? isAdministrator)
-        {
-            var users = GetByFilter(employeeStatus, groupId, activationStatus, employeeType, isAdministrator);
-            return users.Select(EmployeeWraperHelper.Get);
-        }
-
-        private IQueryable<UserInfo> GetByFilter(EmployeeStatus? employeeStatus, Guid? groupId, EmployeeActivationStatus? activationStatus, EmployeeType? employeeType, bool? isAdministrator)
-        {
-            if (CoreBaseSettings.Personal) throw new MethodAccessException("Method not available");
-            var isAdmin = UserManager.GetUsers(SecurityContext.CurrentAccount.ID).IsAdmin(UserManager) ||
-                          WebItemSecurity.IsProductAdministrator(WebItemManager.PeopleProductID, SecurityContext.CurrentAccount.ID);
-
-            var includeGroups = new List<List<Guid>>();
-            if (groupId.HasValue)
-            {
-                includeGroups.Add(new List<Guid> { groupId.Value });
-            }
-
-            var excludeGroups = new List<Guid>();
-
-            if (employeeType != null)
-            {
-                switch (employeeType)
-                {
-                    case EmployeeType.User:
-                        excludeGroups.Add(Constants.GroupVisitor.ID);
-                        break;
-                    case EmployeeType.Visitor:
-                        includeGroups.Add(new List<Guid> { Constants.GroupVisitor.ID });
-                        break;
-                }
-            }
-
-            if (isAdministrator.HasValue && isAdministrator.Value)
-            {
-                var adminGroups = new List<Guid>
-                {
-                    Constants.GroupAdmin.ID
-                };
-
-                var products = WebItemManager.GetItemsAll().Where(i => i is IProduct || i.ID == WebItemManager.MailProductID);
-                adminGroups.AddRange(products.Select(r => r.ID));
-
-                includeGroups.Add(adminGroups);
-            }
-
-            var users = UserManager.GetUsers(isAdmin, employeeStatus, includeGroups, excludeGroups, activationStatus, ApiContext.FilterValue, ApiContext.SortBy, !ApiContext.SortDescending, ApiContext.Count, ApiContext.StartIndex, out var total, out var count);
-
-            ApiContext.SetTotalCount(total).SetCount(count);
-
-            return users;
-        }
-
-        [AllowAnonymous]
-        [Create(@"register")]
-        public Task<string> RegisterUserOnPersonalAsync(RegisterPersonalUserRequestDto model)
-        {
-            if (!CoreBaseSettings.Personal) throw new MethodAccessException("Method is only available on personal.onlyoffice.com");
-
-            return InternalRegisterUserOnPersonalAsync(model);
-        }
-
-        private async Task<string> InternalRegisterUserOnPersonalAsync(RegisterPersonalUserRequestDto model)
-        {
-            try
-            {
-                if (CoreBaseSettings.CustomMode) model.Lang = "ru-RU";
-
-                var cultureInfo = SetupInfo.GetPersonalCulture(model.Lang).Value;
-
-                if (cultureInfo != null)
-                {
-                    Thread.CurrentThread.CurrentUICulture = cultureInfo;
-                }
-
-                model.Email.ThrowIfNull(new ArgumentException(Resource.ErrorEmailEmpty, "email"));
-
-                if (!model.Email.TestEmailRegex()) throw new ArgumentException(Resource.ErrorNotCorrectEmail, "email");
-
-                if (!SetupInfo.IsSecretEmail(model.Email)
-                    && !string.IsNullOrEmpty(SetupInfo.RecaptchaPublicKey) && !string.IsNullOrEmpty(SetupInfo.RecaptchaPrivateKey))
-                {
-                    var ip = Request.Headers["X-Forwarded-For"].ToString() ?? Request.GetUserHostAddress();
-
-                    if (string.IsNullOrEmpty(model.RecaptchaResponse)
-                        || !await Recaptcha.ValidateRecaptchaAsync(model.RecaptchaResponse, ip))
-                    {
-                        throw new RecaptchaException(Resource.RecaptchaInvalid);
-                    }
-                }
-
-                var newUserInfo = UserManager.GetUserByEmail(model.Email);
-
-                if (UserManager.UserExists(newUserInfo.ID))
-                {
-                    if (!SetupInfo.IsSecretEmail(model.Email) || SecurityContext.IsAuthenticated)
-                    {
-                        StudioNotifyService.SendAlreadyExist(model.Email);
-                        return string.Empty;
-                    }
-
-                    try
-                    {
-                        SecurityContext.AuthenticateMe(ASC.Core.Configuration.Constants.CoreSystem);
-                        UserManager.DeleteUser(newUserInfo.ID);
-                    }
-                    finally
-                    {
-                        SecurityContext.Logout();
-                    }
-                }
-                if (!model.Spam)
-                {
-                    try
-                    {
-                        //TODO
-                        //const string _databaseID = "com";
-                        //using (var db = DbManager.FromHttpContext(_databaseID))
-                        //{
-                        //    db.ExecuteNonQuery(new SqlInsert("template_unsubscribe", false)
-                        //                           .InColumnValue("email", email.ToLowerInvariant())
-                        //                           .InColumnValue("reason", "personal")
-                        //        );
-                        //    Log.Debug(String.Format("Write to template_unsubscribe {0}", email.ToLowerInvariant()));
-                        //}
-                    }
-                    catch (Exception ex)
-                    {
-                        Log.Debug($"ERROR write to template_unsubscribe {ex.Message}, email:{model.Email.ToLowerInvariant()}");
-                    }
-                }
-
-                StudioNotifyService.SendInvitePersonal(model.Email);
-            }
-            catch (Exception ex)
-            {
-                return ex.Message;
-            }
-            return string.Empty;
-        }
-
-        [Create]
-        [Authorize(AuthenticationSchemes = "confirm", Roles = "LinkInvite,Everyone")]
-        public EmployeeFullDto AddMemberFromBody([FromBody] MemberRequestDto memberModel)
-        {
-            return AddMember(memberModel);
-        }
-
-        [Create]
-        [Authorize(AuthenticationSchemes = "confirm", Roles = "LinkInvite,Everyone")]
-        [Consumes("application/x-www-form-urlencoded")]
-        public EmployeeFullDto AddMemberFromForm([FromForm] MemberRequestDto memberModel)
-        {
-            return AddMember(memberModel);
-        }
-
-        private EmployeeFullDto AddMember(MemberRequestDto memberModel)
-        {
-            ApiContext.AuthByClaim();
-
-            PermissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
-
-            memberModel.PasswordHash = (memberModel.PasswordHash ?? "").Trim();
-            if (string.IsNullOrEmpty(memberModel.PasswordHash))
-            {
-                memberModel.Password = (memberModel.Password ?? "").Trim();
-
-                if (string.IsNullOrEmpty(memberModel.Password))
-                {
-                    memberModel.Password = UserManagerWrapper.GeneratePassword();
-                }
-                else
-                {
-                    UserManagerWrapper.CheckPasswordPolicy(memberModel.Password);
-                }
-
-                memberModel.PasswordHash = PasswordHasher.GetClientPassword(memberModel.Password);
-            }
-
-            var user = new UserInfo();
-
-            //Validate email
-            var address = new MailAddress(memberModel.Email);
-            user.Email = address.Address;
-            //Set common fields
-            user.FirstName = memberModel.Firstname;
-            user.LastName = memberModel.Lastname;
-            user.Title = memberModel.Title;
-            user.Location = memberModel.Location;
-            user.Notes = memberModel.Comment;
-            user.Sex = "male".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase)
-                           ? true
-                           : ("female".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase) ? (bool?)false : null);
-
-            user.BirthDate = memberModel.Birthday != null && memberModel.Birthday != DateTime.MinValue ? TenantUtil.DateTimeFromUtc(memberModel.Birthday) : null;
-            user.WorkFromDate = memberModel.Worksfrom != null && memberModel.Worksfrom != DateTime.MinValue ? TenantUtil.DateTimeFromUtc(memberModel.Worksfrom) : DateTime.UtcNow.Date;
-
-            UpdateContacts(memberModel.Contacts, user);
-
-            user = UserManagerWrapper.AddUser(user, memberModel.PasswordHash, memberModel.FromInviteLink, true, memberModel.IsVisitor, memberModel.FromInviteLink);
-
-            var messageAction = memberModel.IsVisitor ? MessageAction.GuestCreated : MessageAction.UserCreated;
-            MessageService.Send(messageAction, MessageTarget.Create(user.ID), user.DisplayUserName(false, DisplayUserSettingsHelper));
-
-            UpdateDepartments(memberModel.Department, user);
-
-            if (memberModel.Files != UserPhotoManager.GetDefaultPhotoAbsoluteWebPath())
-            {
-                UpdatePhotoUrl(memberModel.Files, user);
-            }
-
-            return EmployeeWraperFullHelper.GetFull(user);
-        }
-
-        [Create("active")]
-        public EmployeeFullDto AddMemberAsActivatedFromBody([FromBody] MemberRequestDto memberModel)
-        {
-            return AddMemberAsActivated(memberModel);
-        }
-
-        [Create("active")]
-        [Consumes("application/x-www-form-urlencoded")]
-        public EmployeeFullDto AddMemberAsActivatedFromForm([FromForm] MemberRequestDto memberModel)
-        {
-            return AddMemberAsActivated(memberModel);
-        }
-
-        private EmployeeFullDto AddMemberAsActivated(MemberRequestDto memberModel)
-        {
-            PermissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
-
-            var user = new UserInfo();
-
-            memberModel.PasswordHash = (memberModel.PasswordHash ?? "").Trim();
-            if (string.IsNullOrEmpty(memberModel.PasswordHash))
-            {
-                memberModel.Password = (memberModel.Password ?? "").Trim();
-
-                if (string.IsNullOrEmpty(memberModel.Password))
-                {
-                    memberModel.Password = UserManagerWrapper.GeneratePassword();
-                }
-                else
-                {
-                    UserManagerWrapper.CheckPasswordPolicy(memberModel.Password);
-                }
-
-                memberModel.PasswordHash = PasswordHasher.GetClientPassword(memberModel.Password);
-            }
-
-            //Validate email
-            var address = new MailAddress(memberModel.Email);
-            user.Email = address.Address;
-            //Set common fields
-            user.FirstName = memberModel.Firstname;
-            user.LastName = memberModel.Lastname;
-            user.Title = memberModel.Title;
-            user.Location = memberModel.Location;
-            user.Notes = memberModel.Comment;
-            user.Sex = "male".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase)
-                           ? true
-                           : ("female".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase) ? (bool?)false : null);
-
-            user.BirthDate = memberModel.Birthday != null ? TenantUtil.DateTimeFromUtc(memberModel.Birthday) : null;
-            user.WorkFromDate = memberModel.Worksfrom != null ? TenantUtil.DateTimeFromUtc(memberModel.Worksfrom) : DateTime.UtcNow.Date;
-
-            UpdateContacts(memberModel.Contacts, user);
-
-            user = UserManagerWrapper.AddUser(user, memberModel.PasswordHash, false, false, memberModel.IsVisitor);
-
-            user.ActivationStatus = EmployeeActivationStatus.Activated;
-
-            UpdateDepartments(memberModel.Department, user);
-
-            if (memberModel.Files != UserPhotoManager.GetDefaultPhotoAbsoluteWebPath())
-            {
-                UpdatePhotoUrl(memberModel.Files, user);
-            }
-
-            return EmployeeWraperFullHelper.GetFull(user);
-        }
-
-        [Update("{userid}/culture")]
-        public EmployeeFullDto UpdateMemberCultureFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
-        {
-            return UpdateMemberCulture(userid, memberModel);
-        }
-
-        [Update("{userid}/culture")]
-        [Consumes("application/x-www-form-urlencoded")]
-        public EmployeeFullDto UpdateMemberCultureFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
-        {
-            return UpdateMemberCulture(userid, memberModel);
-        }
-
-        private EmployeeFullDto UpdateMemberCulture(string userid, UpdateMemberRequestDto memberModel)
-        {
-            var user = GetUserInfo(userid);
-
-            if (UserManager.IsSystemUser(user.ID))
-                throw new SecurityException();
-
-            PermissionContext.DemandPermissions(new UserSecurityProvider(user.ID), Constants.Action_EditUser);
-
-            var curLng = user.CultureName;
-
-            if (SetupInfo.EnabledCultures.Find(c => string.Equals(c.Name, memberModel.CultureName, StringComparison.InvariantCultureIgnoreCase)) != null)
-            {
-                if (curLng != memberModel.CultureName)
-                {
-                    user.CultureName = memberModel.CultureName;
-
-                    try
-                    {
-                        UserManager.SaveUserInfo(user);
-                    }
-                    catch
-                    {
-                        user.CultureName = curLng;
-                        throw;
-                    }
-
-                    MessageService.Send(MessageAction.UserUpdatedLanguage, MessageTarget.Create(user.ID), user.DisplayUserName(false, DisplayUserSettingsHelper));
-
-                }
-            }
-
-            return EmployeeWraperFullHelper.GetFull(user);
-        }
-
-        [Update("{userid}")]
-        public EmployeeFullDto UpdateMemberFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
-        {
-            return UpdateMember(userid, memberModel);
-        }
-
-        [Update("{userid}")]
-        [Consumes("application/x-www-form-urlencoded")]
-        public EmployeeFullDto UpdateMemberFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
-        {
-            return UpdateMember(userid, memberModel);
-        }
-
-        private EmployeeFullDto UpdateMember(string userid, UpdateMemberRequestDto memberModel)
-        {
-            var user = GetUserInfo(userid);
-
-            if (UserManager.IsSystemUser(user.ID))
-                throw new SecurityException();
-
-            PermissionContext.DemandPermissions(new UserSecurityProvider(user.ID), Constants.Action_EditUser);
-
-            var self = SecurityContext.CurrentAccount.ID.Equals(user.ID);
-            var resetDate = new DateTime(1900, 01, 01);
-
-            //Update it
-
-            var isLdap = user.IsLDAP();
-            var isSso = user.IsSSO();
-            var isAdmin = WebItemSecurity.IsProductAdministrator(WebItemManager.PeopleProductID, SecurityContext.CurrentAccount.ID);
-
-            if (!isLdap && !isSso)
-            {
-                //Set common fields
-
-                user.FirstName = memberModel.Firstname ?? user.FirstName;
-                user.LastName = memberModel.Lastname ?? user.LastName;
-                user.Location = memberModel.Location ?? user.Location;
-
-                if (isAdmin)
-                {
-                    user.Title = memberModel.Title ?? user.Title;
-                }
-            }
-
-            if (!UserFormatter.IsValidUserName(user.FirstName, user.LastName))
-                throw new Exception(Resource.ErrorIncorrectUserName);
-
-            user.Notes = memberModel.Comment ?? user.Notes;
-            user.Sex = ("male".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase)
-                            ? true
-                            : ("female".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase) ? (bool?)false : null)) ?? user.Sex;
-
-            user.BirthDate = memberModel.Birthday != null ? TenantUtil.DateTimeFromUtc(memberModel.Birthday) : user.BirthDate;
-
-            if (user.BirthDate == resetDate)
-            {
-                user.BirthDate = null;
-            }
-
-            user.WorkFromDate = memberModel.Worksfrom != null ? TenantUtil.DateTimeFromUtc(memberModel.Worksfrom) : user.WorkFromDate;
-
-            if (user.WorkFromDate == resetDate)
-            {
-                user.WorkFromDate = null;
-            }
-
-            //Update contacts
-            UpdateContacts(memberModel.Contacts, user);
-            UpdateDepartments(memberModel.Department, user);
-
-            if (memberModel.Files != UserPhotoManager.GetPhotoAbsoluteWebPath(user.ID))
-            {
-                UpdatePhotoUrl(memberModel.Files, user);
-            }
-            if (memberModel.Disable.HasValue)
-            {
-                user.Status = memberModel.Disable.Value ? EmployeeStatus.Terminated : EmployeeStatus.Active;
-                user.TerminatedDate = memberModel.Disable.Value ? DateTime.UtcNow : null;
-            }
-
-            if (self && !isAdmin)
-            {
-                StudioNotifyService.SendMsgToAdminAboutProfileUpdated();
-            }
-
-            // change user type
-            var canBeGuestFlag = !user.IsOwner(Tenant) && !user.IsAdmin(UserManager) && user.GetListAdminModules(WebItemSecurity).Count == 0 && !user.IsMe(AuthContext);
-
-            if (memberModel.IsVisitor && !user.IsVisitor(UserManager) && canBeGuestFlag)
-            {
-                UserManager.AddUserIntoGroup(user.ID, Constants.GroupVisitor.ID);
-                WebItemSecurityCache.ClearCache(Tenant.TenantId);
-            }
-
-            if (!self && !memberModel.IsVisitor && user.IsVisitor(UserManager))
-            {
-                var usersQuota = TenantExtra.GetTenantQuota().ActiveUsers;
-                if (TenantStatisticsProvider.GetUsersCount() < usersQuota)
-                {
-                    UserManager.RemoveUserFromGroup(user.ID, Constants.GroupVisitor.ID);
-                    WebItemSecurityCache.ClearCache(Tenant.TenantId);
-                }
-                else
-                {
-                    throw new TenantQuotaException(string.Format("Exceeds the maximum active users ({0})", usersQuota));
-                }
-            }
-
-            UserManager.SaveUserInfo(user);
-            MessageService.Send(MessageAction.UserUpdated, MessageTarget.Create(user.ID), user.DisplayUserName(false, DisplayUserSettingsHelper));
-
-            if (memberModel.Disable.HasValue && memberModel.Disable.Value)
-            {
-                CookiesManager.ResetUserCookie(user.ID);
-                MessageService.Send(MessageAction.CookieSettingsUpdated);
-            }
-
-            return EmployeeWraperFullHelper.GetFull(user);
-        }
-
-        [Delete("{userid}")]
-        public EmployeeFullDto DeleteMember(string userid)
-        {
-            PermissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
-
-            var user = GetUserInfo(userid);
-
-            if (UserManager.IsSystemUser(user.ID) || user.IsLDAP())
-                throw new SecurityException();
-
-            if (user.Status != EmployeeStatus.Terminated)
-                throw new Exception("The user is not suspended");
-
-            CheckReassignProccess(new[] { user.ID });
-
-            var userName = user.DisplayUserName(false, DisplayUserSettingsHelper);
-
-            UserPhotoManager.RemovePhoto(user.ID);
-            UserManager.DeleteUser(user.ID);
-            QueueWorkerRemove.Start(Tenant.TenantId, user, SecurityContext.CurrentAccount.ID, false);
-
-            MessageService.Send(MessageAction.UserDeleted, MessageTarget.Create(user.ID), userName);
-
-            return EmployeeWraperFullHelper.GetFull(user);
-        }
-
-        [Delete("@self")]
-        [Authorize(AuthenticationSchemes = "confirm", Roles = "ProfileRemove")]
-        public EmployeeFullDto DeleteProfile()
-        {
-            ApiContext.AuthByClaim();
-
-            if (UserManager.IsSystemUser(SecurityContext.CurrentAccount.ID))
-                throw new SecurityException();
-
-            var user = GetUserInfo(SecurityContext.CurrentAccount.ID.ToString());
-
-            if (!UserManager.UserExists(user))
-                throw new Exception(Resource.ErrorUserNotFound);
-
-            if (user.IsLDAP())
-                throw new SecurityException();
-
-            SecurityContext.AuthenticateMeWithoutCookie(ASC.Core.Configuration.Constants.CoreSystem);
-
-            user.Status = EmployeeStatus.Terminated;
-
-            UserManager.SaveUserInfo(user);
-
-            var userName = user.DisplayUserName(false, DisplayUserSettingsHelper);
-            MessageService.Send(MessageAction.UsersUpdatedStatus, MessageTarget.Create(user.ID), userName);
-
-            CookiesManager.ResetUserCookie(user.ID);
-            MessageService.Send(MessageAction.CookieSettingsUpdated);
-
-            if (CoreBaseSettings.Personal)
-            {
-                UserPhotoManager.RemovePhoto(user.ID);
-                UserManager.DeleteUser(user.ID);
-                MessageService.Send(MessageAction.UserDeleted, MessageTarget.Create(user.ID), userName);
-            }
-            else
-            {
-                //StudioNotifyService.Instance.SendMsgProfileHasDeletedItself(user);
-                //StudioNotifyService.SendMsgProfileDeletion(Tenant.TenantId, user);
-            }
-
-            return EmployeeWraperFullHelper.GetFull(user);
-        }
-
-        [Update("{userid}/contacts")]
-        public EmployeeFullDto UpdateMemberContactsFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
-        {
-            return UpdateMemberContacts(userid, memberModel);
-        }
-
-        [Update("{userid}/contacts")]
-        [Consumes("application/x-www-form-urlencoded")]
-        public EmployeeFullDto UpdateMemberContactsFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
-        {
-            return UpdateMemberContacts(userid, memberModel);
-        }
-
-        private EmployeeFullDto UpdateMemberContacts(string userid, UpdateMemberRequestDto memberModel)
-        {
-            var user = GetUserInfo(userid);
-
-            if (UserManager.IsSystemUser(user.ID))
-                throw new SecurityException();
-
-            UpdateContacts(memberModel.Contacts, user);
-            UserManager.SaveUserInfo(user);
-            return EmployeeWraperFullHelper.GetFull(user);
-        }
-
-        [Create("{userid}/contacts")]
-        public EmployeeFullDto SetMemberContactsFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
-        {
-            return SetMemberContacts(userid, memberModel);
-        }
-
-        [Create("{userid}/contacts")]
-        [Consumes("application/x-www-form-urlencoded")]
-        public EmployeeFullDto SetMemberContactsFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
-        {
-            return SetMemberContacts(userid, memberModel);
-        }
-
-        private EmployeeFullDto SetMemberContacts(string userid, UpdateMemberRequestDto memberModel)
-        {
-            var user = GetUserInfo(userid);
-
-            if (UserManager.IsSystemUser(user.ID))
-                throw new SecurityException();
-
-            user.ContactsList.Clear();
-            UpdateContacts(memberModel.Contacts, user);
-            UserManager.SaveUserInfo(user);
-            return EmployeeWraperFullHelper.GetFull(user);
-        }
-
-        [Delete("{userid}/contacts")]
-        public EmployeeFullDto DeleteMemberContactsFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
-        {
-            return DeleteMemberContacts(userid, memberModel);
-        }
-
-        [Delete("{userid}/contacts")]
-        [Consumes("application/x-www-form-urlencoded")]
-        public EmployeeFullDto DeleteMemberContactsFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
-        {
-            return DeleteMemberContacts(userid, memberModel);
-        }
-
-        private EmployeeFullDto DeleteMemberContacts(string userid, UpdateMemberRequestDto memberModel)
-        {
-            var user = GetUserInfo(userid);
-
-            if (UserManager.IsSystemUser(user.ID))
-                throw new SecurityException();
-
-            DeleteContacts(memberModel.Contacts, user);
-            UserManager.SaveUserInfo(user);
-            return EmployeeWraperFullHelper.GetFull(user);
-        }
-
-        [Read("{userid}/photo")]
-        public ThumbnailsDataDto GetMemberPhoto(string userid)
-        {
-            var user = GetUserInfo(userid);
-
-            if (UserManager.IsSystemUser(user.ID))
-                throw new SecurityException();
-
-            return new ThumbnailsDataDto(user.ID, UserPhotoManager);
-        }
-
-        [Create("{userid}/photo")]
-        public FileUploadResultDto UploadMemberPhoto(string userid, IFormCollection model)
-        {
-            var result = new FileUploadResultDto();
-            var autosave = bool.Parse(model["Autosave"]);
-
-            try
-            {
-                if (model.Files.Count != 0)
-                {
-                    Guid userId;
-                    try
-                    {
-                        userId = new Guid(userid);
-                    }
-                    catch
-                    {
-                        userId = SecurityContext.CurrentAccount.ID;
-                    }
-
-                    PermissionContext.DemandPermissions(new UserSecurityProvider(userId), Constants.Action_EditUser);
-
-                    var userPhoto = model.Files[0];
-
-                    if (userPhoto.Length > SetupInfo.MaxImageUploadSize)
-                    {
-                        result.Success = false;
-                        result.Message = FileSizeComment.FileImageSizeExceptionString;
-                        return result;
-                    }
-
-                    var data = new byte[userPhoto.Length];
-                    using var inputStream = userPhoto.OpenReadStream();
-
-                    var br = new BinaryReader(inputStream);
-                    br.Read(data, 0, (int)userPhoto.Length);
-                    br.Close();
-
-                    CheckImgFormat(data);
-
-                    if (autosave)
-                    {
-                        if (data.Length > SetupInfo.MaxImageUploadSize)
-                            throw new ImageSizeLimitException();
-
-                        var mainPhoto = UserPhotoManager.SaveOrUpdatePhoto(userId, data);
-
-                        result.Data =
-                            new
-                            {
-                                main = mainPhoto,
-                                retina = UserPhotoManager.GetRetinaPhotoURL(userId),
-                                max = UserPhotoManager.GetMaxPhotoURL(userId),
-                                big = UserPhotoManager.GetBigPhotoURL(userId),
-                                medium = UserPhotoManager.GetMediumPhotoURL(userId),
-                                small = UserPhotoManager.GetSmallPhotoURL(userId),
-                            };
-                    }
-                    else
-                    {
-                        result.Data = UserPhotoManager.SaveTempPhoto(data, SetupInfo.MaxImageUploadSize, UserPhotoManager.OriginalFotoSize.Width, UserPhotoManager.OriginalFotoSize.Height);
-                    }
-
-                    result.Success = true;
-                }
-                else
-                {
-                    result.Success = false;
-                    result.Message = PeopleResource.ErrorEmptyUploadFileSelected;
-                }
-
-            }
-            catch (Web.Core.Users.UnknownImageFormatException)
-            {
-                result.Success = false;
-                result.Message = PeopleResource.ErrorUnknownFileImageType;
-            }
-            catch (ImageWeightLimitException)
-            {
-                result.Success = false;
-                result.Message = PeopleResource.ErrorImageWeightLimit;
-            }
-            catch (ImageSizeLimitException)
-            {
-                result.Success = false;
-                result.Message = PeopleResource.ErrorImageSizetLimit;
-            }
-            catch (Exception ex)
-            {
-                result.Success = false;
-                result.Message = ex.Message.HtmlEncode();
-            }
-
-            return result;
-        }
-
-        [Update("{userid}/photo")]
-        public ThumbnailsDataDto UpdateMemberPhotoFromBody(string userid, [FromBody] UpdateMemberRequestDto model)
-        {
-            return UpdateMemberPhoto(userid, model);
-        }
-
-        [Update("{userid}/photo")]
-        [Consumes("application/x-www-form-urlencoded")]
-        public ThumbnailsDataDto UpdateMemberPhotoFromForm(string userid, [FromForm] UpdateMemberRequestDto model)
-        {
-            return UpdateMemberPhoto(userid, model);
-        }
-
-        private ThumbnailsDataDto UpdateMemberPhoto(string userid, UpdateMemberRequestDto model)
-        {
-            var user = GetUserInfo(userid);
-
-            if (UserManager.IsSystemUser(user.ID))
-                throw new SecurityException();
-
-            if (model.Files != UserPhotoManager.GetPhotoAbsoluteWebPath(user.ID))
-            {
-                UpdatePhotoUrl(model.Files, user);
-            }
-
-            UserManager.SaveUserInfo(user);
-            MessageService.Send(MessageAction.UserAddedAvatar, MessageTarget.Create(user.ID), user.DisplayUserName(false, DisplayUserSettingsHelper));
-
-            return new ThumbnailsDataDto(user.ID, UserPhotoManager);
-        }
-
-        [Delete("{userid}/photo")]
-        public ThumbnailsDataDto DeleteMemberPhoto(string userid)
-        {
-            var user = GetUserInfo(userid);
-
-            if (UserManager.IsSystemUser(user.ID))
-                throw new SecurityException();
-
-            PermissionContext.DemandPermissions(new UserSecurityProvider(user.ID), Constants.Action_EditUser);
-
-            UserPhotoManager.RemovePhoto(user.ID);
-
-            UserManager.SaveUserInfo(user);
-            MessageService.Send(MessageAction.UserDeletedAvatar, MessageTarget.Create(user.ID), user.DisplayUserName(false, DisplayUserSettingsHelper));
-
-            return new ThumbnailsDataDto(user.ID, UserPhotoManager);
-        }
-
-
-        [Create("{userid}/photo/thumbnails")]
-        public ThumbnailsDataDto CreateMemberPhotoThumbnailsFromBody(string userid, [FromBody] ThumbnailsRequestDto thumbnailsModel)
-        {
-            return CreateMemberPhotoThumbnails(userid, thumbnailsModel);
-        }
-
-        [Create("{userid}/photo/thumbnails")]
-        [Consumes("application/x-www-form-urlencoded")]
-        public ThumbnailsDataDto CreateMemberPhotoThumbnailsFromForm(string userid, [FromForm] ThumbnailsRequestDto thumbnailsModel)
-        {
-            return CreateMemberPhotoThumbnails(userid, thumbnailsModel);
-        }
-
-        private ThumbnailsDataDto CreateMemberPhotoThumbnails(string userid, ThumbnailsRequestDto thumbnailsModel)
-        {
-            var user = GetUserInfo(userid);
-
-            if (UserManager.IsSystemUser(user.ID))
-                throw new SecurityException();
-
-            PermissionContext.DemandPermissions(new UserSecurityProvider(user.ID), Constants.Action_EditUser);
-
-            if (!string.IsNullOrEmpty(thumbnailsModel.TmpFile))
-            {
-                var fileName = Path.GetFileName(thumbnailsModel.TmpFile);
-                var data = UserPhotoManager.GetTempPhotoData(fileName);
-
-                var settings = new UserPhotoThumbnailSettings(thumbnailsModel.X, thumbnailsModel.Y, thumbnailsModel.Width, thumbnailsModel.Height);
-                SettingsManager.SaveForUser(settings, user.ID);
-
-                UserPhotoManager.RemovePhoto(user.ID);
-                UserPhotoManager.SaveOrUpdatePhoto(user.ID, data);
-                UserPhotoManager.RemoveTempPhoto(fileName);
-            }
-            else
-            {
-                UserPhotoThumbnailManager.SaveThumbnails(UserPhotoManager, SettingsManager, thumbnailsModel.X, thumbnailsModel.Y, thumbnailsModel.Width, thumbnailsModel.Height, user.ID);
-            }
-
-            UserManager.SaveUserInfo(user);
-            MessageService.Send(MessageAction.UserUpdatedAvatarThumbnails, MessageTarget.Create(user.ID), user.DisplayUserName(false, DisplayUserSettingsHelper));
-
-            return new ThumbnailsDataDto(user.ID, UserPhotoManager);
-        }
-
-
-        [AllowAnonymous]
-        [Create("password", false)]
-        public object SendUserPasswordFromBody([FromBody] MemberRequestDto memberModel)
-        {
-            return SendUserPassword(memberModel);
-        }
-
-        [AllowAnonymous]
-        [Create("password", false)]
-        [Consumes("application/x-www-form-urlencoded")]
-        public object SendUserPasswordFromForm([FromForm] MemberRequestDto memberModel)
-        {
-            return SendUserPassword(memberModel);
-        }
-
-        private object SendUserPassword(MemberRequestDto memberModel)
-        {
-            string error = UserManagerWrapper.SendUserPassword(memberModel.Email);
-            if (!string.IsNullOrEmpty(error))
-            {
-                Log.ErrorFormat("Password recovery ({0}): {1}", memberModel.Email, error);
-            }
-
-            return string.Format(Resource.MessageYourPasswordSendedToEmail, memberModel.Email);
-        }
-
-        [Update("{userid}/password")]
-        [Authorize(AuthenticationSchemes = "confirm", Roles = "PasswordChange,EmailChange,Activation,EmailActivation,Everyone")]
-        public EmployeeFullDto ChangeUserPasswordFromBody(Guid userid, [FromBody] MemberRequestDto memberModel)
-        {
-            return ChangeUserPassword(userid, memberModel);
-        }
-
-        [Update("{userid}/password")]
-        [Authorize(AuthenticationSchemes = "confirm", Roles = "PasswordChange,EmailChange,Activation,EmailActivation,Everyone")]
-        [Consumes("application/x-www-form-urlencoded")]
-        public EmployeeFullDto ChangeUserPasswordFromForm(Guid userid, [FromForm] MemberRequestDto memberModel)
-        {
-            return ChangeUserPassword(userid, memberModel);
-        }
-
-        private EmployeeFullDto ChangeUserPassword(Guid userid, MemberRequestDto memberModel)
-        {
-            ApiContext.AuthByClaim();
-            PermissionContext.DemandPermissions(new UserSecurityProvider(userid), Constants.Action_EditUser);
-
-            var user = UserManager.GetUsers(userid);
-
-            if (!UserManager.UserExists(user)) return null;
-
-            if (UserManager.IsSystemUser(user.ID))
-                throw new SecurityException();
-
-            if (!string.IsNullOrEmpty(memberModel.Email))
-            {
-                var address = new MailAddress(memberModel.Email);
-                if (!string.Equals(address.Address, user.Email, StringComparison.OrdinalIgnoreCase))
-                {
-                    user.Email = address.Address.ToLowerInvariant();
-                    user.ActivationStatus = EmployeeActivationStatus.Activated;
-                    UserManager.SaveUserInfo(user);
-                }
-            }
-
-            memberModel.PasswordHash = (memberModel.PasswordHash ?? "").Trim();
-            if (string.IsNullOrEmpty(memberModel.PasswordHash))
-            {
-                memberModel.Password = (memberModel.Password ?? "").Trim();
-
-                if (!string.IsNullOrEmpty(memberModel.Password))
-                {
-                    memberModel.PasswordHash = PasswordHasher.GetClientPassword(memberModel.Password);
-                }
-            }
-
-            if (!string.IsNullOrEmpty(memberModel.PasswordHash))
-            {
-                SecurityContext.SetUserPasswordHash(userid, memberModel.PasswordHash);
-                MessageService.Send(MessageAction.UserUpdatedPassword);
-
-                CookiesManager.ResetUserCookie(userid);
-                MessageService.Send(MessageAction.CookieSettingsUpdated);
-            }
-
-            return EmployeeWraperFullHelper.GetFull(GetUserInfo(userid.ToString()));
-        }
-
-
-        [Create("email", false)]
-        public object SendEmailChangeInstructionsFromBody([FromBody] UpdateMemberRequestDto model)
-        {
-            return SendEmailChangeInstructions(model);
-        }
-
-        [Create("email", false)]
-        [Consumes("application/x-www-form-urlencoded")]
-        public object SendEmailChangeInstructionsFromForm([FromForm] UpdateMemberRequestDto model)
-        {
-            return SendEmailChangeInstructions(model);
-        }
-
-        private object SendEmailChangeInstructions(UpdateMemberRequestDto model)
-        {
-            Guid.TryParse(model.UserId, out var userid);
-
-            if (userid == Guid.Empty) throw new ArgumentNullException("userid");
-
-            var email = (model.Email ?? "").Trim();
-
-            if (string.IsNullOrEmpty(email)) throw new Exception(Resource.ErrorEmailEmpty);
-
-            if (!email.TestEmailRegex()) throw new Exception(Resource.ErrorNotCorrectEmail);
-
-            var viewer = UserManager.GetUsers(SecurityContext.CurrentAccount.ID);
-            var user = UserManager.GetUsers(userid);
-
-            if (user == null)
-                throw new Exception(Resource.ErrorUserNotFound);
-
-            if (viewer == null || (user.IsOwner(Tenant) && viewer.ID != user.ID))
-                throw new Exception(Resource.ErrorAccessDenied);
-
-            var existentUser = UserManager.GetUserByEmail(email);
-
-            if (existentUser.ID != Constants.LostUser.ID)
-                throw new Exception(CustomNamingPeople.Substitute<Resource>("ErrorEmailAlreadyExists"));
-
-            if (!viewer.IsAdmin(UserManager))
-            {
-                StudioNotifyService.SendEmailChangeInstructions(user, email);
-            }
-            else
-            {
-                if (email == user.Email)
-                    throw new Exception(Resource.ErrorEmailsAreTheSame);
-
-                user.Email = email;
-                user.ActivationStatus = EmployeeActivationStatus.NotActivated;
-                UserManager.SaveUserInfo(user);
-                StudioNotifyService.SendEmailActivationInstructions(user, email);
-            }
-
-            MessageService.Send(MessageAction.UserSentEmailChangeInstructions, user.DisplayUserName(false, DisplayUserSettingsHelper));
-
-            return string.Format(Resource.MessageEmailChangeInstuctionsSentOnEmail, email);
-        }
-
-        private UserInfo GetUserInfo(string userNameOrId)
-        {
-            UserInfo user;
-            try
-            {
-                var userId = new Guid(userNameOrId);
-                user = UserManager.GetUsers(userId);
-            }
-            catch (FormatException)
-            {
-                user = UserManager.GetUserByUserName(userNameOrId);
-            }
-            if (user == null || user.ID == Constants.LostUser.ID)
-                throw new ItemNotFoundException("user not found");
-            return user;
-        }
-
-        [Update("activationstatus/{activationstatus}")]
-        [Authorize(AuthenticationSchemes = "confirm", Roles = "Activation,Everyone")]
-        public IEnumerable<EmployeeFullDto> UpdateEmployeeActivationStatusFromBody(EmployeeActivationStatus activationstatus, [FromBody] UpdateMembersRequestDto model)
-        {
-            return UpdateEmployeeActivationStatus(activationstatus, model);
-        }
-
-        [Update("activationstatus/{activationstatus}")]
-        [Authorize(AuthenticationSchemes = "confirm", Roles = "Activation,Everyone")]
-        [Consumes("application/x-www-form-urlencoded")]
-        public IEnumerable<EmployeeFullDto> UpdateEmployeeActivationStatusFromForm(EmployeeActivationStatus activationstatus, [FromForm] UpdateMembersRequestDto model)
-        {
-            return UpdateEmployeeActivationStatus(activationstatus, model);
-        }
-
-        private IEnumerable<EmployeeFullDto> UpdateEmployeeActivationStatus(EmployeeActivationStatus activationstatus, UpdateMembersRequestDto model)
-        {
-            ApiContext.AuthByClaim();
-
-            var retuls = new List<EmployeeFullDto>();
-            foreach (var id in model.UserIds.Where(userId => !UserManager.IsSystemUser(userId)))
-            {
-                PermissionContext.DemandPermissions(new UserSecurityProvider(id), Constants.Action_EditUser);
-                var u = UserManager.GetUsers(id);
-                if (u.ID == Constants.LostUser.ID || u.IsLDAP()) continue;
-
-                u.ActivationStatus = activationstatus;
-                UserManager.SaveUserInfo(u);
-                retuls.Add(EmployeeWraperFullHelper.GetFull(u));
-            }
-
-            return retuls;
-        }
-
-        [Update("type/{type}")]
-        public IEnumerable<EmployeeFullDto> UpdateUserTypeFromBody(EmployeeType type, [FromBody] UpdateMembersRequestDto model)
-        {
-            return UpdateUserType(type, model);
-        }
-
-        [Update("type/{type}")]
-        [Consumes("application/x-www-form-urlencoded")]
-        public IEnumerable<EmployeeFullDto> UpdateUserTypeFromForm(EmployeeType type, [FromForm] UpdateMembersRequestDto model)
-        {
-            return UpdateUserType(type, model);
-        }
-
-        private IEnumerable<EmployeeFullDto> UpdateUserType(EmployeeType type, UpdateMembersRequestDto model)
-        {
-            var users = model.UserIds
-                .Where(userId => !UserManager.IsSystemUser(userId))
-                .Select(userId => UserManager.GetUsers(userId))
-                .ToList();
-
-            foreach (var user in users)
-            {
-                if (user.IsOwner(Tenant) || user.IsAdmin(UserManager) || user.IsMe(AuthContext) || user.GetListAdminModules(WebItemSecurity).Count > 0)
-                    continue;
-
-                switch (type)
-                {
-                    case EmployeeType.User:
-                        if (user.IsVisitor(UserManager))
-                        {
-                            if (TenantStatisticsProvider.GetUsersCount() < TenantExtra.GetTenantQuota().ActiveUsers)
-                            {
-                                UserManager.RemoveUserFromGroup(user.ID, Constants.GroupVisitor.ID);
-                                WebItemSecurityCache.ClearCache(Tenant.TenantId);
-                            }
-                        }
-                        break;
-                    case EmployeeType.Visitor:
-                        if (CoreBaseSettings.Standalone || TenantStatisticsProvider.GetVisitorsCount() < TenantExtra.GetTenantQuota().ActiveUsers * Constants.CoefficientOfVisitors)
-                        {
-                            UserManager.AddUserIntoGroup(user.ID, Constants.GroupVisitor.ID);
-                            WebItemSecurityCache.ClearCache(Tenant.TenantId);
-                        }
-                        break;
-                }
-            }
-
-            MessageService.Send(MessageAction.UsersUpdatedType, MessageTarget.Create(users.Select(x => x.ID)), users.Select(x => x.DisplayUserName(false, DisplayUserSettingsHelper)));
-
-            return users.Select(EmployeeWraperFullHelper.GetFull);
-        }
-
-        [Update("status/{status}")]
-        public IEnumerable<EmployeeFullDto> UpdateUserStatusFromBody(EmployeeStatus status, [FromBody] UpdateMembersRequestDto model)
-        {
-            return UpdateUserStatus(status, model);
-        }
-
-        [Update("status/{status}")]
-        [Consumes("application/x-www-form-urlencoded")]
-        public IEnumerable<EmployeeFullDto> UpdateUserStatusFromForm(EmployeeStatus status, [FromForm] UpdateMembersRequestDto model)
-        {
-            return UpdateUserStatus(status, model);
-        }
-
-        private IEnumerable<EmployeeFullDto> UpdateUserStatus(EmployeeStatus status, UpdateMembersRequestDto model)
-        {
-            PermissionContext.DemandPermissions(Constants.Action_EditUser);
-
-            var users = model.UserIds.Select(userId => UserManager.GetUsers(userId))
-                .Where(u => !UserManager.IsSystemUser(u.ID) && !u.IsLDAP())
-                .ToList();
-
-            foreach (var user in users)
-            {
-                if (user.IsOwner(Tenant) || user.IsMe(AuthContext))
-                    continue;
-
-                switch (status)
-                {
-                    case EmployeeStatus.Active:
-                        if (user.Status == EmployeeStatus.Terminated)
-                        {
-                            if (TenantStatisticsProvider.GetUsersCount() < TenantExtra.GetTenantQuota().ActiveUsers || user.IsVisitor(UserManager))
-                            {
-                                user.Status = EmployeeStatus.Active;
-                                UserManager.SaveUserInfo(user);
-                            }
-                        }
-                        break;
-                    case EmployeeStatus.Terminated:
-                        user.Status = EmployeeStatus.Terminated;
-                        UserManager.SaveUserInfo(user);
-
-                        CookiesManager.ResetUserCookie(user.ID);
-                        MessageService.Send(MessageAction.CookieSettingsUpdated);
-                        break;
-                }
-            }
-
-            MessageService.Send(MessageAction.UsersUpdatedStatus, MessageTarget.Create(users.Select(x => x.ID)), users.Select(x => x.DisplayUserName(false, DisplayUserSettingsHelper)));
-
-            return users.Select(EmployeeWraperFullHelper.GetFull);
-        }
-
-
-        [Update("invite")]
-        public IEnumerable<EmployeeFullDto> ResendUserInvitesFromBody([FromBody] UpdateMembersRequestDto model)
-        {
-            return ResendUserInvites(model);
-        }
-
-        [Update("invite")]
-        [Consumes("application/x-www-form-urlencoded")]
-        public IEnumerable<EmployeeFullDto> ResendUserInvitesFromForm([FromForm] UpdateMembersRequestDto model)
-        {
-            return ResendUserInvites(model);
-        }
-
-        private IEnumerable<EmployeeFullDto> ResendUserInvites(UpdateMembersRequestDto model)
-        {
-            var users = model.UserIds
-                .Where(userId => !UserManager.IsSystemUser(userId))
-                .Select(userId => UserManager.GetUsers(userId))
-                .ToList();
-
-            foreach (var user in users)
-            {
-                if (user.IsActive) continue;
-                var viewer = UserManager.GetUsers(SecurityContext.CurrentAccount.ID);
-
-                if (viewer == null) throw new Exception(Resource.ErrorAccessDenied);
-
-                if (viewer.IsAdmin(UserManager) || viewer.ID == user.ID)
-                {
-                    if (user.ActivationStatus == EmployeeActivationStatus.Activated)
-                    {
-                        user.ActivationStatus = EmployeeActivationStatus.NotActivated;
-                    }
-                    if (user.ActivationStatus == (EmployeeActivationStatus.AutoGenerated | EmployeeActivationStatus.Activated))
-                    {
-                        user.ActivationStatus = EmployeeActivationStatus.AutoGenerated;
-                    }
-                    UserManager.SaveUserInfo(user);
-                }
-
-                if (user.ActivationStatus == EmployeeActivationStatus.Pending)
-                {
-                    if (user.IsVisitor(UserManager))
-                    {
-                        StudioNotifyService.GuestInfoActivation(user);
-                    }
-                    else
-                    {
-                        StudioNotifyService.UserInfoActivation(user);
-                    }
-                }
-                else
-                {
-                    StudioNotifyService.SendEmailActivationInstructions(user, user.Email);
-                }
-            }
-
-            MessageService.Send(MessageAction.UsersSentActivationInstructions, MessageTarget.Create(users.Select(x => x.ID)), users.Select(x => x.DisplayUserName(false, DisplayUserSettingsHelper)));
-
-            return users.Select(EmployeeWraperFullHelper.GetFull);
-        }
-
-        [Update("delete", Order = -1)]
-        public IEnumerable<EmployeeFullDto> RemoveUsersFromBody([FromBody] UpdateMembersRequestDto model)
-        {
-            return RemoveUsers(model);
-        }
-
-        [Update("delete", Order = -1)]
-        [Consumes("application/x-www-form-urlencoded")]
-        public IEnumerable<EmployeeFullDto> RemoveUsersFromForm([FromForm] UpdateMembersRequestDto model)
-        {
-            return RemoveUsers(model);
-        }
-
-        private IEnumerable<EmployeeFullDto> RemoveUsers(UpdateMembersRequestDto model)
-        {
-            PermissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
-
-            CheckReassignProccess(model.UserIds);
-
-            var users = model.UserIds.Select(userId => UserManager.GetUsers(userId))
-                .Where(u => !UserManager.IsSystemUser(u.ID) && !u.IsLDAP())
-                .ToList();
-
-            var userNames = users.Select(x => x.DisplayUserName(false, DisplayUserSettingsHelper)).ToList();
-
-            foreach (var user in users)
-            {
-                if (user.Status != EmployeeStatus.Terminated) continue;
-
-                UserPhotoManager.RemovePhoto(user.ID);
-                UserManager.DeleteUser(user.ID);
-                QueueWorkerRemove.Start(Tenant.TenantId, user, SecurityContext.CurrentAccount.ID, false);
-            }
-
-            MessageService.Send(MessageAction.UsersDeleted, MessageTarget.Create(users.Select(x => x.ID)), userNames);
-
-            return users.Select(EmployeeWraperFullHelper.GetFull);
-        }
-
-
-        [Update("self/delete")]
-        public object SendInstructionsToDelete()
-        {
-            var user = UserManager.GetUsers(SecurityContext.CurrentAccount.ID);
-
-            if (user.IsLDAP())
-                throw new SecurityException();
-
-            StudioNotifyService.SendMsgProfileDeletion(user);
-            MessageService.Send(MessageAction.UserSentDeleteInstructions);
-
-            return string.Format(Resource.SuccessfullySentNotificationDeleteUserInfoMessage, "<b>" + user.Email + "</b>");
-        }
-
-        [AllowAnonymous]
-        [Read("thirdparty/providers")]
-        public ICollection<AccountInfoDto> GetAuthProviders(bool inviteView, bool settingsView, string clientCallback, string fromOnly)
-        {
-            ICollection<AccountInfoDto> infos = new List<AccountInfoDto>();
-            IEnumerable<LoginProfile> linkedAccounts = new List<LoginProfile>();
-
-            if (AuthContext.IsAuthenticated)
-            {
-                linkedAccounts = AccountLinker.Get("webstudio").GetLinkedProfiles(AuthContext.CurrentAccount.ID.ToString());
-            }
-
-            fromOnly = string.IsNullOrWhiteSpace(fromOnly) ? string.Empty : fromOnly.ToLower();
-
-            foreach (var provider in ProviderManager.AuthProviders.Where(provider => string.IsNullOrEmpty(fromOnly) || fromOnly == provider || (provider == "google" && fromOnly == "openid")))
-            {
-                if (inviteView && provider.Equals("twitter", StringComparison.OrdinalIgnoreCase)) continue;
-
-                var loginProvider = ProviderManager.GetLoginProvider(provider);
-                if (loginProvider != null && loginProvider.IsEnabled)
-                {
-
-                    var url = VirtualPathUtility.ToAbsolute("~/login.ashx") + $"?auth={provider}";
-                    var mode = settingsView || inviteView || (!MobileDetector.IsMobile() && !Request.DesktopApp())
-                            ? $"&mode=popup&callback={clientCallback}"
-                            : "&mode=Redirect&desktop=true";
-
-                    infos.Add(new AccountInfoDto
-                    {
-                        Linked = linkedAccounts.Any(x => x.Provider == provider),
-                        Provider = provider,
-                        Url = url + mode
-                    });
-                }
-            }
-
-            return infos;
-        }
-
-
-        [Update("thirdparty/linkaccount")]
-        public void LinkAccountFromBody([FromBody] LinkAccountRequestDto model)
-        {
-            LinkAccount(model);
-        }
-
-        [Update("thirdparty/linkaccount")]
-        [Consumes("application/x-www-form-urlencoded")]
-        public void LinkAccountFromForm([FromForm] LinkAccountRequestDto model)
-        {
-            LinkAccount(model);
-        }
-
-        public void LinkAccount(LinkAccountRequestDto model)
-        {
-            var profile = new LoginProfile(Signature, InstanceCrypto, model.SerializedProfile);
-
-            if (!(CoreBaseSettings.Standalone || TenantExtra.GetTenantQuota().Oauth))
-            {
-                throw new Exception("ErrorNotAllowedOption");
-            }
-
-            if (string.IsNullOrEmpty(profile.AuthorizationError))
-            {
-                GetLinker().AddLink(SecurityContext.CurrentAccount.ID.ToString(), profile);
-                MessageService.Send(MessageAction.UserLinkedSocialAccount, GetMeaningfulProviderName(profile.Provider));
-            }
-            else
-            {
-                // ignore cancellation
-                if (profile.AuthorizationError != "Canceled at provider")
-                {
-                    throw new Exception(profile.AuthorizationError);
-                }
-            }
-        }
-
-        [Delete("thirdparty/unlinkaccount")]
-        public void UnlinkAccount(string provider)
-        {
-            GetLinker().RemoveProvider(SecurityContext.CurrentAccount.ID.ToString(), provider);
-            MessageService.Send(MessageAction.UserUnlinkedSocialAccount, GetMeaningfulProviderName(provider));
-        }
-
-        [AllowAnonymous]
-        [Create("thirdparty/signup")]
-        public void SignupAccountFromBody([FromBody] SignupAccountRequestDto model)
-        {
-            SignupAccount(model);
-        }
-
-        [AllowAnonymous]
-        [Create("thirdparty/signup")]
-        [Consumes("application/x-www-form-urlencoded")]
-        public void SignupAccountFromForm([FromForm] SignupAccountRequestDto model)
-        {
-            SignupAccount(model);
-        }
-
-        public void SignupAccount(SignupAccountRequestDto model)
-        {
-            var employeeType = model.EmplType ?? EmployeeType.User;
-            var passwordHash = model.PasswordHash;
-            var mustChangePassword = false;
-
-            if (string.IsNullOrEmpty(passwordHash))
-            {
-                passwordHash = UserManagerWrapper.GeneratePassword();
-                mustChangePassword = true;
-            }
-
-            var thirdPartyProfile = new LoginProfile(Signature, InstanceCrypto, model.SerializedProfile);
-            if (!string.IsNullOrEmpty(thirdPartyProfile.AuthorizationError))
-            {
-                // ignore cancellation
-                if (thirdPartyProfile.AuthorizationError != "Canceled at provider")
-                    throw new Exception(thirdPartyProfile.AuthorizationError);
-
-                return;
-            }
-
-            if (string.IsNullOrEmpty(thirdPartyProfile.EMail))
-            {
-                throw new Exception(Resource.ErrorNotCorrectEmail);
-            }
-
-            var userID = Guid.Empty;
-            try
-            {
-                SecurityContext.AuthenticateMeWithoutCookie(ASC.Core.Configuration.Constants.CoreSystem);
-                var newUser = CreateNewUser(GetFirstName(model, thirdPartyProfile), GetLastName(model, thirdPartyProfile), GetEmailAddress(model, thirdPartyProfile), passwordHash, employeeType, false);
-
-                var messageAction = employeeType == EmployeeType.User ? MessageAction.UserCreatedViaInvite : MessageAction.GuestCreatedViaInvite;
-                MessageService.Send(MessageInitiator.System, messageAction, MessageTarget.Create(newUser.ID), newUser.DisplayUserName(false, DisplayUserSettingsHelper));
-
-                userID = newUser.ID;
-                if (!string.IsNullOrEmpty(thirdPartyProfile.Avatar))
-                {
-                    SaveContactImage(userID, thirdPartyProfile.Avatar);
-                }
-
-                GetLinker().AddLink(userID.ToString(), thirdPartyProfile);
-            }
-            finally
-            {
-                SecurityContext.Logout();
-            }
-
-            var user = UserManager.GetUsers(userID);
-            var cookiesKey = SecurityContext.AuthenticateMe(user.Email, passwordHash);
-            CookiesManager.SetCookies(CookiesType.AuthKey, cookiesKey);
-            MessageService.Send(MessageAction.LoginSuccess);
-            StudioNotifyService.UserHasJoin();
-
-            if (mustChangePassword)
-            {
-                StudioNotifyService.UserPasswordChange(user);
-            }
-
-            UserHelpTourHelper.IsNewUser = true;
-            if (CoreBaseSettings.Personal)
-                PersonalSettingsHelper.IsNewUser = true;
-
-        }
-
-        [Create("phone")]
-        public object SendNotificationToChangeFromBody([FromBody] UpdateMemberRequestDto model)
-        {
-            return SendNotificationToChange(model.UserId);
-        }
-
-        [Create("phone")]
-        [Consumes("application/x-www-form-urlencoded")]
-        public object SendNotificationToChangeFromForm([FromForm] UpdateMemberRequestDto model)
-        {
-            return SendNotificationToChange(model.UserId);
-        }
-
-        public object SendNotificationToChange(string userId)
-        {
-            var user = UserManager.GetUsers(
-                string.IsNullOrEmpty(userId)
-                    ? SecurityContext.CurrentAccount.ID
-                    : new Guid(userId));
-
-            var canChange =
-                user.IsMe(AuthContext)
-                || PermissionContext.CheckPermissions(new UserSecurityProvider(user.ID), Constants.Action_EditUser);
-
-            if (!canChange)
-                throw new SecurityAccessDeniedException(Resource.ErrorAccessDenied);
-
-            user.MobilePhoneActivationStatus = MobilePhoneActivationStatus.NotActivated;
-            UserManager.SaveUserInfo(user);
-
-            if (user.IsMe(AuthContext))
-            {
-                return CommonLinkUtility.GetConfirmationUrl(user.Email, ConfirmType.PhoneActivation);
-            }
-
-            StudioNotifyService.SendMsgMobilePhoneChange(user);
-            return string.Empty;
-        }
-
-        protected string GetEmailAddress(SignupAccountRequestDto model)
-        {
-            if (!string.IsNullOrEmpty(model.Email))
-                return model.Email.Trim();
-
-            return string.Empty;
-        }
-
-        private string GetEmailAddress(SignupAccountRequestDto model, LoginProfile account)
-        {
-            var value = GetEmailAddress(model);
-            return string.IsNullOrEmpty(value) ? account.EMail : value;
-        }
-
-        protected string GetFirstName(SignupAccountRequestDto model)
-        {
-            var value = string.Empty;
-            if (!string.IsNullOrEmpty(model.FirstName)) value = model.FirstName.Trim();
-            return HtmlUtil.GetText(value);
-        }
-
-        private string GetFirstName(SignupAccountRequestDto model, LoginProfile account)
-        {
-            var value = GetFirstName(model);
-            return string.IsNullOrEmpty(value) ? account.FirstName : value;
-        }
-
-        protected string GetLastName(SignupAccountRequestDto model)
-        {
-            var value = string.Empty;
-            if (!string.IsNullOrEmpty(model.LastName)) value = model.LastName.Trim();
-            return HtmlUtil.GetText(value);
-        }
-
-        private string GetLastName(SignupAccountRequestDto model, LoginProfile account)
-        {
-            var value = GetLastName(model);
-            return string.IsNullOrEmpty(value) ? account.LastName : value;
-        }
-
-        private UserInfo CreateNewUser(string firstName, string lastName, string email, string passwordHash, EmployeeType employeeType, bool fromInviteLink)
-        {
-            var isVisitor = employeeType == EmployeeType.Visitor;
-
-            if (SetupInfo.IsSecretEmail(email))
-            {
-                fromInviteLink = false;
-            }
-
-            var userInfo = new UserInfo
-            {
-                FirstName = string.IsNullOrEmpty(firstName) ? UserControlsCommonResource.UnknownFirstName : firstName,
-                LastName = string.IsNullOrEmpty(lastName) ? UserControlsCommonResource.UnknownLastName : lastName,
-                Email = email,
-            };
-
-            if (CoreBaseSettings.Personal)
-            {
-                userInfo.ActivationStatus = EmployeeActivationStatus.Activated;
-                userInfo.CultureName = CoreBaseSettings.CustomMode ? "ru-RU" : Thread.CurrentThread.CurrentUICulture.Name;
-            }
-
-            return UserManagerWrapper.AddUser(userInfo, passwordHash, true, true, isVisitor, fromInviteLink);
-        }
-
-        private void SaveContactImage(Guid userID, string url)
-        {
-            using (var memstream = new MemoryStream())
-            {
-                var request = new HttpRequestMessage();
-                request.RequestUri = new Uri(url);
-
-                var httpClient = ClientFactory.CreateClient();
-                using (var response = httpClient.Send(request))
-                using (var stream = response.Content.ReadAsStream())
-                {
-                    var buffer = new byte[512];
-                    int bytesRead;
-                    while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
-                        memstream.Write(buffer, 0, bytesRead);
-                    var bytes = memstream.ToArray();
-
-                    UserPhotoManager.SaveOrUpdatePhoto(userID, bytes);
-                }
-            }
-        }
-
-        private AccountLinker GetLinker()
-        {
-            return AccountLinker.Get("webstudio");
-        }
-
-        private static string GetMeaningfulProviderName(string providerName)
-        {
-            switch (providerName)
-            {
-                case "google":
-                case "openid":
-                    return "Google";
-                case "facebook":
-                    return "Facebook";
-                case "twitter":
-                    return "Twitter";
-                case "linkedin":
-                    return "LinkedIn";
-                default:
-                    return "Unknown Provider";
-            }
-        }
-
-
-        [Read(@"reassign/progress")]
-        public ReassignProgressItem GetReassignProgress(Guid userId)
-        {
-            PermissionContext.DemandPermissions(Constants.Action_EditUser);
-
-            return QueueWorkerReassign.GetProgressItemStatus(Tenant.TenantId, userId);
-        }
-
-        [Update(@"reassign/terminate")]
-        public void TerminateReassignFromBody([FromBody] TerminateRequestDto model)
-        {
-            PermissionContext.DemandPermissions(Constants.Action_EditUser);
-
-            QueueWorkerReassign.Terminate(Tenant.TenantId, model.UserId);
-        }
-
-        [Update(@"reassign/terminate")]
-        [Consumes("application/x-www-form-urlencoded")]
-        public void TerminateReassignFromForm([FromForm] TerminateRequestDto model)
-        {
-            PermissionContext.DemandPermissions(Constants.Action_EditUser);
-
-            QueueWorkerReassign.Terminate(Tenant.TenantId, model.UserId);
-        }
-
-        [Create(@"reassign/start")]
-        public ReassignProgressItem StartReassignFromBody([FromBody] StartReassignRequestDto model)
-        {
-            return StartReassign(model);
-        }
-
-        [Create(@"reassign/start")]
-        [Consumes("application/x-www-form-urlencoded")]
-        public ReassignProgressItem StartReassignFromForm([FromForm] StartReassignRequestDto model)
-        {
-            return StartReassign(model);
-        }
-
-        private ReassignProgressItem StartReassign(StartReassignRequestDto model)
-        {
-            PermissionContext.DemandPermissions(Constants.Action_EditUser);
-
-            var fromUser = UserManager.GetUsers(model.FromUserId);
-
-            if (fromUser == null || fromUser.ID == Constants.LostUser.ID)
-                throw new ArgumentException("User with id = " + model.FromUserId + " not found");
-
-            if (fromUser.IsOwner(Tenant) || fromUser.IsMe(AuthContext) || fromUser.Status != EmployeeStatus.Terminated)
-                throw new ArgumentException("Can not delete user with id = " + model.FromUserId);
-
-            var toUser = UserManager.GetUsers(model.ToUserId);
-
-            if (toUser == null || toUser.ID == Constants.LostUser.ID)
-                throw new ArgumentException("User with id = " + model.ToUserId + " not found");
-
-            if (toUser.IsVisitor(UserManager) || toUser.Status == EmployeeStatus.Terminated)
-                throw new ArgumentException("Can not reassign data to user with id = " + model.ToUserId);
-
-            return QueueWorkerReassign.Start(Tenant.TenantId, model.FromUserId, model.ToUserId, SecurityContext.CurrentAccount.ID, model.DeleteProfile);
-        }
-
-        private void CheckReassignProccess(IEnumerable<Guid> userIds)
-        {
-            foreach (var userId in userIds)
-            {
-                var reassignStatus = QueueWorkerReassign.GetProgressItemStatus(Tenant.TenantId, userId);
-                if (reassignStatus == null || reassignStatus.IsCompleted)
-                    continue;
-
-                var userName = UserManager.GetUsers(userId).DisplayUserName(DisplayUserSettingsHelper);
-                throw new Exception(string.Format(Resource.ReassignDataRemoveUserError, userName));
-            }
-        }
-
-        //#endregion
-
-        #region Remove user data
-
-
-        [Read(@"remove/progress")]
-        public RemoveProgressItem GetRemoveProgress(Guid userId)
-        {
-            PermissionContext.DemandPermissions(Constants.Action_EditUser);
-
-            return QueueWorkerRemove.GetProgressItemStatus(Tenant.TenantId, userId);
-        }
-
-        [Update(@"remove/terminate")]
-        public void TerminateRemoveFromBody([FromBody] TerminateRequestDto model)
-        {
-            PermissionContext.DemandPermissions(Constants.Action_EditUser);
-
-            QueueWorkerRemove.Terminate(Tenant.TenantId, model.UserId);
-        }
-
-        [Update(@"remove/terminate")]
-        [Consumes("application/x-www-form-urlencoded")]
-        public void TerminateRemoveFromForm([FromForm] TerminateRequestDto model)
-        {
-            PermissionContext.DemandPermissions(Constants.Action_EditUser);
-
-            QueueWorkerRemove.Terminate(Tenant.TenantId, model.UserId);
-        }
-
-        [Create(@"remove/start")]
-        public RemoveProgressItem StartRemoveFromBody([FromBody] TerminateRequestDto model)
-        {
-            return StartRemove(model);
-        }
-
-        [Create(@"remove/start")]
-        [Consumes("application/x-www-form-urlencoded")]
-        public RemoveProgressItem StartRemoveFromForm([FromForm] TerminateRequestDto model)
-        {
-            return StartRemove(model);
-        }
-
-        private RemoveProgressItem StartRemove(TerminateRequestDto model)
-        {
-            PermissionContext.DemandPermissions(Constants.Action_EditUser);
-
-            var user = UserManager.GetUsers(model.UserId);
-
-            if (user == null || user.ID == Constants.LostUser.ID)
-                throw new ArgumentException("User with id = " + model.UserId + " not found");
-
-            if (user.IsOwner(Tenant) || user.IsMe(AuthContext) || user.Status != EmployeeStatus.Terminated)
-                throw new ArgumentException("Can not delete user with id = " + model.UserId);
-
-            return QueueWorkerRemove.Start(Tenant.TenantId, user, SecurityContext.CurrentAccount.ID, true);
-        }
-
-        #endregion
-
-        private void UpdateDepartments(IEnumerable<Guid> department, UserInfo user)
-        {
-            if (!PermissionContext.CheckPermissions(Constants.Action_EditGroups)) return;
-            if (department == null) return;
-
-            var groups = UserManager.GetUserGroups(user.ID);
-            var managerGroups = new List<Guid>();
-            foreach (var groupInfo in groups)
-            {
-                UserManager.RemoveUserFromGroup(user.ID, groupInfo.ID);
-                var managerId = UserManager.GetDepartmentManager(groupInfo.ID);
-                if (managerId == user.ID)
-                {
-                    managerGroups.Add(groupInfo.ID);
-                    UserManager.SetDepartmentManager(groupInfo.ID, Guid.Empty);
-                }
-            }
-            foreach (var guid in department)
-            {
-                var userDepartment = UserManager.GetGroupInfo(guid);
-                if (userDepartment != Constants.LostGroupInfo)
-                {
-                    UserManager.AddUserIntoGroup(user.ID, guid);
-                    if (managerGroups.Contains(guid))
-                    {
-                        UserManager.SetDepartmentManager(guid, user.ID);
-                    }
-                }
-            }
-        }
-
-        private void UpdateContacts(IEnumerable<Contact> contacts, UserInfo user)
-        {
-            PermissionContext.DemandPermissions(new UserSecurityProvider(user.ID), Constants.Action_EditUser);
-
-            if (contacts == null) return;
-            var values = contacts.Where(r => !string.IsNullOrEmpty(r.Value)).Select(r => $"{r.Type}|{r.Value}");
-            user.Contacts = string.Join('|', values);
-        }
-
-        private void DeleteContacts(IEnumerable<Contact> contacts, UserInfo user)
-        {
-            PermissionContext.DemandPermissions(new UserSecurityProvider(user.ID), Constants.Action_EditUser);
-            if (contacts == null) return;
-
-            if (user.ContactsList == null)
-            {
-                user.ContactsList = new List<string>();
-            }
-
-            foreach (var contact in contacts)
-            {
-                var index = user.ContactsList.IndexOf(contact.Type);
-                if (index != -1)
-                {
-                    //Remove existing
-                    user.ContactsList.RemoveRange(index, 2);
-                }
-            }
-        }
-
-        private void UpdatePhotoUrl(string files, UserInfo user)
-        {
-            if (string.IsNullOrEmpty(files))
-            {
-                return;
-            }
-
-            PermissionContext.DemandPermissions(new UserSecurityProvider(user.ID), Constants.Action_EditUser);
-
-            if (!files.StartsWith("http://") && !files.StartsWith("https://"))
-            {
-                files = new Uri(ApiContext.HttpContextAccessor.HttpContext.Request.GetDisplayUrl()).GetLeftPart(UriPartial.Authority) + "/" + files.TrimStart('/');
-            }
-            var request = new HttpRequestMessage();
-            request.RequestUri = new Uri(files);
-
-            var httpClient = ClientFactory.CreateClient();
-            using var response = httpClient.Send(request);
-            using var inputStream = response.Content.ReadAsStream();
-            using var br = new BinaryReader(inputStream);
-            var imageByteArray = br.ReadBytes((int)inputStream.Length);
-            UserPhotoManager.SaveOrUpdatePhoto(user.ID, imageByteArray);
-        }
-
-        private static void CheckImgFormat(byte[] data)
-        {
-            IImageFormat imgFormat;
-            try
-            {
-                using var img = Image.Load(data, out var format);
-                imgFormat = format;
-            }
-            catch (OutOfMemoryException)
-            {
-                throw new ImageSizeLimitException();
-            }
-            catch (ArgumentException error)
-            {
-                throw new Web.Core.Users.UnknownImageFormatException(error);
-            }
-
-            if (imgFormat.Name != "PNG" && imgFormat.Name != "JPEG")
-            {
-                throw new Web.Core.Users.UnknownImageFormatException();
-            }
-        }
-    }
-}

From b21891ef78828ffa64ac1b8a26be49ee415b5da7 Mon Sep 17 00:00:00 2001
From: MaksimChegulov <maksim.chegulov@onlyoffice.com>
Date: Tue, 1 Mar 2022 14:52:52 +0300
Subject: [PATCH 18/28] People: logic transferred to engines

---
 .../Server/Api/ApiControllerBase.cs           |    7 +
 .../Server/Api/ContactsController.cs          |  120 +-
 .../ASC.People/Server/Api/GroupController.cs  |  223 +---
 .../Server/Api/NotificationController.cs      |   63 +-
 .../ASC.People/Server/Api/PhotoController.cs  |  244 +---
 .../Server/Api/ReassignController.cs          |   77 +-
 .../Server/Api/RemoveUserDataController.cs    |   76 +-
 .../Server/Api/ThirdpartyController.cs        |  333 +----
 .../ASC.People/Server/Api/UserController.cs   | 1091 +----------------
 .../ApiControllerEngineBase.cs}               |   22 +-
 .../ApiEngines/ContactsControllerEngine.cs    |  109 ++
 .../ApiEngines/GroupControllerEngine.cs       |  223 ++++
 .../NotificationControllerEngine.cs           |   58 +
 .../PeopleControllerEngine.cs}                |   11 +-
 .../ApiEngines/PhotoControllerEngine.cs       |  246 ++++
 .../ApiEngines/ReassignControllerEngine.cs    |   76 ++
 .../RemoveUserDataControllerEngine.cs         |   78 ++
 .../ApiEngines/ThirdpartyControllerEngine.cs  |  331 +++++
 .../Server/ApiEngines/UserControllerEngine.cs | 1087 ++++++++++++++++
 products/ASC.People/Server/GlobalUsings.cs    |    3 +-
 products/ASC.People/Server/PeopleProduct.cs   |  104 +-
 products/ASC.People/Server/Startup.cs         |   15 +
 22 files changed, 2401 insertions(+), 2196 deletions(-)
 create mode 100644 products/ASC.People/Server/Api/ApiControllerBase.cs
 rename products/ASC.People/Server/{Api/BaseApiController.cs => ApiEngines/ApiControllerEngineBase.cs} (84%)
 create mode 100644 products/ASC.People/Server/ApiEngines/ContactsControllerEngine.cs
 create mode 100644 products/ASC.People/Server/ApiEngines/GroupControllerEngine.cs
 create mode 100644 products/ASC.People/Server/ApiEngines/NotificationControllerEngine.cs
 rename products/ASC.People/Server/{Api/BasePeopleController.cs => ApiEngines/PeopleControllerEngine.cs} (95%)
 create mode 100644 products/ASC.People/Server/ApiEngines/PhotoControllerEngine.cs
 create mode 100644 products/ASC.People/Server/ApiEngines/ReassignControllerEngine.cs
 create mode 100644 products/ASC.People/Server/ApiEngines/RemoveUserDataControllerEngine.cs
 create mode 100644 products/ASC.People/Server/ApiEngines/ThirdpartyControllerEngine.cs
 create mode 100644 products/ASC.People/Server/ApiEngines/UserControllerEngine.cs

diff --git a/products/ASC.People/Server/Api/ApiControllerBase.cs b/products/ASC.People/Server/Api/ApiControllerBase.cs
new file mode 100644
index 0000000000..ec0283308a
--- /dev/null
+++ b/products/ASC.People/Server/Api/ApiControllerBase.cs
@@ -0,0 +1,7 @@
+namespace ASC.People.Api;
+
+[Scope(Additional = typeof(BaseLoginProviderExtension))]
+[DefaultRoute]
+[ApiController]
+[ControllerName("people")]
+public abstract class ApiControllerBase : ControllerBase { }
\ No newline at end of file
diff --git a/products/ASC.People/Server/Api/ContactsController.cs b/products/ASC.People/Server/Api/ContactsController.cs
index e746014996..e19497ee89 100644
--- a/products/ASC.People/Server/Api/ContactsController.cs
+++ b/products/ASC.People/Server/Api/ContactsController.cs
@@ -1,148 +1,50 @@
-using SecurityContext = ASC.Core.SecurityContext;
+namespace ASC.People.Api;
 
-namespace ASC.People.Api;
-
-public class ContactsController : BasePeopleController
+public class ContactsController : ApiControllerBase
 {
-    private readonly EmployeeFullDtoHelper _employeeFullDtoHelper;
+    private readonly ContactsControllerEngine _contactsControllerEngine;
 
-    public ContactsController(
-        UserManager userManager,
-        AuthContext authContext,
-        ApiContext apiContext,
-        PermissionContext permissionContext,
-        SecurityContext securityContext,
-        MessageService messageService,
-        MessageTarget messageTarget,
-        StudioNotifyService studioNotifyService,
-        UserPhotoManager userPhotoManager,
-        IHttpClientFactory httpClientFactory,
-        DisplayUserSettingsHelper displayUserSettingsHelper,
-        SetupInfo setupInfo,
-        EmployeeFullDtoHelper employeeFullDtoHelper)
-        : base(
-            userManager,
-            authContext,
-            apiContext,
-            permissionContext,
-            securityContext,
-            messageService,
-            messageTarget,
-            studioNotifyService,
-            userPhotoManager, 
-            httpClientFactory, 
-            displayUserSettingsHelper,
-            setupInfo)
+    public ContactsController(ContactsControllerEngine contactsControllerEngine)
     {
-        _employeeFullDtoHelper = employeeFullDtoHelper;
+        _contactsControllerEngine = contactsControllerEngine;
     }
 
     [Delete("{userid}/contacts")]
     public EmployeeFullDto DeleteMemberContactsFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
     {
-        return DeleteMemberContacts(userid, memberModel);
+        return _contactsControllerEngine.DeleteMemberContacts(userid, memberModel);
     }
 
     [Delete("{userid}/contacts")]
     [Consumes("application/x-www-form-urlencoded")]
     public EmployeeFullDto DeleteMemberContactsFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
     {
-        return DeleteMemberContacts(userid, memberModel);
+        return _contactsControllerEngine.DeleteMemberContacts(userid, memberModel);
     }
 
     [Create("{userid}/contacts")]
     public EmployeeFullDto SetMemberContactsFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
     {
-        return SetMemberContacts(userid, memberModel);
+        return _contactsControllerEngine.SetMemberContacts(userid, memberModel);
     }
 
     [Create("{userid}/contacts")]
     [Consumes("application/x-www-form-urlencoded")]
     public EmployeeFullDto SetMemberContactsFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
     {
-        return SetMemberContacts(userid, memberModel);
+        return _contactsControllerEngine.SetMemberContacts(userid, memberModel);
     }
 
     [Update("{userid}/contacts")]
     public EmployeeFullDto UpdateMemberContactsFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
     {
-        return UpdateMemberContacts(userid, memberModel);
+        return _contactsControllerEngine.UpdateMemberContacts(userid, memberModel);
     }
 
     [Update("{userid}/contacts")]
     [Consumes("application/x-www-form-urlencoded")]
     public EmployeeFullDto UpdateMemberContactsFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
     {
-        return UpdateMemberContacts(userid, memberModel);
-    }
-
-    private void DeleteContacts(IEnumerable<Contact> contacts, UserInfo user)
-    {
-        PermissionContext.DemandPermissions(new UserSecurityProvider(user.ID), Constants.Action_EditUser);
-        if (contacts == null)
-        {
-            return;
-        }
-
-        if (user.ContactsList == null)
-        {
-            user.ContactsList = new List<string>();
-        }
-
-        foreach (var contact in contacts)
-        {
-            var index = user.ContactsList.IndexOf(contact.Type);
-            if (index != -1)
-            {
-                //Remove existing
-                user.ContactsList.RemoveRange(index, 2);
-            }
-        }
-    }
-
-    private EmployeeFullDto DeleteMemberContacts(string userid, UpdateMemberRequestDto memberModel)
-    {
-        var user = GetUserInfo(userid);
-
-        if (UserManager.IsSystemUser(user.ID))
-        {
-            throw new SecurityException();
-        }
-
-        DeleteContacts(memberModel.Contacts, user);
-        UserManager.SaveUserInfo(user);
-
-        return _employeeFullDtoHelper.GetFull(user);
-    }
-
-    private EmployeeFullDto SetMemberContacts(string userid, UpdateMemberRequestDto memberModel)
-    {
-        var user = GetUserInfo(userid);
-
-        if (UserManager.IsSystemUser(user.ID))
-        {
-            throw new SecurityException();
-        }
-
-        user.ContactsList.Clear();
-        UpdateContacts(memberModel.Contacts, user);
-        UserManager.SaveUserInfo(user);
-
-        return _employeeFullDtoHelper.GetFull(user);
-    }
-
-    private EmployeeFullDto UpdateMemberContacts(string userid, UpdateMemberRequestDto memberModel)
-    {
-        var user = GetUserInfo(userid);
-
-        if (UserManager.IsSystemUser(user.ID))
-        {
-            throw new SecurityException();
-        }
-
-        UpdateContacts(memberModel.Contacts, user);
-        UserManager.SaveUserInfo(user);
-
-        return _employeeFullDtoHelper.GetFull(user);
+        return _contactsControllerEngine.UpdateMemberContacts(userid, memberModel);
     }
 }
diff --git a/products/ASC.People/Server/Api/GroupController.cs b/products/ASC.People/Server/Api/GroupController.cs
index a150c461d1..4aba8ce6a1 100644
--- a/products/ASC.People/Server/Api/GroupController.cs
+++ b/products/ASC.People/Server/Api/GroupController.cs
@@ -5,305 +5,124 @@
 [ApiController]
 public class GroupController : ControllerBase
 {
-    private readonly ApiContext _apiContext;
-    private readonly MessageService _messageService;
-    private readonly UserManager _userManager;
-    private readonly PermissionContext _permissionContext;
-    private readonly MessageTarget _messageTarget;
-    private readonly GroupFullDtoHelper _groupWraperFullHelper;
+    private readonly GroupControllerEngine _groupControllerEngine;
 
-    public GroupController(
-        ApiContext apiContext,
-        MessageService messageService,
-        UserManager userManager,
-        PermissionContext permissionContext,
-        MessageTarget messageTarget,
-        GroupFullDtoHelper groupWraperFullHelper)
+    public GroupController(GroupControllerEngine groupControllerEngine)
     {
-        _apiContext = apiContext;
-        _messageService = messageService;
-        _userManager = userManager;
-        _permissionContext = permissionContext;
-        _messageTarget = messageTarget;
-        _groupWraperFullHelper = groupWraperFullHelper;
+        _groupControllerEngine = groupControllerEngine;
     }
 
     [Read]
     public IEnumerable<GroupSummaryDto> GetAll()
     {
-        var result = _userManager.GetDepartments().Select(r => r);
-        if (!string.IsNullOrEmpty(_apiContext.FilterValue))
-        {
-            result = result.Where(r => r.Name.Contains(_apiContext.FilterValue, StringComparison.InvariantCultureIgnoreCase));
-        }
-
-        return result.Select(x => new GroupSummaryDto(x, _userManager));
+       return _groupControllerEngine.GetAll();
     }
 
     [Read("full")]
     public IEnumerable<GroupDto> GetAllWithMembers()
     {
-        var result = _userManager.GetDepartments().Select(r => r);
-        if (!string.IsNullOrEmpty(_apiContext.FilterValue))
-        {
-            result = result.Where(r => r.Name.Contains(_apiContext.FilterValue, StringComparison.InvariantCultureIgnoreCase));
-        }
-
-        return result.Select(r => _groupWraperFullHelper.Get(r, true));
+        return _groupControllerEngine.GetAllWithMembers();
     }
 
     [Read("{groupid}")]
     public GroupDto GetById(Guid groupid)
     {
-        return _groupWraperFullHelper.Get(GetGroupInfo(groupid), true);
+        return _groupControllerEngine.GetById(groupid);
     }
 
     [Read("user/{userid}")]
     public IEnumerable<GroupSummaryDto> GetByUserId(Guid userid)
     {
-        return _userManager.GetUserGroups(userid).Select(x => new GroupSummaryDto(x, _userManager));
+        return _groupControllerEngine.GetByUserId(userid);
     }
 
     [Create]
     public GroupDto AddGroupFromBody([FromBody] GroupRequestDto groupModel)
     {
-        return AddGroup(groupModel);
+        return _groupControllerEngine.AddGroup(groupModel);
     }
 
     [Create]
     [Consumes("application/x-www-form-urlencoded")]
     public GroupDto AddGroupFromForm([FromForm] GroupRequestDto groupModel)
     {
-        return AddGroup(groupModel);
-    }
-
-    private GroupDto AddGroup(GroupRequestDto groupModel)
-    {
-        _permissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
-
-        var group = _userManager.SaveGroupInfo(new GroupInfo { Name = groupModel.GroupName });
-
-        TransferUserToDepartment(groupModel.GroupManager, @group, true);
-        if (groupModel.Members != null)
-        {
-            foreach (var member in groupModel.Members)
-            {
-                TransferUserToDepartment(member, group, false);
-            }
-        }
-
-        _messageService.Send(MessageAction.GroupCreated, _messageTarget.Create(group.ID), group.Name);
-
-        return _groupWraperFullHelper.Get(group, true);
+        return _groupControllerEngine.AddGroup(groupModel);
     }
 
     [Update("{groupid}")]
     public GroupDto UpdateGroupFromBody(Guid groupid, [FromBody] GroupRequestDto groupModel)
     {
-        return UpdateGroup(groupid, groupModel);
+        return _groupControllerEngine.UpdateGroup(groupid, groupModel);
     }
 
     [Update("{groupid}")]
     [Consumes("application/x-www-form-urlencoded")]
     public GroupDto UpdateGroupFromForm(Guid groupid, [FromForm] GroupRequestDto groupModel)
     {
-        return UpdateGroup(groupid, groupModel);
-    }
-
-    private GroupDto UpdateGroup(Guid groupid, GroupRequestDto groupModel)
-    {
-        _permissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
-        var group = _userManager.GetGroups().SingleOrDefault(x => x.ID == groupid).NotFoundIfNull("group not found");
-        if (groupid == Constants.LostGroupInfo.ID)
-        {
-            throw new ItemNotFoundException("group not found");
-        }
-
-        group.Name = groupModel.GroupName ?? group.Name;
-        _userManager.SaveGroupInfo(group);
-
-        RemoveMembersFrom(groupid, new GroupRequestDto { Members = _userManager.GetUsersByGroup(groupid, EmployeeStatus.All).Select(u => u.ID).Where(id => !groupModel.Members.Contains(id)) });
-
-        TransferUserToDepartment(groupModel.GroupManager, @group, true);
-        if (groupModel.Members != null)
-        {
-            foreach (var member in groupModel.Members)
-            {
-                TransferUserToDepartment(member, group, false);
-            }
-        }
-
-        _messageService.Send(MessageAction.GroupUpdated, _messageTarget.Create(groupid), group.Name);
-
-        return GetById(groupid);
+        return _groupControllerEngine.UpdateGroup(groupid, groupModel);
     }
 
     [Delete("{groupid}")]
     public GroupDto DeleteGroup(Guid groupid)
     {
-        _permissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
-        var @group = GetGroupInfo(groupid);
-        var groupWrapperFull = _groupWraperFullHelper.Get(group, false);
-
-        _userManager.DeleteGroup(groupid);
-
-        _messageService.Send(MessageAction.GroupDeleted, _messageTarget.Create(group.ID), group.Name);
-
-        return groupWrapperFull;
-    }
-
-    private GroupInfo GetGroupInfo(Guid groupid)
-    {
-        var group = _userManager.GetGroups().SingleOrDefault(x => x.ID == groupid).NotFoundIfNull("group not found");
-        if (group.ID == Constants.LostGroupInfo.ID)
-        {
-            throw new ItemNotFoundException("group not found");
-        }
-
-        return @group;
+        return _groupControllerEngine.DeleteGroup(groupid);
     }
 
     [Update("{groupid}/members/{newgroupid}")]
     public GroupDto TransferMembersTo(Guid groupid, Guid newgroupid)
     {
-        _permissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
-        var oldgroup = GetGroupInfo(groupid);
-
-        var newgroup = GetGroupInfo(newgroupid);
-
-        var users = _userManager.GetUsersByGroup(oldgroup.ID);
-        foreach (var userInfo in users)
-        {
-            TransferUserToDepartment(userInfo.ID, newgroup, false);
-        }
-
-        return GetById(newgroupid);
+        return _groupControllerEngine.TransferMembersTo(groupid, newgroupid);
     }
 
     [Create("{groupid}/members")]
     public GroupDto SetMembersToFromBody(Guid groupid, [FromBody] GroupRequestDto groupModel)
     {
-        return SetMembersTo(groupid, groupModel);
+        return _groupControllerEngine.SetMembersTo(groupid, groupModel);
     }
 
     [Create("{groupid}/members")]
     [Consumes("application/x-www-form-urlencoded")]
     public GroupDto SetMembersToFromForm(Guid groupid, [FromForm] GroupRequestDto groupModel)
     {
-        return SetMembersTo(groupid, groupModel);
-    }
-
-    private GroupDto SetMembersTo(Guid groupid, GroupRequestDto groupModel)
-    {
-        RemoveMembersFrom(groupid, new GroupRequestDto { Members = _userManager.GetUsersByGroup(groupid).Select(x => x.ID) });
-        AddMembersTo(groupid, groupModel);
-
-        return GetById(groupid);
+        return _groupControllerEngine.SetMembersTo(groupid, groupModel);
     }
 
     [Update("{groupid}/members")]
     public GroupDto AddMembersToFromBody(Guid groupid, [FromBody] GroupRequestDto groupModel)
     {
-        return AddMembersTo(groupid, groupModel);
+        return _groupControllerEngine.AddMembersTo(groupid, groupModel);
     }
 
     [Update("{groupid}/members")]
     [Consumes("application/x-www-form-urlencoded")]
     public GroupDto AddMembersToFromForm(Guid groupid, [FromForm] GroupRequestDto groupModel)
     {
-        return AddMembersTo(groupid, groupModel);
-    }
-
-    private GroupDto AddMembersTo(Guid groupid, GroupRequestDto groupModel)
-    {
-        _permissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
-        var group = GetGroupInfo(groupid);
-
-        foreach (var userId in groupModel.Members)
-        {
-            TransferUserToDepartment(userId, group, false);
-        }
-
-        return GetById(group.ID);
+        return _groupControllerEngine.AddMembersTo(groupid, groupModel);
     }
 
     [Update("{groupid}/manager")]
     public GroupDto SetManagerFromBody(Guid groupid, [FromBody] SetManagerRequestDto setManagerModel)
     {
-        return SetManager(groupid, setManagerModel);
+        return _groupControllerEngine.SetManager(groupid, setManagerModel);
     }
 
     [Update("{groupid}/manager")]
     [Consumes("application/x-www-form-urlencoded")]
     public GroupDto SetManagerFromForm(Guid groupid, [FromForm] SetManagerRequestDto setManagerModel)
     {
-        return SetManager(groupid, setManagerModel);
-    }
-
-    private GroupDto SetManager(Guid groupid, SetManagerRequestDto setManagerModel)
-    {
-        var group = GetGroupInfo(groupid);
-        if (_userManager.UserExists(setManagerModel.UserId))
-        {
-            _userManager.SetDepartmentManager(group.ID, setManagerModel.UserId);
-        }
-        else
-        {
-            throw new ItemNotFoundException("user not found");
-        }
-
-        return GetById(groupid);
+        return _groupControllerEngine.SetManager(groupid, setManagerModel);
     }
 
     [Delete("{groupid}/members")]
     public GroupDto RemoveMembersFromFromBody(Guid groupid, [FromBody] GroupRequestDto groupModel)
     {
-        return RemoveMembersFrom(groupid, groupModel);
+        return _groupControllerEngine.RemoveMembersFrom(groupid, groupModel);
     }
 
     [Delete("{groupid}/members")]
     [Consumes("application/x-www-form-urlencoded")]
     public GroupDto RemoveMembersFromFromForm(Guid groupid, [FromForm] GroupRequestDto groupModel)
     {
-        return RemoveMembersFrom(groupid, groupModel);
-    }
-
-    private GroupDto RemoveMembersFrom(Guid groupid, GroupRequestDto groupModel)
-    {
-        _permissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
-        var group = GetGroupInfo(groupid);
-
-        foreach (var userId in groupModel.Members)
-        {
-            RemoveUserFromDepartment(userId, group);
-        }
-
-        return GetById(group.ID);
-    }
-
-    private void RemoveUserFromDepartment(Guid userId, GroupInfo @group)
-    {
-        if (!_userManager.UserExists(userId))
-        {
-            return;
-        }
-
-        var user = _userManager.GetUsers(userId);
-        _userManager.RemoveUserFromGroup(user.ID, @group.ID);
-        _userManager.SaveUserInfo(user);
-    }
-
-    private void TransferUserToDepartment(Guid userId, GroupInfo group, bool setAsManager)
-    {
-        if (!_userManager.UserExists(userId) && userId != Guid.Empty)
-        {
-            return;
-        }
-
-        if (setAsManager)
-        {
-            _userManager.SetDepartmentManager(@group.ID, userId);
-        }
-        _userManager.AddUserIntoGroup(userId, @group.ID);
+        return _groupControllerEngine.RemoveMembersFrom(groupid, groupModel);
     }
 }
diff --git a/products/ASC.People/Server/Api/NotificationController.cs b/products/ASC.People/Server/Api/NotificationController.cs
index 17e2d599e9..5084317e1f 100644
--- a/products/ASC.People/Server/Api/NotificationController.cs
+++ b/products/ASC.People/Server/Api/NotificationController.cs
@@ -1,71 +1,24 @@
-using SecurityContext = ASC.Core.SecurityContext;
+namespace ASC.People.Api;
 
-namespace ASC.People.Api;
-
-public class NotificationController : BaseApiController
+public class NotificationController : ApiControllerBase
 {
-    private readonly CommonLinkUtility _commonLinkUtility;
+    private readonly NotificationControllerEngine _notificationControllerEngine;
 
-    public NotificationController(
-        UserManager userManager,
-        AuthContext authContext,
-        ApiContext apiContext,
-        PermissionContext permissionContext,
-        SecurityContext securityContext,
-        MessageService messageService,
-        MessageTarget messageTarget,
-        StudioNotifyService studioNotifyService,
-        CommonLinkUtility commonLinkUtility)
-        : base(
-            userManager,
-            authContext,
-            apiContext,
-            permissionContext,
-            securityContext,
-            messageService,
-            messageTarget,
-            studioNotifyService)
+    public NotificationController(NotificationControllerEngine notificationControllerEngine)
     {
-        _commonLinkUtility = commonLinkUtility;
+        _notificationControllerEngine = notificationControllerEngine;
     }
 
     [Create("phone")]
     public object SendNotificationToChangeFromBody([FromBody] UpdateMemberRequestDto model)
     {
-        return SendNotificationToChange(model.UserId);
+        return _notificationControllerEngine.SendNotificationToChange(model.UserId);
     }
 
     [Create("phone")]
     [Consumes("application/x-www-form-urlencoded")]
     public object SendNotificationToChangeFromForm([FromForm] UpdateMemberRequestDto model)
     {
-        return SendNotificationToChange(model.UserId);
+        return _notificationControllerEngine.SendNotificationToChange(model.UserId);
     }
-
-    private object SendNotificationToChange(string userId)
-    {
-        var user = UserManager.GetUsers(
-            string.IsNullOrEmpty(userId)
-                ? SecurityContext.CurrentAccount.ID
-                : new Guid(userId));
-        var canChange =
-        user.IsMe(AuthContext)
-                    || PermissionContext.CheckPermissions(new UserSecurityProvider(user.ID), Constants.Action_EditUser);
-
-        if (!canChange)
-        {
-            throw new SecurityAccessDeniedException(Resource.ErrorAccessDenied);
-        }
-
-        user.MobilePhoneActivationStatus = MobilePhoneActivationStatus.NotActivated;
-        UserManager.SaveUserInfo(user);
-        if (user.IsMe(AuthContext))
-        {
-            return _commonLinkUtility.GetConfirmationUrl(user.Email, ConfirmType.PhoneActivation);
-        }
-
-        StudioNotifyService.SendMsgMobilePhoneChange(user);
-
-        return string.Empty;
-    }
-}
+}
\ No newline at end of file
diff --git a/products/ASC.People/Server/Api/PhotoController.cs b/products/ASC.People/Server/Api/PhotoController.cs
index cd101274a0..855ea5ddda 100644
--- a/products/ASC.People/Server/Api/PhotoController.cs
+++ b/products/ASC.People/Server/Api/PhotoController.cs
@@ -1,275 +1,55 @@
-using SecurityContext = ASC.Core.SecurityContext;
+namespace ASC.People.Api;
 
-namespace ASC.People.Api;
-
-public class PhotoController : BasePeopleController
+public class PhotoController : ApiControllerBase
 {
-    private readonly FileSizeComment _fileSizeComment;
-    private readonly SettingsManager _settingsManager;
+    private readonly PhotoControllerEngine _photoControllerEgine;
 
-    public PhotoController(
-        UserManager userManager,
-        AuthContext authContext,
-        ApiContext apiContext,
-        PermissionContext permissionContext,
-        SecurityContext securityContext,
-        MessageService messageService,
-        MessageTarget messageTarget,
-        StudioNotifyService studioNotifyService,
-        FileSizeComment fileSizeComment,
-        SettingsManager settingsManager,
-        UserPhotoManager userPhotoManager,
-        IHttpClientFactory httpClientFactory,
-        DisplayUserSettingsHelper displayUserSettingsHelper,
-        SetupInfo setupInfo)
-        : base(
-            userManager,
-            authContext,
-            apiContext,
-            permissionContext,
-            securityContext,
-            messageService,
-            messageTarget,
-            studioNotifyService,
-            userPhotoManager,
-            httpClientFactory,
-            displayUserSettingsHelper,
-            setupInfo)
+    public PhotoController(PhotoControllerEngine photoControllerEgine)
     {
-        _fileSizeComment = fileSizeComment;
-        _settingsManager = settingsManager;
+        _photoControllerEgine = photoControllerEgine;
     }
 
     [Create("{userid}/photo/thumbnails")]
     public ThumbnailsDataDto CreateMemberPhotoThumbnailsFromBody(string userid, [FromBody] ThumbnailsRequestDto thumbnailsModel)
     {
-        return CreateMemberPhotoThumbnails(userid, thumbnailsModel);
+        return _photoControllerEgine.CreateMemberPhotoThumbnails(userid, thumbnailsModel);
     }
 
     [Create("{userid}/photo/thumbnails")]
     [Consumes("application/x-www-form-urlencoded")]
     public ThumbnailsDataDto CreateMemberPhotoThumbnailsFromForm(string userid, [FromForm] ThumbnailsRequestDto thumbnailsModel)
     {
-        return CreateMemberPhotoThumbnails(userid, thumbnailsModel);
+        return _photoControllerEgine.CreateMemberPhotoThumbnails(userid, thumbnailsModel);
     }
 
     [Delete("{userid}/photo")]
     public ThumbnailsDataDto DeleteMemberPhoto(string userid)
     {
-        var user = GetUserInfo(userid);
-
-        if (UserManager.IsSystemUser(user.ID))
-        {
-            throw new SecurityException();
-        }
-
-        PermissionContext.DemandPermissions(new UserSecurityProvider(user.ID), Constants.Action_EditUser);
-
-        UserPhotoManager.RemovePhoto(user.ID);
-        UserManager.SaveUserInfo(user);
-        MessageService.Send(MessageAction.UserDeletedAvatar, MessageTarget.Create(user.ID), user.DisplayUserName(false, DisplayUserSettingsHelper));
-
-        return new ThumbnailsDataDto(user.ID, UserPhotoManager);
+        return _photoControllerEgine.DeleteMemberPhoto(userid);
     }
 
     [Read("{userid}/photo")]
     public ThumbnailsDataDto GetMemberPhoto(string userid)
     {
-        var user = GetUserInfo(userid);
-
-        if (UserManager.IsSystemUser(user.ID))
-        {
-            throw new SecurityException();
-        }
-
-        return new ThumbnailsDataDto(user.ID, UserPhotoManager);
+        return _photoControllerEgine.GetMemberPhoto(userid);
     }
 
     [Update("{userid}/photo")]
     public ThumbnailsDataDto UpdateMemberPhotoFromBody(string userid, [FromBody] UpdateMemberRequestDto model)
     {
-        return UpdateMemberPhoto(userid, model);
+        return _photoControllerEgine.UpdateMemberPhoto(userid, model);
     }
 
     [Update("{userid}/photo")]
     [Consumes("application/x-www-form-urlencoded")]
     public ThumbnailsDataDto UpdateMemberPhotoFromForm(string userid, [FromForm] UpdateMemberRequestDto model)
     {
-        return UpdateMemberPhoto(userid, model);
+        return _photoControllerEgine.UpdateMemberPhoto(userid, model);
     }
 
     [Create("{userid}/photo")]
     public FileUploadResultDto UploadMemberPhoto(string userid, IFormCollection model)
     {
-        var result = new FileUploadResultDto();
-        var autosave = bool.Parse(model["Autosave"]);
-
-        try
-        {
-            if (model.Files.Count != 0)
-            {
-                Guid userId;
-                try
-                {
-                    userId = new Guid(userid);
-                }
-                catch
-                {
-                    userId = SecurityContext.CurrentAccount.ID;
-                }
-
-                PermissionContext.DemandPermissions(new UserSecurityProvider(userId), Constants.Action_EditUser);
-
-                var userPhoto = model.Files[0];
-
-                if (userPhoto.Length > SetupInfo.MaxImageUploadSize)
-                {
-                    result.Success = false;
-                    result.Message = _fileSizeComment.FileImageSizeExceptionString;
-
-                    return result;
-                }
-
-                var data = new byte[userPhoto.Length];
-                using var inputStream = userPhoto.OpenReadStream();
-
-                var br = new BinaryReader(inputStream);
-                br.Read(data, 0, (int)userPhoto.Length);
-                br.Close();
-
-                CheckImgFormat(data);
-
-                if (autosave)
-                {
-                    if (data.Length > SetupInfo.MaxImageUploadSize)
-                    {
-                        throw new ImageSizeLimitException();
-                    }
-
-                    var mainPhoto = UserPhotoManager.SaveOrUpdatePhoto(userId, data);
-
-                    result.Data =
-                        new
-                        {
-                            main = mainPhoto,
-                            retina = UserPhotoManager.GetRetinaPhotoURL(userId),
-                            max = UserPhotoManager.GetMaxPhotoURL(userId),
-                            big = UserPhotoManager.GetBigPhotoURL(userId),
-                            medium = UserPhotoManager.GetMediumPhotoURL(userId),
-                            small = UserPhotoManager.GetSmallPhotoURL(userId),
-                        };
-                }
-                else
-                {
-                    result.Data = UserPhotoManager.SaveTempPhoto(data, SetupInfo.MaxImageUploadSize, UserPhotoManager.OriginalFotoSize.Width, UserPhotoManager.OriginalFotoSize.Height);
-                }
-
-                result.Success = true;
-            }
-            else
-            {
-                result.Success = false;
-                result.Message = PeopleResource.ErrorEmptyUploadFileSelected;
-            }
-
-        }
-        catch (Web.Core.Users.UnknownImageFormatException)
-        {
-            result.Success = false;
-            result.Message = PeopleResource.ErrorUnknownFileImageType;
-        }
-        catch (ImageWeightLimitException)
-        {
-            result.Success = false;
-            result.Message = PeopleResource.ErrorImageWeightLimit;
-        }
-        catch (ImageSizeLimitException)
-        {
-            result.Success = false;
-            result.Message = PeopleResource.ErrorImageSizetLimit;
-        }
-        catch (Exception ex)
-        {
-            result.Success = false;
-            result.Message = ex.Message.HtmlEncode();
-        }
-
-        return result;
-    }
-
-    private static void CheckImgFormat(byte[] data)
-    {
-        IImageFormat imgFormat;
-        try
-        {
-            using var img = Image.Load(data, out var format);
-            imgFormat = format;
-        }
-        catch (OutOfMemoryException)
-        {
-            throw new ImageSizeLimitException();
-        }
-        catch (ArgumentException error)
-        {
-            throw new Web.Core.Users.UnknownImageFormatException(error);
-        }
-
-        if (imgFormat.Name != "PNG" && imgFormat.Name != "JPEG")
-        {
-            throw new Web.Core.Users.UnknownImageFormatException();
-        }
-    }
-
-    private ThumbnailsDataDto CreateMemberPhotoThumbnails(string userid, ThumbnailsRequestDto thumbnailsModel)
-    {
-        var user = GetUserInfo(userid);
-
-        if (UserManager.IsSystemUser(user.ID))
-        {
-            throw new SecurityException();
-        }
-
-        PermissionContext.DemandPermissions(new UserSecurityProvider(user.ID), Constants.Action_EditUser);
-
-        if (!string.IsNullOrEmpty(thumbnailsModel.TmpFile))
-        {
-            var fileName = Path.GetFileName(thumbnailsModel.TmpFile);
-            var data = UserPhotoManager.GetTempPhotoData(fileName);
-
-            var settings = new UserPhotoThumbnailSettings(thumbnailsModel.X, thumbnailsModel.Y, thumbnailsModel.Width, thumbnailsModel.Height);
-            _settingsManager.SaveForUser(settings, user.ID);
-            UserPhotoManager.RemovePhoto(user.ID);
-            UserPhotoManager.SaveOrUpdatePhoto(user.ID, data);
-            UserPhotoManager.RemoveTempPhoto(fileName);
-        }
-        else
-        {
-            UserPhotoThumbnailManager.SaveThumbnails(UserPhotoManager, _settingsManager, thumbnailsModel.X, thumbnailsModel.Y, thumbnailsModel.Width, thumbnailsModel.Height, user.ID);
-        }
-
-        UserManager.SaveUserInfo(user);
-        MessageService.Send(MessageAction.UserUpdatedAvatarThumbnails, MessageTarget.Create(user.ID), user.DisplayUserName(false, DisplayUserSettingsHelper));
-
-        return new ThumbnailsDataDto(user.ID, UserPhotoManager);
-    }
-
-    private ThumbnailsDataDto UpdateMemberPhoto(string userid, UpdateMemberRequestDto model)
-    {
-        var user = GetUserInfo(userid);
-
-        if (UserManager.IsSystemUser(user.ID))
-        {
-            throw new SecurityException();
-        }
-
-        if (model.Files != UserPhotoManager.GetPhotoAbsoluteWebPath(user.ID))
-        {
-            UpdatePhotoUrl(model.Files, user);
-        }
-
-        UserManager.SaveUserInfo(user);
-        MessageService.Send(MessageAction.UserAddedAvatar, MessageTarget.Create(user.ID), user.DisplayUserName(false, DisplayUserSettingsHelper));
-
-        return new ThumbnailsDataDto(user.ID, UserPhotoManager);
+        return _photoControllerEgine.UploadMemberPhoto(userid, model);
     }
 }
diff --git a/products/ASC.People/Server/Api/ReassignController.cs b/products/ASC.People/Server/Api/ReassignController.cs
index a0d37e7ec9..6b9517412e 100644
--- a/products/ASC.People/Server/Api/ReassignController.cs
+++ b/products/ASC.People/Server/Api/ReassignController.cs
@@ -1,100 +1,43 @@
-using SecurityContext = ASC.Core.SecurityContext;
+namespace ASC.People.Api;
 
-namespace ASC.People.Api;
-
-public class ReassignController : BaseApiController
+public class ReassignController : ApiControllerBase
 {
-    private readonly QueueWorkerReassign _queueWorkerReassign;
+    private readonly ReassignControllerEngine _reassignControllerEngine;
 
-    public ReassignController(
-        UserManager userManager,
-        AuthContext authContext,
-        ApiContext apiContext,
-        PermissionContext permissionContext,
-        SecurityContext securityContext,
-        MessageService messageService,
-        MessageTarget messageTarget,
-        StudioNotifyService studioNotifyService,
-        QueueWorkerReassign queueWorkerReassign)
-        : base(
-            userManager,
-            authContext,
-            apiContext,
-            permissionContext,
-            securityContext,
-            messageService,
-            messageTarget,
-            studioNotifyService)
+    public ReassignController(ReassignControllerEngine reassignControllerEngine)
     {
-        _queueWorkerReassign = queueWorkerReassign;
+        _reassignControllerEngine = reassignControllerEngine;
     }
 
     [Read(@"reassign/progress")]
     public ReassignProgressItem GetReassignProgress(Guid userId)
     {
-        PermissionContext.DemandPermissions(Constants.Action_EditUser);
-
-        return _queueWorkerReassign.GetProgressItemStatus(Tenant.TenantId, userId);
+        return _reassignControllerEngine.GetReassignProgress(userId);
     }
 
     [Create(@"reassign/start")]
     public ReassignProgressItem StartReassignFromBody([FromBody] StartReassignRequestDto model)
     {
-        return StartReassign(model);
+        return _reassignControllerEngine.StartReassign(model);
     }
 
     [Create(@"reassign/start")]
     [Consumes("application/x-www-form-urlencoded")]
     public ReassignProgressItem StartReassignFromForm([FromForm] StartReassignRequestDto model)
     {
-        return StartReassign(model);
+        return _reassignControllerEngine.StartReassign(model);
     }
 
     [Update(@"reassign/terminate")]
     public void TerminateReassignFromBody([FromBody] TerminateRequestDto model)
     {
-        PermissionContext.DemandPermissions(Constants.Action_EditUser);
-
-        _queueWorkerReassign.Terminate(Tenant.TenantId, model.UserId);
+        _reassignControllerEngine.TerminateReassign(model);
     }
 
     [Update(@"reassign/terminate")]
     [Consumes("application/x-www-form-urlencoded")]
     public void TerminateReassignFromForm([FromForm] TerminateRequestDto model)
     {
-        PermissionContext.DemandPermissions(Constants.Action_EditUser);
-
-        _queueWorkerReassign.Terminate(Tenant.TenantId, model.UserId);
-    }
-
-    private ReassignProgressItem StartReassign(StartReassignRequestDto model)
-    {
-        PermissionContext.DemandPermissions(Constants.Action_EditUser);
-
-        var fromUser = UserManager.GetUsers(model.FromUserId);
-
-        if (fromUser == null || fromUser.ID == Constants.LostUser.ID)
-        {
-            throw new ArgumentException("User with id = " + model.FromUserId + " not found");
-        }
-
-        if (fromUser.IsOwner(Tenant) || fromUser.IsMe(AuthContext) || fromUser.Status != EmployeeStatus.Terminated)
-        {
-            throw new ArgumentException("Can not delete user with id = " + model.FromUserId);
-        }
-
-        var toUser = UserManager.GetUsers(model.ToUserId);
-
-        if (toUser == null || toUser.ID == Constants.LostUser.ID)
-        {
-            throw new ArgumentException("User with id = " + model.ToUserId + " not found");
-        }
-
-        if (toUser.IsVisitor(UserManager) || toUser.Status == EmployeeStatus.Terminated)
-        {
-            throw new ArgumentException("Can not reassign data to user with id = " + model.ToUserId);
-        }
-
-        return _queueWorkerReassign.Start(Tenant.TenantId, model.FromUserId, model.ToUserId, SecurityContext.CurrentAccount.ID, model.DeleteProfile);
+        _reassignControllerEngine.TerminateReassign(model);
     }
 }
diff --git a/products/ASC.People/Server/Api/RemoveUserDataController.cs b/products/ASC.People/Server/Api/RemoveUserDataController.cs
index 3a6acc85ff..3e4e2d4d57 100644
--- a/products/ASC.People/Server/Api/RemoveUserDataController.cs
+++ b/products/ASC.People/Server/Api/RemoveUserDataController.cs
@@ -1,103 +1,49 @@
-using SecurityContext = ASC.Core.SecurityContext;
+namespace ASC.People.Api;
 
-namespace ASC.People.Api;
-
-public class RemoveUserDataController : BaseApiController
+public class RemoveUserDataController : ApiControllerBase
 {
-    private readonly QueueWorkerRemove _queueWorkerRemove;
+    private readonly RemoveUserDataControllerEngine _removeUserDataControllerEngine;
 
-    public RemoveUserDataController(
-        UserManager userManager,
-        AuthContext authContext,
-        ApiContext apiContext,
-        PermissionContext permissionContext,
-        SecurityContext securityContext,
-        MessageService messageService,
-        MessageTarget messageTarget,
-        StudioNotifyService studioNotifyService,
-        QueueWorkerRemove queueWorkerRemove)
-        : base(userManager,
-               authContext,
-               apiContext,
-               permissionContext,
-               securityContext,
-               messageService,
-               messageTarget,
-               studioNotifyService)
+    public RemoveUserDataController(RemoveUserDataControllerEngine removeUserDataControllerEngine)
     {
-        _queueWorkerRemove = queueWorkerRemove;
+        _removeUserDataControllerEngine = removeUserDataControllerEngine;
     }
 
     [Read(@"remove/progress")]
     public RemoveProgressItem GetRemoveProgress(Guid userId)
     {
-        PermissionContext.DemandPermissions(Constants.Action_EditUser);
-
-        return _queueWorkerRemove.GetProgressItemStatus(Tenant.TenantId, userId);
+       return _removeUserDataControllerEngine.GetRemoveProgress(userId);
     }
 
     [Update("self/delete")]
     public object SendInstructionsToDelete()
     {
-        var user = UserManager.GetUsers(SecurityContext.CurrentAccount.ID);
-
-        if (user.IsLDAP())
-        {
-            throw new SecurityException();
-        }
-
-        StudioNotifyService.SendMsgProfileDeletion(user);
-        MessageService.Send(MessageAction.UserSentDeleteInstructions);
-
-        return string.Format(Resource.SuccessfullySentNotificationDeleteUserInfoMessage, "<b>" + user.Email + "</b>");
+        return _removeUserDataControllerEngine.SendInstructionsToDelete();
     }
 
     [Create(@"remove/start")]
     public RemoveProgressItem StartRemoveFromBody([FromBody] TerminateRequestDto model)
     {
-        return StartRemove(model);
+        return _removeUserDataControllerEngine.StartRemove(model);
     }
 
     [Create(@"remove/start")]
     [Consumes("application/x-www-form-urlencoded")]
     public RemoveProgressItem StartRemoveFromForm([FromForm] TerminateRequestDto model)
     {
-        return StartRemove(model);
+        return _removeUserDataControllerEngine.StartRemove(model);
     }
 
     [Update(@"remove/terminate")]
     public void TerminateRemoveFromBody([FromBody] TerminateRequestDto model)
     {
-        PermissionContext.DemandPermissions(Constants.Action_EditUser);
-
-        _queueWorkerRemove.Terminate(Tenant.TenantId, model.UserId);
+        _removeUserDataControllerEngine.TerminateRemove(model);
     }
 
     [Update(@"remove/terminate")]
     [Consumes("application/x-www-form-urlencoded")]
     public void TerminateRemoveFromForm([FromForm] TerminateRequestDto model)
     {
-        PermissionContext.DemandPermissions(Constants.Action_EditUser);
-
-        _queueWorkerRemove.Terminate(Tenant.TenantId, model.UserId);
-    }
-
-    private RemoveProgressItem StartRemove(TerminateRequestDto model)
-    {
-        PermissionContext.DemandPermissions(Constants.Action_EditUser);
-
-        var user = UserManager.GetUsers(model.UserId);
-
-        if (user == null || user.ID == Constants.LostUser.ID)
-        {
-            throw new ArgumentException("User with id = " + model.UserId + " not found");
-        }
-
-        if (user.IsOwner(Tenant) || user.IsMe(AuthContext) || user.Status != EmployeeStatus.Terminated)
-        {
-            throw new ArgumentException("Can not delete user with id = " + model.UserId);
-        }
-
-        return _queueWorkerRemove.Start(Tenant.TenantId, user, SecurityContext.CurrentAccount.ID, true);
+        _removeUserDataControllerEngine.TerminateRemove(model);
     }
 }
diff --git a/products/ASC.People/Server/Api/ThirdpartyController.cs b/products/ASC.People/Server/Api/ThirdpartyController.cs
index 24a951cdda..1d46ecc432 100644
--- a/products/ASC.People/Server/Api/ThirdpartyController.cs
+++ b/products/ASC.People/Server/Api/ThirdpartyController.cs
@@ -1,133 +1,39 @@
-using SecurityContext = ASC.Core.SecurityContext;
+namespace ASC.People.Api;
 
-namespace ASC.People.Api;
-
-public class ThirdpartyController : BaseApiController
+public class ThirdpartyController : ApiControllerBase
 {
-    private readonly IOptionsSnapshot<AccountLinker> _accountLinker;
-    private readonly CookiesManager _cookiesManager;
-    private readonly CoreBaseSettings _coreBaseSettings;
-    private readonly DisplayUserSettingsHelper _displayUserSettingsHelper;
-    private readonly IHttpClientFactory _httpClientFactory;
-    private readonly InstanceCrypto _instanceCrypto;
-    private readonly MobileDetector _mobileDetector;
-    private readonly PersonalSettingsHelper _personalSettingsHelper;
-    private readonly ProviderManager _providerManager;
-    private readonly Signature _signature;
-    private readonly TenantExtra _tenantExtra;
-    private readonly UserHelpTourHelper _userHelpTourHelper;
-    private readonly UserManagerWrapper _userManagerWrapper;
-    private readonly UserPhotoManager _userPhotoManager;
+    private readonly ThirdpartyControllerEngine _thirdpartyControllerEngine;
 
-    public ThirdpartyController(
-        UserManager userManager,
-        AuthContext authContext,
-        ApiContext apiContext,
-        PermissionContext permissionContext,
-        SecurityContext securityContext,
-        MessageService messageService,
-        MessageTarget messageTarget,
-        StudioNotifyService studioNotifyService,
-        IOptionsSnapshot<AccountLinker> optionsSnapshot,
-        CookiesManager cookiesManager,
-        CoreBaseSettings coreBaseSettings,
-        DisplayUserSettingsHelper displayUserSettingsHelper,
-        IHttpClientFactory httpClientFactory,
-        InstanceCrypto instanceCrypto,
-        MobileDetector mobileDetector,
-        PersonalSettingsHelper personalSettingsHelper,
-        ProviderManager providerManager,
-        Signature signature,
-        TenantExtra tenantExtra,
-        UserHelpTourHelper userHelpTourHelper,
-        UserManagerWrapper userManagerWrapper,
-        UserPhotoManager userPhotoManager
-        )
-        : base(
-            userManager,
-            authContext,
-            apiContext,
-            permissionContext,
-            securityContext,
-            messageService,
-            messageTarget,
-            studioNotifyService)
+    public ThirdpartyController(ThirdpartyControllerEngine thirdpartyControllerEngine)
     {
-        _accountLinker = optionsSnapshot;
-        _cookiesManager = cookiesManager;
-        _coreBaseSettings = coreBaseSettings;
-        _displayUserSettingsHelper = displayUserSettingsHelper;
-        _httpClientFactory = httpClientFactory;
-        _instanceCrypto = instanceCrypto;
-        _mobileDetector = mobileDetector;
-        _personalSettingsHelper = personalSettingsHelper;
-        _providerManager = providerManager;
-        _signature = signature;
-        _tenantExtra = tenantExtra;
-        _userHelpTourHelper = userHelpTourHelper;
-        _userManagerWrapper = userManagerWrapper;
-        _userPhotoManager = userPhotoManager;
+        _thirdpartyControllerEngine = thirdpartyControllerEngine;
     }
 
     [AllowAnonymous]
     [Read("thirdparty/providers")]
     public ICollection<AccountInfoDto> GetAuthProviders(bool inviteView, bool settingsView, string clientCallback, string fromOnly)
     {
-        ICollection<AccountInfoDto> infos = new List<AccountInfoDto>();
-        IEnumerable<LoginProfile> linkedAccounts = new List<LoginProfile>();
-
-        if (AuthContext.IsAuthenticated)
-        {
-            linkedAccounts = _accountLinker.Get("webstudio").GetLinkedProfiles(AuthContext.CurrentAccount.ID.ToString());
-        }
-
-        fromOnly = string.IsNullOrWhiteSpace(fromOnly) ? string.Empty : fromOnly.ToLower();
-
-        foreach (var provider in ProviderManager.AuthProviders.Where(provider => string.IsNullOrEmpty(fromOnly) || fromOnly == provider || (provider == "google" && fromOnly == "openid")))
-        {
-            if (inviteView && provider.Equals("twitter", StringComparison.OrdinalIgnoreCase))
-            {
-                continue;
-            }
-            var loginProvider = _providerManager.GetLoginProvider(provider);
-            if (loginProvider != null && loginProvider.IsEnabled)
-            {
-
-                var url = VirtualPathUtility.ToAbsolute("~/login.ashx") + $"?auth={provider}";
-                var mode = settingsView || inviteView || (!_mobileDetector.IsMobile() && !Request.DesktopApp())
-                        ? $"&mode=popup&callback={clientCallback}"
-                        : "&mode=Redirect&desktop=true";
-
-                infos.Add(new AccountInfoDto
-                {
-                    Linked = linkedAccounts.Any(x => x.Provider == provider),
-                    Provider = provider,
-                    Url = url + mode
-                });
-            }
-        }
-
-        return infos;
+        return _thirdpartyControllerEngine.GetAuthProviders(inviteView, settingsView, clientCallback, fromOnly, Request);
     }
 
     [Update("thirdparty/linkaccount")]
     public void LinkAccountFromBody([FromBody] LinkAccountRequestDto model)
     {
-        LinkAccount(model);
+        _thirdpartyControllerEngine.LinkAccount(model);
     }
 
     [Update("thirdparty/linkaccount")]
     [Consumes("application/x-www-form-urlencoded")]
     public void LinkAccountFromForm([FromForm] LinkAccountRequestDto model)
     {
-        LinkAccount(model);
+        _thirdpartyControllerEngine.LinkAccount(model);
     }
 
     [AllowAnonymous]
     [Create("thirdparty/signup")]
     public void SignupAccountFromBody([FromBody] SignupAccountRequestDto model)
     {
-        SignupAccount(model);
+        _thirdpartyControllerEngine.SignupAccount(model);
     }
 
     [AllowAnonymous]
@@ -135,229 +41,12 @@ public class ThirdpartyController : BaseApiController
     [Consumes("application/x-www-form-urlencoded")]
     public void SignupAccountFromForm([FromForm] SignupAccountRequestDto model)
     {
-        SignupAccount(model);
+        _thirdpartyControllerEngine.SignupAccount(model);
     }
 
     [Delete("thirdparty/unlinkaccount")]
     public void UnlinkAccount(string provider)
     {
-        GetLinker().RemoveProvider(SecurityContext.CurrentAccount.ID.ToString(), provider);
-        MessageService.Send(MessageAction.UserUnlinkedSocialAccount, GetMeaningfulProviderName(provider));
-    }
-
-    private static string GetMeaningfulProviderName(string providerName)
-    {
-        switch (providerName)
-        {
-            case "google":
-            case "openid":
-                return "Google";
-            case "facebook":
-                return "Facebook";
-            case "twitter":
-                return "Twitter";
-            case "linkedin":
-                return "LinkedIn";
-            default:
-                return "Unknown Provider";
-        }
-    }
-
-    private UserInfo CreateNewUser(string firstName, string lastName, string email, string passwordHash, EmployeeType employeeType, bool fromInviteLink)
-    {
-        var isVisitor = employeeType == EmployeeType.Visitor;
-
-        if (SetupInfo.IsSecretEmail(email))
-        {
-            fromInviteLink = false;
-        }
-
-        var userInfo = new UserInfo
-        {
-            FirstName = string.IsNullOrEmpty(firstName) ? UserControlsCommonResource.UnknownFirstName : firstName,
-            LastName = string.IsNullOrEmpty(lastName) ? UserControlsCommonResource.UnknownLastName : lastName,
-            Email = email,
-        };
-
-        if (_coreBaseSettings.Personal)
-        {
-            userInfo.ActivationStatus = EmployeeActivationStatus.Activated;
-            userInfo.CultureName = _coreBaseSettings.CustomMode ? "ru-RU" : Thread.CurrentThread.CurrentUICulture.Name;
-        }
-
-        return _userManagerWrapper.AddUser(userInfo, passwordHash, true, true, isVisitor, fromInviteLink);
-    }
-
-    private string GetEmailAddress(SignupAccountRequestDto model)
-    {
-        if (!string.IsNullOrEmpty(model.Email))
-        {
-            return model.Email.Trim();
-        }
-
-        return string.Empty;
-    }
-
-    private string GetEmailAddress(SignupAccountRequestDto model, LoginProfile account)
-    {
-        var value = GetEmailAddress(model);
-
-        return string.IsNullOrEmpty(value) ? account.EMail : value;
-    }
-
-    private string GetFirstName(SignupAccountRequestDto model)
-    {
-        var value = string.Empty;
-        if (!string.IsNullOrEmpty(model.FirstName))
-        {
-            value = model.FirstName.Trim();
-        }
-
-        return HtmlUtil.GetText(value);
-    }
-
-    private string GetFirstName(SignupAccountRequestDto model, LoginProfile account)
-    {
-        var value = GetFirstName(model);
-
-        return string.IsNullOrEmpty(value) ? account.FirstName : value;
-    }
-
-    private string GetLastName(SignupAccountRequestDto model)
-    {
-        var value = string.Empty;
-        if (!string.IsNullOrEmpty(model.LastName))
-        {
-            value = model.LastName.Trim();
-        }
-
-        return HtmlUtil.GetText(value);
-    }
-
-    private string GetLastName(SignupAccountRequestDto model, LoginProfile account)
-    {
-        var value = GetLastName(model);
-
-        return string.IsNullOrEmpty(value) ? account.LastName : value;
-    }
-
-    private AccountLinker GetLinker()
-    {
-        return _accountLinker.Get("webstudio");
-    }
-
-    private void LinkAccount(LinkAccountRequestDto model)
-    {
-        var profile = new LoginProfile(_signature, _instanceCrypto, model.SerializedProfile);
-
-        if (!(_coreBaseSettings.Standalone || _tenantExtra.GetTenantQuota().Oauth))
-        {
-            throw new Exception("ErrorNotAllowedOption");
-        }
-
-        if (string.IsNullOrEmpty(profile.AuthorizationError))
-        {
-            GetLinker().AddLink(SecurityContext.CurrentAccount.ID.ToString(), profile);
-            MessageService.Send(MessageAction.UserLinkedSocialAccount, GetMeaningfulProviderName(profile.Provider));
-        }
-        else
-        {
-            // ignore cancellation
-            if (profile.AuthorizationError != "Canceled at provider")
-            {
-                throw new Exception(profile.AuthorizationError);
-            }
-        }
-    }
-
-    private void SaveContactImage(Guid userID, string url)
-    {
-        using (var memstream = new MemoryStream())
-        {
-            var request = new HttpRequestMessage();
-            request.RequestUri = new Uri(url);
-
-            var httpClient = _httpClientFactory.CreateClient();
-            using (var response = httpClient.Send(request))
-            using (var stream = response.Content.ReadAsStream())
-            {
-                var buffer = new byte[512];
-                int bytesRead;
-                while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
-                {
-                    memstream.Write(buffer, 0, bytesRead);
-                }
-
-                var bytes = memstream.ToArray();
-
-                _userPhotoManager.SaveOrUpdatePhoto(userID, bytes);
-            }
-        }
-    }
-
-    private void SignupAccount(SignupAccountRequestDto model)
-    {
-        var employeeType = model.EmplType ?? EmployeeType.User;
-        var passwordHash = model.PasswordHash;
-        var mustChangePassword = false;
-        if (string.IsNullOrEmpty(passwordHash))
-        {
-            passwordHash = UserManagerWrapper.GeneratePassword();
-            mustChangePassword = true;
-        }
-
-        var thirdPartyProfile = new LoginProfile(_signature, _instanceCrypto, model.SerializedProfile);
-        if (!string.IsNullOrEmpty(thirdPartyProfile.AuthorizationError))
-        {
-            // ignore cancellation
-            if (thirdPartyProfile.AuthorizationError != "Canceled at provider")
-            {
-                throw new Exception(thirdPartyProfile.AuthorizationError);
-            }
-
-            return;
-        }
-
-        if (string.IsNullOrEmpty(thirdPartyProfile.EMail))
-        {
-            throw new Exception(Resource.ErrorNotCorrectEmail);
-        }
-
-        var userID = Guid.Empty;
-        try
-        {
-            SecurityContext.AuthenticateMeWithoutCookie(ASC.Core.Configuration.Constants.CoreSystem);
-            var newUser = CreateNewUser(GetFirstName(model, thirdPartyProfile), GetLastName(model, thirdPartyProfile), GetEmailAddress(model, thirdPartyProfile), passwordHash, employeeType, false);
-            var messageAction = employeeType == EmployeeType.User ? MessageAction.UserCreatedViaInvite : MessageAction.GuestCreatedViaInvite;
-            MessageService.Send(MessageInitiator.System, messageAction, MessageTarget.Create(newUser.ID), newUser.DisplayUserName(false, _displayUserSettingsHelper));
-            userID = newUser.ID;
-            if (!string.IsNullOrEmpty(thirdPartyProfile.Avatar))
-            {
-                SaveContactImage(userID, thirdPartyProfile.Avatar);
-            }
-
-            GetLinker().AddLink(userID.ToString(), thirdPartyProfile);
-        }
-        finally
-        {
-            SecurityContext.Logout();
-        }
-
-        var user = UserManager.GetUsers(userID);
-        var cookiesKey = SecurityContext.AuthenticateMe(user.Email, passwordHash);
-        _cookiesManager.SetCookies(CookiesType.AuthKey, cookiesKey);
-        MessageService.Send(MessageAction.LoginSuccess);
-        StudioNotifyService.UserHasJoin();
-
-        if (mustChangePassword)
-        {
-            StudioNotifyService.UserPasswordChange(user);
-        }
-
-        _userHelpTourHelper.IsNewUser = true;
-        if (_coreBaseSettings.Personal)
-        {
-            _personalSettingsHelper.IsNewUser = true;
-        }
+        _thirdpartyControllerEngine.UnlinkAccount(provider);
     }
 }
diff --git a/products/ASC.People/Server/Api/UserController.cs b/products/ASC.People/Server/Api/UserController.cs
index 1cf8bddc14..719b1e0b78 100644
--- a/products/ASC.People/Server/Api/UserController.cs
+++ b/products/ASC.People/Server/Api/UserController.cs
@@ -1,115 +1,34 @@
-using SecurityContext = ASC.Core.SecurityContext;
-using Module = ASC.Api.Core.Module;
+using Module = ASC.Api.Core.Module;
 
 namespace ASC.People.Api;
 
-public class UserController : BasePeopleController
+public class UserController : ApiControllerBase
 {
-    private readonly Constants _constants;
-    private readonly CookiesManager _cookiesManager;
-    private readonly CoreBaseSettings _coreBaseSettings;
-    private readonly CustomNamingPeople _customNamingPeople;
-    private readonly ILog _logger;
-    private readonly PasswordHasher _passwordHasher;
-    private readonly QueueWorkerReassign _queueWorkerReassign;
-    private readonly QueueWorkerRemove _queueWorkerRemove;
-    private readonly Recaptcha _recaptcha;
-    private readonly TenantExtra _tenantExtra;
-    private readonly TenantStatisticsProvider _tenantStatisticsProvider;
-    private readonly TenantUtil _tenantUtil;
-    private readonly UserFormatter _userFormatter;
-    private readonly UserManagerWrapper _userManagerWrapper;
-    private readonly WebItemManager _webItemManager;
-    private readonly WebItemSecurity _webItemSecurity;
-    private readonly WebItemSecurityCache _webItemSecurityCache;
-    private readonly EmployeeFullDtoHelper _employeeFullDtoHelper;
-    private readonly EmployeeDtoHelper _employeeDtoHelper;
+    private readonly UserControllerEngine _userControllerEngine;
 
-    public UserController(
-        UserManager userManager,
-        AuthContext authContext,
-        ApiContext apiContext,
-        PermissionContext permissionContext,
-        SecurityContext securityContext,
-        MessageService messageService,
-        MessageTarget messageTarget,
-        StudioNotifyService studioNotifyService,
-        Constants constants,
-        CookiesManager cookiesManager,
-        CoreBaseSettings coreBaseSettings,
-        CustomNamingPeople customNamingPeople,
-        ILog logger,
-        PasswordHasher passwordHasher,
-        QueueWorkerReassign queueWorkerReassign,
-        QueueWorkerRemove queueWorkerRemove,
-        Recaptcha recaptcha,
-        TenantExtra tenantExtra,
-        TenantStatisticsProvider tenantStatisticsProvider,
-        TenantUtil tenantUtil,
-        UserFormatter userFormatter,
-        UserManagerWrapper userManagerWrapper,
-        WebItemManager webItemManager,
-        WebItemSecurity webItemSecurity,
-        WebItemSecurityCache webItemSecurityCache,
-        UserPhotoManager userPhotoManager,
-        IHttpClientFactory httpClientFactory,
-        DisplayUserSettingsHelper displayUserSettingsHelper,
-        SetupInfo setupInfo,
-        EmployeeFullDtoHelper employeeFullDtoHelper,
-        EmployeeDtoHelper employeeDtoHelper)
-        : base(
-            userManager,
-            authContext,
-            apiContext,
-            permissionContext,
-            securityContext,
-            messageService,
-            messageTarget,
-            studioNotifyService,
-            userPhotoManager,
-            httpClientFactory,
-            displayUserSettingsHelper,
-            setupInfo)
+    public UserController(UserControllerEngine userControllerEngine)
     {
-        _constants = constants;
-        _cookiesManager = cookiesManager;
-        _coreBaseSettings = coreBaseSettings;
-        _customNamingPeople = customNamingPeople;
-        _logger = logger;
-        _passwordHasher = passwordHasher;
-        _queueWorkerReassign = queueWorkerReassign;
-        _queueWorkerRemove = queueWorkerRemove;
-        _recaptcha = recaptcha;
-        _tenantExtra = tenantExtra;
-        _tenantStatisticsProvider = tenantStatisticsProvider;
-        _tenantUtil = tenantUtil;
-        _userFormatter = userFormatter;
-        _userManagerWrapper = userManagerWrapper;
-        _webItemManager = webItemManager;
-        _webItemSecurity = webItemSecurity;
-        _webItemSecurityCache = webItemSecurityCache;
-        _employeeDtoHelper = employeeDtoHelper;
-        _employeeFullDtoHelper = employeeFullDtoHelper;
+        _userControllerEngine = userControllerEngine;
     }
 
     [Create("active")]
     public EmployeeFullDto AddMemberAsActivatedFromBody([FromBody] MemberRequestDto memberModel)
     {
-        return AddMemberAsActivated(memberModel);
+        return _userControllerEngine.AddMemberAsActivated(memberModel);
     }
 
     [Create("active")]
     [Consumes("application/x-www-form-urlencoded")]
     public EmployeeFullDto AddMemberAsActivatedFromForm([FromForm] MemberRequestDto memberModel)
     {
-        return AddMemberAsActivated(memberModel);
+        return _userControllerEngine.AddMemberAsActivated(memberModel);
     }
 
     [Create]
     [Authorize(AuthenticationSchemes = "confirm", Roles = "LinkInvite,Everyone")]
     public EmployeeFullDto AddMemberFromBody([FromBody] MemberRequestDto memberModel)
     {
-        return AddMember(memberModel);
+        return _userControllerEngine.AddMember(memberModel);
     }
 
     [Create]
@@ -117,14 +36,14 @@ public class UserController : BasePeopleController
     [Consumes("application/x-www-form-urlencoded")]
     public EmployeeFullDto AddMemberFromForm([FromForm] MemberRequestDto memberModel)
     {
-        return AddMember(memberModel);
+        return _userControllerEngine.AddMember(memberModel);
     }
 
     [Update("{userid}/password")]
     [Authorize(AuthenticationSchemes = "confirm", Roles = "PasswordChange,EmailChange,Activation,EmailActivation,Everyone")]
     public EmployeeFullDto ChangeUserPasswordFromBody(Guid userid, [FromBody] MemberRequestDto memberModel)
     {
-        return ChangeUserPassword(userid, memberModel);
+        return _userControllerEngine.ChangeUserPassword(userid, memberModel);
     }
 
     [Update("{userid}/password")]
@@ -132,116 +51,26 @@ public class UserController : BasePeopleController
     [Consumes("application/x-www-form-urlencoded")]
     public EmployeeFullDto ChangeUserPasswordFromForm(Guid userid, [FromForm] MemberRequestDto memberModel)
     {
-        return ChangeUserPassword(userid, memberModel);
+        return _userControllerEngine.ChangeUserPassword(userid, memberModel);
     }
 
     [Delete("{userid}")]
     public EmployeeFullDto DeleteMember(string userid)
     {
-        PermissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
-
-        var user = GetUserInfo(userid);
-
-        if (UserManager.IsSystemUser(user.ID) || user.IsLDAP())
-        {
-            throw new SecurityException();
-        }
-
-        if (user.Status != EmployeeStatus.Terminated)
-        {
-            throw new Exception("The user is not suspended");
-        }
-
-        CheckReassignProccess(new[] { user.ID });
-
-        var userName = user.DisplayUserName(false, DisplayUserSettingsHelper);
-        UserPhotoManager.RemovePhoto(user.ID);
-        UserManager.DeleteUser(user.ID);
-        _queueWorkerRemove.Start(Tenant.TenantId, user, SecurityContext.CurrentAccount.ID, false);
-
-        MessageService.Send(MessageAction.UserDeleted, MessageTarget.Create(user.ID), userName);
-
-        return _employeeFullDtoHelper.GetFull(user);
+        return _userControllerEngine.DeleteMember(userid);
     }
 
     [Delete("@self")]
     [Authorize(AuthenticationSchemes = "confirm", Roles = "ProfileRemove")]
     public EmployeeFullDto DeleteProfile()
     {
-        ApiContext.AuthByClaim();
-
-        if (UserManager.IsSystemUser(SecurityContext.CurrentAccount.ID))
-        {
-            throw new SecurityException();
-        }
-
-        var user = GetUserInfo(SecurityContext.CurrentAccount.ID.ToString());
-
-        if (!UserManager.UserExists(user))
-        {
-            throw new Exception(Resource.ErrorUserNotFound);
-        }
-
-        if (user.IsLDAP())
-        {
-            throw new SecurityException();
-        }
-
-        SecurityContext.AuthenticateMeWithoutCookie(ASC.Core.Configuration.Constants.CoreSystem);
-        user.Status = EmployeeStatus.Terminated;
-
-        UserManager.SaveUserInfo(user);
-        var userName = user.DisplayUserName(false, DisplayUserSettingsHelper);
-        MessageService.Send(MessageAction.UsersUpdatedStatus, MessageTarget.Create(user.ID), userName);
-
-        _cookiesManager.ResetUserCookie(user.ID);
-        MessageService.Send(MessageAction.CookieSettingsUpdated);
-
-        if (_coreBaseSettings.Personal)
-        {
-            UserPhotoManager.RemovePhoto(user.ID);
-            UserManager.DeleteUser(user.ID);
-            MessageService.Send(MessageAction.UserDeleted, MessageTarget.Create(user.ID), userName);
-        }
-        else
-        {
-            //StudioNotifyService.Instance.SendMsgProfileHasDeletedItself(user);
-            //StudioNotifyService.SendMsgProfileDeletion(Tenant.TenantId, user);
-        }
-
-        return _employeeFullDtoHelper.GetFull(user);
+        return _userControllerEngine.DeleteProfile();
     }
 
     [Read("status/{status}/search")]
     public IEnumerable<EmployeeFullDto> GetAdvanced(EmployeeStatus status, [FromQuery] string query)
     {
-        if (_coreBaseSettings.Personal)
-        {
-            throw new MethodAccessException("Method not available");
-        }
-        try
-        {
-            var list = UserManager.GetUsers(status).AsEnumerable();
-
-            if ("group".Equals(ApiContext.FilterBy, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(ApiContext.FilterValue))
-            {
-                var groupId = new Guid(ApiContext.FilterValue);
-                //Filter by group
-                list = list.Where(x => UserManager.IsUserInGroup(x.ID, groupId));
-                ApiContext.SetDataFiltered();
-            }
-
-            list = list.Where(x => x.FirstName != null && x.FirstName.IndexOf(query, StringComparison.OrdinalIgnoreCase) > -1 || (x.LastName != null && x.LastName.IndexOf(query, StringComparison.OrdinalIgnoreCase) != -1) ||
-                                   (x.UserName != null && x.UserName.IndexOf(query, StringComparison.OrdinalIgnoreCase) != -1) || (x.Email != null && x.Email.IndexOf(query, StringComparison.OrdinalIgnoreCase) != -1) || (x.ContactsList != null && x.ContactsList.Any(y => y.IndexOf(query, StringComparison.OrdinalIgnoreCase) != -1)));
-
-            return list.Select(u => _employeeFullDtoHelper.GetFull(u));
-        }
-        catch (Exception error)
-        {
-            _logger.Error(error);
-        }
-
-        return null;
+        return _userControllerEngine.GetAdvanced(status, query);
     }
 
     [Read]
@@ -253,83 +82,33 @@ public class UserController : BasePeopleController
     [Read("email")]
     public EmployeeFullDto GetByEmail([FromQuery] string email)
     {
-        if (_coreBaseSettings.Personal && !UserManager.GetUsers(SecurityContext.CurrentAccount.ID).IsOwner(Tenant))
-        {
-            throw new MethodAccessException("Method not available");
-        }
-
-        var user = UserManager.GetUserByEmail(email);
-        if (user.ID == Constants.LostUser.ID)
-        {
-            throw new ItemNotFoundException("User not found");
-        }
-
-        return _employeeFullDtoHelper.GetFull(user);
+        return _userControllerEngine.GetByEmail(email);
     }
 
     [Read("{username}", order: int.MaxValue)]
     public EmployeeFullDto GetById(string username)
     {
-        if (_coreBaseSettings.Personal)
-        {
-            throw new MethodAccessException("Method not available");
-        }
-
-        var user = UserManager.GetUserByUserName(username);
-        if (user.ID == Constants.LostUser.ID)
-        {
-            if (Guid.TryParse(username, out var userId))
-            {
-                user = UserManager.GetUsers(userId);
-            }
-            else
-            {
-                _logger.Error(string.Format("Account {0} сould not get user by name {1}", SecurityContext.CurrentAccount.ID, username));
-            }
-        }
-
-        if (user.ID == Constants.LostUser.ID)
-        {
-            throw new ItemNotFoundException("User not found");
-        }
-
-        return _employeeFullDtoHelper.GetFull(user);
+        return _userControllerEngine.GetById(username);
     }
 
     [Read("status/{status}")]
     public IEnumerable<EmployeeDto> GetByStatus(EmployeeStatus status)
     {
-        if (_coreBaseSettings.Personal)
-        {
-            throw new Exception("Method not available");
-        }
-
-        Guid? groupId = null;
-        if ("group".Equals(ApiContext.FilterBy, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(ApiContext.FilterValue))
-        {
-            groupId = new Guid(ApiContext.FilterValue);
-            ApiContext.SetDataFiltered();
-        }
-
-        return GetFullByFilter(status, groupId, null, null, null);
+        return _userControllerEngine.GetByStatus(status);
     }
 
     [Read("filter")]
     public IEnumerable<EmployeeFullDto> GetFullByFilter(EmployeeStatus? employeeStatus, Guid? groupId, EmployeeActivationStatus? activationStatus, EmployeeType? employeeType, bool? isAdministrator)
     {
-        var users = GetByFilter(employeeStatus, groupId, activationStatus, employeeType, isAdministrator).AsEnumerable();
-
-        return users.Select(u => _employeeFullDtoHelper.GetFull(u));
+        return _userControllerEngine.GetFullByFilter(employeeStatus, groupId, activationStatus, employeeType, isAdministrator);
     }
 
     [Read("info")]
     public Module GetModule()
     {
-        var product = new PeopleProduct();
-        product.Init();
-
-        return new Module(product);
+        return _userControllerEngine.GetModule();
     }
+
     [Read("search")]
     public IEnumerable<EmployeeFullDto> GetPeopleSearch([FromQuery] string query)
     {
@@ -339,100 +118,72 @@ public class UserController : BasePeopleController
     [Read("@search/{query}")]
     public IEnumerable<EmployeeFullDto> GetSearch(string query)
     {
-        if (_coreBaseSettings.Personal)
-        {
-            throw new MethodAccessException("Method not available");
-        }
-
-        try
-        {
-            var groupId = Guid.Empty;
-            if ("group".Equals(ApiContext.FilterBy, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(ApiContext.FilterValue))
-            {
-                groupId = new Guid(ApiContext.FilterValue);
-            }
-
-            var users = UserManager.Search(query, EmployeeStatus.Active, groupId);
-
-            return users.Select(u => _employeeFullDtoHelper.GetFull(u));
-        }
-        catch (Exception error)
-        {
-            _logger.Error(error);
-        }
-
-        return null;
+        return _userControllerEngine.GetSearch(query);
     }
 
     [Read("simple/filter")]
     public IEnumerable<EmployeeDto> GetSimpleByFilter(EmployeeStatus? employeeStatus, Guid? groupId, EmployeeActivationStatus? activationStatus, EmployeeType? employeeType, bool? isAdministrator)
     {
-        var users = GetByFilter(employeeStatus, groupId, activationStatus, employeeType, isAdministrator);
-
-        return users.Select(u => _employeeDtoHelper.Get(u));
+        return _userControllerEngine.GetSimpleByFilter(employeeStatus, groupId, activationStatus, employeeType, isAdministrator);
     }
 
     [AllowAnonymous]
     [Create(@"register")]
     public Task<string> RegisterUserOnPersonalAsync(RegisterPersonalUserRequestDto model)
     {
-        if (!_coreBaseSettings.Personal) throw new MethodAccessException("Method is only available on personal.onlyoffice.com");
-
-        return InternalRegisterUserOnPersonalAsync(model);
+        return _userControllerEngine.RegisterUserOnPersonalAsync(model, Request);
     }
 
     [Update("delete", Order = -1)]
     public IEnumerable<EmployeeFullDto> RemoveUsersFromBody([FromBody] UpdateMembersRequestDto model)
     {
-        return RemoveUsers(model);
+        return _userControllerEngine.RemoveUsers(model);
     }
 
     [Update("delete", Order = -1)]
     [Consumes("application/x-www-form-urlencoded")]
     public IEnumerable<EmployeeFullDto> RemoveUsersFromForm([FromForm] UpdateMembersRequestDto model)
     {
-        return RemoveUsers(model);
+        return _userControllerEngine.RemoveUsers(model);
     }
 
     [Update("invite")]
     public IEnumerable<EmployeeFullDto> ResendUserInvitesFromBody([FromBody] UpdateMembersRequestDto model)
     {
-        return ResendUserInvites(model);
+        return _userControllerEngine.ResendUserInvites(model);
     }
 
     [Update("invite")]
     [Consumes("application/x-www-form-urlencoded")]
     public IEnumerable<EmployeeFullDto> ResendUserInvitesFromForm([FromForm] UpdateMembersRequestDto model)
     {
-        return ResendUserInvites(model);
+        return _userControllerEngine.ResendUserInvites(model);
     }
 
     [Read("@self")]
     public EmployeeDto Self()
     {
-        var user = UserManager.GetUser(SecurityContext.CurrentAccount.ID, EmployeeFullDtoHelper.GetExpression(ApiContext));
-
-        return _employeeFullDtoHelper.GetFull(user);
+        return _userControllerEngine.Self();
     }
 
     [Create("email", false)]
     public object SendEmailChangeInstructionsFromBody([FromBody] UpdateMemberRequestDto model)
     {
-        return SendEmailChangeInstructions(model);
+        return _userControllerEngine.SendEmailChangeInstructions(model);
     }
 
     [Create("email", false)]
     [Consumes("application/x-www-form-urlencoded")]
     public object SendEmailChangeInstructionsFromForm([FromForm] UpdateMemberRequestDto model)
     {
-        return SendEmailChangeInstructions(model);
+        return _userControllerEngine.SendEmailChangeInstructions(model);
     }
 
     [AllowAnonymous]
     [Create("password", false)]
     public object SendUserPasswordFromBody([FromBody] MemberRequestDto memberModel)
     {
-        return SendUserPassword(memberModel);
+        return _userControllerEngine.SendUserPassword(memberModel);
     }
 
     [AllowAnonymous]
@@ -440,14 +191,14 @@ public class UserController : BasePeopleController
     [Consumes("application/x-www-form-urlencoded")]
     public object SendUserPasswordFromForm([FromForm] MemberRequestDto memberModel)
     {
-        return SendUserPassword(memberModel);
+        return _userControllerEngine.SendUserPassword(memberModel);
     }
 
     [Update("activationstatus/{activationstatus}")]
     [Authorize(AuthenticationSchemes = "confirm", Roles = "Activation,Everyone")]
     public IEnumerable<EmployeeFullDto> UpdateEmployeeActivationStatusFromBody(EmployeeActivationStatus activationstatus, [FromBody] UpdateMembersRequestDto model)
     {
-        return UpdateEmployeeActivationStatus(activationstatus, model);
+        return _userControllerEngine.UpdateEmployeeActivationStatus(activationstatus, model);
     }
 
     [Update("activationstatus/{activationstatus}")]
@@ -455,817 +206,61 @@ public class UserController : BasePeopleController
     [Consumes("application/x-www-form-urlencoded")]
     public IEnumerable<EmployeeFullDto> UpdateEmployeeActivationStatusFromForm(EmployeeActivationStatus activationstatus, [FromForm] UpdateMembersRequestDto model)
     {
-        return UpdateEmployeeActivationStatus(activationstatus, model);
+        return _userControllerEngine.UpdateEmployeeActivationStatus(activationstatus, model);
     }
 
     [Update("{userid}/culture")]
     public EmployeeFullDto UpdateMemberCultureFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
     {
-        return UpdateMemberCulture(userid, memberModel);
+        return _userControllerEngine.UpdateMemberCulture(userid, memberModel);
     }
 
     [Update("{userid}/culture")]
     [Consumes("application/x-www-form-urlencoded")]
     public EmployeeFullDto UpdateMemberCultureFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
     {
-        return UpdateMemberCulture(userid, memberModel);
+        return _userControllerEngine.UpdateMemberCulture(userid, memberModel);
     }
 
     [Update("{userid}")]
     public EmployeeFullDto UpdateMemberFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
     {
-        return UpdateMember(userid, memberModel);
+        return _userControllerEngine.UpdateMember(userid, memberModel);
     }
 
     [Update("{userid}")]
     [Consumes("application/x-www-form-urlencoded")]
     public EmployeeFullDto UpdateMemberFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
     {
-        return UpdateMember(userid, memberModel);
+        return _userControllerEngine.UpdateMember(userid, memberModel);
     }
 
     [Update("status/{status}")]
     public IEnumerable<EmployeeFullDto> UpdateUserStatusFromBody(EmployeeStatus status, [FromBody] UpdateMembersRequestDto model)
     {
-        return UpdateUserStatus(status, model);
+        return _userControllerEngine.UpdateUserStatus(status, model);
     }
 
     [Update("status/{status}")]
     [Consumes("application/x-www-form-urlencoded")]
     public IEnumerable<EmployeeFullDto> UpdateUserStatusFromForm(EmployeeStatus status, [FromForm] UpdateMembersRequestDto model)
     {
-        return UpdateUserStatus(status, model);
+        return _userControllerEngine.UpdateUserStatus(status, model);
     }
 
     [Update("type/{type}")]
     public IEnumerable<EmployeeFullDto> UpdateUserTypeFromBody(EmployeeType type, [FromBody] UpdateMembersRequestDto model)
     {
-        return UpdateUserType(type, model);
+        return _userControllerEngine.UpdateUserType(type, model);
     }
 
     [Update("type/{type}")]
     [Consumes("application/x-www-form-urlencoded")]
     public IEnumerable<EmployeeFullDto> UpdateUserTypeFromForm(EmployeeType type, [FromForm] UpdateMembersRequestDto model)
     {
-        return UpdateUserType(type, model);
-    }
+        return _userControllerEngine.UpdateUserType(type, model);
+    } 
 
-    private EmployeeFullDto AddMember(MemberRequestDto memberModel)
-    {
-        ApiContext.AuthByClaim();
-
-        PermissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
-
-        memberModel.PasswordHash = (memberModel.PasswordHash ?? "").Trim();
-        if (string.IsNullOrEmpty(memberModel.PasswordHash))
-        {
-            memberModel.Password = (memberModel.Password ?? "").Trim();
-
-            if (string.IsNullOrEmpty(memberModel.Password))
-            {
-                memberModel.Password = UserManagerWrapper.GeneratePassword();
-            }
-            else
-            {
-                _userManagerWrapper.CheckPasswordPolicy(memberModel.Password);
-            }
-            memberModel.PasswordHash = _passwordHasher.GetClientPassword(memberModel.Password);
-        }
-
-        var user = new UserInfo();
-
-        //Validate email
-        var address = new MailAddress(memberModel.Email);
-        user.Email = address.Address;
-        //Set common fields
-        user.FirstName = memberModel.Firstname;
-        user.LastName = memberModel.Lastname;
-        user.Title = memberModel.Title;
-        user.Location = memberModel.Location;
-        user.Notes = memberModel.Comment;
-        user.Sex = "male".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase)
-                       ? true
-                       : ("female".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase) ? (bool?)false : null);
-
-        user.BirthDate = memberModel.Birthday != null && memberModel.Birthday != DateTime.MinValue ? _tenantUtil.DateTimeFromUtc(memberModel.Birthday) : null;
-        user.WorkFromDate = memberModel.Worksfrom != null && memberModel.Worksfrom != DateTime.MinValue ? _tenantUtil.DateTimeFromUtc(memberModel.Worksfrom) : DateTime.UtcNow.Date;
-
-        UpdateContacts(memberModel.Contacts, user);
-
-        user = _userManagerWrapper.AddUser(user, memberModel.PasswordHash, memberModel.FromInviteLink, true, memberModel.IsVisitor, memberModel.FromInviteLink);
-
-        var messageAction = memberModel.IsVisitor ? MessageAction.GuestCreated : MessageAction.UserCreated;
-        MessageService.Send(messageAction, MessageTarget.Create(user.ID), user.DisplayUserName(false, DisplayUserSettingsHelper));
-
-        UpdateDepartments(memberModel.Department, user);
-
-        if (memberModel.Files != UserPhotoManager.GetDefaultPhotoAbsoluteWebPath())
-        {
-            UpdatePhotoUrl(memberModel.Files, user);
-        }
-
-        return _employeeFullDtoHelper.GetFull(user);
-    }
-
-    private EmployeeFullDto AddMemberAsActivated(MemberRequestDto memberModel)
-    {
-        PermissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
-
-        var user = new UserInfo();
-
-        memberModel.PasswordHash = (memberModel.PasswordHash ?? "").Trim();
-        if (string.IsNullOrEmpty(memberModel.PasswordHash))
-        {
-            memberModel.Password = (memberModel.Password ?? "").Trim();
-
-            if (string.IsNullOrEmpty(memberModel.Password))
-            {
-                memberModel.Password = UserManagerWrapper.GeneratePassword();
-            }
-            else
-            {
-                _userManagerWrapper.CheckPasswordPolicy(memberModel.Password);
-            }
-
-            memberModel.PasswordHash = _passwordHasher.GetClientPassword(memberModel.Password);
-        }
-
-        //Validate email
-        var address = new MailAddress(memberModel.Email);
-        user.Email = address.Address;
-        //Set common fields
-        user.FirstName = memberModel.Firstname;
-        user.LastName = memberModel.Lastname;
-        user.Title = memberModel.Title;
-        user.Location = memberModel.Location;
-        user.Notes = memberModel.Comment;
-        user.Sex = "male".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase)
-                       ? true
-                       : ("female".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase) ? (bool?)false : null);
-
-        user.BirthDate = memberModel.Birthday != null ? _tenantUtil.DateTimeFromUtc(memberModel.Birthday) : null;
-        user.WorkFromDate = memberModel.Worksfrom != null ? _tenantUtil.DateTimeFromUtc(memberModel.Worksfrom) : DateTime.UtcNow.Date;
-
-        UpdateContacts(memberModel.Contacts, user);
-
-        user = _userManagerWrapper.AddUser(user, memberModel.PasswordHash, false, false, memberModel.IsVisitor);
-
-        user.ActivationStatus = EmployeeActivationStatus.Activated;
-
-        UpdateDepartments(memberModel.Department, user);
-
-        if (memberModel.Files != UserPhotoManager.GetDefaultPhotoAbsoluteWebPath())
-        {
-            UpdatePhotoUrl(memberModel.Files, user);
-        }
-
-        return _employeeFullDtoHelper.GetFull(user);
-    }
-
-    private EmployeeFullDto ChangeUserPassword(Guid userid, MemberRequestDto memberModel)
-    {
-        ApiContext.AuthByClaim();
-        PermissionContext.DemandPermissions(new UserSecurityProvider(userid), Constants.Action_EditUser);
-
-        var user = UserManager.GetUsers(userid);
-
-        if (!UserManager.UserExists(user))
-        {
-            return null;
-        }
-
-        if (UserManager.IsSystemUser(user.ID))
-        {
-            throw new SecurityException();
-        }
-
-        if (!string.IsNullOrEmpty(memberModel.Email))
-        {
-            var address = new MailAddress(memberModel.Email);
-            if (!string.Equals(address.Address, user.Email, StringComparison.OrdinalIgnoreCase))
-            {
-                user.Email = address.Address.ToLowerInvariant();
-                user.ActivationStatus = EmployeeActivationStatus.Activated;
-                UserManager.SaveUserInfo(user);
-            }
-        }
-
-        memberModel.PasswordHash = (memberModel.PasswordHash ?? "").Trim();
-        if (string.IsNullOrEmpty(memberModel.PasswordHash))
-        {
-            memberModel.Password = (memberModel.Password ?? "").Trim();
-
-            if (!string.IsNullOrEmpty(memberModel.Password))
-            {
-                memberModel.PasswordHash = _passwordHasher.GetClientPassword(memberModel.Password);
-            }
-        }
-
-        if (!string.IsNullOrEmpty(memberModel.PasswordHash))
-        {
-            SecurityContext.SetUserPasswordHash(userid, memberModel.PasswordHash);
-            MessageService.Send(MessageAction.UserUpdatedPassword);
-
-            _cookiesManager.ResetUserCookie(userid);
-            MessageService.Send(MessageAction.CookieSettingsUpdated);
-        }
-
-        return _employeeFullDtoHelper.GetFull(GetUserInfo(userid.ToString()));
-    }
-
-    private void CheckReassignProccess(IEnumerable<Guid> userIds)
-    {
-        foreach (var userId in userIds)
-        {
-            var reassignStatus = _queueWorkerReassign.GetProgressItemStatus(Tenant.TenantId, userId);
-            if (reassignStatus == null || reassignStatus.IsCompleted)
-            {
-                continue;
-            }
-
-            var userName = UserManager.GetUsers(userId).DisplayUserName(DisplayUserSettingsHelper);
-
-            throw new Exception(string.Format(Resource.ReassignDataRemoveUserError, userName));
-        }
-    }
-
-    private IQueryable<UserInfo> GetByFilter(EmployeeStatus? employeeStatus, Guid? groupId, EmployeeActivationStatus? activationStatus, EmployeeType? employeeType, bool? isAdministrator)
-    {
-        if (_coreBaseSettings.Personal)
-        {
-            throw new MethodAccessException("Method not available");
-        }
-
-        var isAdmin = UserManager.GetUsers(SecurityContext.CurrentAccount.ID).IsAdmin(UserManager) ||
-                      _webItemSecurity.IsProductAdministrator(WebItemManager.PeopleProductID, SecurityContext.CurrentAccount.ID);
-
-        var includeGroups = new List<List<Guid>>();
-        if (groupId.HasValue)
-        {
-            includeGroups.Add(new List<Guid> { groupId.Value });
-        }
-
-        var excludeGroups = new List<Guid>();
-
-        if (employeeType != null)
-        {
-            switch (employeeType)
-            {
-                case EmployeeType.User:
-                    excludeGroups.Add(Constants.GroupVisitor.ID);
-                    break;
-                case EmployeeType.Visitor:
-                    includeGroups.Add(new List<Guid> { Constants.GroupVisitor.ID });
-                    break;
-            }
-        }
-
-        if (isAdministrator.HasValue && isAdministrator.Value)
-        {
-            var adminGroups = new List<Guid>
-            {
-                    Constants.GroupAdmin.ID
-            };
-            var products = _webItemManager.GetItemsAll().Where(i => i is IProduct || i.ID == WebItemManager.MailProductID);
-            adminGroups.AddRange(products.Select(r => r.ID));
-
-            includeGroups.Add(adminGroups);
-        }
-
-        var users = UserManager.GetUsers(isAdmin, employeeStatus, includeGroups, excludeGroups, activationStatus, ApiContext.FilterValue, ApiContext.SortBy, !ApiContext.SortDescending, ApiContext.Count, ApiContext.StartIndex, out var total, out var count);
-
-        ApiContext.SetTotalCount(total).SetCount(count);
-
-        return users;
-    }
-
-    private async Task<string> InternalRegisterUserOnPersonalAsync(RegisterPersonalUserRequestDto model)
-    {
-        try
-        {
-            if (_coreBaseSettings.CustomMode) model.Lang = "ru-RU";
-
-            var cultureInfo = SetupInfo.GetPersonalCulture(model.Lang).Value;
-
-            if (cultureInfo != null)
-            {
-                Thread.CurrentThread.CurrentUICulture = cultureInfo;
-            }
-
-            model.Email.ThrowIfNull(new ArgumentException(Resource.ErrorEmailEmpty, "email"));
-
-            if (!model.Email.TestEmailRegex()) throw new ArgumentException(Resource.ErrorNotCorrectEmail, "email");
-
-            if (!SetupInfo.IsSecretEmail(model.Email)
-                && !string.IsNullOrEmpty(SetupInfo.RecaptchaPublicKey) && !string.IsNullOrEmpty(SetupInfo.RecaptchaPrivateKey))
-            {
-                var ip = Request.Headers["X-Forwarded-For"].ToString() ?? Request.GetUserHostAddress();
-
-                if (string.IsNullOrEmpty(model.RecaptchaResponse)
-                    || !await _recaptcha.ValidateRecaptchaAsync(model.RecaptchaResponse, ip))
-                {
-                    throw new RecaptchaException(Resource.RecaptchaInvalid);
-                }
-            }
-
-            var newUserInfo = UserManager.GetUserByEmail(model.Email);
-
-            if (UserManager.UserExists(newUserInfo.ID))
-            {
-                if (!SetupInfo.IsSecretEmail(model.Email) || SecurityContext.IsAuthenticated)
-                {
-                    StudioNotifyService.SendAlreadyExist(model.Email);
-                    return string.Empty;
-                }
-
-                try
-                {
-                    SecurityContext.AuthenticateMe(ASC.Core.Configuration.Constants.CoreSystem);
-                    UserManager.DeleteUser(newUserInfo.ID);
-                }
-                finally
-                {
-                    SecurityContext.Logout();
-                }
-            }
-            if (!model.Spam)
-            {
-                try
-                {
-                    //TODO
-                    //const string _databaseID = "com";
-                    //using (var db = DbManager.FromHttpContext(_databaseID))
-                    //{
-                    //    db.ExecuteNonQuery(new SqlInsert("template_unsubscribe", false)
-                    //                           .InColumnValue("email", email.ToLowerInvariant())
-                    //                           .InColumnValue("reason", "personal")
-                    //        );
-                    //    Log.Debug(String.Format("Write to template_unsubscribe {0}", email.ToLowerInvariant()));
-                    //}
-                }
-                catch (Exception ex)
-                {
-                    _logger.Debug($"ERROR write to template_unsubscribe {ex.Message}, email:{model.Email.ToLowerInvariant()}");
-                }
-            }
-
-            StudioNotifyService.SendInvitePersonal(model.Email);
-        }
-        catch (Exception ex)
-        {
-            return ex.Message;
-        }
-
-        return string.Empty;
-    }
-    private IEnumerable<EmployeeFullDto> RemoveUsers(UpdateMembersRequestDto model)
-    {
-        PermissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
-
-        CheckReassignProccess(model.UserIds);
-
-        var users = model.UserIds.Select(userId => UserManager.GetUsers(userId))
-            .Where(u => !UserManager.IsSystemUser(u.ID) && !u.IsLDAP())
-            .ToList();
-
-        var userNames = users.Select(x => x.DisplayUserName(false, DisplayUserSettingsHelper)).ToList();
-
-        foreach (var user in users)
-        {
-            if (user.Status != EmployeeStatus.Terminated)
-            {
-                continue;
-            }
-
-            UserPhotoManager.RemovePhoto(user.ID);
-            UserManager.DeleteUser(user.ID);
-            _queueWorkerRemove.Start(Tenant.TenantId, user, SecurityContext.CurrentAccount.ID, false);
-        }
-
-        MessageService.Send(MessageAction.UsersDeleted, MessageTarget.Create(users.Select(x => x.ID)), userNames);
-
-        return users.Select(u => _employeeFullDtoHelper.GetFull(u));
-    }
-
-    private IEnumerable<EmployeeFullDto> ResendUserInvites(UpdateMembersRequestDto model)
-    {
-        var users = model.UserIds
-            .Where(userId => !UserManager.IsSystemUser(userId))
-            .Select(userId => UserManager.GetUsers(userId))
-            .ToList();
-
-        foreach (var user in users)
-        {
-            if (user.IsActive)
-            {
-                continue;
-            }
-
-            var viewer = UserManager.GetUsers(SecurityContext.CurrentAccount.ID);
-
-            if (viewer == null)
-            {
-                throw new Exception(Resource.ErrorAccessDenied);
-            }
-
-            if (viewer.IsAdmin(UserManager) || viewer.ID == user.ID)
-            {
-                if (user.ActivationStatus == EmployeeActivationStatus.Activated)
-                {
-                    user.ActivationStatus = EmployeeActivationStatus.NotActivated;
-                }
-                if (user.ActivationStatus == (EmployeeActivationStatus.AutoGenerated | EmployeeActivationStatus.Activated))
-                {
-                    user.ActivationStatus = EmployeeActivationStatus.AutoGenerated;
-                }
-
-                UserManager.SaveUserInfo(user);
-            }
-
-            if (user.ActivationStatus == EmployeeActivationStatus.Pending)
-            {
-                if (user.IsVisitor(UserManager))
-                {
-                    StudioNotifyService.GuestInfoActivation(user);
-                }
-                else
-                {
-                    StudioNotifyService.UserInfoActivation(user);
-                }
-            }
-            else
-            {
-                StudioNotifyService.SendEmailActivationInstructions(user, user.Email);
-            }
-        }
-
-        MessageService.Send(MessageAction.UsersSentActivationInstructions, MessageTarget.Create(users.Select(x => x.ID)), users.Select(x => x.DisplayUserName(false, DisplayUserSettingsHelper)));
-
-        return users.Select(u => _employeeFullDtoHelper.GetFull(u));
-    }
-
-    private object SendEmailChangeInstructions(UpdateMemberRequestDto model)
-    {
-        Guid.TryParse(model.UserId, out var userid);
-
-        if (userid == Guid.Empty)
-        {
-            throw new ArgumentNullException("userid");
-        }
-
-        var email = (model.Email ?? "").Trim();
-
-        if (string.IsNullOrEmpty(email))
-        {
-            throw new Exception(Resource.ErrorEmailEmpty);
-        }
-
-        if (!email.TestEmailRegex())
-        {
-            throw new Exception(Resource.ErrorNotCorrectEmail);
-        }
-
-        var viewer = UserManager.GetUsers(SecurityContext.CurrentAccount.ID);
-        var user = UserManager.GetUsers(userid);
-
-        if (user == null)
-        {
-            throw new Exception(Resource.ErrorUserNotFound);
-        }
-
-        if (viewer == null || (user.IsOwner(Tenant) && viewer.ID != user.ID))
-        {
-            throw new Exception(Resource.ErrorAccessDenied);
-        }
-
-        var existentUser = UserManager.GetUserByEmail(email);
-
-        if (existentUser.ID != Constants.LostUser.ID)
-        {
-            throw new Exception(_customNamingPeople.Substitute<Resource>("ErrorEmailAlreadyExists"));
-        }
-
-        if (!viewer.IsAdmin(UserManager))
-        {
-            StudioNotifyService.SendEmailChangeInstructions(user, email);
-        }
-        else
-        {
-            if (email == user.Email)
-            {
-                throw new Exception(Resource.ErrorEmailsAreTheSame);
-            }
-
-            user.Email = email;
-            user.ActivationStatus = EmployeeActivationStatus.NotActivated;
-            UserManager.SaveUserInfo(user);
-            StudioNotifyService.SendEmailActivationInstructions(user, email);
-        }
-
-        MessageService.Send(MessageAction.UserSentEmailChangeInstructions, user.DisplayUserName(false, DisplayUserSettingsHelper));
-
-        return string.Format(Resource.MessageEmailChangeInstuctionsSentOnEmail, email);
-    }
-
-    private object SendUserPassword(MemberRequestDto memberModel)
-    {
-        string error = _userManagerWrapper.SendUserPassword(memberModel.Email);
-        if (!string.IsNullOrEmpty(error))
-        {
-            _logger.ErrorFormat("Password recovery ({0}): {1}", memberModel.Email, error);
-        }
-
-        return string.Format(Resource.MessageYourPasswordSendedToEmail, memberModel.Email);
-    }
-
-    private void UpdateDepartments(IEnumerable<Guid> department, UserInfo user)
-    {
-        if (!PermissionContext.CheckPermissions(Constants.Action_EditGroups))
-        {
-            return;
-        }
-
-        if (department == null)
-        {
-            return;
-        }
-
-        var groups = UserManager.GetUserGroups(user.ID);
-        var managerGroups = new List<Guid>();
-        foreach (var groupInfo in groups)
-        {
-            UserManager.RemoveUserFromGroup(user.ID, groupInfo.ID);
-            var managerId = UserManager.GetDepartmentManager(groupInfo.ID);
-            if (managerId == user.ID)
-            {
-                managerGroups.Add(groupInfo.ID);
-                UserManager.SetDepartmentManager(groupInfo.ID, Guid.Empty);
-            }
-        }
-        foreach (var guid in department)
-        {
-            var userDepartment = UserManager.GetGroupInfo(guid);
-            if (userDepartment != Constants.LostGroupInfo)
-            {
-                UserManager.AddUserIntoGroup(user.ID, guid);
-                if (managerGroups.Contains(guid))
-                {
-                    UserManager.SetDepartmentManager(guid, user.ID);
-                }
-            }
-        }
-    }
-
-    private IEnumerable<EmployeeFullDto> UpdateEmployeeActivationStatus(EmployeeActivationStatus activationstatus, UpdateMembersRequestDto model)
-    {
-        ApiContext.AuthByClaim();
-
-        var retuls = new List<EmployeeFullDto>();
-        foreach (var id in model.UserIds.Where(userId => !UserManager.IsSystemUser(userId)))
-        {
-            PermissionContext.DemandPermissions(new UserSecurityProvider(id), Constants.Action_EditUser);
-            var u = UserManager.GetUsers(id);
-            if (u.ID == Constants.LostUser.ID || u.IsLDAP())
-            {
-                continue;
-            }
-
-            u.ActivationStatus = activationstatus;
-            UserManager.SaveUserInfo(u);
-            retuls.Add(_employeeFullDtoHelper.GetFull(u));
-        }
-
-        return retuls;
-    }
-
-    private EmployeeFullDto UpdateMember(string userid, UpdateMemberRequestDto memberModel)
-    {
-        var user = GetUserInfo(userid);
-
-        if (UserManager.IsSystemUser(user.ID))
-        {
-            throw new SecurityException();
-        }
-
-        PermissionContext.DemandPermissions(new UserSecurityProvider(user.ID), Constants.Action_EditUser);
-        var self = SecurityContext.CurrentAccount.ID.Equals(user.ID);
-        var resetDate = new DateTime(1900, 01, 01);
-
-        //Update it
-
-        var isLdap = user.IsLDAP();
-        var isSso = user.IsSSO();
-        var isAdmin = _webItemSecurity.IsProductAdministrator(WebItemManager.PeopleProductID, SecurityContext.CurrentAccount.ID);
-
-        if (!isLdap && !isSso)
-        {
-            //Set common fields
-
-            user.FirstName = memberModel.Firstname ?? user.FirstName;
-            user.LastName = memberModel.Lastname ?? user.LastName;
-            user.Location = memberModel.Location ?? user.Location;
-
-            if (isAdmin)
-            {
-                user.Title = memberModel.Title ?? user.Title;
-            }
-        }
-
-        if (!_userFormatter.IsValidUserName(user.FirstName, user.LastName))
-        {
-            throw new Exception(Resource.ErrorIncorrectUserName);
-        }
-
-        user.Notes = memberModel.Comment ?? user.Notes;
-        user.Sex = ("male".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase)
-            ? true
-            : ("female".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase) ? (bool?)false : null)) ?? user.Sex;
-
-        user.BirthDate = memberModel.Birthday != null ? _tenantUtil.DateTimeFromUtc(memberModel.Birthday) : user.BirthDate;
-
-        if (user.BirthDate == resetDate)
-        {
-            user.BirthDate = null;
-        }
-
-        user.WorkFromDate = memberModel.Worksfrom != null ? _tenantUtil.DateTimeFromUtc(memberModel.Worksfrom) : user.WorkFromDate;
-
-        if (user.WorkFromDate == resetDate)
-        {
-            user.WorkFromDate = null;
-        }
-
-        //Update contacts
-        UpdateContacts(memberModel.Contacts, user);
-        UpdateDepartments(memberModel.Department, user);
-
-        if (memberModel.Files != UserPhotoManager.GetPhotoAbsoluteWebPath(user.ID))
-        {
-            UpdatePhotoUrl(memberModel.Files, user);
-        }
-        if (memberModel.Disable.HasValue)
-        {
-            user.Status = memberModel.Disable.Value ? EmployeeStatus.Terminated : EmployeeStatus.Active;
-            user.TerminatedDate = memberModel.Disable.Value ? DateTime.UtcNow : null;
-        }
-        if (self && !isAdmin)
-        {
-            StudioNotifyService.SendMsgToAdminAboutProfileUpdated();
-        }
-
-        // change user type
-        var canBeGuestFlag = !user.IsOwner(Tenant) && !user.IsAdmin(UserManager) && user.GetListAdminModules(_webItemSecurity).Count == 0 && !user.IsMe(AuthContext);
-
-        if (memberModel.IsVisitor && !user.IsVisitor(UserManager) && canBeGuestFlag)
-        {
-            UserManager.AddUserIntoGroup(user.ID, Constants.GroupVisitor.ID);
-            _webItemSecurityCache.ClearCache(Tenant.TenantId);
-        }
-
-        if (!self && !memberModel.IsVisitor && user.IsVisitor(UserManager))
-        {
-            var usersQuota = _tenantExtra.GetTenantQuota().ActiveUsers;
-            if (_tenantStatisticsProvider.GetUsersCount() < usersQuota)
-            {
-                UserManager.RemoveUserFromGroup(user.ID, Constants.GroupVisitor.ID);
-                _webItemSecurityCache.ClearCache(Tenant.TenantId);
-            }
-            else
-            {
-                throw new TenantQuotaException(string.Format("Exceeds the maximum active users ({0})", usersQuota));
-            }
-        }
-
-        UserManager.SaveUserInfo(user);
-        MessageService.Send(MessageAction.UserUpdated, MessageTarget.Create(user.ID), user.DisplayUserName(false, DisplayUserSettingsHelper));
-
-        if (memberModel.Disable.HasValue && memberModel.Disable.Value)
-        {
-            _cookiesManager.ResetUserCookie(user.ID);
-            MessageService.Send(MessageAction.CookieSettingsUpdated);
-        }
-
-        return _employeeFullDtoHelper.GetFull(user);
-    }
-    private EmployeeFullDto UpdateMemberCulture(string userid, UpdateMemberRequestDto memberModel)
-    {
-        var user = GetUserInfo(userid);
-
-        if (UserManager.IsSystemUser(user.ID))
-        {
-            throw new SecurityException();
-        }
-
-        PermissionContext.DemandPermissions(new UserSecurityProvider(user.ID), Constants.Action_EditUser);
-
-        var curLng = user.CultureName;
-
-        if (SetupInfo.EnabledCultures.Find(c => string.Equals(c.Name, memberModel.CultureName, StringComparison.InvariantCultureIgnoreCase)) != null)
-        {
-            if (curLng != memberModel.CultureName)
-            {
-                user.CultureName = memberModel.CultureName;
-
-                try
-                {
-                    UserManager.SaveUserInfo(user);
-                }
-                catch
-                {
-                    user.CultureName = curLng;
-                    throw;
-                }
-
-                MessageService.Send(MessageAction.UserUpdatedLanguage, MessageTarget.Create(user.ID), user.DisplayUserName(false, DisplayUserSettingsHelper));
-
-            }
-        }
-
-        return _employeeFullDtoHelper.GetFull(user);
-    }
-    private IEnumerable<EmployeeFullDto> UpdateUserStatus(EmployeeStatus status, UpdateMembersRequestDto model)
-    {
-        PermissionContext.DemandPermissions(Constants.Action_EditUser);
-
-        var users = model.UserIds.Select(userId => UserManager.GetUsers(userId))
-            .Where(u => !UserManager.IsSystemUser(u.ID) && !u.IsLDAP())
-            .ToList();
-
-        foreach (var user in users)
-        {
-            if (user.IsOwner(Tenant) || user.IsMe(AuthContext))
-            {
-                continue;
-            }
-
-            switch (status)
-            {
-                case EmployeeStatus.Active:
-                    if (user.Status == EmployeeStatus.Terminated)
-                    {
-                        if (_tenantStatisticsProvider.GetUsersCount() < _tenantExtra.GetTenantQuota().ActiveUsers || user.IsVisitor(UserManager))
-                        {
-                            user.Status = EmployeeStatus.Active;
-                            UserManager.SaveUserInfo(user);
-                        }
-                    }
-                    break;
-                case EmployeeStatus.Terminated:
-                    user.Status = EmployeeStatus.Terminated;
-                    UserManager.SaveUserInfo(user);
-
-                    _cookiesManager.ResetUserCookie(user.ID);
-                    MessageService.Send(MessageAction.CookieSettingsUpdated);
-                    break;
-            }
-        }
-
-        MessageService.Send(MessageAction.UsersUpdatedStatus, MessageTarget.Create(users.Select(x => x.ID)), users.Select(x => x.DisplayUserName(false, DisplayUserSettingsHelper)));
-
-        return users.Select(u => _employeeFullDtoHelper.GetFull(u));
-    }
-
-    private IEnumerable<EmployeeFullDto> UpdateUserType(EmployeeType type, UpdateMembersRequestDto model)
-    {
-        var users = model.UserIds
-            .Where(userId => !UserManager.IsSystemUser(userId))
-            .Select(userId => UserManager.GetUsers(userId))
-            .ToList();
-
-        foreach (var user in users)
-        {
-            if (user.IsOwner(Tenant) || user.IsAdmin(UserManager)
-                || user.IsMe(AuthContext) || user.GetListAdminModules(_webItemSecurity).Count > 0)
-            {
-                continue;
-            }
-
-            switch (type)
-            {
-                case EmployeeType.User:
-                    if (user.IsVisitor(UserManager))
-                    {
-                        if (_tenantStatisticsProvider.GetUsersCount() < _tenantExtra.GetTenantQuota().ActiveUsers)
-                        {
-                            UserManager.RemoveUserFromGroup(user.ID, Constants.GroupVisitor.ID);
-                            _webItemSecurityCache.ClearCache(Tenant.TenantId);
-                        }
-                    }
-                    break;
-                case EmployeeType.Visitor:
-                    if (_coreBaseSettings.Standalone || _tenantStatisticsProvider.GetVisitorsCount() < _tenantExtra.GetTenantQuota().ActiveUsers * _constants.CoefficientOfVisitors)
-                    {
-                        UserManager.AddUserIntoGroup(user.ID, Constants.GroupVisitor.ID);
-                        _webItemSecurityCache.ClearCache(Tenant.TenantId);
-                    }
-                    break;
-            }
-        }
-
-        MessageService.Send(MessageAction.UsersUpdatedType, MessageTarget.Create(users.Select(x => x.ID)), users.Select(x => x.DisplayUserName(false, DisplayUserSettingsHelper)));
-
-        return users.Select(u => _employeeFullDtoHelper.GetFull(u));
-    }
     ///// <summary>
     ///// Adds a new portal user from import with the first and last name, email address
     ///// </summary>
diff --git a/products/ASC.People/Server/Api/BaseApiController.cs b/products/ASC.People/Server/ApiEngines/ApiControllerEngineBase.cs
similarity index 84%
rename from products/ASC.People/Server/Api/BaseApiController.cs
rename to products/ASC.People/Server/ApiEngines/ApiControllerEngineBase.cs
index 23f2027757..9195452866 100644
--- a/products/ASC.People/Server/Api/BaseApiController.cs
+++ b/products/ASC.People/Server/ApiEngines/ApiControllerEngineBase.cs
@@ -1,25 +1,19 @@
 using SecurityContext = ASC.Core.SecurityContext;
 
-namespace ASC.People.Api;
+namespace ASC.People.ApiHelpers;
 
-[Scope(Additional = typeof(BaseLoginProviderExtension))]
-[DefaultRoute]
-[ApiController]
-[ControllerName("people")]
-public class BaseApiController : ControllerBase
+public abstract class ApiControllerEngineBase
 {
-    protected Tenant Tenant => ApiContext.Tenant;
-
-    protected readonly UserManager UserManager;
-    protected readonly AuthContext AuthContext;
     protected readonly ApiContext ApiContext;
-    protected readonly PermissionContext PermissionContext;
-    protected readonly SecurityContext SecurityContext;
+    protected readonly AuthContext AuthContext;
     protected readonly MessageService MessageService;
     protected readonly MessageTarget MessageTarget;
+    protected readonly PermissionContext PermissionContext;
+    protected readonly SecurityContext SecurityContext;
     protected readonly StudioNotifyService StudioNotifyService;
+    protected readonly UserManager UserManager;
 
-    protected BaseApiController(
+    protected ApiControllerEngineBase(
         UserManager userManager,
         AuthContext authContext,
         ApiContext apiContext,
@@ -38,4 +32,6 @@ public class BaseApiController : ControllerBase
         MessageTarget = messageTarget;
         StudioNotifyService = studioNotifyService;
     }
+
+    protected Tenant Tenant => ApiContext.Tenant;
 }
\ No newline at end of file
diff --git a/products/ASC.People/Server/ApiEngines/ContactsControllerEngine.cs b/products/ASC.People/Server/ApiEngines/ContactsControllerEngine.cs
new file mode 100644
index 0000000000..9176d878be
--- /dev/null
+++ b/products/ASC.People/Server/ApiEngines/ContactsControllerEngine.cs
@@ -0,0 +1,109 @@
+using SecurityContext = ASC.Core.SecurityContext;
+
+namespace ASC.People.ApiHelpers;
+
+public class ContactsControllerEngine : PeopleControllerEngine
+{
+    private readonly EmployeeFullDtoHelper _employeeFullDtoHelper;
+
+    public ContactsControllerEngine(
+        UserManager userManager,
+        AuthContext authContext,
+        ApiContext apiContext,
+        PermissionContext permissionContext,
+        SecurityContext securityContext,
+        MessageService messageService,
+        MessageTarget messageTarget,
+        StudioNotifyService studioNotifyService,
+        UserPhotoManager userPhotoManager,
+        IHttpClientFactory httpClientFactory,
+        DisplayUserSettingsHelper displayUserSettingsHelper,
+        SetupInfo setupInfo,
+        EmployeeFullDtoHelper employeeFullDtoHelper)
+        : base(
+            userManager,
+            authContext,
+            apiContext,
+            permissionContext,
+            securityContext,
+            messageService,
+            messageTarget,
+            studioNotifyService,
+            userPhotoManager,
+            httpClientFactory,
+            displayUserSettingsHelper,
+            setupInfo)
+    {
+        _employeeFullDtoHelper = employeeFullDtoHelper;
+    }
+
+    public void DeleteContacts(IEnumerable<Contact> contacts, UserInfo user)
+    {
+        PermissionContext.DemandPermissions(new UserSecurityProvider(user.ID), Constants.Action_EditUser);
+        if (contacts == null)
+        {
+            return;
+        }
+
+        if (user.ContactsList == null)
+        {
+            user.ContactsList = new List<string>();
+        }
+
+        foreach (var contact in contacts)
+        {
+            var index = user.ContactsList.IndexOf(contact.Type);
+            if (index != -1)
+            {
+                //Remove existing
+                user.ContactsList.RemoveRange(index, 2);
+            }
+        }
+    }
+
+    public EmployeeFullDto DeleteMemberContacts(string userid, UpdateMemberRequestDto memberModel)
+    {
+        var user = GetUserInfo(userid);
+
+        if (UserManager.IsSystemUser(user.ID))
+        {
+            throw new SecurityException();
+        }
+
+        DeleteContacts(memberModel.Contacts, user);
+        UserManager.SaveUserInfo(user);
+
+        return _employeeFullDtoHelper.GetFull(user);
+    }
+
+    public EmployeeFullDto SetMemberContacts(string userid, UpdateMemberRequestDto memberModel)
+    {
+        var user = GetUserInfo(userid);
+
+        if (UserManager.IsSystemUser(user.ID))
+        {
+            throw new SecurityException();
+        }
+
+        user.ContactsList.Clear();
+        UpdateContacts(memberModel.Contacts, user);
+        UserManager.SaveUserInfo(user);
+
+        return _employeeFullDtoHelper.GetFull(user);
+    }
+
+    public EmployeeFullDto UpdateMemberContacts(string userid, UpdateMemberRequestDto memberModel)
+    {
+        var user = GetUserInfo(userid);
+
+        if (UserManager.IsSystemUser(user.ID))
+        {
+            throw new SecurityException();
+        }
+
+        UpdateContacts(memberModel.Contacts, user);
+        UserManager.SaveUserInfo(user);
+
+        return _employeeFullDtoHelper.GetFull(user);
+    }
+}
\ No newline at end of file
diff --git a/products/ASC.People/Server/ApiEngines/GroupControllerEngine.cs b/products/ASC.People/Server/ApiEngines/GroupControllerEngine.cs
new file mode 100644
index 0000000000..bfbf6958ee
--- /dev/null
+++ b/products/ASC.People/Server/ApiEngines/GroupControllerEngine.cs
@@ -0,0 +1,223 @@
+namespace ASC.People.ApiHelpers;
+
+[Scope]
+public class GroupControllerEngine
+{
+    private readonly ApiContext _apiContext;
+    private readonly MessageService _messageService;
+    private readonly UserManager _userManager;
+    private readonly PermissionContext _permissionContext;
+    private readonly MessageTarget _messageTarget;
+    private readonly GroupFullDtoHelper _groupWraperFullHelper;
+
+    public GroupControllerEngine(
+        ApiContext apiContext,
+        MessageService messageService,
+        UserManager userManager,
+        PermissionContext permissionContext,
+        MessageTarget messageTarget,
+        GroupFullDtoHelper groupWraperFullHelper)
+    {
+        _apiContext = apiContext;
+        _messageService = messageService;
+        _userManager = userManager;
+        _permissionContext = permissionContext;
+        _messageTarget = messageTarget;
+        _groupWraperFullHelper = groupWraperFullHelper;
+    }
+
+    public IEnumerable<GroupSummaryDto> GetAll()
+    {
+        var result = _userManager.GetDepartments().Select(r => r);
+        if (!string.IsNullOrEmpty(_apiContext.FilterValue))
+        {
+            result = result.Where(r => r.Name.Contains(_apiContext.FilterValue, StringComparison.InvariantCultureIgnoreCase));
+        }
+
+        return result.Select(x => new GroupSummaryDto(x, _userManager));
+    }
+
+    public IEnumerable<GroupDto> GetAllWithMembers()
+    {
+        var result = _userManager.GetDepartments().Select(r => r);
+        if (!string.IsNullOrEmpty(_apiContext.FilterValue))
+        {
+            result = result.Where(r => r.Name.Contains(_apiContext.FilterValue, StringComparison.InvariantCultureIgnoreCase));
+        }
+
+        return result.Select(r => _groupWraperFullHelper.Get(r, true));
+    }
+
+    public GroupDto GetById(Guid groupid)
+    {
+        return _groupWraperFullHelper.Get(GetGroupInfo(groupid), true);
+    }
+
+    public IEnumerable<GroupSummaryDto> GetByUserId(Guid userid)
+    {
+        return _userManager.GetUserGroups(userid).Select(x => new GroupSummaryDto(x, _userManager));
+    }
+
+    public GroupDto AddGroup(GroupRequestDto groupModel)
+    {
+        _permissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
+
+        var group = _userManager.SaveGroupInfo(new GroupInfo { Name = groupModel.GroupName });
+
+        TransferUserToDepartment(groupModel.GroupManager, @group, true);
+        if (groupModel.Members != null)
+        {
+            foreach (var member in groupModel.Members)
+            {
+                TransferUserToDepartment(member, group, false);
+            }
+        }
+
+        _messageService.Send(MessageAction.GroupCreated, _messageTarget.Create(group.ID), group.Name);
+
+        return _groupWraperFullHelper.Get(group, true);
+    }
+
+    public GroupDto UpdateGroup(Guid groupid, GroupRequestDto groupModel)
+    {
+        _permissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
+        var group = _userManager.GetGroups().SingleOrDefault(x => x.ID == groupid).NotFoundIfNull("group not found");
+        if (groupid == Constants.LostGroupInfo.ID)
+        {
+            throw new ItemNotFoundException("group not found");
+        }
+
+        group.Name = groupModel.GroupName ?? group.Name;
+        _userManager.SaveGroupInfo(group);
+
+        RemoveMembersFrom(groupid, new GroupRequestDto { Members = _userManager.GetUsersByGroup(groupid, EmployeeStatus.All).Select(u => u.ID).Where(id => !groupModel.Members.Contains(id)) });
+
+        TransferUserToDepartment(groupModel.GroupManager, @group, true);
+        if (groupModel.Members != null)
+        {
+            foreach (var member in groupModel.Members)
+            {
+                TransferUserToDepartment(member, group, false);
+            }
+        }
+
+        _messageService.Send(MessageAction.GroupUpdated, _messageTarget.Create(groupid), group.Name);
+
+        return GetById(groupid);
+    }
+
+    public GroupDto DeleteGroup(Guid groupid)
+    {
+        _permissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
+        var @group = GetGroupInfo(groupid);
+        var groupWrapperFull = _groupWraperFullHelper.Get(group, false);
+
+        _userManager.DeleteGroup(groupid);
+
+        _messageService.Send(MessageAction.GroupDeleted, _messageTarget.Create(group.ID), group.Name);
+
+        return groupWrapperFull;
+    }
+
+    private GroupInfo GetGroupInfo(Guid groupid)
+    {
+        var group = _userManager.GetGroups().SingleOrDefault(x => x.ID == groupid).NotFoundIfNull("group not found");
+        if (group.ID == Constants.LostGroupInfo.ID)
+        {
+            throw new ItemNotFoundException("group not found");
+        }
+
+        return @group;
+    }
+
+    public GroupDto TransferMembersTo(Guid groupid, Guid newgroupid)
+    {
+        _permissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
+        var oldgroup = GetGroupInfo(groupid);
+
+        var newgroup = GetGroupInfo(newgroupid);
+
+        var users = _userManager.GetUsersByGroup(oldgroup.ID);
+        foreach (var userInfo in users)
+        {
+            TransferUserToDepartment(userInfo.ID, newgroup, false);
+        }
+
+        return GetById(newgroupid);
+    }
+
+    public GroupDto SetMembersTo(Guid groupid, GroupRequestDto groupModel)
+    {
+        RemoveMembersFrom(groupid, new GroupRequestDto { Members = _userManager.GetUsersByGroup(groupid).Select(x => x.ID) });
+        AddMembersTo(groupid, groupModel);
+
+        return GetById(groupid);
+    }
+
+    public GroupDto AddMembersTo(Guid groupid, GroupRequestDto groupModel)
+    {
+        _permissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
+        var group = GetGroupInfo(groupid);
+
+        foreach (var userId in groupModel.Members)
+        {
+            TransferUserToDepartment(userId, group, false);
+        }
+
+        return GetById(group.ID);
+    }
+
+    public GroupDto SetManager(Guid groupid, SetManagerRequestDto setManagerModel)
+    {
+        var group = GetGroupInfo(groupid);
+        if (_userManager.UserExists(setManagerModel.UserId))
+        {
+            _userManager.SetDepartmentManager(group.ID, setManagerModel.UserId);
+        }
+        else
+        {
+            throw new ItemNotFoundException("user not found");
+        }
+
+        return GetById(groupid);
+    }
+
+    public GroupDto RemoveMembersFrom(Guid groupid, GroupRequestDto groupModel)
+    {
+        _permissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
+        var group = GetGroupInfo(groupid);
+
+        foreach (var userId in groupModel.Members)
+        {
+            RemoveUserFromDepartment(userId, group);
+        }
+
+        return GetById(group.ID);
+    }
+
+    private void RemoveUserFromDepartment(Guid userId, GroupInfo @group)
+    {
+        if (!_userManager.UserExists(userId))
+        {
+            return;
+        }
+
+        var user = _userManager.GetUsers(userId);
+        _userManager.RemoveUserFromGroup(user.ID, @group.ID);
+        _userManager.SaveUserInfo(user);
+    }
+
+    private void TransferUserToDepartment(Guid userId, GroupInfo group, bool setAsManager)
+    {
+        if (!_userManager.UserExists(userId) && userId != Guid.Empty)
+        {
+            return;
+        }
+
+        if (setAsManager)
+        {
+            _userManager.SetDepartmentManager(@group.ID, userId);
+        }
+        _userManager.AddUserIntoGroup(userId, @group.ID);
+    }
+}
\ No newline at end of file
diff --git a/products/ASC.People/Server/ApiEngines/NotificationControllerEngine.cs b/products/ASC.People/Server/ApiEngines/NotificationControllerEngine.cs
new file mode 100644
index 0000000000..c787883d0d
--- /dev/null
+++ b/products/ASC.People/Server/ApiEngines/NotificationControllerEngine.cs
@@ -0,0 +1,58 @@
+using SecurityContext = ASC.Core.SecurityContext;
+
+namespace ASC.People.ApiHelpers;
+
+public class NotificationControllerEngine : ApiControllerEngineBase
+{
+    private readonly CommonLinkUtility _commonLinkUtility;
+
+    public NotificationControllerEngine(
+        UserManager userManager,
+        AuthContext authContext,
+        ApiContext apiContext,
+        PermissionContext permissionContext,
+        SecurityContext securityContext,
+        MessageService messageService,
+        MessageTarget messageTarget,
+        StudioNotifyService studioNotifyService,
+        CommonLinkUtility commonLinkUtility)
+        : base(
+            userManager,
+            authContext,
+            apiContext,
+            permissionContext,
+            securityContext,
+            messageService,
+            messageTarget,
+            studioNotifyService)
+    {
+        _commonLinkUtility = commonLinkUtility;
+    }
+
+    public object SendNotificationToChange(string userId)
+    {
+        var user = UserManager.GetUsers(
+            string.IsNullOrEmpty(userId)
+                ? SecurityContext.CurrentAccount.ID
+                : new Guid(userId));
+        var canChange =
+        user.IsMe(AuthContext)
+                    || PermissionContext.CheckPermissions(new UserSecurityProvider(user.ID), Constants.Action_EditUser);
+
+        if (!canChange)
+        {
+            throw new SecurityAccessDeniedException(Resource.ErrorAccessDenied);
+        }
+
+        user.MobilePhoneActivationStatus = MobilePhoneActivationStatus.NotActivated;
+        UserManager.SaveUserInfo(user);
+        if (user.IsMe(AuthContext))
+        {
+            return _commonLinkUtility.GetConfirmationUrl(user.Email, ConfirmType.PhoneActivation);
+        }
+
+        StudioNotifyService.SendMsgMobilePhoneChange(user);
+
+        return string.Empty;
+    }
+}
diff --git a/products/ASC.People/Server/Api/BasePeopleController.cs b/products/ASC.People/Server/ApiEngines/PeopleControllerEngine.cs
similarity index 95%
rename from products/ASC.People/Server/Api/BasePeopleController.cs
rename to products/ASC.People/Server/ApiEngines/PeopleControllerEngine.cs
index df294964a7..d843584dbe 100644
--- a/products/ASC.People/Server/Api/BasePeopleController.cs
+++ b/products/ASC.People/Server/ApiEngines/PeopleControllerEngine.cs
@@ -1,16 +1,15 @@
 using SecurityContext = ASC.Core.SecurityContext;
 
-namespace ASC.People.Api;
+namespace ASC.People.ApiHelpers;
 
-public class BasePeopleController : BaseApiController
+public abstract class PeopleControllerEngine : ApiControllerEngineBase
 {
-    protected readonly UserPhotoManager UserPhotoManager;
     protected readonly DisplayUserSettingsHelper DisplayUserSettingsHelper;
     protected readonly SetupInfo SetupInfo;
-
+    protected readonly UserPhotoManager UserPhotoManager;
     private readonly IHttpClientFactory _httpClientFactory;
 
-    protected BasePeopleController(
+    protected PeopleControllerEngine(
         UserManager userManager,
         AuthContext authContext,
         ApiContext apiContext,
@@ -96,4 +95,4 @@ public class BasePeopleController : BaseApiController
         var imageByteArray = br.ReadBytes((int)inputStream.Length);
         UserPhotoManager.SaveOrUpdatePhoto(user.ID, imageByteArray);
     }
-}
+}
\ No newline at end of file
diff --git a/products/ASC.People/Server/ApiEngines/PhotoControllerEngine.cs b/products/ASC.People/Server/ApiEngines/PhotoControllerEngine.cs
new file mode 100644
index 0000000000..b6781a6816
--- /dev/null
+++ b/products/ASC.People/Server/ApiEngines/PhotoControllerEngine.cs
@@ -0,0 +1,246 @@
+using SecurityContext = ASC.Core.SecurityContext;
+
+namespace ASC.People.ApiHelpers;
+
+public class PhotoControllerEngine : PeopleControllerEngine
+{
+    private readonly FileSizeComment _fileSizeComment;
+    private readonly SettingsManager _settingsManager;
+
+    public PhotoControllerEngine(
+        UserManager userManager,
+        AuthContext authContext,
+        ApiContext apiContext,
+        PermissionContext permissionContext,
+        SecurityContext securityContext,
+        MessageService messageService,
+        MessageTarget messageTarget,
+        StudioNotifyService studioNotifyService,
+        FileSizeComment fileSizeComment,
+        SettingsManager settingsManager,
+        UserPhotoManager userPhotoManager,
+        IHttpClientFactory httpClientFactory,
+        DisplayUserSettingsHelper displayUserSettingsHelper,
+        SetupInfo setupInfo)
+        : base(
+            userManager,
+            authContext,
+            apiContext,
+            permissionContext,
+            securityContext,
+            messageService,
+            messageTarget,
+            studioNotifyService,
+            userPhotoManager,
+            httpClientFactory,
+            displayUserSettingsHelper,
+            setupInfo)
+    {
+        _fileSizeComment = fileSizeComment;
+        _settingsManager = settingsManager;
+    }
+
+    public ThumbnailsDataDto CreateMemberPhotoThumbnails(string userid, ThumbnailsRequestDto thumbnailsModel)
+    {
+        var user = GetUserInfo(userid);
+
+        if (UserManager.IsSystemUser(user.ID))
+        {
+            throw new SecurityException();
+        }
+
+        PermissionContext.DemandPermissions(new UserSecurityProvider(user.ID), Constants.Action_EditUser);
+
+        if (!string.IsNullOrEmpty(thumbnailsModel.TmpFile))
+        {
+            var fileName = Path.GetFileName(thumbnailsModel.TmpFile);
+            var data = UserPhotoManager.GetTempPhotoData(fileName);
+
+            var settings = new UserPhotoThumbnailSettings(thumbnailsModel.X, thumbnailsModel.Y, thumbnailsModel.Width, thumbnailsModel.Height);
+            _settingsManager.SaveForUser(settings, user.ID);
+            UserPhotoManager.RemovePhoto(user.ID);
+            UserPhotoManager.SaveOrUpdatePhoto(user.ID, data);
+            UserPhotoManager.RemoveTempPhoto(fileName);
+        }
+        else
+        {
+            UserPhotoThumbnailManager.SaveThumbnails(UserPhotoManager, _settingsManager, thumbnailsModel.X, thumbnailsModel.Y, thumbnailsModel.Width, thumbnailsModel.Height, user.ID);
+        }
+
+        UserManager.SaveUserInfo(user);
+        MessageService.Send(MessageAction.UserUpdatedAvatarThumbnails, MessageTarget.Create(user.ID), user.DisplayUserName(false, DisplayUserSettingsHelper));
+
+        return new ThumbnailsDataDto(user.ID, UserPhotoManager);
+    }
+
+    public ThumbnailsDataDto DeleteMemberPhoto(string userid)
+    {
+        var user = GetUserInfo(userid);
+
+        if (UserManager.IsSystemUser(user.ID))
+        {
+            throw new SecurityException();
+        }
+
+        PermissionContext.DemandPermissions(new UserSecurityProvider(user.ID), Constants.Action_EditUser);
+
+        UserPhotoManager.RemovePhoto(user.ID);
+        UserManager.SaveUserInfo(user);
+        MessageService.Send(MessageAction.UserDeletedAvatar, MessageTarget.Create(user.ID), user.DisplayUserName(false, DisplayUserSettingsHelper));
+
+        return new ThumbnailsDataDto(user.ID, UserPhotoManager);
+    }
+
+    public ThumbnailsDataDto GetMemberPhoto(string userid)
+    {
+        var user = GetUserInfo(userid);
+
+        if (UserManager.IsSystemUser(user.ID))
+        {
+            throw new SecurityException();
+        }
+
+        return new ThumbnailsDataDto(user.ID, UserPhotoManager);
+    }
+
+    public ThumbnailsDataDto UpdateMemberPhoto(string userid, UpdateMemberRequestDto model)
+    {
+        var user = GetUserInfo(userid);
+
+        if (UserManager.IsSystemUser(user.ID))
+        {
+            throw new SecurityException();
+        }
+
+        if (model.Files != UserPhotoManager.GetPhotoAbsoluteWebPath(user.ID))
+        {
+            UpdatePhotoUrl(model.Files, user);
+        }
+
+        UserManager.SaveUserInfo(user);
+        MessageService.Send(MessageAction.UserAddedAvatar, MessageTarget.Create(user.ID), user.DisplayUserName(false, DisplayUserSettingsHelper));
+
+        return new ThumbnailsDataDto(user.ID, UserPhotoManager);
+    }
+
+    public FileUploadResultDto UploadMemberPhoto(string userid, IFormCollection model)
+    {
+        var result = new FileUploadResultDto();
+        var autosave = bool.Parse(model["Autosave"]);
+
+        try
+        {
+            if (model.Files.Count != 0)
+            {
+                Guid userId;
+                try
+                {
+                    userId = new Guid(userid);
+                }
+                catch
+                {
+                    userId = SecurityContext.CurrentAccount.ID;
+                }
+
+                PermissionContext.DemandPermissions(new UserSecurityProvider(userId), Constants.Action_EditUser);
+
+                var userPhoto = model.Files[0];
+
+                if (userPhoto.Length > SetupInfo.MaxImageUploadSize)
+                {
+                    result.Success = false;
+                    result.Message = _fileSizeComment.FileImageSizeExceptionString;
+
+                    return result;
+                }
+
+                var data = new byte[userPhoto.Length];
+                using var inputStream = userPhoto.OpenReadStream();
+
+                var br = new BinaryReader(inputStream);
+                br.Read(data, 0, (int)userPhoto.Length);
+                br.Close();
+
+                CheckImgFormat(data);
+
+                if (autosave)
+                {
+                    if (data.Length > SetupInfo.MaxImageUploadSize)
+                    {
+                        throw new ImageSizeLimitException();
+                    }
+
+                    var mainPhoto = UserPhotoManager.SaveOrUpdatePhoto(userId, data);
+
+                    result.Data =
+                        new
+                        {
+                            main = mainPhoto,
+                            retina = UserPhotoManager.GetRetinaPhotoURL(userId),
+                            max = UserPhotoManager.GetMaxPhotoURL(userId),
+                            big = UserPhotoManager.GetBigPhotoURL(userId),
+                            medium = UserPhotoManager.GetMediumPhotoURL(userId),
+                            small = UserPhotoManager.GetSmallPhotoURL(userId),
+                        };
+                }
+                else
+                {
+                    result.Data = UserPhotoManager.SaveTempPhoto(data, SetupInfo.MaxImageUploadSize, UserPhotoManager.OriginalFotoSize.Width, UserPhotoManager.OriginalFotoSize.Height);
+                }
+
+                result.Success = true;
+            }
+            else
+            {
+                result.Success = false;
+                result.Message = PeopleResource.ErrorEmptyUploadFileSelected;
+            }
+
+        }
+        catch (Web.Core.Users.UnknownImageFormatException)
+        {
+            result.Success = false;
+            result.Message = PeopleResource.ErrorUnknownFileImageType;
+        }
+        catch (ImageWeightLimitException)
+        {
+            result.Success = false;
+            result.Message = PeopleResource.ErrorImageWeightLimit;
+        }
+        catch (ImageSizeLimitException)
+        {
+            result.Success = false;
+            result.Message = PeopleResource.ErrorImageSizetLimit;
+        }
+        catch (Exception ex)
+        {
+            result.Success = false;
+            result.Message = ex.Message.HtmlEncode();
+        }
+
+        return result;
+    }
+
+    private static void CheckImgFormat(byte[] data)
+    {
+        IImageFormat imgFormat;
+        try
+        {
+            using var img = Image.Load(data, out var format);
+            imgFormat = format;
+        }
+        catch (OutOfMemoryException)
+        {
+            throw new ImageSizeLimitException();
+        }
+        catch (ArgumentException error)
+        {
+            throw new Web.Core.Users.UnknownImageFormatException(error);
+        }
+
+        if (imgFormat.Name != "PNG" && imgFormat.Name != "JPEG")
+        {
+            throw new Web.Core.Users.UnknownImageFormatException();
+        }
+    }
+}
diff --git a/products/ASC.People/Server/ApiEngines/ReassignControllerEngine.cs b/products/ASC.People/Server/ApiEngines/ReassignControllerEngine.cs
new file mode 100644
index 0000000000..e5e3f90d34
--- /dev/null
+++ b/products/ASC.People/Server/ApiEngines/ReassignControllerEngine.cs
@@ -0,0 +1,76 @@
+using SecurityContext = ASC.Core.SecurityContext;
+
+namespace ASC.People.ApiHelpers;
+
+public class ReassignControllerEngine : ApiControllerEngineBase
+{
+    private readonly QueueWorkerReassign _queueWorkerReassign;
+
+    public ReassignControllerEngine(
+        UserManager userManager,
+        AuthContext authContext,
+        ApiContext apiContext,
+        PermissionContext permissionContext,
+        SecurityContext securityContext,
+        MessageService messageService,
+        MessageTarget messageTarget,
+        StudioNotifyService studioNotifyService,
+        QueueWorkerReassign queueWorkerReassign)
+        : base(
+            userManager,
+            authContext,
+            apiContext,
+            permissionContext,
+            securityContext,
+            messageService,
+            messageTarget,
+            studioNotifyService)
+    {
+        _queueWorkerReassign = queueWorkerReassign;
+    }
+
+    public ReassignProgressItem GetReassignProgress(Guid userId)
+    {
+        PermissionContext.DemandPermissions(Constants.Action_EditUser);
+
+        return _queueWorkerReassign.GetProgressItemStatus(Tenant.TenantId, userId);
+    }
+
+    public void TerminateReassign(TerminateRequestDto model)
+    {
+        PermissionContext.DemandPermissions(Constants.Action_EditUser);
+
+        _queueWorkerReassign.Terminate(Tenant.TenantId, model.UserId);
+    }
+
+    public ReassignProgressItem StartReassign(StartReassignRequestDto model)
+    {
+        PermissionContext.DemandPermissions(Constants.Action_EditUser);
+
+        var fromUser = UserManager.GetUsers(model.FromUserId);
+
+        if (fromUser == null || fromUser.ID == Constants.LostUser.ID)
+        {
+            throw new ArgumentException("User with id = " + model.FromUserId + " not found");
+        }
+
+        if (fromUser.IsOwner(Tenant) || fromUser.IsMe(AuthContext) || fromUser.Status != EmployeeStatus.Terminated)
+        {
+            throw new ArgumentException("Can not delete user with id = " + model.FromUserId);
+        }
+
+        var toUser = UserManager.GetUsers(model.ToUserId);
+
+        if (toUser == null || toUser.ID == Constants.LostUser.ID)
+        {
+            throw new ArgumentException("User with id = " + model.ToUserId + " not found");
+        }
+
+        if (toUser.IsVisitor(UserManager) || toUser.Status == EmployeeStatus.Terminated)
+        {
+            throw new ArgumentException("Can not reassign data to user with id = " + model.ToUserId);
+        }
+
+        return _queueWorkerReassign.Start(Tenant.TenantId, model.FromUserId, model.ToUserId, SecurityContext.CurrentAccount.ID, model.DeleteProfile);
+    }
+}
diff --git a/products/ASC.People/Server/ApiEngines/RemoveUserDataControllerEngine.cs b/products/ASC.People/Server/ApiEngines/RemoveUserDataControllerEngine.cs
new file mode 100644
index 0000000000..09897f3c36
--- /dev/null
+++ b/products/ASC.People/Server/ApiEngines/RemoveUserDataControllerEngine.cs
@@ -0,0 +1,78 @@
+using SecurityContext = ASC.Core.SecurityContext;
+
+namespace ASC.People.ApiHelpers;
+
+public class RemoveUserDataControllerEngine : ApiControllerEngineBase
+{
+    private readonly QueueWorkerRemove _queueWorkerRemove;
+
+    public RemoveUserDataControllerEngine(
+        UserManager userManager,
+        AuthContext authContext,
+        ApiContext apiContext,
+        PermissionContext permissionContext,
+        SecurityContext securityContext,
+        MessageService messageService,
+        MessageTarget messageTarget,
+        StudioNotifyService studioNotifyService,
+        QueueWorkerRemove queueWorkerRemove)
+        : base(userManager,
+               authContext,
+               apiContext,
+               permissionContext,
+               securityContext,
+               messageService,
+               messageTarget,
+               studioNotifyService)
+    {
+        _queueWorkerRemove = queueWorkerRemove;
+    }
+
+    public RemoveProgressItem GetRemoveProgress(Guid userId)
+    {
+        PermissionContext.DemandPermissions(Constants.Action_EditUser);
+
+        return _queueWorkerRemove.GetProgressItemStatus(Tenant.TenantId, userId);
+    }
+
+    public object SendInstructionsToDelete()
+    {
+        var user = UserManager.GetUsers(SecurityContext.CurrentAccount.ID);
+
+        if (user.IsLDAP())
+        {
+            throw new SecurityException();
+        }
+
+        StudioNotifyService.SendMsgProfileDeletion(user);
+        MessageService.Send(MessageAction.UserSentDeleteInstructions);
+
+        return string.Format(Resource.SuccessfullySentNotificationDeleteUserInfoMessage, "<b>" + user.Email + "</b>");
+    }
+
+    public void TerminateRemove(TerminateRequestDto model)
+    {
+        PermissionContext.DemandPermissions(Constants.Action_EditUser);
+
+        _queueWorkerRemove.Terminate(Tenant.TenantId, model.UserId);
+    }
+
+    public RemoveProgressItem StartRemove(TerminateRequestDto model)
+    {
+        PermissionContext.DemandPermissions(Constants.Action_EditUser);
+
+        var user = UserManager.GetUsers(model.UserId);
+
+        if (user == null || user.ID == Constants.LostUser.ID)
+        {
+            throw new ArgumentException("User with id = " + model.UserId + " not found");
+        }
+
+        if (user.IsOwner(Tenant) || user.IsMe(AuthContext) || user.Status != EmployeeStatus.Terminated)
+        {
+            throw new ArgumentException("Can not delete user with id = " + model.UserId);
+        }
+
+        return _queueWorkerRemove.Start(Tenant.TenantId, user, SecurityContext.CurrentAccount.ID, true);
+    }
+}
diff --git a/products/ASC.People/Server/ApiEngines/ThirdpartyControllerEngine.cs b/products/ASC.People/Server/ApiEngines/ThirdpartyControllerEngine.cs
new file mode 100644
index 0000000000..bce4cc83fd
--- /dev/null
+++ b/products/ASC.People/Server/ApiEngines/ThirdpartyControllerEngine.cs
@@ -0,0 +1,331 @@
+using SecurityContext = ASC.Core.SecurityContext;
+
+namespace ASC.People.ApiHelpers;
+
+public class ThirdpartyControllerEngine : ApiControllerEngineBase
+{
+    private readonly IOptionsSnapshot<AccountLinker> _accountLinker;
+    private readonly CookiesManager _cookiesManager;
+    private readonly CoreBaseSettings _coreBaseSettings;
+    private readonly DisplayUserSettingsHelper _displayUserSettingsHelper;
+    private readonly IHttpClientFactory _httpClientFactory;
+    private readonly InstanceCrypto _instanceCrypto;
+    private readonly MobileDetector _mobileDetector;
+    private readonly PersonalSettingsHelper _personalSettingsHelper;
+    private readonly ProviderManager _providerManager;
+    private readonly Signature _signature;
+    private readonly TenantExtra _tenantExtra;
+    private readonly UserHelpTourHelper _userHelpTourHelper;
+    private readonly UserManagerWrapper _userManagerWrapper;
+    private readonly UserPhotoManager _userPhotoManager;
+
+    public ThirdpartyControllerEngine(
+        UserManager userManager,
+        AuthContext authContext,
+        ApiContext apiContext,
+        PermissionContext permissionContext,
+        SecurityContext securityContext,
+        MessageService messageService,
+        MessageTarget messageTarget,
+        StudioNotifyService studioNotifyService,
+        IOptionsSnapshot<AccountLinker> optionsSnapshot,
+        CookiesManager cookiesManager,
+        CoreBaseSettings coreBaseSettings,
+        DisplayUserSettingsHelper displayUserSettingsHelper,
+        IHttpClientFactory httpClientFactory,
+        InstanceCrypto instanceCrypto,
+        MobileDetector mobileDetector,
+        PersonalSettingsHelper personalSettingsHelper,
+        ProviderManager providerManager,
+        Signature signature,
+        TenantExtra tenantExtra,
+        UserHelpTourHelper userHelpTourHelper,
+        UserManagerWrapper userManagerWrapper,
+        UserPhotoManager userPhotoManager
+        )
+        : base(
+            userManager,
+            authContext,
+            apiContext,
+            permissionContext,
+            securityContext,
+            messageService,
+            messageTarget,
+            studioNotifyService)
+    {
+        _accountLinker = optionsSnapshot;
+        _cookiesManager = cookiesManager;
+        _coreBaseSettings = coreBaseSettings;
+        _displayUserSettingsHelper = displayUserSettingsHelper;
+        _httpClientFactory = httpClientFactory;
+        _instanceCrypto = instanceCrypto;
+        _mobileDetector = mobileDetector;
+        _personalSettingsHelper = personalSettingsHelper;
+        _providerManager = providerManager;
+        _signature = signature;
+        _tenantExtra = tenantExtra;
+        _userHelpTourHelper = userHelpTourHelper;
+        _userManagerWrapper = userManagerWrapper;
+        _userPhotoManager = userPhotoManager;
+    }
+
+    public ICollection<AccountInfoDto> GetAuthProviders(bool inviteView, bool settingsView, string clientCallback, string fromOnly, HttpRequest request)
+    {
+        ICollection<AccountInfoDto> infos = new List<AccountInfoDto>();
+        IEnumerable<LoginProfile> linkedAccounts = new List<LoginProfile>();
+
+        if (AuthContext.IsAuthenticated)
+        {
+            linkedAccounts = _accountLinker.Get("webstudio").GetLinkedProfiles(AuthContext.CurrentAccount.ID.ToString());
+        }
+
+        fromOnly = string.IsNullOrWhiteSpace(fromOnly) ? string.Empty : fromOnly.ToLower();
+
+        foreach (var provider in ProviderManager.AuthProviders.Where(provider => string.IsNullOrEmpty(fromOnly) || fromOnly == provider || (provider == "google" && fromOnly == "openid")))
+        {
+            if (inviteView && provider.Equals("twitter", StringComparison.OrdinalIgnoreCase))
+            {
+                continue;
+            }
+            var loginProvider = _providerManager.GetLoginProvider(provider);
+            if (loginProvider != null && loginProvider.IsEnabled)
+            {
+
+                var url = VirtualPathUtility.ToAbsolute("~/login.ashx") + $"?auth={provider}";
+                var mode = settingsView || inviteView || (!_mobileDetector.IsMobile() && !request.DesktopApp())
+                        ? $"&mode=popup&callback={clientCallback}"
+                        : "&mode=Redirect&desktop=true";
+
+                infos.Add(new AccountInfoDto
+                {
+                    Linked = linkedAccounts.Any(x => x.Provider == provider),
+                    Provider = provider,
+                    Url = url + mode
+                });
+            }
+        }
+
+        return infos;
+    }
+
+    public void LinkAccount(LinkAccountRequestDto model)
+    {
+        var profile = new LoginProfile(_signature, _instanceCrypto, model.SerializedProfile);
+
+        if (!(_coreBaseSettings.Standalone || _tenantExtra.GetTenantQuota().Oauth))
+        {
+            throw new Exception("ErrorNotAllowedOption");
+        }
+
+        if (string.IsNullOrEmpty(profile.AuthorizationError))
+        {
+            GetLinker().AddLink(SecurityContext.CurrentAccount.ID.ToString(), profile);
+            MessageService.Send(MessageAction.UserLinkedSocialAccount, GetMeaningfulProviderName(profile.Provider));
+        }
+        else
+        {
+            // ignore cancellation
+            if (profile.AuthorizationError != "Canceled at provider")
+            {
+                throw new Exception(profile.AuthorizationError);
+            }
+        }
+    }
+
+    public void SignupAccount(SignupAccountRequestDto model)
+    {
+        var employeeType = model.EmplType ?? EmployeeType.User;
+        var passwordHash = model.PasswordHash;
+        var mustChangePassword = false;
+        if (string.IsNullOrEmpty(passwordHash))
+        {
+            passwordHash = UserManagerWrapper.GeneratePassword();
+            mustChangePassword = true;
+        }
+
+        var thirdPartyProfile = new LoginProfile(_signature, _instanceCrypto, model.SerializedProfile);
+        if (!string.IsNullOrEmpty(thirdPartyProfile.AuthorizationError))
+        {
+            // ignore cancellation
+            if (thirdPartyProfile.AuthorizationError != "Canceled at provider")
+            {
+                throw new Exception(thirdPartyProfile.AuthorizationError);
+            }
+
+            return;
+        }
+
+        if (string.IsNullOrEmpty(thirdPartyProfile.EMail))
+        {
+            throw new Exception(Resource.ErrorNotCorrectEmail);
+        }
+
+        var userID = Guid.Empty;
+        try
+        {
+            SecurityContext.AuthenticateMeWithoutCookie(ASC.Core.Configuration.Constants.CoreSystem);
+            var newUser = CreateNewUser(GetFirstName(model, thirdPartyProfile), GetLastName(model, thirdPartyProfile), GetEmailAddress(model, thirdPartyProfile), passwordHash, employeeType, false);
+            var messageAction = employeeType == EmployeeType.User ? MessageAction.UserCreatedViaInvite : MessageAction.GuestCreatedViaInvite;
+            MessageService.Send(MessageInitiator.System, messageAction, MessageTarget.Create(newUser.ID), newUser.DisplayUserName(false, _displayUserSettingsHelper));
+            userID = newUser.ID;
+            if (!string.IsNullOrEmpty(thirdPartyProfile.Avatar))
+            {
+                SaveContactImage(userID, thirdPartyProfile.Avatar);
+            }
+
+            GetLinker().AddLink(userID.ToString(), thirdPartyProfile);
+        }
+        finally
+        {
+            SecurityContext.Logout();
+        }
+
+        var user = UserManager.GetUsers(userID);
+        var cookiesKey = SecurityContext.AuthenticateMe(user.Email, passwordHash);
+        _cookiesManager.SetCookies(CookiesType.AuthKey, cookiesKey);
+        MessageService.Send(MessageAction.LoginSuccess);
+        StudioNotifyService.UserHasJoin();
+
+        if (mustChangePassword)
+        {
+            StudioNotifyService.UserPasswordChange(user);
+        }
+
+        _userHelpTourHelper.IsNewUser = true;
+        if (_coreBaseSettings.Personal)
+        {
+            _personalSettingsHelper.IsNewUser = true;
+        }
+    }
+
+    public void UnlinkAccount(string provider)
+    {
+        GetLinker().RemoveProvider(SecurityContext.CurrentAccount.ID.ToString(), provider);
+        MessageService.Send(MessageAction.UserUnlinkedSocialAccount, GetMeaningfulProviderName(provider));
+    }
+
+    private static string GetMeaningfulProviderName(string providerName)
+    {
+        switch (providerName)
+        {
+            case "google":
+            case "openid":
+                return "Google";
+            case "facebook":
+                return "Facebook";
+            case "twitter":
+                return "Twitter";
+            case "linkedin":
+                return "LinkedIn";
+            default:
+                return "Unknown Provider";
+        }
+    }
+
+    private UserInfo CreateNewUser(string firstName, string lastName, string email, string passwordHash, EmployeeType employeeType, bool fromInviteLink)
+    {
+        var isVisitor = employeeType == EmployeeType.Visitor;
+
+        if (SetupInfo.IsSecretEmail(email))
+        {
+            fromInviteLink = false;
+        }
+
+        var userInfo = new UserInfo
+        {
+            FirstName = string.IsNullOrEmpty(firstName) ? UserControlsCommonResource.UnknownFirstName : firstName,
+            LastName = string.IsNullOrEmpty(lastName) ? UserControlsCommonResource.UnknownLastName : lastName,
+            Email = email,
+        };
+
+        if (_coreBaseSettings.Personal)
+        {
+            userInfo.ActivationStatus = EmployeeActivationStatus.Activated;
+            userInfo.CultureName = _coreBaseSettings.CustomMode ? "ru-RU" : Thread.CurrentThread.CurrentUICulture.Name;
+        }
+
+        return _userManagerWrapper.AddUser(userInfo, passwordHash, true, true, isVisitor, fromInviteLink);
+    }
+
+    private string GetEmailAddress(SignupAccountRequestDto model)
+    {
+        if (!string.IsNullOrEmpty(model.Email))
+        {
+            return model.Email.Trim();
+        }
+
+        return string.Empty;
+    }
+
+    private string GetEmailAddress(SignupAccountRequestDto model, LoginProfile account)
+    {
+        var value = GetEmailAddress(model);
+
+        return string.IsNullOrEmpty(value) ? account.EMail : value;
+    }
+
+    private string GetFirstName(SignupAccountRequestDto model)
+    {
+        var value = string.Empty;
+        if (!string.IsNullOrEmpty(model.FirstName))
+        {
+            value = model.FirstName.Trim();
+        }
+
+        return HtmlUtil.GetText(value);
+    }
+
+    private string GetFirstName(SignupAccountRequestDto model, LoginProfile account)
+    {
+        var value = GetFirstName(model);
+
+        return string.IsNullOrEmpty(value) ? account.FirstName : value;
+    }
+
+    private string GetLastName(SignupAccountRequestDto model)
+    {
+        var value = string.Empty;
+        if (!string.IsNullOrEmpty(model.LastName))
+        {
+            value = model.LastName.Trim();
+        }
+
+        return HtmlUtil.GetText(value);
+    }
+
+    private string GetLastName(SignupAccountRequestDto model, LoginProfile account)
+    {
+        var value = GetLastName(model);
+
+        return string.IsNullOrEmpty(value) ? account.LastName : value;
+    }
+
+    private AccountLinker GetLinker()
+    {
+        return _accountLinker.Get("webstudio");
+    }
+    private void SaveContactImage(Guid userID, string url)
+    {
+        using (var memstream = new MemoryStream())
+        {
+            var request = new HttpRequestMessage();
+            request.RequestUri = new Uri(url);
+
+            var httpClient = _httpClientFactory.CreateClient();
+            using (var response = httpClient.Send(request))
+            using (var stream = response.Content.ReadAsStream())
+            {
+                var buffer = new byte[512];
+                int bytesRead;
+                while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
+                {
+                    memstream.Write(buffer, 0, bytesRead);
+                }
+
+                var bytes = memstream.ToArray();
+
+                _userPhotoManager.SaveOrUpdatePhoto(userID, bytes);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/products/ASC.People/Server/ApiEngines/UserControllerEngine.cs b/products/ASC.People/Server/ApiEngines/UserControllerEngine.cs
new file mode 100644
index 0000000000..78b24248e9
--- /dev/null
+++ b/products/ASC.People/Server/ApiEngines/UserControllerEngine.cs
@@ -0,0 +1,1087 @@
+using Module = ASC.Api.Core.Module;
+using SecurityContext = ASC.Core.SecurityContext;
+
+namespace ASC.People.ApiHelpers;
+
+[Scope]
+public class UserControllerEngine : PeopleControllerEngine
+{
+    private readonly Constants _constants;
+    private readonly CookiesManager _cookiesManager;
+    private readonly CoreBaseSettings _coreBaseSettings;
+    private readonly CustomNamingPeople _customNamingPeople;
+    private readonly EmployeeDtoHelper _employeeDtoHelper;
+    private readonly EmployeeFullDtoHelper _employeeFullDtoHelper;
+    private readonly ILog _logger;
+    private readonly PasswordHasher _passwordHasher;
+    private readonly QueueWorkerReassign _queueWorkerReassign;
+    private readonly QueueWorkerRemove _queueWorkerRemove;
+    private readonly Recaptcha _recaptcha;
+    private readonly TenantExtra _tenantExtra;
+    private readonly TenantStatisticsProvider _tenantStatisticsProvider;
+    private readonly TenantUtil _tenantUtil;
+    private readonly UserFormatter _userFormatter;
+    private readonly UserManagerWrapper _userManagerWrapper;
+    private readonly WebItemManager _webItemManager;
+    private readonly WebItemSecurity _webItemSecurity;
+    private readonly WebItemSecurityCache _webItemSecurityCache;
+
+    public UserControllerEngine(
+        UserManager userManager,
+        AuthContext authContext,
+        ApiContext apiContext,
+        PermissionContext permissionContext,
+        SecurityContext securityContext,
+        MessageService messageService,
+        MessageTarget messageTarget,
+        StudioNotifyService studioNotifyService,
+        Constants constants,
+        CookiesManager cookiesManager,
+        CoreBaseSettings coreBaseSettings,
+        CustomNamingPeople customNamingPeople,
+        ILog logger,
+        PasswordHasher passwordHasher,
+        QueueWorkerReassign queueWorkerReassign,
+        QueueWorkerRemove queueWorkerRemove,
+        Recaptcha recaptcha,
+        TenantExtra tenantExtra,
+        TenantStatisticsProvider tenantStatisticsProvider,
+        TenantUtil tenantUtil,
+        UserFormatter userFormatter,
+        UserManagerWrapper userManagerWrapper,
+        WebItemManager webItemManager,
+        WebItemSecurity webItemSecurity,
+        WebItemSecurityCache webItemSecurityCache,
+        UserPhotoManager userPhotoManager,
+        IHttpClientFactory httpClientFactory,
+        DisplayUserSettingsHelper displayUserSettingsHelper,
+        SetupInfo setupInfo,
+        EmployeeFullDtoHelper employeeFullDtoHelper,
+        EmployeeDtoHelper employeeDtoHelper)
+        : base(
+            userManager,
+            authContext,
+            apiContext,
+            permissionContext,
+            securityContext,
+            messageService,
+            messageTarget,
+            studioNotifyService,
+            userPhotoManager,
+            httpClientFactory,
+            displayUserSettingsHelper,
+            setupInfo)
+    {
+        _constants = constants;
+        _cookiesManager = cookiesManager;
+        _coreBaseSettings = coreBaseSettings;
+        _customNamingPeople = customNamingPeople;
+        _logger = logger;
+        _passwordHasher = passwordHasher;
+        _queueWorkerReassign = queueWorkerReassign;
+        _queueWorkerRemove = queueWorkerRemove;
+        _recaptcha = recaptcha;
+        _tenantExtra = tenantExtra;
+        _tenantStatisticsProvider = tenantStatisticsProvider;
+        _tenantUtil = tenantUtil;
+        _userFormatter = userFormatter;
+        _userManagerWrapper = userManagerWrapper;
+        _webItemManager = webItemManager;
+        _webItemSecurity = webItemSecurity;
+        _webItemSecurityCache = webItemSecurityCache;
+        _employeeDtoHelper = employeeDtoHelper;
+        _employeeFullDtoHelper = employeeFullDtoHelper;
+    }
+
+    public EmployeeFullDto AddMember(MemberRequestDto memberModel)
+    {
+        ApiContext.AuthByClaim();
+
+        PermissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
+
+        memberModel.PasswordHash = (memberModel.PasswordHash ?? "").Trim();
+        if (string.IsNullOrEmpty(memberModel.PasswordHash))
+        {
+            memberModel.Password = (memberModel.Password ?? "").Trim();
+
+            if (string.IsNullOrEmpty(memberModel.Password))
+            {
+                memberModel.Password = UserManagerWrapper.GeneratePassword();
+            }
+            else
+            {
+                _userManagerWrapper.CheckPasswordPolicy(memberModel.Password);
+            }
+            memberModel.PasswordHash = _passwordHasher.GetClientPassword(memberModel.Password);
+        }
+
+        var user = new UserInfo();
+
+        //Validate email
+        var address = new MailAddress(memberModel.Email);
+        user.Email = address.Address;
+        //Set common fields
+        user.FirstName = memberModel.Firstname;
+        user.LastName = memberModel.Lastname;
+        user.Title = memberModel.Title;
+        user.Location = memberModel.Location;
+        user.Notes = memberModel.Comment;
+        user.Sex = "male".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase)
+                       ? true
+                       : ("female".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase) ? (bool?)false : null);
+
+        user.BirthDate = memberModel.Birthday != null && memberModel.Birthday != DateTime.MinValue ? _tenantUtil.DateTimeFromUtc(memberModel.Birthday) : null;
+        user.WorkFromDate = memberModel.Worksfrom != null && memberModel.Worksfrom != DateTime.MinValue ? _tenantUtil.DateTimeFromUtc(memberModel.Worksfrom) : DateTime.UtcNow.Date;
+
+        UpdateContacts(memberModel.Contacts, user);
+
+        user = _userManagerWrapper.AddUser(user, memberModel.PasswordHash, memberModel.FromInviteLink, true, memberModel.IsVisitor, memberModel.FromInviteLink);
+
+        var messageAction = memberModel.IsVisitor ? MessageAction.GuestCreated : MessageAction.UserCreated;
+        MessageService.Send(messageAction, MessageTarget.Create(user.ID), user.DisplayUserName(false, DisplayUserSettingsHelper));
+
+        UpdateDepartments(memberModel.Department, user);
+
+        if (memberModel.Files != UserPhotoManager.GetDefaultPhotoAbsoluteWebPath())
+        {
+            UpdatePhotoUrl(memberModel.Files, user);
+        }
+
+        return _employeeFullDtoHelper.GetFull(user);
+    }
+
+    public EmployeeFullDto AddMemberAsActivated(MemberRequestDto memberModel)
+    {
+        PermissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
+
+        var user = new UserInfo();
+
+        memberModel.PasswordHash = (memberModel.PasswordHash ?? "").Trim();
+        if (string.IsNullOrEmpty(memberModel.PasswordHash))
+        {
+            memberModel.Password = (memberModel.Password ?? "").Trim();
+
+            if (string.IsNullOrEmpty(memberModel.Password))
+            {
+                memberModel.Password = UserManagerWrapper.GeneratePassword();
+            }
+            else
+            {
+                _userManagerWrapper.CheckPasswordPolicy(memberModel.Password);
+            }
+
+            memberModel.PasswordHash = _passwordHasher.GetClientPassword(memberModel.Password);
+        }
+
+        //Validate email
+        var address = new MailAddress(memberModel.Email);
+        user.Email = address.Address;
+        //Set common fields
+        user.FirstName = memberModel.Firstname;
+        user.LastName = memberModel.Lastname;
+        user.Title = memberModel.Title;
+        user.Location = memberModel.Location;
+        user.Notes = memberModel.Comment;
+        user.Sex = "male".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase)
+                       ? true
+                       : ("female".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase) ? (bool?)false : null);
+
+        user.BirthDate = memberModel.Birthday != null ? _tenantUtil.DateTimeFromUtc(memberModel.Birthday) : null;
+        user.WorkFromDate = memberModel.Worksfrom != null ? _tenantUtil.DateTimeFromUtc(memberModel.Worksfrom) : DateTime.UtcNow.Date;
+
+        UpdateContacts(memberModel.Contacts, user);
+
+        user = _userManagerWrapper.AddUser(user, memberModel.PasswordHash, false, false, memberModel.IsVisitor);
+
+        user.ActivationStatus = EmployeeActivationStatus.Activated;
+
+        UpdateDepartments(memberModel.Department, user);
+
+        if (memberModel.Files != UserPhotoManager.GetDefaultPhotoAbsoluteWebPath())
+        {
+            UpdatePhotoUrl(memberModel.Files, user);
+        }
+
+        return _employeeFullDtoHelper.GetFull(user);
+    }
+
+    public EmployeeFullDto ChangeUserPassword(Guid userid, MemberRequestDto memberModel)
+    {
+        ApiContext.AuthByClaim();
+        PermissionContext.DemandPermissions(new UserSecurityProvider(userid), Constants.Action_EditUser);
+
+        var user = UserManager.GetUsers(userid);
+
+        if (!UserManager.UserExists(user))
+        {
+            return null;
+        }
+
+        if (UserManager.IsSystemUser(user.ID))
+        {
+            throw new SecurityException();
+        }
+
+        if (!string.IsNullOrEmpty(memberModel.Email))
+        {
+            var address = new MailAddress(memberModel.Email);
+            if (!string.Equals(address.Address, user.Email, StringComparison.OrdinalIgnoreCase))
+            {
+                user.Email = address.Address.ToLowerInvariant();
+                user.ActivationStatus = EmployeeActivationStatus.Activated;
+                UserManager.SaveUserInfo(user);
+            }
+        }
+
+        memberModel.PasswordHash = (memberModel.PasswordHash ?? "").Trim();
+        if (string.IsNullOrEmpty(memberModel.PasswordHash))
+        {
+            memberModel.Password = (memberModel.Password ?? "").Trim();
+
+            if (!string.IsNullOrEmpty(memberModel.Password))
+            {
+                memberModel.PasswordHash = _passwordHasher.GetClientPassword(memberModel.Password);
+            }
+        }
+
+        if (!string.IsNullOrEmpty(memberModel.PasswordHash))
+        {
+            SecurityContext.SetUserPasswordHash(userid, memberModel.PasswordHash);
+            MessageService.Send(MessageAction.UserUpdatedPassword);
+
+            _cookiesManager.ResetUserCookie(userid);
+            MessageService.Send(MessageAction.CookieSettingsUpdated);
+        }
+
+        return _employeeFullDtoHelper.GetFull(GetUserInfo(userid.ToString()));
+    }
+
+    public EmployeeFullDto DeleteMember(string userid)
+    {
+        PermissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
+
+        var user = GetUserInfo(userid);
+
+        if (UserManager.IsSystemUser(user.ID) || user.IsLDAP())
+        {
+            throw new SecurityException();
+        }
+
+        if (user.Status != EmployeeStatus.Terminated)
+        {
+            throw new Exception("The user is not suspended");
+        }
+
+        CheckReassignProccess(new[] { user.ID });
+
+        var userName = user.DisplayUserName(false, DisplayUserSettingsHelper);
+        UserPhotoManager.RemovePhoto(user.ID);
+        UserManager.DeleteUser(user.ID);
+        _queueWorkerRemove.Start(Tenant.TenantId, user, SecurityContext.CurrentAccount.ID, false);
+
+        MessageService.Send(MessageAction.UserDeleted, MessageTarget.Create(user.ID), userName);
+
+        return _employeeFullDtoHelper.GetFull(user);
+    }
+
+    public EmployeeFullDto DeleteProfile()
+    {
+        ApiContext.AuthByClaim();
+
+        if (UserManager.IsSystemUser(SecurityContext.CurrentAccount.ID))
+        {
+            throw new SecurityException();
+        }
+
+        var user = GetUserInfo(SecurityContext.CurrentAccount.ID.ToString());
+
+        if (!UserManager.UserExists(user))
+        {
+            throw new Exception(Resource.ErrorUserNotFound);
+        }
+
+        if (user.IsLDAP())
+        {
+            throw new SecurityException();
+        }
+
+        SecurityContext.AuthenticateMeWithoutCookie(ASC.Core.Configuration.Constants.CoreSystem);
+        user.Status = EmployeeStatus.Terminated;
+
+        UserManager.SaveUserInfo(user);
+        var userName = user.DisplayUserName(false, DisplayUserSettingsHelper);
+        MessageService.Send(MessageAction.UsersUpdatedStatus, MessageTarget.Create(user.ID), userName);
+
+        _cookiesManager.ResetUserCookie(user.ID);
+        MessageService.Send(MessageAction.CookieSettingsUpdated);
+
+        if (_coreBaseSettings.Personal)
+        {
+            UserPhotoManager.RemovePhoto(user.ID);
+            UserManager.DeleteUser(user.ID);
+            MessageService.Send(MessageAction.UserDeleted, MessageTarget.Create(user.ID), userName);
+        }
+        else
+        {
+            //StudioNotifyService.Instance.SendMsgProfileHasDeletedItself(user);
+            //StudioNotifyService.SendMsgProfileDeletion(Tenant.TenantId, user);
+        }
+
+        return _employeeFullDtoHelper.GetFull(user);
+    }
+
+    public IEnumerable<EmployeeFullDto> GetAdvanced(EmployeeStatus status, string query)
+    {
+        if (_coreBaseSettings.Personal)
+        {
+            throw new MethodAccessException("Method not available");
+        }
+        try
+        {
+            var list = UserManager.GetUsers(status).AsEnumerable();
+
+            if ("group".Equals(ApiContext.FilterBy, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(ApiContext.FilterValue))
+            {
+                var groupId = new Guid(ApiContext.FilterValue);
+                //Filter by group
+                list = list.Where(x => UserManager.IsUserInGroup(x.ID, groupId));
+                ApiContext.SetDataFiltered();
+            }
+
+            list = list.Where(x => x.FirstName != null && x.FirstName.IndexOf(query, StringComparison.OrdinalIgnoreCase) > -1 || (x.LastName != null && x.LastName.IndexOf(query, StringComparison.OrdinalIgnoreCase) != -1) ||
+                                   (x.UserName != null && x.UserName.IndexOf(query, StringComparison.OrdinalIgnoreCase) != -1) || (x.Email != null && x.Email.IndexOf(query, StringComparison.OrdinalIgnoreCase) != -1) || (x.ContactsList != null && x.ContactsList.Any(y => y.IndexOf(query, StringComparison.OrdinalIgnoreCase) != -1)));
+
+            return list.Select(u => _employeeFullDtoHelper.GetFull(u));
+        }
+        catch (Exception error)
+        {
+            _logger.Error(error);
+        }
+
+        return null;
+    }
+
+    public EmployeeFullDto GetByEmail(string email)
+    {
+        if (_coreBaseSettings.Personal && !UserManager.GetUsers(SecurityContext.CurrentAccount.ID).IsOwner(Tenant))
+        {
+            throw new MethodAccessException("Method not available");
+        }
+
+        var user = UserManager.GetUserByEmail(email);
+        if (user.ID == Constants.LostUser.ID)
+        {
+            throw new ItemNotFoundException("User not found");
+        }
+
+        return _employeeFullDtoHelper.GetFull(user);
+    }
+
+    public EmployeeFullDto GetById(string username)
+    {
+        if (_coreBaseSettings.Personal)
+        {
+            throw new MethodAccessException("Method not available");
+        }
+
+        var user = UserManager.GetUserByUserName(username);
+        if (user.ID == Constants.LostUser.ID)
+        {
+            if (Guid.TryParse(username, out var userId))
+            {
+                user = UserManager.GetUsers(userId);
+            }
+            else
+            {
+                _logger.Error(string.Format("Account {0} сould not get user by name {1}", SecurityContext.CurrentAccount.ID, username));
+            }
+        }
+
+        if (user.ID == Constants.LostUser.ID)
+        {
+            throw new ItemNotFoundException("User not found");
+        }
+
+        return _employeeFullDtoHelper.GetFull(user);
+    }
+
+    public IEnumerable<EmployeeDto> GetByStatus(EmployeeStatus status)
+    {
+        if (_coreBaseSettings.Personal)
+        {
+            throw new Exception("Method not available");
+        }
+
+        Guid? groupId = null;
+        if ("group".Equals(ApiContext.FilterBy, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(ApiContext.FilterValue))
+        {
+            groupId = new Guid(ApiContext.FilterValue);
+            ApiContext.SetDataFiltered();
+        }
+
+        return GetFullByFilter(status, groupId, null, null, null);
+    }
+
+    public IEnumerable<EmployeeFullDto> GetFullByFilter(EmployeeStatus? employeeStatus, Guid? groupId, EmployeeActivationStatus? activationStatus, EmployeeType? employeeType, bool? isAdministrator)
+    {
+        var users = GetByFilter(employeeStatus, groupId, activationStatus, employeeType, isAdministrator).AsEnumerable();
+
+        return users.Select(u => _employeeFullDtoHelper.GetFull(u));
+    }
+
+    public Module GetModule()
+    {
+        var product = new PeopleProduct();
+        product.Init();
+
+        return new Module(product);
+    }
+
+    public IEnumerable<EmployeeFullDto> GetSearch(string query)
+    {
+        if (_coreBaseSettings.Personal)
+        {
+            throw new MethodAccessException("Method not available");
+        }
+
+        try
+        {
+            var groupId = Guid.Empty;
+            if ("group".Equals(ApiContext.FilterBy, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(ApiContext.FilterValue))
+            {
+                groupId = new Guid(ApiContext.FilterValue);
+            }
+
+            var users = UserManager.Search(query, EmployeeStatus.Active, groupId);
+
+            return users.Select(u => _employeeFullDtoHelper.GetFull(u));
+        }
+        catch (Exception error)
+        {
+            _logger.Error(error);
+        }
+
+        return null;
+    }
+
+    public IEnumerable<EmployeeDto> GetSimpleByFilter(EmployeeStatus? employeeStatus, Guid? groupId, EmployeeActivationStatus? activationStatus, EmployeeType? employeeType, bool? isAdministrator)
+    {
+        var users = GetByFilter(employeeStatus, groupId, activationStatus, employeeType, isAdministrator);
+
+        return users.Select(u => _employeeDtoHelper.Get(u));
+    }
+
+    public Task<string> RegisterUserOnPersonalAsync(RegisterPersonalUserRequestDto model, HttpRequest request)
+    {
+        if (!_coreBaseSettings.Personal)
+        {
+            throw new MethodAccessException("Method is only available on personal.onlyoffice.com");
+        }
+
+        return InternalRegisterUserOnPersonalAsync(model, request);
+    }
+
+    public IEnumerable<EmployeeFullDto> RemoveUsers(UpdateMembersRequestDto model)
+    {
+        PermissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
+
+        CheckReassignProccess(model.UserIds);
+
+        var users = model.UserIds.Select(userId => UserManager.GetUsers(userId))
+            .Where(u => !UserManager.IsSystemUser(u.ID) && !u.IsLDAP())
+            .ToList();
+
+        var userNames = users.Select(x => x.DisplayUserName(false, DisplayUserSettingsHelper)).ToList();
+
+        foreach (var user in users)
+        {
+            if (user.Status != EmployeeStatus.Terminated)
+            {
+                continue;
+            }
+
+            UserPhotoManager.RemovePhoto(user.ID);
+            UserManager.DeleteUser(user.ID);
+            _queueWorkerRemove.Start(Tenant.TenantId, user, SecurityContext.CurrentAccount.ID, false);
+        }
+
+        MessageService.Send(MessageAction.UsersDeleted, MessageTarget.Create(users.Select(x => x.ID)), userNames);
+
+        return users.Select(u => _employeeFullDtoHelper.GetFull(u));
+    }
+
+    public IEnumerable<EmployeeFullDto> ResendUserInvites(UpdateMembersRequestDto model)
+    {
+        var users = model.UserIds
+            .Where(userId => !UserManager.IsSystemUser(userId))
+            .Select(userId => UserManager.GetUsers(userId))
+            .ToList();
+
+        foreach (var user in users)
+        {
+            if (user.IsActive)
+            {
+                continue;
+            }
+
+            var viewer = UserManager.GetUsers(SecurityContext.CurrentAccount.ID);
+
+            if (viewer == null)
+            {
+                throw new Exception(Resource.ErrorAccessDenied);
+            }
+
+            if (viewer.IsAdmin(UserManager) || viewer.ID == user.ID)
+            {
+                if (user.ActivationStatus == EmployeeActivationStatus.Activated)
+                {
+                    user.ActivationStatus = EmployeeActivationStatus.NotActivated;
+                }
+                if (user.ActivationStatus == (EmployeeActivationStatus.AutoGenerated | EmployeeActivationStatus.Activated))
+                {
+                    user.ActivationStatus = EmployeeActivationStatus.AutoGenerated;
+                }
+
+                UserManager.SaveUserInfo(user);
+            }
+
+            if (user.ActivationStatus == EmployeeActivationStatus.Pending)
+            {
+                if (user.IsVisitor(UserManager))
+                {
+                    StudioNotifyService.GuestInfoActivation(user);
+                }
+                else
+                {
+                    StudioNotifyService.UserInfoActivation(user);
+                }
+            }
+            else
+            {
+                StudioNotifyService.SendEmailActivationInstructions(user, user.Email);
+            }
+        }
+
+        MessageService.Send(MessageAction.UsersSentActivationInstructions, MessageTarget.Create(users.Select(x => x.ID)), users.Select(x => x.DisplayUserName(false, DisplayUserSettingsHelper)));
+
+        return users.Select(u => _employeeFullDtoHelper.GetFull(u));
+    }
+
+    public EmployeeDto Self()
+    {
+        var user = UserManager.GetUser(SecurityContext.CurrentAccount.ID, EmployeeFullDtoHelper.GetExpression(ApiContext));
+
+        return _employeeFullDtoHelper.GetFull(user);
+    }
+
+    public object SendEmailChangeInstructions(UpdateMemberRequestDto model)
+    {
+        Guid.TryParse(model.UserId, out var userid);
+
+        if (userid == Guid.Empty)
+        {
+            throw new ArgumentNullException("userid");
+        }
+
+        var email = (model.Email ?? "").Trim();
+
+        if (string.IsNullOrEmpty(email))
+        {
+            throw new Exception(Resource.ErrorEmailEmpty);
+        }
+
+        if (!email.TestEmailRegex())
+        {
+            throw new Exception(Resource.ErrorNotCorrectEmail);
+        }
+
+        var viewer = UserManager.GetUsers(SecurityContext.CurrentAccount.ID);
+        var user = UserManager.GetUsers(userid);
+
+        if (user == null)
+        {
+            throw new Exception(Resource.ErrorUserNotFound);
+        }
+
+        if (viewer == null || (user.IsOwner(Tenant) && viewer.ID != user.ID))
+        {
+            throw new Exception(Resource.ErrorAccessDenied);
+        }
+
+        var existentUser = UserManager.GetUserByEmail(email);
+
+        if (existentUser.ID != Constants.LostUser.ID)
+        {
+            throw new Exception(_customNamingPeople.Substitute<Resource>("ErrorEmailAlreadyExists"));
+        }
+
+        if (!viewer.IsAdmin(UserManager))
+        {
+            StudioNotifyService.SendEmailChangeInstructions(user, email);
+        }
+        else
+        {
+            if (email == user.Email)
+            {
+                throw new Exception(Resource.ErrorEmailsAreTheSame);
+            }
+
+            user.Email = email;
+            user.ActivationStatus = EmployeeActivationStatus.NotActivated;
+            UserManager.SaveUserInfo(user);
+            StudioNotifyService.SendEmailActivationInstructions(user, email);
+        }
+
+        MessageService.Send(MessageAction.UserSentEmailChangeInstructions, user.DisplayUserName(false, DisplayUserSettingsHelper));
+
+        return string.Format(Resource.MessageEmailChangeInstuctionsSentOnEmail, email);
+    }
+
+    public object SendUserPassword(MemberRequestDto memberModel)
+    {
+        string error = _userManagerWrapper.SendUserPassword(memberModel.Email);
+        if (!string.IsNullOrEmpty(error))
+        {
+            _logger.ErrorFormat("Password recovery ({0}): {1}", memberModel.Email, error);
+        }
+
+        return string.Format(Resource.MessageYourPasswordSendedToEmail, memberModel.Email);
+    }
+
+    public IEnumerable<EmployeeFullDto> UpdateEmployeeActivationStatus(EmployeeActivationStatus activationstatus, UpdateMembersRequestDto model)
+    {
+        ApiContext.AuthByClaim();
+
+        var retuls = new List<EmployeeFullDto>();
+        foreach (var id in model.UserIds.Where(userId => !UserManager.IsSystemUser(userId)))
+        {
+            PermissionContext.DemandPermissions(new UserSecurityProvider(id), Constants.Action_EditUser);
+            var u = UserManager.GetUsers(id);
+            if (u.ID == Constants.LostUser.ID || u.IsLDAP())
+            {
+                continue;
+            }
+
+            u.ActivationStatus = activationstatus;
+            UserManager.SaveUserInfo(u);
+            retuls.Add(_employeeFullDtoHelper.GetFull(u));
+        }
+
+        return retuls;
+    }
+
+    public EmployeeFullDto UpdateMember(string userid, UpdateMemberRequestDto memberModel)
+    {
+        var user = GetUserInfo(userid);
+
+        if (UserManager.IsSystemUser(user.ID))
+        {
+            throw new SecurityException();
+        }
+
+        PermissionContext.DemandPermissions(new UserSecurityProvider(user.ID), Constants.Action_EditUser);
+        var self = SecurityContext.CurrentAccount.ID.Equals(user.ID);
+        var resetDate = new DateTime(1900, 01, 01);
+
+        //Update it
+
+        var isLdap = user.IsLDAP();
+        var isSso = user.IsSSO();
+        var isAdmin = _webItemSecurity.IsProductAdministrator(WebItemManager.PeopleProductID, SecurityContext.CurrentAccount.ID);
+
+        if (!isLdap && !isSso)
+        {
+            //Set common fields
+
+            user.FirstName = memberModel.Firstname ?? user.FirstName;
+            user.LastName = memberModel.Lastname ?? user.LastName;
+            user.Location = memberModel.Location ?? user.Location;
+
+            if (isAdmin)
+            {
+                user.Title = memberModel.Title ?? user.Title;
+            }
+        }
+
+        if (!_userFormatter.IsValidUserName(user.FirstName, user.LastName))
+        {
+            throw new Exception(Resource.ErrorIncorrectUserName);
+        }
+
+        user.Notes = memberModel.Comment ?? user.Notes;
+        user.Sex = ("male".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase)
+            ? true
+            : ("female".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase) ? (bool?)false : null)) ?? user.Sex;
+
+        user.BirthDate = memberModel.Birthday != null ? _tenantUtil.DateTimeFromUtc(memberModel.Birthday) : user.BirthDate;
+
+        if (user.BirthDate == resetDate)
+        {
+            user.BirthDate = null;
+        }
+
+        user.WorkFromDate = memberModel.Worksfrom != null ? _tenantUtil.DateTimeFromUtc(memberModel.Worksfrom) : user.WorkFromDate;
+
+        if (user.WorkFromDate == resetDate)
+        {
+            user.WorkFromDate = null;
+        }
+
+        //Update contacts
+        UpdateContacts(memberModel.Contacts, user);
+        UpdateDepartments(memberModel.Department, user);
+
+        if (memberModel.Files != UserPhotoManager.GetPhotoAbsoluteWebPath(user.ID))
+        {
+            UpdatePhotoUrl(memberModel.Files, user);
+        }
+        if (memberModel.Disable.HasValue)
+        {
+            user.Status = memberModel.Disable.Value ? EmployeeStatus.Terminated : EmployeeStatus.Active;
+            user.TerminatedDate = memberModel.Disable.Value ? DateTime.UtcNow : null;
+        }
+        if (self && !isAdmin)
+        {
+            StudioNotifyService.SendMsgToAdminAboutProfileUpdated();
+        }
+
+        // change user type
+        var canBeGuestFlag = !user.IsOwner(Tenant) && !user.IsAdmin(UserManager) && user.GetListAdminModules(_webItemSecurity).Count == 0 && !user.IsMe(AuthContext);
+
+        if (memberModel.IsVisitor && !user.IsVisitor(UserManager) && canBeGuestFlag)
+        {
+            UserManager.AddUserIntoGroup(user.ID, Constants.GroupVisitor.ID);
+            _webItemSecurityCache.ClearCache(Tenant.TenantId);
+        }
+
+        if (!self && !memberModel.IsVisitor && user.IsVisitor(UserManager))
+        {
+            var usersQuota = _tenantExtra.GetTenantQuota().ActiveUsers;
+            if (_tenantStatisticsProvider.GetUsersCount() < usersQuota)
+            {
+                UserManager.RemoveUserFromGroup(user.ID, Constants.GroupVisitor.ID);
+                _webItemSecurityCache.ClearCache(Tenant.TenantId);
+            }
+            else
+            {
+                throw new TenantQuotaException(string.Format("Exceeds the maximum active users ({0})", usersQuota));
+            }
+        }
+
+        UserManager.SaveUserInfo(user);
+        MessageService.Send(MessageAction.UserUpdated, MessageTarget.Create(user.ID), user.DisplayUserName(false, DisplayUserSettingsHelper));
+
+        if (memberModel.Disable.HasValue && memberModel.Disable.Value)
+        {
+            _cookiesManager.ResetUserCookie(user.ID);
+            MessageService.Send(MessageAction.CookieSettingsUpdated);
+        }
+
+        return _employeeFullDtoHelper.GetFull(user);
+    }
+
+    public EmployeeFullDto UpdateMemberCulture(string userid, UpdateMemberRequestDto memberModel)
+    {
+        var user = GetUserInfo(userid);
+
+        if (UserManager.IsSystemUser(user.ID))
+        {
+            throw new SecurityException();
+        }
+
+        PermissionContext.DemandPermissions(new UserSecurityProvider(user.ID), Constants.Action_EditUser);
+
+        var curLng = user.CultureName;
+
+        if (SetupInfo.EnabledCultures.Find(c => string.Equals(c.Name, memberModel.CultureName, StringComparison.InvariantCultureIgnoreCase)) != null)
+        {
+            if (curLng != memberModel.CultureName)
+            {
+                user.CultureName = memberModel.CultureName;
+
+                try
+                {
+                    UserManager.SaveUserInfo(user);
+                }
+                catch
+                {
+                    user.CultureName = curLng;
+                    throw;
+                }
+
+                MessageService.Send(MessageAction.UserUpdatedLanguage, MessageTarget.Create(user.ID), user.DisplayUserName(false, DisplayUserSettingsHelper));
+
+            }
+        }
+
+        return _employeeFullDtoHelper.GetFull(user);
+    }
+
+    public IEnumerable<EmployeeFullDto> UpdateUserStatus(EmployeeStatus status, UpdateMembersRequestDto model)
+    {
+        PermissionContext.DemandPermissions(Constants.Action_EditUser);
+
+        var users = model.UserIds.Select(userId => UserManager.GetUsers(userId))
+            .Where(u => !UserManager.IsSystemUser(u.ID) && !u.IsLDAP())
+            .ToList();
+
+        foreach (var user in users)
+        {
+            if (user.IsOwner(Tenant) || user.IsMe(AuthContext))
+            {
+                continue;
+            }
+
+            switch (status)
+            {
+                case EmployeeStatus.Active:
+                    if (user.Status == EmployeeStatus.Terminated)
+                    {
+                        if (_tenantStatisticsProvider.GetUsersCount() < _tenantExtra.GetTenantQuota().ActiveUsers || user.IsVisitor(UserManager))
+                        {
+                            user.Status = EmployeeStatus.Active;
+                            UserManager.SaveUserInfo(user);
+                        }
+                    }
+                    break;
+                case EmployeeStatus.Terminated:
+                    user.Status = EmployeeStatus.Terminated;
+                    UserManager.SaveUserInfo(user);
+
+                    _cookiesManager.ResetUserCookie(user.ID);
+                    MessageService.Send(MessageAction.CookieSettingsUpdated);
+                    break;
+            }
+        }
+
+        MessageService.Send(MessageAction.UsersUpdatedStatus, MessageTarget.Create(users.Select(x => x.ID)), users.Select(x => x.DisplayUserName(false, DisplayUserSettingsHelper)));
+
+        return users.Select(u => _employeeFullDtoHelper.GetFull(u));
+    }
+
+    public IEnumerable<EmployeeFullDto> UpdateUserType(EmployeeType type, UpdateMembersRequestDto model)
+    {
+        var users = model.UserIds
+            .Where(userId => !UserManager.IsSystemUser(userId))
+            .Select(userId => UserManager.GetUsers(userId))
+            .ToList();
+
+        foreach (var user in users)
+        {
+            if (user.IsOwner(Tenant) || user.IsAdmin(UserManager)
+                || user.IsMe(AuthContext) || user.GetListAdminModules(_webItemSecurity).Count > 0)
+            {
+                continue;
+            }
+
+            switch (type)
+            {
+                case EmployeeType.User:
+                    if (user.IsVisitor(UserManager))
+                    {
+                        if (_tenantStatisticsProvider.GetUsersCount() < _tenantExtra.GetTenantQuota().ActiveUsers)
+                        {
+                            UserManager.RemoveUserFromGroup(user.ID, Constants.GroupVisitor.ID);
+                            _webItemSecurityCache.ClearCache(Tenant.TenantId);
+                        }
+                    }
+                    break;
+                case EmployeeType.Visitor:
+                    if (_coreBaseSettings.Standalone || _tenantStatisticsProvider.GetVisitorsCount() < _tenantExtra.GetTenantQuota().ActiveUsers * _constants.CoefficientOfVisitors)
+                    {
+                        UserManager.AddUserIntoGroup(user.ID, Constants.GroupVisitor.ID);
+                        _webItemSecurityCache.ClearCache(Tenant.TenantId);
+                    }
+                    break;
+            }
+        }
+
+        MessageService.Send(MessageAction.UsersUpdatedType, MessageTarget.Create(users.Select(x => x.ID)), users.Select(x => x.DisplayUserName(false, DisplayUserSettingsHelper)));
+
+        return users.Select(u => _employeeFullDtoHelper.GetFull(u));
+    }
+
+    private void CheckReassignProccess(IEnumerable<Guid> userIds)
+    {
+        foreach (var userId in userIds)
+        {
+            var reassignStatus = _queueWorkerReassign.GetProgressItemStatus(Tenant.TenantId, userId);
+            if (reassignStatus == null || reassignStatus.IsCompleted)
+            {
+                continue;
+            }
+
+            var userName = UserManager.GetUsers(userId).DisplayUserName(DisplayUserSettingsHelper);
+
+            throw new Exception(string.Format(Resource.ReassignDataRemoveUserError, userName));
+        }
+    }
+
+    private IQueryable<UserInfo> GetByFilter(EmployeeStatus? employeeStatus, Guid? groupId, EmployeeActivationStatus? activationStatus, EmployeeType? employeeType, bool? isAdministrator)
+    {
+        if (_coreBaseSettings.Personal)
+        {
+            throw new MethodAccessException("Method not available");
+        }
+
+        var isAdmin = UserManager.GetUsers(SecurityContext.CurrentAccount.ID).IsAdmin(UserManager) ||
+                      _webItemSecurity.IsProductAdministrator(WebItemManager.PeopleProductID, SecurityContext.CurrentAccount.ID);
+
+        var includeGroups = new List<List<Guid>>();
+        if (groupId.HasValue)
+        {
+            includeGroups.Add(new List<Guid> { groupId.Value });
+        }
+
+        var excludeGroups = new List<Guid>();
+
+        if (employeeType != null)
+        {
+            switch (employeeType)
+            {
+                case EmployeeType.User:
+                    excludeGroups.Add(Constants.GroupVisitor.ID);
+                    break;
+                case EmployeeType.Visitor:
+                    includeGroups.Add(new List<Guid> { Constants.GroupVisitor.ID });
+                    break;
+            }
+        }
+
+        if (isAdministrator.HasValue && isAdministrator.Value)
+        {
+            var adminGroups = new List<Guid>
+            {
+                    Constants.GroupAdmin.ID
+            };
+            var products = _webItemManager.GetItemsAll().Where(i => i is IProduct || i.ID == WebItemManager.MailProductID);
+            adminGroups.AddRange(products.Select(r => r.ID));
+
+            includeGroups.Add(adminGroups);
+        }
+
+        var users = UserManager.GetUsers(isAdmin, employeeStatus, includeGroups, excludeGroups, activationStatus, ApiContext.FilterValue, ApiContext.SortBy, !ApiContext.SortDescending, ApiContext.Count, ApiContext.StartIndex, out var total, out var count);
+
+        ApiContext.SetTotalCount(total).SetCount(count);
+
+        return users;
+    }
+
+    private async Task<string> InternalRegisterUserOnPersonalAsync(RegisterPersonalUserRequestDto model, HttpRequest request)
+    {
+        try
+        {
+            if (_coreBaseSettings.CustomMode) model.Lang = "ru-RU";
+
+            var cultureInfo = SetupInfo.GetPersonalCulture(model.Lang).Value;
+
+            if (cultureInfo != null)
+            {
+                Thread.CurrentThread.CurrentUICulture = cultureInfo;
+            }
+
+            model.Email.ThrowIfNull(new ArgumentException(Resource.ErrorEmailEmpty, "email"));
+
+            if (!model.Email.TestEmailRegex()) throw new ArgumentException(Resource.ErrorNotCorrectEmail, "email");
+
+            if (!SetupInfo.IsSecretEmail(model.Email)
+                && !string.IsNullOrEmpty(SetupInfo.RecaptchaPublicKey) && !string.IsNullOrEmpty(SetupInfo.RecaptchaPrivateKey))
+            {
+                var ip = request.Headers["X-Forwarded-For"].ToString() ?? request.GetUserHostAddress();
+
+                if (string.IsNullOrEmpty(model.RecaptchaResponse)
+                    || !await _recaptcha.ValidateRecaptchaAsync(model.RecaptchaResponse, ip))
+                {
+                    throw new RecaptchaException(Resource.RecaptchaInvalid);
+                }
+            }
+
+            var newUserInfo = UserManager.GetUserByEmail(model.Email);
+
+            if (UserManager.UserExists(newUserInfo.ID))
+            {
+                if (!SetupInfo.IsSecretEmail(model.Email) || SecurityContext.IsAuthenticated)
+                {
+                    StudioNotifyService.SendAlreadyExist(model.Email);
+                    return string.Empty;
+                }
+
+                try
+                {
+                    SecurityContext.AuthenticateMe(ASC.Core.Configuration.Constants.CoreSystem);
+                    UserManager.DeleteUser(newUserInfo.ID);
+                }
+                finally
+                {
+                    SecurityContext.Logout();
+                }
+            }
+            if (!model.Spam)
+            {
+                try
+                {
+                    //TODO
+                    //const string _databaseID = "com";
+                    //using (var db = DbManager.FromHttpContext(_databaseID))
+                    //{
+                    //    db.ExecuteNonQuery(new SqlInsert("template_unsubscribe", false)
+                    //                           .InColumnValue("email", email.ToLowerInvariant())
+                    //                           .InColumnValue("reason", "personal")
+                    //        );
+                    //    Log.Debug(String.Format("Write to template_unsubscribe {0}", email.ToLowerInvariant()));
+                    //}
+                }
+                catch (Exception ex)
+                {
+                    _logger.Debug($"ERROR write to template_unsubscribe {ex.Message}, email:{model.Email.ToLowerInvariant()}");
+                }
+            }
+
+            StudioNotifyService.SendInvitePersonal(model.Email);
+        }
+        catch (Exception ex)
+        {
+            return ex.Message;
+        }
+
+        return string.Empty;
+    }
+
+    private void UpdateDepartments(IEnumerable<Guid> department, UserInfo user)
+    {
+        if (!PermissionContext.CheckPermissions(Constants.Action_EditGroups))
+        {
+            return;
+        }
+
+        if (department == null)
+        {
+            return;
+        }
+
+        var groups = UserManager.GetUserGroups(user.ID);
+        var managerGroups = new List<Guid>();
+        foreach (var groupInfo in groups)
+        {
+            UserManager.RemoveUserFromGroup(user.ID, groupInfo.ID);
+            var managerId = UserManager.GetDepartmentManager(groupInfo.ID);
+            if (managerId == user.ID)
+            {
+                managerGroups.Add(groupInfo.ID);
+                UserManager.SetDepartmentManager(groupInfo.ID, Guid.Empty);
+            }
+        }
+        foreach (var guid in department)
+        {
+            var userDepartment = UserManager.GetGroupInfo(guid);
+            if (userDepartment != Constants.LostGroupInfo)
+            {
+                UserManager.AddUserIntoGroup(user.ID, guid);
+                if (managerGroups.Contains(guid))
+                {
+                    UserManager.SetDepartmentManager(guid, user.ID);
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/products/ASC.People/Server/GlobalUsings.cs b/products/ASC.People/Server/GlobalUsings.cs
index de1d92052c..c0741fa562 100644
--- a/products/ASC.People/Server/GlobalUsings.cs
+++ b/products/ASC.People/Server/GlobalUsings.cs
@@ -30,6 +30,7 @@ global using ASC.FederatedLogin.Profile;
 global using ASC.MessagingSystem.Core;
 global using ASC.MessagingSystem.Models;
 global using ASC.People;
+global using ASC.People.ApiHelpers;
 global using ASC.People.Api;
 global using ASC.People.ApiModels.RequestDto;
 global using ASC.People.ApiModels.ResponseDto;
@@ -46,8 +47,6 @@ global using ASC.Web.Studio.Core.Notify;
 global using ASC.Web.Studio.UserControls.Statistics;
 global using ASC.Web.Studio.Utility;
 
-global using AutoMapper;
-
 global using Autofac;
 global using Autofac.Extensions.DependencyInjection;
 
diff --git a/products/ASC.People/Server/PeopleProduct.cs b/products/ASC.People/Server/PeopleProduct.cs
index f010ff87e8..59aa2b4f10 100644
--- a/products/ASC.People/Server/PeopleProduct.cs
+++ b/products/ASC.People/Server/PeopleProduct.cs
@@ -1,81 +1,35 @@
-namespace ASC.People
+namespace ASC.People;
+
+public class PeopleProduct : Product
 {
-    public class PeopleProduct : Product
+    internal const string ProductPath = "/products/people/";
+
+    private ProductContext _context;
+    public static Guid ID => new Guid("{F4D98AFD-D336-4332-8778-3C6945C81EA0}");
+    public override bool Visible => true;
+    public override ProductContext Context => _context;
+    public override string Name => PeopleResource.ProductName;
+    public override string Description => PeopleResource.ProductDescription;
+    public override string ExtendedDescription => PeopleResource.ProductDescription;
+    public override Guid ProductID => ID;
+    public override string StartURL => ProductPath;
+    public override string HelpURL => string.Concat(ProductPath, "help.aspx");
+    public override string ProductClassName => "people";
+    public override string ApiURL => "api/2.0/people/info.json";
+    public override bool IsPrimary { get => false; }
+
+    public override void Init()
     {
-        internal const string ProductPath = "/products/people/";
-
-        private ProductContext _context;
-
-        public static Guid ID
+        _context = new ProductContext
         {
-            get { return new Guid("{F4D98AFD-D336-4332-8778-3C6945C81EA0}"); }
-        }
+            DisabledIconFileName = "product_disabled_logo.png",
+            IconFileName = "images/people.menu.svg",
+            LargeIconFileName = "images/people.svg",
+            DefaultSortOrder = 50,
+            AdminOpportunities = () => PeopleResource.ProductAdminOpportunities.Split('|').ToList(),
+            UserOpportunities = () => PeopleResource.ProductUserOpportunities.Split('|').ToList()
+        };
 
-        public override bool Visible { get { return true; } }
-
-        public override ProductContext Context
-        {
-            get { return _context; }
-        }
-
-        public override string Name
-        {
-            get { return PeopleResource.ProductName; }
-        }
-
-        public override string Description
-        {
-            get { return PeopleResource.ProductDescription; }
-        }
-
-        public override string ExtendedDescription
-        {
-            get { return PeopleResource.ProductDescription; }
-        }
-
-        public override Guid ProductID
-        {
-            get { return ID; }
-        }
-
-        public override string StartURL
-        {
-            get { return ProductPath; }
-        }
-
-        public override string HelpURL
-        {
-            get { return string.Concat(ProductPath, "help.aspx"); }
-        }
-
-        public override string ProductClassName
-        {
-            get { return "people"; }
-        }
-
-        public override string ApiURL
-        {
-            get
-            {
-                return "api/2.0/people/info.json";
-            }
-        }
-
-        public override bool IsPrimary { get => false; }
-
-        public override void Init()
-        {
-            _context = new ProductContext
-            {
-                DisabledIconFileName = "product_disabled_logo.png",
-                IconFileName = "images/people.menu.svg",
-                LargeIconFileName = "images/people.svg",
-                DefaultSortOrder = 50,
-                AdminOpportunities = () => PeopleResource.ProductAdminOpportunities.Split('|').ToList(),
-                UserOpportunities = () => PeopleResource.ProductUserOpportunities.Split('|').ToList()
-            };
-
-            //SearchHandlerManager.Registry(new SearchHandler());
-        }
+        //SearchHandlerManager.Registry(new SearchHandler());
     }
 }
diff --git a/products/ASC.People/Server/Startup.cs b/products/ASC.People/Server/Startup.cs
index 43ff7771bb..562a32f55f 100644
--- a/products/ASC.People/Server/Startup.cs
+++ b/products/ASC.People/Server/Startup.cs
@@ -13,12 +13,27 @@ public class Startup : BaseStartup
         base.ConfigureServices(services);
 
         DIHelper.TryAdd<UserController>();
+        DIHelper.TryAdd<UserControllerEngine>();
+
         DIHelper.TryAdd<ContactsController>();
+        DIHelper.TryAdd<ContactsControllerEngine>();
+
         DIHelper.TryAdd<NotificationController>();
+        DIHelper.TryAdd<NotificationControllerEngine>();
+
         DIHelper.TryAdd<PhotoController>();
+        DIHelper.TryAdd<PhotoControllerEngine>();
+
         DIHelper.TryAdd<ReassignController>();
+        DIHelper.TryAdd<ReassignControllerEngine>();
+
         DIHelper.TryAdd<RemoveUserDataController>();
+        DIHelper.TryAdd<RemoveUserDataController>();
+
         DIHelper.TryAdd<ThirdpartyController>();
+        DIHelper.TryAdd<ThirdpartyControllerEngine>();
+
         DIHelper.TryAdd<GroupController>();
+        DIHelper.TryAdd<GroupControllerEngine>();
     }
 }
\ No newline at end of file

From 2719149f3ded78054ec00e1c14997d82ff04df75 Mon Sep 17 00:00:00 2001
From: MaksimChegulov <maksim.chegulov@onlyoffice.com>
Date: Tue, 1 Mar 2022 14:58:37 +0300
Subject: [PATCH 19/28] People: used imlicit usings

---
 products/ASC.People/Server/ASC.People.csproj |  1 +
 products/ASC.People/Server/GlobalUsings.cs   | 15 +--------------
 2 files changed, 2 insertions(+), 14 deletions(-)

diff --git a/products/ASC.People/Server/ASC.People.csproj b/products/ASC.People/Server/ASC.People.csproj
index 27c2945ebb..1373643a49 100644
--- a/products/ASC.People/Server/ASC.People.csproj
+++ b/products/ASC.People/Server/ASC.People.csproj
@@ -10,6 +10,7 @@
     <AssemblyTitle>ASC.People</AssemblyTitle>
     <Company>Ascensio System SIA</Company>
     <Product>ASC.People</Product>
+	<ImplicitUsings>enable</ImplicitUsings>
     <Copyright>(c) Ascensio System SIA. All rights reserved</Copyright>
   </PropertyGroup>
 
diff --git a/products/ASC.People/Server/GlobalUsings.cs b/products/ASC.People/Server/GlobalUsings.cs
index c0741fa562..8b424df4ce 100644
--- a/products/ASC.People/Server/GlobalUsings.cs
+++ b/products/ASC.People/Server/GlobalUsings.cs
@@ -1,14 +1,7 @@
-global using System;
-global using System.Collections.Generic;
-global using System.IO;
-global using System.Linq;
-global using System.Net.Http;
-global using System.Net.Mail;
+global using System.Net.Mail;
 global using System.Runtime.InteropServices;
 global using System.Security;
 global using System.ServiceModel.Security;
-global using System.Threading;
-global using System.Threading.Tasks;
 global using System.Web;
 
 global using ASC.Api.Core;
@@ -51,14 +44,8 @@ global using Autofac;
 global using Autofac.Extensions.DependencyInjection;
 
 global using Microsoft.AspNetCore.Authorization;
-global using Microsoft.AspNetCore.Builder;
-global using Microsoft.AspNetCore.Hosting;
-global using Microsoft.AspNetCore.Http;
 global using Microsoft.AspNetCore.Http.Extensions;
 global using Microsoft.AspNetCore.Mvc;
-global using Microsoft.Extensions.Configuration;
-global using Microsoft.Extensions.DependencyInjection;
-global using Microsoft.Extensions.Hosting;
 global using Microsoft.Extensions.Options;
 global using Microsoft.Extensions.Hosting.WindowsServices;
 

From 0600452b87ecaa33551f25b98f88a9748b6df67f Mon Sep 17 00:00:00 2001
From: MaksimChegulov <maksim.chegulov@onlyoffice.com>
Date: Wed, 2 Mar 2022 21:24:45 +0300
Subject: [PATCH 20/28] People: renamed

---
 .../ApiEngines/ApiControllerEngineBase.cs     |  34 +--
 .../ApiEngines/ContactsControllerEngine.cs    |  14 +-
 .../NotificationControllerEngine.cs           |  14 +-
 .../ApiEngines/PeopleControllerEngine.cs      |  24 +-
 .../ApiEngines/PhotoControllerEngine.cs       |  68 ++---
 .../ApiEngines/ReassignControllerEngine.cs    |  16 +-
 .../RemoveUserDataControllerEngine.cs         |  18 +-
 .../ApiEngines/ThirdpartyControllerEngine.cs  |  28 +-
 .../Server/ApiEngines/UserControllerEngine.cs | 282 +++++++++---------
 9 files changed, 249 insertions(+), 249 deletions(-)

diff --git a/products/ASC.People/Server/ApiEngines/ApiControllerEngineBase.cs b/products/ASC.People/Server/ApiEngines/ApiControllerEngineBase.cs
index 9195452866..bd21f02d7d 100644
--- a/products/ASC.People/Server/ApiEngines/ApiControllerEngineBase.cs
+++ b/products/ASC.People/Server/ApiEngines/ApiControllerEngineBase.cs
@@ -4,14 +4,14 @@ namespace ASC.People.ApiHelpers;
 
 public abstract class ApiControllerEngineBase
 {
-    protected readonly ApiContext ApiContext;
-    protected readonly AuthContext AuthContext;
-    protected readonly MessageService MessageService;
-    protected readonly MessageTarget MessageTarget;
-    protected readonly PermissionContext PermissionContext;
-    protected readonly SecurityContext SecurityContext;
-    protected readonly StudioNotifyService StudioNotifyService;
-    protected readonly UserManager UserManager;
+    protected readonly ApiContext _apiContext;
+    protected readonly AuthContext _authContext;
+    protected readonly MessageService _messageService;
+    protected readonly MessageTarget _messageTarget;
+    protected readonly PermissionContext _permissionContext;
+    protected readonly SecurityContext _securityContext;
+    protected readonly StudioNotifyService _studioNotifyService;
+    protected readonly UserManager _userManager;
 
     protected ApiControllerEngineBase(
         UserManager userManager,
@@ -23,15 +23,15 @@ public abstract class ApiControllerEngineBase
         MessageTarget messageTarget,
         StudioNotifyService studioNotifyService)
     {
-        UserManager = userManager;
-        AuthContext = authContext;
-        ApiContext = apiContext;
-        PermissionContext = permissionContext;
-        SecurityContext = securityContext;
-        MessageService = messageService;
-        MessageTarget = messageTarget;
-        StudioNotifyService = studioNotifyService;
+        _userManager = userManager;
+        _authContext = authContext;
+        _apiContext = apiContext;
+        _permissionContext = permissionContext;
+        _securityContext = securityContext;
+        _messageService = messageService;
+        _messageTarget = messageTarget;
+        _studioNotifyService = studioNotifyService;
     }
 
-    protected Tenant Tenant => ApiContext.Tenant;
+    protected Tenant Tenant => _apiContext.Tenant;
 }
\ No newline at end of file
diff --git a/products/ASC.People/Server/ApiEngines/ContactsControllerEngine.cs b/products/ASC.People/Server/ApiEngines/ContactsControllerEngine.cs
index 4101b2bba3..19a09a9e60 100644
--- a/products/ASC.People/Server/ApiEngines/ContactsControllerEngine.cs
+++ b/products/ASC.People/Server/ApiEngines/ContactsControllerEngine.cs
@@ -39,7 +39,7 @@ public class ContactsControllerEngine : PeopleControllerEngine
 
     public void DeleteContacts(IEnumerable<Contact> contacts, UserInfo user)
     {
-        PermissionContext.DemandPermissions(new UserSecurityProvider(user.Id), Constants.Action_EditUser);
+        _permissionContext.DemandPermissions(new UserSecurityProvider(user.Id), Constants.Action_EditUser);
         if (contacts == null)
         {
             return;
@@ -65,13 +65,13 @@ public class ContactsControllerEngine : PeopleControllerEngine
     {
         var user = GetUserInfo(userid);
 
-        if (UserManager.IsSystemUser(user.Id))
+        if (_userManager.IsSystemUser(user.Id))
         {
             throw new SecurityException();
         }
 
         DeleteContacts(memberModel.Contacts, user);
-        UserManager.SaveUserInfo(user);
+        _userManager.SaveUserInfo(user);
 
         return _employeeFullDtoHelper.GetFull(user);
     }
@@ -80,14 +80,14 @@ public class ContactsControllerEngine : PeopleControllerEngine
     {
         var user = GetUserInfo(userid);
 
-        if (UserManager.IsSystemUser(user.Id))
+        if (_userManager.IsSystemUser(user.Id))
         {
             throw new SecurityException();
         }
 
         user.ContactsList.Clear();
         UpdateContacts(memberModel.Contacts, user);
-        UserManager.SaveUserInfo(user);
+        _userManager.SaveUserInfo(user);
 
         return _employeeFullDtoHelper.GetFull(user);
     }
@@ -96,13 +96,13 @@ public class ContactsControllerEngine : PeopleControllerEngine
     {
         var user = GetUserInfo(userid);
 
-        if (UserManager.IsSystemUser(user.Id))
+        if (_userManager.IsSystemUser(user.Id))
         {
             throw new SecurityException();
         }
 
         UpdateContacts(memberModel.Contacts, user);
-        UserManager.SaveUserInfo(user);
+        _userManager.SaveUserInfo(user);
 
         return _employeeFullDtoHelper.GetFull(user);
     }
diff --git a/products/ASC.People/Server/ApiEngines/NotificationControllerEngine.cs b/products/ASC.People/Server/ApiEngines/NotificationControllerEngine.cs
index 6213f74ecb..1e97263842 100644
--- a/products/ASC.People/Server/ApiEngines/NotificationControllerEngine.cs
+++ b/products/ASC.People/Server/ApiEngines/NotificationControllerEngine.cs
@@ -31,13 +31,13 @@ public class NotificationControllerEngine : ApiControllerEngineBase
 
     public object SendNotificationToChange(string userId)
     {
-        var user = UserManager.GetUsers(
+        var user = _userManager.GetUsers(
             string.IsNullOrEmpty(userId)
-                ? SecurityContext.CurrentAccount.ID
+                ? _securityContext.CurrentAccount.ID
                 : new Guid(userId));
         var canChange =
-        user.IsMe(AuthContext)
-                    || PermissionContext.CheckPermissions(new UserSecurityProvider(user.Id), Constants.Action_EditUser);
+        user.IsMe(_authContext)
+                    || _permissionContext.CheckPermissions(new UserSecurityProvider(user.Id), Constants.Action_EditUser);
 
         if (!canChange)
         {
@@ -45,13 +45,13 @@ public class NotificationControllerEngine : ApiControllerEngineBase
         }
 
         user.MobilePhoneActivationStatus = MobilePhoneActivationStatus.NotActivated;
-        UserManager.SaveUserInfo(user);
-        if (user.IsMe(AuthContext))
+        _userManager.SaveUserInfo(user);
+        if (user.IsMe(_authContext))
         {
             return _commonLinkUtility.GetConfirmationUrl(user.Email, ConfirmType.PhoneActivation);
         }
 
-        StudioNotifyService.SendMsgMobilePhoneChange(user);
+        _studioNotifyService.SendMsgMobilePhoneChange(user);
 
         return string.Empty;
     }
diff --git a/products/ASC.People/Server/ApiEngines/PeopleControllerEngine.cs b/products/ASC.People/Server/ApiEngines/PeopleControllerEngine.cs
index cf5421f773..530f70bdd6 100644
--- a/products/ASC.People/Server/ApiEngines/PeopleControllerEngine.cs
+++ b/products/ASC.People/Server/ApiEngines/PeopleControllerEngine.cs
@@ -4,9 +4,9 @@ namespace ASC.People.ApiHelpers;
 
 public abstract class PeopleControllerEngine : ApiControllerEngineBase
 {
-    protected readonly DisplayUserSettingsHelper DisplayUserSettingsHelper;
-    protected readonly SetupInfo SetupInfo;
-    protected readonly UserPhotoManager UserPhotoManager;
+    protected readonly DisplayUserSettingsHelper _displayUserSettingsHelper;
+    protected readonly SetupInfo _setupInfo;
+    protected readonly UserPhotoManager _userPhotoManager;
     private readonly IHttpClientFactory _httpClientFactory;
 
     protected PeopleControllerEngine(
@@ -32,10 +32,10 @@ public abstract class PeopleControllerEngine : ApiControllerEngineBase
             messageTarget,
             studioNotifyService)
     {
-        UserPhotoManager = userPhotoManager;
+        _userPhotoManager = userPhotoManager;
         _httpClientFactory = httpClientFactory;
-        DisplayUserSettingsHelper = displayUserSettingsHelper;
-        SetupInfo = setupInfo;
+        _displayUserSettingsHelper = displayUserSettingsHelper;
+        _setupInfo = setupInfo;
     }
 
     protected UserInfo GetUserInfo(string userNameOrId)
@@ -44,11 +44,11 @@ public abstract class PeopleControllerEngine : ApiControllerEngineBase
         try
         {
             var userId = new Guid(userNameOrId);
-            user = UserManager.GetUsers(userId);
+            user = _userManager.GetUsers(userId);
         }
         catch (FormatException)
         {
-            user = UserManager.GetUserByUserName(userNameOrId);
+            user = _userManager.GetUserByUserName(userNameOrId);
         }
 
         if (user == null || user.Id == Constants.LostUser.Id)
@@ -61,7 +61,7 @@ public abstract class PeopleControllerEngine : ApiControllerEngineBase
 
     protected void UpdateContacts(IEnumerable<Contact> contacts, UserInfo user)
     {
-        PermissionContext.DemandPermissions(new UserSecurityProvider(user.Id), Constants.Action_EditUser);
+        _permissionContext.DemandPermissions(new UserSecurityProvider(user.Id), Constants.Action_EditUser);
 
         if (contacts == null)
         {
@@ -79,11 +79,11 @@ public abstract class PeopleControllerEngine : ApiControllerEngineBase
             return;
         }
 
-        PermissionContext.DemandPermissions(new UserSecurityProvider(user.Id), Constants.Action_EditUser);
+        _permissionContext.DemandPermissions(new UserSecurityProvider(user.Id), Constants.Action_EditUser);
 
         if (!files.StartsWith("http://") && !files.StartsWith("https://"))
         {
-            files = new Uri(ApiContext.HttpContextAccessor.HttpContext.Request.GetDisplayUrl()).GetLeftPart(UriPartial.Authority) + "/" + files.TrimStart('/');
+            files = new Uri(_apiContext.HttpContextAccessor.HttpContext.Request.GetDisplayUrl()).GetLeftPart(UriPartial.Authority) + "/" + files.TrimStart('/');
         }
         var request = new HttpRequestMessage();
         request.RequestUri = new Uri(files);
@@ -93,6 +93,6 @@ public abstract class PeopleControllerEngine : ApiControllerEngineBase
         using var inputStream = response.Content.ReadAsStream();
         using var br = new BinaryReader(inputStream);
         var imageByteArray = br.ReadBytes((int)inputStream.Length);
-        UserPhotoManager.SaveOrUpdatePhoto(user.Id, imageByteArray);
+        _userPhotoManager.SaveOrUpdatePhoto(user.Id, imageByteArray);
     }
 }
\ No newline at end of file
diff --git a/products/ASC.People/Server/ApiEngines/PhotoControllerEngine.cs b/products/ASC.People/Server/ApiEngines/PhotoControllerEngine.cs
index fcf164c7b6..ed475457ed 100644
--- a/products/ASC.People/Server/ApiEngines/PhotoControllerEngine.cs
+++ b/products/ASC.People/Server/ApiEngines/PhotoControllerEngine.cs
@@ -44,83 +44,83 @@ public class PhotoControllerEngine : PeopleControllerEngine
     {
         var user = GetUserInfo(userid);
 
-        if (UserManager.IsSystemUser(user.Id))
+        if (_userManager.IsSystemUser(user.Id))
         {
             throw new SecurityException();
         }
 
-        PermissionContext.DemandPermissions(new UserSecurityProvider(user.Id), Constants.Action_EditUser);
+        _permissionContext.DemandPermissions(new UserSecurityProvider(user.Id), Constants.Action_EditUser);
 
         if (!string.IsNullOrEmpty(thumbnailsModel.TmpFile))
         {
             var fileName = Path.GetFileName(thumbnailsModel.TmpFile);
-            var data = UserPhotoManager.GetTempPhotoData(fileName);
+            var data = _userPhotoManager.GetTempPhotoData(fileName);
 
             var settings = new UserPhotoThumbnailSettings(thumbnailsModel.X, thumbnailsModel.Y, thumbnailsModel.Width, thumbnailsModel.Height);
             _settingsManager.SaveForUser(settings, user.Id);
-            UserPhotoManager.RemovePhoto(user.Id);
-            UserPhotoManager.SaveOrUpdatePhoto(user.Id, data);
-            UserPhotoManager.RemoveTempPhoto(fileName);
+            _userPhotoManager.RemovePhoto(user.Id);
+            _userPhotoManager.SaveOrUpdatePhoto(user.Id, data);
+            _userPhotoManager.RemoveTempPhoto(fileName);
         }
         else
         {
-            UserPhotoThumbnailManager.SaveThumbnails(UserPhotoManager, _settingsManager, thumbnailsModel.X, thumbnailsModel.Y, thumbnailsModel.Width, thumbnailsModel.Height, user.Id);
+            UserPhotoThumbnailManager.SaveThumbnails(_userPhotoManager, _settingsManager, thumbnailsModel.X, thumbnailsModel.Y, thumbnailsModel.Width, thumbnailsModel.Height, user.Id);
         }
 
-        UserManager.SaveUserInfo(user);
-        MessageService.Send(MessageAction.UserUpdatedAvatarThumbnails, MessageTarget.Create(user.Id), user.DisplayUserName(false, DisplayUserSettingsHelper));
+        _userManager.SaveUserInfo(user);
+        _messageService.Send(MessageAction.UserUpdatedAvatarThumbnails, _messageTarget.Create(user.Id), user.DisplayUserName(false, _displayUserSettingsHelper));
 
-        return new ThumbnailsDataDto(user.Id, UserPhotoManager);
+        return new ThumbnailsDataDto(user.Id, _userPhotoManager);
     }
 
     public ThumbnailsDataDto DeleteMemberPhoto(string userid)
     {
         var user = GetUserInfo(userid);
 
-        if (UserManager.IsSystemUser(user.Id))
+        if (_userManager.IsSystemUser(user.Id))
         {
             throw new SecurityException();
         }
 
-        PermissionContext.DemandPermissions(new UserSecurityProvider(user.Id), Constants.Action_EditUser);
+        _permissionContext.DemandPermissions(new UserSecurityProvider(user.Id), Constants.Action_EditUser);
 
-        UserPhotoManager.RemovePhoto(user.Id);
-        UserManager.SaveUserInfo(user);
-        MessageService.Send(MessageAction.UserDeletedAvatar, MessageTarget.Create(user.Id), user.DisplayUserName(false, DisplayUserSettingsHelper));
+        _userPhotoManager.RemovePhoto(user.Id);
+        _userManager.SaveUserInfo(user);
+        _messageService.Send(MessageAction.UserDeletedAvatar, _messageTarget.Create(user.Id), user.DisplayUserName(false, _displayUserSettingsHelper));
 
-        return new ThumbnailsDataDto(user.Id, UserPhotoManager);
+        return new ThumbnailsDataDto(user.Id, _userPhotoManager);
     }
 
     public ThumbnailsDataDto GetMemberPhoto(string userid)
     {
         var user = GetUserInfo(userid);
 
-        if (UserManager.IsSystemUser(user.Id))
+        if (_userManager.IsSystemUser(user.Id))
         {
             throw new SecurityException();
         }
 
-        return new ThumbnailsDataDto(user.Id, UserPhotoManager);
+        return new ThumbnailsDataDto(user.Id, _userPhotoManager);
     }
 
     public ThumbnailsDataDto UpdateMemberPhoto(string userid, UpdateMemberRequestDto model)
     {
         var user = GetUserInfo(userid);
 
-        if (UserManager.IsSystemUser(user.Id))
+        if (_userManager.IsSystemUser(user.Id))
         {
             throw new SecurityException();
         }
 
-        if (model.Files != UserPhotoManager.GetPhotoAbsoluteWebPath(user.Id))
+        if (model.Files != _userPhotoManager.GetPhotoAbsoluteWebPath(user.Id))
         {
             UpdatePhotoUrl(model.Files, user);
         }
 
-        UserManager.SaveUserInfo(user);
-        MessageService.Send(MessageAction.UserAddedAvatar, MessageTarget.Create(user.Id), user.DisplayUserName(false, DisplayUserSettingsHelper));
+        _userManager.SaveUserInfo(user);
+        _messageService.Send(MessageAction.UserAddedAvatar, _messageTarget.Create(user.Id), user.DisplayUserName(false, _displayUserSettingsHelper));
 
-        return new ThumbnailsDataDto(user.Id, UserPhotoManager);
+        return new ThumbnailsDataDto(user.Id, _userPhotoManager);
     }
 
     public FileUploadResultDto UploadMemberPhoto(string userid, IFormCollection model)
@@ -139,14 +139,14 @@ public class PhotoControllerEngine : PeopleControllerEngine
                 }
                 catch
                 {
-                    userId = SecurityContext.CurrentAccount.ID;
+                    userId = _securityContext.CurrentAccount.ID;
                 }
 
-                PermissionContext.DemandPermissions(new UserSecurityProvider(userId), Constants.Action_EditUser);
+                _permissionContext.DemandPermissions(new UserSecurityProvider(userId), Constants.Action_EditUser);
 
                 var userPhoto = model.Files[0];
 
-                if (userPhoto.Length > SetupInfo.MaxImageUploadSize)
+                if (userPhoto.Length > _setupInfo.MaxImageUploadSize)
                 {
                     result.Success = false;
                     result.Message = _fileSizeComment.FileImageSizeExceptionString;
@@ -165,27 +165,27 @@ public class PhotoControllerEngine : PeopleControllerEngine
 
                 if (autosave)
                 {
-                    if (data.Length > SetupInfo.MaxImageUploadSize)
+                    if (data.Length > _setupInfo.MaxImageUploadSize)
                     {
                         throw new ImageSizeLimitException();
                     }
 
-                    var mainPhoto = UserPhotoManager.SaveOrUpdatePhoto(userId, data);
+                    var mainPhoto = _userPhotoManager.SaveOrUpdatePhoto(userId, data);
 
                     result.Data =
                         new
                         {
                             main = mainPhoto,
-                            retina = UserPhotoManager.GetRetinaPhotoURL(userId),
-                            max = UserPhotoManager.GetMaxPhotoURL(userId),
-                            big = UserPhotoManager.GetBigPhotoURL(userId),
-                            medium = UserPhotoManager.GetMediumPhotoURL(userId),
-                            small = UserPhotoManager.GetSmallPhotoURL(userId),
+                            retina = _userPhotoManager.GetRetinaPhotoURL(userId),
+                            max = _userPhotoManager.GetMaxPhotoURL(userId),
+                            big = _userPhotoManager.GetBigPhotoURL(userId),
+                            medium = _userPhotoManager.GetMediumPhotoURL(userId),
+                            small = _userPhotoManager.GetSmallPhotoURL(userId),
                         };
                 }
                 else
                 {
-                    result.Data = UserPhotoManager.SaveTempPhoto(data, SetupInfo.MaxImageUploadSize, UserPhotoManager.OriginalFotoSize.Width, UserPhotoManager.OriginalFotoSize.Height);
+                    result.Data = _userPhotoManager.SaveTempPhoto(data, _setupInfo.MaxImageUploadSize, UserPhotoManager.OriginalFotoSize.Width, UserPhotoManager.OriginalFotoSize.Height);
                 }
 
                 result.Success = true;
diff --git a/products/ASC.People/Server/ApiEngines/ReassignControllerEngine.cs b/products/ASC.People/Server/ApiEngines/ReassignControllerEngine.cs
index 06c1a7d122..90e9f241dd 100644
--- a/products/ASC.People/Server/ApiEngines/ReassignControllerEngine.cs
+++ b/products/ASC.People/Server/ApiEngines/ReassignControllerEngine.cs
@@ -31,46 +31,46 @@ public class ReassignControllerEngine : ApiControllerEngineBase
 
     public ReassignProgressItem GetReassignProgress(Guid userId)
     {
-        PermissionContext.DemandPermissions(Constants.Action_EditUser);
+        _permissionContext.DemandPermissions(Constants.Action_EditUser);
 
         return _queueWorkerReassign.GetProgressItemStatus(Tenant.Id, userId);
     }
 
     public void TerminateReassign(TerminateRequestDto model)
     {
-        PermissionContext.DemandPermissions(Constants.Action_EditUser);
+        _permissionContext.DemandPermissions(Constants.Action_EditUser);
 
         _queueWorkerReassign.Terminate(Tenant.Id, model.UserId);
     }
 
     public ReassignProgressItem StartReassign(StartReassignRequestDto model)
     {
-        PermissionContext.DemandPermissions(Constants.Action_EditUser);
+        _permissionContext.DemandPermissions(Constants.Action_EditUser);
 
-        var fromUser = UserManager.GetUsers(model.FromUserId);
+        var fromUser = _userManager.GetUsers(model.FromUserId);
 
         if (fromUser == null || fromUser.Id == Constants.LostUser.Id)
         {
             throw new ArgumentException("User with id = " + model.FromUserId + " not found");
         }
 
-        if (fromUser.IsOwner(Tenant) || fromUser.IsMe(AuthContext) || fromUser.Status != EmployeeStatus.Terminated)
+        if (fromUser.IsOwner(Tenant) || fromUser.IsMe(_authContext) || fromUser.Status != EmployeeStatus.Terminated)
         {
             throw new ArgumentException("Can not delete user with id = " + model.FromUserId);
         }
 
-        var toUser = UserManager.GetUsers(model.ToUserId);
+        var toUser = _userManager.GetUsers(model.ToUserId);
 
         if (toUser == null || toUser.Id == Constants.LostUser.Id)
         {
             throw new ArgumentException("User with id = " + model.ToUserId + " not found");
         }
 
-        if (toUser.IsVisitor(UserManager) || toUser.Status == EmployeeStatus.Terminated)
+        if (toUser.IsVisitor(_userManager) || toUser.Status == EmployeeStatus.Terminated)
         {
             throw new ArgumentException("Can not reassign data to user with id = " + model.ToUserId);
         }
 
-        return _queueWorkerReassign.Start(Tenant.Id, model.FromUserId, model.ToUserId, SecurityContext.CurrentAccount.ID, model.DeleteProfile);
+        return _queueWorkerReassign.Start(Tenant.Id, model.FromUserId, model.ToUserId, _securityContext.CurrentAccount.ID, model.DeleteProfile);
     }
 }
diff --git a/products/ASC.People/Server/ApiEngines/RemoveUserDataControllerEngine.cs b/products/ASC.People/Server/ApiEngines/RemoveUserDataControllerEngine.cs
index a12fd25db1..85f578a54b 100644
--- a/products/ASC.People/Server/ApiEngines/RemoveUserDataControllerEngine.cs
+++ b/products/ASC.People/Server/ApiEngines/RemoveUserDataControllerEngine.cs
@@ -30,49 +30,49 @@ public class RemoveUserDataControllerEngine : ApiControllerEngineBase
 
     public RemoveProgressItem GetRemoveProgress(Guid userId)
     {
-        PermissionContext.DemandPermissions(Constants.Action_EditUser);
+        _permissionContext.DemandPermissions(Constants.Action_EditUser);
 
         return _queueWorkerRemove.GetProgressItemStatus(Tenant.Id, userId);
     }
 
     public object SendInstructionsToDelete()
     {
-        var user = UserManager.GetUsers(SecurityContext.CurrentAccount.ID);
+        var user = _userManager.GetUsers(_securityContext.CurrentAccount.ID);
 
         if (user.IsLDAP())
         {
             throw new SecurityException();
         }
 
-        StudioNotifyService.SendMsgProfileDeletion(user);
-        MessageService.Send(MessageAction.UserSentDeleteInstructions);
+        _studioNotifyService.SendMsgProfileDeletion(user);
+        _messageService.Send(MessageAction.UserSentDeleteInstructions);
 
         return string.Format(Resource.SuccessfullySentNotificationDeleteUserInfoMessage, "<b>" + user.Email + "</b>");
     }
 
     public void TerminateRemove(TerminateRequestDto model)
     {
-        PermissionContext.DemandPermissions(Constants.Action_EditUser);
+        _permissionContext.DemandPermissions(Constants.Action_EditUser);
 
         _queueWorkerRemove.Terminate(Tenant.Id, model.UserId);
     }
 
     public RemoveProgressItem StartRemove(TerminateRequestDto model)
     {
-        PermissionContext.DemandPermissions(Constants.Action_EditUser);
+        _permissionContext.DemandPermissions(Constants.Action_EditUser);
 
-        var user = UserManager.GetUsers(model.UserId);
+        var user = _userManager.GetUsers(model.UserId);
 
         if (user == null || user.Id == Constants.LostUser.Id)
         {
             throw new ArgumentException("User with id = " + model.UserId + " not found");
         }
 
-        if (user.IsOwner(Tenant) || user.IsMe(AuthContext) || user.Status != EmployeeStatus.Terminated)
+        if (user.IsOwner(Tenant) || user.IsMe(_authContext) || user.Status != EmployeeStatus.Terminated)
         {
             throw new ArgumentException("Can not delete user with id = " + model.UserId);
         }
 
-        return _queueWorkerRemove.Start(Tenant.Id, user, SecurityContext.CurrentAccount.ID, true);
+        return _queueWorkerRemove.Start(Tenant.Id, user, _securityContext.CurrentAccount.ID, true);
     }
 }
diff --git a/products/ASC.People/Server/ApiEngines/ThirdpartyControllerEngine.cs b/products/ASC.People/Server/ApiEngines/ThirdpartyControllerEngine.cs
index 99695e1ccb..8ba0a3ed92 100644
--- a/products/ASC.People/Server/ApiEngines/ThirdpartyControllerEngine.cs
+++ b/products/ASC.People/Server/ApiEngines/ThirdpartyControllerEngine.cs
@@ -74,9 +74,9 @@ public class ThirdpartyControllerEngine : ApiControllerEngineBase
         ICollection<AccountInfoDto> infos = new List<AccountInfoDto>();
         IEnumerable<LoginProfile> linkedAccounts = new List<LoginProfile>();
 
-        if (AuthContext.IsAuthenticated)
+        if (_authContext.IsAuthenticated)
         {
-            linkedAccounts = _accountLinker.Get("webstudio").GetLinkedProfiles(AuthContext.CurrentAccount.ID.ToString());
+            linkedAccounts = _accountLinker.Get("webstudio").GetLinkedProfiles(_authContext.CurrentAccount.ID.ToString());
         }
 
         fromOnly = string.IsNullOrWhiteSpace(fromOnly) ? string.Empty : fromOnly.ToLower();
@@ -119,8 +119,8 @@ public class ThirdpartyControllerEngine : ApiControllerEngineBase
 
         if (string.IsNullOrEmpty(profile.AuthorizationError))
         {
-            GetLinker().AddLink(SecurityContext.CurrentAccount.ID.ToString(), profile);
-            MessageService.Send(MessageAction.UserLinkedSocialAccount, GetMeaningfulProviderName(profile.Provider));
+            GetLinker().AddLink(_securityContext.CurrentAccount.ID.ToString(), profile);
+            _messageService.Send(MessageAction.UserLinkedSocialAccount, GetMeaningfulProviderName(profile.Provider));
         }
         else
         {
@@ -163,10 +163,10 @@ public class ThirdpartyControllerEngine : ApiControllerEngineBase
         var userID = Guid.Empty;
         try
         {
-            SecurityContext.AuthenticateMeWithoutCookie(ASC.Core.Configuration.Constants.CoreSystem);
+            _securityContext.AuthenticateMeWithoutCookie(ASC.Core.Configuration.Constants.CoreSystem);
             var newUser = CreateNewUser(GetFirstName(model, thirdPartyProfile), GetLastName(model, thirdPartyProfile), GetEmailAddress(model, thirdPartyProfile), passwordHash, employeeType, false);
             var messageAction = employeeType == EmployeeType.User ? MessageAction.UserCreatedViaInvite : MessageAction.GuestCreatedViaInvite;
-            MessageService.Send(MessageInitiator.System, messageAction, MessageTarget.Create(newUser.Id), newUser.DisplayUserName(false, _displayUserSettingsHelper));
+            _messageService.Send(MessageInitiator.System, messageAction, _messageTarget.Create(newUser.Id), newUser.DisplayUserName(false, _displayUserSettingsHelper));
             userID = newUser.Id;
             if (!string.IsNullOrEmpty(thirdPartyProfile.Avatar))
             {
@@ -177,18 +177,18 @@ public class ThirdpartyControllerEngine : ApiControllerEngineBase
         }
         finally
         {
-            SecurityContext.Logout();
+            _securityContext.Logout();
         }
 
-        var user = UserManager.GetUsers(userID);
-        var cookiesKey = SecurityContext.AuthenticateMe(user.Email, passwordHash);
+        var user = _userManager.GetUsers(userID);
+        var cookiesKey = _securityContext.AuthenticateMe(user.Email, passwordHash);
         _cookiesManager.SetCookies(CookiesType.AuthKey, cookiesKey);
-        MessageService.Send(MessageAction.LoginSuccess);
-        StudioNotifyService.UserHasJoin();
+        _messageService.Send(MessageAction.LoginSuccess);
+        _studioNotifyService.UserHasJoin();
 
         if (mustChangePassword)
         {
-            StudioNotifyService.UserPasswordChange(user);
+            _studioNotifyService.UserPasswordChange(user);
         }
 
         _userHelpTourHelper.IsNewUser = true;
@@ -200,8 +200,8 @@ public class ThirdpartyControllerEngine : ApiControllerEngineBase
 
     public void UnlinkAccount(string provider)
     {
-        GetLinker().RemoveProvider(SecurityContext.CurrentAccount.ID.ToString(), provider);
-        MessageService.Send(MessageAction.UserUnlinkedSocialAccount, GetMeaningfulProviderName(provider));
+        GetLinker().RemoveProvider(_securityContext.CurrentAccount.ID.ToString(), provider);
+        _messageService.Send(MessageAction.UserUnlinkedSocialAccount, GetMeaningfulProviderName(provider));
     }
 
     private static string GetMeaningfulProviderName(string providerName)
diff --git a/products/ASC.People/Server/ApiEngines/UserControllerEngine.cs b/products/ASC.People/Server/ApiEngines/UserControllerEngine.cs
index af3dc110dc..71d27ba6be 100644
--- a/products/ASC.People/Server/ApiEngines/UserControllerEngine.cs
+++ b/products/ASC.People/Server/ApiEngines/UserControllerEngine.cs
@@ -95,9 +95,9 @@ public class UserControllerEngine : PeopleControllerEngine
 
     public EmployeeDto AddMember(MemberRequestDto memberModel)
     {
-        ApiContext.AuthByClaim();
+        _apiContext.AuthByClaim();
 
-        PermissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
+        _permissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
 
         memberModel.PasswordHash = (memberModel.PasswordHash ?? "").Trim();
         if (string.IsNullOrEmpty(memberModel.PasswordHash))
@@ -138,11 +138,11 @@ public class UserControllerEngine : PeopleControllerEngine
         user = _userManagerWrapper.AddUser(user, memberModel.PasswordHash, memberModel.FromInviteLink, true, memberModel.IsVisitor, memberModel.FromInviteLink);
 
         var messageAction = memberModel.IsVisitor ? MessageAction.GuestCreated : MessageAction.UserCreated;
-        MessageService.Send(messageAction, MessageTarget.Create(user.Id), user.DisplayUserName(false, DisplayUserSettingsHelper));
+        _messageService.Send(messageAction, _messageTarget.Create(user.Id), user.DisplayUserName(false, _displayUserSettingsHelper));
 
         UpdateDepartments(memberModel.Department, user);
 
-        if (memberModel.Files != UserPhotoManager.GetDefaultPhotoAbsoluteWebPath())
+        if (memberModel.Files != _userPhotoManager.GetDefaultPhotoAbsoluteWebPath())
         {
             UpdatePhotoUrl(memberModel.Files, user);
         }
@@ -152,7 +152,7 @@ public class UserControllerEngine : PeopleControllerEngine
 
     public EmployeeDto AddMemberAsActivated(MemberRequestDto memberModel)
     {
-        PermissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
+        _permissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
 
         var user = new UserInfo();
 
@@ -197,7 +197,7 @@ public class UserControllerEngine : PeopleControllerEngine
 
         UpdateDepartments(memberModel.Department, user);
 
-        if (memberModel.Files != UserPhotoManager.GetDefaultPhotoAbsoluteWebPath())
+        if (memberModel.Files != _userPhotoManager.GetDefaultPhotoAbsoluteWebPath())
         {
             UpdatePhotoUrl(memberModel.Files, user);
         }
@@ -207,17 +207,17 @@ public class UserControllerEngine : PeopleControllerEngine
 
     public EmployeeDto ChangeUserPassword(Guid userid, MemberRequestDto memberModel)
     {
-        ApiContext.AuthByClaim();
-        PermissionContext.DemandPermissions(new UserSecurityProvider(userid), Constants.Action_EditUser);
+        _apiContext.AuthByClaim();
+        _permissionContext.DemandPermissions(new UserSecurityProvider(userid), Constants.Action_EditUser);
 
-        var user = UserManager.GetUsers(userid);
+        var user = _userManager.GetUsers(userid);
 
-        if (!UserManager.UserExists(user))
+        if (!_userManager.UserExists(user))
         {
             return null;
         }
 
-        if (UserManager.IsSystemUser(user.Id))
+        if (_userManager.IsSystemUser(user.Id))
         {
             throw new SecurityException();
         }
@@ -229,7 +229,7 @@ public class UserControllerEngine : PeopleControllerEngine
             {
                 user.Email = address.Address.ToLowerInvariant();
                 user.ActivationStatus = EmployeeActivationStatus.Activated;
-                UserManager.SaveUserInfo(user);
+                _userManager.SaveUserInfo(user);
             }
         }
 
@@ -246,11 +246,11 @@ public class UserControllerEngine : PeopleControllerEngine
 
         if (!string.IsNullOrEmpty(memberModel.PasswordHash))
         {
-            SecurityContext.SetUserPasswordHash(userid, memberModel.PasswordHash);
-            MessageService.Send(MessageAction.UserUpdatedPassword);
+            _securityContext.SetUserPasswordHash(userid, memberModel.PasswordHash);
+            _messageService.Send(MessageAction.UserUpdatedPassword);
 
             _cookiesManager.ResetUserCookie(userid);
-            MessageService.Send(MessageAction.CookieSettingsUpdated);
+            _messageService.Send(MessageAction.CookieSettingsUpdated);
         }
 
         return _employeeFullDtoHelper.GetFull(GetUserInfo(userid.ToString()));
@@ -258,11 +258,11 @@ public class UserControllerEngine : PeopleControllerEngine
 
     public EmployeeDto DeleteMember(string userid)
     {
-        PermissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
+        _permissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
 
         var user = GetUserInfo(userid);
 
-        if (UserManager.IsSystemUser(user.Id) || user.IsLDAP())
+        if (_userManager.IsSystemUser(user.Id) || user.IsLDAP())
         {
             throw new SecurityException();
         }
@@ -274,28 +274,28 @@ public class UserControllerEngine : PeopleControllerEngine
 
         CheckReassignProccess(new[] { user.Id });
 
-        var userName = user.DisplayUserName(false, DisplayUserSettingsHelper);
-        UserPhotoManager.RemovePhoto(user.Id);
-        UserManager.DeleteUser(user.Id);
-        _queueWorkerRemove.Start(Tenant.Id, user, SecurityContext.CurrentAccount.ID, false);
+        var userName = user.DisplayUserName(false, _displayUserSettingsHelper);
+        _userPhotoManager.RemovePhoto(user.Id);
+        _userManager.DeleteUser(user.Id);
+        _queueWorkerRemove.Start(Tenant.Id, user, _securityContext.CurrentAccount.ID, false);
 
-        MessageService.Send(MessageAction.UserDeleted, MessageTarget.Create(user.Id), userName);
+        _messageService.Send(MessageAction.UserDeleted, _messageTarget.Create(user.Id), userName);
 
         return _employeeFullDtoHelper.GetFull(user);
     }
 
     public EmployeeDto DeleteProfile()
     {
-        ApiContext.AuthByClaim();
+        _apiContext.AuthByClaim();
 
-        if (UserManager.IsSystemUser(SecurityContext.CurrentAccount.ID))
+        if (_userManager.IsSystemUser(_securityContext.CurrentAccount.ID))
         {
             throw new SecurityException();
         }
 
-        var user = GetUserInfo(SecurityContext.CurrentAccount.ID.ToString());
+        var user = GetUserInfo(_securityContext.CurrentAccount.ID.ToString());
 
-        if (!UserManager.UserExists(user))
+        if (!_userManager.UserExists(user))
         {
             throw new Exception(Resource.ErrorUserNotFound);
         }
@@ -305,21 +305,21 @@ public class UserControllerEngine : PeopleControllerEngine
             throw new SecurityException();
         }
 
-        SecurityContext.AuthenticateMeWithoutCookie(ASC.Core.Configuration.Constants.CoreSystem);
+        _securityContext.AuthenticateMeWithoutCookie(ASC.Core.Configuration.Constants.CoreSystem);
         user.Status = EmployeeStatus.Terminated;
 
-        UserManager.SaveUserInfo(user);
-        var userName = user.DisplayUserName(false, DisplayUserSettingsHelper);
-        MessageService.Send(MessageAction.UsersUpdatedStatus, MessageTarget.Create(user.Id), userName);
+        _userManager.SaveUserInfo(user);
+        var userName = user.DisplayUserName(false, _displayUserSettingsHelper);
+        _messageService.Send(MessageAction.UsersUpdatedStatus, _messageTarget.Create(user.Id), userName);
 
         _cookiesManager.ResetUserCookie(user.Id);
-        MessageService.Send(MessageAction.CookieSettingsUpdated);
+        _messageService.Send(MessageAction.CookieSettingsUpdated);
 
         if (_coreBaseSettings.Personal)
         {
-            UserPhotoManager.RemovePhoto(user.Id);
-            UserManager.DeleteUser(user.Id);
-            MessageService.Send(MessageAction.UserDeleted, MessageTarget.Create(user.Id), userName);
+            _userPhotoManager.RemovePhoto(user.Id);
+            _userManager.DeleteUser(user.Id);
+            _messageService.Send(MessageAction.UserDeleted, _messageTarget.Create(user.Id), userName);
         }
         else
         {
@@ -338,14 +338,14 @@ public class UserControllerEngine : PeopleControllerEngine
         }
         try
         {
-            var list = UserManager.GetUsers(status).AsEnumerable();
+            var list = _userManager.GetUsers(status).AsEnumerable();
 
-            if ("group".Equals(ApiContext.FilterBy, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(ApiContext.FilterValue))
+            if ("group".Equals(_apiContext.FilterBy, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(_apiContext.FilterValue))
             {
-                var groupId = new Guid(ApiContext.FilterValue);
+                var groupId = new Guid(_apiContext.FilterValue);
                 //Filter by group
-                list = list.Where(x => UserManager.IsUserInGroup(x.Id, groupId));
-                ApiContext.SetDataFiltered();
+                list = list.Where(x => _userManager.IsUserInGroup(x.Id, groupId));
+                _apiContext.SetDataFiltered();
             }
 
             list = list.Where(x => x.FirstName != null && x.FirstName.IndexOf(query, StringComparison.OrdinalIgnoreCase) > -1 || (x.LastName != null && x.LastName.IndexOf(query, StringComparison.OrdinalIgnoreCase) != -1) ||
@@ -363,12 +363,12 @@ public class UserControllerEngine : PeopleControllerEngine
 
     public EmployeeDto GetByEmail(string email)
     {
-        if (_coreBaseSettings.Personal && !UserManager.GetUsers(SecurityContext.CurrentAccount.ID).IsOwner(Tenant))
+        if (_coreBaseSettings.Personal && !_userManager.GetUsers(_securityContext.CurrentAccount.ID).IsOwner(Tenant))
         {
             throw new MethodAccessException("Method not available");
         }
 
-        var user = UserManager.GetUserByEmail(email);
+        var user = _userManager.GetUserByEmail(email);
         if (user.Id == Constants.LostUser.Id)
         {
             throw new ItemNotFoundException("User not found");
@@ -384,16 +384,16 @@ public class UserControllerEngine : PeopleControllerEngine
             throw new MethodAccessException("Method not available");
         }
 
-        var user = UserManager.GetUserByUserName(username);
+        var user = _userManager.GetUserByUserName(username);
         if (user.Id == Constants.LostUser.Id)
         {
             if (Guid.TryParse(username, out var userId))
             {
-                user = UserManager.GetUsers(userId);
+                user = _userManager.GetUsers(userId);
             }
             else
             {
-                _logger.Error(string.Format("Account {0} сould not get user by name {1}", SecurityContext.CurrentAccount.ID, username));
+                _logger.Error(string.Format("Account {0} сould not get user by name {1}", _securityContext.CurrentAccount.ID, username));
             }
         }
 
@@ -413,10 +413,10 @@ public class UserControllerEngine : PeopleControllerEngine
         }
 
         Guid? groupId = null;
-        if ("group".Equals(ApiContext.FilterBy, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(ApiContext.FilterValue))
+        if ("group".Equals(_apiContext.FilterBy, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(_apiContext.FilterValue))
         {
-            groupId = new Guid(ApiContext.FilterValue);
-            ApiContext.SetDataFiltered();
+            groupId = new Guid(_apiContext.FilterValue);
+            _apiContext.SetDataFiltered();
         }
 
         return GetFullByFilter(status, groupId, null, null, null);
@@ -447,12 +447,12 @@ public class UserControllerEngine : PeopleControllerEngine
         try
         {
             var groupId = Guid.Empty;
-            if ("group".Equals(ApiContext.FilterBy, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(ApiContext.FilterValue))
+            if ("group".Equals(_apiContext.FilterBy, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(_apiContext.FilterValue))
             {
-                groupId = new Guid(ApiContext.FilterValue);
+                groupId = new Guid(_apiContext.FilterValue);
             }
 
-            var users = UserManager.Search(query, EmployeeStatus.Active, groupId);
+            var users = _userManager.Search(query, EmployeeStatus.Active, groupId);
 
             return users.Select(u => _employeeFullDtoHelper.GetFull(u));
         }
@@ -483,15 +483,15 @@ public class UserControllerEngine : PeopleControllerEngine
 
     public IEnumerable<EmployeeDto> RemoveUsers(UpdateMembersRequestDto model)
     {
-        PermissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
+        _permissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
 
         CheckReassignProccess(model.UserIds);
 
-        var users = model.UserIds.Select(userId => UserManager.GetUsers(userId))
-            .Where(u => !UserManager.IsSystemUser(u.Id) && !u.IsLDAP())
+        var users = model.UserIds.Select(userId => _userManager.GetUsers(userId))
+            .Where(u => !_userManager.IsSystemUser(u.Id) && !u.IsLDAP())
             .ToList();
 
-        var userNames = users.Select(x => x.DisplayUserName(false, DisplayUserSettingsHelper)).ToList();
+        var userNames = users.Select(x => x.DisplayUserName(false, _displayUserSettingsHelper)).ToList();
 
         foreach (var user in users)
         {
@@ -500,12 +500,12 @@ public class UserControllerEngine : PeopleControllerEngine
                 continue;
             }
 
-            UserPhotoManager.RemovePhoto(user.Id);
-            UserManager.DeleteUser(user.Id);
-            _queueWorkerRemove.Start(Tenant.Id, user, SecurityContext.CurrentAccount.ID, false);
+            _userPhotoManager.RemovePhoto(user.Id);
+            _userManager.DeleteUser(user.Id);
+            _queueWorkerRemove.Start(Tenant.Id, user, _securityContext.CurrentAccount.ID, false);
         }
 
-        MessageService.Send(MessageAction.UsersDeleted, MessageTarget.Create(users.Select(x => x.Id)), userNames);
+        _messageService.Send(MessageAction.UsersDeleted, _messageTarget.Create(users.Select(x => x.Id)), userNames);
 
         return users.Select(u => _employeeFullDtoHelper.GetFull(u));
     }
@@ -513,8 +513,8 @@ public class UserControllerEngine : PeopleControllerEngine
     public IEnumerable<EmployeeDto> ResendUserInvites(UpdateMembersRequestDto model)
     {
         var users = model.UserIds
-            .Where(userId => !UserManager.IsSystemUser(userId))
-            .Select(userId => UserManager.GetUsers(userId))
+            .Where(userId => !_userManager.IsSystemUser(userId))
+            .Select(userId => _userManager.GetUsers(userId))
             .ToList();
 
         foreach (var user in users)
@@ -524,14 +524,14 @@ public class UserControllerEngine : PeopleControllerEngine
                 continue;
             }
 
-            var viewer = UserManager.GetUsers(SecurityContext.CurrentAccount.ID);
+            var viewer = _userManager.GetUsers(_securityContext.CurrentAccount.ID);
 
             if (viewer == null)
             {
                 throw new Exception(Resource.ErrorAccessDenied);
             }
 
-            if (viewer.IsAdmin(UserManager) || viewer.Id == user.Id)
+            if (viewer.IsAdmin(_userManager) || viewer.Id == user.Id)
             {
                 if (user.ActivationStatus == EmployeeActivationStatus.Activated)
                 {
@@ -542,34 +542,34 @@ public class UserControllerEngine : PeopleControllerEngine
                     user.ActivationStatus = EmployeeActivationStatus.AutoGenerated;
                 }
 
-                UserManager.SaveUserInfo(user);
+                _userManager.SaveUserInfo(user);
             }
 
             if (user.ActivationStatus == EmployeeActivationStatus.Pending)
             {
-                if (user.IsVisitor(UserManager))
+                if (user.IsVisitor(_userManager))
                 {
-                    StudioNotifyService.GuestInfoActivation(user);
+                    _studioNotifyService.GuestInfoActivation(user);
                 }
                 else
                 {
-                    StudioNotifyService.UserInfoActivation(user);
+                    _studioNotifyService.UserInfoActivation(user);
                 }
             }
             else
             {
-                StudioNotifyService.SendEmailActivationInstructions(user, user.Email);
+                _studioNotifyService.SendEmailActivationInstructions(user, user.Email);
             }
         }
 
-        MessageService.Send(MessageAction.UsersSentActivationInstructions, MessageTarget.Create(users.Select(x => x.Id)), users.Select(x => x.DisplayUserName(false, DisplayUserSettingsHelper)));
+        _messageService.Send(MessageAction.UsersSentActivationInstructions, _messageTarget.Create(users.Select(x => x.Id)), users.Select(x => x.DisplayUserName(false, _displayUserSettingsHelper)));
 
         return users.Select(u => _employeeFullDtoHelper.GetFull(u));
     }
 
     public EmployeeDto Self()
     {
-        var user = UserManager.GetUser(SecurityContext.CurrentAccount.ID, EmployeeFullDtoHelper.GetExpression(ApiContext));
+        var user = _userManager.GetUser(_securityContext.CurrentAccount.ID, EmployeeFullDtoHelper.GetExpression(_apiContext));
 
         return _employeeFullDtoHelper.GetFull(user);
     }
@@ -595,8 +595,8 @@ public class UserControllerEngine : PeopleControllerEngine
             throw new Exception(Resource.ErrorNotCorrectEmail);
         }
 
-        var viewer = UserManager.GetUsers(SecurityContext.CurrentAccount.ID);
-        var user = UserManager.GetUsers(userid);
+        var viewer = _userManager.GetUsers(_securityContext.CurrentAccount.ID);
+        var user = _userManager.GetUsers(userid);
 
         if (user == null)
         {
@@ -608,16 +608,16 @@ public class UserControllerEngine : PeopleControllerEngine
             throw new Exception(Resource.ErrorAccessDenied);
         }
 
-        var existentUser = UserManager.GetUserByEmail(email);
+        var existentUser = _userManager.GetUserByEmail(email);
 
         if (existentUser.Id != Constants.LostUser.Id)
         {
             throw new Exception(_customNamingPeople.Substitute<Resource>("ErrorEmailAlreadyExists"));
         }
 
-        if (!viewer.IsAdmin(UserManager))
+        if (!viewer.IsAdmin(_userManager))
         {
-            StudioNotifyService.SendEmailChangeInstructions(user, email);
+            _studioNotifyService.SendEmailChangeInstructions(user, email);
         }
         else
         {
@@ -628,11 +628,11 @@ public class UserControllerEngine : PeopleControllerEngine
 
             user.Email = email;
             user.ActivationStatus = EmployeeActivationStatus.NotActivated;
-            UserManager.SaveUserInfo(user);
-            StudioNotifyService.SendEmailActivationInstructions(user, email);
+            _userManager.SaveUserInfo(user);
+            _studioNotifyService.SendEmailActivationInstructions(user, email);
         }
 
-        MessageService.Send(MessageAction.UserSentEmailChangeInstructions, user.DisplayUserName(false, DisplayUserSettingsHelper));
+        _messageService.Send(MessageAction.UserSentEmailChangeInstructions, user.DisplayUserName(false, _displayUserSettingsHelper));
 
         return string.Format(Resource.MessageEmailChangeInstuctionsSentOnEmail, email);
     }
@@ -650,20 +650,20 @@ public class UserControllerEngine : PeopleControllerEngine
 
     public IEnumerable<EmployeeDto> UpdateEmployeeActivationStatus(EmployeeActivationStatus activationstatus, UpdateMembersRequestDto model)
     {
-        ApiContext.AuthByClaim();
+        _apiContext.AuthByClaim();
 
         var retuls = new List<EmployeeDto>();
-        foreach (var id in model.UserIds.Where(userId => !UserManager.IsSystemUser(userId)))
+        foreach (var id in model.UserIds.Where(userId => !_userManager.IsSystemUser(userId)))
         {
-            PermissionContext.DemandPermissions(new UserSecurityProvider(id), Constants.Action_EditUser);
-            var u = UserManager.GetUsers(id);
+            _permissionContext.DemandPermissions(new UserSecurityProvider(id), Constants.Action_EditUser);
+            var u = _userManager.GetUsers(id);
             if (u.Id == Constants.LostUser.Id || u.IsLDAP())
             {
                 continue;
             }
 
             u.ActivationStatus = activationstatus;
-            UserManager.SaveUserInfo(u);
+            _userManager.SaveUserInfo(u);
             retuls.Add(_employeeFullDtoHelper.GetFull(u));
         }
 
@@ -674,20 +674,20 @@ public class UserControllerEngine : PeopleControllerEngine
     {
         var user = GetUserInfo(userid);
 
-        if (UserManager.IsSystemUser(user.Id))
+        if (_userManager.IsSystemUser(user.Id))
         {
             throw new SecurityException();
         }
 
-        PermissionContext.DemandPermissions(new UserSecurityProvider(user.Id), Constants.Action_EditUser);
-        var self = SecurityContext.CurrentAccount.ID.Equals(user.Id);
+        _permissionContext.DemandPermissions(new UserSecurityProvider(user.Id), Constants.Action_EditUser);
+        var self = _securityContext.CurrentAccount.ID.Equals(user.Id);
         var resetDate = new DateTime(1900, 01, 01);
 
         //Update it
 
         var isLdap = user.IsLDAP();
         var isSso = user.IsSSO();
-        var isAdmin = _webItemSecurity.IsProductAdministrator(WebItemManager.PeopleProductID, SecurityContext.CurrentAccount.ID);
+        var isAdmin = _webItemSecurity.IsProductAdministrator(WebItemManager.PeopleProductID, _securityContext.CurrentAccount.ID);
 
         if (!isLdap && !isSso)
         {
@@ -731,7 +731,7 @@ public class UserControllerEngine : PeopleControllerEngine
         UpdateContacts(memberModel.Contacts, user);
         UpdateDepartments(memberModel.Department, user);
 
-        if (memberModel.Files != UserPhotoManager.GetPhotoAbsoluteWebPath(user.Id))
+        if (memberModel.Files != _userPhotoManager.GetPhotoAbsoluteWebPath(user.Id))
         {
             UpdatePhotoUrl(memberModel.Files, user);
         }
@@ -742,24 +742,24 @@ public class UserControllerEngine : PeopleControllerEngine
         }
         if (self && !isAdmin)
         {
-            StudioNotifyService.SendMsgToAdminAboutProfileUpdated();
+            _studioNotifyService.SendMsgToAdminAboutProfileUpdated();
         }
 
         // change user type
-        var canBeGuestFlag = !user.IsOwner(Tenant) && !user.IsAdmin(UserManager) && user.GetListAdminModules(_webItemSecurity).Count == 0 && !user.IsMe(AuthContext);
+        var canBeGuestFlag = !user.IsOwner(Tenant) && !user.IsAdmin(_userManager) && user.GetListAdminModules(_webItemSecurity).Count == 0 && !user.IsMe(_authContext);
 
-        if (memberModel.IsVisitor && !user.IsVisitor(UserManager) && canBeGuestFlag)
+        if (memberModel.IsVisitor && !user.IsVisitor(_userManager) && canBeGuestFlag)
         {
-            UserManager.AddUserIntoGroup(user.Id, Constants.GroupVisitor.ID);
+            _userManager.AddUserIntoGroup(user.Id, Constants.GroupVisitor.ID);
             _webItemSecurityCache.ClearCache(Tenant.Id);
         }
 
-        if (!self && !memberModel.IsVisitor && user.IsVisitor(UserManager))
+        if (!self && !memberModel.IsVisitor && user.IsVisitor(_userManager))
         {
             var usersQuota = _tenantExtra.GetTenantQuota().ActiveUsers;
             if (_tenantStatisticsProvider.GetUsersCount() < usersQuota)
             {
-                UserManager.RemoveUserFromGroup(user.Id, Constants.GroupVisitor.ID);
+                _userManager.RemoveUserFromGroup(user.Id, Constants.GroupVisitor.ID);
                 _webItemSecurityCache.ClearCache(Tenant.Id);
             }
             else
@@ -768,13 +768,13 @@ public class UserControllerEngine : PeopleControllerEngine
             }
         }
 
-        UserManager.SaveUserInfo(user);
-        MessageService.Send(MessageAction.UserUpdated, MessageTarget.Create(user.Id), user.DisplayUserName(false, DisplayUserSettingsHelper));
+        _userManager.SaveUserInfo(user);
+        _messageService.Send(MessageAction.UserUpdated, _messageTarget.Create(user.Id), user.DisplayUserName(false, _displayUserSettingsHelper));
 
         if (memberModel.Disable.HasValue && memberModel.Disable.Value)
         {
             _cookiesManager.ResetUserCookie(user.Id);
-            MessageService.Send(MessageAction.CookieSettingsUpdated);
+            _messageService.Send(MessageAction.CookieSettingsUpdated);
         }
 
         return _employeeFullDtoHelper.GetFull(user);
@@ -784,16 +784,16 @@ public class UserControllerEngine : PeopleControllerEngine
     {
         var user = GetUserInfo(userid);
 
-        if (UserManager.IsSystemUser(user.Id))
+        if (_userManager.IsSystemUser(user.Id))
         {
             throw new SecurityException();
         }
 
-        PermissionContext.DemandPermissions(new UserSecurityProvider(user.Id), Constants.Action_EditUser);
+        _permissionContext.DemandPermissions(new UserSecurityProvider(user.Id), Constants.Action_EditUser);
 
         var curLng = user.CultureName;
 
-        if (SetupInfo.EnabledCultures.Find(c => string.Equals(c.Name, memberModel.CultureName, StringComparison.InvariantCultureIgnoreCase)) != null)
+        if (_setupInfo.EnabledCultures.Find(c => string.Equals(c.Name, memberModel.CultureName, StringComparison.InvariantCultureIgnoreCase)) != null)
         {
             if (curLng != memberModel.CultureName)
             {
@@ -801,7 +801,7 @@ public class UserControllerEngine : PeopleControllerEngine
 
                 try
                 {
-                    UserManager.SaveUserInfo(user);
+                    _userManager.SaveUserInfo(user);
                 }
                 catch
                 {
@@ -809,7 +809,7 @@ public class UserControllerEngine : PeopleControllerEngine
                     throw;
                 }
 
-                MessageService.Send(MessageAction.UserUpdatedLanguage, MessageTarget.Create(user.Id), user.DisplayUserName(false, DisplayUserSettingsHelper));
+                _messageService.Send(MessageAction.UserUpdatedLanguage, _messageTarget.Create(user.Id), user.DisplayUserName(false, _displayUserSettingsHelper));
 
             }
         }
@@ -819,15 +819,15 @@ public class UserControllerEngine : PeopleControllerEngine
 
     public IEnumerable<EmployeeDto> UpdateUserStatus(EmployeeStatus status, UpdateMembersRequestDto model)
     {
-        PermissionContext.DemandPermissions(Constants.Action_EditUser);
+        _permissionContext.DemandPermissions(Constants.Action_EditUser);
 
-        var users = model.UserIds.Select(userId => UserManager.GetUsers(userId))
-            .Where(u => !UserManager.IsSystemUser(u.Id) && !u.IsLDAP())
+        var users = model.UserIds.Select(userId => _userManager.GetUsers(userId))
+            .Where(u => !_userManager.IsSystemUser(u.Id) && !u.IsLDAP())
             .ToList();
 
         foreach (var user in users)
         {
-            if (user.IsOwner(Tenant) || user.IsMe(AuthContext))
+            if (user.IsOwner(Tenant) || user.IsMe(_authContext))
             {
                 continue;
             }
@@ -837,24 +837,24 @@ public class UserControllerEngine : PeopleControllerEngine
                 case EmployeeStatus.Active:
                     if (user.Status == EmployeeStatus.Terminated)
                     {
-                        if (_tenantStatisticsProvider.GetUsersCount() < _tenantExtra.GetTenantQuota().ActiveUsers || user.IsVisitor(UserManager))
+                        if (_tenantStatisticsProvider.GetUsersCount() < _tenantExtra.GetTenantQuota().ActiveUsers || user.IsVisitor(_userManager))
                         {
                             user.Status = EmployeeStatus.Active;
-                            UserManager.SaveUserInfo(user);
+                            _userManager.SaveUserInfo(user);
                         }
                     }
                     break;
                 case EmployeeStatus.Terminated:
                     user.Status = EmployeeStatus.Terminated;
-                    UserManager.SaveUserInfo(user);
+                    _userManager.SaveUserInfo(user);
 
                     _cookiesManager.ResetUserCookie(user.Id);
-                    MessageService.Send(MessageAction.CookieSettingsUpdated);
+                    _messageService.Send(MessageAction.CookieSettingsUpdated);
                     break;
             }
         }
 
-        MessageService.Send(MessageAction.UsersUpdatedStatus, MessageTarget.Create(users.Select(x => x.Id)), users.Select(x => x.DisplayUserName(false, DisplayUserSettingsHelper)));
+        _messageService.Send(MessageAction.UsersUpdatedStatus, _messageTarget.Create(users.Select(x => x.Id)), users.Select(x => x.DisplayUserName(false, _displayUserSettingsHelper)));
 
         return users.Select(u => _employeeFullDtoHelper.GetFull(u));
     }
@@ -862,14 +862,14 @@ public class UserControllerEngine : PeopleControllerEngine
     public IEnumerable<EmployeeDto> UpdateUserType(EmployeeType type, UpdateMembersRequestDto model)
     {
         var users = model.UserIds
-            .Where(userId => !UserManager.IsSystemUser(userId))
-            .Select(userId => UserManager.GetUsers(userId))
+            .Where(userId => !_userManager.IsSystemUser(userId))
+            .Select(userId => _userManager.GetUsers(userId))
             .ToList();
 
         foreach (var user in users)
         {
-            if (user.IsOwner(Tenant) || user.IsAdmin(UserManager)
-                || user.IsMe(AuthContext) || user.GetListAdminModules(_webItemSecurity).Count > 0)
+            if (user.IsOwner(Tenant) || user.IsAdmin(_userManager)
+                || user.IsMe(_authContext) || user.GetListAdminModules(_webItemSecurity).Count > 0)
             {
                 continue;
             }
@@ -877,11 +877,11 @@ public class UserControllerEngine : PeopleControllerEngine
             switch (type)
             {
                 case EmployeeType.User:
-                    if (user.IsVisitor(UserManager))
+                    if (user.IsVisitor(_userManager))
                     {
                         if (_tenantStatisticsProvider.GetUsersCount() < _tenantExtra.GetTenantQuota().ActiveUsers)
                         {
-                            UserManager.RemoveUserFromGroup(user.Id, Constants.GroupVisitor.ID);
+                            _userManager.RemoveUserFromGroup(user.Id, Constants.GroupVisitor.ID);
                             _webItemSecurityCache.ClearCache(Tenant.Id);
                         }
                     }
@@ -889,14 +889,14 @@ public class UserControllerEngine : PeopleControllerEngine
                 case EmployeeType.Visitor:
                     if (_coreBaseSettings.Standalone || _tenantStatisticsProvider.GetVisitorsCount() < _tenantExtra.GetTenantQuota().ActiveUsers * _constants.CoefficientOfVisitors)
                     {
-                        UserManager.AddUserIntoGroup(user.Id, Constants.GroupVisitor.ID);
+                        _userManager.AddUserIntoGroup(user.Id, Constants.GroupVisitor.ID);
                         _webItemSecurityCache.ClearCache(Tenant.Id);
                     }
                     break;
             }
         }
 
-        MessageService.Send(MessageAction.UsersUpdatedType, MessageTarget.Create(users.Select(x => x.Id)), users.Select(x => x.DisplayUserName(false, DisplayUserSettingsHelper)));
+        _messageService.Send(MessageAction.UsersUpdatedType, _messageTarget.Create(users.Select(x => x.Id)), users.Select(x => x.DisplayUserName(false, _displayUserSettingsHelper)));
 
         return users.Select(u => _employeeFullDtoHelper.GetFull(u));
     }
@@ -911,7 +911,7 @@ public class UserControllerEngine : PeopleControllerEngine
                 continue;
             }
 
-            var userName = UserManager.GetUsers(userId).DisplayUserName(DisplayUserSettingsHelper);
+            var userName = _userManager.GetUsers(userId).DisplayUserName(_displayUserSettingsHelper);
 
             throw new Exception(string.Format(Resource.ReassignDataRemoveUserError, userName));
         }
@@ -924,8 +924,8 @@ public class UserControllerEngine : PeopleControllerEngine
             throw new MethodAccessException("Method not available");
         }
 
-        var isAdmin = UserManager.GetUsers(SecurityContext.CurrentAccount.ID).IsAdmin(UserManager) ||
-                      _webItemSecurity.IsProductAdministrator(WebItemManager.PeopleProductID, SecurityContext.CurrentAccount.ID);
+        var isAdmin = _userManager.GetUsers(_securityContext.CurrentAccount.ID).IsAdmin(_userManager) ||
+                      _webItemSecurity.IsProductAdministrator(WebItemManager.PeopleProductID, _securityContext.CurrentAccount.ID);
 
         var includeGroups = new List<List<Guid>>();
         if (groupId.HasValue)
@@ -960,9 +960,9 @@ public class UserControllerEngine : PeopleControllerEngine
             includeGroups.Add(adminGroups);
         }
 
-        var users = UserManager.GetUsers(isAdmin, employeeStatus, includeGroups, excludeGroups, activationStatus, ApiContext.FilterValue, ApiContext.SortBy, !ApiContext.SortDescending, ApiContext.Count, ApiContext.StartIndex, out var total, out var count);
+        var users = _userManager.GetUsers(isAdmin, employeeStatus, includeGroups, excludeGroups, activationStatus, _apiContext.FilterValue, _apiContext.SortBy, !_apiContext.SortDescending, _apiContext.Count, _apiContext.StartIndex, out var total, out var count);
 
-        ApiContext.SetTotalCount(total).SetCount(count);
+        _apiContext.SetTotalCount(total).SetCount(count);
 
         return users;
     }
@@ -973,7 +973,7 @@ public class UserControllerEngine : PeopleControllerEngine
         {
             if (_coreBaseSettings.CustomMode) model.Lang = "ru-RU";
 
-            var cultureInfo = SetupInfo.GetPersonalCulture(model.Lang).Value;
+            var cultureInfo = _setupInfo.GetPersonalCulture(model.Lang).Value;
 
             if (cultureInfo != null)
             {
@@ -985,7 +985,7 @@ public class UserControllerEngine : PeopleControllerEngine
             if (!model.Email.TestEmailRegex()) throw new ArgumentException(Resource.ErrorNotCorrectEmail, "email");
 
             if (!SetupInfo.IsSecretEmail(model.Email)
-                && !string.IsNullOrEmpty(SetupInfo.RecaptchaPublicKey) && !string.IsNullOrEmpty(SetupInfo.RecaptchaPrivateKey))
+                && !string.IsNullOrEmpty(_setupInfo.RecaptchaPublicKey) && !string.IsNullOrEmpty(_setupInfo.RecaptchaPrivateKey))
             {
                 var ip = request.Headers["X-Forwarded-For"].ToString() ?? request.GetUserHostAddress();
 
@@ -996,24 +996,24 @@ public class UserControllerEngine : PeopleControllerEngine
                 }
             }
 
-            var newUserInfo = UserManager.GetUserByEmail(model.Email);
+            var newUserInfo = _userManager.GetUserByEmail(model.Email);
 
-            if (UserManager.UserExists(newUserInfo.Id))
+            if (_userManager.UserExists(newUserInfo.Id))
             {
-                if (!SetupInfo.IsSecretEmail(model.Email) || SecurityContext.IsAuthenticated)
+                if (!SetupInfo.IsSecretEmail(model.Email) || _securityContext.IsAuthenticated)
                 {
-                    StudioNotifyService.SendAlreadyExist(model.Email);
+                    _studioNotifyService.SendAlreadyExist(model.Email);
                     return string.Empty;
                 }
 
                 try
                 {
-                    SecurityContext.AuthenticateMe(Core.Configuration.Constants.CoreSystem);
-                    UserManager.DeleteUser(newUserInfo.Id);
+                    _securityContext.AuthenticateMe(Core.Configuration.Constants.CoreSystem);
+                    _userManager.DeleteUser(newUserInfo.Id);
                 }
                 finally
                 {
-                    SecurityContext.Logout();
+                    _securityContext.Logout();
                 }
             }
             if (!model.Spam)
@@ -1037,7 +1037,7 @@ public class UserControllerEngine : PeopleControllerEngine
                 }
             }
 
-            StudioNotifyService.SendInvitePersonal(model.Email);
+            _studioNotifyService.SendInvitePersonal(model.Email);
         }
         catch (Exception ex)
         {
@@ -1049,7 +1049,7 @@ public class UserControllerEngine : PeopleControllerEngine
 
     private void UpdateDepartments(IEnumerable<Guid> department, UserInfo user)
     {
-        if (!PermissionContext.CheckPermissions(Constants.Action_EditGroups))
+        if (!_permissionContext.CheckPermissions(Constants.Action_EditGroups))
         {
             return;
         }
@@ -1059,27 +1059,27 @@ public class UserControllerEngine : PeopleControllerEngine
             return;
         }
 
-        var groups = UserManager.GetUserGroups(user.Id);
+        var groups = _userManager.GetUserGroups(user.Id);
         var managerGroups = new List<Guid>();
         foreach (var groupInfo in groups)
         {
-            UserManager.RemoveUserFromGroup(user.Id, groupInfo.ID);
-            var managerId = UserManager.GetDepartmentManager(groupInfo.ID);
+            _userManager.RemoveUserFromGroup(user.Id, groupInfo.ID);
+            var managerId = _userManager.GetDepartmentManager(groupInfo.ID);
             if (managerId == user.Id)
             {
                 managerGroups.Add(groupInfo.ID);
-                UserManager.SetDepartmentManager(groupInfo.ID, Guid.Empty);
+                _userManager.SetDepartmentManager(groupInfo.ID, Guid.Empty);
             }
         }
         foreach (var guid in department)
         {
-            var userDepartment = UserManager.GetGroupInfo(guid);
+            var userDepartment = _userManager.GetGroupInfo(guid);
             if (userDepartment != Constants.LostGroupInfo)
             {
-                UserManager.AddUserIntoGroup(user.Id, guid);
+                _userManager.AddUserIntoGroup(user.Id, guid);
                 if (managerGroups.Contains(guid))
                 {
-                    UserManager.SetDepartmentManager(guid, user.Id);
+                    _userManager.SetDepartmentManager(guid, user.Id);
                 }
             }
         }

From eed7efc81bd2e791b917abf46b901eb101a25835 Mon Sep 17 00:00:00 2001
From: pavelbannov <pavel.bannov@onlyoffice.com>
Date: Fri, 4 Mar 2022 14:01:54 +0300
Subject: [PATCH 21/28] new rules

---
 .editorconfig | 69 ++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 60 insertions(+), 9 deletions(-)

diff --git a/.editorconfig b/.editorconfig
index 47dae92c15..c6993f18f3 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -100,23 +100,23 @@ csharp_style_namespace_declarations = file_scoped:warning
 # Expression-level preferences
 csharp_prefer_simple_default_expression = false:silent
 csharp_style_deconstructed_variable_declaration = true:suggestion
-csharp_style_implicit_object_creation_when_type_is_apparent = false
+csharp_style_implicit_object_creation_when_type_is_apparent = false:suggestion
 csharp_style_inlined_variable_declaration = true:suggestion
 csharp_style_pattern_local_over_anonymous_function = true:suggestion
-csharp_style_prefer_index_operator = false
-csharp_style_prefer_null_check_over_type_check = true
-csharp_style_prefer_range_operator = false
+csharp_style_prefer_index_operator = false:suggestion
+csharp_style_prefer_null_check_over_type_check = true:suggestion
+csharp_style_prefer_range_operator = false:suggestion
 csharp_style_throw_expression = true:suggestion
-csharp_style_unused_value_assignment_preference = discard_variable
+csharp_style_unused_value_assignment_preference = discard_variable:suggestion
 csharp_style_unused_value_expression_statement_preference = discard_variable:suggestion
 
 # 'using' directive preferences
 csharp_using_directive_placement = outside_namespace:warning
 
 # New line preferences
-csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = false
-csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false
-csharp_style_allow_embedded_statements_on_same_line_experimental = true
+csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = false:silent
+csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false:silent
+csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent
 
 #### C# Formatting Rules ####
 
@@ -134,7 +134,7 @@ csharp_indent_block_contents = true
 csharp_indent_braces = false
 csharp_indent_case_contents = true
 csharp_indent_case_contents_when_block = true
-csharp_indent_labels = one_less_than_current 
+csharp_indent_labels = one_less_than_current
 csharp_indent_switch_labels = true
 
 # Space preferences
@@ -211,3 +211,54 @@ dotnet_naming_style.begin_with_underscore.required_prefix = _
 dotnet_naming_style.begin_with_underscore.required_suffix = 
 dotnet_naming_style.begin_with_underscore.word_separator = 
 dotnet_naming_style.begin_with_underscore.capitalization = camel_case
+csharp_style_expression_bodied_lambdas = true:silent
+csharp_style_expression_bodied_local_functions = false:silent
+csharp_style_prefer_local_over_anonymous_function = true:suggestion
+csharp_style_prefer_tuple_swap = true:suggestion
+csharp_prefer_static_local_function = true:suggestion
+csharp_style_prefer_switch_expression = true:suggestion
+csharp_style_prefer_pattern_matching = true:silent
+csharp_style_prefer_not_pattern = true:suggestion
+csharp_style_prefer_extended_property_pattern = true:suggestion
+dotnet_diagnostic.CA1001.severity = warning
+dotnet_diagnostic.CA1805.severity = warning
+dotnet_diagnostic.CA1841.severity = warning
+
+[*.{cs,vb}]
+dotnet_style_operator_placement_when_wrapping = beginning_of_line
+tab_width = 4
+indent_size = 4
+end_of_line = crlf
+dotnet_style_coalesce_expression = true:suggestion
+dotnet_style_null_propagation = true:suggestion
+dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent
+dotnet_style_prefer_auto_properties = true:silent
+dotnet_style_object_initializer = true:suggestion
+dotnet_style_collection_initializer = true:suggestion
+dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
+dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion
+dotnet_style_prefer_conditional_expression_over_return = true:suggestion
+dotnet_style_explicit_tuple_names = true:suggestion
+dotnet_style_prefer_inferred_tuple_names = true:suggestion
+dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
+dotnet_style_prefer_compound_assignment = true:suggestion
+dotnet_style_prefer_simplified_interpolation = true:suggestion
+dotnet_style_namespace_match_folder = true:suggestion
+dotnet_style_readonly_field = true:warning
+dotnet_style_predefined_type_for_locals_parameters_members = true:silent
+dotnet_style_predefined_type_for_member_access = true:silent
+dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
+dotnet_style_allow_multiple_blank_lines_experimental = false:silent
+dotnet_style_allow_statement_immediately_after_block_experimental = false:silent
+dotnet_code_quality_unused_parameters = all:warning
+dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
+dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
+dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
+dotnet_style_parentheses_in_other_operators = always_for_clarity:silent
+dotnet_style_qualification_for_field = false:silent
+dotnet_style_qualification_for_property = false:silent
+dotnet_style_qualification_for_method = false:silent
+dotnet_style_qualification_for_event = false:silent
+dotnet_diagnostic.CA1715.severity = warning
+dotnet_diagnostic.CA1716.severity = warning
+dotnet_diagnostic.CA5397.severity = warning
\ No newline at end of file

From f234fd1cfda0dfd8ec0c1b54f633f18d55ccc3ca Mon Sep 17 00:00:00 2001
From: pavelbannov <pavel.bannov@onlyoffice.com>
Date: Fri, 4 Mar 2022 14:22:35 +0300
Subject: [PATCH 22/28] fix warning

---
 .editorconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.editorconfig b/.editorconfig
index c6993f18f3..819fc5a894 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -260,5 +260,5 @@ dotnet_style_qualification_for_property = false:silent
 dotnet_style_qualification_for_method = false:silent
 dotnet_style_qualification_for_event = false:silent
 dotnet_diagnostic.CA1715.severity = warning
-dotnet_diagnostic.CA1716.severity = warning
+dotnet_diagnostic.CA1716.severity = silent
 dotnet_diagnostic.CA5397.severity = warning
\ No newline at end of file

From 4a61f9fce5e1f17039971d19e553a5d961f57eea Mon Sep 17 00:00:00 2001
From: MaksimChegulov <maksim.chegulov@onlyoffice.com>
Date: Fri, 4 Mar 2022 19:35:12 +0300
Subject: [PATCH 23/28] VoipService: refactor mapping

---
 .../EF/Model/CRM/DbVoipCall.cs                | 18 +++---
 common/ASC.VoipService/Dao/VoipDao.cs         | 58 ++++---------------
 ...{CallConverter.cs => CallTypeConverter.cs} | 16 ++---
 common/ASC.VoipService/Twilio/TwilioPhone.cs  |  4 +-
 .../ASC.VoipService/Twilio/TwilioProvider.cs  |  2 +-
 common/ASC.VoipService/VoipCall.cs            |  8 +--
 common/ASC.VoipService/VoipPhone.cs           | 12 +++-
 products/ASC.CRM/Server/Api/VoipController.cs |  6 +-
 products/ASC.CRM/Server/Classes/VoipEngine.cs | 12 ++--
 .../TypeConverter/VoipCallDtoTypeConverter.cs |  4 +-
 10 files changed, 51 insertions(+), 89 deletions(-)
 rename common/ASC.VoipService/Mappings/{CallConverter.cs => CallTypeConverter.cs} (60%)

diff --git a/common/ASC.Core.Common/EF/Model/CRM/DbVoipCall.cs b/common/ASC.Core.Common/EF/Model/CRM/DbVoipCall.cs
index c372b356af..5193d26b32 100644
--- a/common/ASC.Core.Common/EF/Model/CRM/DbVoipCall.cs
+++ b/common/ASC.Core.Common/EF/Model/CRM/DbVoipCall.cs
@@ -10,9 +10,9 @@
         public Guid AnsweredBy { get; set; }
         public DateTime DialDate { get; set; }
         public int DialDuration { get; set; }
-        public string RecordSid { get; set; }
-        public string RecordUrl { get; set; }
-        public int RecordDuration { get; set; }
+        public string Sid { get; set; }
+        public string Uri { get; set; }
+        public int Duration { get; set; }
         public decimal RecordPrice { get; set; }
         public int ContactId { get; set; }
         public decimal Price { get; set; }
@@ -86,19 +86,19 @@
                     .HasColumnName("price")
                     .HasColumnType("decimal(10,4)");
 
-                entity.Property(e => e.RecordDuration).HasColumnName("record_duration");
+                entity.Property(e => e.Duration).HasColumnName("record_duration");
 
                 entity.Property(e => e.RecordPrice)
                     .HasColumnName("record_price")
                     .HasColumnType("decimal(10,4)");
 
-                entity.Property(e => e.RecordSid)
+                entity.Property(e => e.Sid)
                     .HasColumnName("record_sid")
                     .HasColumnType("varchar(50)")
                     .HasCharSet("utf8")
                     .UseCollation("utf8_general_ci");
 
-                entity.Property(e => e.RecordUrl)
+                entity.Property(e => e.Uri)
                     .HasColumnName("record_url")
                     .HasColumnType("text")
                     .HasCharSet("utf8")
@@ -157,18 +157,18 @@
                     .HasColumnType("numeric(10,4)")
                     .HasDefaultValueSql("NULL");
 
-                entity.Property(e => e.RecordDuration).HasColumnName("record_duration");
+                entity.Property(e => e.Duration).HasColumnName("record_duration");
 
                 entity.Property(e => e.RecordPrice)
                     .HasColumnName("record_price")
                     .HasColumnType("numeric(10,4)");
 
-                entity.Property(e => e.RecordSid)
+                entity.Property(e => e.Sid)
                     .HasColumnName("record_sid")
                     .HasMaxLength(50)
                     .HasDefaultValueSql("NULL");
 
-                entity.Property(e => e.RecordUrl).HasColumnName("record_url");
+                entity.Property(e => e.Uri).HasColumnName("record_url");
 
                 entity.Property(e => e.Status).HasColumnName("status");
 
diff --git a/common/ASC.VoipService/Dao/VoipDao.cs b/common/ASC.VoipService/Dao/VoipDao.cs
index 8a5afb629c..89cea091f6 100644
--- a/common/ASC.VoipService/Dao/VoipDao.cs
+++ b/common/ASC.VoipService/Dao/VoipDao.cs
@@ -120,14 +120,14 @@ public class VoipDao : AbstractDao
         {
             TenantId = TenantID,
             Id = call.Id,
-            NumberFrom = call.From,
-            NumberTo = call.To,
+            NumberFrom = call.NumberFrom,
+            NumberTo = call.NumberTo,
             ContactId = call.ContactId
         };
 
-        if (!string.IsNullOrEmpty(call.ParentID))
+        if (!string.IsNullOrEmpty(call.ParentCallId))
         {
-            voipCall.ParentCallId = call.ParentID;
+            voipCall.ParentCallId = call.ParentCallId;
         }
 
         if (call.Status.HasValue)
@@ -159,19 +159,19 @@ public class VoipDao : AbstractDao
 
         if (call.VoipRecord != null)
         {
-            if (!string.IsNullOrEmpty(call.VoipRecord.Id))
+            if (!string.IsNullOrEmpty(call.VoipRecord.Sid))
             {
-                voipCall.RecordSid = call.VoipRecord.Id;
+                voipCall.Sid = call.VoipRecord.Sid;
             }
 
             if (!string.IsNullOrEmpty(call.VoipRecord.Uri))
             {
-                voipCall.RecordUrl = call.VoipRecord.Uri;
+                voipCall.Uri = call.VoipRecord.Uri;
             }
 
             if (call.VoipRecord.Duration != 0)
             {
-                voipCall.RecordDuration = call.VoipRecord.Duration;
+                voipCall.Duration = call.VoipRecord.Duration;
             }
 
             if (call.VoipRecord.Price != default)
@@ -200,11 +200,11 @@ public class VoipDao : AbstractDao
 
         var calls = _mapper.Map<List<CallContact>, IEnumerable<VoipCall>>(query.ToList());
 
-        calls = calls.GroupJoin(calls, call => call.Id, h => h.ParentID, (call, h) =>
+        calls = calls.GroupJoin(calls, call => call.Id, h => h.ParentCallId, (call, h) =>
         {
             call.ChildCalls.AddRange(h);
             return call;
-        }).Where(r => string.IsNullOrEmpty(r.ParentID)).ToList();
+        }).Where(r => string.IsNullOrEmpty(r.ParentCallId)).ToList();
 
         return calls;
     }
@@ -298,44 +298,6 @@ public class VoipDao : AbstractDao
         return GetProvider().GetPhone(r);
     }
 
-    private VoipCall ToCall(CallContact dbVoipCall)
-    {
-        var call = new VoipCall
-        {
-            Id = dbVoipCall.DbVoipCall.Id,
-            ParentID = dbVoipCall.DbVoipCall.ParentCallId,
-            From = dbVoipCall.DbVoipCall.NumberFrom,
-            To = dbVoipCall.DbVoipCall.NumberTo,
-            AnsweredBy = dbVoipCall.DbVoipCall.AnsweredBy,
-            DialDate = _tenantUtil.DateTimeFromUtc(dbVoipCall.DbVoipCall.DialDate),
-            DialDuration = dbVoipCall.DbVoipCall.DialDuration,
-            Price = dbVoipCall.DbVoipCall.Price,
-            Status = (VoipCallStatus)dbVoipCall.DbVoipCall.Status,
-            VoipRecord = new VoipRecord
-            {
-                Id = dbVoipCall.DbVoipCall.RecordSid,
-                Uri = dbVoipCall.DbVoipCall.RecordUrl,
-                Duration = dbVoipCall.DbVoipCall.RecordDuration,
-                Price = dbVoipCall.DbVoipCall.RecordPrice
-            }
-        };
-
-        if (dbVoipCall.CrmContact != null)
-        {
-            call.ContactId = dbVoipCall.CrmContact.Id;
-            call.ContactIsCompany = dbVoipCall.CrmContact.IsCompany;
-            call.ContactTitle = call.ContactIsCompany
-                                    ? dbVoipCall.CrmContact.CompanyName
-                                    : dbVoipCall.CrmContact.FirstName == null || dbVoipCall.CrmContact.LastName == null ? null : $"{dbVoipCall.CrmContact.FirstName} {dbVoipCall.CrmContact.LastName}";
-        }
-        else
-        {
-            call.ContactId = 0;
-        }
-
-        return call;
-    }
-
     public Consumer Consumer
     {
         get { return _consumerFactory.GetByKey("twilio"); }
diff --git a/common/ASC.VoipService/Mappings/CallConverter.cs b/common/ASC.VoipService/Mappings/CallTypeConverter.cs
similarity index 60%
rename from common/ASC.VoipService/Mappings/CallConverter.cs
rename to common/ASC.VoipService/Mappings/CallTypeConverter.cs
index a5fde09da1..f95b7029d1 100644
--- a/common/ASC.VoipService/Mappings/CallConverter.cs
+++ b/common/ASC.VoipService/Mappings/CallTypeConverter.cs
@@ -1,20 +1,12 @@
 namespace ASC.VoipService.Mappings;
 
 [Scope]
-public class CallConverter : ITypeConverter<CallContact, VoipCall>
+public class CallTypeConverter : ITypeConverter<CallContact, VoipCall>
 {
     public VoipCall Convert(CallContact source, VoipCall destination, ResolutionContext context)
     {
-        var result = context.Mapper.Map<VoipCall>(source.DbVoipCall);
-        result.ParentID = source.DbVoipCall.ParentCallId;
-        result.To = source.DbVoipCall.NumberTo;
-        result.VoipRecord = new VoipRecord
-        {
-            Id = source.DbVoipCall.RecordSid,
-            Uri = source.DbVoipCall.RecordUrl,
-            Duration = source.DbVoipCall.RecordDuration,
-            Price = source.DbVoipCall.RecordPrice
-        };
+        var result = context.Mapper.Map<DbVoipCall, VoipCall>(source.DbVoipCall);
+        result.VoipRecord = context.Mapper.Map<DbVoipCall, VoipRecord>(source.DbVoipCall);
 
         if (source.CrmContact != null)
         {
@@ -37,6 +29,6 @@ public class EventTypeConverterExtension
 {
     public static void Register(DIHelper services)
     {
-        services.TryAdd<CallConverter>();
+        services.TryAdd<CallTypeConverter>();
     }
 }
\ No newline at end of file
diff --git a/common/ASC.VoipService/Twilio/TwilioPhone.cs b/common/ASC.VoipService/Twilio/TwilioPhone.cs
index 554c8fd231..02eebeab12 100644
--- a/common/ASC.VoipService/Twilio/TwilioPhone.cs
+++ b/common/ASC.VoipService/Twilio/TwilioPhone.cs
@@ -55,7 +55,7 @@ namespace ASC.VoipService.Twilio
                 Url = new System.Uri(Settings.Connect(contactId: contactId))
             }, _twilio);
 
-            return new VoipCall { Id = call.Sid, From = call.From, To = call.To };
+            return new VoipCall { Id = call.Sid, NumberFrom = call.From, NumberTo = call.To };
         }
 
         public override VoipCall LocalCall(string to)
@@ -66,7 +66,7 @@ namespace ASC.VoipService.Twilio
         public override VoipCall RedirectCall(string callId, string to)
         {
             var call = CallResource.Update(callId, url: new System.Uri(Settings.Redirect(to)), method: HttpMethod.Post, client: _twilio);
-            return new VoipCall { Id = call.Sid, To = to };
+            return new VoipCall { Id = call.Sid, NumberTo = to };
         }
 
         public override VoipCall HoldUp(string callId)
diff --git a/common/ASC.VoipService/Twilio/TwilioProvider.cs b/common/ASC.VoipService/Twilio/TwilioProvider.cs
index 4f84fe560c..1786c02605 100644
--- a/common/ASC.VoipService/Twilio/TwilioProvider.cs
+++ b/common/ASC.VoipService/Twilio/TwilioProvider.cs
@@ -58,7 +58,7 @@ namespace ASC.VoipService.Twilio
 
         public VoipRecord GetRecord(string callId, string recordSid)
         {
-            var result = new VoipRecord { Id = recordSid };
+            var result = new VoipRecord { Sid = recordSid };
             var count = 6;
 
             while (count > 0)
diff --git a/common/ASC.VoipService/VoipCall.cs b/common/ASC.VoipService/VoipCall.cs
index bf72d2b5ce..bb542adedd 100644
--- a/common/ASC.VoipService/VoipCall.cs
+++ b/common/ASC.VoipService/VoipCall.cs
@@ -28,9 +28,9 @@ namespace ASC.VoipService;
 public class VoipCall : IMapFrom<CallContact>
 {
     public string Id { get; set; }
-    public string ParentID { get; set; }
-    public string From { get; set; }
-    public string To { get; set; }
+    public string ParentCallId { get; set; }
+    public string NumberFrom { get; set; }
+    public string NumberTo { get; set; }
     public Guid AnsweredBy { get; set; }
     public DateTime DialDate { get; set; }
     public int DialDuration { get; set; }
@@ -55,7 +55,7 @@ public class VoipCall : IMapFrom<CallContact>
         profile.CreateMap<DbVoipCall, VoipCall>();
 
         profile.CreateMap<CallContact, VoipCall>()
-            .ConvertUsing<CallConverter>();
+            .ConvertUsing<CallTypeConverter>();
     }
 }
 
diff --git a/common/ASC.VoipService/VoipPhone.cs b/common/ASC.VoipService/VoipPhone.cs
index dbcc586160..4156436fc7 100644
--- a/common/ASC.VoipService/VoipPhone.cs
+++ b/common/ASC.VoipService/VoipPhone.cs
@@ -23,6 +23,8 @@
  *
 */
 
+using AutoMapper;
+
 namespace ASC.VoipService;
 
 public class VoipPhone
@@ -72,10 +74,16 @@ public class VoipPhone
     }
 }
 
-public class VoipRecord
+public class VoipRecord : IMapFrom<DbVoipCall>
 {
-    public string Id { get; set; }
+    public string Sid { get; set; }
     public string Uri { get; set; }
     public int Duration { get; set; }
     public decimal Price { get; set; }
+
+    public void Mapping(Profile profile)
+    {
+        profile.CreateMap<DbVoipCall, VoipRecord>()
+            .ForMember(dest => dest.Price, opt => opt.MapFrom(src => src.RecordPrice));
+    }
 }
\ No newline at end of file
diff --git a/products/ASC.CRM/Server/Api/VoipController.cs b/products/ASC.CRM/Server/Api/VoipController.cs
index c75f71c17a..0ac1176a09 100644
--- a/products/ASC.CRM/Server/Api/VoipController.cs
+++ b/products/ASC.CRM/Server/Api/VoipController.cs
@@ -800,15 +800,15 @@ namespace ASC.CRM.Api
             var call = dao.GetCall(callId) ?? new VoipCall();
 
             call.Id = callId;
-            call.From = Update.IfNotEmptyAndNotEquals(call.From, from);
-            call.To = Update.IfNotEmptyAndNotEquals(call.To, to);
+            call.NumberFrom = Update.IfNotEmptyAndNotEquals(call.NumberFrom, from);
+            call.NumberTo = Update.IfNotEmptyAndNotEquals(call.NumberTo, to);
             call.AnsweredBy = Update.IfNotEmptyAndNotEquals(call.AnsweredBy, answeredBy);
 
             try
             {
                 if (call.ContactId == 0)
                 {
-                    var contactPhone = call.Status == VoipCallStatus.Incoming || call.Status == VoipCallStatus.Answered ? call.From : call.To;
+                    var contactPhone = call.Status == VoipCallStatus.Incoming || call.Status == VoipCallStatus.Answered ? call.NumberFrom : call.NumberTo;
                     if (!string.IsNullOrEmpty(contactId))
                     {
                         call.ContactId = Convert.ToInt32(contactId);
diff --git a/products/ASC.CRM/Server/Classes/VoipEngine.cs b/products/ASC.CRM/Server/Classes/VoipEngine.cs
index 9897af0e73..022265318f 100644
--- a/products/ASC.CRM/Server/Classes/VoipEngine.cs
+++ b/products/ASC.CRM/Server/Classes/VoipEngine.cs
@@ -86,7 +86,7 @@ namespace ASC.Web.CRM.Classes
             var dao = _daoFactory.GetVoipDao();
             var call = dao.GetCall(callHistory.Id) ?? callHistory;
 
-            if (string.IsNullOrEmpty(call.ParentID))
+            if (string.IsNullOrEmpty(call.ParentCallId))
             {
                 GetContact(call);
             }
@@ -121,9 +121,9 @@ namespace ASC.Web.CRM.Classes
                 call.VoipRecord = new VoipRecord();
             }
 
-            if (string.IsNullOrEmpty(call.VoipRecord.Id))
+            if (string.IsNullOrEmpty(call.VoipRecord.Sid))
             {
-                call.VoipRecord.Id = callHistory.VoipRecord.Id;
+                call.VoipRecord.Sid = callHistory.VoipRecord.Sid;
             }
 
             if (call.VoipRecord.Price == default(decimal))
@@ -193,7 +193,7 @@ namespace ASC.Web.CRM.Classes
                 return null;
             }
 
-            var contactPhone = call.Status == VoipCallStatus.Incoming || call.Status == VoipCallStatus.Answered ? call.From : call.To;
+            var contactPhone = call.Status == VoipCallStatus.Incoming || call.Status == VoipCallStatus.Answered ? call.NumberFrom : call.NumberTo;
 
             var newContactIds = _daoFactory.GetContactDao().GetContactIDsByContactInfo(ContactInfoType.Phone, contactPhone.TrimStart('+'), null, true);
 
@@ -262,9 +262,9 @@ namespace ASC.Web.CRM.Classes
 
                 call = voipEngine.SaveOrUpdateCall(call);
 
-                if (!string.IsNullOrEmpty(call.VoipRecord.Id))
+                if (!string.IsNullOrEmpty(call.VoipRecord.Sid))
                 {
-                    call.VoipRecord = _voipDao.GetProvider().GetRecord((string)call.Id, (string)call.VoipRecord.Id);
+                    call.VoipRecord = _voipDao.GetProvider().GetRecord((string)call.Id, (string)call.VoipRecord.Sid);
                     voipEngine.SaveOrUpdateCall(call);
                 }
 
diff --git a/products/ASC.CRM/Server/Mapping/TypeConverter/VoipCallDtoTypeConverter.cs b/products/ASC.CRM/Server/Mapping/TypeConverter/VoipCallDtoTypeConverter.cs
index 04f72bbea7..b6617cd081 100644
--- a/products/ASC.CRM/Server/Mapping/TypeConverter/VoipCallDtoTypeConverter.cs
+++ b/products/ASC.CRM/Server/Mapping/TypeConverter/VoipCallDtoTypeConverter.cs
@@ -61,8 +61,8 @@ namespace ASC.CRM.Mapping
             var result = new VoipCallDto
             {
                 Id = source.Id,
-                From = source.From,
-                To = source.To,
+                From = source.NumberFrom,
+                To = source.NumberTo,
                 Status = source.Status,
                 AnsweredBy = _employeeWraperHelper.Get(source.AnsweredBy),
                 DialDate = _apiDateTimeHelper.Get(source.DialDate),

From 99378a027ee3bfffae1c9e28adab4808e14286e8 Mon Sep 17 00:00:00 2001
From: pavelbannov <pavel.bannov@onlyoffice.com>
Date: Sat, 5 Mar 2022 11:20:05 +0300
Subject: [PATCH 24/28] Csproj: ImplicitUsings

---
 common/ASC.Api.Core/ASC.Api.Core.csproj       |  1 +
 common/ASC.Api.Core/GlobalUsings.cs           | 13 +++----
 common/ASC.Common/ASC.Common.csproj           |  1 +
 common/ASC.Common/GlobalUsings.cs             | 38 ++++++++-----------
 common/ASC.Core.Common/ASC.Core.Common.csproj |  1 +
 common/ASC.Core.Common/GlobalUsings.cs        |  9 +----
 .../ASC.Data.Backup.Core.csproj               |  1 +
 common/ASC.Data.Backup.Core/GlobalUsings.cs   |  8 +---
 .../ASC.Data.Reassigns.csproj                 |  1 +
 common/ASC.Data.Reassigns/GlobalUsings.cs     |  7 +---
 .../ASC.Data.Storage/ASC.Data.Storage.csproj  |  1 +
 common/ASC.Data.Storage/GlobalUsings.cs       |  9 +----
 .../ASC.FederatedLogin.csproj                 |  1 +
 common/ASC.FederatedLogin/GlobalUsings.cs     |  9 +----
 common/ASC.Feed/ASC.Feed.csproj               |  1 +
 common/ASC.Feed/GlobalUsings.cs               | 27 ++++++-------
 common/ASC.IPSecurity/ASC.IPSecurity.csproj   |  1 +
 common/ASC.IPSecurity/GlobalUsings.cs         | 15 +++-----
 .../ASC.MessagingSystem.csproj                |  1 +
 common/ASC.MessagingSystem/GlobalUsings.cs    | 24 +++++-------
 .../ASC.Notify.Textile.csproj                 |  1 +
 common/ASC.Notify.Textile/GlobalUsings.cs     |  5 +--
 common/ASC.VoipService/GlobalUsings.cs        |  8 +---
 .../ASC.Webhooks.Core.csproj                  |  1 +
 common/ASC.Webhooks.Core/GlobalUsings.cs      |  6 +--
 .../ASC.AuditTrail/ASC.AuditTrail.csproj      |  1 +
 .../services/ASC.AuditTrail/GlobalUsings.cs   | 38 ++++++++-----------
 .../ASC.ClearEvents/ASC.ClearEvents.csproj    |  1 +
 .../services/ASC.ClearEvents/GlobalUsings.cs  | 22 +++--------
 .../ASC.Data.Backup/ASC.Data.Backup.csproj    |  3 +-
 .../services/ASC.Data.Backup/GlobalUsings.cs  | 14 +------
 .../ASC.ElasticSearch.csproj                  |  1 +
 .../ASC.ElasticSearch/GlobalUsings.cs         |  9 +----
 .../ASC.Feed.Aggregator.csproj                |  1 +
 .../ASC.Feed.Aggregator/GlobalUsings.cs       |  7 +---
 common/services/ASC.Notify/GlobalUsings.cs    | 24 ++++++------
 .../ASC.Socket.IO.Svc.csproj                  |  1 +
 .../ASC.Studio.Notify.csproj                  |  1 +
 .../ASC.Studio.Notify/GlobalUsings.cs         | 14 +------
 .../ASC.TelegramService/GlobalUsings.cs       |  9 +----
 .../ASC.UrlShortener.Svc.csproj               |  1 +
 .../ASC.UrlShortener.Svc/GlobalUsings.cs      | 11 +-----
 .../ASC.Webhooks.Service.csproj               |  1 +
 .../ASC.Webhooks.Service/GlobalUsings.cs      | 14 +------
 products/ASC.Files/Core/GlobalUsings.cs       |  8 ++--
 products/ASC.Files/Server/ASC.Files.csproj    |  1 +
 products/ASC.Files/Server/GlobalUsings.cs     | 16 +-------
 products/ASC.People/Server/ASC.People.csproj  |  1 +
 products/ASC.People/Server/GlobalUsings.cs    | 18 +--------
 web/ASC.Web.Api/ASC.Web.Api.csproj            |  1 +
 web/ASC.Web.Api/GlobalUsings.cs               | 32 +++++-----------
 web/ASC.Web.Core/ASC.Web.Core.csproj          |  1 +
 web/ASC.Web.Core/GlobalUsings.cs              | 35 +++++++----------
 .../ASC.Web.HealthChecks.UI.csproj            |  1 +
 web/ASC.Web.HealthChecks.UI/GlobalUsings.cs   |  9 +----
 web/ASC.Web.Studio/ASC.Web.Studio.csproj      |  1 +
 web/ASC.Web.Studio/GlobalUsings.cs            | 10 +----
 57 files changed, 163 insertions(+), 334 deletions(-)

diff --git a/common/ASC.Api.Core/ASC.Api.Core.csproj b/common/ASC.Api.Core/ASC.Api.Core.csproj
index da346a0610..ef85eda50b 100644
--- a/common/ASC.Api.Core/ASC.Api.Core.csproj
+++ b/common/ASC.Api.Core/ASC.Api.Core.csproj
@@ -3,6 +3,7 @@
   <PropertyGroup>
     <TargetFramework>net6.0</TargetFramework>
     <ProduceReferenceAssembly>false</ProduceReferenceAssembly>
+	  <ImplicitUsings>enable</ImplicitUsings>
   </PropertyGroup>
 
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
diff --git a/common/ASC.Api.Core/GlobalUsings.cs b/common/ASC.Api.Core/GlobalUsings.cs
index 632da821ba..d6a25cb7e2 100644
--- a/common/ASC.Api.Core/GlobalUsings.cs
+++ b/common/ASC.Api.Core/GlobalUsings.cs
@@ -1,11 +1,9 @@
-global using System;
-global using System.Collections.Generic;
-global using System.ComponentModel;
-global using System.Globalization;
-global using System.Linq;
+global using System.ComponentModel;
+global using System.Globalization;
+
 global using System.Linq.Expressions;
 global using System.Net;
-global using System.Net.Http;
+
 global using System.Reflection;
 global using System.Runtime.Serialization;
 global using System.Security;
@@ -14,8 +12,7 @@ global using System.Security.Claims;
 global using System.Text.Encodings.Web;
 global using System.Text.Json;
 global using System.Text.Json.Serialization;
-global using System.Threading;
-global using System.Threading.Tasks;
+
 global using System.Web;
 global using System.Xml.Linq;
 
diff --git a/common/ASC.Common/ASC.Common.csproj b/common/ASC.Common/ASC.Common.csproj
index 13b1a9dbfc..188f99f114 100644
--- a/common/ASC.Common/ASC.Common.csproj
+++ b/common/ASC.Common/ASC.Common.csproj
@@ -12,6 +12,7 @@
     <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
     <WarningsAsErrors></WarningsAsErrors>
     <NoWarn>$(NoWarn);NU1605</NoWarn>
+	  <ImplicitUsings>enable</ImplicitUsings>
     <ProduceReferenceAssembly>false</ProduceReferenceAssembly>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
diff --git a/common/ASC.Common/GlobalUsings.cs b/common/ASC.Common/GlobalUsings.cs
index 1cf21ba438..b4089c92e3 100644
--- a/common/ASC.Common/GlobalUsings.cs
+++ b/common/ASC.Common/GlobalUsings.cs
@@ -1,32 +1,26 @@
-global using System;
-global using System.Collections;
+global using System.Collections;
 global using System.Collections.Concurrent;
-global using System.Collections.Generic;
 global using System.Configuration;
 global using System.Diagnostics;
 global using System.Globalization;
-global using System.IO;
-global using System.Linq;
 global using System.Net;
 global using System.Net.Mail;
 global using System.Reflection;
 global using System.Runtime.Caching;
 global using System.Runtime.Loader;
+global using System.Runtime.Serialization;
 global using System.Security.Cryptography;
 global using System.Security.Principal;
+global using System.ServiceModel;
 global using System.Text;
 global using System.Text.RegularExpressions;
-global using System.Threading;
-global using System.Threading.Tasks;
 global using System.Web;
 global using System.Xml.Linq;
 global using System.Xml.XPath;
-global using System.ServiceModel;
-global using System.Runtime.Serialization;
-
+
 global using ARSoft.Tools.Net;
 global using ARSoft.Tools.Net.Dns;
-
+
 global using ASC.Common;
 global using ASC.Common.Caching;
 global using ASC.Common.DependencyInjection;
@@ -35,26 +29,26 @@ global using ASC.Common.Security;
 global using ASC.Common.Security.Authorizing;
 global using ASC.Common.Utils;
 global using ASC.Security.Cryptography;
-
+
 global using Autofac;
 global using Autofac.Configuration;
-
+
 global using AutoMapper;
-
+
 global using Confluent.Kafka;
 global using Confluent.Kafka.Admin;
-
+
 global using Google.Protobuf;
-
+
 global using JWT;
 global using JWT.Algorithms;
 global using JWT.Serializers;
-
+
 global using log4net.Appender;
 global using log4net.Config;
 global using log4net.Core;
 global using log4net.Util;
-
+
 global using Microsoft.AspNetCore.Cryptography.KeyDerivation;
 global using Microsoft.AspNetCore.Http;
 global using Microsoft.AspNetCore.Http.Extensions;
@@ -70,16 +64,16 @@ global using Microsoft.Extensions.Hosting;
 global using Microsoft.Extensions.Logging;
 global using Microsoft.Extensions.Options;
 global using Microsoft.Net.Http.Headers;
-
+
 global using Newtonsoft.Json;
 global using Newtonsoft.Json.Serialization;
-
+
 global using NLog;
 global using NLog.Common;
 global using NLog.Targets;
-
+
 global using NVelocity;
 global using NVelocity.App;
 global using NVelocity.Runtime.Resource.Loader;
-
+
 global using StackExchange.Redis.Extensions.Core.Abstractions;
diff --git a/common/ASC.Core.Common/ASC.Core.Common.csproj b/common/ASC.Core.Common/ASC.Core.Common.csproj
index 1884764312..27b4177153 100644
--- a/common/ASC.Core.Common/ASC.Core.Common.csproj
+++ b/common/ASC.Core.Common/ASC.Core.Common.csproj
@@ -11,6 +11,7 @@
     <Copyright>(c) Ascensio System SIA. All rights reserved</Copyright>
     <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
     <ProduceReferenceAssembly>false</ProduceReferenceAssembly>
+	  <ImplicitUsings>enable</ImplicitUsings>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugType>full</DebugType>
diff --git a/common/ASC.Core.Common/GlobalUsings.cs b/common/ASC.Core.Common/GlobalUsings.cs
index d99cdd3bd0..41e7fcb483 100644
--- a/common/ASC.Core.Common/GlobalUsings.cs
+++ b/common/ASC.Core.Common/GlobalUsings.cs
@@ -1,16 +1,11 @@
-global using System;
-global using System.Collections;
+global using System.Collections;
 global using System.Collections.Concurrent;
-global using System.Collections.Generic;
 global using System.Configuration;
 global using System.Data.Common;
 global using System.Diagnostics;
 global using System.Globalization;
-global using System.IO;
-global using System.Linq;
 global using System.Linq.Expressions;
 global using System.Net;
-global using System.Net.Http;
 global using System.Reflection;
 global using System.Resources;
 global using System.Runtime.Caching;
@@ -25,8 +20,6 @@ global using System.Text;
 global using System.Text.Json;
 global using System.Text.Json.Serialization;
 global using System.Text.RegularExpressions;
-global using System.Threading;
-global using System.Threading.Tasks;
 global using System.Web;
 global using System.Xml;
 
diff --git a/common/ASC.Data.Backup.Core/ASC.Data.Backup.Core.csproj b/common/ASC.Data.Backup.Core/ASC.Data.Backup.Core.csproj
index 5e0701b2cf..ff499af100 100644
--- a/common/ASC.Data.Backup.Core/ASC.Data.Backup.Core.csproj
+++ b/common/ASC.Data.Backup.Core/ASC.Data.Backup.Core.csproj
@@ -5,6 +5,7 @@
     <TargetFramework>net6.0</TargetFramework>
     <OutputType>Library</OutputType>
     <NoWarn>NU1701</NoWarn>
+	  <ImplicitUsings>enable</ImplicitUsings>
   </PropertyGroup>
 
   <ItemGroup>
diff --git a/common/ASC.Data.Backup.Core/GlobalUsings.cs b/common/ASC.Data.Backup.Core/GlobalUsings.cs
index a5cf3ca6fd..b71ec2b34b 100644
--- a/common/ASC.Data.Backup.Core/GlobalUsings.cs
+++ b/common/ASC.Data.Backup.Core/GlobalUsings.cs
@@ -1,20 +1,14 @@
-global using System;
-global using System.Collections.Generic;
-global using System.ComponentModel.DataAnnotations;
+global using System.ComponentModel.DataAnnotations;
 global using System.ComponentModel.DataAnnotations.Schema;
 global using System.Configuration;
 global using System.Data;
 global using System.Data.Common;
 global using System.Diagnostics;
-global using System.IO;
-global using System.Linq;
 global using System.Reflection;
 global using System.Security.Cryptography;
 global using System.ServiceModel;
 global using System.Text;
 global using System.Text.RegularExpressions;
-global using System.Threading;
-global using System.Threading.Tasks;
 global using System.Xml;
 global using System.Xml.Linq;
 global using System.Xml.XPath;
diff --git a/common/ASC.Data.Reassigns/ASC.Data.Reassigns.csproj b/common/ASC.Data.Reassigns/ASC.Data.Reassigns.csproj
index c1a8ad2ff4..fd97c01c5c 100644
--- a/common/ASC.Data.Reassigns/ASC.Data.Reassigns.csproj
+++ b/common/ASC.Data.Reassigns/ASC.Data.Reassigns.csproj
@@ -2,6 +2,7 @@
 
   <PropertyGroup>
     <TargetFramework>net6.0</TargetFramework>
+	  <ImplicitUsings>enable</ImplicitUsings>
   </PropertyGroup>
 
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
diff --git a/common/ASC.Data.Reassigns/GlobalUsings.cs b/common/ASC.Data.Reassigns/GlobalUsings.cs
index bd1d0dfc15..f1d623a765 100644
--- a/common/ASC.Data.Reassigns/GlobalUsings.cs
+++ b/common/ASC.Data.Reassigns/GlobalUsings.cs
@@ -1,6 +1,4 @@
-global using System;
-global using System.Collections.Generic;
-global using System.Globalization;
+global using System.Globalization;
 global using System.Security.Cryptography;
 global using System.Text;
 
@@ -19,5 +17,4 @@ global using ASC.Web.Studio.Core.Notify;
 global using Microsoft.AspNetCore.Http;
 global using Microsoft.Extensions.DependencyInjection;
 global using Microsoft.Extensions.Options;
-global using Microsoft.Extensions.Primitives;
-
+global using Microsoft.Extensions.Primitives;
\ No newline at end of file
diff --git a/common/ASC.Data.Storage/ASC.Data.Storage.csproj b/common/ASC.Data.Storage/ASC.Data.Storage.csproj
index 92f7eb02e4..6b07fb72f0 100644
--- a/common/ASC.Data.Storage/ASC.Data.Storage.csproj
+++ b/common/ASC.Data.Storage/ASC.Data.Storage.csproj
@@ -3,6 +3,7 @@
   <PropertyGroup>
     <TargetFramework>net6.0</TargetFramework>
 	<ProduceReferenceAssembly>false</ProduceReferenceAssembly>
+	  <ImplicitUsings>enable</ImplicitUsings>
   </PropertyGroup>
 
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
diff --git a/common/ASC.Data.Storage/GlobalUsings.cs b/common/ASC.Data.Storage/GlobalUsings.cs
index 05c42d6138..86f76dce3f 100644
--- a/common/ASC.Data.Storage/GlobalUsings.cs
+++ b/common/ASC.Data.Storage/GlobalUsings.cs
@@ -1,19 +1,12 @@
-global using System;
-global using System.Collections.Concurrent;
-global using System.Collections.Generic;
+global using System.Collections.Concurrent;
 global using System.Globalization;
-global using System.IO;
-global using System.Linq;
 global using System.Net;
-global using System.Net.Http;
 global using System.Runtime.Serialization;
 global using System.Security.Cryptography;
 global using System.ServiceModel;
 global using System.Text;
 global using System.Text.Json;
 global using System.Text.Json.Serialization;
-global using System.Threading;
-global using System.Threading.Tasks;
 global using System.Web;
 
 global using Amazon;
diff --git a/common/ASC.FederatedLogin/ASC.FederatedLogin.csproj b/common/ASC.FederatedLogin/ASC.FederatedLogin.csproj
index 9d55334c68..c4e8c796f3 100644
--- a/common/ASC.FederatedLogin/ASC.FederatedLogin.csproj
+++ b/common/ASC.FederatedLogin/ASC.FederatedLogin.csproj
@@ -3,6 +3,7 @@
   <PropertyGroup>
     <TargetFramework>net6.0</TargetFramework>
     <NoWarn>NU1701</NoWarn>
+	  <ImplicitUsings>enable</ImplicitUsings>
   </PropertyGroup>
 
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
diff --git a/common/ASC.FederatedLogin/GlobalUsings.cs b/common/ASC.FederatedLogin/GlobalUsings.cs
index 2486885abb..011e3695af 100644
--- a/common/ASC.FederatedLogin/GlobalUsings.cs
+++ b/common/ASC.FederatedLogin/GlobalUsings.cs
@@ -1,12 +1,7 @@
-global using System;
-global using System.Collections.Generic;
-global using System.Data;
+global using System.Data;
 global using System.Diagnostics;
 global using System.Globalization;
-global using System.IO;
-global using System.Linq;
 global using System.Net;
-global using System.Net.Http;
 global using System.Net.Http.Headers;
 global using System.Reflection;
 global using System.Runtime.Serialization;
@@ -14,8 +9,6 @@ global using System.Security.Cryptography.Pkcs;
 global using System.Security.Cryptography.X509Certificates;
 global using System.Text;
 global using System.Text.Json.Serialization;
-global using System.Threading;
-global using System.Threading.Tasks;
 global using System.Web;
 global using System.Xml.Linq;
 global using System.Xml.XPath;
diff --git a/common/ASC.Feed/ASC.Feed.csproj b/common/ASC.Feed/ASC.Feed.csproj
index 50c014837d..9e240c51b6 100644
--- a/common/ASC.Feed/ASC.Feed.csproj
+++ b/common/ASC.Feed/ASC.Feed.csproj
@@ -5,6 +5,7 @@
     <ApplicationIcon />
     <OutputType>Library</OutputType>
     <StartupObject />
+	  <ImplicitUsings>enable</ImplicitUsings>
   </PropertyGroup>
 
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
diff --git a/common/ASC.Feed/GlobalUsings.cs b/common/ASC.Feed/GlobalUsings.cs
index 97c4f5c17e..3bcce92481 100644
--- a/common/ASC.Feed/GlobalUsings.cs
+++ b/common/ASC.Feed/GlobalUsings.cs
@@ -1,26 +1,23 @@
-global using System;
-global using System.Collections.Generic;
-global using System.Data;
-global using System.Linq;
-
+global using System.Data;
+
 global using ASC.Common;
+global using ASC.Common.Mapping;
 global using ASC.Core;
 global using ASC.Core.Common.EF;
-global using ASC.Feed.Models;
 global using ASC.Core.Common.EF.Model;
 global using ASC.Core.Tenants;
 global using ASC.Core.Users;
-global using ASC.Common.Mapping;
-global using ASC.Feed.Mapping;
-global using ASC.Feed.Data;
 global using ASC.Feed.Core;
-
-global using AutoMapper;
-
+global using ASC.Feed.Data;
+global using ASC.Feed.Mapping;
+global using ASC.Feed.Models;
+
 global using Autofac;
-
+
+global using AutoMapper;
+
 global using Microsoft.EntityFrameworkCore;
-global using Microsoft.EntityFrameworkCore.Migrations;
 global using Microsoft.EntityFrameworkCore.Infrastructure;
-
+global using Microsoft.EntityFrameworkCore.Migrations;
+
 global using Newtonsoft.Json;
diff --git a/common/ASC.IPSecurity/ASC.IPSecurity.csproj b/common/ASC.IPSecurity/ASC.IPSecurity.csproj
index 4af550a685..072f85eea2 100644
--- a/common/ASC.IPSecurity/ASC.IPSecurity.csproj
+++ b/common/ASC.IPSecurity/ASC.IPSecurity.csproj
@@ -5,6 +5,7 @@
     <ApplicationIcon />
     <OutputType>Library</OutputType>
     <StartupObject />
+	  <ImplicitUsings>enable</ImplicitUsings>
   </PropertyGroup>
 
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
diff --git a/common/ASC.IPSecurity/GlobalUsings.cs b/common/ASC.IPSecurity/GlobalUsings.cs
index 0a5fc53683..dff1701620 100644
--- a/common/ASC.IPSecurity/GlobalUsings.cs
+++ b/common/ASC.IPSecurity/GlobalUsings.cs
@@ -1,11 +1,8 @@
-global using System;
-global using System.Collections.Generic;
-global using System.Linq;
-global using System.Net;
+global using System.Net;
 global using System.Net.Sockets;
 global using System.Runtime.Serialization;
 global using System.Web;
-
+
 global using ASC.Common;
 global using ASC.Common.Caching;
 global using ASC.Common.Logging;
@@ -15,11 +12,11 @@ global using ASC.Core.Common.EF;
 global using ASC.Core.Common.EF.Context;
 global using ASC.Core.Common.EF.Model;
 global using ASC.Core.Common.Settings;
-
+
+global using AutoMapper;
+global using AutoMapper.QueryableExtensions;
+
 global using Microsoft.AspNetCore.Http;
 global using Microsoft.AspNetCore.Http.Extensions;
 global using Microsoft.Extensions.Configuration;
 global using Microsoft.Extensions.Options;
-
-global using AutoMapper;
-global using AutoMapper.QueryableExtensions;
\ No newline at end of file
diff --git a/common/ASC.MessagingSystem/ASC.MessagingSystem.csproj b/common/ASC.MessagingSystem/ASC.MessagingSystem.csproj
index 4209ed64a4..3a065da678 100644
--- a/common/ASC.MessagingSystem/ASC.MessagingSystem.csproj
+++ b/common/ASC.MessagingSystem/ASC.MessagingSystem.csproj
@@ -5,6 +5,7 @@
     <ApplicationIcon />
     <OutputType>Library</OutputType>
     <StartupObject />
+	  <ImplicitUsings>enable</ImplicitUsings>
   </PropertyGroup>
 
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
diff --git a/common/ASC.MessagingSystem/GlobalUsings.cs b/common/ASC.MessagingSystem/GlobalUsings.cs
index 442cf201d5..1f4fd10f81 100644
--- a/common/ASC.MessagingSystem/GlobalUsings.cs
+++ b/common/ASC.MessagingSystem/GlobalUsings.cs
@@ -1,33 +1,29 @@
-global using System;
-global using System.Collections.Generic;
-global using System.Linq;
-global using System.Threading;
-global using System.Web;
-
+global using System.Web;
+
 global using ASC.Common;
 global using ASC.Common.Logging;
 global using ASC.Common.Mapping;
 global using ASC.Core;
 global using ASC.Core.Common.EF;
 global using ASC.Core.Common.EF.Model;
-global using ASC.MessagingSystem.Mapping;
 global using ASC.MessagingSystem.Core;
 global using ASC.MessagingSystem.Core.Sender;
 global using ASC.MessagingSystem.Data;
+global using ASC.MessagingSystem.Mapping;
 global using ASC.MessagingSystem.Models;
-
+
+global using AutoMapper;
+
 global using Microsoft.AspNetCore.Http;
 global using Microsoft.EntityFrameworkCore;
-global using Microsoft.EntityFrameworkCore.Migrations;
-global using Microsoft.EntityFrameworkCore.Metadata;
 global using Microsoft.EntityFrameworkCore.Infrastructure;
+global using Microsoft.EntityFrameworkCore.Metadata;
+global using Microsoft.EntityFrameworkCore.Migrations;
 global using Microsoft.Extensions.Configuration;
 global using Microsoft.Extensions.DependencyInjection;
 global using Microsoft.Extensions.Options;
 global using Microsoft.Extensions.Primitives;
-
-global using AutoMapper;
-
+
 global using Newtonsoft.Json;
-
+
 global using UAParser;
diff --git a/common/ASC.Notify.Textile/ASC.Notify.Textile.csproj b/common/ASC.Notify.Textile/ASC.Notify.Textile.csproj
index cd9275d33f..4b6f6bc086 100644
--- a/common/ASC.Notify.Textile/ASC.Notify.Textile.csproj
+++ b/common/ASC.Notify.Textile/ASC.Notify.Textile.csproj
@@ -6,6 +6,7 @@
     <Product>ASC.Notify.Textile</Product>
     <Copyright>(c) Ascensio System SIA. All rights reserved</Copyright>
     <ProduceReferenceAssembly>false</ProduceReferenceAssembly>
+	  <ImplicitUsings>enable</ImplicitUsings>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugType>full</DebugType>
diff --git a/common/ASC.Notify.Textile/GlobalUsings.cs b/common/ASC.Notify.Textile/GlobalUsings.cs
index c0e9f6021d..ecdeb4a752 100644
--- a/common/ASC.Notify.Textile/GlobalUsings.cs
+++ b/common/ASC.Notify.Textile/GlobalUsings.cs
@@ -1,7 +1,4 @@
-global using System;
-global using System.IO;
-global using System.Linq;
-global using System.Reflection;
+global using System.Reflection;
 global using System.Text;
 global using System.Text.RegularExpressions;
 global using System.Web;
diff --git a/common/ASC.VoipService/GlobalUsings.cs b/common/ASC.VoipService/GlobalUsings.cs
index 121f767fbe..22b5c3979c 100644
--- a/common/ASC.VoipService/GlobalUsings.cs
+++ b/common/ASC.VoipService/GlobalUsings.cs
@@ -1,9 +1,5 @@
-global using System;
-global using System.Collections.Generic;
-global using System.Linq;
-global using System.Reflection;
+global using System.Reflection;
 global using System.Text;
-global using System.Threading;
 global using System.Web;
 
 global using ASC.Common;
@@ -33,4 +29,4 @@ global using Twilio.Rest.Api.V2010.Account;
 global using Twilio.Rest.Api.V2010.Account.AvailablePhoneNumberCountry;
 global using Twilio.Rest.Api.V2010.Account.Queue;
 global using Twilio.TwiML;
-global using Twilio.Types;
+global using Twilio.Types;
\ No newline at end of file
diff --git a/common/ASC.Webhooks.Core/ASC.Webhooks.Core.csproj b/common/ASC.Webhooks.Core/ASC.Webhooks.Core.csproj
index e7c030eb10..a47fa83ac2 100644
--- a/common/ASC.Webhooks.Core/ASC.Webhooks.Core.csproj
+++ b/common/ASC.Webhooks.Core/ASC.Webhooks.Core.csproj
@@ -2,6 +2,7 @@
 
   <PropertyGroup>
     <TargetFramework>net6.0</TargetFramework>
+	  <ImplicitUsings>enable</ImplicitUsings>
   </PropertyGroup>
 
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
diff --git a/common/ASC.Webhooks.Core/GlobalUsings.cs b/common/ASC.Webhooks.Core/GlobalUsings.cs
index 07dfa9e307..739dc20a4b 100644
--- a/common/ASC.Webhooks.Core/GlobalUsings.cs
+++ b/common/ASC.Webhooks.Core/GlobalUsings.cs
@@ -1,8 +1,4 @@
-global using System;
-global using System.Collections.Generic;
-global using System.Linq;
-
-global using ASC.Common;
+global using ASC.Common;
 global using ASC.Common.Caching;
 global using ASC.Common.Logging;
 global using ASC.Core;
diff --git a/common/services/ASC.AuditTrail/ASC.AuditTrail.csproj b/common/services/ASC.AuditTrail/ASC.AuditTrail.csproj
index b01f2130f5..3215b72a37 100644
--- a/common/services/ASC.AuditTrail/ASC.AuditTrail.csproj
+++ b/common/services/ASC.AuditTrail/ASC.AuditTrail.csproj
@@ -2,6 +2,7 @@
 
   <PropertyGroup>
     <TargetFramework>net6.0</TargetFramework>
+	  <ImplicitUsings>enable</ImplicitUsings>
   </PropertyGroup>
 
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
diff --git a/common/services/ASC.AuditTrail/GlobalUsings.cs b/common/services/ASC.AuditTrail/GlobalUsings.cs
index 8e18726604..153f7dbc0d 100644
--- a/common/services/ASC.AuditTrail/GlobalUsings.cs
+++ b/common/services/ASC.AuditTrail/GlobalUsings.cs
@@ -1,37 +1,31 @@
-global using System;
-global using System.Collections.Generic;
-global using System.Globalization;
-global using System.IO;
-global using System.Linq;
-global using System.Text;
+global using System.Globalization;
 global using System.Reflection;
-
+global using System.Text;
+
+global using ASC.AuditTrail.Attributes;
 global using ASC.AuditTrail.Mappers;
+global using ASC.AuditTrail.Models;
+global using ASC.AuditTrail.Models.Mappings;
 global using ASC.Common;
 global using ASC.Common.Logging;
+global using ASC.Common.Mapping;
 global using ASC.Core.Common.EF;
 global using ASC.Core.Users;
 global using ASC.MessagingSystem.Core;
 global using ASC.MessagingSystem.Data;
 global using ASC.MessagingSystem.Models;
-global using ASC.Web.Studio.Utility;
-global using ASC.AuditTrail.Attributes;
 global using ASC.Web.Core.Files;
 global using ASC.Web.Files.Classes;
 global using ASC.Web.Files.Utils;
-global using ASC.AuditTrail.Models;
-global using ASC.AuditTrail.Models.Mappings;
-global using ASC.Common.Mapping;
-
+global using ASC.Web.Studio.Utility;
+
 global using Autofac;
-
-global using Microsoft.Extensions.Configuration;
-global using Microsoft.Extensions.Options;
-
-global using Newtonsoft.Json;
-
+
 global using AutoMapper;
-
+
 global using CsvHelper;
-
-global using CsvHelper.Configuration;
\ No newline at end of file
+global using CsvHelper.Configuration;
+
+global using Microsoft.Extensions.Options;
+
+global using Newtonsoft.Json;
diff --git a/common/services/ASC.ClearEvents/ASC.ClearEvents.csproj b/common/services/ASC.ClearEvents/ASC.ClearEvents.csproj
index b335630620..b841ef1635 100644
--- a/common/services/ASC.ClearEvents/ASC.ClearEvents.csproj
+++ b/common/services/ASC.ClearEvents/ASC.ClearEvents.csproj
@@ -5,6 +5,7 @@
     <ApplicationIcon />
     <OutputType>Exe</OutputType>
     <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
+	  <ImplicitUsings>enable</ImplicitUsings>
   </PropertyGroup>
 
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
diff --git a/common/services/ASC.ClearEvents/GlobalUsings.cs b/common/services/ASC.ClearEvents/GlobalUsings.cs
index f98f091980..762e48e9e0 100644
--- a/common/services/ASC.ClearEvents/GlobalUsings.cs
+++ b/common/services/ASC.ClearEvents/GlobalUsings.cs
@@ -1,32 +1,22 @@
-global using System;
-global using System.IO;
-global using System.Collections.Generic;
-global using System.Linq;
-global using System.Linq.Expressions;
-global using System.Threading;
-global using System.Threading.Tasks;
-
+global using System.Linq.Expressions;
+
 global using ASC.Api.Core;
 global using ASC.ClearEvents.Services;
 global using ASC.Common;
-global using ASC.Common.Utils;
 global using ASC.Common.Caching;
 global using ASC.Common.DependencyInjection;
 global using ASC.Common.Logging;
+global using ASC.Common.Utils;
 global using ASC.Core.Common.EF;
-global using ASC.Core.Tenants;
+global using ASC.Core.Tenants;
 global using ASC.MessagingSystem.Data;
 global using ASC.MessagingSystem.Models;
-
+
 global using Autofac;
 global using Autofac.Extensions.DependencyInjection;
 
 global using Microsoft.EntityFrameworkCore;
-global using Microsoft.Extensions.Configuration;
-global using Microsoft.Extensions.DependencyInjection;
-global using Microsoft.AspNetCore.Builder;
 global using Microsoft.Extensions.Hosting.WindowsServices;
-global using Microsoft.Extensions.Hosting;
 global using Microsoft.Extensions.Options;
-
+
 global using StackExchange.Redis.Extensions.Core.Configuration;
\ No newline at end of file
diff --git a/common/services/ASC.Data.Backup/ASC.Data.Backup.csproj b/common/services/ASC.Data.Backup/ASC.Data.Backup.csproj
index b158678d5c..c7bffe25fa 100644
--- a/common/services/ASC.Data.Backup/ASC.Data.Backup.csproj
+++ b/common/services/ASC.Data.Backup/ASC.Data.Backup.csproj
@@ -6,7 +6,8 @@
     <OutputType>Exe</OutputType>
     <RazorCompileOnBuild>false</RazorCompileOnBuild>
     <GenerateMvcApplicationPartsAssemblyAttributes>false</GenerateMvcApplicationPartsAssemblyAttributes>
-    <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
+    <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
+	  <ImplicitUsings>enable</ImplicitUsings>
   </PropertyGroup>
 
 	<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
diff --git a/common/services/ASC.Data.Backup/GlobalUsings.cs b/common/services/ASC.Data.Backup/GlobalUsings.cs
index 45e32aa25b..7a84575beb 100644
--- a/common/services/ASC.Data.Backup/GlobalUsings.cs
+++ b/common/services/ASC.Data.Backup/GlobalUsings.cs
@@ -1,10 +1,4 @@
-global using System;
-global using System.Collections.Generic;
-global using System.IO;
-global using System.Linq;
-global using System.Runtime.InteropServices;
-global using System.Threading;
-global using System.Threading.Tasks;
+global using System.Runtime.InteropServices;
 
 global using ASC.Api.Collections;
 global using ASC.Api.Core;
@@ -18,7 +12,6 @@ global using ASC.Core.Billing;
 global using ASC.Data.Backup;
 global using ASC.Data.Backup.ApiModels;
 global using ASC.Data.Backup.Contracts;
-global using ASC.Data.Backup.Controllers;
 global using ASC.Data.Backup.Services;
 global using ASC.Data.Backup.Storage;
 global using ASC.Files.Core;
@@ -29,12 +22,7 @@ global using ASC.Web.Studio.Utility;
 global using Autofac;
 global using Autofac.Extensions.DependencyInjection;
 
-global using Microsoft.AspNetCore.Builder;
-global using Microsoft.AspNetCore.Hosting;
 global using Microsoft.AspNetCore.Mvc;
-global using Microsoft.Extensions.Configuration;
-global using Microsoft.Extensions.DependencyInjection;
-global using Microsoft.Extensions.Hosting;
 global using Microsoft.Extensions.Options;
 
 global using static ASC.Data.Backup.BackupAjaxHandler;
diff --git a/common/services/ASC.ElasticSearch/ASC.ElasticSearch.csproj b/common/services/ASC.ElasticSearch/ASC.ElasticSearch.csproj
index 7705a34077..bb99f89546 100644
--- a/common/services/ASC.ElasticSearch/ASC.ElasticSearch.csproj
+++ b/common/services/ASC.ElasticSearch/ASC.ElasticSearch.csproj
@@ -10,6 +10,7 @@
     <Product>ASC.ElasticSearch</Product>
     <Copyright>(c) Ascensio System SIA. All rights reserved</Copyright>
     <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
+	  <ImplicitUsings>enable</ImplicitUsings>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugType>full</DebugType>
diff --git a/common/services/ASC.ElasticSearch/GlobalUsings.cs b/common/services/ASC.ElasticSearch/GlobalUsings.cs
index 5ce36e544b..0775a80a0d 100644
--- a/common/services/ASC.ElasticSearch/GlobalUsings.cs
+++ b/common/services/ASC.ElasticSearch/GlobalUsings.cs
@@ -1,14 +1,9 @@
-global using System;
-global using System.Collections;
+global using System.Collections;
 global using System.Collections.Concurrent;
-global using System.Collections.Generic;
 global using System.Data;
 global using System.Globalization;
-global using System.Linq;
 global using System.Linq.Expressions;
 global using System.Text;
-global using System.Threading;
-global using System.Threading.Tasks;
 
 global using ASC.Common;
 global using ASC.Common.Caching;
@@ -34,4 +29,4 @@ global using Microsoft.Extensions.Options;
 
 global using Nest;
 
-global using Newtonsoft.Json;
+global using Newtonsoft.Json;
\ No newline at end of file
diff --git a/common/services/ASC.Feed.Aggregator/ASC.Feed.Aggregator.csproj b/common/services/ASC.Feed.Aggregator/ASC.Feed.Aggregator.csproj
index a8ee5a8e4d..46c7490f94 100644
--- a/common/services/ASC.Feed.Aggregator/ASC.Feed.Aggregator.csproj
+++ b/common/services/ASC.Feed.Aggregator/ASC.Feed.Aggregator.csproj
@@ -3,6 +3,7 @@
   <PropertyGroup>
     <OutputType>Library</OutputType>
     <TargetFramework>net6.0</TargetFramework>
+	  <ImplicitUsings>enable</ImplicitUsings>
   </PropertyGroup>
 
   <ItemGroup>
diff --git a/common/services/ASC.Feed.Aggregator/GlobalUsings.cs b/common/services/ASC.Feed.Aggregator/GlobalUsings.cs
index 989b6f6d4b..eadbc6c9b8 100644
--- a/common/services/ASC.Feed.Aggregator/GlobalUsings.cs
+++ b/common/services/ASC.Feed.Aggregator/GlobalUsings.cs
@@ -1,9 +1,4 @@
-global using System;
-global using System.Collections.Generic;
-global using System.Data;
-global using System.Linq;
-global using System.Threading;
-global using System.Threading.Tasks;
+global using System.Data;
 
 global using ASC.Common;
 global using ASC.Common.Caching;
diff --git a/common/services/ASC.Notify/GlobalUsings.cs b/common/services/ASC.Notify/GlobalUsings.cs
index 86a454ee10..e29341dfde 100644
--- a/common/services/ASC.Notify/GlobalUsings.cs
+++ b/common/services/ASC.Notify/GlobalUsings.cs
@@ -1,6 +1,6 @@
-global using System.Reflection;
-global using System.Data;
-
+global using System.Data;
+global using System.Reflection;
+
 global using ASC.Api.Core;
 global using ASC.Common;
 global using ASC.Common.Caching;
@@ -14,24 +14,24 @@ global using ASC.Core.Common.EF.Context;
 global using ASC.Core.Common.EF.Model;
 global using ASC.Core.Common.Settings;
 global using ASC.Core.Notify.Senders;
-global using ASC.Notify.Services;
 global using ASC.Notify.Config;
 global using ASC.Notify.Messages;
+global using ASC.Notify.Services;
 global using ASC.Web.Core.WhiteLabel;
 global using ASC.Web.Studio.Core.Notify;
-
-global using AutoMapper;
-
+
 global using Autofac;
 global using Autofac.Extensions.DependencyInjection;
-
+
+global using AutoMapper;
+
 global using Google.Protobuf.Collections;
-
-global using Microsoft.Extensions.Options;
+
 global using Microsoft.EntityFrameworkCore;
 global using Microsoft.Extensions.Hosting.WindowsServices;
-
+global using Microsoft.Extensions.Options;
+
 global using Newtonsoft.Json;
-
+
 global using StackExchange.Redis.Extensions.Core.Configuration;
 global using StackExchange.Redis.Extensions.Newtonsoft;
diff --git a/common/services/ASC.Socket.IO.Svc/ASC.Socket.IO.Svc.csproj b/common/services/ASC.Socket.IO.Svc/ASC.Socket.IO.Svc.csproj
index fac60bbf96..b06e76aa43 100644
--- a/common/services/ASC.Socket.IO.Svc/ASC.Socket.IO.Svc.csproj
+++ b/common/services/ASC.Socket.IO.Svc/ASC.Socket.IO.Svc.csproj
@@ -7,6 +7,7 @@
     <RazorCompileOnBuild>false</RazorCompileOnBuild>
     <GenerateMvcApplicationPartsAssemblyAttributes>false</GenerateMvcApplicationPartsAssemblyAttributes>
     <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
+	  <ImplicitUsings>enable</ImplicitUsings>
   </PropertyGroup>
 
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
diff --git a/common/services/ASC.Studio.Notify/ASC.Studio.Notify.csproj b/common/services/ASC.Studio.Notify/ASC.Studio.Notify.csproj
index c83caa5d67..402401071d 100644
--- a/common/services/ASC.Studio.Notify/ASC.Studio.Notify.csproj
+++ b/common/services/ASC.Studio.Notify/ASC.Studio.Notify.csproj
@@ -6,6 +6,7 @@
     <RazorCompileOnBuild>false</RazorCompileOnBuild>
     <GenerateMvcApplicationPartsAssemblyAttributes>false</GenerateMvcApplicationPartsAssemblyAttributes>
     <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
+	  <ImplicitUsings>enable</ImplicitUsings>
   </PropertyGroup>
 
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
diff --git a/common/services/ASC.Studio.Notify/GlobalUsings.cs b/common/services/ASC.Studio.Notify/GlobalUsings.cs
index 6a96194783..4e7ae618c6 100644
--- a/common/services/ASC.Studio.Notify/GlobalUsings.cs
+++ b/common/services/ASC.Studio.Notify/GlobalUsings.cs
@@ -1,10 +1,5 @@
-global using System;
-global using System.Collections.Generic;
-global using System.IO;
-global using System.Reflection;
+global using System.Reflection;
 global using System.Runtime.InteropServices;
-global using System.Threading;
-global using System.Threading.Tasks;
 
 global using ASC.Api.Core;
 global using ASC.Common;
@@ -17,12 +12,7 @@ global using ASC.Web.Studio.Core.Notify;
 
 global using Autofac.Extensions.DependencyInjection;
 
-global using Microsoft.AspNetCore.Builder;
-global using Microsoft.AspNetCore.Hosting;
-global using Microsoft.Extensions.Configuration;
-global using Microsoft.Extensions.DependencyInjection;
-global using Microsoft.Extensions.Hosting;
 global using Microsoft.Extensions.Hosting.WindowsServices;
 
 global using StackExchange.Redis.Extensions.Core.Configuration;
-global using StackExchange.Redis.Extensions.Newtonsoft;
+global using StackExchange.Redis.Extensions.Newtonsoft;
\ No newline at end of file
diff --git a/common/services/ASC.TelegramService/GlobalUsings.cs b/common/services/ASC.TelegramService/GlobalUsings.cs
index 046b7ac868..91df562f9c 100644
--- a/common/services/ASC.TelegramService/GlobalUsings.cs
+++ b/common/services/ASC.TelegramService/GlobalUsings.cs
@@ -19,13 +19,8 @@ global using ASC.TelegramService;
 global using ASC.TelegramService.Core;
 
 global using Autofac;
-global using Autofac.Extensions.DependencyInjection;
-
-global using Microsoft.AspNetCore.Builder;
-global using Microsoft.AspNetCore.Hosting;
-global using Microsoft.Extensions.Configuration;
-global using Microsoft.Extensions.DependencyInjection;
-global using Microsoft.Extensions.Hosting;
+global using Autofac.Extensions.DependencyInjection;
+
 global using Microsoft.Extensions.Hosting.WindowsServices;
 global using Microsoft.Extensions.Options;
 
diff --git a/common/services/ASC.UrlShortener.Svc/ASC.UrlShortener.Svc.csproj b/common/services/ASC.UrlShortener.Svc/ASC.UrlShortener.Svc.csproj
index 5a9230af8c..3bee5a7052 100644
--- a/common/services/ASC.UrlShortener.Svc/ASC.UrlShortener.Svc.csproj
+++ b/common/services/ASC.UrlShortener.Svc/ASC.UrlShortener.Svc.csproj
@@ -7,6 +7,7 @@
     <RazorCompileOnBuild>false</RazorCompileOnBuild>
     <GenerateMvcApplicationPartsAssemblyAttributes>false</GenerateMvcApplicationPartsAssemblyAttributes>
     <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
+	  <ImplicitUsings>enable</ImplicitUsings>
   </PropertyGroup>
 
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
diff --git a/common/services/ASC.UrlShortener.Svc/GlobalUsings.cs b/common/services/ASC.UrlShortener.Svc/GlobalUsings.cs
index f1fef22d98..838f36cae8 100644
--- a/common/services/ASC.UrlShortener.Svc/GlobalUsings.cs
+++ b/common/services/ASC.UrlShortener.Svc/GlobalUsings.cs
@@ -1,9 +1,4 @@
-global using System;
-global using System.Collections.Generic;
-global using System.Diagnostics;
-global using System.IO;
-global using System.Threading;
-global using System.Threading.Tasks;
+global using System.Diagnostics;
 
 global using ASC.Api.Core;
 global using ASC.Common;
@@ -15,10 +10,6 @@ global using ASC.Common.Utils;
 global using Autofac;
 global using Autofac.Extensions.DependencyInjection;
 
-global using Microsoft.AspNetCore.Hosting;
-global using Microsoft.Extensions.Configuration;
-global using Microsoft.Extensions.DependencyInjection;
-global using Microsoft.Extensions.Hosting;
 global using Microsoft.Extensions.Options;
 
 global using StackExchange.Redis.Extensions.Core.Configuration;
diff --git a/common/services/ASC.Webhooks.Service/ASC.Webhooks.Service.csproj b/common/services/ASC.Webhooks.Service/ASC.Webhooks.Service.csproj
index 4656bc88dd..af8fac4651 100644
--- a/common/services/ASC.Webhooks.Service/ASC.Webhooks.Service.csproj
+++ b/common/services/ASC.Webhooks.Service/ASC.Webhooks.Service.csproj
@@ -3,6 +3,7 @@
   <PropertyGroup>
     <TargetFramework>net6.0</TargetFramework>
     <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
+	  <ImplicitUsings>enable</ImplicitUsings>
   </PropertyGroup>
 
   <ItemGroup>
diff --git a/common/services/ASC.Webhooks.Service/GlobalUsings.cs b/common/services/ASC.Webhooks.Service/GlobalUsings.cs
index 13eaabb2a0..76d74c3fb6 100644
--- a/common/services/ASC.Webhooks.Service/GlobalUsings.cs
+++ b/common/services/ASC.Webhooks.Service/GlobalUsings.cs
@@ -1,15 +1,8 @@
-global using System;
-global using System.Collections.Concurrent;
-global using System.Collections.Generic;
-global using System.IO;
-global using System.Linq;
-global using System.Net.Http;
+global using System.Collections.Concurrent;
 global using System.Runtime.InteropServices;
 global using System.Security.Cryptography;
 global using System.Text;
 global using System.Text.Json;
-global using System.Threading;
-global using System.Threading.Tasks;
 
 global using ASC.Api.Core;
 global using ASC.Common;
@@ -24,11 +17,6 @@ global using ASC.Webhooks.Service.Services;
 global using Autofac;
 global using Autofac.Extensions.DependencyInjection;
 
-global using Microsoft.AspNetCore.Builder;
-global using Microsoft.AspNetCore.Hosting;
-global using Microsoft.Extensions.Configuration;
-global using Microsoft.Extensions.DependencyInjection;
-global using Microsoft.Extensions.Hosting;
 global using Microsoft.Extensions.Hosting.WindowsServices;
 global using Microsoft.Extensions.Options;
 
diff --git a/products/ASC.Files/Core/GlobalUsings.cs b/products/ASC.Files/Core/GlobalUsings.cs
index b65919ee02..49e6a2e660 100644
--- a/products/ASC.Files/Core/GlobalUsings.cs
+++ b/products/ASC.Files/Core/GlobalUsings.cs
@@ -7,8 +7,8 @@ global using System.Linq.Expressions;
 global using System.Net;
 global using System.Net.Http.Headers;
 global using System.Net.Mime;
-global using System.Runtime.Serialization;
 global using System.Reflection;
+global using System.Runtime.Serialization;
 global using System.Security;
 global using System.Security.Principal;
 global using System.Text;
@@ -55,7 +55,6 @@ global using ASC.FederatedLogin.Helpers;
 global using ASC.FederatedLogin.LoginProviders;
 global using ASC.FederatedLogin.Profile;
 global using ASC.Files.Core;
-global using ASC.Files.Model;
 global using ASC.Files.Core.Data;
 global using ASC.Files.Core.EF;
 global using ASC.Files.Core.Model;
@@ -63,6 +62,7 @@ global using ASC.Files.Core.Resources;
 global using ASC.Files.Core.Security;
 global using ASC.Files.Core.Services.NotifyService;
 global using ASC.Files.Core.Thirdparty;
+global using ASC.Files.Model;
 global using ASC.Files.Thirdparty;
 global using ASC.Files.Thirdparty.Box;
 global using ASC.Files.Thirdparty.Dropbox;
@@ -71,8 +71,8 @@ global using ASC.Files.Thirdparty.OneDrive;
 global using ASC.Files.Thirdparty.ProviderDao;
 global using ASC.Files.Thirdparty.SharePoint;
 global using ASC.Files.Thirdparty.Sharpbox;
-global using ASC.MessagingSystem.Models;
 global using ASC.MessagingSystem.Core;
+global using ASC.MessagingSystem.Models;
 global using ASC.Notify.Model;
 global using ASC.Notify.Patterns;
 global using ASC.Notify.Recipients;
@@ -178,4 +178,4 @@ global using JsonSerializer = System.Text.Json.JsonSerializer;
 global using JsonTokenType = System.Text.Json.JsonTokenType;
 global using JsonConverter = System.Text.Json.Serialization.JsonConverter;
 global using JsonConverterAttribute = System.Text.Json.Serialization.JsonConverterAttribute;
-global using JsonIgnoreAttribute = System.Text.Json.Serialization.JsonIgnoreAttribute;
+global using JsonIgnoreAttribute = System.Text.Json.Serialization.JsonIgnoreAttribute;
\ No newline at end of file
diff --git a/products/ASC.Files/Server/ASC.Files.csproj b/products/ASC.Files/Server/ASC.Files.csproj
index ee4c730114..4546ffd646 100644
--- a/products/ASC.Files/Server/ASC.Files.csproj
+++ b/products/ASC.Files/Server/ASC.Files.csproj
@@ -10,6 +10,7 @@
     <Product>ASC.Files</Product>
     <Copyright>(c) Ascensio System SIA. All rights reserved</Copyright>
     <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
+	  <ImplicitUsings>enable</ImplicitUsings>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugType>full</DebugType>
diff --git a/products/ASC.Files/Server/GlobalUsings.cs b/products/ASC.Files/Server/GlobalUsings.cs
index fd661b0c35..3fe8d96ed0 100644
--- a/products/ASC.Files/Server/GlobalUsings.cs
+++ b/products/ASC.Files/Server/GlobalUsings.cs
@@ -1,15 +1,9 @@
-global using System;
-global using System.Collections.Generic;
-global using System.Globalization;
-global using System.IO;
-global using System.Linq;
-global using System.Net.Http;
+global using System.Globalization;
 global using System.Runtime.InteropServices;
 global using System.Text;
 global using System.Text.Json;
 global using System.Text.Json.Serialization;
 global using System.Text.RegularExpressions;
-global using System.Threading.Tasks;
 global using System.Web;
 
 global using ASC.Api.Core;
@@ -54,15 +48,9 @@ global using ASC.Web.Studio.Utility;
 global using Autofac.Extensions.DependencyInjection;
 
 global using Microsoft.AspNetCore.Authorization;
-global using Microsoft.AspNetCore.Builder;
-global using Microsoft.AspNetCore.Hosting;
-global using Microsoft.AspNetCore.Http;
 global using Microsoft.AspNetCore.Mvc;
-global using Microsoft.Extensions.Configuration;
-global using Microsoft.Extensions.DependencyInjection;
-global using Microsoft.Extensions.Hosting;
 global using Microsoft.Extensions.Options;
 
 global using Newtonsoft.Json.Linq;
 
-global using static ASC.Api.Documents.FilesController;
+global using static ASC.Api.Documents.FilesController;
\ No newline at end of file
diff --git a/products/ASC.People/Server/ASC.People.csproj b/products/ASC.People/Server/ASC.People.csproj
index 27c2945ebb..69dc068152 100644
--- a/products/ASC.People/Server/ASC.People.csproj
+++ b/products/ASC.People/Server/ASC.People.csproj
@@ -11,6 +11,7 @@
     <Company>Ascensio System SIA</Company>
     <Product>ASC.People</Product>
     <Copyright>(c) Ascensio System SIA. All rights reserved</Copyright>
+	  <ImplicitUsings>enable</ImplicitUsings>
   </PropertyGroup>
 
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
diff --git a/products/ASC.People/Server/GlobalUsings.cs b/products/ASC.People/Server/GlobalUsings.cs
index 1a920c070a..a503f76959 100644
--- a/products/ASC.People/Server/GlobalUsings.cs
+++ b/products/ASC.People/Server/GlobalUsings.cs
@@ -1,14 +1,7 @@
-global using System;
-global using System.Collections.Generic;
-global using System.IO;
-global using System.Linq;
-global using System.Net.Http;
-global using System.Net.Mail;
+global using System.Net.Mail;
 global using System.Runtime.InteropServices;
 global using System.Security;
 global using System.ServiceModel.Security;
-global using System.Threading;
-global using System.Threading.Tasks;
 global using System.Web;
 
 global using ASC.Api.Core;
@@ -22,7 +15,6 @@ global using ASC.Core.Common.Settings;
 global using ASC.Core.Tenants;
 global using ASC.Core.Users;
 global using ASC.Data.Reassigns;
-global using ASC.Employee.Core.Controllers;
 global using ASC.FederatedLogin;
 global using ASC.FederatedLogin.LoginProviders;
 global using ASC.FederatedLogin.Profile;
@@ -46,17 +38,9 @@ global using ASC.Web.Studio.Utility;
 global using Autofac.Extensions.DependencyInjection;
 
 global using Microsoft.AspNetCore.Authorization;
-global using Microsoft.AspNetCore.Hosting;
-global using Microsoft.AspNetCore.Http;
 global using Microsoft.AspNetCore.Http.Extensions;
 global using Microsoft.AspNetCore.Mvc;
-global using Microsoft.Extensions.Configuration;
-global using Microsoft.Extensions.DependencyInjection;
-global using Microsoft.Extensions.Hosting;
 global using Microsoft.Extensions.Options;
 
 global using SixLabors.ImageSharp;
 global using SixLabors.ImageSharp.Formats;
-
-global using StackExchange.Redis.Extensions.Core.Configuration;
-global using StackExchange.Redis.Extensions.Newtonsoft;
diff --git a/web/ASC.Web.Api/ASC.Web.Api.csproj b/web/ASC.Web.Api/ASC.Web.Api.csproj
index 86fd6999fd..58e31613ef 100644
--- a/web/ASC.Web.Api/ASC.Web.Api.csproj
+++ b/web/ASC.Web.Api/ASC.Web.Api.csproj
@@ -9,6 +9,7 @@
     <RazorCompileOnBuild>false</RazorCompileOnBuild>
     <GenerateMvcApplicationPartsAssemblyAttributes>false</GenerateMvcApplicationPartsAssemblyAttributes>
     <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
+	  <ImplicitUsings>enable</ImplicitUsings>
   </PropertyGroup>
 
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
diff --git a/web/ASC.Web.Api/GlobalUsings.cs b/web/ASC.Web.Api/GlobalUsings.cs
index c6a379b0e8..657739a175 100644
--- a/web/ASC.Web.Api/GlobalUsings.cs
+++ b/web/ASC.Web.Api/GlobalUsings.cs
@@ -1,11 +1,6 @@
-global using System;
-global using System.Collections.Generic;
-global using System.Collections.Specialized;
+global using System.Collections.Specialized;
 global using System.Globalization;
-global using System.IO;
-global using System.Linq;
 global using System.Net;
-global using System.Net.Http;
 global using System.Net.Mail;
 global using System.Net.Sockets;
 global using System.Runtime.InteropServices;
@@ -14,18 +9,16 @@ global using System.ServiceModel.Security;
 global using System.Text.Json;
 global using System.Text.Json.Serialization;
 global using System.Text.RegularExpressions;
-global using System.Threading;
-global using System.Threading.Tasks;
 global using System.Web;
-
+
 global using ASC.Api.Collections;
 global using ASC.Api.Core;
 global using ASC.Api.Security;
-global using ASC.Api.Settings;
 global using ASC.Api.Settings.Smtp;
 global using ASC.Api.Utils;
 global using ASC.AuditTrail;
 global using ASC.AuditTrail.Models;
+global using ASC.AuditTrail.Repositories;
 global using ASC.Common;
 global using ASC.Common.Caching;
 global using ASC.Common.Logging;
@@ -57,7 +50,6 @@ global using ASC.IPSecurity;
 global using ASC.MessagingSystem.Core;
 global using ASC.MessagingSystem.Models;
 global using ASC.Security.Cryptography;
-global using ASC.Web.Api.Controllers;
 global using ASC.Web.Api.Core;
 global using ASC.Web.Api.Models;
 global using ASC.Web.Api.Routing;
@@ -84,25 +76,19 @@ global using ASC.Web.Studio.UserControls.Statistics;
 global using ASC.Web.Studio.Utility;
 global using ASC.Webhooks.Core;
 global using ASC.Webhooks.Core.Dao.Models;
-global using ASC.AuditTrail.Repositories;
-
+
 global using Autofac.Extensions.DependencyInjection;
-
+
 global using Google.Authenticator;
-
+
 global using MailKit.Security;
-
+
 global using Microsoft.AspNetCore.Authorization;
-global using Microsoft.AspNetCore.Hosting;
-global using Microsoft.AspNetCore.Http;
 global using Microsoft.AspNetCore.Mvc;
 global using Microsoft.AspNetCore.Mvc.ModelBinding;
 global using Microsoft.Extensions.Caching.Memory;
-global using Microsoft.Extensions.Configuration;
-global using Microsoft.Extensions.DependencyInjection;
-global using Microsoft.Extensions.Hosting;
 global using Microsoft.Extensions.Options;
-
+
 global using MimeKit;
-
+
 global using static ASC.Security.Cryptography.EmailValidationKeyProvider;
diff --git a/web/ASC.Web.Core/ASC.Web.Core.csproj b/web/ASC.Web.Core/ASC.Web.Core.csproj
index 33a7b4790e..702d7a5372 100644
--- a/web/ASC.Web.Core/ASC.Web.Core.csproj
+++ b/web/ASC.Web.Core/ASC.Web.Core.csproj
@@ -3,6 +3,7 @@
   <PropertyGroup>
     <TargetFramework>net6.0</TargetFramework>
     <ProduceReferenceAssembly>false</ProduceReferenceAssembly>
+	  <ImplicitUsings>enable</ImplicitUsings>
   </PropertyGroup>
 
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
diff --git a/web/ASC.Web.Core/GlobalUsings.cs b/web/ASC.Web.Core/GlobalUsings.cs
index 98c7441af3..953a5a171e 100644
--- a/web/ASC.Web.Core/GlobalUsings.cs
+++ b/web/ASC.Web.Core/GlobalUsings.cs
@@ -1,14 +1,9 @@
-global using System;
-global using System.Collections.Concurrent;
-global using System.Collections.Generic;
+global using System.Collections.Concurrent;
 global using System.ComponentModel;
 global using System.Data;
 global using System.Diagnostics;
 global using System.Globalization;
-global using System.IO;
-global using System.Linq;
 global using System.Net;
-global using System.Net.Http;
 global using System.Net.Http.Headers;
 global using System.Net.Mail;
 global using System.Net.Mime;
@@ -21,11 +16,9 @@ global using System.Text;
 global using System.Text.Encodings.Web;
 global using System.Text.Json.Serialization;
 global using System.Text.RegularExpressions;
-global using System.Threading;
-global using System.Threading.Tasks;
 global using System.Web;
 global using System.Xml;
-
+
 global using ASC.Common;
 global using ASC.Common.Caching;
 global using ASC.Common.Logging;
@@ -84,10 +77,12 @@ global using ASC.Web.Studio.Core.Notify;
 global using ASC.Web.Studio.UserControls.Management;
 global using ASC.Web.Studio.UserControls.Statistics;
 global using ASC.Web.Studio.Utility;
-
+
+global using AutoMapper;
+
 global using Google.Authenticator;
 global using Google.Protobuf;
-
+
 global using Microsoft.AspNetCore.Hosting;
 global using Microsoft.AspNetCore.Http;
 global using Microsoft.AspNetCore.Mvc;
@@ -97,28 +92,26 @@ global using Microsoft.Extensions.Configuration;
 global using Microsoft.Extensions.DependencyInjection;
 global using Microsoft.Extensions.Hosting;
 global using Microsoft.Extensions.Options;
-
+
 global using MimeKit.Utils;
-
+
 global using Newtonsoft.Json;
 global using Newtonsoft.Json.Linq;
-
-global using AutoMapper;
-
+
 global using SixLabors.ImageSharp;
 global using SixLabors.ImageSharp.Drawing.Processing;
 global using SixLabors.ImageSharp.Formats;
 global using SixLabors.ImageSharp.Formats.Png;
 global using SixLabors.ImageSharp.PixelFormats;
 global using SixLabors.ImageSharp.Processing;
-
+
 global using TMResourceData;
-
+
 global using Twilio.Clients;
 global using Twilio.Rest.Api.V2010.Account;
 global using Twilio.Types;
-
+
 global using static ASC.Web.Core.Files.DocumentService;
-
+
 global using License = ASC.Core.Billing.License;
-global using SecurityContext = ASC.Core.SecurityContext;
+global using SecurityContext = ASC.Core.SecurityContext;
\ No newline at end of file
diff --git a/web/ASC.Web.HealthChecks.UI/ASC.Web.HealthChecks.UI.csproj b/web/ASC.Web.HealthChecks.UI/ASC.Web.HealthChecks.UI.csproj
index 6e87bf0b9b..b11b6b2e1b 100644
--- a/web/ASC.Web.HealthChecks.UI/ASC.Web.HealthChecks.UI.csproj
+++ b/web/ASC.Web.HealthChecks.UI/ASC.Web.HealthChecks.UI.csproj
@@ -3,6 +3,7 @@
   <PropertyGroup>
     <TargetFramework>net6.0</TargetFramework>
     <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
+	  <ImplicitUsings>enable</ImplicitUsings>
   </PropertyGroup>
 
   <ItemGroup>
diff --git a/web/ASC.Web.HealthChecks.UI/GlobalUsings.cs b/web/ASC.Web.HealthChecks.UI/GlobalUsings.cs
index ff68c82176..bd95d5eb03 100644
--- a/web/ASC.Web.HealthChecks.UI/GlobalUsings.cs
+++ b/web/ASC.Web.HealthChecks.UI/GlobalUsings.cs
@@ -1,13 +1,6 @@
-
-global using System;
+global using ASC.Web.HealthChecks.UI;
 
-global using ASC.Web.HealthChecks.UI;
 
-global using Microsoft.AspNetCore.Builder;
 global using Microsoft.AspNetCore.Diagnostics.HealthChecks;
-global using Microsoft.AspNetCore.Hosting;
-global using Microsoft.Extensions.Configuration;
-global using Microsoft.Extensions.DependencyInjection;
 global using Microsoft.Extensions.Diagnostics.HealthChecks;
-global using Microsoft.Extensions.Hosting;
 global using Microsoft.Extensions.Hosting.WindowsServices;
\ No newline at end of file
diff --git a/web/ASC.Web.Studio/ASC.Web.Studio.csproj b/web/ASC.Web.Studio/ASC.Web.Studio.csproj
index e4a7429970..f058703eb0 100644
--- a/web/ASC.Web.Studio/ASC.Web.Studio.csproj
+++ b/web/ASC.Web.Studio/ASC.Web.Studio.csproj
@@ -7,6 +7,7 @@
     <RazorCompileOnBuild>false</RazorCompileOnBuild>
     <GenerateMvcApplicationPartsAssemblyAttributes>false</GenerateMvcApplicationPartsAssemblyAttributes>
     <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
+	  <ImplicitUsings>enable</ImplicitUsings>
   </PropertyGroup>
 
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
diff --git a/web/ASC.Web.Studio/GlobalUsings.cs b/web/ASC.Web.Studio/GlobalUsings.cs
index 8a502fdcf7..0c7a0cae73 100644
--- a/web/ASC.Web.Studio/GlobalUsings.cs
+++ b/web/ASC.Web.Studio/GlobalUsings.cs
@@ -1,7 +1,4 @@
-global using System;
-global using System.Collections.Generic;
-global using System.IO;
-global using System.Runtime.InteropServices;
+global using System.Runtime.InteropServices;
 
 global using ASC.Api.Core;
 global using ASC.Common.Utils;
@@ -14,10 +11,5 @@ global using ASC.Web.Studio;
 global using Autofac;
 global using Autofac.Extensions.DependencyInjection;
 
-global using Microsoft.AspNetCore.Builder;
-global using Microsoft.AspNetCore.Hosting;
 global using Microsoft.AspNetCore.HttpOverrides;
-global using Microsoft.Extensions.Configuration;
-global using Microsoft.Extensions.DependencyInjection;
-global using Microsoft.Extensions.Hosting;
 global using Microsoft.Extensions.Hosting.WindowsServices;

From 51475c0c519526a6cb2fc64467b746f2cb8ee153 Mon Sep 17 00:00:00 2001
From: MaksimChegulov <maksim.chegulov@onlyoffice.com>
Date: Sat, 5 Mar 2022 15:57:46 +0300
Subject: [PATCH 25/28] People: removed engines

---
 .../Server/Api/ContactsController.cs          |   98 +-
 .../ASC.People/Server/Api/GroupController.cs  |  253 +++-
 .../Server/Api/NotificationController.cs      |   56 +-
 .../PeopleControllerBase.cs}                  |   42 +-
 .../ASC.People/Server/Api/PhotoController.cs  |  241 +++-
 .../Server/Api/ReassignController.cs          |   80 +-
 .../Server/Api/RemoveUserDataController.cs    |   86 +-
 .../Server/Api/ThirdpartyController.cs        |  332 ++++-
 .../ASC.People/Server/Api/UserController.cs   | 1100 ++++++++++++++++-
 .../ApiEngines/ApiControllerEngineBase.cs     |   37 -
 .../ApiEngines/ContactsControllerEngine.cs    |  109 --
 .../ApiEngines/GroupControllerEngine.cs       |  223 ----
 .../NotificationControllerEngine.cs           |   58 -
 .../ApiEngines/PhotoControllerEngine.cs       |  246 ----
 .../ApiEngines/ReassignControllerEngine.cs    |   76 --
 .../RemoveUserDataControllerEngine.cs         |   78 --
 .../ApiEngines/ThirdpartyControllerEngine.cs  |  331 -----
 .../Server/ApiEngines/UserControllerEngine.cs | 1087 ----------------
 products/ASC.People/Server/GlobalUsings.cs    |    3 -
 19 files changed, 2127 insertions(+), 2409 deletions(-)
 rename products/ASC.People/Server/{ApiEngines/PeopleControllerEngine.cs => Api/PeopleControllerBase.cs} (68%)
 delete mode 100644 products/ASC.People/Server/ApiEngines/ApiControllerEngineBase.cs
 delete mode 100644 products/ASC.People/Server/ApiEngines/ContactsControllerEngine.cs
 delete mode 100644 products/ASC.People/Server/ApiEngines/GroupControllerEngine.cs
 delete mode 100644 products/ASC.People/Server/ApiEngines/NotificationControllerEngine.cs
 delete mode 100644 products/ASC.People/Server/ApiEngines/PhotoControllerEngine.cs
 delete mode 100644 products/ASC.People/Server/ApiEngines/ReassignControllerEngine.cs
 delete mode 100644 products/ASC.People/Server/ApiEngines/RemoveUserDataControllerEngine.cs
 delete mode 100644 products/ASC.People/Server/ApiEngines/ThirdpartyControllerEngine.cs
 delete mode 100644 products/ASC.People/Server/ApiEngines/UserControllerEngine.cs

diff --git a/products/ASC.People/Server/Api/ContactsController.cs b/products/ASC.People/Server/Api/ContactsController.cs
index e19497ee89..419400698f 100644
--- a/products/ASC.People/Server/Api/ContactsController.cs
+++ b/products/ASC.People/Server/Api/ContactsController.cs
@@ -1,50 +1,128 @@
 namespace ASC.People.Api;
 
-public class ContactsController : ApiControllerBase
+public class ContactsController : PeopleControllerBase
 {
-    private readonly ContactsControllerEngine _contactsControllerEngine;
+    private readonly EmployeeFullDtoHelper _employeeFullDtoHelper;
 
-    public ContactsController(ContactsControllerEngine contactsControllerEngine)
+    public ContactsController(
+        UserManager userManager,
+        PermissionContext permissionContext,
+        ApiContext apiContext,
+        UserPhotoManager userPhotoManager,
+        IHttpClientFactory httpClientFactory,
+        EmployeeFullDtoHelper employeeFullDtoHelper) 
+        : base(userManager, permissionContext, apiContext, userPhotoManager, httpClientFactory)
     {
-        _contactsControllerEngine = contactsControllerEngine;
+        _employeeFullDtoHelper = employeeFullDtoHelper;
     }
 
     [Delete("{userid}/contacts")]
     public EmployeeFullDto DeleteMemberContactsFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
     {
-        return _contactsControllerEngine.DeleteMemberContacts(userid, memberModel);
+        return DeleteMemberContacts(userid, memberModel);
     }
 
     [Delete("{userid}/contacts")]
     [Consumes("application/x-www-form-urlencoded")]
     public EmployeeFullDto DeleteMemberContactsFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
     {
-        return _contactsControllerEngine.DeleteMemberContacts(userid, memberModel);
+        return DeleteMemberContacts(userid, memberModel);
     }
 
     [Create("{userid}/contacts")]
     public EmployeeFullDto SetMemberContactsFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
     {
-        return _contactsControllerEngine.SetMemberContacts(userid, memberModel);
+        return SetMemberContacts(userid, memberModel);
     }
 
     [Create("{userid}/contacts")]
     [Consumes("application/x-www-form-urlencoded")]
     public EmployeeFullDto SetMemberContactsFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
     {
-        return _contactsControllerEngine.SetMemberContacts(userid, memberModel);
+        return SetMemberContacts(userid, memberModel);
     }
 
     [Update("{userid}/contacts")]
     public EmployeeFullDto UpdateMemberContactsFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
     {
-        return _contactsControllerEngine.UpdateMemberContacts(userid, memberModel);
+        return UpdateMemberContacts(userid, memberModel);
     }
 
     [Update("{userid}/contacts")]
     [Consumes("application/x-www-form-urlencoded")]
     public EmployeeFullDto UpdateMemberContactsFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
     {
-        return _contactsControllerEngine.UpdateMemberContacts(userid, memberModel);
+        return UpdateMemberContacts(userid, memberModel);
+    }
+
+    private EmployeeFullDto DeleteMemberContacts(string userid, UpdateMemberRequestDto memberModel)
+    {
+        var user = GetUserInfo(userid);
+
+        if (_userManager.IsSystemUser(user.Id))
+        {
+            throw new SecurityException();
+        }
+
+        DeleteContacts(memberModel.Contacts, user);
+        _userManager.SaveUserInfo(user);
+
+        return _employeeFullDtoHelper.GetFull(user);
+    }
+
+    private EmployeeFullDto SetMemberContacts(string userid, UpdateMemberRequestDto memberModel)
+    {
+        var user = GetUserInfo(userid);
+
+        if (_userManager.IsSystemUser(user.Id))
+        {
+            throw new SecurityException();
+        }
+
+        user.ContactsList.Clear();
+        UpdateContacts(memberModel.Contacts, user);
+        _userManager.SaveUserInfo(user);
+
+        return _employeeFullDtoHelper.GetFull(user);
+    }
+
+    private EmployeeFullDto UpdateMemberContacts(string userid, UpdateMemberRequestDto memberModel)
+    {
+        var user = GetUserInfo(userid);
+
+        if (_userManager.IsSystemUser(user.Id))
+        {
+            throw new SecurityException();
+        }
+
+        UpdateContacts(memberModel.Contacts, user);
+        _userManager.SaveUserInfo(user);
+
+        return _employeeFullDtoHelper.GetFull(user);
+    }
+
+    private void DeleteContacts(IEnumerable<Contact> contacts, UserInfo user)
+    {   
+        _permissionContext.DemandPermissions(new UserSecurityProvider(user.Id), Constants.Action_EditUser);
+
+        if (contacts == null)
+        {
+            return;
+        }
+
+        if (user.ContactsList == null)
+        {
+            user.ContactsList = new List<string>();
+        }
+
+        foreach (var contact in contacts)
+        {
+            var index = user.ContactsList.IndexOf(contact.Type);
+            if (index != -1)
+            {
+                //Remove existing
+                user.ContactsList.RemoveRange(index, 2);
+            }
+        }
     }
 }
diff --git a/products/ASC.People/Server/Api/GroupController.cs b/products/ASC.People/Server/Api/GroupController.cs
index 4aba8ce6a1..7cef61b93b 100644
--- a/products/ASC.People/Server/Api/GroupController.cs
+++ b/products/ASC.People/Server/Api/GroupController.cs
@@ -5,124 +5,311 @@
 [ApiController]
 public class GroupController : ControllerBase
 {
-    private readonly GroupControllerEngine _groupControllerEngine;
+    private readonly UserManager _userManager;
+    private readonly ApiContext _apiContext;
+    private readonly GroupFullDtoHelper _groupFullDtoHelper;
+    private readonly MessageService _messageService;
+    private readonly MessageTarget _messageTarget;
+    private readonly PermissionContext _permissionContext;
 
-    public GroupController(GroupControllerEngine groupControllerEngine)
+    public GroupController(
+        UserManager userManager,
+        ApiContext apiContext,
+        GroupFullDtoHelper groupFullDtoHelper,
+        MessageService messageService,
+        MessageTarget messageTarget,
+        PermissionContext permissionContext)
     {
-        _groupControllerEngine = groupControllerEngine;
+        _userManager = userManager;
+        _apiContext = apiContext;
+        _groupFullDtoHelper = groupFullDtoHelper;
+        _messageService = messageService;
+        _messageTarget = messageTarget;
+        _permissionContext = permissionContext;
     }
 
     [Read]
     public IEnumerable<GroupSummaryDto> GetAll()
     {
-       return _groupControllerEngine.GetAll();
+        var result = _userManager.GetDepartments().Select(r => r);
+        if (!string.IsNullOrEmpty(_apiContext.FilterValue))
+        {
+            result = result.Where(r => r.Name.Contains(_apiContext.FilterValue, StringComparison.InvariantCultureIgnoreCase));
+        }
+
+        return result.Select(x => new GroupSummaryDto(x, _userManager));
     }
 
     [Read("full")]
     public IEnumerable<GroupDto> GetAllWithMembers()
     {
-        return _groupControllerEngine.GetAllWithMembers();
+        var result = _userManager.GetDepartments().Select(r => r);
+        if (!string.IsNullOrEmpty(_apiContext.FilterValue))
+        {
+            result = result.Where(r => r.Name.Contains(_apiContext.FilterValue, StringComparison.InvariantCultureIgnoreCase));
+        }
+
+        return result.Select(r => _groupFullDtoHelper.Get(r, true));
     }
 
     [Read("{groupid}")]
     public GroupDto GetById(Guid groupid)
     {
-        return _groupControllerEngine.GetById(groupid);
+        return _groupFullDtoHelper.Get(GetGroupInfo(groupid), true);
     }
 
     [Read("user/{userid}")]
     public IEnumerable<GroupSummaryDto> GetByUserId(Guid userid)
     {
-        return _groupControllerEngine.GetByUserId(userid);
+        return _userManager.GetUserGroups(userid).Select(x => new GroupSummaryDto(x, _userManager));
     }
 
     [Create]
-    public GroupDto AddGroupFromBody([FromBody] GroupRequestDto groupModel)
+    public GroupDto AddGroupFromBody([FromBody] GroupRequestDto inDto)
     {
-        return _groupControllerEngine.AddGroup(groupModel);
+        return AddGroup(inDto);
     }
 
     [Create]
     [Consumes("application/x-www-form-urlencoded")]
-    public GroupDto AddGroupFromForm([FromForm] GroupRequestDto groupModel)
+    public GroupDto AddGroupFromForm([FromForm] GroupRequestDto inDto)
     {
-        return _groupControllerEngine.AddGroup(groupModel);
+        return AddGroup(inDto);
     }
 
     [Update("{groupid}")]
-    public GroupDto UpdateGroupFromBody(Guid groupid, [FromBody] GroupRequestDto groupModel)
+    public GroupDto UpdateGroupFromBody(Guid groupid, [FromBody] GroupRequestDto inDto)
     {
-        return _groupControllerEngine.UpdateGroup(groupid, groupModel);
+        return UpdateGroup(groupid, inDto);
     }
 
     [Update("{groupid}")]
     [Consumes("application/x-www-form-urlencoded")]
-    public GroupDto UpdateGroupFromForm(Guid groupid, [FromForm] GroupRequestDto groupModel)
+    public GroupDto UpdateGroupFromForm(Guid groupid, [FromForm] GroupRequestDto inDto)
     {
-        return _groupControllerEngine.UpdateGroup(groupid, groupModel);
+        return UpdateGroup(groupid, inDto);
     }
 
     [Delete("{groupid}")]
     public GroupDto DeleteGroup(Guid groupid)
     {
-        return _groupControllerEngine.DeleteGroup(groupid);
+        _permissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
+
+        var @group = GetGroupInfo(groupid);
+        var groupWrapperFull = _groupFullDtoHelper.Get(group, false);
+
+       _userManager.DeleteGroup(groupid);
+
+       _messageService.Send(MessageAction.GroupDeleted, _messageTarget.Create(group.ID), group.Name);
+
+       return groupWrapperFull;
     }
 
     [Update("{groupid}/members/{newgroupid}")]
     public GroupDto TransferMembersTo(Guid groupid, Guid newgroupid)
     {
-        return _groupControllerEngine.TransferMembersTo(groupid, newgroupid);
+        _permissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
+
+        var oldgroup = GetGroupInfo(groupid);
+
+        var newgroup = GetGroupInfo(newgroupid);
+
+        var users = _userManager.GetUsersByGroup(oldgroup.ID);
+        foreach (var userInfo in users)
+        {
+            TransferUserToDepartment(userInfo.Id, newgroup, false);
+        }
+
+        return GetById(newgroupid);
     }
 
     [Create("{groupid}/members")]
-    public GroupDto SetMembersToFromBody(Guid groupid, [FromBody] GroupRequestDto groupModel)
+    public GroupDto SetMembersToFromBody(Guid groupid, [FromBody] GroupRequestDto inDto)
     {
-        return _groupControllerEngine.SetMembersTo(groupid, groupModel);
+        return SetMembersTo(groupid, inDto);
     }
 
     [Create("{groupid}/members")]
     [Consumes("application/x-www-form-urlencoded")]
-    public GroupDto SetMembersToFromForm(Guid groupid, [FromForm] GroupRequestDto groupModel)
+    public GroupDto SetMembersToFromForm(Guid groupid, [FromForm] GroupRequestDto inDto)
     {
-        return _groupControllerEngine.SetMembersTo(groupid, groupModel);
+        return SetMembersTo(groupid, inDto);
     }
 
     [Update("{groupid}/members")]
-    public GroupDto AddMembersToFromBody(Guid groupid, [FromBody] GroupRequestDto groupModel)
+    public GroupDto AddMembersToFromBody(Guid groupid, [FromBody] GroupRequestDto inDto)
     {
-        return _groupControllerEngine.AddMembersTo(groupid, groupModel);
+        return AddMembersTo(groupid, inDto);
     }
 
     [Update("{groupid}/members")]
     [Consumes("application/x-www-form-urlencoded")]
-    public GroupDto AddMembersToFromForm(Guid groupid, [FromForm] GroupRequestDto groupModel)
+    public GroupDto AddMembersToFromForm(Guid groupid, [FromForm] GroupRequestDto inDto)
     {
-        return _groupControllerEngine.AddMembersTo(groupid, groupModel);
+        return AddMembersTo(groupid, inDto);
     }
 
     [Update("{groupid}/manager")]
-    public GroupDto SetManagerFromBody(Guid groupid, [FromBody] SetManagerRequestDto setManagerModel)
+    public GroupDto SetManagerFromBody(Guid groupid, [FromBody] SetManagerRequestDto inDto)
     {
-        return _groupControllerEngine.SetManager(groupid, setManagerModel);
+        return SetManager(groupid, inDto);
     }
 
     [Update("{groupid}/manager")]
     [Consumes("application/x-www-form-urlencoded")]
-    public GroupDto SetManagerFromForm(Guid groupid, [FromForm] SetManagerRequestDto setManagerModel)
+    public GroupDto SetManagerFromForm(Guid groupid, [FromForm] SetManagerRequestDto inDto)
     {
-        return _groupControllerEngine.SetManager(groupid, setManagerModel);
+        return SetManager(groupid, inDto);
     }
 
     [Delete("{groupid}/members")]
-    public GroupDto RemoveMembersFromFromBody(Guid groupid, [FromBody] GroupRequestDto groupModel)
+    public GroupDto RemoveMembersFromFromBody(Guid groupid, [FromBody] GroupRequestDto inDto)
     {
-        return _groupControllerEngine.RemoveMembersFrom(groupid, groupModel);
+        return RemoveMembersFrom(groupid, inDto);
     }
 
     [Delete("{groupid}/members")]
     [Consumes("application/x-www-form-urlencoded")]
-    public GroupDto RemoveMembersFromFromForm(Guid groupid, [FromForm] GroupRequestDto groupModel)
+    public GroupDto RemoveMembersFromFromForm(Guid groupid, [FromForm] GroupRequestDto inDto)
     {
-        return _groupControllerEngine.RemoveMembersFrom(groupid, groupModel);
+        return RemoveMembersFrom(groupid, inDto);
+    }
+
+    private GroupInfo GetGroupInfo(Guid groupid)
+    {
+        var group = _userManager.GetGroups().SingleOrDefault(x => x.ID == groupid).NotFoundIfNull("group not found");
+        if (group.ID == Constants.LostGroupInfo.ID)
+        {
+            throw new ItemNotFoundException("group not found");
+        }
+
+        return @group;
+    }
+
+    private GroupDto AddGroup(GroupRequestDto inDto)
+    {
+        _permissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
+
+        var group = _userManager.SaveGroupInfo(new GroupInfo { Name = inDto.GroupName });
+
+        TransferUserToDepartment(inDto.GroupManager, @group, true);
+
+        if (inDto.Members != null)
+        {
+            foreach (var member in inDto.Members)
+            {
+                TransferUserToDepartment(member, group, false);
+            }
+        }
+
+        _messageService.Send(MessageAction.GroupCreated, _messageTarget.Create(group.ID), group.Name);
+
+        return _groupFullDtoHelper.Get(group, true);
+    }
+
+    private GroupDto UpdateGroup(Guid groupid, GroupRequestDto inDto)
+    {
+        _permissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
+        var group = _userManager.GetGroups().SingleOrDefault(x => x.ID == groupid).NotFoundIfNull("group not found");
+        if (groupid == Constants.LostGroupInfo.ID)
+        {
+            throw new ItemNotFoundException("group not found");
+        }
+
+        group.Name = inDto.GroupName ?? group.Name;
+        _userManager.SaveGroupInfo(group);
+
+        RemoveMembersFrom(groupid, new GroupRequestDto { Members = _userManager.GetUsersByGroup(groupid, EmployeeStatus.All).Select(u => u.Id).Where(id => !inDto.Members.Contains(id)) });
+
+        TransferUserToDepartment(inDto.GroupManager, @group, true);
+
+        if (inDto.Members != null)
+        {
+            foreach (var member in inDto.Members)
+            {
+                TransferUserToDepartment(member, group, false);
+            }
+        }
+
+        _messageService.Send(MessageAction.GroupUpdated, _messageTarget.Create(groupid), group.Name);
+
+        return GetById(groupid);
+    }
+
+    private void TransferUserToDepartment(Guid userId, GroupInfo group, bool setAsManager)
+    {
+        if (!_userManager.UserExists(userId) && userId != Guid.Empty)
+        {
+            return;
+        }
+
+        if (setAsManager)
+        {
+            _userManager.SetDepartmentManager(@group.ID, userId);
+        }
+        _userManager.AddUserIntoGroup(userId, @group.ID);
+    }
+
+    private GroupDto SetMembersTo(Guid groupid, GroupRequestDto inDto)
+    {
+        RemoveMembersFrom(groupid, new GroupRequestDto { Members = _userManager.GetUsersByGroup(groupid).Select(x => x.Id) });
+        AddMembersTo(groupid, inDto);
+
+        return GetById(groupid);
+    }
+
+    private GroupDto RemoveMembersFrom(Guid groupid, GroupRequestDto inDto)
+    {
+        _permissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
+
+        var group = GetGroupInfo(groupid);
+
+        foreach (var userId in inDto.Members)
+        {
+            RemoveUserFromDepartment(userId, group);
+        }
+
+        return GetById(group.ID);
+    }
+
+    private GroupDto AddMembersTo(Guid groupid, GroupRequestDto inDto)
+    {
+        _permissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
+
+        var group = GetGroupInfo(groupid);
+
+        foreach (var userId in inDto.Members)
+        {
+            TransferUserToDepartment(userId, group, false);
+        }
+
+        return GetById(group.ID);
+    }
+
+    private GroupDto SetManager(Guid groupid, SetManagerRequestDto inDto)
+    {
+        var group = GetGroupInfo(groupid);
+        if (_userManager.UserExists(inDto.UserId))
+        {
+            _userManager.SetDepartmentManager(group.ID, inDto.UserId);
+        }
+        else
+        {
+            throw new ItemNotFoundException("user not found");
+        }
+
+        return GetById(groupid);
+    }
+
+    private void RemoveUserFromDepartment(Guid userId, GroupInfo @group)
+    {
+        if (!_userManager.UserExists(userId))
+        {
+            return;
+        }
+
+        var user = _userManager.GetUsers(userId);
+        _userManager.RemoveUserFromGroup(user.Id, @group.ID);
+        _userManager.SaveUserInfo(user);
     }
 }
diff --git a/products/ASC.People/Server/Api/NotificationController.cs b/products/ASC.People/Server/Api/NotificationController.cs
index 5084317e1f..9caeea3f2f 100644
--- a/products/ASC.People/Server/Api/NotificationController.cs
+++ b/products/ASC.People/Server/Api/NotificationController.cs
@@ -1,24 +1,68 @@
-namespace ASC.People.Api;
+using SecurityContext = ASC.Core.SecurityContext;
+
+namespace ASC.People.Api;
 
 public class NotificationController : ApiControllerBase
 {
-    private readonly NotificationControllerEngine _notificationControllerEngine;
+    private readonly UserManager _userManager;
+    private readonly SecurityContext _securityContext;
+    private readonly AuthContext _authContext;
+    private readonly PermissionContext _permissionContext;
+    private readonly CommonLinkUtility _commonLinkUtility;
+    private readonly StudioNotifyService _studioNotifyService;
 
-    public NotificationController(NotificationControllerEngine notificationControllerEngine)
+    public NotificationController(
+        UserManager userManager,
+        SecurityContext securityContext,
+        AuthContext authContext,
+        PermissionContext permissionContext,
+        CommonLinkUtility commonLinkUtility,
+        StudioNotifyService studioNotifyService)
     {
-        _notificationControllerEngine = notificationControllerEngine;
+        _userManager = userManager;
+        _securityContext = securityContext;
+        _authContext = authContext;
+        _permissionContext = permissionContext;
+        _commonLinkUtility = commonLinkUtility;
+        _studioNotifyService = studioNotifyService;
     }
 
     [Create("phone")]
     public object SendNotificationToChangeFromBody([FromBody] UpdateMemberRequestDto model)
     {
-        return _notificationControllerEngine.SendNotificationToChange(model.UserId);
+        return SendNotificationToChange(model.UserId);
     }
 
     [Create("phone")]
     [Consumes("application/x-www-form-urlencoded")]
     public object SendNotificationToChangeFromForm([FromForm] UpdateMemberRequestDto model)
     {
-        return _notificationControllerEngine.SendNotificationToChange(model.UserId);
+        return SendNotificationToChange(model.UserId);
+    }
+
+    private object SendNotificationToChange(string userId)
+    {
+        var user = _userManager.GetUsers(string.IsNullOrEmpty(userId) 
+            ? _securityContext.CurrentAccount.ID : new Guid(userId));
+
+        var canChange = user.IsMe(_authContext) || _permissionContext.CheckPermissions(new UserSecurityProvider(user.Id), Constants.Action_EditUser);
+
+        if (!canChange)
+        {
+            throw new SecurityAccessDeniedException(Resource.ErrorAccessDenied);
+        }
+
+        user.MobilePhoneActivationStatus = MobilePhoneActivationStatus.NotActivated;
+
+        _userManager.SaveUserInfo(user);
+
+        if (user.IsMe(_authContext))
+        {
+            return _commonLinkUtility.GetConfirmationUrl(user.Email, ConfirmType.PhoneActivation);
+        }
+
+        _studioNotifyService.SendMsgMobilePhoneChange(user);
+
+        return string.Empty;
     }
 }
\ No newline at end of file
diff --git a/products/ASC.People/Server/ApiEngines/PeopleControllerEngine.cs b/products/ASC.People/Server/Api/PeopleControllerBase.cs
similarity index 68%
rename from products/ASC.People/Server/ApiEngines/PeopleControllerEngine.cs
rename to products/ASC.People/Server/Api/PeopleControllerBase.cs
index 530f70bdd6..71ad9a0fa0 100644
--- a/products/ASC.People/Server/ApiEngines/PeopleControllerEngine.cs
+++ b/products/ASC.People/Server/Api/PeopleControllerBase.cs
@@ -1,41 +1,25 @@
-using SecurityContext = ASC.Core.SecurityContext;
+namespace ASC.People.Api;
 
-namespace ASC.People.ApiHelpers;
-
-public abstract class PeopleControllerEngine : ApiControllerEngineBase
+public abstract class PeopleControllerBase : ApiControllerBase
 {
-    protected readonly DisplayUserSettingsHelper _displayUserSettingsHelper;
-    protected readonly SetupInfo _setupInfo;
+    protected readonly UserManager _userManager;
+    protected readonly PermissionContext _permissionContext;
+    protected readonly ApiContext _apiContext;
     protected readonly UserPhotoManager _userPhotoManager;
-    private readonly IHttpClientFactory _httpClientFactory;
+    protected readonly IHttpClientFactory _httpClientFactory;
 
-    protected PeopleControllerEngine(
+    public PeopleControllerBase(
         UserManager userManager,
-        AuthContext authContext,
-        ApiContext apiContext,
         PermissionContext permissionContext,
-        SecurityContext securityContext,
-        MessageService messageService,
-        MessageTarget messageTarget,
-        StudioNotifyService studioNotifyService,
+        ApiContext apiContext,
         UserPhotoManager userPhotoManager,
-        IHttpClientFactory httpClientFactory,
-        DisplayUserSettingsHelper displayUserSettingsHelper,
-        SetupInfo setupInfo)
-        : base(
-            userManager,
-            authContext,
-            apiContext,
-            permissionContext,
-            securityContext,
-            messageService,
-            messageTarget,
-            studioNotifyService)
+        IHttpClientFactory httpClientFactory)
     {
+        _userManager = userManager;
+        _permissionContext = permissionContext;
+        _apiContext = apiContext;
         _userPhotoManager = userPhotoManager;
         _httpClientFactory = httpClientFactory;
-        _displayUserSettingsHelper = displayUserSettingsHelper;
-        _setupInfo = setupInfo;
     }
 
     protected UserInfo GetUserInfo(string userNameOrId)
@@ -85,6 +69,7 @@ public abstract class PeopleControllerEngine : ApiControllerEngineBase
         {
             files = new Uri(_apiContext.HttpContextAccessor.HttpContext.Request.GetDisplayUrl()).GetLeftPart(UriPartial.Authority) + "/" + files.TrimStart('/');
         }
+
         var request = new HttpRequestMessage();
         request.RequestUri = new Uri(files);
 
@@ -93,6 +78,7 @@ public abstract class PeopleControllerEngine : ApiControllerEngineBase
         using var inputStream = response.Content.ReadAsStream();
         using var br = new BinaryReader(inputStream);
         var imageByteArray = br.ReadBytes((int)inputStream.Length);
+
         _userPhotoManager.SaveOrUpdatePhoto(user.Id, imageByteArray);
     }
 }
\ No newline at end of file
diff --git a/products/ASC.People/Server/Api/PhotoController.cs b/products/ASC.People/Server/Api/PhotoController.cs
index 855ea5ddda..3b14c8cc3b 100644
--- a/products/ASC.People/Server/Api/PhotoController.cs
+++ b/products/ASC.People/Server/Api/PhotoController.cs
@@ -1,55 +1,272 @@
-namespace ASC.People.Api;
+using SecurityContext = ASC.Core.SecurityContext;
 
-public class PhotoController : ApiControllerBase
+namespace ASC.People.Api;
+
+public class PhotoController : PeopleControllerBase
 {
-    private readonly PhotoControllerEngine _photoControllerEgine;
+    private readonly MessageService _messageService;
+    private readonly MessageTarget _messageTarget;
+    private readonly DisplayUserSettingsHelper _displayUserSettingsHelper;
+    private readonly SecurityContext _securityContext;
+    private readonly SettingsManager _settingsManager;
+    private readonly FileSizeComment _fileSizeComment;
+    private readonly SetupInfo _setupInfo;
 
-    public PhotoController(PhotoControllerEngine photoControllerEgine)
+    public PhotoController(
+        UserManager userManager,
+        PermissionContext permissionContext,
+        ApiContext apiContext,
+        UserPhotoManager userPhotoManager,
+        MessageService messageService,
+        MessageTarget messageTarget,
+        DisplayUserSettingsHelper displayUserSettingsHelper,
+        SecurityContext securityContext,
+        SettingsManager settingsManager,
+        FileSizeComment fileSizeComment,
+        SetupInfo setupInfo,
+        IHttpClientFactory httpClientFactory) 
+        : base(userManager, permissionContext, apiContext, userPhotoManager, httpClientFactory)
     {
-        _photoControllerEgine = photoControllerEgine;
+        _messageService = messageService;
+        _messageTarget = messageTarget;
+        _displayUserSettingsHelper = displayUserSettingsHelper;
+        _securityContext = securityContext;
+        _settingsManager = settingsManager;
+        _fileSizeComment = fileSizeComment;
+        _setupInfo = setupInfo;
     }
 
     [Create("{userid}/photo/thumbnails")]
     public ThumbnailsDataDto CreateMemberPhotoThumbnailsFromBody(string userid, [FromBody] ThumbnailsRequestDto thumbnailsModel)
     {
-        return _photoControllerEgine.CreateMemberPhotoThumbnails(userid, thumbnailsModel);
+        return CreateMemberPhotoThumbnails(userid, thumbnailsModel);
     }
 
     [Create("{userid}/photo/thumbnails")]
     [Consumes("application/x-www-form-urlencoded")]
     public ThumbnailsDataDto CreateMemberPhotoThumbnailsFromForm(string userid, [FromForm] ThumbnailsRequestDto thumbnailsModel)
     {
-        return _photoControllerEgine.CreateMemberPhotoThumbnails(userid, thumbnailsModel);
+        return CreateMemberPhotoThumbnails(userid, thumbnailsModel);
     }
 
     [Delete("{userid}/photo")]
     public ThumbnailsDataDto DeleteMemberPhoto(string userid)
     {
-        return _photoControllerEgine.DeleteMemberPhoto(userid);
+        var user = GetUserInfo(userid);
+
+        if (_userManager.IsSystemUser(user.Id))
+        {
+            throw new SecurityException();
+        }
+
+        _permissionContext.DemandPermissions(new UserSecurityProvider(user.Id), Constants.Action_EditUser);
+
+        _userPhotoManager.RemovePhoto(user.Id);
+        _userManager.SaveUserInfo(user);
+        _messageService.Send(MessageAction.UserDeletedAvatar, _messageTarget.Create(user.Id), user.DisplayUserName(false, _displayUserSettingsHelper));
+
+        return new ThumbnailsDataDto(user.Id, _userPhotoManager);
     }
 
     [Read("{userid}/photo")]
     public ThumbnailsDataDto GetMemberPhoto(string userid)
     {
-        return _photoControllerEgine.GetMemberPhoto(userid);
+        var user = GetUserInfo(userid);
+
+        if (_userManager.IsSystemUser(user.Id))
+        {
+            throw new SecurityException();
+        }
+
+        return new ThumbnailsDataDto(user.Id, _userPhotoManager);
     }
 
     [Update("{userid}/photo")]
     public ThumbnailsDataDto UpdateMemberPhotoFromBody(string userid, [FromBody] UpdateMemberRequestDto model)
     {
-        return _photoControllerEgine.UpdateMemberPhoto(userid, model);
+        return UpdateMemberPhoto(userid, model);
     }
 
     [Update("{userid}/photo")]
     [Consumes("application/x-www-form-urlencoded")]
     public ThumbnailsDataDto UpdateMemberPhotoFromForm(string userid, [FromForm] UpdateMemberRequestDto model)
     {
-        return _photoControllerEgine.UpdateMemberPhoto(userid, model);
+        return UpdateMemberPhoto(userid, model);
     }
 
     [Create("{userid}/photo")]
     public FileUploadResultDto UploadMemberPhoto(string userid, IFormCollection model)
     {
-        return _photoControllerEgine.UploadMemberPhoto(userid, model);
+        var result = new FileUploadResultDto();
+        var autosave = bool.Parse(model["Autosave"]);
+
+        try
+        {
+            if (model.Files.Count != 0)
+            {
+                Guid userId;
+                try
+                {
+                    userId = new Guid(userid);
+                }
+                catch
+                {
+                    userId = _securityContext.CurrentAccount.ID;
+                }
+
+                _permissionContext.DemandPermissions(new UserSecurityProvider(userId), Constants.Action_EditUser);
+
+                var userPhoto = model.Files[0];
+
+                if (userPhoto.Length > _setupInfo.MaxImageUploadSize)
+                {
+                    result.Success = false;
+                    result.Message = _fileSizeComment.FileImageSizeExceptionString;
+
+                    return result;
+                }
+
+                var data = new byte[userPhoto.Length];
+                using var inputStream = userPhoto.OpenReadStream();
+
+                var br = new BinaryReader(inputStream);
+                br.Read(data, 0, (int)userPhoto.Length);
+                br.Close();
+
+                CheckImgFormat(data);
+
+                if (autosave)
+                {
+                    if (data.Length > _setupInfo.MaxImageUploadSize)
+                    {
+                        throw new ImageSizeLimitException();
+                    }
+
+                    var mainPhoto = _userPhotoManager.SaveOrUpdatePhoto(userId, data);
+
+                    result.Data =
+                        new
+                        {
+                            main = mainPhoto,
+                            retina = _userPhotoManager.GetRetinaPhotoURL(userId),
+                            max = _userPhotoManager.GetMaxPhotoURL(userId),
+                            big = _userPhotoManager.GetBigPhotoURL(userId),
+                            medium = _userPhotoManager.GetMediumPhotoURL(userId),
+                            small = _userPhotoManager.GetSmallPhotoURL(userId),
+                        };
+                }
+                else
+                {
+                    result.Data = _userPhotoManager.SaveTempPhoto(data, _setupInfo.MaxImageUploadSize, UserPhotoManager.OriginalFotoSize.Width, UserPhotoManager.OriginalFotoSize.Height);
+                }
+
+                result.Success = true;
+            }
+            else
+            {
+                result.Success = false;
+                result.Message = PeopleResource.ErrorEmptyUploadFileSelected;
+            }
+
+        }
+        catch (Web.Core.Users.UnknownImageFormatException)
+        {
+            result.Success = false;
+            result.Message = PeopleResource.ErrorUnknownFileImageType;
+        }
+        catch (ImageWeightLimitException)
+        {
+            result.Success = false;
+            result.Message = PeopleResource.ErrorImageWeightLimit;
+        }
+        catch (ImageSizeLimitException)
+        {
+            result.Success = false;
+            result.Message = PeopleResource.ErrorImageSizetLimit;
+        }
+        catch (Exception ex)
+        {
+            result.Success = false;
+            result.Message = ex.Message.HtmlEncode();
+        }
+
+        return result;
+    }
+
+    private ThumbnailsDataDto CreateMemberPhotoThumbnails(string userid, ThumbnailsRequestDto thumbnailsModel)
+    {
+        var user = GetUserInfo(userid);
+
+        if (_userManager.IsSystemUser(user.Id))
+        {
+            throw new SecurityException();
+        }
+
+        _permissionContext.DemandPermissions(new UserSecurityProvider(user.Id), Constants.Action_EditUser);
+
+        if (!string.IsNullOrEmpty(thumbnailsModel.TmpFile))
+        {
+            var fileName = Path.GetFileName(thumbnailsModel.TmpFile);
+            var data = _userPhotoManager.GetTempPhotoData(fileName);
+
+            var settings = new UserPhotoThumbnailSettings(thumbnailsModel.X, thumbnailsModel.Y, thumbnailsModel.Width, thumbnailsModel.Height);
+
+            _settingsManager.SaveForUser(settings, user.Id);
+            _userPhotoManager.RemovePhoto(user.Id);
+            _userPhotoManager.SaveOrUpdatePhoto(user.Id, data);
+            _userPhotoManager.RemoveTempPhoto(fileName);
+        }
+        else
+        {
+            UserPhotoThumbnailManager.SaveThumbnails(_userPhotoManager, _settingsManager, thumbnailsModel.X, thumbnailsModel.Y, thumbnailsModel.Width, thumbnailsModel.Height, user.Id);
+        }
+
+        _userManager.SaveUserInfo(user);
+        _messageService.Send(MessageAction.UserUpdatedAvatarThumbnails, _messageTarget.Create(user.Id), user.DisplayUserName(false, _displayUserSettingsHelper));
+
+        return new ThumbnailsDataDto(user.Id, _userPhotoManager);
+    }
+
+    private ThumbnailsDataDto UpdateMemberPhoto(string userid, UpdateMemberRequestDto model)
+    {
+        var user = GetUserInfo(userid);
+
+        if (_userManager.IsSystemUser(user.Id))
+        {
+            throw new SecurityException();
+        }
+
+        if (model.Files != _userPhotoManager.GetPhotoAbsoluteWebPath(user.Id))
+        {
+            UpdatePhotoUrl(model.Files, user);
+        }
+
+        _userManager.SaveUserInfo(user);
+        _messageService.Send(MessageAction.UserAddedAvatar, _messageTarget.Create(user.Id), user.DisplayUserName(false, _displayUserSettingsHelper));
+
+        return new ThumbnailsDataDto(user.Id, _userPhotoManager);
+    }
+
+    private static void CheckImgFormat(byte[] data)
+    {
+        IImageFormat imgFormat;
+        try
+        {
+            using var img = Image.Load(data, out var format);
+            imgFormat = format;
+        }
+        catch (OutOfMemoryException)
+        {
+            throw new ImageSizeLimitException();
+        }
+        catch (ArgumentException error)
+        {
+            throw new Web.Core.Users.UnknownImageFormatException(error);
+        }
+
+        if (imgFormat.Name != "PNG" && imgFormat.Name != "JPEG")
+        {
+            throw new Web.Core.Users.UnknownImageFormatException();
+        }
     }
 }
diff --git a/products/ASC.People/Server/Api/ReassignController.cs b/products/ASC.People/Server/Api/ReassignController.cs
index 6b9517412e..c3d54ca8bd 100644
--- a/products/ASC.People/Server/Api/ReassignController.cs
+++ b/products/ASC.People/Server/Api/ReassignController.cs
@@ -1,43 +1,103 @@
-namespace ASC.People.Api;
+using SecurityContext = ASC.Core.SecurityContext;
+
+namespace ASC.People.Api;
 
 public class ReassignController : ApiControllerBase
 {
-    private readonly ReassignControllerEngine _reassignControllerEngine;
+    private Tenant Tenant => _apiContext.Tenant;
 
-    public ReassignController(ReassignControllerEngine reassignControllerEngine)
+    private readonly PermissionContext _permissionContext;
+    private readonly QueueWorkerReassign _queueWorkerReassign;
+    private readonly UserManager _userManager;
+    private readonly AuthContext _authContext;
+    private readonly ApiContext _apiContext;
+    private readonly SecurityContext _securityContext;
+
+    public ReassignController(
+        PermissionContext permissionContext,
+        QueueWorkerReassign queueWorkerReassign,
+        UserManager userManager,
+        AuthContext authContext,
+        ApiContext apiContext,
+        SecurityContext securityContext)
     {
-        _reassignControllerEngine = reassignControllerEngine;
+        _permissionContext = permissionContext;
+        _queueWorkerReassign = queueWorkerReassign;
+        _userManager = userManager;
+        _authContext = authContext;
+        _apiContext = apiContext;
+        _securityContext = securityContext;
     }
 
     [Read(@"reassign/progress")]
     public ReassignProgressItem GetReassignProgress(Guid userId)
-    {
-        return _reassignControllerEngine.GetReassignProgress(userId);
+{
+        _permissionContext.DemandPermissions(Constants.Action_EditUser);
+
+        return _queueWorkerReassign.GetProgressItemStatus(Tenant.Id, userId);
     }
 
     [Create(@"reassign/start")]
     public ReassignProgressItem StartReassignFromBody([FromBody] StartReassignRequestDto model)
     {
-        return _reassignControllerEngine.StartReassign(model);
+        return StartReassign(model);
     }
 
     [Create(@"reassign/start")]
     [Consumes("application/x-www-form-urlencoded")]
     public ReassignProgressItem StartReassignFromForm([FromForm] StartReassignRequestDto model)
     {
-        return _reassignControllerEngine.StartReassign(model);
+        return StartReassign(model);
     }
 
     [Update(@"reassign/terminate")]
     public void TerminateReassignFromBody([FromBody] TerminateRequestDto model)
     {
-        _reassignControllerEngine.TerminateReassign(model);
+        TerminateReassign(model);
     }
 
     [Update(@"reassign/terminate")]
     [Consumes("application/x-www-form-urlencoded")]
     public void TerminateReassignFromForm([FromForm] TerminateRequestDto model)
     {
-        _reassignControllerEngine.TerminateReassign(model);
+        TerminateReassign(model);
+    }
+
+    private ReassignProgressItem StartReassign(StartReassignRequestDto model)
+    {
+        _permissionContext.DemandPermissions(Constants.Action_EditUser);
+
+        var fromUser = _userManager.GetUsers(model.FromUserId);
+
+        if (fromUser == null || fromUser.Id == Constants.LostUser.Id)
+        {
+            throw new ArgumentException("User with id = " + model.FromUserId + " not found");
+        }
+
+        if (fromUser.IsOwner(Tenant) || fromUser.IsMe(_authContext) || fromUser.Status != EmployeeStatus.Terminated)
+        {
+            throw new ArgumentException("Can not delete user with id = " + model.FromUserId);
+        }
+
+        var toUser = _userManager.GetUsers(model.ToUserId);
+
+        if (toUser == null || toUser.Id == Constants.LostUser.Id)
+        {
+            throw new ArgumentException("User with id = " + model.ToUserId + " not found");
+        }
+
+        if (toUser.IsVisitor(_userManager) || toUser.Status == EmployeeStatus.Terminated)
+        {
+            throw new ArgumentException("Can not reassign data to user with id = " + model.ToUserId);
+        }
+
+        return _queueWorkerReassign.Start(Tenant.Id, model.FromUserId, model.ToUserId, _securityContext.CurrentAccount.ID, model.DeleteProfile);
+    }
+
+    private void TerminateReassign(TerminateRequestDto model)
+    {
+        _permissionContext.DemandPermissions(Constants.Action_EditUser);
+
+        _queueWorkerReassign.Terminate(Tenant.Id, model.UserId);
     }
 }
diff --git a/products/ASC.People/Server/Api/RemoveUserDataController.cs b/products/ASC.People/Server/Api/RemoveUserDataController.cs
index 3e4e2d4d57..09043f519d 100644
--- a/products/ASC.People/Server/Api/RemoveUserDataController.cs
+++ b/products/ASC.People/Server/Api/RemoveUserDataController.cs
@@ -1,49 +1,113 @@
-namespace ASC.People.Api;
+using SecurityContext = ASC.Core.SecurityContext;
+
+namespace ASC.People.Api;
 
 public class RemoveUserDataController : ApiControllerBase
 {
-    private readonly RemoveUserDataControllerEngine _removeUserDataControllerEngine;
+    private Tenant Tenant => _apiContext.Tenant;
 
-    public RemoveUserDataController(RemoveUserDataControllerEngine removeUserDataControllerEngine)
+    private readonly PermissionContext _permissionContext;
+    private readonly UserManager _userManager;
+    private readonly QueueWorkerRemove _queueWorkerRemove;
+    private readonly SecurityContext _securityContext;
+    private readonly StudioNotifyService _studioNotifyService;
+    private readonly MessageService _messageService;
+    private readonly AuthContext _authContext;
+    private readonly ApiContext _apiContext;
+
+    public RemoveUserDataController(
+        PermissionContext permissionContext,
+        UserManager userManager,
+        QueueWorkerRemove queueWorkerRemove,
+        SecurityContext securityContext,
+        StudioNotifyService studioNotifyService,
+        MessageService messageService,
+        AuthContext authContext,
+        ApiContext apiContext)
     {
-        _removeUserDataControllerEngine = removeUserDataControllerEngine;
+        _permissionContext = permissionContext;
+        _userManager = userManager;
+        _queueWorkerRemove = queueWorkerRemove;
+        _securityContext = securityContext;
+        _studioNotifyService = studioNotifyService;
+        _messageService = messageService;
+        _authContext = authContext;
+        _apiContext = apiContext;
     }
 
     [Read(@"remove/progress")]
     public RemoveProgressItem GetRemoveProgress(Guid userId)
-    {
-       return _removeUserDataControllerEngine.GetRemoveProgress(userId);
+{
+        _permissionContext.DemandPermissions(Constants.Action_EditUser);
+
+        return _queueWorkerRemove.GetProgressItemStatus(Tenant.Id, userId);
     }
 
     [Update("self/delete")]
     public object SendInstructionsToDelete()
     {
-        return _removeUserDataControllerEngine.SendInstructionsToDelete();
+        var user = _userManager.GetUsers(_securityContext.CurrentAccount.ID);
+
+        if (user.IsLDAP())
+        {
+            throw new SecurityException();
+        }
+
+        _studioNotifyService.SendMsgProfileDeletion(user);
+        _messageService.Send(MessageAction.UserSentDeleteInstructions);
+
+        return string.Format(Resource.SuccessfullySentNotificationDeleteUserInfoMessage, "<b>" + user.Email + "</b>");
     }
 
     [Create(@"remove/start")]
     public RemoveProgressItem StartRemoveFromBody([FromBody] TerminateRequestDto model)
     {
-        return _removeUserDataControllerEngine.StartRemove(model);
+        return StartRemove(model);
     }
 
     [Create(@"remove/start")]
     [Consumes("application/x-www-form-urlencoded")]
     public RemoveProgressItem StartRemoveFromForm([FromForm] TerminateRequestDto model)
     {
-        return _removeUserDataControllerEngine.StartRemove(model);
+        return StartRemove(model);
     }
 
     [Update(@"remove/terminate")]
     public void TerminateRemoveFromBody([FromBody] TerminateRequestDto model)
     {
-        _removeUserDataControllerEngine.TerminateRemove(model);
+        TerminateRemove(model);
     }
 
     [Update(@"remove/terminate")]
     [Consumes("application/x-www-form-urlencoded")]
     public void TerminateRemoveFromForm([FromForm] TerminateRequestDto model)
     {
-        _removeUserDataControllerEngine.TerminateRemove(model);
+        TerminateRemove(model);
+    }
+
+    private void TerminateRemove(TerminateRequestDto model)
+    {
+        _permissionContext.DemandPermissions(Constants.Action_EditUser);
+
+        _queueWorkerRemove.Terminate(Tenant.Id, model.UserId);
+    }
+
+    private RemoveProgressItem StartRemove(TerminateRequestDto model)
+    {
+        _permissionContext.DemandPermissions(Constants.Action_EditUser);
+
+        var user = _userManager.GetUsers(model.UserId);
+
+        if (user == null || user.Id == Constants.LostUser.Id)
+        {
+            throw new ArgumentException("User with id = " + model.UserId + " not found");
+        }
+
+        if (user.IsOwner(Tenant) || user.IsMe(_authContext) || user.Status != EmployeeStatus.Terminated)
+        {
+            throw new ArgumentException("Can not delete user with id = " + model.UserId);
+        }
+
+        return _queueWorkerRemove.Start(Tenant.Id, user, _securityContext.CurrentAccount.ID, true);
     }
 }
diff --git a/products/ASC.People/Server/Api/ThirdpartyController.cs b/products/ASC.People/Server/Api/ThirdpartyController.cs
index 1d46ecc432..6bea322486 100644
--- a/products/ASC.People/Server/Api/ThirdpartyController.cs
+++ b/products/ASC.People/Server/Api/ThirdpartyController.cs
@@ -1,39 +1,133 @@
-namespace ASC.People.Api;
+using SecurityContext = ASC.Core.SecurityContext;
+
+namespace ASC.People.Api;
 
 public class ThirdpartyController : ApiControllerBase
 {
-    private readonly ThirdpartyControllerEngine _thirdpartyControllerEngine;
+    private readonly IOptionsSnapshot<AccountLinker> _accountLinker;
+    private readonly CookiesManager _cookiesManager;
+    private readonly CoreBaseSettings _coreBaseSettings;
+    private readonly DisplayUserSettingsHelper _displayUserSettingsHelper;
+    private readonly IHttpClientFactory _httpClientFactory;
+    private readonly InstanceCrypto _instanceCrypto;
+    private readonly MobileDetector _mobileDetector;
+    private readonly PersonalSettingsHelper _personalSettingsHelper;
+    private readonly ProviderManager _providerManager;
+    private readonly Signature _signature;
+    private readonly TenantExtra _tenantExtra;
+    private readonly UserHelpTourHelper _userHelpTourHelper;
+    private readonly UserManagerWrapper _userManagerWrapper;
+    private readonly UserPhotoManager _userPhotoManager;
+    private readonly AuthContext _authContext;
+    private readonly SecurityContext _securityContext;
+    private readonly MessageService _messageService;
+    private readonly UserManager _userManager;
+    private readonly MessageTarget _messageTarget;
+    private readonly StudioNotifyService _studioNotifyService;
 
-    public ThirdpartyController(ThirdpartyControllerEngine thirdpartyControllerEngine)
+    public ThirdpartyController(
+        IOptionsSnapshot<AccountLinker> accountLinker,
+        CookiesManager cookiesManager,
+        CoreBaseSettings coreBaseSettings,
+        DisplayUserSettingsHelper displayUserSettingsHelper,
+        IHttpClientFactory httpClientFactory,
+        InstanceCrypto instanceCrypto,
+        MobileDetector mobileDetector,
+        PersonalSettingsHelper personalSettingsHelper,
+        ProviderManager providerManager,
+        Signature signature,
+        TenantExtra tenantExtra,
+        UserHelpTourHelper userHelpTourHelper,
+        UserManagerWrapper userManagerWrapper,
+        UserPhotoManager userPhotoManager,
+        AuthContext authContext,
+        SecurityContext securityContext,
+        MessageService messageService,
+        UserManager userManager,
+        MessageTarget messageTarget,
+        StudioNotifyService studioNotifyService)
     {
-        _thirdpartyControllerEngine = thirdpartyControllerEngine;
+        _accountLinker = accountLinker;
+        _cookiesManager = cookiesManager;
+        _coreBaseSettings = coreBaseSettings;
+        _displayUserSettingsHelper = displayUserSettingsHelper;
+        _httpClientFactory = httpClientFactory;
+        _instanceCrypto = instanceCrypto;
+        _mobileDetector = mobileDetector;
+        _personalSettingsHelper = personalSettingsHelper;
+        _providerManager = providerManager;
+        _signature = signature;
+        _tenantExtra = tenantExtra;
+        _userHelpTourHelper = userHelpTourHelper;
+        _userManagerWrapper = userManagerWrapper;
+        _userPhotoManager = userPhotoManager;
+        _authContext = authContext;
+        _securityContext = securityContext;
+        _messageService = messageService;
+        _userManager = userManager;
+        _messageTarget = messageTarget;
+        _studioNotifyService = studioNotifyService;
     }
 
     [AllowAnonymous]
     [Read("thirdparty/providers")]
     public ICollection<AccountInfoDto> GetAuthProviders(bool inviteView, bool settingsView, string clientCallback, string fromOnly)
     {
-        return _thirdpartyControllerEngine.GetAuthProviders(inviteView, settingsView, clientCallback, fromOnly, Request);
+        ICollection<AccountInfoDto> infos = new List<AccountInfoDto>();
+        IEnumerable<LoginProfile> linkedAccounts = new List<LoginProfile>();
+
+        if (_authContext.IsAuthenticated)
+        {
+            linkedAccounts = _accountLinker.Get("webstudio").GetLinkedProfiles(_authContext.CurrentAccount.ID.ToString());
+        }
+
+        fromOnly = string.IsNullOrWhiteSpace(fromOnly) ? string.Empty : fromOnly.ToLower();
+
+        foreach (var provider in ProviderManager.AuthProviders.Where(provider => string.IsNullOrEmpty(fromOnly) || fromOnly == provider || (provider == "google" && fromOnly == "openid")))
+        {
+            if (inviteView && provider.Equals("twitter", StringComparison.OrdinalIgnoreCase))
+            {
+                continue;
+            }
+            var loginProvider = _providerManager.GetLoginProvider(provider);
+            if (loginProvider != null && loginProvider.IsEnabled)
+            {
+
+                var url = VirtualPathUtility.ToAbsolute("~/login.ashx") + $"?auth={provider}";
+                var mode = settingsView || inviteView || (!_mobileDetector.IsMobile() && !Request.DesktopApp())
+                        ? $"&mode=popup&callback={clientCallback}"
+                        : "&mode=Redirect&desktop=true";
+
+                infos.Add(new AccountInfoDto
+                {
+                    Linked = linkedAccounts.Any(x => x.Provider == provider),
+                    Provider = provider,
+                    Url = url + mode
+                });
+            }
+        }
+
+        return infos;
     }
 
     [Update("thirdparty/linkaccount")]
     public void LinkAccountFromBody([FromBody] LinkAccountRequestDto model)
     {
-        _thirdpartyControllerEngine.LinkAccount(model);
+        LinkAccount(model);
     }
 
     [Update("thirdparty/linkaccount")]
     [Consumes("application/x-www-form-urlencoded")]
     public void LinkAccountFromForm([FromForm] LinkAccountRequestDto model)
     {
-        _thirdpartyControllerEngine.LinkAccount(model);
+        LinkAccount(model);
     }
 
     [AllowAnonymous]
     [Create("thirdparty/signup")]
     public void SignupAccountFromBody([FromBody] SignupAccountRequestDto model)
     {
-        _thirdpartyControllerEngine.SignupAccount(model);
+        SignupAccount(model);
     }
 
     [AllowAnonymous]
@@ -41,12 +135,230 @@ public class ThirdpartyController : ApiControllerBase
     [Consumes("application/x-www-form-urlencoded")]
     public void SignupAccountFromForm([FromForm] SignupAccountRequestDto model)
     {
-        _thirdpartyControllerEngine.SignupAccount(model);
+        SignupAccount(model);
     }
 
     [Delete("thirdparty/unlinkaccount")]
     public void UnlinkAccount(string provider)
     {
-        _thirdpartyControllerEngine.UnlinkAccount(provider);
+        GetLinker().RemoveProvider(_securityContext.CurrentAccount.ID.ToString(), provider);
+
+        _messageService.Send(MessageAction.UserUnlinkedSocialAccount, GetMeaningfulProviderName(provider));
+    }
+
+    private void LinkAccount(LinkAccountRequestDto model)
+    {
+        var profile = new LoginProfile(_signature, _instanceCrypto, model.SerializedProfile);
+
+        if (!(_coreBaseSettings.Standalone || _tenantExtra.GetTenantQuota().Oauth))
+        {
+            throw new Exception("ErrorNotAllowedOption");
+        }
+
+        if (string.IsNullOrEmpty(profile.AuthorizationError))
+        {
+            GetLinker().AddLink(_securityContext.CurrentAccount.ID.ToString(), profile);
+            _messageService.Send(MessageAction.UserLinkedSocialAccount, GetMeaningfulProviderName(profile.Provider));
+        }
+        else
+        {
+            // ignore cancellation
+            if (profile.AuthorizationError != "Canceled at provider")
+            {
+                throw new Exception(profile.AuthorizationError);
+            }
+        }
+    }
+
+    private void SignupAccount(SignupAccountRequestDto model)
+    {
+        var employeeType = model.EmplType ?? EmployeeType.User;
+        var passwordHash = model.PasswordHash;
+        var mustChangePassword = false;
+        if (string.IsNullOrEmpty(passwordHash))
+        {
+            passwordHash = UserManagerWrapper.GeneratePassword();
+            mustChangePassword = true;
+        }
+
+        var thirdPartyProfile = new LoginProfile(_signature, _instanceCrypto, model.SerializedProfile);
+        if (!string.IsNullOrEmpty(thirdPartyProfile.AuthorizationError))
+        {
+            // ignore cancellation
+            if (thirdPartyProfile.AuthorizationError != "Canceled at provider")
+            {
+                throw new Exception(thirdPartyProfile.AuthorizationError);
+            }
+
+            return;
+        }
+
+        if (string.IsNullOrEmpty(thirdPartyProfile.EMail))
+        {
+            throw new Exception(Resource.ErrorNotCorrectEmail);
+        }
+
+        var userID = Guid.Empty;
+        try
+        {
+            _securityContext.AuthenticateMeWithoutCookie(ASC.Core.Configuration.Constants.CoreSystem);
+            var newUser = CreateNewUser(GetFirstName(model, thirdPartyProfile), GetLastName(model, thirdPartyProfile), GetEmailAddress(model, thirdPartyProfile), passwordHash, employeeType, false);
+            var messageAction = employeeType == EmployeeType.User ? MessageAction.UserCreatedViaInvite : MessageAction.GuestCreatedViaInvite;
+            _messageService.Send(MessageInitiator.System, messageAction, _messageTarget.Create(newUser.Id), newUser.DisplayUserName(false, _displayUserSettingsHelper));
+            userID = newUser.Id;
+            if (!string.IsNullOrEmpty(thirdPartyProfile.Avatar))
+            {
+                SaveContactImage(userID, thirdPartyProfile.Avatar);
+            }
+
+            GetLinker().AddLink(userID.ToString(), thirdPartyProfile);
+        }
+        finally
+        {
+            _securityContext.Logout();
+        }
+
+        var user = _userManager.GetUsers(userID);
+        var cookiesKey = _securityContext.AuthenticateMe(user.Email, passwordHash);
+        _cookiesManager.SetCookies(CookiesType.AuthKey, cookiesKey);
+        _messageService.Send(MessageAction.LoginSuccess);
+        _studioNotifyService.UserHasJoin();
+
+        if (mustChangePassword)
+        {
+            _studioNotifyService.UserPasswordChange(user);
+        }
+
+        _userHelpTourHelper.IsNewUser = true;
+        if (_coreBaseSettings.Personal)
+        {
+            _personalSettingsHelper.IsNewUser = true;
+        }
+    }
+
+    private UserInfo CreateNewUser(string firstName, string lastName, string email, string passwordHash, EmployeeType employeeType, bool fromInviteLink)
+    {
+        var isVisitor = employeeType == EmployeeType.Visitor;
+
+        if (SetupInfo.IsSecretEmail(email))
+        {
+            fromInviteLink = false;
+        }
+
+        var userInfo = new UserInfo
+        {
+            FirstName = string.IsNullOrEmpty(firstName) ? UserControlsCommonResource.UnknownFirstName : firstName,
+            LastName = string.IsNullOrEmpty(lastName) ? UserControlsCommonResource.UnknownLastName : lastName,
+            Email = email,
+        };
+
+        if (_coreBaseSettings.Personal)
+        {
+            userInfo.ActivationStatus = EmployeeActivationStatus.Activated;
+            userInfo.CultureName = _coreBaseSettings.CustomMode ? "ru-RU" : Thread.CurrentThread.CurrentUICulture.Name;
+        }
+
+        return _userManagerWrapper.AddUser(userInfo, passwordHash, true, true, isVisitor, fromInviteLink);
+    }
+
+    private AccountLinker GetLinker()
+    {
+        return _accountLinker.Get("webstudio");
+    }
+
+    private void SaveContactImage(Guid userID, string url)
+    {
+        using (var memstream = new MemoryStream())
+        {
+            var request = new HttpRequestMessage();
+            request.RequestUri = new Uri(url);
+
+            var httpClient = _httpClientFactory.CreateClient();
+            using (var response = httpClient.Send(request))
+            using (var stream = response.Content.ReadAsStream())
+            {
+                var buffer = new byte[512];
+                int bytesRead;
+                while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
+                {
+                    memstream.Write(buffer, 0, bytesRead);
+                }
+
+                var bytes = memstream.ToArray();
+
+                _userPhotoManager.SaveOrUpdatePhoto(userID, bytes);
+            }
+        }
+    }
+
+    private string GetEmailAddress(SignupAccountRequestDto model)
+    {
+        if (!string.IsNullOrEmpty(model.Email))
+        {
+            return model.Email.Trim();
+        }
+
+        return string.Empty;
+    }
+
+    private string GetEmailAddress(SignupAccountRequestDto model, LoginProfile account)
+    {
+        var value = GetEmailAddress(model);
+
+        return string.IsNullOrEmpty(value) ? account.EMail : value;
+    }
+
+    private string GetFirstName(SignupAccountRequestDto model)
+    {
+        var value = string.Empty;
+        if (!string.IsNullOrEmpty(model.FirstName))
+        {
+            value = model.FirstName.Trim();
+        }
+
+        return HtmlUtil.GetText(value);
+    }
+
+    private string GetFirstName(SignupAccountRequestDto model, LoginProfile account)
+    {
+        var value = GetFirstName(model);
+
+        return string.IsNullOrEmpty(value) ? account.FirstName : value;
+    }
+
+    private string GetLastName(SignupAccountRequestDto model)
+    {
+        var value = string.Empty;
+        if (!string.IsNullOrEmpty(model.LastName))
+        {
+            value = model.LastName.Trim();
+        }
+
+        return HtmlUtil.GetText(value);
+    }
+
+    private string GetLastName(SignupAccountRequestDto model, LoginProfile account)
+    {
+        var value = GetLastName(model);
+
+        return string.IsNullOrEmpty(value) ? account.LastName : value;
+    }
+
+    private static string GetMeaningfulProviderName(string providerName)
+    {
+        switch (providerName)
+        {
+            case "google":
+            case "openid":
+                return "Google";
+            case "facebook":
+                return "Facebook";
+            case "twitter":
+                return "Twitter";
+            case "linkedin":
+                return "LinkedIn";
+            default:
+                return "Unknown Provider";
+        }
     }
 }
diff --git a/products/ASC.People/Server/Api/UserController.cs b/products/ASC.People/Server/Api/UserController.cs
index a126b65adb..e8b718c597 100644
--- a/products/ASC.People/Server/Api/UserController.cs
+++ b/products/ASC.People/Server/Api/UserController.cs
@@ -1,34 +1,119 @@
 using Module = ASC.Api.Core.Module;
+using SecurityContext = ASC.Core.SecurityContext;
 
 namespace ASC.People.Api;
 
-public class UserController : ApiControllerBase
+public class UserController : PeopleControllerBase
 {
-    private readonly UserControllerEngine _userControllerEngine;
+    private Tenant Tenant => _apiContext.Tenant;
 
-    public UserController(UserControllerEngine userControllerEngine)
+    private readonly Constants _constants;
+    private readonly CookiesManager _cookiesManager;
+    private readonly CoreBaseSettings _coreBaseSettings;
+    private readonly CustomNamingPeople _customNamingPeople;
+    private readonly EmployeeDtoHelper _employeeDtoHelper;
+    private readonly EmployeeFullDtoHelper _employeeFullDtoHelper;
+    private readonly ILog _logger;
+    private readonly PasswordHasher _passwordHasher;
+    private readonly QueueWorkerReassign _queueWorkerReassign;
+    private readonly QueueWorkerRemove _queueWorkerRemove;
+    private readonly Recaptcha _recaptcha;
+    private readonly TenantExtra _tenantExtra;
+    private readonly TenantStatisticsProvider _tenantStatisticsProvider;
+    private readonly TenantUtil _tenantUtil;
+    private readonly UserFormatter _userFormatter;
+    private readonly UserManagerWrapper _userManagerWrapper;
+    private readonly WebItemManager _webItemManager;
+    private readonly WebItemSecurity _webItemSecurity;
+    private readonly WebItemSecurityCache _webItemSecurityCache;
+    private readonly DisplayUserSettingsHelper _displayUserSettingsHelper;
+    private readonly MessageTarget _messageTarget;
+    private readonly SecurityContext _securityContext;
+    private readonly StudioNotifyService _studioNotifyService;
+    private readonly MessageService _messageService;
+    private readonly AuthContext _authContext;
+    private readonly SetupInfo _setupInfo;
+
+    public UserController(
+        Constants constants,
+        CookiesManager cookiesManager,
+        CoreBaseSettings coreBaseSettings,
+        CustomNamingPeople customNamingPeople,
+        EmployeeDtoHelper employeeDtoHelper,
+        EmployeeFullDtoHelper employeeFullDtoHelper,
+        ILog logger,
+        PasswordHasher passwordHasher,
+        QueueWorkerReassign queueWorkerReassign,
+        QueueWorkerRemove queueWorkerRemove,
+        Recaptcha recaptcha,
+        TenantExtra tenantExtra,
+        TenantStatisticsProvider tenantStatisticsProvider,
+        TenantUtil tenantUtil,
+        UserFormatter userFormatter,
+        UserManagerWrapper userManagerWrapper,
+        WebItemManager webItemManager,
+        WebItemSecurity webItemSecurity,
+        WebItemSecurityCache webItemSecurityCache,
+        DisplayUserSettingsHelper displayUserSettingsHelper,
+        MessageTarget messageTarget,
+        SecurityContext securityContext,
+        StudioNotifyService studioNotifyService,
+        MessageService messageService,
+        AuthContext authContext,
+        SetupInfo setupInfo,
+        UserManager userManager,
+        PermissionContext permissionContext,
+        ApiContext apiContext,
+        UserPhotoManager userPhotoManager,
+        IHttpClientFactory httpClientFactory)
+        : base(userManager, permissionContext, apiContext, userPhotoManager, httpClientFactory)
     {
-        _userControllerEngine = userControllerEngine;
+        _constants = constants;
+        _cookiesManager = cookiesManager;
+        _coreBaseSettings = coreBaseSettings;
+        _customNamingPeople = customNamingPeople;
+        _employeeDtoHelper = employeeDtoHelper;
+        _employeeFullDtoHelper = employeeFullDtoHelper;
+        _logger = logger;
+        _passwordHasher = passwordHasher;
+        _queueWorkerReassign = queueWorkerReassign;
+        _queueWorkerRemove = queueWorkerRemove;
+        _recaptcha = recaptcha;
+        _tenantExtra = tenantExtra;
+        _tenantStatisticsProvider = tenantStatisticsProvider;
+        _tenantUtil = tenantUtil;
+        _userFormatter = userFormatter;
+        _userManagerWrapper = userManagerWrapper;
+        _webItemManager = webItemManager;
+        _webItemSecurity = webItemSecurity;
+        _webItemSecurityCache = webItemSecurityCache;
+        _displayUserSettingsHelper = displayUserSettingsHelper;
+        _messageTarget = messageTarget;
+        _securityContext = securityContext;
+        _studioNotifyService = studioNotifyService;
+        _messageService = messageService;
+        _authContext = authContext;
+        _setupInfo = setupInfo;
     }
 
     [Create("active")]
     public EmployeeDto AddMemberAsActivatedFromBody([FromBody] MemberRequestDto memberModel)
     {
-        return _userControllerEngine.AddMemberAsActivated(memberModel);
+        return AddMemberAsActivated(memberModel);
     }
 
     [Create("active")]
     [Consumes("application/x-www-form-urlencoded")]
     public EmployeeDto AddMemberAsActivatedFromForm([FromForm] MemberRequestDto memberModel)
     {
-        return _userControllerEngine.AddMemberAsActivated(memberModel);
+        return AddMemberAsActivated(memberModel);
     }
 
     [Create]
     [Authorize(AuthenticationSchemes = "confirm", Roles = "LinkInvite,Everyone")]
     public EmployeeDto AddMemberFromBody([FromBody] MemberRequestDto memberModel)
     {
-        return _userControllerEngine.AddMember(memberModel);
+        return AddMember(memberModel);
     }
 
     [Create]
@@ -36,14 +121,14 @@ public class UserController : ApiControllerBase
     [Consumes("application/x-www-form-urlencoded")]
     public EmployeeDto AddMemberFromForm([FromForm] MemberRequestDto memberModel)
     {
-        return _userControllerEngine.AddMember(memberModel);
+        return AddMember(memberModel);
     }
 
     [Update("{userid}/password")]
     [Authorize(AuthenticationSchemes = "confirm", Roles = "PasswordChange,EmailChange,Activation,EmailActivation,Everyone")]
     public EmployeeDto ChangeUserPasswordFromBody(Guid userid, [FromBody] MemberRequestDto memberModel)
     {
-        return _userControllerEngine.ChangeUserPassword(userid, memberModel);
+        return ChangeUserPassword(userid, memberModel);
     }
 
     [Update("{userid}/password")]
@@ -51,26 +136,116 @@ public class UserController : ApiControllerBase
     [Consumes("application/x-www-form-urlencoded")]
     public EmployeeDto ChangeUserPasswordFromForm(Guid userid, [FromForm] MemberRequestDto memberModel)
     {
-        return _userControllerEngine.ChangeUserPassword(userid, memberModel);
+        return ChangeUserPassword(userid, memberModel);
     }
 
     [Delete("{userid}")]
     public EmployeeDto DeleteMember(string userid)
     {
-        return _userControllerEngine.DeleteMember(userid);
+        _permissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
+
+        var user = GetUserInfo(userid);
+
+        if (_userManager.IsSystemUser(user.Id) || user.IsLDAP())
+        {
+            throw new SecurityException();
+        }
+
+        if (user.Status != EmployeeStatus.Terminated)
+        {
+            throw new Exception("The user is not suspended");
+        }
+
+        CheckReassignProccess(new[] { user.Id });
+
+        var userName = user.DisplayUserName(false, _displayUserSettingsHelper);
+        _userPhotoManager.RemovePhoto(user.Id);
+        _userManager.DeleteUser(user.Id);
+        _queueWorkerRemove.Start(Tenant.Id, user, _securityContext.CurrentAccount.ID, false);
+
+        _messageService.Send(MessageAction.UserDeleted, _messageTarget.Create(user.Id), userName);
+
+        return _employeeFullDtoHelper.GetFull(user);
     }
 
     [Delete("@self")]
     [Authorize(AuthenticationSchemes = "confirm", Roles = "ProfileRemove")]
     public EmployeeDto DeleteProfile()
     {
-        return _userControllerEngine.DeleteProfile();
+        _apiContext.AuthByClaim();
+
+        if (_userManager.IsSystemUser(_securityContext.CurrentAccount.ID))
+        {
+            throw new SecurityException();
+        }
+
+        var user = GetUserInfo(_securityContext.CurrentAccount.ID.ToString());
+
+        if (!_userManager.UserExists(user))
+        {
+            throw new Exception(Resource.ErrorUserNotFound);
+        }
+
+        if (user.IsLDAP())
+        {
+            throw new SecurityException();
+        }
+
+        _securityContext.AuthenticateMeWithoutCookie(ASC.Core.Configuration.Constants.CoreSystem);
+        user.Status = EmployeeStatus.Terminated;
+
+        _userManager.SaveUserInfo(user);
+        var userName = user.DisplayUserName(false, _displayUserSettingsHelper);
+        _messageService.Send(MessageAction.UsersUpdatedStatus, _messageTarget.Create(user.Id), userName);
+
+        _cookiesManager.ResetUserCookie(user.Id);
+        _messageService.Send(MessageAction.CookieSettingsUpdated);
+
+        if (_coreBaseSettings.Personal)
+        {
+            _userPhotoManager.RemovePhoto(user.Id);
+            _userManager.DeleteUser(user.Id);
+            _messageService.Send(MessageAction.UserDeleted, _messageTarget.Create(user.Id), userName);
+        }
+        else
+        {
+            //StudioNotifyService.Instance.SendMsgProfileHasDeletedItself(user);
+            //StudioNotifyService.SendMsgProfileDeletion(Tenant.TenantId, user);
+        }
+
+        return _employeeFullDtoHelper.GetFull(user);
     }
 
     [Read("status/{status}/search")]
     public IEnumerable<EmployeeDto> GetAdvanced(EmployeeStatus status, [FromQuery] string query)
     {
-        return _userControllerEngine.GetAdvanced(status, query);
+        if (_coreBaseSettings.Personal)
+        {
+            throw new MethodAccessException("Method not available");
+        }
+        try
+        {
+            var list = _userManager.GetUsers(status).AsEnumerable();
+
+            if ("group".Equals(_apiContext.FilterBy, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(_apiContext.FilterValue))
+            {
+                var groupId = new Guid(_apiContext.FilterValue);
+                //Filter by group
+                list = list.Where(x => _userManager.IsUserInGroup(x.Id, groupId));
+                _apiContext.SetDataFiltered();
+            }
+
+            list = list.Where(x => x.FirstName != null && x.FirstName.IndexOf(query, StringComparison.OrdinalIgnoreCase) > -1 || (x.LastName != null && x.LastName.IndexOf(query, StringComparison.OrdinalIgnoreCase) != -1) ||
+                                   (x.UserName != null && x.UserName.IndexOf(query, StringComparison.OrdinalIgnoreCase) != -1) || (x.Email != null && x.Email.IndexOf(query, StringComparison.OrdinalIgnoreCase) != -1) || (x.ContactsList != null && x.ContactsList.Any(y => y.IndexOf(query, StringComparison.OrdinalIgnoreCase) != -1)));
+
+            return list.Select(u => _employeeFullDtoHelper.GetFull(u));
+        }
+        catch (Exception error)
+        {
+            _logger.Error(error);
+        }
+
+        return null;
     }
 
     [Read]
@@ -82,31 +257,82 @@ public class UserController : ApiControllerBase
     [Read("email")]
     public EmployeeDto GetByEmail([FromQuery] string email)
     {
-        return _userControllerEngine.GetByEmail(email);
+        if (_coreBaseSettings.Personal && !_userManager.GetUsers(_securityContext.CurrentAccount.ID).IsOwner(Tenant))
+        {
+            throw new MethodAccessException("Method not available");
+        }
+
+        var user = _userManager.GetUserByEmail(email);
+        if (user.Id == Constants.LostUser.Id)
+        {
+            throw new ItemNotFoundException("User not found");
+        }
+
+        return _employeeFullDtoHelper.GetFull(user);
     }
 
     [Read("{username}", order: int.MaxValue)]
     public EmployeeDto GetById(string username)
     {
-        return _userControllerEngine.GetById(username);
+        if (_coreBaseSettings.Personal)
+        {
+            throw new MethodAccessException("Method not available");
+}
+
+        var user = _userManager.GetUserByUserName(username);
+        if (user.Id == Constants.LostUser.Id)
+        {
+            if (Guid.TryParse(username, out var userId))
+{
+                user = _userManager.GetUsers(userId);
+            }
+            else
+            {
+                _logger.Error(string.Format("Account {0} сould not get user by name {1}", _securityContext.CurrentAccount.ID, username));
+            }
+        }
+
+        if (user.Id == Constants.LostUser.Id)
+        {
+            throw new ItemNotFoundException("User not found");
+        }
+
+        return _employeeFullDtoHelper.GetFull(user);
     }
 
     [Read("status/{status}")]
     public IEnumerable<EmployeeDto> GetByStatus(EmployeeStatus status)
     {
-        return _userControllerEngine.GetByStatus(status);
+        if (_coreBaseSettings.Personal)
+        {
+            throw new Exception("Method not available");
+        }
+
+        Guid? groupId = null;
+        if ("group".Equals(_apiContext.FilterBy, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(_apiContext.FilterValue))
+        {
+            groupId = new Guid(_apiContext.FilterValue);
+            _apiContext.SetDataFiltered();
+        }
+
+        return GetFullByFilter(status, groupId, null, null, null);
     }
 
     [Read("filter")]
     public IEnumerable<EmployeeDto> GetFullByFilter(EmployeeStatus? employeeStatus, Guid? groupId, EmployeeActivationStatus? activationStatus, EmployeeType? employeeType, bool? isAdministrator)
     {
-        return _userControllerEngine.GetFullByFilter(employeeStatus, groupId, activationStatus, employeeType, isAdministrator);
+        var users = GetByFilter(employeeStatus, groupId, activationStatus, employeeType, isAdministrator);
+
+        return users.Select(r => _employeeFullDtoHelper.GetFull(r));
     }
 
     [Read("info")]
     public Module GetModule()
     {
-        return _userControllerEngine.GetModule();
+        var product = new PeopleProduct();
+        product.Init();
+
+        return new Module(product);
     }
 
     [Read("search")]
@@ -118,72 +344,103 @@ public class UserController : ApiControllerBase
     [Read("@search/{query}")]
     public IEnumerable<EmployeeDto> GetSearch(string query)
     {
-        return _userControllerEngine.GetSearch(query);
+        if (_coreBaseSettings.Personal)
+        {
+            throw new MethodAccessException("Method not available");
+        }
+
+        try
+        {
+            var groupId = Guid.Empty;
+            if ("group".Equals(_apiContext.FilterBy, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(_apiContext.FilterValue))
+            {
+                groupId = new Guid(_apiContext.FilterValue);
+            }
+
+            var users = _userManager.Search(query, EmployeeStatus.Active, groupId);
+
+            return users.Select(u => _employeeFullDtoHelper.GetFull(u));
+        }
+        catch (Exception error)
+        {
+            _logger.Error(error);
+        }
+
+        return null;
     }
 
     [Read("simple/filter")]
     public IEnumerable<EmployeeDto> GetSimpleByFilter(EmployeeStatus? employeeStatus, Guid? groupId, EmployeeActivationStatus? activationStatus, EmployeeType? employeeType, bool? isAdministrator)
     {
-        return _userControllerEngine.GetSimpleByFilter(employeeStatus, groupId, activationStatus, employeeType, isAdministrator);
+        var users = GetByFilter(employeeStatus, groupId, activationStatus, employeeType, isAdministrator);
+
+        return users.Select(_employeeDtoHelper.Get);
     }
 
     [AllowAnonymous]
     [Create(@"register")]
     public Task<string> RegisterUserOnPersonalAsync(RegisterPersonalUserRequestDto model)
     {
-        return _userControllerEngine.RegisterUserOnPersonalAsync(model, Request);
+        if (!_coreBaseSettings.Personal)
+        {
+            throw new MethodAccessException("Method is only available on personal.onlyoffice.com");
+        }
+
+        return InternalRegisterUserOnPersonalAsync(model);
     }
 
     [Update("delete", Order = -1)]
     public IEnumerable<EmployeeDto> RemoveUsersFromBody([FromBody] UpdateMembersRequestDto model)
     {
-        return _userControllerEngine.RemoveUsers(model);
+        return RemoveUsers(model);
     }
 
     [Update("delete", Order = -1)]
     [Consumes("application/x-www-form-urlencoded")]
     public IEnumerable<EmployeeDto> RemoveUsersFromForm([FromForm] UpdateMembersRequestDto model)
     {
-        return _userControllerEngine.RemoveUsers(model);
+        return RemoveUsers(model);
     }
 
     [Update("invite")]
     public IEnumerable<EmployeeDto> ResendUserInvitesFromBody([FromBody] UpdateMembersRequestDto model)
     {
-        return _userControllerEngine.ResendUserInvites(model);
+        return ResendUserInvites(model);
     }
 
     [Update("invite")]
     [Consumes("application/x-www-form-urlencoded")]
     public IEnumerable<EmployeeDto> ResendUserInvitesFromForm([FromForm] UpdateMembersRequestDto model)
     {
-        return _userControllerEngine.ResendUserInvites(model);
+        return ResendUserInvites(model);
     }
 
     [Read("@self")]
     public EmployeeDto Self()
     {
-        return _userControllerEngine.Self();
+        var user = _userManager.GetUser(_securityContext.CurrentAccount.ID, EmployeeFullDtoHelper.GetExpression(_apiContext));
+
+        return _employeeFullDtoHelper.GetFull(user);
     }
 
     [Create("email", false)]
     public object SendEmailChangeInstructionsFromBody([FromBody] UpdateMemberRequestDto model)
     {
-        return _userControllerEngine.SendEmailChangeInstructions(model);
+        return SendEmailChangeInstructions(model);
     }
 
     [Create("email", false)]
     [Consumes("application/x-www-form-urlencoded")]
     public object SendEmailChangeInstructionsFromForm([FromForm] UpdateMemberRequestDto model)
     {
-        return _userControllerEngine.SendEmailChangeInstructions(model);
+        return SendEmailChangeInstructions(model);
     }
 
     [AllowAnonymous]
     [Create("password", false)]
     public object SendUserPasswordFromBody([FromBody] MemberRequestDto memberModel)
     {
-        return _userControllerEngine.SendUserPassword(memberModel);
+        return SendUserPassword(memberModel);
     }
 
     [AllowAnonymous]
@@ -191,14 +448,14 @@ public class UserController : ApiControllerBase
     [Consumes("application/x-www-form-urlencoded")]
     public object SendUserPasswordFromForm([FromForm] MemberRequestDto memberModel)
     {
-        return _userControllerEngine.SendUserPassword(memberModel);
+        return SendUserPassword(memberModel);
     }
 
     [Update("activationstatus/{activationstatus}")]
     [Authorize(AuthenticationSchemes = "confirm", Roles = "Activation,Everyone")]
     public IEnumerable<EmployeeDto> UpdateEmployeeActivationStatusFromBody(EmployeeActivationStatus activationstatus, [FromBody] UpdateMembersRequestDto model)
     {
-        return _userControllerEngine.UpdateEmployeeActivationStatus(activationstatus, model);
+        return UpdateEmployeeActivationStatus(activationstatus, model);
     }
 
     [Update("activationstatus/{activationstatus}")]
@@ -206,60 +463,821 @@ public class UserController : ApiControllerBase
     [Consumes("application/x-www-form-urlencoded")]
     public IEnumerable<EmployeeDto> UpdateEmployeeActivationStatusFromForm(EmployeeActivationStatus activationstatus, [FromForm] UpdateMembersRequestDto model)
     {
-        return _userControllerEngine.UpdateEmployeeActivationStatus(activationstatus, model);
+        return UpdateEmployeeActivationStatus(activationstatus, model);
     }
 
     [Update("{userid}/culture")]
     public EmployeeDto UpdateMemberCultureFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
     {
-        return _userControllerEngine.UpdateMemberCulture(userid, memberModel);
+        return UpdateMemberCulture(userid, memberModel);
     }
 
     [Update("{userid}/culture")]
     [Consumes("application/x-www-form-urlencoded")]
     public EmployeeDto UpdateMemberCultureFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
     {
-        return _userControllerEngine.UpdateMemberCulture(userid, memberModel);
+        return UpdateMemberCulture(userid, memberModel);
     }
 
     [Update("{userid}")]
     public EmployeeDto UpdateMemberFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
     {
-        return _userControllerEngine.UpdateMember(userid, memberModel);
+        return UpdateMember(userid, memberModel);
     }
 
     [Update("{userid}")]
     [Consumes("application/x-www-form-urlencoded")]
     public EmployeeDto UpdateMemberFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
     {
-        return _userControllerEngine.UpdateMember(userid, memberModel);
+        return UpdateMember(userid, memberModel);
     }
 
     [Update("status/{status}")]
     public IEnumerable<EmployeeDto> UpdateUserStatusFromBody(EmployeeStatus status, [FromBody] UpdateMembersRequestDto model)
     {
-        return _userControllerEngine.UpdateUserStatus(status, model);
+        return UpdateUserStatus(status, model);
     }
 
     [Update("status/{status}")]
     [Consumes("application/x-www-form-urlencoded")]
     public IEnumerable<EmployeeDto> UpdateUserStatusFromForm(EmployeeStatus status, [FromForm] UpdateMembersRequestDto model)
     {
-        return _userControllerEngine.UpdateUserStatus(status, model);
+        return UpdateUserStatus(status, model);
     }
 
     [Update("type/{type}")]
     public IEnumerable<EmployeeDto> UpdateUserTypeFromBody(EmployeeType type, [FromBody] UpdateMembersRequestDto model)
     {
-        return _userControllerEngine.UpdateUserType(type, model);
+        return UpdateUserType(type, model);
     }
 
     [Update("type/{type}")]
     [Consumes("application/x-www-form-urlencoded")]
     public IEnumerable<EmployeeDto> UpdateUserTypeFromForm(EmployeeType type, [FromForm] UpdateMembersRequestDto model)
     {
-        return _userControllerEngine.UpdateUserType(type, model);
-    } 
+        return UpdateUserType(type, model);
+    }
+
+    private EmployeeDto AddMemberAsActivated(MemberRequestDto memberModel)
+    {
+        _permissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
+
+        var user = new UserInfo();
+
+        memberModel.PasswordHash = (memberModel.PasswordHash ?? "").Trim();
+        if (string.IsNullOrEmpty(memberModel.PasswordHash))
+        {
+            memberModel.Password = (memberModel.Password ?? "").Trim();
+
+            if (string.IsNullOrEmpty(memberModel.Password))
+            {
+                memberModel.Password = UserManagerWrapper.GeneratePassword();
+            }
+            else
+            {
+                _userManagerWrapper.CheckPasswordPolicy(memberModel.Password);
+            }
+
+            memberModel.PasswordHash = _passwordHasher.GetClientPassword(memberModel.Password);
+        }
+
+        //Validate email
+        var address = new MailAddress(memberModel.Email);
+        user.Email = address.Address;
+        //Set common fields
+        user.FirstName = memberModel.Firstname;
+        user.LastName = memberModel.Lastname;
+        user.Title = memberModel.Title;
+        user.Location = memberModel.Location;
+        user.Notes = memberModel.Comment;
+        user.Sex = "male".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase)
+                       ? true
+                       : ("female".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase) ? (bool?)false : null);
+
+        user.BirthDate = memberModel.Birthday != null ? _tenantUtil.DateTimeFromUtc(memberModel.Birthday) : null;
+        user.WorkFromDate = memberModel.Worksfrom != null ? _tenantUtil.DateTimeFromUtc(memberModel.Worksfrom) : DateTime.UtcNow.Date;
+
+        UpdateContacts(memberModel.Contacts, user);
+
+        user = _userManagerWrapper.AddUser(user, memberModel.PasswordHash, false, false, memberModel.IsVisitor);
+
+        user.ActivationStatus = EmployeeActivationStatus.Activated;
+
+        UpdateDepartments(memberModel.Department, user);
+
+        if (memberModel.Files != _userPhotoManager.GetDefaultPhotoAbsoluteWebPath())
+        {
+            UpdatePhotoUrl(memberModel.Files, user);
+        }
+
+        return _employeeFullDtoHelper.GetFull(user);
+    }
+
+    private void UpdateDepartments(IEnumerable<Guid> department, UserInfo user)
+    {
+        if (!_permissionContext.CheckPermissions(Constants.Action_EditGroups))
+        {
+            return;
+        }
+
+        if (department == null)
+        {
+            return;
+        }
+
+        var groups = _userManager.GetUserGroups(user.Id);
+        var managerGroups = new List<Guid>();
+        foreach (var groupInfo in groups)
+        {
+            _userManager.RemoveUserFromGroup(user.Id, groupInfo.ID);
+            var managerId = _userManager.GetDepartmentManager(groupInfo.ID);
+            if (managerId == user.Id)
+            {
+                managerGroups.Add(groupInfo.ID);
+                _userManager.SetDepartmentManager(groupInfo.ID, Guid.Empty);
+            }
+        }
+        foreach (var guid in department)
+        {
+            var userDepartment = _userManager.GetGroupInfo(guid);
+            if (userDepartment != Constants.LostGroupInfo)
+            {
+                _userManager.AddUserIntoGroup(user.Id, guid);
+                if (managerGroups.Contains(guid))
+                {
+                    _userManager.SetDepartmentManager(guid, user.Id);
+                }
+            }
+        }
+    }
+
+    private void CheckReassignProccess(IEnumerable<Guid> userIds)
+    {
+        foreach (var userId in userIds)
+        {
+            var reassignStatus = _queueWorkerReassign.GetProgressItemStatus(Tenant.Id, userId);
+            if (reassignStatus == null || reassignStatus.IsCompleted)
+            {
+                continue;
+            }
+
+            var userName = _userManager.GetUsers(userId).DisplayUserName(_displayUserSettingsHelper);
+
+            throw new Exception(string.Format(Resource.ReassignDataRemoveUserError, userName));
+        }
+    }
+
+    private async Task<string> InternalRegisterUserOnPersonalAsync(RegisterPersonalUserRequestDto model)
+    {
+        try
+        {
+            if (_coreBaseSettings.CustomMode) model.Lang = "ru-RU";
+
+            var cultureInfo = _setupInfo.GetPersonalCulture(model.Lang).Value;
+
+            if (cultureInfo != null)
+            {
+                Thread.CurrentThread.CurrentUICulture = cultureInfo;
+            }
+
+            model.Email.ThrowIfNull(new ArgumentException(Resource.ErrorEmailEmpty, "email"));
+
+            if (!model.Email.TestEmailRegex()) throw new ArgumentException(Resource.ErrorNotCorrectEmail, "email");
+
+            if (!SetupInfo.IsSecretEmail(model.Email)
+                && !string.IsNullOrEmpty(_setupInfo.RecaptchaPublicKey) && !string.IsNullOrEmpty(_setupInfo.RecaptchaPrivateKey))
+            {
+                var ip = Request.Headers["X-Forwarded-For"].ToString() ?? Request.GetUserHostAddress();
+
+                if (string.IsNullOrEmpty(model.RecaptchaResponse)
+                    || !await _recaptcha.ValidateRecaptchaAsync(model.RecaptchaResponse, ip))
+                {
+                    throw new RecaptchaException(Resource.RecaptchaInvalid);
+                }
+            }
+
+            var newUserInfo = _userManager.GetUserByEmail(model.Email);
+
+            if (_userManager.UserExists(newUserInfo.Id))
+            {
+                if (!SetupInfo.IsSecretEmail(model.Email) || _securityContext.IsAuthenticated)
+                {
+                    _studioNotifyService.SendAlreadyExist(model.Email);
+                    return string.Empty;
+                }
+
+                try
+                {
+                    _securityContext.AuthenticateMe(Core.Configuration.Constants.CoreSystem);
+                    _userManager.DeleteUser(newUserInfo.Id);
+                }
+                finally
+                {
+                    _securityContext.Logout();
+                }
+            }
+            if (!model.Spam)
+            {
+                try
+                {
+                    //TODO
+                    //const string _databaseID = "com";
+                    //using (var db = DbManager.FromHttpContext(_databaseID))
+                    //{
+                    //    db.ExecuteNonQuery(new SqlInsert("template_unsubscribe", false)
+                    //                           .InColumnValue("email", email.ToLowerInvariant())
+                    //                           .InColumnValue("reason", "personal")
+                    //        );
+                    //    Log.Debug(String.Format("Write to template_unsubscribe {0}", email.ToLowerInvariant()));
+                    //}
+                }
+                catch (Exception ex)
+                {
+                    _logger.Debug($"ERROR write to template_unsubscribe {ex.Message}, email:{model.Email.ToLowerInvariant()}");
+                }
+            }
+
+            _studioNotifyService.SendInvitePersonal(model.Email);
+        }
+        catch (Exception ex)
+        {
+            return ex.Message;
+        }
+
+        return string.Empty;
+    }
+
+    public EmployeeDto AddMember(MemberRequestDto memberModel)
+    {
+        _apiContext.AuthByClaim();
+
+        _permissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
+
+        memberModel.PasswordHash = (memberModel.PasswordHash ?? "").Trim();
+        if (string.IsNullOrEmpty(memberModel.PasswordHash))
+        {
+            memberModel.Password = (memberModel.Password ?? "").Trim();
+
+            if (string.IsNullOrEmpty(memberModel.Password))
+            {
+                memberModel.Password = UserManagerWrapper.GeneratePassword();
+            }
+            else
+            {
+                _userManagerWrapper.CheckPasswordPolicy(memberModel.Password);
+            }
+            memberModel.PasswordHash = _passwordHasher.GetClientPassword(memberModel.Password);
+        }
+
+        var user = new UserInfo();
+
+        //Validate email
+        var address = new MailAddress(memberModel.Email);
+        user.Email = address.Address;
+        //Set common fields
+        user.FirstName = memberModel.Firstname;
+        user.LastName = memberModel.Lastname;
+        user.Title = memberModel.Title;
+        user.Location = memberModel.Location;
+        user.Notes = memberModel.Comment;
+        user.Sex = "male".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase)
+                       ? true
+                       : ("female".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase) ? (bool?)false : null);
+
+        user.BirthDate = memberModel.Birthday != null && memberModel.Birthday != DateTime.MinValue ? _tenantUtil.DateTimeFromUtc(memberModel.Birthday) : null;
+        user.WorkFromDate = memberModel.Worksfrom != null && memberModel.Worksfrom != DateTime.MinValue ? _tenantUtil.DateTimeFromUtc(memberModel.Worksfrom) : DateTime.UtcNow.Date;
+
+        UpdateContacts(memberModel.Contacts, user);
+
+        user = _userManagerWrapper.AddUser(user, memberModel.PasswordHash, memberModel.FromInviteLink, true, memberModel.IsVisitor, memberModel.FromInviteLink);
+
+        var messageAction = memberModel.IsVisitor ? MessageAction.GuestCreated : MessageAction.UserCreated;
+        _messageService.Send(messageAction, _messageTarget.Create(user.Id), user.DisplayUserName(false, _displayUserSettingsHelper));
+
+        UpdateDepartments(memberModel.Department, user);
+
+        if (memberModel.Files != _userPhotoManager.GetDefaultPhotoAbsoluteWebPath())
+        {
+            UpdatePhotoUrl(memberModel.Files, user);
+        }
+
+        return _employeeFullDtoHelper.GetFull(user);
+    }
+
+    private EmployeeDto ChangeUserPassword(Guid userid, MemberRequestDto memberModel)
+    {
+        _apiContext.AuthByClaim();
+        _permissionContext.DemandPermissions(new UserSecurityProvider(userid), Constants.Action_EditUser);
+
+        var user = _userManager.GetUsers(userid);
+
+        if (!_userManager.UserExists(user))
+        {
+            return null;
+        }
+
+        if (_userManager.IsSystemUser(user.Id))
+        {
+            throw new SecurityException();
+        }
+
+        if (!string.IsNullOrEmpty(memberModel.Email))
+        {
+            var address = new MailAddress(memberModel.Email);
+            if (!string.Equals(address.Address, user.Email, StringComparison.OrdinalIgnoreCase))
+            {
+                user.Email = address.Address.ToLowerInvariant();
+                user.ActivationStatus = EmployeeActivationStatus.Activated;
+                _userManager.SaveUserInfo(user);
+            }
+        }
+
+        memberModel.PasswordHash = (memberModel.PasswordHash ?? "").Trim();
+
+        if (string.IsNullOrEmpty(memberModel.PasswordHash))
+        {
+            memberModel.Password = (memberModel.Password ?? "").Trim();
+
+            if (!string.IsNullOrEmpty(memberModel.Password))
+            {
+                memberModel.PasswordHash = _passwordHasher.GetClientPassword(memberModel.Password);
+            }
+        }
+
+        if (!string.IsNullOrEmpty(memberModel.PasswordHash))
+        {
+            _securityContext.SetUserPasswordHash(userid, memberModel.PasswordHash);
+            _messageService.Send(MessageAction.UserUpdatedPassword);
+
+            _cookiesManager.ResetUserCookie(userid);
+            _messageService.Send(MessageAction.CookieSettingsUpdated);
+        }
+
+        return _employeeFullDtoHelper.GetFull(GetUserInfo(userid.ToString()));
+    }
+
+    private IQueryable<UserInfo> GetByFilter(EmployeeStatus? employeeStatus, Guid? groupId, EmployeeActivationStatus? activationStatus, EmployeeType? employeeType, bool? isAdministrator)
+    {
+        if (_coreBaseSettings.Personal)
+        {
+            throw new MethodAccessException("Method not available");
+        }
+
+        var isAdmin = _userManager.GetUsers(_securityContext.CurrentAccount.ID).IsAdmin(_userManager) ||
+                      _webItemSecurity.IsProductAdministrator(WebItemManager.PeopleProductID, _securityContext.CurrentAccount.ID);
+
+        var includeGroups = new List<List<Guid>>();
+        if (groupId.HasValue)
+        {
+            includeGroups.Add(new List<Guid> { groupId.Value });
+        }
+
+        var excludeGroups = new List<Guid>();
+
+        if (employeeType != null)
+        {
+            switch (employeeType)
+            {
+                case EmployeeType.User:
+                    excludeGroups.Add(Constants.GroupVisitor.ID);
+                    break;
+                case EmployeeType.Visitor:
+                    includeGroups.Add(new List<Guid> { Constants.GroupVisitor.ID });
+                    break;
+            }
+        }
+
+        if (isAdministrator.HasValue && isAdministrator.Value)
+        {
+            var adminGroups = new List<Guid>
+            {
+                    Constants.GroupAdmin.ID
+            };
+            var products = _webItemManager.GetItemsAll().Where(i => i is IProduct || i.ID == WebItemManager.MailProductID);
+            adminGroups.AddRange(products.Select(r => r.ID));
+
+            includeGroups.Add(adminGroups);
+        }
+
+        var users = _userManager.GetUsers(isAdmin, employeeStatus, includeGroups, excludeGroups, activationStatus, _apiContext.FilterValue, _apiContext.SortBy, !_apiContext.SortDescending, _apiContext.Count, _apiContext.StartIndex, out var total, out var count);
+
+        _apiContext.SetTotalCount(total).SetCount(count);
+
+        return users;
+    }
+
+    public object SendEmailChangeInstructions(UpdateMemberRequestDto model)
+    {
+        Guid.TryParse(model.UserId, out var userid);
+
+        if (userid == Guid.Empty)
+        {
+            throw new ArgumentNullException("userid");
+        }
+
+        var email = (model.Email ?? "").Trim();
+
+        if (string.IsNullOrEmpty(email))
+        {
+            throw new Exception(Resource.ErrorEmailEmpty);
+        }
+
+        if (!email.TestEmailRegex())
+        {
+            throw new Exception(Resource.ErrorNotCorrectEmail);
+        }
+
+        var viewer = _userManager.GetUsers(_securityContext.CurrentAccount.ID);
+        var user = _userManager.GetUsers(userid);
+
+        if (user == null)
+        {
+            throw new Exception(Resource.ErrorUserNotFound);
+        }
+
+        if (viewer == null || (user.IsOwner(Tenant) && viewer.Id != user.Id))
+        {
+            throw new Exception(Resource.ErrorAccessDenied);
+        }
+
+        var existentUser = _userManager.GetUserByEmail(email);
+
+        if (existentUser.Id != Constants.LostUser.Id)
+        {
+            throw new Exception(_customNamingPeople.Substitute<Resource>("ErrorEmailAlreadyExists"));
+        }
+
+        if (!viewer.IsAdmin(_userManager))
+        {
+            _studioNotifyService.SendEmailChangeInstructions(user, email);
+        }
+        else
+        {
+            if (email == user.Email)
+            {
+                throw new Exception(Resource.ErrorEmailsAreTheSame);
+            }
+
+            user.Email = email;
+            user.ActivationStatus = EmployeeActivationStatus.NotActivated;
+            _userManager.SaveUserInfo(user);
+            _studioNotifyService.SendEmailActivationInstructions(user, email);
+        }
+
+        _messageService.Send(MessageAction.UserSentEmailChangeInstructions, user.DisplayUserName(false, _displayUserSettingsHelper));
+
+        return string.Format(Resource.MessageEmailChangeInstuctionsSentOnEmail, email);
+    }
+
+    public IEnumerable<EmployeeDto> RemoveUsers(UpdateMembersRequestDto model)
+    {
+        _permissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
+
+        CheckReassignProccess(model.UserIds);
+
+        var users = model.UserIds.Select(userId => _userManager.GetUsers(userId))
+            .Where(u => !_userManager.IsSystemUser(u.Id) && !u.IsLDAP())
+            .ToList();
+
+        var userNames = users.Select(x => x.DisplayUserName(false, _displayUserSettingsHelper)).ToList();
+
+        foreach (var user in users)
+        {
+            if (user.Status != EmployeeStatus.Terminated)
+            {
+                continue;
+            }
+
+            _userPhotoManager.RemovePhoto(user.Id);
+            _userManager.DeleteUser(user.Id);
+            _queueWorkerRemove.Start(Tenant.Id, user, _securityContext.CurrentAccount.ID, false);
+        }
+
+        _messageService.Send(MessageAction.UsersDeleted, _messageTarget.Create(users.Select(x => x.Id)), userNames);
+
+        return users.Select(u => _employeeFullDtoHelper.GetFull(u));
+    }
+
+    public IEnumerable<EmployeeDto> ResendUserInvites(UpdateMembersRequestDto model)
+    {
+        var users = model.UserIds
+            .Where(userId => !_userManager.IsSystemUser(userId))
+            .Select(userId => _userManager.GetUsers(userId))
+            .ToList();
+
+        foreach (var user in users)
+        {
+            if (user.IsActive)
+            {
+                continue;
+            }
+
+            var viewer = _userManager.GetUsers(_securityContext.CurrentAccount.ID);
+
+            if (viewer == null)
+            {
+                throw new Exception(Resource.ErrorAccessDenied);
+            }
+
+            if (viewer.IsAdmin(_userManager) || viewer.Id == user.Id)
+            {
+                if (user.ActivationStatus == EmployeeActivationStatus.Activated)
+                {
+                    user.ActivationStatus = EmployeeActivationStatus.NotActivated;
+                }
+                if (user.ActivationStatus == (EmployeeActivationStatus.AutoGenerated | EmployeeActivationStatus.Activated))
+                {
+                    user.ActivationStatus = EmployeeActivationStatus.AutoGenerated;
+                }
+
+                _userManager.SaveUserInfo(user);
+            }
+
+            if (user.ActivationStatus == EmployeeActivationStatus.Pending)
+            {
+                if (user.IsVisitor(_userManager))
+                {
+                    _studioNotifyService.GuestInfoActivation(user);
+                }
+                else
+                {
+                    _studioNotifyService.UserInfoActivation(user);
+                }
+            }
+            else
+            {
+                _studioNotifyService.SendEmailActivationInstructions(user, user.Email);
+            }
+        }
+
+        _messageService.Send(MessageAction.UsersSentActivationInstructions, _messageTarget.Create(users.Select(x => x.Id)), users.Select(x => x.DisplayUserName(false, _displayUserSettingsHelper)));
+
+        return users.Select(u => _employeeFullDtoHelper.GetFull(u));
+    }
+
+    public object SendUserPassword(MemberRequestDto memberModel)
+    {
+        string error = _userManagerWrapper.SendUserPassword(memberModel.Email);
+        if (!string.IsNullOrEmpty(error))
+        {
+            _logger.ErrorFormat("Password recovery ({0}): {1}", memberModel.Email, error);
+        }
+
+        return string.Format(Resource.MessageYourPasswordSendedToEmail, memberModel.Email);
+    }
+
+    public IEnumerable<EmployeeDto> UpdateEmployeeActivationStatus(EmployeeActivationStatus activationstatus, UpdateMembersRequestDto model)
+    {
+        _apiContext.AuthByClaim();
+
+        var retuls = new List<EmployeeDto>();
+        foreach (var id in model.UserIds.Where(userId => !_userManager.IsSystemUser(userId)))
+        {
+            _permissionContext.DemandPermissions(new UserSecurityProvider(id), Constants.Action_EditUser);
+            var u = _userManager.GetUsers(id);
+            if (u.Id == Constants.LostUser.Id || u.IsLDAP())
+            {
+                continue;
+            }
+
+            u.ActivationStatus = activationstatus;
+            _userManager.SaveUserInfo(u);
+            retuls.Add(_employeeFullDtoHelper.GetFull(u));
+        }
+
+        return retuls;
+    }
+
+    public EmployeeDto UpdateMemberCulture(string userid, UpdateMemberRequestDto memberModel)
+    {
+        var user = GetUserInfo(userid);
+
+        if (_userManager.IsSystemUser(user.Id))
+        {
+            throw new SecurityException();
+        }
+
+        _permissionContext.DemandPermissions(new UserSecurityProvider(user.Id), Constants.Action_EditUser);
+
+        var curLng = user.CultureName;
+
+        if (_setupInfo.EnabledCultures.Find(c => string.Equals(c.Name, memberModel.CultureName, StringComparison.InvariantCultureIgnoreCase)) != null)
+        {
+            if (curLng != memberModel.CultureName)
+            {
+                user.CultureName = memberModel.CultureName;
+
+                try
+                {
+                    _userManager.SaveUserInfo(user);
+                }
+                catch
+                {
+                    user.CultureName = curLng;
+                    throw;
+                }
+
+                _messageService.Send(MessageAction.UserUpdatedLanguage, _messageTarget.Create(user.Id), user.DisplayUserName(false, _displayUserSettingsHelper));
+
+            }
+        }
+
+        return _employeeFullDtoHelper.GetFull(user);
+    }
+
+    public EmployeeDto UpdateMember(string userid, UpdateMemberRequestDto memberModel)
+    {
+        var user = GetUserInfo(userid);
+
+        if (_userManager.IsSystemUser(user.Id))
+        {
+            throw new SecurityException();
+        }
+
+        _permissionContext.DemandPermissions(new UserSecurityProvider(user.Id), Constants.Action_EditUser);
+        var self = _securityContext.CurrentAccount.ID.Equals(user.Id);
+        var resetDate = new DateTime(1900, 01, 01);
+
+        //Update it
+
+        var isLdap = user.IsLDAP();
+        var isSso = user.IsSSO();
+        var isAdmin = _webItemSecurity.IsProductAdministrator(WebItemManager.PeopleProductID, _securityContext.CurrentAccount.ID);
+
+        if (!isLdap && !isSso)
+        {
+            //Set common fields
+
+            user.FirstName = memberModel.Firstname ?? user.FirstName;
+            user.LastName = memberModel.Lastname ?? user.LastName;
+            user.Location = memberModel.Location ?? user.Location;
+
+            if (isAdmin)
+            {
+                user.Title = memberModel.Title ?? user.Title;
+            }
+        }
+
+        if (!_userFormatter.IsValidUserName(user.FirstName, user.LastName))
+        {
+            throw new Exception(Resource.ErrorIncorrectUserName);
+        }
+
+        user.Notes = memberModel.Comment ?? user.Notes;
+        user.Sex = ("male".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase)
+            ? true
+            : ("female".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase) ? (bool?)false : null)) ?? user.Sex;
+
+        user.BirthDate = memberModel.Birthday != null ? _tenantUtil.DateTimeFromUtc(memberModel.Birthday) : user.BirthDate;
+
+        if (user.BirthDate == resetDate)
+        {
+            user.BirthDate = null;
+        }
+
+        user.WorkFromDate = memberModel.Worksfrom != null ? _tenantUtil.DateTimeFromUtc(memberModel.Worksfrom) : user.WorkFromDate;
+
+        if (user.WorkFromDate == resetDate)
+        {
+            user.WorkFromDate = null;
+        }
+
+        //Update contacts
+        UpdateContacts(memberModel.Contacts, user);
+        UpdateDepartments(memberModel.Department, user);
+
+        if (memberModel.Files != _userPhotoManager.GetPhotoAbsoluteWebPath(user.Id))
+        {
+            UpdatePhotoUrl(memberModel.Files, user);
+        }
+        if (memberModel.Disable.HasValue)
+        {
+            user.Status = memberModel.Disable.Value ? EmployeeStatus.Terminated : EmployeeStatus.Active;
+            user.TerminatedDate = memberModel.Disable.Value ? DateTime.UtcNow : null;
+        }
+        if (self && !isAdmin)
+        {
+            _studioNotifyService.SendMsgToAdminAboutProfileUpdated();
+        }
+
+        // change user type
+        var canBeGuestFlag = !user.IsOwner(Tenant) && !user.IsAdmin(_userManager) && user.GetListAdminModules(_webItemSecurity).Count == 0 && !user.IsMe(_authContext);
+
+        if (memberModel.IsVisitor && !user.IsVisitor(_userManager) && canBeGuestFlag)
+        {
+            _userManager.AddUserIntoGroup(user.Id, Constants.GroupVisitor.ID);
+            _webItemSecurityCache.ClearCache(Tenant.Id);
+        }
+
+        if (!self && !memberModel.IsVisitor && user.IsVisitor(_userManager))
+        {
+            var usersQuota = _tenantExtra.GetTenantQuota().ActiveUsers;
+            if (_tenantStatisticsProvider.GetUsersCount() < usersQuota)
+            {
+                _userManager.RemoveUserFromGroup(user.Id, Constants.GroupVisitor.ID);
+                _webItemSecurityCache.ClearCache(Tenant.Id);
+            }
+            else
+            {
+                throw new TenantQuotaException(string.Format("Exceeds the maximum active users ({0})", usersQuota));
+            }
+        }
+
+        _userManager.SaveUserInfo(user);
+        _messageService.Send(MessageAction.UserUpdated, _messageTarget.Create(user.Id), user.DisplayUserName(false, _displayUserSettingsHelper));
+
+        if (memberModel.Disable.HasValue && memberModel.Disable.Value)
+        {
+            _cookiesManager.ResetUserCookie(user.Id);
+            _messageService.Send(MessageAction.CookieSettingsUpdated);
+        }
+
+        return _employeeFullDtoHelper.GetFull(user);
+    }
+
+    public IEnumerable<EmployeeDto> UpdateUserStatus(EmployeeStatus status, UpdateMembersRequestDto model)
+    {
+        _permissionContext.DemandPermissions(Constants.Action_EditUser);
+
+        var users = model.UserIds.Select(userId => _userManager.GetUsers(userId))
+            .Where(u => !_userManager.IsSystemUser(u.Id) && !u.IsLDAP())
+            .ToList();
+
+        foreach (var user in users)
+        {
+            if (user.IsOwner(Tenant) || user.IsMe(_authContext))
+            {
+                continue;
+            }
+
+            switch (status)
+            {
+                case EmployeeStatus.Active:
+                    if (user.Status == EmployeeStatus.Terminated)
+                    {
+                        if (_tenantStatisticsProvider.GetUsersCount() < _tenantExtra.GetTenantQuota().ActiveUsers || user.IsVisitor(_userManager))
+                        {
+                            user.Status = EmployeeStatus.Active;
+                            _userManager.SaveUserInfo(user);
+                        }
+                    }
+                    break;
+                case EmployeeStatus.Terminated:
+                    user.Status = EmployeeStatus.Terminated;
+                    _userManager.SaveUserInfo(user);
+
+                    _cookiesManager.ResetUserCookie(user.Id);
+                    _messageService.Send(MessageAction.CookieSettingsUpdated);
+                    break;
+            }
+        }
+
+        _messageService.Send(MessageAction.UsersUpdatedStatus, _messageTarget.Create(users.Select(x => x.Id)), users.Select(x => x.DisplayUserName(false, _displayUserSettingsHelper)));
+
+        return users.Select(u => _employeeFullDtoHelper.GetFull(u));
+    }
+
+    public IEnumerable<EmployeeDto> UpdateUserType(EmployeeType type, UpdateMembersRequestDto model)
+    {
+        var users = model.UserIds
+            .Where(userId => !_userManager.IsSystemUser(userId))
+            .Select(userId => _userManager.GetUsers(userId))
+            .ToList();
+
+        foreach (var user in users)
+        {
+            if (user.IsOwner(Tenant) || user.IsAdmin(_userManager)
+                || user.IsMe(_authContext) || user.GetListAdminModules(_webItemSecurity).Count > 0)
+            {
+                continue;
+            }
+
+            switch (type)
+            {
+                case EmployeeType.User:
+                    if (user.IsVisitor(_userManager))
+                    {
+                        if (_tenantStatisticsProvider.GetUsersCount() < _tenantExtra.GetTenantQuota().ActiveUsers)
+                        {
+                            _userManager.RemoveUserFromGroup(user.Id, Constants.GroupVisitor.ID);
+                            _webItemSecurityCache.ClearCache(Tenant.Id);
+                        }
+                    }
+                    break;
+                case EmployeeType.Visitor:
+                    if (_coreBaseSettings.Standalone || _tenantStatisticsProvider.GetVisitorsCount() < _tenantExtra.GetTenantQuota().ActiveUsers * _constants.CoefficientOfVisitors)
+                    {
+                        _userManager.AddUserIntoGroup(user.Id, Constants.GroupVisitor.ID);
+                        _webItemSecurityCache.ClearCache(Tenant.Id);
+                    }
+                    break;
+            }
+        }
+
+        _messageService.Send(MessageAction.UsersUpdatedType, _messageTarget.Create(users.Select(x => x.Id)), users.Select(x => x.DisplayUserName(false, _displayUserSettingsHelper)));
+
+        return users.Select(u => _employeeFullDtoHelper.GetFull(u));
+    }
 
     ///// <summary>
     ///// Adds a new portal user from import with the first and last name, email address
diff --git a/products/ASC.People/Server/ApiEngines/ApiControllerEngineBase.cs b/products/ASC.People/Server/ApiEngines/ApiControllerEngineBase.cs
deleted file mode 100644
index bd21f02d7d..0000000000
--- a/products/ASC.People/Server/ApiEngines/ApiControllerEngineBase.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-using SecurityContext = ASC.Core.SecurityContext;
-
-namespace ASC.People.ApiHelpers;
-
-public abstract class ApiControllerEngineBase
-{
-    protected readonly ApiContext _apiContext;
-    protected readonly AuthContext _authContext;
-    protected readonly MessageService _messageService;
-    protected readonly MessageTarget _messageTarget;
-    protected readonly PermissionContext _permissionContext;
-    protected readonly SecurityContext _securityContext;
-    protected readonly StudioNotifyService _studioNotifyService;
-    protected readonly UserManager _userManager;
-
-    protected ApiControllerEngineBase(
-        UserManager userManager,
-        AuthContext authContext,
-        ApiContext apiContext,
-        PermissionContext permissionContext,
-        SecurityContext securityContext,
-        MessageService messageService,
-        MessageTarget messageTarget,
-        StudioNotifyService studioNotifyService)
-    {
-        _userManager = userManager;
-        _authContext = authContext;
-        _apiContext = apiContext;
-        _permissionContext = permissionContext;
-        _securityContext = securityContext;
-        _messageService = messageService;
-        _messageTarget = messageTarget;
-        _studioNotifyService = studioNotifyService;
-    }
-
-    protected Tenant Tenant => _apiContext.Tenant;
-}
\ No newline at end of file
diff --git a/products/ASC.People/Server/ApiEngines/ContactsControllerEngine.cs b/products/ASC.People/Server/ApiEngines/ContactsControllerEngine.cs
deleted file mode 100644
index 19a09a9e60..0000000000
--- a/products/ASC.People/Server/ApiEngines/ContactsControllerEngine.cs
+++ /dev/null
@@ -1,109 +0,0 @@
-using SecurityContext = ASC.Core.SecurityContext;
-
-namespace ASC.People.ApiHelpers;
-
-public class ContactsControllerEngine : PeopleControllerEngine
-{
-    private readonly EmployeeFullDtoHelper _employeeFullDtoHelper;
-
-    public ContactsControllerEngine(
-        UserManager userManager,
-        AuthContext authContext,
-        ApiContext apiContext,
-        PermissionContext permissionContext,
-        SecurityContext securityContext,
-        MessageService messageService,
-        MessageTarget messageTarget,
-        StudioNotifyService studioNotifyService,
-        UserPhotoManager userPhotoManager,
-        IHttpClientFactory httpClientFactory,
-        DisplayUserSettingsHelper displayUserSettingsHelper,
-        SetupInfo setupInfo,
-        EmployeeFullDtoHelper employeeFullDtoHelper)
-        : base(
-            userManager,
-            authContext,
-            apiContext,
-            permissionContext,
-            securityContext,
-            messageService,
-            messageTarget,
-            studioNotifyService,
-            userPhotoManager,
-            httpClientFactory,
-            displayUserSettingsHelper,
-            setupInfo)
-    {
-        _employeeFullDtoHelper = employeeFullDtoHelper;
-    }
-
-    public void DeleteContacts(IEnumerable<Contact> contacts, UserInfo user)
-    {
-        _permissionContext.DemandPermissions(new UserSecurityProvider(user.Id), Constants.Action_EditUser);
-        if (contacts == null)
-        {
-            return;
-        }
-
-        if (user.ContactsList == null)
-        {
-            user.ContactsList = new List<string>();
-        }
-
-        foreach (var contact in contacts)
-        {
-            var index = user.ContactsList.IndexOf(contact.Type);
-            if (index != -1)
-            {
-                //Remove existing
-                user.ContactsList.RemoveRange(index, 2);
-            }
-        }
-    }
-
-    public EmployeeFullDto DeleteMemberContacts(string userid, UpdateMemberRequestDto memberModel)
-    {
-        var user = GetUserInfo(userid);
-
-        if (_userManager.IsSystemUser(user.Id))
-        {
-            throw new SecurityException();
-        }
-
-        DeleteContacts(memberModel.Contacts, user);
-        _userManager.SaveUserInfo(user);
-
-        return _employeeFullDtoHelper.GetFull(user);
-    }
-
-    public EmployeeFullDto SetMemberContacts(string userid, UpdateMemberRequestDto memberModel)
-    {
-        var user = GetUserInfo(userid);
-
-        if (_userManager.IsSystemUser(user.Id))
-        {
-            throw new SecurityException();
-        }
-
-        user.ContactsList.Clear();
-        UpdateContacts(memberModel.Contacts, user);
-        _userManager.SaveUserInfo(user);
-
-        return _employeeFullDtoHelper.GetFull(user);
-    }
-
-    public EmployeeFullDto UpdateMemberContacts(string userid, UpdateMemberRequestDto memberModel)
-    {
-        var user = GetUserInfo(userid);
-
-        if (_userManager.IsSystemUser(user.Id))
-        {
-            throw new SecurityException();
-        }
-
-        UpdateContacts(memberModel.Contacts, user);
-        _userManager.SaveUserInfo(user);
-
-        return _employeeFullDtoHelper.GetFull(user);
-    }
-}
\ No newline at end of file
diff --git a/products/ASC.People/Server/ApiEngines/GroupControllerEngine.cs b/products/ASC.People/Server/ApiEngines/GroupControllerEngine.cs
deleted file mode 100644
index 597da839aa..0000000000
--- a/products/ASC.People/Server/ApiEngines/GroupControllerEngine.cs
+++ /dev/null
@@ -1,223 +0,0 @@
-namespace ASC.People.ApiHelpers;
-
-[Scope]
-public class GroupControllerEngine
-{
-    private readonly ApiContext _apiContext;
-    private readonly MessageService _messageService;
-    private readonly UserManager _userManager;
-    private readonly PermissionContext _permissionContext;
-    private readonly MessageTarget _messageTarget;
-    private readonly GroupFullDtoHelper _groupWraperFullHelper;
-
-    public GroupControllerEngine(
-        ApiContext apiContext,
-        MessageService messageService,
-        UserManager userManager,
-        PermissionContext permissionContext,
-        MessageTarget messageTarget,
-        GroupFullDtoHelper groupWraperFullHelper)
-    {
-        _apiContext = apiContext;
-        _messageService = messageService;
-        _userManager = userManager;
-        _permissionContext = permissionContext;
-        _messageTarget = messageTarget;
-        _groupWraperFullHelper = groupWraperFullHelper;
-    }
-
-    public IEnumerable<GroupSummaryDto> GetAll()
-    {
-        var result = _userManager.GetDepartments().Select(r => r);
-        if (!string.IsNullOrEmpty(_apiContext.FilterValue))
-        {
-            result = result.Where(r => r.Name.Contains(_apiContext.FilterValue, StringComparison.InvariantCultureIgnoreCase));
-        }
-
-        return result.Select(x => new GroupSummaryDto(x, _userManager));
-    }
-
-    public IEnumerable<GroupDto> GetAllWithMembers()
-    {
-        var result = _userManager.GetDepartments().Select(r => r);
-        if (!string.IsNullOrEmpty(_apiContext.FilterValue))
-        {
-            result = result.Where(r => r.Name.Contains(_apiContext.FilterValue, StringComparison.InvariantCultureIgnoreCase));
-        }
-
-        return result.Select(r => _groupWraperFullHelper.Get(r, true));
-    }
-
-    public GroupDto GetById(Guid groupid)
-    {
-        return _groupWraperFullHelper.Get(GetGroupInfo(groupid), true);
-    }
-
-    public IEnumerable<GroupSummaryDto> GetByUserId(Guid userid)
-    {
-        return _userManager.GetUserGroups(userid).Select(x => new GroupSummaryDto(x, _userManager));
-    }
-
-    public GroupDto AddGroup(GroupRequestDto groupModel)
-    {
-        _permissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
-
-        var group = _userManager.SaveGroupInfo(new GroupInfo { Name = groupModel.GroupName });
-
-        TransferUserToDepartment(groupModel.GroupManager, @group, true);
-        if (groupModel.Members != null)
-        {
-            foreach (var member in groupModel.Members)
-            {
-                TransferUserToDepartment(member, group, false);
-            }
-        }
-
-        _messageService.Send(MessageAction.GroupCreated, _messageTarget.Create(group.ID), group.Name);
-
-        return _groupWraperFullHelper.Get(group, true);
-    }
-
-    public GroupDto UpdateGroup(Guid groupid, GroupRequestDto groupModel)
-    {
-        _permissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
-        var group = _userManager.GetGroups().SingleOrDefault(x => x.ID == groupid).NotFoundIfNull("group not found");
-        if (groupid == Constants.LostGroupInfo.ID)
-        {
-            throw new ItemNotFoundException("group not found");
-        }
-
-        group.Name = groupModel.GroupName ?? group.Name;
-        _userManager.SaveGroupInfo(group);
-
-        RemoveMembersFrom(groupid, new GroupRequestDto { Members = _userManager.GetUsersByGroup(groupid, EmployeeStatus.All).Select(u => u.Id).Where(id => !groupModel.Members.Contains(id)) });
-
-        TransferUserToDepartment(groupModel.GroupManager, @group, true);
-        if (groupModel.Members != null)
-        {
-            foreach (var member in groupModel.Members)
-            {
-                TransferUserToDepartment(member, group, false);
-            }
-        }
-
-        _messageService.Send(MessageAction.GroupUpdated, _messageTarget.Create(groupid), group.Name);
-
-        return GetById(groupid);
-    }
-
-    public GroupDto DeleteGroup(Guid groupid)
-    {
-        _permissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
-        var @group = GetGroupInfo(groupid);
-        var groupWrapperFull = _groupWraperFullHelper.Get(group, false);
-
-        _userManager.DeleteGroup(groupid);
-
-        _messageService.Send(MessageAction.GroupDeleted, _messageTarget.Create(group.ID), group.Name);
-
-        return groupWrapperFull;
-    }
-
-    private GroupInfo GetGroupInfo(Guid groupid)
-    {
-        var group = _userManager.GetGroups().SingleOrDefault(x => x.ID == groupid).NotFoundIfNull("group not found");
-        if (group.ID == Constants.LostGroupInfo.ID)
-        {
-            throw new ItemNotFoundException("group not found");
-        }
-
-        return @group;
-    }
-
-    public GroupDto TransferMembersTo(Guid groupid, Guid newgroupid)
-    {
-        _permissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
-        var oldgroup = GetGroupInfo(groupid);
-
-        var newgroup = GetGroupInfo(newgroupid);
-
-        var users = _userManager.GetUsersByGroup(oldgroup.ID);
-        foreach (var userInfo in users)
-        {
-            TransferUserToDepartment(userInfo.Id, newgroup, false);
-        }
-
-        return GetById(newgroupid);
-    }
-
-    public GroupDto SetMembersTo(Guid groupid, GroupRequestDto groupModel)
-    {
-        RemoveMembersFrom(groupid, new GroupRequestDto { Members = _userManager.GetUsersByGroup(groupid).Select(x => x.Id) });
-        AddMembersTo(groupid, groupModel);
-
-        return GetById(groupid);
-    }
-
-    public GroupDto AddMembersTo(Guid groupid, GroupRequestDto groupModel)
-    {
-        _permissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
-        var group = GetGroupInfo(groupid);
-
-        foreach (var userId in groupModel.Members)
-        {
-            TransferUserToDepartment(userId, group, false);
-        }
-
-        return GetById(group.ID);
-    }
-
-    public GroupDto SetManager(Guid groupid, SetManagerRequestDto setManagerModel)
-    {
-        var group = GetGroupInfo(groupid);
-        if (_userManager.UserExists(setManagerModel.UserId))
-        {
-            _userManager.SetDepartmentManager(group.ID, setManagerModel.UserId);
-        }
-        else
-        {
-            throw new ItemNotFoundException("user not found");
-        }
-
-        return GetById(groupid);
-    }
-
-    public GroupDto RemoveMembersFrom(Guid groupid, GroupRequestDto groupModel)
-    {
-        _permissionContext.DemandPermissions(Constants.Action_EditGroups, Constants.Action_AddRemoveUser);
-        var group = GetGroupInfo(groupid);
-
-        foreach (var userId in groupModel.Members)
-        {
-            RemoveUserFromDepartment(userId, group);
-        }
-
-        return GetById(group.ID);
-    }
-
-    private void RemoveUserFromDepartment(Guid userId, GroupInfo @group)
-    {
-        if (!_userManager.UserExists(userId))
-        {
-            return;
-        }
-
-        var user = _userManager.GetUsers(userId);
-        _userManager.RemoveUserFromGroup(user.Id, @group.ID);
-        _userManager.SaveUserInfo(user);
-    }
-
-    private void TransferUserToDepartment(Guid userId, GroupInfo group, bool setAsManager)
-    {
-        if (!_userManager.UserExists(userId) && userId != Guid.Empty)
-        {
-            return;
-        }
-
-        if (setAsManager)
-        {
-            _userManager.SetDepartmentManager(@group.ID, userId);
-        }
-        _userManager.AddUserIntoGroup(userId, @group.ID);
-    }
-}
\ No newline at end of file
diff --git a/products/ASC.People/Server/ApiEngines/NotificationControllerEngine.cs b/products/ASC.People/Server/ApiEngines/NotificationControllerEngine.cs
deleted file mode 100644
index 1e97263842..0000000000
--- a/products/ASC.People/Server/ApiEngines/NotificationControllerEngine.cs
+++ /dev/null
@@ -1,58 +0,0 @@
-using SecurityContext = ASC.Core.SecurityContext;
-
-namespace ASC.People.ApiHelpers;
-
-public class NotificationControllerEngine : ApiControllerEngineBase
-{
-    private readonly CommonLinkUtility _commonLinkUtility;
-
-    public NotificationControllerEngine(
-        UserManager userManager,
-        AuthContext authContext,
-        ApiContext apiContext,
-        PermissionContext permissionContext,
-        SecurityContext securityContext,
-        MessageService messageService,
-        MessageTarget messageTarget,
-        StudioNotifyService studioNotifyService,
-        CommonLinkUtility commonLinkUtility)
-        : base(
-            userManager,
-            authContext,
-            apiContext,
-            permissionContext,
-            securityContext,
-            messageService,
-            messageTarget,
-            studioNotifyService)
-    {
-        _commonLinkUtility = commonLinkUtility;
-    }
-
-    public object SendNotificationToChange(string userId)
-    {
-        var user = _userManager.GetUsers(
-            string.IsNullOrEmpty(userId)
-                ? _securityContext.CurrentAccount.ID
-                : new Guid(userId));
-        var canChange =
-        user.IsMe(_authContext)
-                    || _permissionContext.CheckPermissions(new UserSecurityProvider(user.Id), Constants.Action_EditUser);
-
-        if (!canChange)
-        {
-            throw new SecurityAccessDeniedException(Resource.ErrorAccessDenied);
-        }
-
-        user.MobilePhoneActivationStatus = MobilePhoneActivationStatus.NotActivated;
-        _userManager.SaveUserInfo(user);
-        if (user.IsMe(_authContext))
-        {
-            return _commonLinkUtility.GetConfirmationUrl(user.Email, ConfirmType.PhoneActivation);
-        }
-
-        _studioNotifyService.SendMsgMobilePhoneChange(user);
-
-        return string.Empty;
-    }
-}
diff --git a/products/ASC.People/Server/ApiEngines/PhotoControllerEngine.cs b/products/ASC.People/Server/ApiEngines/PhotoControllerEngine.cs
deleted file mode 100644
index ed475457ed..0000000000
--- a/products/ASC.People/Server/ApiEngines/PhotoControllerEngine.cs
+++ /dev/null
@@ -1,246 +0,0 @@
-using SecurityContext = ASC.Core.SecurityContext;
-
-namespace ASC.People.ApiHelpers;
-
-public class PhotoControllerEngine : PeopleControllerEngine
-{
-    private readonly FileSizeComment _fileSizeComment;
-    private readonly SettingsManager _settingsManager;
-
-    public PhotoControllerEngine(
-        UserManager userManager,
-        AuthContext authContext,
-        ApiContext apiContext,
-        PermissionContext permissionContext,
-        SecurityContext securityContext,
-        MessageService messageService,
-        MessageTarget messageTarget,
-        StudioNotifyService studioNotifyService,
-        FileSizeComment fileSizeComment,
-        SettingsManager settingsManager,
-        UserPhotoManager userPhotoManager,
-        IHttpClientFactory httpClientFactory,
-        DisplayUserSettingsHelper displayUserSettingsHelper,
-        SetupInfo setupInfo)
-        : base(
-            userManager,
-            authContext,
-            apiContext,
-            permissionContext,
-            securityContext,
-            messageService,
-            messageTarget,
-            studioNotifyService,
-            userPhotoManager,
-            httpClientFactory,
-            displayUserSettingsHelper,
-            setupInfo)
-    {
-        _fileSizeComment = fileSizeComment;
-        _settingsManager = settingsManager;
-    }
-
-    public ThumbnailsDataDto CreateMemberPhotoThumbnails(string userid, ThumbnailsRequestDto thumbnailsModel)
-    {
-        var user = GetUserInfo(userid);
-
-        if (_userManager.IsSystemUser(user.Id))
-        {
-            throw new SecurityException();
-        }
-
-        _permissionContext.DemandPermissions(new UserSecurityProvider(user.Id), Constants.Action_EditUser);
-
-        if (!string.IsNullOrEmpty(thumbnailsModel.TmpFile))
-        {
-            var fileName = Path.GetFileName(thumbnailsModel.TmpFile);
-            var data = _userPhotoManager.GetTempPhotoData(fileName);
-
-            var settings = new UserPhotoThumbnailSettings(thumbnailsModel.X, thumbnailsModel.Y, thumbnailsModel.Width, thumbnailsModel.Height);
-            _settingsManager.SaveForUser(settings, user.Id);
-            _userPhotoManager.RemovePhoto(user.Id);
-            _userPhotoManager.SaveOrUpdatePhoto(user.Id, data);
-            _userPhotoManager.RemoveTempPhoto(fileName);
-        }
-        else
-        {
-            UserPhotoThumbnailManager.SaveThumbnails(_userPhotoManager, _settingsManager, thumbnailsModel.X, thumbnailsModel.Y, thumbnailsModel.Width, thumbnailsModel.Height, user.Id);
-        }
-
-        _userManager.SaveUserInfo(user);
-        _messageService.Send(MessageAction.UserUpdatedAvatarThumbnails, _messageTarget.Create(user.Id), user.DisplayUserName(false, _displayUserSettingsHelper));
-
-        return new ThumbnailsDataDto(user.Id, _userPhotoManager);
-    }
-
-    public ThumbnailsDataDto DeleteMemberPhoto(string userid)
-    {
-        var user = GetUserInfo(userid);
-
-        if (_userManager.IsSystemUser(user.Id))
-        {
-            throw new SecurityException();
-        }
-
-        _permissionContext.DemandPermissions(new UserSecurityProvider(user.Id), Constants.Action_EditUser);
-
-        _userPhotoManager.RemovePhoto(user.Id);
-        _userManager.SaveUserInfo(user);
-        _messageService.Send(MessageAction.UserDeletedAvatar, _messageTarget.Create(user.Id), user.DisplayUserName(false, _displayUserSettingsHelper));
-
-        return new ThumbnailsDataDto(user.Id, _userPhotoManager);
-    }
-
-    public ThumbnailsDataDto GetMemberPhoto(string userid)
-    {
-        var user = GetUserInfo(userid);
-
-        if (_userManager.IsSystemUser(user.Id))
-        {
-            throw new SecurityException();
-        }
-
-        return new ThumbnailsDataDto(user.Id, _userPhotoManager);
-    }
-
-    public ThumbnailsDataDto UpdateMemberPhoto(string userid, UpdateMemberRequestDto model)
-    {
-        var user = GetUserInfo(userid);
-
-        if (_userManager.IsSystemUser(user.Id))
-        {
-            throw new SecurityException();
-        }
-
-        if (model.Files != _userPhotoManager.GetPhotoAbsoluteWebPath(user.Id))
-        {
-            UpdatePhotoUrl(model.Files, user);
-        }
-
-        _userManager.SaveUserInfo(user);
-        _messageService.Send(MessageAction.UserAddedAvatar, _messageTarget.Create(user.Id), user.DisplayUserName(false, _displayUserSettingsHelper));
-
-        return new ThumbnailsDataDto(user.Id, _userPhotoManager);
-    }
-
-    public FileUploadResultDto UploadMemberPhoto(string userid, IFormCollection model)
-    {
-        var result = new FileUploadResultDto();
-        var autosave = bool.Parse(model["Autosave"]);
-
-        try
-        {
-            if (model.Files.Count != 0)
-            {
-                Guid userId;
-                try
-                {
-                    userId = new Guid(userid);
-                }
-                catch
-                {
-                    userId = _securityContext.CurrentAccount.ID;
-                }
-
-                _permissionContext.DemandPermissions(new UserSecurityProvider(userId), Constants.Action_EditUser);
-
-                var userPhoto = model.Files[0];
-
-                if (userPhoto.Length > _setupInfo.MaxImageUploadSize)
-                {
-                    result.Success = false;
-                    result.Message = _fileSizeComment.FileImageSizeExceptionString;
-
-                    return result;
-                }
-
-                var data = new byte[userPhoto.Length];
-                using var inputStream = userPhoto.OpenReadStream();
-
-                var br = new BinaryReader(inputStream);
-                br.Read(data, 0, (int)userPhoto.Length);
-                br.Close();
-
-                CheckImgFormat(data);
-
-                if (autosave)
-                {
-                    if (data.Length > _setupInfo.MaxImageUploadSize)
-                    {
-                        throw new ImageSizeLimitException();
-                    }
-
-                    var mainPhoto = _userPhotoManager.SaveOrUpdatePhoto(userId, data);
-
-                    result.Data =
-                        new
-                        {
-                            main = mainPhoto,
-                            retina = _userPhotoManager.GetRetinaPhotoURL(userId),
-                            max = _userPhotoManager.GetMaxPhotoURL(userId),
-                            big = _userPhotoManager.GetBigPhotoURL(userId),
-                            medium = _userPhotoManager.GetMediumPhotoURL(userId),
-                            small = _userPhotoManager.GetSmallPhotoURL(userId),
-                        };
-                }
-                else
-                {
-                    result.Data = _userPhotoManager.SaveTempPhoto(data, _setupInfo.MaxImageUploadSize, UserPhotoManager.OriginalFotoSize.Width, UserPhotoManager.OriginalFotoSize.Height);
-                }
-
-                result.Success = true;
-            }
-            else
-            {
-                result.Success = false;
-                result.Message = PeopleResource.ErrorEmptyUploadFileSelected;
-            }
-
-        }
-        catch (Web.Core.Users.UnknownImageFormatException)
-        {
-            result.Success = false;
-            result.Message = PeopleResource.ErrorUnknownFileImageType;
-        }
-        catch (ImageWeightLimitException)
-        {
-            result.Success = false;
-            result.Message = PeopleResource.ErrorImageWeightLimit;
-        }
-        catch (ImageSizeLimitException)
-        {
-            result.Success = false;
-            result.Message = PeopleResource.ErrorImageSizetLimit;
-        }
-        catch (Exception ex)
-        {
-            result.Success = false;
-            result.Message = ex.Message.HtmlEncode();
-        }
-
-        return result;
-    }
-
-    private static void CheckImgFormat(byte[] data)
-    {
-        IImageFormat imgFormat;
-        try
-        {
-            using var img = Image.Load(data, out var format);
-            imgFormat = format;
-        }
-        catch (OutOfMemoryException)
-        {
-            throw new ImageSizeLimitException();
-        }
-        catch (ArgumentException error)
-        {
-            throw new Web.Core.Users.UnknownImageFormatException(error);
-        }
-
-        if (imgFormat.Name != "PNG" && imgFormat.Name != "JPEG")
-        {
-            throw new Web.Core.Users.UnknownImageFormatException();
-        }
-    }
-}
diff --git a/products/ASC.People/Server/ApiEngines/ReassignControllerEngine.cs b/products/ASC.People/Server/ApiEngines/ReassignControllerEngine.cs
deleted file mode 100644
index 90e9f241dd..0000000000
--- a/products/ASC.People/Server/ApiEngines/ReassignControllerEngine.cs
+++ /dev/null
@@ -1,76 +0,0 @@
-using SecurityContext = ASC.Core.SecurityContext;
-
-namespace ASC.People.ApiHelpers;
-
-public class ReassignControllerEngine : ApiControllerEngineBase
-{
-    private readonly QueueWorkerReassign _queueWorkerReassign;
-
-    public ReassignControllerEngine(
-        UserManager userManager,
-        AuthContext authContext,
-        ApiContext apiContext,
-        PermissionContext permissionContext,
-        SecurityContext securityContext,
-        MessageService messageService,
-        MessageTarget messageTarget,
-        StudioNotifyService studioNotifyService,
-        QueueWorkerReassign queueWorkerReassign)
-        : base(
-            userManager,
-            authContext,
-            apiContext,
-            permissionContext,
-            securityContext,
-            messageService,
-            messageTarget,
-            studioNotifyService)
-    {
-        _queueWorkerReassign = queueWorkerReassign;
-    }
-
-    public ReassignProgressItem GetReassignProgress(Guid userId)
-    {
-        _permissionContext.DemandPermissions(Constants.Action_EditUser);
-
-        return _queueWorkerReassign.GetProgressItemStatus(Tenant.Id, userId);
-    }
-
-    public void TerminateReassign(TerminateRequestDto model)
-    {
-        _permissionContext.DemandPermissions(Constants.Action_EditUser);
-
-        _queueWorkerReassign.Terminate(Tenant.Id, model.UserId);
-    }
-
-    public ReassignProgressItem StartReassign(StartReassignRequestDto model)
-    {
-        _permissionContext.DemandPermissions(Constants.Action_EditUser);
-
-        var fromUser = _userManager.GetUsers(model.FromUserId);
-
-        if (fromUser == null || fromUser.Id == Constants.LostUser.Id)
-        {
-            throw new ArgumentException("User with id = " + model.FromUserId + " not found");
-        }
-
-        if (fromUser.IsOwner(Tenant) || fromUser.IsMe(_authContext) || fromUser.Status != EmployeeStatus.Terminated)
-        {
-            throw new ArgumentException("Can not delete user with id = " + model.FromUserId);
-        }
-
-        var toUser = _userManager.GetUsers(model.ToUserId);
-
-        if (toUser == null || toUser.Id == Constants.LostUser.Id)
-        {
-            throw new ArgumentException("User with id = " + model.ToUserId + " not found");
-        }
-
-        if (toUser.IsVisitor(_userManager) || toUser.Status == EmployeeStatus.Terminated)
-        {
-            throw new ArgumentException("Can not reassign data to user with id = " + model.ToUserId);
-        }
-
-        return _queueWorkerReassign.Start(Tenant.Id, model.FromUserId, model.ToUserId, _securityContext.CurrentAccount.ID, model.DeleteProfile);
-    }
-}
diff --git a/products/ASC.People/Server/ApiEngines/RemoveUserDataControllerEngine.cs b/products/ASC.People/Server/ApiEngines/RemoveUserDataControllerEngine.cs
deleted file mode 100644
index 85f578a54b..0000000000
--- a/products/ASC.People/Server/ApiEngines/RemoveUserDataControllerEngine.cs
+++ /dev/null
@@ -1,78 +0,0 @@
-using SecurityContext = ASC.Core.SecurityContext;
-
-namespace ASC.People.ApiHelpers;
-
-public class RemoveUserDataControllerEngine : ApiControllerEngineBase
-{
-    private readonly QueueWorkerRemove _queueWorkerRemove;
-
-    public RemoveUserDataControllerEngine(
-        UserManager userManager,
-        AuthContext authContext,
-        ApiContext apiContext,
-        PermissionContext permissionContext,
-        SecurityContext securityContext,
-        MessageService messageService,
-        MessageTarget messageTarget,
-        StudioNotifyService studioNotifyService,
-        QueueWorkerRemove queueWorkerRemove)
-        : base(userManager,
-               authContext,
-               apiContext,
-               permissionContext,
-               securityContext,
-               messageService,
-               messageTarget,
-               studioNotifyService)
-    {
-        _queueWorkerRemove = queueWorkerRemove;
-    }
-
-    public RemoveProgressItem GetRemoveProgress(Guid userId)
-    {
-        _permissionContext.DemandPermissions(Constants.Action_EditUser);
-
-        return _queueWorkerRemove.GetProgressItemStatus(Tenant.Id, userId);
-    }
-
-    public object SendInstructionsToDelete()
-    {
-        var user = _userManager.GetUsers(_securityContext.CurrentAccount.ID);
-
-        if (user.IsLDAP())
-        {
-            throw new SecurityException();
-        }
-
-        _studioNotifyService.SendMsgProfileDeletion(user);
-        _messageService.Send(MessageAction.UserSentDeleteInstructions);
-
-        return string.Format(Resource.SuccessfullySentNotificationDeleteUserInfoMessage, "<b>" + user.Email + "</b>");
-    }
-
-    public void TerminateRemove(TerminateRequestDto model)
-    {
-        _permissionContext.DemandPermissions(Constants.Action_EditUser);
-
-        _queueWorkerRemove.Terminate(Tenant.Id, model.UserId);
-    }
-
-    public RemoveProgressItem StartRemove(TerminateRequestDto model)
-    {
-        _permissionContext.DemandPermissions(Constants.Action_EditUser);
-
-        var user = _userManager.GetUsers(model.UserId);
-
-        if (user == null || user.Id == Constants.LostUser.Id)
-        {
-            throw new ArgumentException("User with id = " + model.UserId + " not found");
-        }
-
-        if (user.IsOwner(Tenant) || user.IsMe(_authContext) || user.Status != EmployeeStatus.Terminated)
-        {
-            throw new ArgumentException("Can not delete user with id = " + model.UserId);
-        }
-
-        return _queueWorkerRemove.Start(Tenant.Id, user, _securityContext.CurrentAccount.ID, true);
-    }
-}
diff --git a/products/ASC.People/Server/ApiEngines/ThirdpartyControllerEngine.cs b/products/ASC.People/Server/ApiEngines/ThirdpartyControllerEngine.cs
deleted file mode 100644
index 8ba0a3ed92..0000000000
--- a/products/ASC.People/Server/ApiEngines/ThirdpartyControllerEngine.cs
+++ /dev/null
@@ -1,331 +0,0 @@
-using SecurityContext = ASC.Core.SecurityContext;
-
-namespace ASC.People.ApiHelpers;
-
-public class ThirdpartyControllerEngine : ApiControllerEngineBase
-{
-    private readonly IOptionsSnapshot<AccountLinker> _accountLinker;
-    private readonly CookiesManager _cookiesManager;
-    private readonly CoreBaseSettings _coreBaseSettings;
-    private readonly DisplayUserSettingsHelper _displayUserSettingsHelper;
-    private readonly IHttpClientFactory _httpClientFactory;
-    private readonly InstanceCrypto _instanceCrypto;
-    private readonly MobileDetector _mobileDetector;
-    private readonly PersonalSettingsHelper _personalSettingsHelper;
-    private readonly ProviderManager _providerManager;
-    private readonly Signature _signature;
-    private readonly TenantExtra _tenantExtra;
-    private readonly UserHelpTourHelper _userHelpTourHelper;
-    private readonly UserManagerWrapper _userManagerWrapper;
-    private readonly UserPhotoManager _userPhotoManager;
-
-    public ThirdpartyControllerEngine(
-        UserManager userManager,
-        AuthContext authContext,
-        ApiContext apiContext,
-        PermissionContext permissionContext,
-        SecurityContext securityContext,
-        MessageService messageService,
-        MessageTarget messageTarget,
-        StudioNotifyService studioNotifyService,
-        IOptionsSnapshot<AccountLinker> optionsSnapshot,
-        CookiesManager cookiesManager,
-        CoreBaseSettings coreBaseSettings,
-        DisplayUserSettingsHelper displayUserSettingsHelper,
-        IHttpClientFactory httpClientFactory,
-        InstanceCrypto instanceCrypto,
-        MobileDetector mobileDetector,
-        PersonalSettingsHelper personalSettingsHelper,
-        ProviderManager providerManager,
-        Signature signature,
-        TenantExtra tenantExtra,
-        UserHelpTourHelper userHelpTourHelper,
-        UserManagerWrapper userManagerWrapper,
-        UserPhotoManager userPhotoManager
-        )
-        : base(
-            userManager,
-            authContext,
-            apiContext,
-            permissionContext,
-            securityContext,
-            messageService,
-            messageTarget,
-            studioNotifyService)
-    {
-        _accountLinker = optionsSnapshot;
-        _cookiesManager = cookiesManager;
-        _coreBaseSettings = coreBaseSettings;
-        _displayUserSettingsHelper = displayUserSettingsHelper;
-        _httpClientFactory = httpClientFactory;
-        _instanceCrypto = instanceCrypto;
-        _mobileDetector = mobileDetector;
-        _personalSettingsHelper = personalSettingsHelper;
-        _providerManager = providerManager;
-        _signature = signature;
-        _tenantExtra = tenantExtra;
-        _userHelpTourHelper = userHelpTourHelper;
-        _userManagerWrapper = userManagerWrapper;
-        _userPhotoManager = userPhotoManager;
-    }
-
-    public ICollection<AccountInfoDto> GetAuthProviders(bool inviteView, bool settingsView, string clientCallback, string fromOnly, HttpRequest request)
-    {
-        ICollection<AccountInfoDto> infos = new List<AccountInfoDto>();
-        IEnumerable<LoginProfile> linkedAccounts = new List<LoginProfile>();
-
-        if (_authContext.IsAuthenticated)
-        {
-            linkedAccounts = _accountLinker.Get("webstudio").GetLinkedProfiles(_authContext.CurrentAccount.ID.ToString());
-        }
-
-        fromOnly = string.IsNullOrWhiteSpace(fromOnly) ? string.Empty : fromOnly.ToLower();
-
-        foreach (var provider in ProviderManager.AuthProviders.Where(provider => string.IsNullOrEmpty(fromOnly) || fromOnly == provider || (provider == "google" && fromOnly == "openid")))
-        {
-            if (inviteView && provider.Equals("twitter", StringComparison.OrdinalIgnoreCase))
-            {
-                continue;
-            }
-            var loginProvider = _providerManager.GetLoginProvider(provider);
-            if (loginProvider != null && loginProvider.IsEnabled)
-            {
-
-                var url = VirtualPathUtility.ToAbsolute("~/login.ashx") + $"?auth={provider}";
-                var mode = settingsView || inviteView || (!_mobileDetector.IsMobile() && !request.DesktopApp())
-                        ? $"&mode=popup&callback={clientCallback}"
-                        : "&mode=Redirect&desktop=true";
-
-                infos.Add(new AccountInfoDto
-                {
-                    Linked = linkedAccounts.Any(x => x.Provider == provider),
-                    Provider = provider,
-                    Url = url + mode
-                });
-            }
-        }
-
-        return infos;
-    }
-
-    public void LinkAccount(LinkAccountRequestDto model)
-    {
-        var profile = new LoginProfile(_signature, _instanceCrypto, model.SerializedProfile);
-
-        if (!(_coreBaseSettings.Standalone || _tenantExtra.GetTenantQuota().Oauth))
-        {
-            throw new Exception("ErrorNotAllowedOption");
-        }
-
-        if (string.IsNullOrEmpty(profile.AuthorizationError))
-        {
-            GetLinker().AddLink(_securityContext.CurrentAccount.ID.ToString(), profile);
-            _messageService.Send(MessageAction.UserLinkedSocialAccount, GetMeaningfulProviderName(profile.Provider));
-        }
-        else
-        {
-            // ignore cancellation
-            if (profile.AuthorizationError != "Canceled at provider")
-            {
-                throw new Exception(profile.AuthorizationError);
-            }
-        }
-    }
-
-    public void SignupAccount(SignupAccountRequestDto model)
-    {
-        var employeeType = model.EmplType ?? EmployeeType.User;
-        var passwordHash = model.PasswordHash;
-        var mustChangePassword = false;
-        if (string.IsNullOrEmpty(passwordHash))
-        {
-            passwordHash = UserManagerWrapper.GeneratePassword();
-            mustChangePassword = true;
-        }
-
-        var thirdPartyProfile = new LoginProfile(_signature, _instanceCrypto, model.SerializedProfile);
-        if (!string.IsNullOrEmpty(thirdPartyProfile.AuthorizationError))
-        {
-            // ignore cancellation
-            if (thirdPartyProfile.AuthorizationError != "Canceled at provider")
-            {
-                throw new Exception(thirdPartyProfile.AuthorizationError);
-            }
-
-            return;
-        }
-
-        if (string.IsNullOrEmpty(thirdPartyProfile.EMail))
-        {
-            throw new Exception(Resource.ErrorNotCorrectEmail);
-        }
-
-        var userID = Guid.Empty;
-        try
-        {
-            _securityContext.AuthenticateMeWithoutCookie(ASC.Core.Configuration.Constants.CoreSystem);
-            var newUser = CreateNewUser(GetFirstName(model, thirdPartyProfile), GetLastName(model, thirdPartyProfile), GetEmailAddress(model, thirdPartyProfile), passwordHash, employeeType, false);
-            var messageAction = employeeType == EmployeeType.User ? MessageAction.UserCreatedViaInvite : MessageAction.GuestCreatedViaInvite;
-            _messageService.Send(MessageInitiator.System, messageAction, _messageTarget.Create(newUser.Id), newUser.DisplayUserName(false, _displayUserSettingsHelper));
-            userID = newUser.Id;
-            if (!string.IsNullOrEmpty(thirdPartyProfile.Avatar))
-            {
-                SaveContactImage(userID, thirdPartyProfile.Avatar);
-            }
-
-            GetLinker().AddLink(userID.ToString(), thirdPartyProfile);
-        }
-        finally
-        {
-            _securityContext.Logout();
-        }
-
-        var user = _userManager.GetUsers(userID);
-        var cookiesKey = _securityContext.AuthenticateMe(user.Email, passwordHash);
-        _cookiesManager.SetCookies(CookiesType.AuthKey, cookiesKey);
-        _messageService.Send(MessageAction.LoginSuccess);
-        _studioNotifyService.UserHasJoin();
-
-        if (mustChangePassword)
-        {
-            _studioNotifyService.UserPasswordChange(user);
-        }
-
-        _userHelpTourHelper.IsNewUser = true;
-        if (_coreBaseSettings.Personal)
-        {
-            _personalSettingsHelper.IsNewUser = true;
-        }
-    }
-
-    public void UnlinkAccount(string provider)
-    {
-        GetLinker().RemoveProvider(_securityContext.CurrentAccount.ID.ToString(), provider);
-        _messageService.Send(MessageAction.UserUnlinkedSocialAccount, GetMeaningfulProviderName(provider));
-    }
-
-    private static string GetMeaningfulProviderName(string providerName)
-    {
-        switch (providerName)
-        {
-            case "google":
-            case "openid":
-                return "Google";
-            case "facebook":
-                return "Facebook";
-            case "twitter":
-                return "Twitter";
-            case "linkedin":
-                return "LinkedIn";
-            default:
-                return "Unknown Provider";
-        }
-    }
-
-    private UserInfo CreateNewUser(string firstName, string lastName, string email, string passwordHash, EmployeeType employeeType, bool fromInviteLink)
-    {
-        var isVisitor = employeeType == EmployeeType.Visitor;
-
-        if (SetupInfo.IsSecretEmail(email))
-        {
-            fromInviteLink = false;
-        }
-
-        var userInfo = new UserInfo
-        {
-            FirstName = string.IsNullOrEmpty(firstName) ? UserControlsCommonResource.UnknownFirstName : firstName,
-            LastName = string.IsNullOrEmpty(lastName) ? UserControlsCommonResource.UnknownLastName : lastName,
-            Email = email,
-        };
-
-        if (_coreBaseSettings.Personal)
-        {
-            userInfo.ActivationStatus = EmployeeActivationStatus.Activated;
-            userInfo.CultureName = _coreBaseSettings.CustomMode ? "ru-RU" : Thread.CurrentThread.CurrentUICulture.Name;
-        }
-
-        return _userManagerWrapper.AddUser(userInfo, passwordHash, true, true, isVisitor, fromInviteLink);
-    }
-
-    private string GetEmailAddress(SignupAccountRequestDto model)
-    {
-        if (!string.IsNullOrEmpty(model.Email))
-        {
-            return model.Email.Trim();
-        }
-
-        return string.Empty;
-    }
-
-    private string GetEmailAddress(SignupAccountRequestDto model, LoginProfile account)
-    {
-        var value = GetEmailAddress(model);
-
-        return string.IsNullOrEmpty(value) ? account.EMail : value;
-    }
-
-    private string GetFirstName(SignupAccountRequestDto model)
-    {
-        var value = string.Empty;
-        if (!string.IsNullOrEmpty(model.FirstName))
-        {
-            value = model.FirstName.Trim();
-        }
-
-        return HtmlUtil.GetText(value);
-    }
-
-    private string GetFirstName(SignupAccountRequestDto model, LoginProfile account)
-    {
-        var value = GetFirstName(model);
-
-        return string.IsNullOrEmpty(value) ? account.FirstName : value;
-    }
-
-    private string GetLastName(SignupAccountRequestDto model)
-    {
-        var value = string.Empty;
-        if (!string.IsNullOrEmpty(model.LastName))
-        {
-            value = model.LastName.Trim();
-        }
-
-        return HtmlUtil.GetText(value);
-    }
-
-    private string GetLastName(SignupAccountRequestDto model, LoginProfile account)
-    {
-        var value = GetLastName(model);
-
-        return string.IsNullOrEmpty(value) ? account.LastName : value;
-    }
-
-    private AccountLinker GetLinker()
-    {
-        return _accountLinker.Get("webstudio");
-    }
-    private void SaveContactImage(Guid userID, string url)
-    {
-        using (var memstream = new MemoryStream())
-        {
-            var request = new HttpRequestMessage();
-            request.RequestUri = new Uri(url);
-
-            var httpClient = _httpClientFactory.CreateClient();
-            using (var response = httpClient.Send(request))
-            using (var stream = response.Content.ReadAsStream())
-            {
-                var buffer = new byte[512];
-                int bytesRead;
-                while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
-                {
-                    memstream.Write(buffer, 0, bytesRead);
-                }
-
-                var bytes = memstream.ToArray();
-
-                _userPhotoManager.SaveOrUpdatePhoto(userID, bytes);
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/products/ASC.People/Server/ApiEngines/UserControllerEngine.cs b/products/ASC.People/Server/ApiEngines/UserControllerEngine.cs
deleted file mode 100644
index 71d27ba6be..0000000000
--- a/products/ASC.People/Server/ApiEngines/UserControllerEngine.cs
+++ /dev/null
@@ -1,1087 +0,0 @@
-using Module = ASC.Api.Core.Module;
-using SecurityContext = ASC.Core.SecurityContext;
-
-namespace ASC.People.ApiHelpers;
-
-[Scope]
-public class UserControllerEngine : PeopleControllerEngine
-{
-    private readonly Constants _constants;
-    private readonly CookiesManager _cookiesManager;
-    private readonly CoreBaseSettings _coreBaseSettings;
-    private readonly CustomNamingPeople _customNamingPeople;
-    private readonly EmployeeDtoHelper _employeeDtoHelper;
-    private readonly EmployeeFullDtoHelper _employeeFullDtoHelper;
-    private readonly ILog _logger;
-    private readonly PasswordHasher _passwordHasher;
-    private readonly QueueWorkerReassign _queueWorkerReassign;
-    private readonly QueueWorkerRemove _queueWorkerRemove;
-    private readonly Recaptcha _recaptcha;
-    private readonly TenantExtra _tenantExtra;
-    private readonly TenantStatisticsProvider _tenantStatisticsProvider;
-    private readonly TenantUtil _tenantUtil;
-    private readonly UserFormatter _userFormatter;
-    private readonly UserManagerWrapper _userManagerWrapper;
-    private readonly WebItemManager _webItemManager;
-    private readonly WebItemSecurity _webItemSecurity;
-    private readonly WebItemSecurityCache _webItemSecurityCache;
-
-    public UserControllerEngine(
-        UserManager userManager,
-        AuthContext authContext,
-        ApiContext apiContext,
-        PermissionContext permissionContext,
-        SecurityContext securityContext,
-        MessageService messageService,
-        MessageTarget messageTarget,
-        StudioNotifyService studioNotifyService,
-        Constants constants,
-        CookiesManager cookiesManager,
-        CoreBaseSettings coreBaseSettings,
-        CustomNamingPeople customNamingPeople,
-        ILog logger,
-        PasswordHasher passwordHasher,
-        QueueWorkerReassign queueWorkerReassign,
-        QueueWorkerRemove queueWorkerRemove,
-        Recaptcha recaptcha,
-        TenantExtra tenantExtra,
-        TenantStatisticsProvider tenantStatisticsProvider,
-        TenantUtil tenantUtil,
-        UserFormatter userFormatter,
-        UserManagerWrapper userManagerWrapper,
-        WebItemManager webItemManager,
-        WebItemSecurity webItemSecurity,
-        WebItemSecurityCache webItemSecurityCache,
-        UserPhotoManager userPhotoManager,
-        IHttpClientFactory httpClientFactory,
-        DisplayUserSettingsHelper displayUserSettingsHelper,
-        SetupInfo setupInfo,
-        EmployeeFullDtoHelper employeeFullDtoHelper,
-        EmployeeDtoHelper employeeDtoHelper)
-        : base(
-            userManager,
-            authContext,
-            apiContext,
-            permissionContext,
-            securityContext,
-            messageService,
-            messageTarget,
-            studioNotifyService,
-            userPhotoManager,
-            httpClientFactory,
-            displayUserSettingsHelper,
-            setupInfo)
-    {
-        _constants = constants;
-        _cookiesManager = cookiesManager;
-        _coreBaseSettings = coreBaseSettings;
-        _customNamingPeople = customNamingPeople;
-        _logger = logger;
-        _passwordHasher = passwordHasher;
-        _queueWorkerReassign = queueWorkerReassign;
-        _queueWorkerRemove = queueWorkerRemove;
-        _recaptcha = recaptcha;
-        _tenantExtra = tenantExtra;
-        _tenantStatisticsProvider = tenantStatisticsProvider;
-        _tenantUtil = tenantUtil;
-        _userFormatter = userFormatter;
-        _userManagerWrapper = userManagerWrapper;
-        _webItemManager = webItemManager;
-        _webItemSecurity = webItemSecurity;
-        _webItemSecurityCache = webItemSecurityCache;
-        _employeeDtoHelper = employeeDtoHelper;
-        _employeeFullDtoHelper = employeeFullDtoHelper;
-    }
-
-    public EmployeeDto AddMember(MemberRequestDto memberModel)
-    {
-        _apiContext.AuthByClaim();
-
-        _permissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
-
-        memberModel.PasswordHash = (memberModel.PasswordHash ?? "").Trim();
-        if (string.IsNullOrEmpty(memberModel.PasswordHash))
-        {
-            memberModel.Password = (memberModel.Password ?? "").Trim();
-
-            if (string.IsNullOrEmpty(memberModel.Password))
-            {
-                memberModel.Password = UserManagerWrapper.GeneratePassword();
-            }
-            else
-            {
-                _userManagerWrapper.CheckPasswordPolicy(memberModel.Password);
-            }
-            memberModel.PasswordHash = _passwordHasher.GetClientPassword(memberModel.Password);
-        }
-
-        var user = new UserInfo();
-
-        //Validate email
-        var address = new MailAddress(memberModel.Email);
-        user.Email = address.Address;
-        //Set common fields
-        user.FirstName = memberModel.Firstname;
-        user.LastName = memberModel.Lastname;
-        user.Title = memberModel.Title;
-        user.Location = memberModel.Location;
-        user.Notes = memberModel.Comment;
-        user.Sex = "male".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase)
-                       ? true
-                       : ("female".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase) ? (bool?)false : null);
-
-        user.BirthDate = memberModel.Birthday != null && memberModel.Birthday != DateTime.MinValue ? _tenantUtil.DateTimeFromUtc(memberModel.Birthday) : null;
-        user.WorkFromDate = memberModel.Worksfrom != null && memberModel.Worksfrom != DateTime.MinValue ? _tenantUtil.DateTimeFromUtc(memberModel.Worksfrom) : DateTime.UtcNow.Date;
-
-        UpdateContacts(memberModel.Contacts, user);
-
-        user = _userManagerWrapper.AddUser(user, memberModel.PasswordHash, memberModel.FromInviteLink, true, memberModel.IsVisitor, memberModel.FromInviteLink);
-
-        var messageAction = memberModel.IsVisitor ? MessageAction.GuestCreated : MessageAction.UserCreated;
-        _messageService.Send(messageAction, _messageTarget.Create(user.Id), user.DisplayUserName(false, _displayUserSettingsHelper));
-
-        UpdateDepartments(memberModel.Department, user);
-
-        if (memberModel.Files != _userPhotoManager.GetDefaultPhotoAbsoluteWebPath())
-        {
-            UpdatePhotoUrl(memberModel.Files, user);
-        }
-
-        return _employeeFullDtoHelper.GetFull(user);
-    }
-
-    public EmployeeDto AddMemberAsActivated(MemberRequestDto memberModel)
-    {
-        _permissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
-
-        var user = new UserInfo();
-
-        memberModel.PasswordHash = (memberModel.PasswordHash ?? "").Trim();
-        if (string.IsNullOrEmpty(memberModel.PasswordHash))
-        {
-            memberModel.Password = (memberModel.Password ?? "").Trim();
-
-            if (string.IsNullOrEmpty(memberModel.Password))
-            {
-                memberModel.Password = UserManagerWrapper.GeneratePassword();
-            }
-            else
-            {
-                _userManagerWrapper.CheckPasswordPolicy(memberModel.Password);
-            }
-
-            memberModel.PasswordHash = _passwordHasher.GetClientPassword(memberModel.Password);
-        }
-
-        //Validate email
-        var address = new MailAddress(memberModel.Email);
-        user.Email = address.Address;
-        //Set common fields
-        user.FirstName = memberModel.Firstname;
-        user.LastName = memberModel.Lastname;
-        user.Title = memberModel.Title;
-        user.Location = memberModel.Location;
-        user.Notes = memberModel.Comment;
-        user.Sex = "male".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase)
-                       ? true
-                       : ("female".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase) ? (bool?)false : null);
-
-        user.BirthDate = memberModel.Birthday != null ? _tenantUtil.DateTimeFromUtc(memberModel.Birthday) : null;
-        user.WorkFromDate = memberModel.Worksfrom != null ? _tenantUtil.DateTimeFromUtc(memberModel.Worksfrom) : DateTime.UtcNow.Date;
-
-        UpdateContacts(memberModel.Contacts, user);
-
-        user = _userManagerWrapper.AddUser(user, memberModel.PasswordHash, false, false, memberModel.IsVisitor);
-
-        user.ActivationStatus = EmployeeActivationStatus.Activated;
-
-        UpdateDepartments(memberModel.Department, user);
-
-        if (memberModel.Files != _userPhotoManager.GetDefaultPhotoAbsoluteWebPath())
-        {
-            UpdatePhotoUrl(memberModel.Files, user);
-        }
-
-        return _employeeFullDtoHelper.GetFull(user);
-    }
-
-    public EmployeeDto ChangeUserPassword(Guid userid, MemberRequestDto memberModel)
-    {
-        _apiContext.AuthByClaim();
-        _permissionContext.DemandPermissions(new UserSecurityProvider(userid), Constants.Action_EditUser);
-
-        var user = _userManager.GetUsers(userid);
-
-        if (!_userManager.UserExists(user))
-        {
-            return null;
-        }
-
-        if (_userManager.IsSystemUser(user.Id))
-        {
-            throw new SecurityException();
-        }
-
-        if (!string.IsNullOrEmpty(memberModel.Email))
-        {
-            var address = new MailAddress(memberModel.Email);
-            if (!string.Equals(address.Address, user.Email, StringComparison.OrdinalIgnoreCase))
-            {
-                user.Email = address.Address.ToLowerInvariant();
-                user.ActivationStatus = EmployeeActivationStatus.Activated;
-                _userManager.SaveUserInfo(user);
-            }
-        }
-
-        memberModel.PasswordHash = (memberModel.PasswordHash ?? "").Trim();
-        if (string.IsNullOrEmpty(memberModel.PasswordHash))
-        {
-            memberModel.Password = (memberModel.Password ?? "").Trim();
-
-            if (!string.IsNullOrEmpty(memberModel.Password))
-            {
-                memberModel.PasswordHash = _passwordHasher.GetClientPassword(memberModel.Password);
-            }
-        }
-
-        if (!string.IsNullOrEmpty(memberModel.PasswordHash))
-        {
-            _securityContext.SetUserPasswordHash(userid, memberModel.PasswordHash);
-            _messageService.Send(MessageAction.UserUpdatedPassword);
-
-            _cookiesManager.ResetUserCookie(userid);
-            _messageService.Send(MessageAction.CookieSettingsUpdated);
-        }
-
-        return _employeeFullDtoHelper.GetFull(GetUserInfo(userid.ToString()));
-    }
-
-    public EmployeeDto DeleteMember(string userid)
-    {
-        _permissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
-
-        var user = GetUserInfo(userid);
-
-        if (_userManager.IsSystemUser(user.Id) || user.IsLDAP())
-        {
-            throw new SecurityException();
-        }
-
-        if (user.Status != EmployeeStatus.Terminated)
-        {
-            throw new Exception("The user is not suspended");
-        }
-
-        CheckReassignProccess(new[] { user.Id });
-
-        var userName = user.DisplayUserName(false, _displayUserSettingsHelper);
-        _userPhotoManager.RemovePhoto(user.Id);
-        _userManager.DeleteUser(user.Id);
-        _queueWorkerRemove.Start(Tenant.Id, user, _securityContext.CurrentAccount.ID, false);
-
-        _messageService.Send(MessageAction.UserDeleted, _messageTarget.Create(user.Id), userName);
-
-        return _employeeFullDtoHelper.GetFull(user);
-    }
-
-    public EmployeeDto DeleteProfile()
-    {
-        _apiContext.AuthByClaim();
-
-        if (_userManager.IsSystemUser(_securityContext.CurrentAccount.ID))
-        {
-            throw new SecurityException();
-        }
-
-        var user = GetUserInfo(_securityContext.CurrentAccount.ID.ToString());
-
-        if (!_userManager.UserExists(user))
-        {
-            throw new Exception(Resource.ErrorUserNotFound);
-        }
-
-        if (user.IsLDAP())
-        {
-            throw new SecurityException();
-        }
-
-        _securityContext.AuthenticateMeWithoutCookie(ASC.Core.Configuration.Constants.CoreSystem);
-        user.Status = EmployeeStatus.Terminated;
-
-        _userManager.SaveUserInfo(user);
-        var userName = user.DisplayUserName(false, _displayUserSettingsHelper);
-        _messageService.Send(MessageAction.UsersUpdatedStatus, _messageTarget.Create(user.Id), userName);
-
-        _cookiesManager.ResetUserCookie(user.Id);
-        _messageService.Send(MessageAction.CookieSettingsUpdated);
-
-        if (_coreBaseSettings.Personal)
-        {
-            _userPhotoManager.RemovePhoto(user.Id);
-            _userManager.DeleteUser(user.Id);
-            _messageService.Send(MessageAction.UserDeleted, _messageTarget.Create(user.Id), userName);
-        }
-        else
-        {
-            //StudioNotifyService.Instance.SendMsgProfileHasDeletedItself(user);
-            //StudioNotifyService.SendMsgProfileDeletion(Tenant.TenantId, user);
-        }
-
-        return _employeeFullDtoHelper.GetFull(user);
-    }
-
-    public IEnumerable<EmployeeDto> GetAdvanced(EmployeeStatus status, string query)
-    {
-        if (_coreBaseSettings.Personal)
-        {
-            throw new MethodAccessException("Method not available");
-        }
-        try
-        {
-            var list = _userManager.GetUsers(status).AsEnumerable();
-
-            if ("group".Equals(_apiContext.FilterBy, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(_apiContext.FilterValue))
-            {
-                var groupId = new Guid(_apiContext.FilterValue);
-                //Filter by group
-                list = list.Where(x => _userManager.IsUserInGroup(x.Id, groupId));
-                _apiContext.SetDataFiltered();
-            }
-
-            list = list.Where(x => x.FirstName != null && x.FirstName.IndexOf(query, StringComparison.OrdinalIgnoreCase) > -1 || (x.LastName != null && x.LastName.IndexOf(query, StringComparison.OrdinalIgnoreCase) != -1) ||
-                                   (x.UserName != null && x.UserName.IndexOf(query, StringComparison.OrdinalIgnoreCase) != -1) || (x.Email != null && x.Email.IndexOf(query, StringComparison.OrdinalIgnoreCase) != -1) || (x.ContactsList != null && x.ContactsList.Any(y => y.IndexOf(query, StringComparison.OrdinalIgnoreCase) != -1)));
-
-            return list.Select(u => _employeeFullDtoHelper.GetFull(u));
-        }
-        catch (Exception error)
-        {
-            _logger.Error(error);
-        }
-
-        return null;
-    }
-
-    public EmployeeDto GetByEmail(string email)
-    {
-        if (_coreBaseSettings.Personal && !_userManager.GetUsers(_securityContext.CurrentAccount.ID).IsOwner(Tenant))
-        {
-            throw new MethodAccessException("Method not available");
-        }
-
-        var user = _userManager.GetUserByEmail(email);
-        if (user.Id == Constants.LostUser.Id)
-        {
-            throw new ItemNotFoundException("User not found");
-        }
-
-        return _employeeFullDtoHelper.GetFull(user);
-    }
-
-    public EmployeeDto GetById(string username)
-    {
-        if (_coreBaseSettings.Personal)
-        {
-            throw new MethodAccessException("Method not available");
-        }
-
-        var user = _userManager.GetUserByUserName(username);
-        if (user.Id == Constants.LostUser.Id)
-        {
-            if (Guid.TryParse(username, out var userId))
-            {
-                user = _userManager.GetUsers(userId);
-            }
-            else
-            {
-                _logger.Error(string.Format("Account {0} сould not get user by name {1}", _securityContext.CurrentAccount.ID, username));
-            }
-        }
-
-        if (user.Id == Constants.LostUser.Id)
-        {
-            throw new ItemNotFoundException("User not found");
-        }
-
-        return _employeeFullDtoHelper.GetFull(user);
-    }
-
-    public IEnumerable<EmployeeDto> GetByStatus(EmployeeStatus status)
-    {
-        if (_coreBaseSettings.Personal)
-        {
-            throw new Exception("Method not available");
-        }
-
-        Guid? groupId = null;
-        if ("group".Equals(_apiContext.FilterBy, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(_apiContext.FilterValue))
-        {
-            groupId = new Guid(_apiContext.FilterValue);
-            _apiContext.SetDataFiltered();
-        }
-
-        return GetFullByFilter(status, groupId, null, null, null);
-    }
-
-    public IEnumerable<EmployeeDto> GetFullByFilter(EmployeeStatus? employeeStatus, Guid? groupId, EmployeeActivationStatus? activationStatus, EmployeeType? employeeType, bool? isAdministrator)
-    {
-        var users = GetByFilter(employeeStatus, groupId, activationStatus, employeeType, isAdministrator).AsEnumerable();
-
-        return users.Select(u => _employeeFullDtoHelper.GetFull(u));
-    }
-
-    public Module GetModule()
-    {
-        var product = new PeopleProduct();
-        product.Init();
-
-        return new Module(product);
-    }
-
-    public IEnumerable<EmployeeDto> GetSearch(string query)
-    {
-        if (_coreBaseSettings.Personal)
-        {
-            throw new MethodAccessException("Method not available");
-        }
-
-        try
-        {
-            var groupId = Guid.Empty;
-            if ("group".Equals(_apiContext.FilterBy, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(_apiContext.FilterValue))
-            {
-                groupId = new Guid(_apiContext.FilterValue);
-            }
-
-            var users = _userManager.Search(query, EmployeeStatus.Active, groupId);
-
-            return users.Select(u => _employeeFullDtoHelper.GetFull(u));
-        }
-        catch (Exception error)
-        {
-            _logger.Error(error);
-        }
-
-        return null;
-    }
-
-    public IEnumerable<EmployeeDto> GetSimpleByFilter(EmployeeStatus? employeeStatus, Guid? groupId, EmployeeActivationStatus? activationStatus, EmployeeType? employeeType, bool? isAdministrator)
-    {
-        var users = GetByFilter(employeeStatus, groupId, activationStatus, employeeType, isAdministrator);
-
-        return users.Select(u => _employeeDtoHelper.Get(u));
-    }
-
-    public Task<string> RegisterUserOnPersonalAsync(RegisterPersonalUserRequestDto model, HttpRequest request)
-    {
-        if (!_coreBaseSettings.Personal)
-        {
-            throw new MethodAccessException("Method is only available on personal.onlyoffice.com");
-        }
-
-        return InternalRegisterUserOnPersonalAsync(model, request);
-    }
-
-    public IEnumerable<EmployeeDto> RemoveUsers(UpdateMembersRequestDto model)
-    {
-        _permissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
-
-        CheckReassignProccess(model.UserIds);
-
-        var users = model.UserIds.Select(userId => _userManager.GetUsers(userId))
-            .Where(u => !_userManager.IsSystemUser(u.Id) && !u.IsLDAP())
-            .ToList();
-
-        var userNames = users.Select(x => x.DisplayUserName(false, _displayUserSettingsHelper)).ToList();
-
-        foreach (var user in users)
-        {
-            if (user.Status != EmployeeStatus.Terminated)
-            {
-                continue;
-            }
-
-            _userPhotoManager.RemovePhoto(user.Id);
-            _userManager.DeleteUser(user.Id);
-            _queueWorkerRemove.Start(Tenant.Id, user, _securityContext.CurrentAccount.ID, false);
-        }
-
-        _messageService.Send(MessageAction.UsersDeleted, _messageTarget.Create(users.Select(x => x.Id)), userNames);
-
-        return users.Select(u => _employeeFullDtoHelper.GetFull(u));
-    }
-
-    public IEnumerable<EmployeeDto> ResendUserInvites(UpdateMembersRequestDto model)
-    {
-        var users = model.UserIds
-            .Where(userId => !_userManager.IsSystemUser(userId))
-            .Select(userId => _userManager.GetUsers(userId))
-            .ToList();
-
-        foreach (var user in users)
-        {
-            if (user.IsActive)
-            {
-                continue;
-            }
-
-            var viewer = _userManager.GetUsers(_securityContext.CurrentAccount.ID);
-
-            if (viewer == null)
-            {
-                throw new Exception(Resource.ErrorAccessDenied);
-            }
-
-            if (viewer.IsAdmin(_userManager) || viewer.Id == user.Id)
-            {
-                if (user.ActivationStatus == EmployeeActivationStatus.Activated)
-                {
-                    user.ActivationStatus = EmployeeActivationStatus.NotActivated;
-                }
-                if (user.ActivationStatus == (EmployeeActivationStatus.AutoGenerated | EmployeeActivationStatus.Activated))
-                {
-                    user.ActivationStatus = EmployeeActivationStatus.AutoGenerated;
-                }
-
-                _userManager.SaveUserInfo(user);
-            }
-
-            if (user.ActivationStatus == EmployeeActivationStatus.Pending)
-            {
-                if (user.IsVisitor(_userManager))
-                {
-                    _studioNotifyService.GuestInfoActivation(user);
-                }
-                else
-                {
-                    _studioNotifyService.UserInfoActivation(user);
-                }
-            }
-            else
-            {
-                _studioNotifyService.SendEmailActivationInstructions(user, user.Email);
-            }
-        }
-
-        _messageService.Send(MessageAction.UsersSentActivationInstructions, _messageTarget.Create(users.Select(x => x.Id)), users.Select(x => x.DisplayUserName(false, _displayUserSettingsHelper)));
-
-        return users.Select(u => _employeeFullDtoHelper.GetFull(u));
-    }
-
-    public EmployeeDto Self()
-    {
-        var user = _userManager.GetUser(_securityContext.CurrentAccount.ID, EmployeeFullDtoHelper.GetExpression(_apiContext));
-
-        return _employeeFullDtoHelper.GetFull(user);
-    }
-
-    public object SendEmailChangeInstructions(UpdateMemberRequestDto model)
-    {
-        Guid.TryParse(model.UserId, out var userid);
-
-        if (userid == Guid.Empty)
-        {
-            throw new ArgumentNullException("userid");
-        }
-
-        var email = (model.Email ?? "").Trim();
-
-        if (string.IsNullOrEmpty(email))
-        {
-            throw new Exception(Resource.ErrorEmailEmpty);
-        }
-
-        if (!email.TestEmailRegex())
-        {
-            throw new Exception(Resource.ErrorNotCorrectEmail);
-        }
-
-        var viewer = _userManager.GetUsers(_securityContext.CurrentAccount.ID);
-        var user = _userManager.GetUsers(userid);
-
-        if (user == null)
-        {
-            throw new Exception(Resource.ErrorUserNotFound);
-        }
-
-        if (viewer == null || (user.IsOwner(Tenant) && viewer.Id != user.Id))
-        {
-            throw new Exception(Resource.ErrorAccessDenied);
-        }
-
-        var existentUser = _userManager.GetUserByEmail(email);
-
-        if (existentUser.Id != Constants.LostUser.Id)
-        {
-            throw new Exception(_customNamingPeople.Substitute<Resource>("ErrorEmailAlreadyExists"));
-        }
-
-        if (!viewer.IsAdmin(_userManager))
-        {
-            _studioNotifyService.SendEmailChangeInstructions(user, email);
-        }
-        else
-        {
-            if (email == user.Email)
-            {
-                throw new Exception(Resource.ErrorEmailsAreTheSame);
-            }
-
-            user.Email = email;
-            user.ActivationStatus = EmployeeActivationStatus.NotActivated;
-            _userManager.SaveUserInfo(user);
-            _studioNotifyService.SendEmailActivationInstructions(user, email);
-        }
-
-        _messageService.Send(MessageAction.UserSentEmailChangeInstructions, user.DisplayUserName(false, _displayUserSettingsHelper));
-
-        return string.Format(Resource.MessageEmailChangeInstuctionsSentOnEmail, email);
-    }
-
-    public object SendUserPassword(MemberRequestDto memberModel)
-    {
-        string error = _userManagerWrapper.SendUserPassword(memberModel.Email);
-        if (!string.IsNullOrEmpty(error))
-        {
-            _logger.ErrorFormat("Password recovery ({0}): {1}", memberModel.Email, error);
-        }
-
-        return string.Format(Resource.MessageYourPasswordSendedToEmail, memberModel.Email);
-    }
-
-    public IEnumerable<EmployeeDto> UpdateEmployeeActivationStatus(EmployeeActivationStatus activationstatus, UpdateMembersRequestDto model)
-    {
-        _apiContext.AuthByClaim();
-
-        var retuls = new List<EmployeeDto>();
-        foreach (var id in model.UserIds.Where(userId => !_userManager.IsSystemUser(userId)))
-        {
-            _permissionContext.DemandPermissions(new UserSecurityProvider(id), Constants.Action_EditUser);
-            var u = _userManager.GetUsers(id);
-            if (u.Id == Constants.LostUser.Id || u.IsLDAP())
-            {
-                continue;
-            }
-
-            u.ActivationStatus = activationstatus;
-            _userManager.SaveUserInfo(u);
-            retuls.Add(_employeeFullDtoHelper.GetFull(u));
-        }
-
-        return retuls;
-    }
-
-    public EmployeeDto UpdateMember(string userid, UpdateMemberRequestDto memberModel)
-    {
-        var user = GetUserInfo(userid);
-
-        if (_userManager.IsSystemUser(user.Id))
-        {
-            throw new SecurityException();
-        }
-
-        _permissionContext.DemandPermissions(new UserSecurityProvider(user.Id), Constants.Action_EditUser);
-        var self = _securityContext.CurrentAccount.ID.Equals(user.Id);
-        var resetDate = new DateTime(1900, 01, 01);
-
-        //Update it
-
-        var isLdap = user.IsLDAP();
-        var isSso = user.IsSSO();
-        var isAdmin = _webItemSecurity.IsProductAdministrator(WebItemManager.PeopleProductID, _securityContext.CurrentAccount.ID);
-
-        if (!isLdap && !isSso)
-        {
-            //Set common fields
-
-            user.FirstName = memberModel.Firstname ?? user.FirstName;
-            user.LastName = memberModel.Lastname ?? user.LastName;
-            user.Location = memberModel.Location ?? user.Location;
-
-            if (isAdmin)
-            {
-                user.Title = memberModel.Title ?? user.Title;
-            }
-        }
-
-        if (!_userFormatter.IsValidUserName(user.FirstName, user.LastName))
-        {
-            throw new Exception(Resource.ErrorIncorrectUserName);
-        }
-
-        user.Notes = memberModel.Comment ?? user.Notes;
-        user.Sex = ("male".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase)
-            ? true
-            : ("female".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase) ? (bool?)false : null)) ?? user.Sex;
-
-        user.BirthDate = memberModel.Birthday != null ? _tenantUtil.DateTimeFromUtc(memberModel.Birthday) : user.BirthDate;
-
-        if (user.BirthDate == resetDate)
-        {
-            user.BirthDate = null;
-        }
-
-        user.WorkFromDate = memberModel.Worksfrom != null ? _tenantUtil.DateTimeFromUtc(memberModel.Worksfrom) : user.WorkFromDate;
-
-        if (user.WorkFromDate == resetDate)
-        {
-            user.WorkFromDate = null;
-        }
-
-        //Update contacts
-        UpdateContacts(memberModel.Contacts, user);
-        UpdateDepartments(memberModel.Department, user);
-
-        if (memberModel.Files != _userPhotoManager.GetPhotoAbsoluteWebPath(user.Id))
-        {
-            UpdatePhotoUrl(memberModel.Files, user);
-        }
-        if (memberModel.Disable.HasValue)
-        {
-            user.Status = memberModel.Disable.Value ? EmployeeStatus.Terminated : EmployeeStatus.Active;
-            user.TerminatedDate = memberModel.Disable.Value ? DateTime.UtcNow : null;
-        }
-        if (self && !isAdmin)
-        {
-            _studioNotifyService.SendMsgToAdminAboutProfileUpdated();
-        }
-
-        // change user type
-        var canBeGuestFlag = !user.IsOwner(Tenant) && !user.IsAdmin(_userManager) && user.GetListAdminModules(_webItemSecurity).Count == 0 && !user.IsMe(_authContext);
-
-        if (memberModel.IsVisitor && !user.IsVisitor(_userManager) && canBeGuestFlag)
-        {
-            _userManager.AddUserIntoGroup(user.Id, Constants.GroupVisitor.ID);
-            _webItemSecurityCache.ClearCache(Tenant.Id);
-        }
-
-        if (!self && !memberModel.IsVisitor && user.IsVisitor(_userManager))
-        {
-            var usersQuota = _tenantExtra.GetTenantQuota().ActiveUsers;
-            if (_tenantStatisticsProvider.GetUsersCount() < usersQuota)
-            {
-                _userManager.RemoveUserFromGroup(user.Id, Constants.GroupVisitor.ID);
-                _webItemSecurityCache.ClearCache(Tenant.Id);
-            }
-            else
-            {
-                throw new TenantQuotaException(string.Format("Exceeds the maximum active users ({0})", usersQuota));
-            }
-        }
-
-        _userManager.SaveUserInfo(user);
-        _messageService.Send(MessageAction.UserUpdated, _messageTarget.Create(user.Id), user.DisplayUserName(false, _displayUserSettingsHelper));
-
-        if (memberModel.Disable.HasValue && memberModel.Disable.Value)
-        {
-            _cookiesManager.ResetUserCookie(user.Id);
-            _messageService.Send(MessageAction.CookieSettingsUpdated);
-        }
-
-        return _employeeFullDtoHelper.GetFull(user);
-    }
-
-    public EmployeeDto UpdateMemberCulture(string userid, UpdateMemberRequestDto memberModel)
-    {
-        var user = GetUserInfo(userid);
-
-        if (_userManager.IsSystemUser(user.Id))
-        {
-            throw new SecurityException();
-        }
-
-        _permissionContext.DemandPermissions(new UserSecurityProvider(user.Id), Constants.Action_EditUser);
-
-        var curLng = user.CultureName;
-
-        if (_setupInfo.EnabledCultures.Find(c => string.Equals(c.Name, memberModel.CultureName, StringComparison.InvariantCultureIgnoreCase)) != null)
-        {
-            if (curLng != memberModel.CultureName)
-            {
-                user.CultureName = memberModel.CultureName;
-
-                try
-                {
-                    _userManager.SaveUserInfo(user);
-                }
-                catch
-                {
-                    user.CultureName = curLng;
-                    throw;
-                }
-
-                _messageService.Send(MessageAction.UserUpdatedLanguage, _messageTarget.Create(user.Id), user.DisplayUserName(false, _displayUserSettingsHelper));
-
-            }
-        }
-
-        return _employeeFullDtoHelper.GetFull(user);
-    }
-
-    public IEnumerable<EmployeeDto> UpdateUserStatus(EmployeeStatus status, UpdateMembersRequestDto model)
-    {
-        _permissionContext.DemandPermissions(Constants.Action_EditUser);
-
-        var users = model.UserIds.Select(userId => _userManager.GetUsers(userId))
-            .Where(u => !_userManager.IsSystemUser(u.Id) && !u.IsLDAP())
-            .ToList();
-
-        foreach (var user in users)
-        {
-            if (user.IsOwner(Tenant) || user.IsMe(_authContext))
-            {
-                continue;
-            }
-
-            switch (status)
-            {
-                case EmployeeStatus.Active:
-                    if (user.Status == EmployeeStatus.Terminated)
-                    {
-                        if (_tenantStatisticsProvider.GetUsersCount() < _tenantExtra.GetTenantQuota().ActiveUsers || user.IsVisitor(_userManager))
-                        {
-                            user.Status = EmployeeStatus.Active;
-                            _userManager.SaveUserInfo(user);
-                        }
-                    }
-                    break;
-                case EmployeeStatus.Terminated:
-                    user.Status = EmployeeStatus.Terminated;
-                    _userManager.SaveUserInfo(user);
-
-                    _cookiesManager.ResetUserCookie(user.Id);
-                    _messageService.Send(MessageAction.CookieSettingsUpdated);
-                    break;
-            }
-        }
-
-        _messageService.Send(MessageAction.UsersUpdatedStatus, _messageTarget.Create(users.Select(x => x.Id)), users.Select(x => x.DisplayUserName(false, _displayUserSettingsHelper)));
-
-        return users.Select(u => _employeeFullDtoHelper.GetFull(u));
-    }
-
-    public IEnumerable<EmployeeDto> UpdateUserType(EmployeeType type, UpdateMembersRequestDto model)
-    {
-        var users = model.UserIds
-            .Where(userId => !_userManager.IsSystemUser(userId))
-            .Select(userId => _userManager.GetUsers(userId))
-            .ToList();
-
-        foreach (var user in users)
-        {
-            if (user.IsOwner(Tenant) || user.IsAdmin(_userManager)
-                || user.IsMe(_authContext) || user.GetListAdminModules(_webItemSecurity).Count > 0)
-            {
-                continue;
-            }
-
-            switch (type)
-            {
-                case EmployeeType.User:
-                    if (user.IsVisitor(_userManager))
-                    {
-                        if (_tenantStatisticsProvider.GetUsersCount() < _tenantExtra.GetTenantQuota().ActiveUsers)
-                        {
-                            _userManager.RemoveUserFromGroup(user.Id, Constants.GroupVisitor.ID);
-                            _webItemSecurityCache.ClearCache(Tenant.Id);
-                        }
-                    }
-                    break;
-                case EmployeeType.Visitor:
-                    if (_coreBaseSettings.Standalone || _tenantStatisticsProvider.GetVisitorsCount() < _tenantExtra.GetTenantQuota().ActiveUsers * _constants.CoefficientOfVisitors)
-                    {
-                        _userManager.AddUserIntoGroup(user.Id, Constants.GroupVisitor.ID);
-                        _webItemSecurityCache.ClearCache(Tenant.Id);
-                    }
-                    break;
-            }
-        }
-
-        _messageService.Send(MessageAction.UsersUpdatedType, _messageTarget.Create(users.Select(x => x.Id)), users.Select(x => x.DisplayUserName(false, _displayUserSettingsHelper)));
-
-        return users.Select(u => _employeeFullDtoHelper.GetFull(u));
-    }
-
-    private void CheckReassignProccess(IEnumerable<Guid> userIds)
-    {
-        foreach (var userId in userIds)
-        {
-            var reassignStatus = _queueWorkerReassign.GetProgressItemStatus(Tenant.Id, userId);
-            if (reassignStatus == null || reassignStatus.IsCompleted)
-            {
-                continue;
-            }
-
-            var userName = _userManager.GetUsers(userId).DisplayUserName(_displayUserSettingsHelper);
-
-            throw new Exception(string.Format(Resource.ReassignDataRemoveUserError, userName));
-        }
-    }
-
-    private IQueryable<UserInfo> GetByFilter(EmployeeStatus? employeeStatus, Guid? groupId, EmployeeActivationStatus? activationStatus, EmployeeType? employeeType, bool? isAdministrator)
-    {
-        if (_coreBaseSettings.Personal)
-        {
-            throw new MethodAccessException("Method not available");
-        }
-
-        var isAdmin = _userManager.GetUsers(_securityContext.CurrentAccount.ID).IsAdmin(_userManager) ||
-                      _webItemSecurity.IsProductAdministrator(WebItemManager.PeopleProductID, _securityContext.CurrentAccount.ID);
-
-        var includeGroups = new List<List<Guid>>();
-        if (groupId.HasValue)
-        {
-            includeGroups.Add(new List<Guid> { groupId.Value });
-        }
-
-        var excludeGroups = new List<Guid>();
-
-        if (employeeType != null)
-        {
-            switch (employeeType)
-            {
-                case EmployeeType.User:
-                    excludeGroups.Add(Constants.GroupVisitor.ID);
-                    break;
-                case EmployeeType.Visitor:
-                    includeGroups.Add(new List<Guid> { Constants.GroupVisitor.ID });
-                    break;
-            }
-        }
-
-        if (isAdministrator.HasValue && isAdministrator.Value)
-        {
-            var adminGroups = new List<Guid>
-            {
-                    Constants.GroupAdmin.ID
-            };
-            var products = _webItemManager.GetItemsAll().Where(i => i is IProduct || i.ID == WebItemManager.MailProductID);
-            adminGroups.AddRange(products.Select(r => r.ID));
-
-            includeGroups.Add(adminGroups);
-        }
-
-        var users = _userManager.GetUsers(isAdmin, employeeStatus, includeGroups, excludeGroups, activationStatus, _apiContext.FilterValue, _apiContext.SortBy, !_apiContext.SortDescending, _apiContext.Count, _apiContext.StartIndex, out var total, out var count);
-
-        _apiContext.SetTotalCount(total).SetCount(count);
-
-        return users;
-    }
-
-    private async Task<string> InternalRegisterUserOnPersonalAsync(RegisterPersonalUserRequestDto model, HttpRequest request)
-    {
-        try
-        {
-            if (_coreBaseSettings.CustomMode) model.Lang = "ru-RU";
-
-            var cultureInfo = _setupInfo.GetPersonalCulture(model.Lang).Value;
-
-            if (cultureInfo != null)
-            {
-                Thread.CurrentThread.CurrentUICulture = cultureInfo;
-            }
-
-            model.Email.ThrowIfNull(new ArgumentException(Resource.ErrorEmailEmpty, "email"));
-
-            if (!model.Email.TestEmailRegex()) throw new ArgumentException(Resource.ErrorNotCorrectEmail, "email");
-
-            if (!SetupInfo.IsSecretEmail(model.Email)
-                && !string.IsNullOrEmpty(_setupInfo.RecaptchaPublicKey) && !string.IsNullOrEmpty(_setupInfo.RecaptchaPrivateKey))
-            {
-                var ip = request.Headers["X-Forwarded-For"].ToString() ?? request.GetUserHostAddress();
-
-                if (string.IsNullOrEmpty(model.RecaptchaResponse)
-                    || !await _recaptcha.ValidateRecaptchaAsync(model.RecaptchaResponse, ip))
-                {
-                    throw new RecaptchaException(Resource.RecaptchaInvalid);
-                }
-            }
-
-            var newUserInfo = _userManager.GetUserByEmail(model.Email);
-
-            if (_userManager.UserExists(newUserInfo.Id))
-            {
-                if (!SetupInfo.IsSecretEmail(model.Email) || _securityContext.IsAuthenticated)
-                {
-                    _studioNotifyService.SendAlreadyExist(model.Email);
-                    return string.Empty;
-                }
-
-                try
-                {
-                    _securityContext.AuthenticateMe(Core.Configuration.Constants.CoreSystem);
-                    _userManager.DeleteUser(newUserInfo.Id);
-                }
-                finally
-                {
-                    _securityContext.Logout();
-                }
-            }
-            if (!model.Spam)
-            {
-                try
-                {
-                    //TODO
-                    //const string _databaseID = "com";
-                    //using (var db = DbManager.FromHttpContext(_databaseID))
-                    //{
-                    //    db.ExecuteNonQuery(new SqlInsert("template_unsubscribe", false)
-                    //                           .InColumnValue("email", email.ToLowerInvariant())
-                    //                           .InColumnValue("reason", "personal")
-                    //        );
-                    //    Log.Debug(String.Format("Write to template_unsubscribe {0}", email.ToLowerInvariant()));
-                    //}
-                }
-                catch (Exception ex)
-                {
-                    _logger.Debug($"ERROR write to template_unsubscribe {ex.Message}, email:{model.Email.ToLowerInvariant()}");
-                }
-            }
-
-            _studioNotifyService.SendInvitePersonal(model.Email);
-        }
-        catch (Exception ex)
-        {
-            return ex.Message;
-        }
-
-        return string.Empty;
-    }
-
-    private void UpdateDepartments(IEnumerable<Guid> department, UserInfo user)
-    {
-        if (!_permissionContext.CheckPermissions(Constants.Action_EditGroups))
-        {
-            return;
-        }
-
-        if (department == null)
-        {
-            return;
-        }
-
-        var groups = _userManager.GetUserGroups(user.Id);
-        var managerGroups = new List<Guid>();
-        foreach (var groupInfo in groups)
-        {
-            _userManager.RemoveUserFromGroup(user.Id, groupInfo.ID);
-            var managerId = _userManager.GetDepartmentManager(groupInfo.ID);
-            if (managerId == user.Id)
-            {
-                managerGroups.Add(groupInfo.ID);
-                _userManager.SetDepartmentManager(groupInfo.ID, Guid.Empty);
-            }
-        }
-        foreach (var guid in department)
-        {
-            var userDepartment = _userManager.GetGroupInfo(guid);
-            if (userDepartment != Constants.LostGroupInfo)
-            {
-                _userManager.AddUserIntoGroup(user.Id, guid);
-                if (managerGroups.Contains(guid))
-                {
-                    _userManager.SetDepartmentManager(guid, user.Id);
-                }
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/products/ASC.People/Server/GlobalUsings.cs b/products/ASC.People/Server/GlobalUsings.cs
index 8b424df4ce..a3193c0b9e 100644
--- a/products/ASC.People/Server/GlobalUsings.cs
+++ b/products/ASC.People/Server/GlobalUsings.cs
@@ -16,15 +16,12 @@ global using ASC.Core.Common.Settings;
 global using ASC.Core.Tenants;
 global using ASC.Core.Users;
 global using ASC.Data.Reassigns;
-global using ASC.Employee.Core.Controllers;
 global using ASC.FederatedLogin;
 global using ASC.FederatedLogin.LoginProviders;
 global using ASC.FederatedLogin.Profile;
 global using ASC.MessagingSystem.Core;
 global using ASC.MessagingSystem.Models;
 global using ASC.People;
-global using ASC.People.ApiHelpers;
-global using ASC.People.Api;
 global using ASC.People.ApiModels.RequestDto;
 global using ASC.People.ApiModels.ResponseDto;
 global using ASC.People.Resources;

From 9add54cf6b4f299dfa21983b795cd23454290e55 Mon Sep 17 00:00:00 2001
From: MaksimChegulov <maksim.chegulov@onlyoffice.com>
Date: Sat, 5 Mar 2022 16:20:51 +0300
Subject: [PATCH 26/28] People: renamed api params

---
 .../Server/Api/ContactsController.cs          |  36 +-
 .../Server/Api/NotificationController.cs      |   8 +-
 .../ASC.People/Server/Api/PhotoController.cs  |  40 +--
 .../Server/Api/ReassignController.cs          |  36 +-
 .../Server/Api/RemoveUserDataController.cs    |  28 +-
 .../Server/Api/ThirdpartyController.cs        |  60 ++--
 .../ASC.People/Server/Api/UserController.cs   | 326 +++++++++---------
 7 files changed, 267 insertions(+), 267 deletions(-)

diff --git a/products/ASC.People/Server/Api/ContactsController.cs b/products/ASC.People/Server/Api/ContactsController.cs
index 419400698f..149efbbea3 100644
--- a/products/ASC.People/Server/Api/ContactsController.cs
+++ b/products/ASC.People/Server/Api/ContactsController.cs
@@ -17,45 +17,45 @@ public class ContactsController : PeopleControllerBase
     }
 
     [Delete("{userid}/contacts")]
-    public EmployeeFullDto DeleteMemberContactsFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
+    public EmployeeFullDto DeleteMemberContactsFromBody(string userid, [FromBody] UpdateMemberRequestDto inDto)
     {
-        return DeleteMemberContacts(userid, memberModel);
+        return DeleteMemberContacts(userid, inDto);
     }
 
     [Delete("{userid}/contacts")]
     [Consumes("application/x-www-form-urlencoded")]
-    public EmployeeFullDto DeleteMemberContactsFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
+    public EmployeeFullDto DeleteMemberContactsFromForm(string userid, [FromForm] UpdateMemberRequestDto inDto)
     {
-        return DeleteMemberContacts(userid, memberModel);
+        return DeleteMemberContacts(userid, inDto);
     }
 
     [Create("{userid}/contacts")]
-    public EmployeeFullDto SetMemberContactsFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
+    public EmployeeFullDto SetMemberContactsFromBody(string userid, [FromBody] UpdateMemberRequestDto inDto)
     {
-        return SetMemberContacts(userid, memberModel);
+        return SetMemberContacts(userid, inDto);
     }
 
     [Create("{userid}/contacts")]
     [Consumes("application/x-www-form-urlencoded")]
-    public EmployeeFullDto SetMemberContactsFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
+    public EmployeeFullDto SetMemberContactsFromForm(string userid, [FromForm] UpdateMemberRequestDto inDto)
     {
-        return SetMemberContacts(userid, memberModel);
+        return SetMemberContacts(userid, inDto);
     }
 
     [Update("{userid}/contacts")]
-    public EmployeeFullDto UpdateMemberContactsFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
+    public EmployeeFullDto UpdateMemberContactsFromBody(string userid, [FromBody] UpdateMemberRequestDto inDto)
     {
-        return UpdateMemberContacts(userid, memberModel);
+        return UpdateMemberContacts(userid, inDto);
     }
 
     [Update("{userid}/contacts")]
     [Consumes("application/x-www-form-urlencoded")]
-    public EmployeeFullDto UpdateMemberContactsFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
+    public EmployeeFullDto UpdateMemberContactsFromForm(string userid, [FromForm] UpdateMemberRequestDto inDto)
     {
-        return UpdateMemberContacts(userid, memberModel);
+        return UpdateMemberContacts(userid, inDto);
     }
 
-    private EmployeeFullDto DeleteMemberContacts(string userid, UpdateMemberRequestDto memberModel)
+    private EmployeeFullDto DeleteMemberContacts(string userid, UpdateMemberRequestDto inDto)
     {
         var user = GetUserInfo(userid);
 
@@ -64,13 +64,13 @@ public class ContactsController : PeopleControllerBase
             throw new SecurityException();
         }
 
-        DeleteContacts(memberModel.Contacts, user);
+        DeleteContacts(inDto.Contacts, user);
         _userManager.SaveUserInfo(user);
 
         return _employeeFullDtoHelper.GetFull(user);
     }
 
-    private EmployeeFullDto SetMemberContacts(string userid, UpdateMemberRequestDto memberModel)
+    private EmployeeFullDto SetMemberContacts(string userid, UpdateMemberRequestDto inDto)
     {
         var user = GetUserInfo(userid);
 
@@ -80,13 +80,13 @@ public class ContactsController : PeopleControllerBase
         }
 
         user.ContactsList.Clear();
-        UpdateContacts(memberModel.Contacts, user);
+        UpdateContacts(inDto.Contacts, user);
         _userManager.SaveUserInfo(user);
 
         return _employeeFullDtoHelper.GetFull(user);
     }
 
-    private EmployeeFullDto UpdateMemberContacts(string userid, UpdateMemberRequestDto memberModel)
+    private EmployeeFullDto UpdateMemberContacts(string userid, UpdateMemberRequestDto inDto)
     {
         var user = GetUserInfo(userid);
 
@@ -95,7 +95,7 @@ public class ContactsController : PeopleControllerBase
             throw new SecurityException();
         }
 
-        UpdateContacts(memberModel.Contacts, user);
+        UpdateContacts(inDto.Contacts, user);
         _userManager.SaveUserInfo(user);
 
         return _employeeFullDtoHelper.GetFull(user);
diff --git a/products/ASC.People/Server/Api/NotificationController.cs b/products/ASC.People/Server/Api/NotificationController.cs
index 9caeea3f2f..3e813c51a0 100644
--- a/products/ASC.People/Server/Api/NotificationController.cs
+++ b/products/ASC.People/Server/Api/NotificationController.cs
@@ -28,16 +28,16 @@ public class NotificationController : ApiControllerBase
     }
 
     [Create("phone")]
-    public object SendNotificationToChangeFromBody([FromBody] UpdateMemberRequestDto model)
+    public object SendNotificationToChangeFromBody([FromBody] UpdateMemberRequestDto inDto)
     {
-        return SendNotificationToChange(model.UserId);
+        return SendNotificationToChange(inDto.UserId);
     }
 
     [Create("phone")]
     [Consumes("application/x-www-form-urlencoded")]
-    public object SendNotificationToChangeFromForm([FromForm] UpdateMemberRequestDto model)
+    public object SendNotificationToChangeFromForm([FromForm] UpdateMemberRequestDto inDto)
     {
-        return SendNotificationToChange(model.UserId);
+        return SendNotificationToChange(inDto.UserId);
     }
 
     private object SendNotificationToChange(string userId)
diff --git a/products/ASC.People/Server/Api/PhotoController.cs b/products/ASC.People/Server/Api/PhotoController.cs
index 3b14c8cc3b..b749503e61 100644
--- a/products/ASC.People/Server/Api/PhotoController.cs
+++ b/products/ASC.People/Server/Api/PhotoController.cs
@@ -37,16 +37,16 @@ public class PhotoController : PeopleControllerBase
     }
 
     [Create("{userid}/photo/thumbnails")]
-    public ThumbnailsDataDto CreateMemberPhotoThumbnailsFromBody(string userid, [FromBody] ThumbnailsRequestDto thumbnailsModel)
+    public ThumbnailsDataDto CreateMemberPhotoThumbnailsFromBody(string userid, [FromBody] ThumbnailsRequestDto inDto)
     {
-        return CreateMemberPhotoThumbnails(userid, thumbnailsModel);
+        return CreateMemberPhotoThumbnails(userid, inDto);
     }
 
     [Create("{userid}/photo/thumbnails")]
     [Consumes("application/x-www-form-urlencoded")]
-    public ThumbnailsDataDto CreateMemberPhotoThumbnailsFromForm(string userid, [FromForm] ThumbnailsRequestDto thumbnailsModel)
+    public ThumbnailsDataDto CreateMemberPhotoThumbnailsFromForm(string userid, [FromForm] ThumbnailsRequestDto inDto)
     {
-        return CreateMemberPhotoThumbnails(userid, thumbnailsModel);
+        return CreateMemberPhotoThumbnails(userid, inDto);
     }
 
     [Delete("{userid}/photo")]
@@ -82,27 +82,27 @@ public class PhotoController : PeopleControllerBase
     }
 
     [Update("{userid}/photo")]
-    public ThumbnailsDataDto UpdateMemberPhotoFromBody(string userid, [FromBody] UpdateMemberRequestDto model)
+    public ThumbnailsDataDto UpdateMemberPhotoFromBody(string userid, [FromBody] UpdateMemberRequestDto inDto)
     {
-        return UpdateMemberPhoto(userid, model);
+        return UpdateMemberPhoto(userid, inDto);
     }
 
     [Update("{userid}/photo")]
     [Consumes("application/x-www-form-urlencoded")]
-    public ThumbnailsDataDto UpdateMemberPhotoFromForm(string userid, [FromForm] UpdateMemberRequestDto model)
+    public ThumbnailsDataDto UpdateMemberPhotoFromForm(string userid, [FromForm] UpdateMemberRequestDto inDto)
     {
-        return UpdateMemberPhoto(userid, model);
+        return UpdateMemberPhoto(userid, inDto);
     }
 
     [Create("{userid}/photo")]
-    public FileUploadResultDto UploadMemberPhoto(string userid, IFormCollection model)
+    public FileUploadResultDto UploadMemberPhoto(string userid, IFormCollection formCollection)
     {
         var result = new FileUploadResultDto();
-        var autosave = bool.Parse(model["Autosave"]);
+        var autosave = bool.Parse(formCollection["Autosave"]);
 
         try
         {
-            if (model.Files.Count != 0)
+            if (formCollection.Files.Count != 0)
             {
                 Guid userId;
                 try
@@ -116,7 +116,7 @@ public class PhotoController : PeopleControllerBase
 
                 _permissionContext.DemandPermissions(new UserSecurityProvider(userId), Constants.Action_EditUser);
 
-                var userPhoto = model.Files[0];
+                var userPhoto = formCollection.Files[0];
 
                 if (userPhoto.Length > _setupInfo.MaxImageUploadSize)
                 {
@@ -193,7 +193,7 @@ public class PhotoController : PeopleControllerBase
         return result;
     }
 
-    private ThumbnailsDataDto CreateMemberPhotoThumbnails(string userid, ThumbnailsRequestDto thumbnailsModel)
+    private ThumbnailsDataDto CreateMemberPhotoThumbnails(string userid, ThumbnailsRequestDto inDto)
     {
         var user = GetUserInfo(userid);
 
@@ -204,12 +204,12 @@ public class PhotoController : PeopleControllerBase
 
         _permissionContext.DemandPermissions(new UserSecurityProvider(user.Id), Constants.Action_EditUser);
 
-        if (!string.IsNullOrEmpty(thumbnailsModel.TmpFile))
+        if (!string.IsNullOrEmpty(inDto.TmpFile))
         {
-            var fileName = Path.GetFileName(thumbnailsModel.TmpFile);
+            var fileName = Path.GetFileName(inDto.TmpFile);
             var data = _userPhotoManager.GetTempPhotoData(fileName);
 
-            var settings = new UserPhotoThumbnailSettings(thumbnailsModel.X, thumbnailsModel.Y, thumbnailsModel.Width, thumbnailsModel.Height);
+            var settings = new UserPhotoThumbnailSettings(inDto.X, inDto.Y, inDto.Width, inDto.Height);
 
             _settingsManager.SaveForUser(settings, user.Id);
             _userPhotoManager.RemovePhoto(user.Id);
@@ -218,7 +218,7 @@ public class PhotoController : PeopleControllerBase
         }
         else
         {
-            UserPhotoThumbnailManager.SaveThumbnails(_userPhotoManager, _settingsManager, thumbnailsModel.X, thumbnailsModel.Y, thumbnailsModel.Width, thumbnailsModel.Height, user.Id);
+            UserPhotoThumbnailManager.SaveThumbnails(_userPhotoManager, _settingsManager, inDto.X, inDto.Y, inDto.Width, inDto.Height, user.Id);
         }
 
         _userManager.SaveUserInfo(user);
@@ -227,7 +227,7 @@ public class PhotoController : PeopleControllerBase
         return new ThumbnailsDataDto(user.Id, _userPhotoManager);
     }
 
-    private ThumbnailsDataDto UpdateMemberPhoto(string userid, UpdateMemberRequestDto model)
+    private ThumbnailsDataDto UpdateMemberPhoto(string userid, UpdateMemberRequestDto inDto)
     {
         var user = GetUserInfo(userid);
 
@@ -236,9 +236,9 @@ public class PhotoController : PeopleControllerBase
             throw new SecurityException();
         }
 
-        if (model.Files != _userPhotoManager.GetPhotoAbsoluteWebPath(user.Id))
+        if (inDto.Files != _userPhotoManager.GetPhotoAbsoluteWebPath(user.Id))
         {
-            UpdatePhotoUrl(model.Files, user);
+            UpdatePhotoUrl(inDto.Files, user);
         }
 
         _userManager.SaveUserInfo(user);
diff --git a/products/ASC.People/Server/Api/ReassignController.cs b/products/ASC.People/Server/Api/ReassignController.cs
index c3d54ca8bd..632edaa61a 100644
--- a/products/ASC.People/Server/Api/ReassignController.cs
+++ b/products/ASC.People/Server/Api/ReassignController.cs
@@ -38,66 +38,66 @@ public class ReassignController : ApiControllerBase
     }
 
     [Create(@"reassign/start")]
-    public ReassignProgressItem StartReassignFromBody([FromBody] StartReassignRequestDto model)
+    public ReassignProgressItem StartReassignFromBody([FromBody] StartReassignRequestDto inDto)
     {
-        return StartReassign(model);
+        return StartReassign(inDto);
     }
 
     [Create(@"reassign/start")]
     [Consumes("application/x-www-form-urlencoded")]
-    public ReassignProgressItem StartReassignFromForm([FromForm] StartReassignRequestDto model)
+    public ReassignProgressItem StartReassignFromForm([FromForm] StartReassignRequestDto inDto)
     {
-        return StartReassign(model);
+        return StartReassign(inDto);
     }
 
     [Update(@"reassign/terminate")]
-    public void TerminateReassignFromBody([FromBody] TerminateRequestDto model)
+    public void TerminateReassignFromBody([FromBody] TerminateRequestDto inDto)
     {
-        TerminateReassign(model);
+        TerminateReassign(inDto);
     }
 
     [Update(@"reassign/terminate")]
     [Consumes("application/x-www-form-urlencoded")]
-    public void TerminateReassignFromForm([FromForm] TerminateRequestDto model)
+    public void TerminateReassignFromForm([FromForm] TerminateRequestDto inDto)
     {
-        TerminateReassign(model);
+        TerminateReassign(inDto);
     }
 
-    private ReassignProgressItem StartReassign(StartReassignRequestDto model)
+    private ReassignProgressItem StartReassign(StartReassignRequestDto inDto)
     {
         _permissionContext.DemandPermissions(Constants.Action_EditUser);
 
-        var fromUser = _userManager.GetUsers(model.FromUserId);
+        var fromUser = _userManager.GetUsers(inDto.FromUserId);
 
         if (fromUser == null || fromUser.Id == Constants.LostUser.Id)
         {
-            throw new ArgumentException("User with id = " + model.FromUserId + " not found");
+            throw new ArgumentException("User with id = " + inDto.FromUserId + " not found");
         }
 
         if (fromUser.IsOwner(Tenant) || fromUser.IsMe(_authContext) || fromUser.Status != EmployeeStatus.Terminated)
         {
-            throw new ArgumentException("Can not delete user with id = " + model.FromUserId);
+            throw new ArgumentException("Can not delete user with id = " + inDto.FromUserId);
         }
 
-        var toUser = _userManager.GetUsers(model.ToUserId);
+        var toUser = _userManager.GetUsers(inDto.ToUserId);
 
         if (toUser == null || toUser.Id == Constants.LostUser.Id)
         {
-            throw new ArgumentException("User with id = " + model.ToUserId + " not found");
+            throw new ArgumentException("User with id = " + inDto.ToUserId + " not found");
         }
 
         if (toUser.IsVisitor(_userManager) || toUser.Status == EmployeeStatus.Terminated)
         {
-            throw new ArgumentException("Can not reassign data to user with id = " + model.ToUserId);
+            throw new ArgumentException("Can not reassign data to user with id = " + inDto.ToUserId);
         }
 
-        return _queueWorkerReassign.Start(Tenant.Id, model.FromUserId, model.ToUserId, _securityContext.CurrentAccount.ID, model.DeleteProfile);
+        return _queueWorkerReassign.Start(Tenant.Id, inDto.FromUserId, inDto.ToUserId, _securityContext.CurrentAccount.ID, inDto.DeleteProfile);
     }
 
-    private void TerminateReassign(TerminateRequestDto model)
+    private void TerminateReassign(TerminateRequestDto inDto)
     {
         _permissionContext.DemandPermissions(Constants.Action_EditUser);
 
-        _queueWorkerReassign.Terminate(Tenant.Id, model.UserId);
+        _queueWorkerReassign.Terminate(Tenant.Id, inDto.UserId);
     }
 }
diff --git a/products/ASC.People/Server/Api/RemoveUserDataController.cs b/products/ASC.People/Server/Api/RemoveUserDataController.cs
index 09043f519d..2fa0ade821 100644
--- a/products/ASC.People/Server/Api/RemoveUserDataController.cs
+++ b/products/ASC.People/Server/Api/RemoveUserDataController.cs
@@ -60,52 +60,52 @@ public class RemoveUserDataController : ApiControllerBase
     }
 
     [Create(@"remove/start")]
-    public RemoveProgressItem StartRemoveFromBody([FromBody] TerminateRequestDto model)
+    public RemoveProgressItem StartRemoveFromBody([FromBody] TerminateRequestDto inDto)
     {
-        return StartRemove(model);
+        return StartRemove(inDto);
     }
 
     [Create(@"remove/start")]
     [Consumes("application/x-www-form-urlencoded")]
-    public RemoveProgressItem StartRemoveFromForm([FromForm] TerminateRequestDto model)
+    public RemoveProgressItem StartRemoveFromForm([FromForm] TerminateRequestDto inDto)
     {
-        return StartRemove(model);
+        return StartRemove(inDto);
     }
 
     [Update(@"remove/terminate")]
-    public void TerminateRemoveFromBody([FromBody] TerminateRequestDto model)
+    public void TerminateRemoveFromBody([FromBody] TerminateRequestDto inDto)
     {
-        TerminateRemove(model);
+        TerminateRemove(inDto);
     }
 
     [Update(@"remove/terminate")]
     [Consumes("application/x-www-form-urlencoded")]
-    public void TerminateRemoveFromForm([FromForm] TerminateRequestDto model)
+    public void TerminateRemoveFromForm([FromForm] TerminateRequestDto inDto)
     {
-        TerminateRemove(model);
+        TerminateRemove(inDto);
     }
 
-    private void TerminateRemove(TerminateRequestDto model)
+    private void TerminateRemove(TerminateRequestDto inDto)
     {
         _permissionContext.DemandPermissions(Constants.Action_EditUser);
 
-        _queueWorkerRemove.Terminate(Tenant.Id, model.UserId);
+        _queueWorkerRemove.Terminate(Tenant.Id, inDto.UserId);
     }
 
-    private RemoveProgressItem StartRemove(TerminateRequestDto model)
+    private RemoveProgressItem StartRemove(TerminateRequestDto inDto)
     {
         _permissionContext.DemandPermissions(Constants.Action_EditUser);
 
-        var user = _userManager.GetUsers(model.UserId);
+        var user = _userManager.GetUsers(inDto.UserId);
 
         if (user == null || user.Id == Constants.LostUser.Id)
         {
-            throw new ArgumentException("User with id = " + model.UserId + " not found");
+            throw new ArgumentException("User with id = " + inDto.UserId + " not found");
         }
 
         if (user.IsOwner(Tenant) || user.IsMe(_authContext) || user.Status != EmployeeStatus.Terminated)
         {
-            throw new ArgumentException("Can not delete user with id = " + model.UserId);
+            throw new ArgumentException("Can not delete user with id = " + inDto.UserId);
         }
 
         return _queueWorkerRemove.Start(Tenant.Id, user, _securityContext.CurrentAccount.ID, true);
diff --git a/products/ASC.People/Server/Api/ThirdpartyController.cs b/products/ASC.People/Server/Api/ThirdpartyController.cs
index 6bea322486..c83c04398a 100644
--- a/products/ASC.People/Server/Api/ThirdpartyController.cs
+++ b/products/ASC.People/Server/Api/ThirdpartyController.cs
@@ -111,31 +111,31 @@ public class ThirdpartyController : ApiControllerBase
     }
 
     [Update("thirdparty/linkaccount")]
-    public void LinkAccountFromBody([FromBody] LinkAccountRequestDto model)
+    public void LinkAccountFromBody([FromBody] LinkAccountRequestDto inDto)
     {
-        LinkAccount(model);
+        LinkAccount(inDto);
     }
 
     [Update("thirdparty/linkaccount")]
     [Consumes("application/x-www-form-urlencoded")]
-    public void LinkAccountFromForm([FromForm] LinkAccountRequestDto model)
+    public void LinkAccountFromForm([FromForm] LinkAccountRequestDto inDto)
     {
-        LinkAccount(model);
+        LinkAccount(inDto);
     }
 
     [AllowAnonymous]
     [Create("thirdparty/signup")]
-    public void SignupAccountFromBody([FromBody] SignupAccountRequestDto model)
+    public void SignupAccountFromBody([FromBody] SignupAccountRequestDto inDto)
     {
-        SignupAccount(model);
+        SignupAccount(inDto);
     }
 
     [AllowAnonymous]
     [Create("thirdparty/signup")]
     [Consumes("application/x-www-form-urlencoded")]
-    public void SignupAccountFromForm([FromForm] SignupAccountRequestDto model)
+    public void SignupAccountFromForm([FromForm] SignupAccountRequestDto inDto)
     {
-        SignupAccount(model);
+        SignupAccount(inDto);
     }
 
     [Delete("thirdparty/unlinkaccount")]
@@ -146,9 +146,9 @@ public class ThirdpartyController : ApiControllerBase
         _messageService.Send(MessageAction.UserUnlinkedSocialAccount, GetMeaningfulProviderName(provider));
     }
 
-    private void LinkAccount(LinkAccountRequestDto model)
+    private void LinkAccount(LinkAccountRequestDto inDto)
     {
-        var profile = new LoginProfile(_signature, _instanceCrypto, model.SerializedProfile);
+        var profile = new LoginProfile(_signature, _instanceCrypto, inDto.SerializedProfile);
 
         if (!(_coreBaseSettings.Standalone || _tenantExtra.GetTenantQuota().Oauth))
         {
@@ -170,10 +170,10 @@ public class ThirdpartyController : ApiControllerBase
         }
     }
 
-    private void SignupAccount(SignupAccountRequestDto model)
+    private void SignupAccount(SignupAccountRequestDto inDto)
     {
-        var employeeType = model.EmplType ?? EmployeeType.User;
-        var passwordHash = model.PasswordHash;
+        var employeeType = inDto.EmplType ?? EmployeeType.User;
+        var passwordHash = inDto.PasswordHash;
         var mustChangePassword = false;
         if (string.IsNullOrEmpty(passwordHash))
         {
@@ -181,7 +181,7 @@ public class ThirdpartyController : ApiControllerBase
             mustChangePassword = true;
         }
 
-        var thirdPartyProfile = new LoginProfile(_signature, _instanceCrypto, model.SerializedProfile);
+        var thirdPartyProfile = new LoginProfile(_signature, _instanceCrypto, inDto.SerializedProfile);
         if (!string.IsNullOrEmpty(thirdPartyProfile.AuthorizationError))
         {
             // ignore cancellation
@@ -202,7 +202,7 @@ public class ThirdpartyController : ApiControllerBase
         try
         {
             _securityContext.AuthenticateMeWithoutCookie(ASC.Core.Configuration.Constants.CoreSystem);
-            var newUser = CreateNewUser(GetFirstName(model, thirdPartyProfile), GetLastName(model, thirdPartyProfile), GetEmailAddress(model, thirdPartyProfile), passwordHash, employeeType, false);
+            var newUser = CreateNewUser(GetFirstName(inDto, thirdPartyProfile), GetLastName(inDto, thirdPartyProfile), GetEmailAddress(inDto, thirdPartyProfile), passwordHash, employeeType, false);
             var messageAction = employeeType == EmployeeType.User ? MessageAction.UserCreatedViaInvite : MessageAction.GuestCreatedViaInvite;
             _messageService.Send(MessageInitiator.System, messageAction, _messageTarget.Create(newUser.Id), newUser.DisplayUserName(false, _displayUserSettingsHelper));
             userID = newUser.Id;
@@ -291,55 +291,55 @@ public class ThirdpartyController : ApiControllerBase
         }
     }
 
-    private string GetEmailAddress(SignupAccountRequestDto model)
+    private string GetEmailAddress(SignupAccountRequestDto inDto)
     {
-        if (!string.IsNullOrEmpty(model.Email))
+        if (!string.IsNullOrEmpty(inDto.Email))
         {
-            return model.Email.Trim();
+            return inDto.Email.Trim();
         }
 
         return string.Empty;
     }
 
-    private string GetEmailAddress(SignupAccountRequestDto model, LoginProfile account)
+    private string GetEmailAddress(SignupAccountRequestDto inDto, LoginProfile account)
     {
-        var value = GetEmailAddress(model);
+        var value = GetEmailAddress(inDto);
 
         return string.IsNullOrEmpty(value) ? account.EMail : value;
     }
 
-    private string GetFirstName(SignupAccountRequestDto model)
+    private string GetFirstName(SignupAccountRequestDto inDto)
     {
         var value = string.Empty;
-        if (!string.IsNullOrEmpty(model.FirstName))
+        if (!string.IsNullOrEmpty(inDto.FirstName))
         {
-            value = model.FirstName.Trim();
+            value = inDto.FirstName.Trim();
         }
 
         return HtmlUtil.GetText(value);
     }
 
-    private string GetFirstName(SignupAccountRequestDto model, LoginProfile account)
+    private string GetFirstName(SignupAccountRequestDto inDto, LoginProfile account)
     {
-        var value = GetFirstName(model);
+        var value = GetFirstName(inDto);
 
         return string.IsNullOrEmpty(value) ? account.FirstName : value;
     }
 
-    private string GetLastName(SignupAccountRequestDto model)
+    private string GetLastName(SignupAccountRequestDto inDto)
     {
         var value = string.Empty;
-        if (!string.IsNullOrEmpty(model.LastName))
+        if (!string.IsNullOrEmpty(inDto.LastName))
         {
-            value = model.LastName.Trim();
+            value = inDto.LastName.Trim();
         }
 
         return HtmlUtil.GetText(value);
     }
 
-    private string GetLastName(SignupAccountRequestDto model, LoginProfile account)
+    private string GetLastName(SignupAccountRequestDto inDto, LoginProfile account)
     {
-        var value = GetLastName(model);
+        var value = GetLastName(inDto);
 
         return string.IsNullOrEmpty(value) ? account.LastName : value;
     }
diff --git a/products/ASC.People/Server/Api/UserController.cs b/products/ASC.People/Server/Api/UserController.cs
index e8b718c597..77d8f2525c 100644
--- a/products/ASC.People/Server/Api/UserController.cs
+++ b/products/ASC.People/Server/Api/UserController.cs
@@ -97,46 +97,46 @@ public class UserController : PeopleControllerBase
     }
 
     [Create("active")]
-    public EmployeeDto AddMemberAsActivatedFromBody([FromBody] MemberRequestDto memberModel)
+    public EmployeeDto AddMemberAsActivatedFromBody([FromBody] MemberRequestDto inDto)
     {
-        return AddMemberAsActivated(memberModel);
+        return AddMemberAsActivated(inDto);
     }
 
     [Create("active")]
     [Consumes("application/x-www-form-urlencoded")]
-    public EmployeeDto AddMemberAsActivatedFromForm([FromForm] MemberRequestDto memberModel)
+    public EmployeeDto AddMemberAsActivatedFromForm([FromForm] MemberRequestDto inDto)
     {
-        return AddMemberAsActivated(memberModel);
+        return AddMemberAsActivated(inDto);
     }
 
     [Create]
     [Authorize(AuthenticationSchemes = "confirm", Roles = "LinkInvite,Everyone")]
-    public EmployeeDto AddMemberFromBody([FromBody] MemberRequestDto memberModel)
+    public EmployeeDto AddMemberFromBody([FromBody] MemberRequestDto inDto)
     {
-        return AddMember(memberModel);
+        return AddMember(inDto);
     }
 
     [Create]
     [Authorize(AuthenticationSchemes = "confirm", Roles = "LinkInvite,Everyone")]
     [Consumes("application/x-www-form-urlencoded")]
-    public EmployeeDto AddMemberFromForm([FromForm] MemberRequestDto memberModel)
+    public EmployeeDto AddMemberFromForm([FromForm] MemberRequestDto inDto)
     {
-        return AddMember(memberModel);
+        return AddMember(inDto);
     }
 
     [Update("{userid}/password")]
     [Authorize(AuthenticationSchemes = "confirm", Roles = "PasswordChange,EmailChange,Activation,EmailActivation,Everyone")]
-    public EmployeeDto ChangeUserPasswordFromBody(Guid userid, [FromBody] MemberRequestDto memberModel)
+    public EmployeeDto ChangeUserPasswordFromBody(Guid userid, [FromBody] MemberRequestDto inDto)
     {
-        return ChangeUserPassword(userid, memberModel);
+        return ChangeUserPassword(userid, inDto);
     }
 
     [Update("{userid}/password")]
     [Authorize(AuthenticationSchemes = "confirm", Roles = "PasswordChange,EmailChange,Activation,EmailActivation,Everyone")]
     [Consumes("application/x-www-form-urlencoded")]
-    public EmployeeDto ChangeUserPasswordFromForm(Guid userid, [FromForm] MemberRequestDto memberModel)
+    public EmployeeDto ChangeUserPasswordFromForm(Guid userid, [FromForm] MemberRequestDto inDto)
     {
-        return ChangeUserPassword(userid, memberModel);
+        return ChangeUserPassword(userid, inDto);
     }
 
     [Delete("{userid}")]
@@ -379,40 +379,40 @@ public class UserController : PeopleControllerBase
 
     [AllowAnonymous]
     [Create(@"register")]
-    public Task<string> RegisterUserOnPersonalAsync(RegisterPersonalUserRequestDto model)
+    public Task<string> RegisterUserOnPersonalAsync(RegisterPersonalUserRequestDto inDto)
     {
         if (!_coreBaseSettings.Personal)
         {
             throw new MethodAccessException("Method is only available on personal.onlyoffice.com");
         }
 
-        return InternalRegisterUserOnPersonalAsync(model);
+        return InternalRegisterUserOnPersonalAsync(inDto);
     }
 
     [Update("delete", Order = -1)]
-    public IEnumerable<EmployeeDto> RemoveUsersFromBody([FromBody] UpdateMembersRequestDto model)
+    public IEnumerable<EmployeeDto> RemoveUsersFromBody([FromBody] UpdateMembersRequestDto inDto)
     {
-        return RemoveUsers(model);
+        return RemoveUsers(inDto);
     }
 
     [Update("delete", Order = -1)]
     [Consumes("application/x-www-form-urlencoded")]
-    public IEnumerable<EmployeeDto> RemoveUsersFromForm([FromForm] UpdateMembersRequestDto model)
+    public IEnumerable<EmployeeDto> RemoveUsersFromForm([FromForm] UpdateMembersRequestDto inDto)
     {
-        return RemoveUsers(model);
+        return RemoveUsers(inDto);
     }
 
     [Update("invite")]
-    public IEnumerable<EmployeeDto> ResendUserInvitesFromBody([FromBody] UpdateMembersRequestDto model)
+    public IEnumerable<EmployeeDto> ResendUserInvitesFromBody([FromBody] UpdateMembersRequestDto inDto)
     {
-        return ResendUserInvites(model);
+        return ResendUserInvites(inDto);
     }
 
     [Update("invite")]
     [Consumes("application/x-www-form-urlencoded")]
-    public IEnumerable<EmployeeDto> ResendUserInvitesFromForm([FromForm] UpdateMembersRequestDto model)
+    public IEnumerable<EmployeeDto> ResendUserInvitesFromForm([FromForm] UpdateMembersRequestDto inDto)
     {
-        return ResendUserInvites(model);
+        return ResendUserInvites(inDto);
     }
 
     [Read("@self")]
@@ -424,150 +424,150 @@ public class UserController : PeopleControllerBase
     }
 
     [Create("email", false)]
-    public object SendEmailChangeInstructionsFromBody([FromBody] UpdateMemberRequestDto model)
+    public object SendEmailChangeInstructionsFromBody([FromBody] UpdateMemberRequestDto inDto)
     {
-        return SendEmailChangeInstructions(model);
+        return SendEmailChangeInstructions(inDto);
     }
 
     [Create("email", false)]
     [Consumes("application/x-www-form-urlencoded")]
-    public object SendEmailChangeInstructionsFromForm([FromForm] UpdateMemberRequestDto model)
+    public object SendEmailChangeInstructionsFromForm([FromForm] UpdateMemberRequestDto inDto)
     {
-        return SendEmailChangeInstructions(model);
+        return SendEmailChangeInstructions(inDto);
     }
 
     [AllowAnonymous]
     [Create("password", false)]
-    public object SendUserPasswordFromBody([FromBody] MemberRequestDto memberModel)
+    public object SendUserPasswordFromBody([FromBody] MemberRequestDto inDto)
     {
-        return SendUserPassword(memberModel);
+        return SendUserPassword(inDto);
     }
 
     [AllowAnonymous]
     [Create("password", false)]
     [Consumes("application/x-www-form-urlencoded")]
-    public object SendUserPasswordFromForm([FromForm] MemberRequestDto memberModel)
+    public object SendUserPasswordFromForm([FromForm] MemberRequestDto inDto)
     {
-        return SendUserPassword(memberModel);
+        return SendUserPassword(inDto);
     }
 
     [Update("activationstatus/{activationstatus}")]
     [Authorize(AuthenticationSchemes = "confirm", Roles = "Activation,Everyone")]
-    public IEnumerable<EmployeeDto> UpdateEmployeeActivationStatusFromBody(EmployeeActivationStatus activationstatus, [FromBody] UpdateMembersRequestDto model)
+    public IEnumerable<EmployeeDto> UpdateEmployeeActivationStatusFromBody(EmployeeActivationStatus activationstatus, [FromBody] UpdateMembersRequestDto inDto)
     {
-        return UpdateEmployeeActivationStatus(activationstatus, model);
+        return UpdateEmployeeActivationStatus(activationstatus, inDto);
     }
 
     [Update("activationstatus/{activationstatus}")]
     [Authorize(AuthenticationSchemes = "confirm", Roles = "Activation,Everyone")]
     [Consumes("application/x-www-form-urlencoded")]
-    public IEnumerable<EmployeeDto> UpdateEmployeeActivationStatusFromForm(EmployeeActivationStatus activationstatus, [FromForm] UpdateMembersRequestDto model)
+    public IEnumerable<EmployeeDto> UpdateEmployeeActivationStatusFromForm(EmployeeActivationStatus activationstatus, [FromForm] UpdateMembersRequestDto inDto)
     {
-        return UpdateEmployeeActivationStatus(activationstatus, model);
+        return UpdateEmployeeActivationStatus(activationstatus, inDto);
     }
 
     [Update("{userid}/culture")]
-    public EmployeeDto UpdateMemberCultureFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
+    public EmployeeDto UpdateMemberCultureFromBody(string userid, [FromBody] UpdateMemberRequestDto inDto)
     {
-        return UpdateMemberCulture(userid, memberModel);
+        return UpdateMemberCulture(userid, inDto);
     }
 
     [Update("{userid}/culture")]
     [Consumes("application/x-www-form-urlencoded")]
-    public EmployeeDto UpdateMemberCultureFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
+    public EmployeeDto UpdateMemberCultureFromForm(string userid, [FromForm] UpdateMemberRequestDto inDto)
     {
-        return UpdateMemberCulture(userid, memberModel);
+        return UpdateMemberCulture(userid, inDto);
     }
 
     [Update("{userid}")]
-    public EmployeeDto UpdateMemberFromBody(string userid, [FromBody] UpdateMemberRequestDto memberModel)
+    public EmployeeDto UpdateMemberFromBody(string userid, [FromBody] UpdateMemberRequestDto inDto)
     {
-        return UpdateMember(userid, memberModel);
+        return UpdateMember(userid, inDto);
     }
 
     [Update("{userid}")]
     [Consumes("application/x-www-form-urlencoded")]
-    public EmployeeDto UpdateMemberFromForm(string userid, [FromForm] UpdateMemberRequestDto memberModel)
+    public EmployeeDto UpdateMemberFromForm(string userid, [FromForm] UpdateMemberRequestDto inDto)
     {
-        return UpdateMember(userid, memberModel);
+        return UpdateMember(userid, inDto);
     }
 
     [Update("status/{status}")]
-    public IEnumerable<EmployeeDto> UpdateUserStatusFromBody(EmployeeStatus status, [FromBody] UpdateMembersRequestDto model)
+    public IEnumerable<EmployeeDto> UpdateUserStatusFromBody(EmployeeStatus status, [FromBody] UpdateMembersRequestDto inDto)
     {
-        return UpdateUserStatus(status, model);
+        return UpdateUserStatus(status, inDto);
     }
 
     [Update("status/{status}")]
     [Consumes("application/x-www-form-urlencoded")]
-    public IEnumerable<EmployeeDto> UpdateUserStatusFromForm(EmployeeStatus status, [FromForm] UpdateMembersRequestDto model)
+    public IEnumerable<EmployeeDto> UpdateUserStatusFromForm(EmployeeStatus status, [FromForm] UpdateMembersRequestDto inDto)
     {
-        return UpdateUserStatus(status, model);
+        return UpdateUserStatus(status, inDto);
     }
 
     [Update("type/{type}")]
-    public IEnumerable<EmployeeDto> UpdateUserTypeFromBody(EmployeeType type, [FromBody] UpdateMembersRequestDto model)
+    public IEnumerable<EmployeeDto> UpdateUserTypeFromBody(EmployeeType type, [FromBody] UpdateMembersRequestDto inDto)
     {
-        return UpdateUserType(type, model);
+        return UpdateUserType(type, inDto);
     }
 
     [Update("type/{type}")]
     [Consumes("application/x-www-form-urlencoded")]
-    public IEnumerable<EmployeeDto> UpdateUserTypeFromForm(EmployeeType type, [FromForm] UpdateMembersRequestDto model)
+    public IEnumerable<EmployeeDto> UpdateUserTypeFromForm(EmployeeType type, [FromForm] UpdateMembersRequestDto inDto)
     {
-        return UpdateUserType(type, model);
+        return UpdateUserType(type, inDto);
     }
 
-    private EmployeeDto AddMemberAsActivated(MemberRequestDto memberModel)
+    private EmployeeDto AddMemberAsActivated(MemberRequestDto inDto)
     {
         _permissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
 
         var user = new UserInfo();
 
-        memberModel.PasswordHash = (memberModel.PasswordHash ?? "").Trim();
-        if (string.IsNullOrEmpty(memberModel.PasswordHash))
+        inDto.PasswordHash = (inDto.PasswordHash ?? "").Trim();
+        if (string.IsNullOrEmpty(inDto.PasswordHash))
         {
-            memberModel.Password = (memberModel.Password ?? "").Trim();
+            inDto.Password = (inDto.Password ?? "").Trim();
 
-            if (string.IsNullOrEmpty(memberModel.Password))
+            if (string.IsNullOrEmpty(inDto.Password))
             {
-                memberModel.Password = UserManagerWrapper.GeneratePassword();
+                inDto.Password = UserManagerWrapper.GeneratePassword();
             }
             else
             {
-                _userManagerWrapper.CheckPasswordPolicy(memberModel.Password);
+                _userManagerWrapper.CheckPasswordPolicy(inDto.Password);
             }
 
-            memberModel.PasswordHash = _passwordHasher.GetClientPassword(memberModel.Password);
+            inDto.PasswordHash = _passwordHasher.GetClientPassword(inDto.Password);
         }
 
         //Validate email
-        var address = new MailAddress(memberModel.Email);
+        var address = new MailAddress(inDto.Email);
         user.Email = address.Address;
         //Set common fields
-        user.FirstName = memberModel.Firstname;
-        user.LastName = memberModel.Lastname;
-        user.Title = memberModel.Title;
-        user.Location = memberModel.Location;
-        user.Notes = memberModel.Comment;
-        user.Sex = "male".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase)
+        user.FirstName = inDto.Firstname;
+        user.LastName = inDto.Lastname;
+        user.Title = inDto.Title;
+        user.Location = inDto.Location;
+        user.Notes = inDto.Comment;
+        user.Sex = "male".Equals(inDto.Sex, StringComparison.OrdinalIgnoreCase)
                        ? true
-                       : ("female".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase) ? (bool?)false : null);
+                       : ("female".Equals(inDto.Sex, StringComparison.OrdinalIgnoreCase) ? (bool?)false : null);
 
-        user.BirthDate = memberModel.Birthday != null ? _tenantUtil.DateTimeFromUtc(memberModel.Birthday) : null;
-        user.WorkFromDate = memberModel.Worksfrom != null ? _tenantUtil.DateTimeFromUtc(memberModel.Worksfrom) : DateTime.UtcNow.Date;
+        user.BirthDate = inDto.Birthday != null ? _tenantUtil.DateTimeFromUtc(inDto.Birthday) : null;
+        user.WorkFromDate = inDto.Worksfrom != null ? _tenantUtil.DateTimeFromUtc(inDto.Worksfrom) : DateTime.UtcNow.Date;
 
-        UpdateContacts(memberModel.Contacts, user);
+        UpdateContacts(inDto.Contacts, user);
 
-        user = _userManagerWrapper.AddUser(user, memberModel.PasswordHash, false, false, memberModel.IsVisitor);
+        user = _userManagerWrapper.AddUser(user, inDto.PasswordHash, false, false, inDto.IsVisitor);
 
         user.ActivationStatus = EmployeeActivationStatus.Activated;
 
-        UpdateDepartments(memberModel.Department, user);
+        UpdateDepartments(inDto.Department, user);
 
-        if (memberModel.Files != _userPhotoManager.GetDefaultPhotoAbsoluteWebPath())
+        if (inDto.Files != _userPhotoManager.GetDefaultPhotoAbsoluteWebPath())
         {
-            UpdatePhotoUrl(memberModel.Files, user);
+            UpdatePhotoUrl(inDto.Files, user);
         }
 
         return _employeeFullDtoHelper.GetFull(user);
@@ -627,42 +627,42 @@ public class UserController : PeopleControllerBase
         }
     }
 
-    private async Task<string> InternalRegisterUserOnPersonalAsync(RegisterPersonalUserRequestDto model)
+    private async Task<string> InternalRegisterUserOnPersonalAsync(RegisterPersonalUserRequestDto inDto)
     {
         try
         {
-            if (_coreBaseSettings.CustomMode) model.Lang = "ru-RU";
+            if (_coreBaseSettings.CustomMode) inDto.Lang = "ru-RU";
 
-            var cultureInfo = _setupInfo.GetPersonalCulture(model.Lang).Value;
+            var cultureInfo = _setupInfo.GetPersonalCulture(inDto.Lang).Value;
 
             if (cultureInfo != null)
             {
                 Thread.CurrentThread.CurrentUICulture = cultureInfo;
             }
 
-            model.Email.ThrowIfNull(new ArgumentException(Resource.ErrorEmailEmpty, "email"));
+            inDto.Email.ThrowIfNull(new ArgumentException(Resource.ErrorEmailEmpty, "email"));
 
-            if (!model.Email.TestEmailRegex()) throw new ArgumentException(Resource.ErrorNotCorrectEmail, "email");
+            if (!inDto.Email.TestEmailRegex()) throw new ArgumentException(Resource.ErrorNotCorrectEmail, "email");
 
-            if (!SetupInfo.IsSecretEmail(model.Email)
+            if (!SetupInfo.IsSecretEmail(inDto.Email)
                 && !string.IsNullOrEmpty(_setupInfo.RecaptchaPublicKey) && !string.IsNullOrEmpty(_setupInfo.RecaptchaPrivateKey))
             {
                 var ip = Request.Headers["X-Forwarded-For"].ToString() ?? Request.GetUserHostAddress();
 
-                if (string.IsNullOrEmpty(model.RecaptchaResponse)
-                    || !await _recaptcha.ValidateRecaptchaAsync(model.RecaptchaResponse, ip))
+                if (string.IsNullOrEmpty(inDto.RecaptchaResponse)
+                    || !await _recaptcha.ValidateRecaptchaAsync(inDto.RecaptchaResponse, ip))
                 {
                     throw new RecaptchaException(Resource.RecaptchaInvalid);
                 }
             }
 
-            var newUserInfo = _userManager.GetUserByEmail(model.Email);
+            var newUserInfo = _userManager.GetUserByEmail(inDto.Email);
 
             if (_userManager.UserExists(newUserInfo.Id))
             {
-                if (!SetupInfo.IsSecretEmail(model.Email) || _securityContext.IsAuthenticated)
+                if (!SetupInfo.IsSecretEmail(inDto.Email) || _securityContext.IsAuthenticated)
                 {
-                    _studioNotifyService.SendAlreadyExist(model.Email);
+                    _studioNotifyService.SendAlreadyExist(inDto.Email);
                     return string.Empty;
                 }
 
@@ -676,7 +676,7 @@ public class UserController : PeopleControllerBase
                     _securityContext.Logout();
                 }
             }
-            if (!model.Spam)
+            if (!inDto.Spam)
             {
                 try
                 {
@@ -693,11 +693,11 @@ public class UserController : PeopleControllerBase
                 }
                 catch (Exception ex)
                 {
-                    _logger.Debug($"ERROR write to template_unsubscribe {ex.Message}, email:{model.Email.ToLowerInvariant()}");
+                    _logger.Debug($"ERROR write to template_unsubscribe {ex.Message}, email:{inDto.Email.ToLowerInvariant()}");
                 }
             }
 
-            _studioNotifyService.SendInvitePersonal(model.Email);
+            _studioNotifyService.SendInvitePersonal(inDto.Email);
         }
         catch (Exception ex)
         {
@@ -707,64 +707,64 @@ public class UserController : PeopleControllerBase
         return string.Empty;
     }
 
-    public EmployeeDto AddMember(MemberRequestDto memberModel)
+    public EmployeeDto AddMember(MemberRequestDto inDto)
     {
         _apiContext.AuthByClaim();
 
         _permissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
 
-        memberModel.PasswordHash = (memberModel.PasswordHash ?? "").Trim();
-        if (string.IsNullOrEmpty(memberModel.PasswordHash))
+        inDto.PasswordHash = (inDto.PasswordHash ?? "").Trim();
+        if (string.IsNullOrEmpty(inDto.PasswordHash))
         {
-            memberModel.Password = (memberModel.Password ?? "").Trim();
+            inDto.Password = (inDto.Password ?? "").Trim();
 
-            if (string.IsNullOrEmpty(memberModel.Password))
+            if (string.IsNullOrEmpty(inDto.Password))
             {
-                memberModel.Password = UserManagerWrapper.GeneratePassword();
+                inDto.Password = UserManagerWrapper.GeneratePassword();
             }
             else
             {
-                _userManagerWrapper.CheckPasswordPolicy(memberModel.Password);
+                _userManagerWrapper.CheckPasswordPolicy(inDto.Password);
             }
-            memberModel.PasswordHash = _passwordHasher.GetClientPassword(memberModel.Password);
+            inDto.PasswordHash = _passwordHasher.GetClientPassword(inDto.Password);
         }
 
         var user = new UserInfo();
 
         //Validate email
-        var address = new MailAddress(memberModel.Email);
+        var address = new MailAddress(inDto.Email);
         user.Email = address.Address;
         //Set common fields
-        user.FirstName = memberModel.Firstname;
-        user.LastName = memberModel.Lastname;
-        user.Title = memberModel.Title;
-        user.Location = memberModel.Location;
-        user.Notes = memberModel.Comment;
-        user.Sex = "male".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase)
+        user.FirstName = inDto.Firstname;
+        user.LastName = inDto.Lastname;
+        user.Title = inDto.Title;
+        user.Location = inDto.Location;
+        user.Notes = inDto.Comment;
+        user.Sex = "male".Equals(inDto.Sex, StringComparison.OrdinalIgnoreCase)
                        ? true
-                       : ("female".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase) ? (bool?)false : null);
+                       : ("female".Equals(inDto.Sex, StringComparison.OrdinalIgnoreCase) ? (bool?)false : null);
 
-        user.BirthDate = memberModel.Birthday != null && memberModel.Birthday != DateTime.MinValue ? _tenantUtil.DateTimeFromUtc(memberModel.Birthday) : null;
-        user.WorkFromDate = memberModel.Worksfrom != null && memberModel.Worksfrom != DateTime.MinValue ? _tenantUtil.DateTimeFromUtc(memberModel.Worksfrom) : DateTime.UtcNow.Date;
+        user.BirthDate = inDto.Birthday != null && inDto.Birthday != DateTime.MinValue ? _tenantUtil.DateTimeFromUtc(inDto.Birthday) : null;
+        user.WorkFromDate = inDto.Worksfrom != null && inDto.Worksfrom != DateTime.MinValue ? _tenantUtil.DateTimeFromUtc(inDto.Worksfrom) : DateTime.UtcNow.Date;
 
-        UpdateContacts(memberModel.Contacts, user);
+        UpdateContacts(inDto.Contacts, user);
 
-        user = _userManagerWrapper.AddUser(user, memberModel.PasswordHash, memberModel.FromInviteLink, true, memberModel.IsVisitor, memberModel.FromInviteLink);
+        user = _userManagerWrapper.AddUser(user, inDto.PasswordHash, inDto.FromInviteLink, true, inDto.IsVisitor, inDto.FromInviteLink);
 
-        var messageAction = memberModel.IsVisitor ? MessageAction.GuestCreated : MessageAction.UserCreated;
+        var messageAction = inDto.IsVisitor ? MessageAction.GuestCreated : MessageAction.UserCreated;
         _messageService.Send(messageAction, _messageTarget.Create(user.Id), user.DisplayUserName(false, _displayUserSettingsHelper));
 
-        UpdateDepartments(memberModel.Department, user);
+        UpdateDepartments(inDto.Department, user);
 
-        if (memberModel.Files != _userPhotoManager.GetDefaultPhotoAbsoluteWebPath())
+        if (inDto.Files != _userPhotoManager.GetDefaultPhotoAbsoluteWebPath())
         {
-            UpdatePhotoUrl(memberModel.Files, user);
+            UpdatePhotoUrl(inDto.Files, user);
         }
 
         return _employeeFullDtoHelper.GetFull(user);
     }
 
-    private EmployeeDto ChangeUserPassword(Guid userid, MemberRequestDto memberModel)
+    private EmployeeDto ChangeUserPassword(Guid userid, MemberRequestDto inDto)
     {
         _apiContext.AuthByClaim();
         _permissionContext.DemandPermissions(new UserSecurityProvider(userid), Constants.Action_EditUser);
@@ -781,9 +781,9 @@ public class UserController : PeopleControllerBase
             throw new SecurityException();
         }
 
-        if (!string.IsNullOrEmpty(memberModel.Email))
+        if (!string.IsNullOrEmpty(inDto.Email))
         {
-            var address = new MailAddress(memberModel.Email);
+            var address = new MailAddress(inDto.Email);
             if (!string.Equals(address.Address, user.Email, StringComparison.OrdinalIgnoreCase))
             {
                 user.Email = address.Address.ToLowerInvariant();
@@ -792,21 +792,21 @@ public class UserController : PeopleControllerBase
             }
         }
 
-        memberModel.PasswordHash = (memberModel.PasswordHash ?? "").Trim();
+        inDto.PasswordHash = (inDto.PasswordHash ?? "").Trim();
 
-        if (string.IsNullOrEmpty(memberModel.PasswordHash))
+        if (string.IsNullOrEmpty(inDto.PasswordHash))
         {
-            memberModel.Password = (memberModel.Password ?? "").Trim();
+            inDto.Password = (inDto.Password ?? "").Trim();
 
-            if (!string.IsNullOrEmpty(memberModel.Password))
+            if (!string.IsNullOrEmpty(inDto.Password))
             {
-                memberModel.PasswordHash = _passwordHasher.GetClientPassword(memberModel.Password);
+                inDto.PasswordHash = _passwordHasher.GetClientPassword(inDto.Password);
             }
         }
 
-        if (!string.IsNullOrEmpty(memberModel.PasswordHash))
+        if (!string.IsNullOrEmpty(inDto.PasswordHash))
         {
-            _securityContext.SetUserPasswordHash(userid, memberModel.PasswordHash);
+            _securityContext.SetUserPasswordHash(userid, inDto.PasswordHash);
             _messageService.Send(MessageAction.UserUpdatedPassword);
 
             _cookiesManager.ResetUserCookie(userid);
@@ -866,16 +866,16 @@ public class UserController : PeopleControllerBase
         return users;
     }
 
-    public object SendEmailChangeInstructions(UpdateMemberRequestDto model)
+    public object SendEmailChangeInstructions(UpdateMemberRequestDto inDto)
     {
-        Guid.TryParse(model.UserId, out var userid);
+        Guid.TryParse(inDto.UserId, out var userid);
 
         if (userid == Guid.Empty)
         {
             throw new ArgumentNullException("userid");
         }
 
-        var email = (model.Email ?? "").Trim();
+        var email = (inDto.Email ?? "").Trim();
 
         if (string.IsNullOrEmpty(email))
         {
@@ -929,13 +929,13 @@ public class UserController : PeopleControllerBase
         return string.Format(Resource.MessageEmailChangeInstuctionsSentOnEmail, email);
     }
 
-    public IEnumerable<EmployeeDto> RemoveUsers(UpdateMembersRequestDto model)
+    public IEnumerable<EmployeeDto> RemoveUsers(UpdateMembersRequestDto inDto)
     {
         _permissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
 
-        CheckReassignProccess(model.UserIds);
+        CheckReassignProccess(inDto.UserIds);
 
-        var users = model.UserIds.Select(userId => _userManager.GetUsers(userId))
+        var users = inDto.UserIds.Select(userId => _userManager.GetUsers(userId))
             .Where(u => !_userManager.IsSystemUser(u.Id) && !u.IsLDAP())
             .ToList();
 
@@ -958,9 +958,9 @@ public class UserController : PeopleControllerBase
         return users.Select(u => _employeeFullDtoHelper.GetFull(u));
     }
 
-    public IEnumerable<EmployeeDto> ResendUserInvites(UpdateMembersRequestDto model)
+    public IEnumerable<EmployeeDto> ResendUserInvites(UpdateMembersRequestDto inDto)
     {
-        var users = model.UserIds
+        var users = inDto.UserIds
             .Where(userId => !_userManager.IsSystemUser(userId))
             .Select(userId => _userManager.GetUsers(userId))
             .ToList();
@@ -1015,23 +1015,23 @@ public class UserController : PeopleControllerBase
         return users.Select(u => _employeeFullDtoHelper.GetFull(u));
     }
 
-    public object SendUserPassword(MemberRequestDto memberModel)
+    public object SendUserPassword(MemberRequestDto inDto)
     {
-        string error = _userManagerWrapper.SendUserPassword(memberModel.Email);
+        string error = _userManagerWrapper.SendUserPassword(inDto.Email);
         if (!string.IsNullOrEmpty(error))
         {
-            _logger.ErrorFormat("Password recovery ({0}): {1}", memberModel.Email, error);
+            _logger.ErrorFormat("Password recovery ({0}): {1}", inDto.Email, error);
         }
 
-        return string.Format(Resource.MessageYourPasswordSendedToEmail, memberModel.Email);
+        return string.Format(Resource.MessageYourPasswordSendedToEmail, inDto.Email);
     }
 
-    public IEnumerable<EmployeeDto> UpdateEmployeeActivationStatus(EmployeeActivationStatus activationstatus, UpdateMembersRequestDto model)
+    public IEnumerable<EmployeeDto> UpdateEmployeeActivationStatus(EmployeeActivationStatus activationstatus, UpdateMembersRequestDto inDto)
     {
         _apiContext.AuthByClaim();
 
         var retuls = new List<EmployeeDto>();
-        foreach (var id in model.UserIds.Where(userId => !_userManager.IsSystemUser(userId)))
+        foreach (var id in inDto.UserIds.Where(userId => !_userManager.IsSystemUser(userId)))
         {
             _permissionContext.DemandPermissions(new UserSecurityProvider(id), Constants.Action_EditUser);
             var u = _userManager.GetUsers(id);
@@ -1048,7 +1048,7 @@ public class UserController : PeopleControllerBase
         return retuls;
     }
 
-    public EmployeeDto UpdateMemberCulture(string userid, UpdateMemberRequestDto memberModel)
+    public EmployeeDto UpdateMemberCulture(string userid, UpdateMemberRequestDto inDto)
     {
         var user = GetUserInfo(userid);
 
@@ -1061,11 +1061,11 @@ public class UserController : PeopleControllerBase
 
         var curLng = user.CultureName;
 
-        if (_setupInfo.EnabledCultures.Find(c => string.Equals(c.Name, memberModel.CultureName, StringComparison.InvariantCultureIgnoreCase)) != null)
+        if (_setupInfo.EnabledCultures.Find(c => string.Equals(c.Name, inDto.CultureName, StringComparison.InvariantCultureIgnoreCase)) != null)
         {
-            if (curLng != memberModel.CultureName)
+            if (curLng != inDto.CultureName)
             {
-                user.CultureName = memberModel.CultureName;
+                user.CultureName = inDto.CultureName;
 
                 try
                 {
@@ -1085,7 +1085,7 @@ public class UserController : PeopleControllerBase
         return _employeeFullDtoHelper.GetFull(user);
     }
 
-    public EmployeeDto UpdateMember(string userid, UpdateMemberRequestDto memberModel)
+    public EmployeeDto UpdateMember(string userid, UpdateMemberRequestDto inDto)
     {
         var user = GetUserInfo(userid);
 
@@ -1108,13 +1108,13 @@ public class UserController : PeopleControllerBase
         {
             //Set common fields
 
-            user.FirstName = memberModel.Firstname ?? user.FirstName;
-            user.LastName = memberModel.Lastname ?? user.LastName;
-            user.Location = memberModel.Location ?? user.Location;
+            user.FirstName = inDto.Firstname ?? user.FirstName;
+            user.LastName = inDto.Lastname ?? user.LastName;
+            user.Location = inDto.Location ?? user.Location;
 
             if (isAdmin)
             {
-                user.Title = memberModel.Title ?? user.Title;
+                user.Title = inDto.Title ?? user.Title;
             }
         }
 
@@ -1123,19 +1123,19 @@ public class UserController : PeopleControllerBase
             throw new Exception(Resource.ErrorIncorrectUserName);
         }
 
-        user.Notes = memberModel.Comment ?? user.Notes;
-        user.Sex = ("male".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase)
+        user.Notes = inDto.Comment ?? user.Notes;
+        user.Sex = ("male".Equals(inDto.Sex, StringComparison.OrdinalIgnoreCase)
             ? true
-            : ("female".Equals(memberModel.Sex, StringComparison.OrdinalIgnoreCase) ? (bool?)false : null)) ?? user.Sex;
+            : ("female".Equals(inDto.Sex, StringComparison.OrdinalIgnoreCase) ? (bool?)false : null)) ?? user.Sex;
 
-        user.BirthDate = memberModel.Birthday != null ? _tenantUtil.DateTimeFromUtc(memberModel.Birthday) : user.BirthDate;
+        user.BirthDate = inDto.Birthday != null ? _tenantUtil.DateTimeFromUtc(inDto.Birthday) : user.BirthDate;
 
         if (user.BirthDate == resetDate)
         {
             user.BirthDate = null;
         }
 
-        user.WorkFromDate = memberModel.Worksfrom != null ? _tenantUtil.DateTimeFromUtc(memberModel.Worksfrom) : user.WorkFromDate;
+        user.WorkFromDate = inDto.Worksfrom != null ? _tenantUtil.DateTimeFromUtc(inDto.Worksfrom) : user.WorkFromDate;
 
         if (user.WorkFromDate == resetDate)
         {
@@ -1143,17 +1143,17 @@ public class UserController : PeopleControllerBase
         }
 
         //Update contacts
-        UpdateContacts(memberModel.Contacts, user);
-        UpdateDepartments(memberModel.Department, user);
+        UpdateContacts(inDto.Contacts, user);
+        UpdateDepartments(inDto.Department, user);
 
-        if (memberModel.Files != _userPhotoManager.GetPhotoAbsoluteWebPath(user.Id))
+        if (inDto.Files != _userPhotoManager.GetPhotoAbsoluteWebPath(user.Id))
         {
-            UpdatePhotoUrl(memberModel.Files, user);
+            UpdatePhotoUrl(inDto.Files, user);
         }
-        if (memberModel.Disable.HasValue)
+        if (inDto.Disable.HasValue)
         {
-            user.Status = memberModel.Disable.Value ? EmployeeStatus.Terminated : EmployeeStatus.Active;
-            user.TerminatedDate = memberModel.Disable.Value ? DateTime.UtcNow : null;
+            user.Status = inDto.Disable.Value ? EmployeeStatus.Terminated : EmployeeStatus.Active;
+            user.TerminatedDate = inDto.Disable.Value ? DateTime.UtcNow : null;
         }
         if (self && !isAdmin)
         {
@@ -1163,13 +1163,13 @@ public class UserController : PeopleControllerBase
         // change user type
         var canBeGuestFlag = !user.IsOwner(Tenant) && !user.IsAdmin(_userManager) && user.GetListAdminModules(_webItemSecurity).Count == 0 && !user.IsMe(_authContext);
 
-        if (memberModel.IsVisitor && !user.IsVisitor(_userManager) && canBeGuestFlag)
+        if (inDto.IsVisitor && !user.IsVisitor(_userManager) && canBeGuestFlag)
         {
             _userManager.AddUserIntoGroup(user.Id, Constants.GroupVisitor.ID);
             _webItemSecurityCache.ClearCache(Tenant.Id);
         }
 
-        if (!self && !memberModel.IsVisitor && user.IsVisitor(_userManager))
+        if (!self && !inDto.IsVisitor && user.IsVisitor(_userManager))
         {
             var usersQuota = _tenantExtra.GetTenantQuota().ActiveUsers;
             if (_tenantStatisticsProvider.GetUsersCount() < usersQuota)
@@ -1186,7 +1186,7 @@ public class UserController : PeopleControllerBase
         _userManager.SaveUserInfo(user);
         _messageService.Send(MessageAction.UserUpdated, _messageTarget.Create(user.Id), user.DisplayUserName(false, _displayUserSettingsHelper));
 
-        if (memberModel.Disable.HasValue && memberModel.Disable.Value)
+        if (inDto.Disable.HasValue && inDto.Disable.Value)
         {
             _cookiesManager.ResetUserCookie(user.Id);
             _messageService.Send(MessageAction.CookieSettingsUpdated);
@@ -1195,11 +1195,11 @@ public class UserController : PeopleControllerBase
         return _employeeFullDtoHelper.GetFull(user);
     }
 
-    public IEnumerable<EmployeeDto> UpdateUserStatus(EmployeeStatus status, UpdateMembersRequestDto model)
+    public IEnumerable<EmployeeDto> UpdateUserStatus(EmployeeStatus status, UpdateMembersRequestDto inDto)
     {
         _permissionContext.DemandPermissions(Constants.Action_EditUser);
 
-        var users = model.UserIds.Select(userId => _userManager.GetUsers(userId))
+        var users = inDto.UserIds.Select(userId => _userManager.GetUsers(userId))
             .Where(u => !_userManager.IsSystemUser(u.Id) && !u.IsLDAP())
             .ToList();
 
@@ -1237,9 +1237,9 @@ public class UserController : PeopleControllerBase
         return users.Select(u => _employeeFullDtoHelper.GetFull(u));
     }
 
-    public IEnumerable<EmployeeDto> UpdateUserType(EmployeeType type, UpdateMembersRequestDto model)
+    public IEnumerable<EmployeeDto> UpdateUserType(EmployeeType type, UpdateMembersRequestDto inDto)
     {
-        var users = model.UserIds
+        var users = inDto.UserIds
             .Where(userId => !_userManager.IsSystemUser(userId))
             .Select(userId => _userManager.GetUsers(userId))
             .ToList();

From 78fafb08ab4fbb7e315122546711a401b71d1670 Mon Sep 17 00:00:00 2001
From: pavelbannov <pavel.bannov@onlyoffice.com>
Date: Sat, 5 Mar 2022 18:38:42 +0300
Subject: [PATCH 27/28] Microsoft.NET.Sdk.Worker

---
 .../services/ASC.ClearEvents/ASC.ClearEvents.csproj  |  4 ++--
 common/services/ASC.ClearEvents/GlobalUsings.cs      |  5 +++--
 common/services/ASC.Notify/ASC.Notify.csproj         |  4 +---
 common/services/ASC.Notify/GlobalUsings.cs           |  3 ++-
 .../ASC.Studio.Notify/ASC.Studio.Notify.csproj       |  6 ++----
 common/services/ASC.Studio.Notify/GlobalUsings.cs    | 12 +++++++-----
 .../ASC.TelegramService/ASC.TelegramService.csproj   |  4 +---
 common/services/ASC.TelegramService/GlobalUsings.cs  |  2 ++
 .../ASC.Webhooks.Service/ASC.Webhooks.Service.csproj |  4 ++--
 common/services/ASC.Webhooks.Service/GlobalUsings.cs |  4 +++-
 products/ASC.Files/Service/ASC.Files.Service.csproj  |  6 ++----
 products/ASC.Files/Service/GlobalUsings.cs           |  1 +
 web/ASC.Web.Studio/ASC.Web.Studio.csproj             |  6 ++----
 web/ASC.Web.Studio/GlobalUsings.cs                   |  8 +++++---
 14 files changed, 35 insertions(+), 34 deletions(-)

diff --git a/common/services/ASC.ClearEvents/ASC.ClearEvents.csproj b/common/services/ASC.ClearEvents/ASC.ClearEvents.csproj
index b841ef1635..8d3968a277 100644
--- a/common/services/ASC.ClearEvents/ASC.ClearEvents.csproj
+++ b/common/services/ASC.ClearEvents/ASC.ClearEvents.csproj
@@ -1,11 +1,11 @@
-<Project Sdk="Microsoft.NET.Sdk.Web">
+<Project Sdk="Microsoft.NET.Sdk.Worker">
 
   <PropertyGroup>
     <TargetFramework>net6.0</TargetFramework>
     <ApplicationIcon />
     <OutputType>Exe</OutputType>
     <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
-	  <ImplicitUsings>enable</ImplicitUsings>
+    <ImplicitUsings>enable</ImplicitUsings>
   </PropertyGroup>
 
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
diff --git a/common/services/ASC.ClearEvents/GlobalUsings.cs b/common/services/ASC.ClearEvents/GlobalUsings.cs
index 762e48e9e0..2331c50e97 100644
--- a/common/services/ASC.ClearEvents/GlobalUsings.cs
+++ b/common/services/ASC.ClearEvents/GlobalUsings.cs
@@ -14,8 +14,9 @@ global using ASC.MessagingSystem.Models;
 
 global using Autofac;
 global using Autofac.Extensions.DependencyInjection;
-
-global using Microsoft.EntityFrameworkCore;
+
+global using Microsoft.AspNetCore.Builder;
+global using Microsoft.EntityFrameworkCore;
 global using Microsoft.Extensions.Hosting.WindowsServices;
 global using Microsoft.Extensions.Options;
 
diff --git a/common/services/ASC.Notify/ASC.Notify.csproj b/common/services/ASC.Notify/ASC.Notify.csproj
index d1dbcb3de6..2656290b73 100644
--- a/common/services/ASC.Notify/ASC.Notify.csproj
+++ b/common/services/ASC.Notify/ASC.Notify.csproj
@@ -1,11 +1,9 @@
-<Project Sdk="Microsoft.NET.Sdk.Web">
+<Project Sdk="Microsoft.NET.Sdk.Worker">
 
   <PropertyGroup>
     <TargetFramework>net6.0</TargetFramework>
     <ApplicationIcon />
     <OutputType>Exe</OutputType>
-    <RazorCompileOnBuild>false</RazorCompileOnBuild>
-    <GenerateMvcApplicationPartsAssemblyAttributes>false</GenerateMvcApplicationPartsAssemblyAttributes>
     <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
 	<ImplicitUsings>enable</ImplicitUsings>
   </PropertyGroup>
diff --git a/common/services/ASC.Notify/GlobalUsings.cs b/common/services/ASC.Notify/GlobalUsings.cs
index e29341dfde..cde1c53cdb 100644
--- a/common/services/ASC.Notify/GlobalUsings.cs
+++ b/common/services/ASC.Notify/GlobalUsings.cs
@@ -27,7 +27,8 @@ global using AutoMapper;
 
 global using Google.Protobuf.Collections;
 
-global using Microsoft.EntityFrameworkCore;
+global using Microsoft.AspNetCore.Builder;
+global using Microsoft.EntityFrameworkCore;
 global using Microsoft.Extensions.Hosting.WindowsServices;
 global using Microsoft.Extensions.Options;
 
diff --git a/common/services/ASC.Studio.Notify/ASC.Studio.Notify.csproj b/common/services/ASC.Studio.Notify/ASC.Studio.Notify.csproj
index 402401071d..6dfbcfb5fb 100644
--- a/common/services/ASC.Studio.Notify/ASC.Studio.Notify.csproj
+++ b/common/services/ASC.Studio.Notify/ASC.Studio.Notify.csproj
@@ -1,12 +1,10 @@
-<Project Sdk="Microsoft.NET.Sdk.Web">
+<Project Sdk="Microsoft.NET.Sdk.Worker">
 
   <PropertyGroup>
     <OutputType>Exe</OutputType>
     <TargetFramework>net6.0</TargetFramework>
-    <RazorCompileOnBuild>false</RazorCompileOnBuild>
-    <GenerateMvcApplicationPartsAssemblyAttributes>false</GenerateMvcApplicationPartsAssemblyAttributes>
     <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
-	  <ImplicitUsings>enable</ImplicitUsings>
+    <ImplicitUsings>enable</ImplicitUsings>
   </PropertyGroup>
 
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
diff --git a/common/services/ASC.Studio.Notify/GlobalUsings.cs b/common/services/ASC.Studio.Notify/GlobalUsings.cs
index 4e7ae618c6..e7b6300880 100644
--- a/common/services/ASC.Studio.Notify/GlobalUsings.cs
+++ b/common/services/ASC.Studio.Notify/GlobalUsings.cs
@@ -1,6 +1,6 @@
 global using System.Reflection;
 global using System.Runtime.InteropServices;
-
+
 global using ASC.Api.Core;
 global using ASC.Common;
 global using ASC.Common.Caching;
@@ -9,10 +9,12 @@ global using ASC.Common.Utils;
 global using ASC.Core.Notify;
 global using ASC.Notify;
 global using ASC.Web.Studio.Core.Notify;
-
+
 global using Autofac.Extensions.DependencyInjection;
-
-global using Microsoft.Extensions.Hosting.WindowsServices;
-
+
+global using Microsoft.AspNetCore.Builder;
+global using Microsoft.AspNetCore.Hosting;
+global using Microsoft.Extensions.Hosting.WindowsServices;
+
 global using StackExchange.Redis.Extensions.Core.Configuration;
 global using StackExchange.Redis.Extensions.Newtonsoft;
\ No newline at end of file
diff --git a/common/services/ASC.TelegramService/ASC.TelegramService.csproj b/common/services/ASC.TelegramService/ASC.TelegramService.csproj
index aa4c693649..a2fdb99a20 100644
--- a/common/services/ASC.TelegramService/ASC.TelegramService.csproj
+++ b/common/services/ASC.TelegramService/ASC.TelegramService.csproj
@@ -1,11 +1,9 @@
-<Project Sdk="Microsoft.NET.Sdk.Web">
+<Project Sdk="Microsoft.NET.Sdk.Worker">
 
   <PropertyGroup>
     <TargetFramework>net6.0</TargetFramework>
     <ApplicationIcon />
     <OutputType>Exe</OutputType>
-    <RazorCompileOnBuild>false</RazorCompileOnBuild>
-    <GenerateMvcApplicationPartsAssemblyAttributes>false</GenerateMvcApplicationPartsAssemblyAttributes>
     <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
     <ImplicitUsings>enable</ImplicitUsings>
   </PropertyGroup>
diff --git a/common/services/ASC.TelegramService/GlobalUsings.cs b/common/services/ASC.TelegramService/GlobalUsings.cs
index 91df562f9c..70f20e5259 100644
--- a/common/services/ASC.TelegramService/GlobalUsings.cs
+++ b/common/services/ASC.TelegramService/GlobalUsings.cs
@@ -21,6 +21,8 @@ global using ASC.TelegramService.Core;
 global using Autofac;
 global using Autofac.Extensions.DependencyInjection;
 
+global using Microsoft.AspNetCore.Builder;
+global using Microsoft.AspNetCore.Hosting;
 global using Microsoft.Extensions.Hosting.WindowsServices;
 global using Microsoft.Extensions.Options;
 
diff --git a/common/services/ASC.Webhooks.Service/ASC.Webhooks.Service.csproj b/common/services/ASC.Webhooks.Service/ASC.Webhooks.Service.csproj
index af8fac4651..6d1a4deaf8 100644
--- a/common/services/ASC.Webhooks.Service/ASC.Webhooks.Service.csproj
+++ b/common/services/ASC.Webhooks.Service/ASC.Webhooks.Service.csproj
@@ -1,9 +1,9 @@
-<Project Sdk="Microsoft.NET.Sdk.Web">
+<Project Sdk="Microsoft.NET.Sdk.Worker">
 
   <PropertyGroup>
     <TargetFramework>net6.0</TargetFramework>
     <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
-	  <ImplicitUsings>enable</ImplicitUsings>
+    <ImplicitUsings>enable</ImplicitUsings>
   </PropertyGroup>
 
   <ItemGroup>
diff --git a/common/services/ASC.Webhooks.Service/GlobalUsings.cs b/common/services/ASC.Webhooks.Service/GlobalUsings.cs
index 76d74c3fb6..d45329e60f 100644
--- a/common/services/ASC.Webhooks.Service/GlobalUsings.cs
+++ b/common/services/ASC.Webhooks.Service/GlobalUsings.cs
@@ -16,7 +16,9 @@ global using ASC.Webhooks.Service.Services;
 
 global using Autofac;
 global using Autofac.Extensions.DependencyInjection;
-
+
+global using Microsoft.AspNetCore.Builder;
+global using Microsoft.AspNetCore.Hosting;
 global using Microsoft.Extensions.Hosting.WindowsServices;
 global using Microsoft.Extensions.Options;
 
diff --git a/products/ASC.Files/Service/ASC.Files.Service.csproj b/products/ASC.Files/Service/ASC.Files.Service.csproj
index 144f6eb473..cd74542897 100644
--- a/products/ASC.Files/Service/ASC.Files.Service.csproj
+++ b/products/ASC.Files/Service/ASC.Files.Service.csproj
@@ -1,11 +1,9 @@
-<Project Sdk="Microsoft.NET.Sdk.Web">
+<Project Sdk="Microsoft.NET.Sdk.Worker">
 
   <PropertyGroup>
     <OutputType>Exe</OutputType>
     <TargetFramework>net6.0</TargetFramework>
-	<ImplicitUsings>enable</ImplicitUsings>
-    <RazorCompileOnBuild>false</RazorCompileOnBuild>
-    <GenerateMvcApplicationPartsAssemblyAttributes>false</GenerateMvcApplicationPartsAssemblyAttributes>
+    <ImplicitUsings>enable</ImplicitUsings>
     <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
   </PropertyGroup>
 
diff --git a/products/ASC.Files/Service/GlobalUsings.cs b/products/ASC.Files/Service/GlobalUsings.cs
index a59833c442..146f831e6a 100644
--- a/products/ASC.Files/Service/GlobalUsings.cs
+++ b/products/ASC.Files/Service/GlobalUsings.cs
@@ -35,6 +35,7 @@ global using ASC.Web.Files.Services.DocumentService;
 global using Autofac;
 global using Autofac.Extensions.DependencyInjection;
 
+global using Microsoft.AspNetCore.Builder;
 global using Microsoft.Extensions.Hosting.WindowsServices;
 global using Microsoft.Extensions.Options;
 
diff --git a/web/ASC.Web.Studio/ASC.Web.Studio.csproj b/web/ASC.Web.Studio/ASC.Web.Studio.csproj
index f058703eb0..c9fb8819c6 100644
--- a/web/ASC.Web.Studio/ASC.Web.Studio.csproj
+++ b/web/ASC.Web.Studio/ASC.Web.Studio.csproj
@@ -1,13 +1,11 @@
-<Project Sdk="Microsoft.NET.Sdk.Web">
+<Project Sdk="Microsoft.NET.Sdk.Worker">
 
   <PropertyGroup>
     <TargetFramework>net6.0</TargetFramework>
     <IsPackable>false</IsPackable>
     <DefaultItemExcludes>$(DefaultItemExcludes);</DefaultItemExcludes>
-    <RazorCompileOnBuild>false</RazorCompileOnBuild>
-    <GenerateMvcApplicationPartsAssemblyAttributes>false</GenerateMvcApplicationPartsAssemblyAttributes>
     <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
-	  <ImplicitUsings>enable</ImplicitUsings>
+    <ImplicitUsings>enable</ImplicitUsings>
   </PropertyGroup>
 
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
diff --git a/web/ASC.Web.Studio/GlobalUsings.cs b/web/ASC.Web.Studio/GlobalUsings.cs
index 0c7a0cae73..9ba88cd515 100644
--- a/web/ASC.Web.Studio/GlobalUsings.cs
+++ b/web/ASC.Web.Studio/GlobalUsings.cs
@@ -1,5 +1,5 @@
 global using System.Runtime.InteropServices;
-
+
 global using ASC.Api.Core;
 global using ASC.Common.Utils;
 global using ASC.Data.Storage;
@@ -7,9 +7,11 @@ global using ASC.Data.Storage.DiscStorage;
 global using ASC.FederatedLogin;
 global using ASC.FederatedLogin.LoginProviders;
 global using ASC.Web.Studio;
-
+
 global using Autofac;
 global using Autofac.Extensions.DependencyInjection;
-
+
+global using Microsoft.AspNetCore.Builder;
+global using Microsoft.AspNetCore.Hosting;
 global using Microsoft.AspNetCore.HttpOverrides;
 global using Microsoft.Extensions.Hosting.WindowsServices;

From b9719755be8353c0f68c309ae6d2d7647bffe939 Mon Sep 17 00:00:00 2001
From: pavelbannov <pavel.bannov@onlyoffice.com>
Date: Wed, 9 Mar 2022 20:15:51 +0300
Subject: [PATCH 28/28] Added ThrowIfNull

---
 common/ASC.Api.Core/Core/ApiDateTime.cs       |  22 +-
 .../ArgumentNullExceptionExtension.cs         |  12 +
 common/ASC.Common/Data/StreamExtension.cs     |   4 +-
 common/ASC.Common/Data/TempStream.cs          |   2 +-
 common/ASC.Common/GlobalUsings.cs             |   1 +
 common/ASC.Common/Security/AscRandom.cs       |   5 +-
 .../Authorizing/AuthorizingException.cs       |  12 +-
 .../AzObjectSecurityProviderHelper.cs         |   5 +-
 .../Security/Authorizing/Domain/Role.cs       |   8 +-
 .../Security/Cryptography/Hasher.cs           |  20 +-
 .../ASC.Common/Security/SecurityObjectId.cs   |   4 +-
 common/ASC.Common/Utils/DnsLookup.cs          |  59 +---
 .../ASC.Common/Web/DisposableHttpContext.cs   |   5 +-
 .../ASC.Core.Common/BaseCommonLinkUtility.cs  |  10 +-
 .../ASC.Core.Common/Billing/BillingClient.cs  |   5 +-
 .../Billing/License/LicenseReader.cs          |   5 +-
 .../ASC.Core.Common/Billing/TariffService.cs  |  13 +-
 .../Context/Impl/CoreConfiguration.cs         |  10 +-
 .../Context/Impl/PaymentManager.cs            |   5 +-
 .../Context/Impl/TenantManager.cs             |   5 +-
 .../Context/SecurityContext.cs                |  21 +-
 .../ASC.Core.Common/Core/DBResourceManager.cs |  10 +-
 common/ASC.Core.Common/Data/DbQuotaService.cs |  12 +-
 .../ASC.Core.Common/Data/DbSettingsManager.cs |   5 +-
 .../Data/DbSubscriptionService.cs             |  96 ++----
 .../ASC.Core.Common/Data/DbTenantService.cs   |  93 +++---
 common/ASC.Core.Common/Data/DbUserService.cs  |  34 +--
 common/ASC.Core.Common/HostedSolution.cs      |  60 ++--
 .../Notify/Channels/SenderChannel.cs          |   5 +-
 .../Notify/DirectSubscriptionProvider.cs      |  89 ++----
 .../Notify/Engine/InterceptorStorage.cs       |   2 +-
 .../Notify/Engine/NotifyEngine.cs             |  21 +-
 .../Notify/Engine/NotifyRequest.cs            |   5 +-
 .../Notify/Engine/SendInterceptorSkeleton.cs  |   9 +-
 .../Notify/Messages/NoticeMessage.cs          |   3 +-
 .../Notify/Model/NotifyClientImpl.cs          |  15 +-
 common/ASC.Core.Common/Notify/NotifySource.cs |   5 +-
 .../Notify/Patterns/PatternFormatter.cs       |  24 +-
 .../Notify/Patterns/TagValue.cs               |   5 +-
 .../Notify/RecipientProviderImpl.cs           |  15 +-
 .../Notify/TopSubscriptionProvider.cs         |  90 ++----
 .../Security/Authorizing/AzManager.cs         |  11 +-
 .../Authorizing/PermissionProvider.cs         |  12 +-
 .../Security/EmailValidationKeyProvider.cs    |  22 +-
 common/ASC.Core.Common/Users/UserFormatter.cs |   5 +-
 common/ASC.Data.Backup.Core/ActionInvoker.cs  |   7 +-
 .../Extensions/EnumerableExtensions.cs        |  34 +--
 .../Tasks/BackupPortalTask.cs                 | 112 +++----
 .../Tasks/RestorePortalTask.cs                |  43 ++-
 common/ASC.Data.Storage/BaseStorage.cs        | 189 ++++++------
 .../CrossModuleTransferUtility.cs             |  23 +-
 .../DiscStorage/DiscDataStore.cs              | 283 +++++++-----------
 common/ASC.Data.Storage/TenantPath.cs         |   5 +-
 .../Helpers/OAuth20TokenHelper.cs             |  17 +-
 .../Helpers/RequestHelper.cs                  |   5 +-
 .../LoginProviders/DocuSignLoginProvider.cs   |  17 +-
 .../Profile/LoginProfile.cs                   |  20 +-
 .../ASC.VoipService/Twilio/TwilioProvider.cs  |   4 +-
 products/ASC.Files/Core/ApiModels/Binders.cs  |  25 +-
 .../Core/Core/Dao/TeamlabDao/FileDao.cs       |  40 +--
 .../Core/Core/Dao/TeamlabDao/FolderDao.cs     |  33 +-
 .../Core/Core/Dao/TeamlabDao/TagDao.cs        |  10 +-
 .../Core/Core/Entries/EncryptionKeyPair.cs    |  10 +-
 .../ASC.Files/Core/Core/FilesIntegration.cs   |   5 +-
 .../Core/Core/Thirdparty/Box/BoxFileDao.cs    |  10 +-
 .../Core/Core/Thirdparty/Box/BoxFolderDao.cs  |   5 +-
 .../Core/Core/Thirdparty/Box/BoxStorage.cs    |   5 +-
 .../Core/Thirdparty/Dropbox/DropboxFileDao.cs |  10 +-
 .../Thirdparty/Dropbox/DropboxFolderDao.cs    |   5 +-
 .../Core/Thirdparty/Dropbox/DropboxStorage.cs |   5 +-
 .../GoogleDrive/GoogleDriveFileDao.cs         |  11 +-
 .../GoogleDrive/GoogleDriveFolderDao.cs       |   5 +-
 .../GoogleDrive/GoogleDriveStorage.cs         |  15 +-
 .../Thirdparty/OneDrive/OneDriveFileDao.cs    |  10 +-
 .../Thirdparty/OneDrive/OneDriveFolderDao.cs  |   3 +-
 .../Thirdparty/OneDrive/OneDriveStorage.cs    |  16 +-
 .../Thirdparty/ProviderDao/ProviderFileDao.cs |  26 +-
 .../ProviderDao/ProviderFolderDao.cs          |   5 +-
 .../Core/Thirdparty/RegexDaoSelectorBase.cs   |   5 +-
 .../SharePoint/SharePointFileDao.cs           |   5 +-
 .../Thirdparty/Sharpbox/SharpBoxFileDao.cs    |   5 +-
 .../ASC.Files/Core/Helpers/DocuSignHelper.cs  |  36 +--
 .../ASC.Files/Core/Helpers/PathProvider.cs    |   5 +-
 .../ASC.Files/Core/Helpers/WordpressHelper.cs |  15 +-
 .../Core/Services/FFmpegService/FFmpeg.cs     |  11 +-
 .../Server/Helpers/FilesControllerHelper.cs   |  38 +--
 .../Controllers/SettingsController.cs         |  42 +--
 .../Controllers/SmtpSettingsController.cs     |  13 +-
 web/ASC.Web.Core/Files/DocumentService.cs     |  10 +-
 .../Notify/StudioNotifyService.cs             |  17 +-
 web/ASC.Web.Core/Sms/SmsKeyStorage.cs         |   5 +-
 web/ASC.Web.Core/Sms/SmsSender.cs             |  13 +-
 web/ASC.Web.Core/Users/UserManagerWrapper.cs  |   2 +-
 web/ASC.Web.Core/WebItemSecurity.cs           |   5 +-
 94 files changed, 709 insertions(+), 1412 deletions(-)
 create mode 100644 common/ASC.Common/ArgumentNullExceptionExtension.cs

diff --git a/common/ASC.Api.Core/Core/ApiDateTime.cs b/common/ASC.Api.Core/Core/ApiDateTime.cs
index a860cac531..bea22bf866 100644
--- a/common/ASC.Api.Core/Core/ApiDateTime.cs
+++ b/common/ASC.Api.Core/Core/ApiDateTime.cs
@@ -85,18 +85,18 @@ public sealed class ApiDateTime : IComparable<ApiDateTime>, IComparable
 
     public static ApiDateTime Parse(string data, TimeZoneInfo tz, TenantManager tenantManager, TimeZoneConverter timeZoneConverter)
     {
-            if (string.IsNullOrEmpty(data)) throw new ArgumentNullException(nameof(data));
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(data);
 
         var offsetPart = data.Substring(data.Length - 6, 6);
         if (DateTime.TryParseExact(data, Formats, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out var dateTime))
         {
             //Parse time   
             var tzOffset = TimeSpan.Zero;
-                if (offsetPart.Contains(':') && TimeSpan.TryParse(offsetPart.TrimStart('+'), out tzOffset))
+            if (offsetPart.Contains(':') && TimeSpan.TryParse(offsetPart.TrimStart('+'), out tzOffset))
             {
                 return new ApiDateTime(dateTime, tzOffset);
             }
-                
+
             if (!data.EndsWith("Z", true, CultureInfo.InvariantCulture))
             {
                 if (tz == null)
@@ -139,7 +139,7 @@ public sealed class ApiDateTime : IComparable<ApiDateTime>, IComparable
         if (value.Kind == DateTimeKind.Unspecified)
         {
             value = new DateTime(value.Ticks, DateTimeKind.Utc); //Assume it's utc
-        } 
+        }
 
         if (value.Kind == DateTimeKind.Utc)
         {
@@ -166,8 +166,8 @@ public sealed class ApiDateTime : IComparable<ApiDateTime>, IComparable
     private string ToRoundTripString(DateTime date, TimeSpan offset)
     {
         var dateString = date.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffffff", CultureInfo.InvariantCulture);
-        var offsetString = offset.Ticks == 0 
-            ? "Z" : ((offset < TimeSpan.Zero) 
+        var offsetString = offset.Ticks == 0
+            ? "Z" : ((offset < TimeSpan.Zero)
             ? "-" : "+") + offset.ToString("hh\\:mm", CultureInfo.InvariantCulture);
 
         return dateString + offsetString;
@@ -277,9 +277,9 @@ public sealed class ApiDateTime : IComparable<ApiDateTime>, IComparable
 
     public override bool Equals(object obj)
     {
-            if (obj is null) return false;
-            if (ReferenceEquals(this, obj)) return true;
-            if (!(obj is ApiDateTime)) return false;
+        if (obj is null) return false;
+        if (ReferenceEquals(this, obj)) return true;
+        if (!(obj is ApiDateTime)) return false;
         return Equals((ApiDateTime)obj);
     }
 
@@ -369,7 +369,7 @@ public class ApiDateTimeConverter : System.Text.Json.Serialization.JsonConverter
         }
         else
         {
-            if (DateTime.TryParseExact(reader.GetString(), ApiDateTime.Formats, 
+            if (DateTime.TryParseExact(reader.GetString(), ApiDateTime.Formats,
                 CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out var dateTime))
             {
                 return new ApiDateTime(dateTime, TimeSpan.Zero);
@@ -377,7 +377,7 @@ public class ApiDateTimeConverter : System.Text.Json.Serialization.JsonConverter
             else
             {
                 return new ApiDateTime();
-            }  
+            }
         }
     }
 
diff --git a/common/ASC.Common/ArgumentNullExceptionExtension.cs b/common/ASC.Common/ArgumentNullExceptionExtension.cs
new file mode 100644
index 0000000000..bbd5815f15
--- /dev/null
+++ b/common/ASC.Common/ArgumentNullExceptionExtension.cs
@@ -0,0 +1,12 @@
+namespace System;
+
+public static class ArgumentNullOrEmptyException
+{
+    public static void ThrowIfNullOrEmpty(string argument, [CallerArgumentExpression("argument")] string? paramName = null)
+    {
+        if (string.IsNullOrEmpty(argument))
+        {
+            throw new ArgumentNullException(paramName);
+        }
+    }
+}
diff --git a/common/ASC.Common/Data/StreamExtension.cs b/common/ASC.Common/Data/StreamExtension.cs
index 02bd49b22d..bb788a3d42 100644
--- a/common/ASC.Common/Data/StreamExtension.cs
+++ b/common/ASC.Common/Data/StreamExtension.cs
@@ -31,8 +31,8 @@ public static class StreamExtension
 
     public static void StreamCopyTo(this Stream srcStream, Stream dstStream, int length)
     {
-        if (srcStream == null) throw new ArgumentNullException(nameof(srcStream));
-        if (dstStream == null) throw new ArgumentNullException(nameof(dstStream));
+        ArgumentNullException.ThrowIfNull(srcStream);
+        ArgumentNullException.ThrowIfNull(dstStream);
 
         var buffer = new byte[BufferSize];
         int totalRead = 0;
diff --git a/common/ASC.Common/Data/TempStream.cs b/common/ASC.Common/Data/TempStream.cs
index 28b10e1525..61cbc948f5 100644
--- a/common/ASC.Common/Data/TempStream.cs
+++ b/common/ASC.Common/Data/TempStream.cs
@@ -28,7 +28,7 @@ public class TempStream
 
     public Stream GetBuffered(Stream srcStream)
     {
-            if (srcStream == null) throw new ArgumentNullException(nameof(srcStream));
+        ArgumentNullException.ThrowIfNull(srcStream);
         if (!srcStream.CanSeek || srcStream.CanTimeout)
         {
             //Buffer it
diff --git a/common/ASC.Common/GlobalUsings.cs b/common/ASC.Common/GlobalUsings.cs
index b4089c92e3..acba37bf66 100644
--- a/common/ASC.Common/GlobalUsings.cs
+++ b/common/ASC.Common/GlobalUsings.cs
@@ -7,6 +7,7 @@ global using System.Net;
 global using System.Net.Mail;
 global using System.Reflection;
 global using System.Runtime.Caching;
+global using System.Runtime.CompilerServices;
 global using System.Runtime.Loader;
 global using System.Runtime.Serialization;
 global using System.Security.Cryptography;
diff --git a/common/ASC.Common/Security/AscRandom.cs b/common/ASC.Common/Security/AscRandom.cs
index 789639f1ac..e95bb3af86 100644
--- a/common/ASC.Common/Security/AscRandom.cs
+++ b/common/ASC.Common/Security/AscRandom.cs
@@ -88,10 +88,7 @@ public class AscRandom : Random
 
     public override void NextBytes(byte[] buffer)
     {
-        if (buffer == null)
-        {
-            throw new ArgumentNullException(nameof(buffer));
-        }
+        ArgumentNullException.ThrowIfNull(buffer);
 
         for (var i = 0; i < buffer.Length; i++)
         {
diff --git a/common/ASC.Common/Security/Authorizing/AuthorizingException.cs b/common/ASC.Common/Security/Authorizing/AuthorizingException.cs
index bb7c3bc5b9..83317af1da 100644
--- a/common/ASC.Common/Security/Authorizing/AuthorizingException.cs
+++ b/common/ASC.Common/Security/Authorizing/AuthorizingException.cs
@@ -43,9 +43,11 @@ public class AuthorizingException : Exception
         if (actions == null || actions.Length == 0)
         {
             throw new ArgumentNullException(nameof(actions));
-        }
+        }
+
+        ArgumentNullException.ThrowIfNull(subject);
 
-        Subject = subject ?? throw new ArgumentNullException(nameof(subject));
+        Subject = subject;
         Actions = actions;
         var sactions = "";
 
@@ -80,10 +82,8 @@ public class AuthorizingException : Exception
     internal static string FormatErrorMessage(ISubject subject, IAction[] actions, ISubject[] denySubjects,
                                               IAction[] denyActions)
     {
-        if (subject == null)
-        {
-            throw new ArgumentNullException(nameof(subject));
-        }
+        ArgumentNullException.ThrowIfNull(subject);
+
         if (actions == null || actions.Length == 0)
         {
             throw new ArgumentNullException(nameof(actions));
diff --git a/common/ASC.Common/Security/Authorizing/AzObjectSecurityProviderHelper.cs b/common/ASC.Common/Security/Authorizing/AzObjectSecurityProviderHelper.cs
index 673f5a6e8e..531b3ae566 100644
--- a/common/ASC.Common/Security/Authorizing/AzObjectSecurityProviderHelper.cs
+++ b/common/ASC.Common/Security/Authorizing/AzObjectSecurityProviderHelper.cs
@@ -35,9 +35,10 @@ public class AzObjectSecurityProviderHelper
     private ISecurityObjectProvider _currSecObjProvider;
 
     public AzObjectSecurityProviderHelper(ISecurityObjectId objectId, ISecurityObjectProvider secObjProvider)
-    {
+    {
+        ArgumentNullException.ThrowIfNull(objectId);
         _currObjIdAsProvider = false;
-        CurrentObjectId = objectId ?? throw new ArgumentNullException(nameof(objectId));
+        CurrentObjectId = objectId;
         _currSecObjProvider = secObjProvider;
 
         if (_currSecObjProvider == null && CurrentObjectId is ISecurityObjectProvider securityObjectProvider)
diff --git a/common/ASC.Common/Security/Authorizing/Domain/Role.cs b/common/ASC.Common/Security/Authorizing/Domain/Role.cs
index b5721611eb..0793d3a972 100644
--- a/common/ASC.Common/Security/Authorizing/Domain/Role.cs
+++ b/common/ASC.Common/Security/Authorizing/Domain/Role.cs
@@ -45,11 +45,9 @@ public sealed class Role : IRole
         if (id == Guid.Empty)
         {
             throw new ArgumentException(nameof(id));
-        }
-        if (string.IsNullOrEmpty(name))
-        {
-            throw new ArgumentNullException(nameof(name));
-        }
+        }
+
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(name);
 
         ID = id;
         Name = name;
diff --git a/common/ASC.Common/Security/Cryptography/Hasher.cs b/common/ASC.Common/Security/Cryptography/Hasher.cs
index 52b160019d..af8a95746a 100644
--- a/common/ASC.Common/Security/Cryptography/Hasher.cs
+++ b/common/ASC.Common/Security/Cryptography/Hasher.cs
@@ -106,40 +106,28 @@ public static class Hasher
 
     private static byte[] S2B(string str)
     {
-        if (str == null)
-        {
-            throw new ArgumentNullException(nameof(str));
-        }
+        ArgumentNullException.ThrowIfNull(str);
 
         return Encoding.UTF8.GetBytes(str);
     }
 
     private static string B2S(byte[] data)
     {
-        if (data == null)
-        {
-            throw new ArgumentNullException(nameof(data));
-        }
+        ArgumentNullException.ThrowIfNull(data);
 
         return Encoding.UTF8.GetString(data);
     }
 
     private static byte[] S642B(string str)
     {
-        if (str == null)
-        {
-            throw new ArgumentNullException(nameof(str));
-        }
+        ArgumentNullException.ThrowIfNull(str);
 
         return Convert.FromBase64String(str);
     }
 
     private static string B2S64(byte[] data)
     {
-        if (data == null)
-        {
-            throw new ArgumentNullException(nameof(data));
-        }
+        ArgumentNullException.ThrowIfNull(data);
 
         return Convert.ToBase64String(data);
     }
diff --git a/common/ASC.Common/Security/SecurityObjectId.cs b/common/ASC.Common/Security/SecurityObjectId.cs
index ad33bffed6..6f33f50274 100644
--- a/common/ASC.Common/Security/SecurityObjectId.cs
+++ b/common/ASC.Common/Security/SecurityObjectId.cs
@@ -34,8 +34,10 @@ public class SecurityObjectId : ISecurityObjectId
 
     public SecurityObjectId(object id, Type objType)
     {
+        ArgumentNullException.ThrowIfNull(objType);
+
         SecurityId = id;
-        ObjectType = objType ?? throw new ArgumentNullException(nameof(objType));
+        ObjectType = objType;
     }
 
     public override int GetHashCode()
diff --git a/common/ASC.Common/Utils/DnsLookup.cs b/common/ASC.Common/Utils/DnsLookup.cs
index 6873ab0c05..0c73936a45 100644
--- a/common/ASC.Common/Utils/DnsLookup.cs
+++ b/common/ASC.Common/Utils/DnsLookup.cs
@@ -45,10 +45,7 @@ public class DnsLookup
     /// <returns>list of MxRecord</returns>
     public List<MxRecord> GetDomainMxRecords(string domainName)
     {
-        if (string.IsNullOrEmpty(domainName))
-        {
-            throw new ArgumentNullException(nameof(domainName));
-        }
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(domainName);
 
         var mxRecords = DnsResolve<MxRecord>(domainName, RecordType.Mx);
 
@@ -65,15 +62,8 @@ public class DnsLookup
     /// <returns>true if exists and vice versa</returns>
     public bool IsDomainMxRecordExists(string domainName, string mxRecord)
     {
-        if (string.IsNullOrEmpty(domainName))
-        {
-            throw new ArgumentNullException(nameof(domainName));
-        }
-
-        if (string.IsNullOrEmpty(mxRecord))
-        {
-            throw new ArgumentNullException(nameof(mxRecord));
-        }
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(domainName);
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(mxRecord);
 
         var mxDomain = DomainName.Parse(mxRecord);
 
@@ -93,14 +83,11 @@ public class DnsLookup
     /// <returns>true if any DNS record exists and vice versa</returns>
     public bool IsDomainExists(string domainName)
     {
-        if (string.IsNullOrEmpty(domainName))
-        {
-            throw new ArgumentNullException(nameof(domainName));
-        }
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(domainName);
 
         var dnsMessage = GetDnsMessage(domainName);
 
-            return dnsMessage.AnswerRecords.Count != 0;
+        return dnsMessage.AnswerRecords.Count != 0;
     }
 
     /// <summary>
@@ -112,10 +99,7 @@ public class DnsLookup
     /// <returns>list of ARecord</returns>
     public List<ARecord> GetDomainARecords(string domainName)
     {
-        if (string.IsNullOrEmpty(domainName))
-        {
-            throw new ArgumentNullException(nameof(domainName));
-        }
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(domainName);
 
         var aRecords = DnsResolve<ARecord>(domainName, RecordType.A);
 
@@ -131,10 +115,7 @@ public class DnsLookup
     /// <returns>list of IPAddress</returns>
     public List<IPAddress> GetDomainIPs(string domainName)
     {
-        if (string.IsNullOrEmpty(domainName))
-        {
-            throw new ArgumentNullException(nameof(domainName));
-        }
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(domainName);
 
         var addresses = _sDnsResolver.ResolveHost(domainName);
 
@@ -150,10 +131,7 @@ public class DnsLookup
     /// <returns>list of TxtRecord</returns>
     public List<TxtRecord> GetDomainTxtRecords(string domainName)
     {
-        if (string.IsNullOrEmpty(domainName))
-        {
-            throw new ArgumentNullException(nameof(domainName));
-        }
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(domainName);
 
         var txtRecords = DnsResolve<TxtRecord>(domainName, RecordType.Txt);
 
@@ -206,14 +184,9 @@ public class DnsLookup
     /// <returns>true if exists and vice versa</returns>
     public bool IsDomainPtrRecordExists(IPAddress ipAddress, string domainName)
     {
-        if (string.IsNullOrEmpty(domainName))
-        {
-            throw new ArgumentNullException(nameof(domainName));
-        }
-        if (ipAddress == null)
-        {
-            throw new ArgumentNullException(nameof(ipAddress));
-        }
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(domainName);
+
+        ArgumentNullException.ThrowIfNull(ipAddress);
 
         var domain = DomainName.Parse(domainName);
 
@@ -238,10 +211,7 @@ public class DnsLookup
 
     private DnsMessage GetDnsMessage(string domainName, RecordType? type = null)
     {
-        if (string.IsNullOrEmpty(domainName))
-        {
-            throw new ArgumentNullException(nameof(domainName));
-        }
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(domainName);
 
         var domain = DomainName.Parse(domainName);
 
@@ -257,10 +227,7 @@ public class DnsLookup
 
     private List<T> DnsResolve<T>(string domainName, RecordType type)
     {
-        if (string.IsNullOrEmpty(domainName))
-        {
-            throw new ArgumentNullException(nameof(domainName));
-        }
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(domainName);
 
         var dnsMessage = GetDnsMessage(domainName, type);
 
diff --git a/common/ASC.Common/Web/DisposableHttpContext.cs b/common/ASC.Common/Web/DisposableHttpContext.cs
index 139f7714d7..b449723cd0 100644
--- a/common/ASC.Common/Web/DisposableHttpContext.cs
+++ b/common/ASC.Common/Web/DisposableHttpContext.cs
@@ -68,8 +68,9 @@ public class DisposableHttpContext : IDisposable
     private bool _isDisposed;
 
     public DisposableHttpContext(HttpContext ctx)
-    {
-        _context = ctx ?? throw new ArgumentNullException(nameof(ctx));
+    {
+        ArgumentNullException.ThrowIfNull(ctx);
+        _context = ctx;
     }
 
     public void Dispose()
diff --git a/common/ASC.Core.Common/BaseCommonLinkUtility.cs b/common/ASC.Core.Common/BaseCommonLinkUtility.cs
index 30bba3e670..58b1318c29 100644
--- a/common/ASC.Core.Common/BaseCommonLinkUtility.cs
+++ b/common/ASC.Core.Common/BaseCommonLinkUtility.cs
@@ -78,10 +78,7 @@ public class BaseCommonLinkUtility
                 {
                     var u = HttpContextAccessor?.HttpContext.Request.GetUrlRewriter();
 
-                    if (u == null)
-                    {
-                        throw new ArgumentNullException(nameof(u));
-                    }
+                    ArgumentNullException.ThrowIfNull(u);
 
                     uriBuilder = new UriBuilder(u.Scheme, LocalHost, u.Port);
                 }
@@ -120,10 +117,7 @@ public class BaseCommonLinkUtility
             {
                 var u = HttpContextAccessor?.HttpContext?.Request.GetUrlRewriter();
 
-                if (u == null)
-                {
-                    throw new ArgumentNullException(nameof(u));
-                }
+                ArgumentNullException.ThrowIfNull(u);
 
                 result = new UriBuilder(u.Scheme, u.Host, u.Port);
 
diff --git a/common/ASC.Core.Common/Billing/BillingClient.cs b/common/ASC.Core.Common/Billing/BillingClient.cs
index d799f499a8..9c9c259d95 100644
--- a/common/ASC.Core.Common/Billing/BillingClient.cs
+++ b/common/ASC.Core.Common/Billing/BillingClient.cs
@@ -170,10 +170,7 @@ public class BillingClient
 
     public IDictionary<string, Dictionary<string, decimal>> GetProductPriceInfo(params string[] productIds)
     {
-        if (productIds == null)
-        {
-            throw new ArgumentNullException(nameof(productIds));
-        }
+        ArgumentNullException.ThrowIfNull(productIds);
 
         var parameters = productIds.Select(pid => Tuple.Create("ProductId", pid)).ToList();
         parameters.Add(Tuple.Create("PaymentSystemId", AvangatePaymentSystemId.ToString()));
diff --git a/common/ASC.Core.Common/Billing/License/LicenseReader.cs b/common/ASC.Core.Common/Billing/License/LicenseReader.cs
index 7b7c1b5138..3bd3c42c75 100644
--- a/common/ASC.Core.Common/Billing/License/LicenseReader.cs
+++ b/common/ASC.Core.Common/Billing/License/LicenseReader.cs
@@ -153,10 +153,7 @@ public class LicenseReader
 
     private static void SaveLicense(Stream licenseStream, string path)
     {
-        if (licenseStream == null)
-        {
-            throw new ArgumentNullException(nameof(licenseStream));
-        }
+        ArgumentNullException.ThrowIfNull(licenseStream);
 
         if (licenseStream.CanSeek)
         {
diff --git a/common/ASC.Core.Common/Billing/TariffService.cs b/common/ASC.Core.Common/Billing/TariffService.cs
index d3a9cfc622..51367b7f4b 100644
--- a/common/ASC.Core.Common/Billing/TariffService.cs
+++ b/common/ASC.Core.Common/Billing/TariffService.cs
@@ -40,7 +40,7 @@ public class TariffServiceStorage
             Cache.Remove(TariffService.GetTariffCacheKey(i.TenantId));
             Cache.Remove(TariffService.GetBillingUrlCacheKey(i.TenantId));
             Cache.Remove(TariffService.GetBillingPaymentCacheKey(i.TenantId)); // clear all payments
-            }, CacheNotifyAction.Remove);
+        }, CacheNotifyAction.Remove);
 
         //TODO: Change code of WCF -> not supported in .NET standard/.Net Core
         /*try
@@ -259,10 +259,7 @@ public class TariffService : ITariffService
 
     public void SetTariff(int tenantId, Tariff tariff)
     {
-        if (tariff == null)
-        {
-            throw new ArgumentNullException(nameof(tariff));
-        }
+        ArgumentNullException.ThrowIfNull(tariff);
 
         var q = QuotaService.GetTenantQuota(tariff.QuotaId);
         if (q == null)
@@ -423,10 +420,8 @@ public class TariffService : ITariffService
 
     public IDictionary<string, Dictionary<string, decimal>> GetProductPriceInfo(params string[] productIds)
     {
-        if (productIds == null)
-        {
-            throw new ArgumentNullException(nameof(productIds));
-        }
+        ArgumentNullException.ThrowIfNull(productIds);
+
         try
         {
             var key = "biling-prices" + string.Join(",", productIds);
diff --git a/common/ASC.Core.Common/Context/Impl/CoreConfiguration.cs b/common/ASC.Core.Common/Context/Impl/CoreConfiguration.cs
index d20f93c2a3..c3e83b34e1 100644
--- a/common/ASC.Core.Common/Context/Impl/CoreConfiguration.cs
+++ b/common/ASC.Core.Common/Context/Impl/CoreConfiguration.cs
@@ -151,10 +151,7 @@ public class CoreSettings
 
     public void SaveSetting(string key, string value, int tenant = Tenant.DefaultTenant)
     {
-        if (string.IsNullOrEmpty(key))
-        {
-            throw new ArgumentNullException(nameof(key));
-        }
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(key);
 
         byte[] bytes = null;
         if (value != null)
@@ -167,10 +164,7 @@ public class CoreSettings
 
     public string GetSetting(string key, int tenant = Tenant.DefaultTenant)
     {
-        if (string.IsNullOrEmpty(key))
-        {
-            throw new ArgumentNullException(nameof(key));
-        }
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(key);
 
         var bytes = TenantService.GetTenantSettings(tenant, key);
 
diff --git a/common/ASC.Core.Common/Context/Impl/PaymentManager.cs b/common/ASC.Core.Common/Context/Impl/PaymentManager.cs
index afaf456735..e2fb89b8d8 100644
--- a/common/ASC.Core.Common/Context/Impl/PaymentManager.cs
+++ b/common/ASC.Core.Common/Context/Impl/PaymentManager.cs
@@ -84,10 +84,7 @@ public class PaymentManager
 
     public void ActivateKey(string key)
     {
-        if (string.IsNullOrEmpty(key))
-        {
-            throw new ArgumentNullException(nameof(key));
-        }
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(key);
 
         var now = DateTime.UtcNow;
         var actionUrl = "/partnerapi/ActivateKey?code=" + HttpUtility.UrlEncode(key) + "&portal=" + HttpUtility.UrlEncode(_tenantManager.GetCurrentTenant().Alias);
diff --git a/common/ASC.Core.Common/Context/Impl/TenantManager.cs b/common/ASC.Core.Common/Context/Impl/TenantManager.cs
index cf23b78328..a0e761b808 100644
--- a/common/ASC.Core.Common/Context/Impl/TenantManager.cs
+++ b/common/ASC.Core.Common/Context/Impl/TenantManager.cs
@@ -185,10 +185,7 @@ public class TenantManager
 
     public Tenant SetTenantVersion(Tenant tenant, int version)
     {
-        if (tenant == null)
-        {
-            throw new ArgumentNullException(nameof(tenant));
-        }
+        ArgumentNullException.ThrowIfNull(tenant);
 
         if (tenant.Version != version)
         {
diff --git a/common/ASC.Core.Common/Context/SecurityContext.cs b/common/ASC.Core.Common/Context/SecurityContext.cs
index 5bc341eaeb..7ceeee45cd 100644
--- a/common/ASC.Core.Common/Context/SecurityContext.cs
+++ b/common/ASC.Core.Common/Context/SecurityContext.cs
@@ -80,15 +80,8 @@ public class SecurityContext
 
     public string AuthenticateMe(string login, string passwordHash)
     {
-        if (login == null)
-        {
-            throw new ArgumentNullException(nameof(login));
-        }
-
-        if (passwordHash == null)
-        {
-            throw new ArgumentNullException(nameof(passwordHash));
-        }
+        ArgumentNullException.ThrowIfNull(login);
+        ArgumentNullException.ThrowIfNull(passwordHash);
 
         var tenantid = _tenantManager.GetCurrentTenant().Id;
         var u = _userManager.GetUsersByPasswordHash(tenantid, login, passwordHash);
@@ -109,10 +102,7 @@ public class SecurityContext
                 {
                     var request = _httpContextAccessor?.HttpContext.Request;
 
-                    if (request == null)
-                    {
-                        throw new ArgumentNullException(nameof(request));
-                    }
+                    ArgumentNullException.ThrowIfNull(request);
 
                     ipFrom = "from " + (request.Headers["X-Forwarded-For"].ToString() ?? request.GetUserHostAddress());
                     address = "for " + request.GetUrlRewriter();
@@ -170,10 +160,7 @@ public class SecurityContext
                 {
                     var request = _httpContextAccessor?.HttpContext.Request;
 
-                    if (request == null)
-                    {
-                        throw new ArgumentNullException(nameof(request));
-                    }
+                    ArgumentNullException.ThrowIfNull(request);
 
                     address = "for " + request.GetUrlRewriter();
                     ipFrom = "from " + (request.Headers["X-Forwarded-For"].ToString() ?? request.GetUserHostAddress());
diff --git a/common/ASC.Core.Common/Core/DBResourceManager.cs b/common/ASC.Core.Common/Core/DBResourceManager.cs
index 3457abeccf..dc78115205 100644
--- a/common/ASC.Core.Common/Core/DBResourceManager.cs
+++ b/common/ASC.Core.Common/Core/DBResourceManager.cs
@@ -145,14 +145,8 @@ public class DBResourceManager : ResourceManager
             CultureInfo culture,
             string filename)
         {
-            if (culture == null)
-            {
-                throw new ArgumentNullException(nameof(culture));
-            }
-            if (string.IsNullOrEmpty(filename))
-            {
-                throw new ArgumentNullException(nameof(filename));
-            }
+            ArgumentNullException.ThrowIfNull(culture);
+            ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(filename);
 
             _dbContext = dbContext;
             _logger = option.CurrentValue;
diff --git a/common/ASC.Core.Common/Data/DbQuotaService.cs b/common/ASC.Core.Common/Data/DbQuotaService.cs
index 7f8c4e7c88..4b0413d09d 100644
--- a/common/ASC.Core.Common/Data/DbQuotaService.cs
+++ b/common/ASC.Core.Common/Data/DbQuotaService.cs
@@ -23,8 +23,6 @@
  *
 */
 
-using System.Diagnostics.Metrics;
-
 using AutoMapper.QueryableExtensions;
 
 namespace ASC.Core.Data;
@@ -81,10 +79,7 @@ class DbQuotaService : IQuotaService
 
     public TenantQuota SaveTenantQuota(TenantQuota quota)
     {
-        if (quota == null)
-        {
-            throw new ArgumentNullException(nameof(quota));
-        }
+        ArgumentNullException.ThrowIfNull(quota);
 
         CoreDbContext.AddOrUpdate(r => r.Quotas, _mapper.Map<TenantQuota, DbQuota>(quota));
         CoreDbContext.SaveChanges();
@@ -111,10 +106,7 @@ class DbQuotaService : IQuotaService
 
     public void SetTenantQuotaRow(TenantQuotaRow row, bool exchange)
     {
-        if (row == null)
-        {
-            throw new ArgumentNullException(nameof(row));
-        }
+        ArgumentNullException.ThrowIfNull(row);
 
         using var tx = CoreDbContext.Database.BeginTransaction();
 
diff --git a/common/ASC.Core.Common/Data/DbSettingsManager.cs b/common/ASC.Core.Common/Data/DbSettingsManager.cs
index bbe1248b18..02f169b40f 100644
--- a/common/ASC.Core.Common/Data/DbSettingsManager.cs
+++ b/common/ASC.Core.Common/Data/DbSettingsManager.cs
@@ -169,10 +169,7 @@ public class DbSettingsManager
 
     public bool SaveSettingsFor<T>(T settings, int tenantId, Guid userId) where T : ISettings
     {
-        if (settings == null)
-        {
-            throw new ArgumentNullException(nameof(settings));
-        }
+        ArgumentNullException.ThrowIfNull(settings);
 
         try
         {
diff --git a/common/ASC.Core.Common/Data/DbSubscriptionService.cs b/common/ASC.Core.Common/Data/DbSubscriptionService.cs
index 0557802ff9..3a9c9ca6bb 100644
--- a/common/ASC.Core.Common/Data/DbSubscriptionService.cs
+++ b/common/ASC.Core.Common/Data/DbSubscriptionService.cs
@@ -40,14 +40,8 @@ public class DbSubscriptionService : ISubscriptionService
 
     public string[] GetRecipients(int tenant, string sourceId, string actionId, string objectId)
     {
-        if (sourceId == null)
-        {
-            throw new ArgumentNullException(nameof(sourceId));
-        }
-        if (actionId == null)
-        {
-            throw new ArgumentNullException(nameof(actionId));
-        }
+        ArgumentNullException.ThrowIfNull(sourceId);
+        ArgumentNullException.ThrowIfNull(actionId);
 
         var q = GetQuery(tenant, sourceId, actionId)
             .Where(r => r.Object == (objectId ?? string.Empty))
@@ -60,14 +54,8 @@ public class DbSubscriptionService : ISubscriptionService
 
     public IEnumerable<SubscriptionRecord> GetSubscriptions(int tenant, string sourceId, string actionId)
     {
-        if (sourceId == null)
-        {
-            throw new ArgumentNullException(nameof(sourceId));
-        }
-        if (actionId == null)
-        {
-            throw new ArgumentNullException(nameof(actionId));
-        }
+        ArgumentNullException.ThrowIfNull(sourceId);
+        ArgumentNullException.ThrowIfNull(actionId);
 
         var q = GetQuery(tenant, sourceId, actionId);
 
@@ -92,10 +80,7 @@ public class DbSubscriptionService : ISubscriptionService
 
     public SubscriptionRecord GetSubscription(int tenant, string sourceId, string actionId, string recipientId, string objectId)
     {
-        if (recipientId == null)
-        {
-            throw new ArgumentNullException(nameof(recipientId));
-        }
+        ArgumentNullException.ThrowIfNull(recipientId);
 
         var q = GetQuery(tenant, sourceId, actionId)
             .Where(r => r.Recipient == recipientId)
@@ -106,18 +91,9 @@ public class DbSubscriptionService : ISubscriptionService
 
     public bool IsUnsubscribe(int tenant, string sourceId, string actionId, string recipientId, string objectId)
     {
-        if (recipientId == null)
-        {
-            throw new ArgumentNullException(nameof(recipientId));
-        }
-        if (sourceId == null)
-        {
-            throw new ArgumentNullException(nameof(sourceId));
-        }
-        if (actionId == null)
-        {
-            throw new ArgumentNullException(nameof(actionId));
-        }
+        ArgumentNullException.ThrowIfNull(recipientId);
+        ArgumentNullException.ThrowIfNull(sourceId);
+        ArgumentNullException.ThrowIfNull(actionId);
 
         var q = UserDbContext.Subscriptions
             .Where(r => r.Source == sourceId &&
@@ -140,18 +116,9 @@ public class DbSubscriptionService : ISubscriptionService
 
     public string[] GetSubscriptions(int tenant, string sourceId, string actionId, string recipientId, bool checkSubscribe)
     {
-        if (recipientId == null)
-        {
-            throw new ArgumentNullException(nameof(recipientId));
-        }
-        if (sourceId == null)
-        {
-            throw new ArgumentNullException(nameof(sourceId));
-        }
-        if (actionId == null)
-        {
-            throw new ArgumentNullException(nameof(actionId));
-        }
+        ArgumentNullException.ThrowIfNull(recipientId);
+        ArgumentNullException.ThrowIfNull(sourceId);
+        ArgumentNullException.ThrowIfNull(actionId);
 
         var q = GetQuery(tenant, sourceId, actionId)
             .Where(r => r.Recipient == recipientId)
@@ -168,10 +135,7 @@ public class DbSubscriptionService : ISubscriptionService
 
     public void SaveSubscription(SubscriptionRecord s)
     {
-        if (s == null)
-        {
-            throw new ArgumentNullException(nameof(s));
-        }
+        ArgumentNullException.ThrowIfNull(s);
 
         var subs = new Subscription
         {
@@ -194,15 +158,8 @@ public class DbSubscriptionService : ISubscriptionService
 
     public void RemoveSubscriptions(int tenant, string sourceId, string actionId, string objectId)
     {
-        if (sourceId == null)
-        {
-            throw new ArgumentNullException(nameof(sourceId));
-        }
-
-        if (actionId == null)
-        {
-            throw new ArgumentNullException(nameof(actionId));
-        }
+        ArgumentNullException.ThrowIfNull(sourceId);
+        ArgumentNullException.ThrowIfNull(actionId);
 
         using var tr = UserDbContext.Database.BeginTransaction();
         var q = UserDbContext.Subscriptions
@@ -228,14 +185,8 @@ public class DbSubscriptionService : ISubscriptionService
 
     public IEnumerable<SubscriptionMethod> GetSubscriptionMethods(int tenant, string sourceId, string actionId, string recipientId)
     {
-        if (sourceId == null)
-        {
-            throw new ArgumentNullException(nameof(sourceId));
-        }
-        if (actionId == null)
-        {
-            throw new ArgumentNullException(nameof(actionId));
-        }
+        ArgumentNullException.ThrowIfNull(sourceId);
+        ArgumentNullException.ThrowIfNull(actionId);
 
         var q = UserDbContext.SubscriptionMethods
             .Where(r => r.Tenant == -1 || r.Tenant == tenant)
@@ -278,10 +229,7 @@ public class DbSubscriptionService : ISubscriptionService
 
     public void SetSubscriptionMethod(SubscriptionMethod m)
     {
-        if (m == null)
-        {
-            throw new ArgumentNullException(nameof(m));
-        }
+        ArgumentNullException.ThrowIfNull(m);
 
         using var tr = UserDbContext.Database.BeginTransaction();
 
@@ -320,14 +268,8 @@ public class DbSubscriptionService : ISubscriptionService
 
     private IQueryable<Subscription> GetQuery(int tenant, string sourceId, string actionId)
     {
-        if (sourceId == null)
-        {
-            throw new ArgumentNullException(nameof(sourceId));
-        }
-        if (actionId == null)
-        {
-            throw new ArgumentNullException(nameof(actionId));
-        }
+        ArgumentNullException.ThrowIfNull(sourceId);
+        ArgumentNullException.ThrowIfNull(actionId);
 
         return
             UserDbContext.Subscriptions
diff --git a/common/ASC.Core.Common/Data/DbTenantService.cs b/common/ASC.Core.Common/Data/DbTenantService.cs
index b1cfe0ab2b..4c74864c37 100644
--- a/common/ASC.Core.Common/Data/DbTenantService.cs
+++ b/common/ASC.Core.Common/Data/DbTenantService.cs
@@ -114,10 +114,7 @@ public class DbTenantService : ITenantService
 
     public IEnumerable<Tenant> GetTenants(string login, string passwordHash)
     {
-        if (string.IsNullOrEmpty(login))
-        {
-            throw new ArgumentNullException(nameof(login));
-        }
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(login);
 
         IQueryable<TenantUserSecurity> query() => TenantsQuery()
                 .Where(r => r.Status == TenantStatus.Active)
@@ -205,10 +202,7 @@ public class DbTenantService : ITenantService
 
     public Tenant GetTenant(string domain)
     {
-        if (string.IsNullOrEmpty(domain))
-        {
-            throw new ArgumentNullException(nameof(domain));
-        }
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(domain);
 
         domain = domain.ToLowerInvariant();
 
@@ -229,79 +223,76 @@ public class DbTenantService : ITenantService
             .FirstOrDefault();
     }
 
-    public Tenant SaveTenant(CoreSettings coreSettings, Tenant t)
+    public Tenant SaveTenant(CoreSettings coreSettings, Tenant tenant)
     {
-        if (t == null)
-        {
-            throw new ArgumentNullException("tenant");
-        }
+        ArgumentNullException.ThrowIfNull(tenant);
 
         using var tx = TenantDbContext.Database.BeginTransaction();
 
-        if (!string.IsNullOrEmpty(t.MappedDomain))
+        if (!string.IsNullOrEmpty(tenant.MappedDomain))
         {
-            var baseUrl = coreSettings.GetBaseDomain(t.HostedRegion);
+            var baseUrl = coreSettings.GetBaseDomain(tenant.HostedRegion);
 
-            if (baseUrl != null && t.MappedDomain.EndsWith("." + baseUrl, StringComparison.InvariantCultureIgnoreCase))
+            if (baseUrl != null && tenant.MappedDomain.EndsWith("." + baseUrl, StringComparison.InvariantCultureIgnoreCase))
             {
-                ValidateDomain(t.MappedDomain.Substring(0, t.MappedDomain.Length - baseUrl.Length - 1), t.Id, false);
+                ValidateDomain(tenant.MappedDomain.Substring(0, tenant.MappedDomain.Length - baseUrl.Length - 1), tenant.Id, false);
             }
             else
             {
-                ValidateDomain(t.MappedDomain, t.Id, false);
+                ValidateDomain(tenant.MappedDomain, tenant.Id, false);
             }
         }
 
-        if (t.Id == Tenant.DefaultTenant)
+        if (tenant.Id == Tenant.DefaultTenant)
         {
-            t.Version = TenantDbContext.TenantVersion
+            tenant.Version = TenantDbContext.TenantVersion
                 .Where(r => r.DefaultVersion == 1 || r.Id == 0)
                 .OrderByDescending(r => r.Id)
                 .Select(r => r.Id)
                 .FirstOrDefault();
 
-            t.LastModified = DateTime.UtcNow;
+            tenant.LastModified = DateTime.UtcNow;
 
-            var tenant = _mapper.Map<Tenant, DbTenant>(t);
+            var dbTenant = _mapper.Map<Tenant, DbTenant>(tenant);
 
-            tenant = TenantDbContext.Tenants.Add(tenant).Entity;
+            dbTenant = TenantDbContext.Tenants.Add(dbTenant).Entity;
             TenantDbContext.SaveChanges();
-            t.Id = tenant.Id;
+            tenant.Id = dbTenant.Id;
         }
         else
         {
-            var tenant = TenantDbContext.Tenants
-                .Where(r => r.Id == t.Id)
+            var dbTenant = TenantDbContext.Tenants
+                .Where(r => r.Id == tenant.Id)
                 .FirstOrDefault();
 
-            if (tenant != null)
+            if (dbTenant != null)
             {
-                tenant.Alias = t.Alias.ToLowerInvariant();
-                tenant.MappedDomain = !string.IsNullOrEmpty(t.MappedDomain) ? t.MappedDomain.ToLowerInvariant() : null;
-                tenant.Version = t.Version;
-                tenant.VersionChanged = t.VersionChanged;
-                tenant.Name = t.Name ?? t.Alias;
-                tenant.Language = t.Language;
-                tenant.TimeZone = t.TimeZone;
-                tenant.TrustedDomainsRaw = t.GetTrustedDomains();
-                tenant.TrustedDomainsEnabled = t.TrustedDomainsType;
-                tenant.CreationDateTime = t.CreationDateTime;
-                tenant.Status = t.Status;
-                tenant.StatusChanged = t.StatusChangeDate;
-                tenant.PaymentId = t.PaymentId;
-                tenant.LastModified = t.LastModified = DateTime.UtcNow;
-                tenant.Industry = t.Industry;
-                tenant.Spam = t.Spam;
-                tenant.Calls = t.Calls;
+                dbTenant.Alias = tenant.Alias.ToLowerInvariant();
+                dbTenant.MappedDomain = !string.IsNullOrEmpty(tenant.MappedDomain) ? tenant.MappedDomain.ToLowerInvariant() : null;
+                dbTenant.Version = tenant.Version;
+                dbTenant.VersionChanged = tenant.VersionChanged;
+                dbTenant.Name = tenant.Name ?? tenant.Alias;
+                dbTenant.Language = tenant.Language;
+                dbTenant.TimeZone = tenant.TimeZone;
+                dbTenant.TrustedDomainsRaw = tenant.GetTrustedDomains();
+                dbTenant.TrustedDomainsEnabled = tenant.TrustedDomainsType;
+                dbTenant.CreationDateTime = tenant.CreationDateTime;
+                dbTenant.Status = tenant.Status;
+                dbTenant.StatusChanged = tenant.StatusChangeDate;
+                dbTenant.PaymentId = tenant.PaymentId;
+                dbTenant.LastModified = tenant.LastModified = DateTime.UtcNow;
+                dbTenant.Industry = tenant.Industry;
+                dbTenant.Spam = tenant.Spam;
+                dbTenant.Calls = tenant.Calls;
             }
 
             TenantDbContext.SaveChanges();
         }
 
-        if (string.IsNullOrEmpty(t.PartnerId) && string.IsNullOrEmpty(t.AffiliateId) && string.IsNullOrEmpty(t.Campaign))
+        if (string.IsNullOrEmpty(tenant.PartnerId) && string.IsNullOrEmpty(tenant.AffiliateId) && string.IsNullOrEmpty(tenant.Campaign))
         {
             var p = TenantDbContext.TenantPartner
-                .Where(r => r.TenantId == t.Id)
+                .Where(r => r.TenantId == tenant.Id)
                 .FirstOrDefault();
 
             if (p != null)
@@ -313,10 +304,10 @@ public class DbTenantService : ITenantService
         {
             var tenantPartner = new DbTenantPartner
             {
-                TenantId = t.Id,
-                PartnerId = t.PartnerId,
-                AffiliateId = t.AffiliateId,
-                Campaign = t.Campaign
+                TenantId = tenant.Id,
+                PartnerId = tenant.PartnerId,
+                AffiliateId = tenant.AffiliateId,
+                Campaign = tenant.Campaign
             };
 
             TenantDbContext.TenantPartner.Add(tenantPartner);
@@ -325,7 +316,7 @@ public class DbTenantService : ITenantService
         tx.Commit();
 
         //CalculateTenantDomain(t);
-        return t;
+        return tenant;
     }
 
     public void RemoveTenant(int id, bool auto = false)
diff --git a/common/ASC.Core.Common/Data/DbUserService.cs b/common/ASC.Core.Common/Data/DbUserService.cs
index 4d01318e56..d1e50fe966 100644
--- a/common/ASC.Core.Common/Data/DbUserService.cs
+++ b/common/ASC.Core.Common/Data/DbUserService.cs
@@ -115,10 +115,7 @@ public class EFUserService : IUserService
 
     public UserInfo GetUserByPasswordHash(int tenant, string login, string passwordHash)
     {
-        if (string.IsNullOrEmpty(login))
-        {
-            throw new ArgumentNullException(nameof(login));
-        }
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(login);
 
         if (Guid.TryParse(login, out var userId))
         {
@@ -430,10 +427,7 @@ public class EFUserService : IUserService
 
     public Group SaveGroup(int tenant, Group group)
     {
-        if (group == null)
-        {
-            throw new ArgumentNullException(nameof(group));
-        }
+        ArgumentNullException.ThrowIfNull(group);
 
         if (group.Id == default)
         {
@@ -452,10 +446,7 @@ public class EFUserService : IUserService
 
     public UserInfo SaveUser(int tenant, UserInfo user)
     {
-        if (user == null)
-        {
-            throw new ArgumentNullException(nameof(user));
-        }
+        ArgumentNullException.ThrowIfNull(user);
 
         if (string.IsNullOrEmpty(user.UserName))
         {
@@ -501,29 +492,26 @@ public class EFUserService : IUserService
         return user;
     }
 
-    public UserGroupRef SaveUserGroupRef(int tenant, UserGroupRef r)
+    public UserGroupRef SaveUserGroupRef(int tenant, UserGroupRef userGroupRef)
     {
-        if (r == null)
-        {
-            throw new ArgumentNullException("userGroupRef");
-        }
+        ArgumentNullException.ThrowIfNull(userGroupRef);
 
-        r.LastModified = DateTime.UtcNow;
-        r.Tenant = tenant;
+        userGroupRef.LastModified = DateTime.UtcNow;
+        userGroupRef.Tenant = tenant;
 
         using var tr = UserDbContext.Database.BeginTransaction();
 
-        var user = GetUserQuery(tenant).FirstOrDefault(a => a.Tenant == tenant && a.Id == r.UserId);
+        var user = GetUserQuery(tenant).FirstOrDefault(a => a.Tenant == tenant && a.Id == userGroupRef.UserId);
         if (user != null)
         {
-            user.LastModified = r.LastModified;
-            UserDbContext.AddOrUpdate(r => r.UserGroups, _mapper.Map<UserGroupRef, UserGroup>(r));
+            user.LastModified = userGroupRef.LastModified;
+            UserDbContext.AddOrUpdate(r => r.UserGroups, _mapper.Map<UserGroupRef, UserGroup>(userGroupRef));
         }
 
         UserDbContext.SaveChanges();
         tr.Commit();
 
-        return r;
+        return userGroupRef;
     }
 
     public void SetUserPasswordHash(int tenant, Guid id, string passwordHash)
diff --git a/common/ASC.Core.Common/HostedSolution.cs b/common/ASC.Core.Common/HostedSolution.cs
index c08f90505f..e5b1fac319 100644
--- a/common/ASC.Core.Common/HostedSolution.cs
+++ b/common/ASC.Core.Common/HostedSolution.cs
@@ -143,51 +143,49 @@ public class HostedSolution
         TenantService.ValidateDomain(address);
     }
 
-    public void RegisterTenant(TenantRegistrationInfo ri, out Tenant tenant)
+    public void RegisterTenant(TenantRegistrationInfo registrationInfo, out Tenant tenant)
     {
-        if (ri == null)
-        {
-            throw new ArgumentNullException("registrationInfo");
-        }
-        if (string.IsNullOrEmpty(ri.Address))
+        ArgumentNullException.ThrowIfNull(registrationInfo);
+
+        if (string.IsNullOrEmpty(registrationInfo.Address))
         {
             throw new Exception("Address can not be empty");
         }
-        if (string.IsNullOrEmpty(ri.Email))
+        if (string.IsNullOrEmpty(registrationInfo.Email))
         {
             throw new Exception("Account email can not be empty");
         }
-        if (ri.FirstName == null)
+        if (registrationInfo.FirstName == null)
         {
             throw new Exception("Account firstname can not be empty");
         }
-        if (ri.LastName == null)
+        if (registrationInfo.LastName == null)
         {
             throw new Exception("Account lastname can not be empty");
         }
-        if (!UserFormatter.IsValidUserName(ri.FirstName, ri.LastName))
+        if (!UserFormatter.IsValidUserName(registrationInfo.FirstName, registrationInfo.LastName))
         {
             throw new Exception("Incorrect firstname or lastname");
         }
 
-        if (string.IsNullOrEmpty(ri.PasswordHash))
+        if (string.IsNullOrEmpty(registrationInfo.PasswordHash))
         {
-            ri.PasswordHash = Guid.NewGuid().ToString();
+            registrationInfo.PasswordHash = Guid.NewGuid().ToString();
         }
 
         // create tenant
-        tenant = new Tenant(ri.Address.ToLowerInvariant())
+        tenant = new Tenant(registrationInfo.Address.ToLowerInvariant())
         {
-            Name = ri.Name,
-            Language = ri.Culture.Name,
-            TimeZone = ri.TimeZoneInfo.Id,
-            HostedRegion = ri.HostedRegion,
-            PartnerId = ri.PartnerId,
-            AffiliateId = ri.AffiliateId,
-            Campaign = ri.Campaign,
-            Industry = ri.Industry,
-            Spam = ri.Spam,
-            Calls = ri.Calls
+            Name = registrationInfo.Name,
+            Language = registrationInfo.Culture.Name,
+            TimeZone = registrationInfo.TimeZoneInfo.Id,
+            HostedRegion = registrationInfo.HostedRegion,
+            PartnerId = registrationInfo.PartnerId,
+            AffiliateId = registrationInfo.AffiliateId,
+            Campaign = registrationInfo.Campaign,
+            Industry = registrationInfo.Industry,
+            Spam = registrationInfo.Spam,
+            Calls = registrationInfo.Calls
         };
 
         tenant = TenantService.SaveTenant(CoreSettings, tenant);
@@ -195,24 +193,24 @@ public class HostedSolution
         // create user
         var user = new UserInfo
         {
-            UserName = ri.Email.Substring(0, ri.Email.IndexOf('@')),
-            LastName = ri.LastName,
-            FirstName = ri.FirstName,
-            Email = ri.Email,
-            MobilePhone = ri.MobilePhone,
+            UserName = registrationInfo.Email.Substring(0, registrationInfo.Email.IndexOf('@')),
+            LastName = registrationInfo.LastName,
+            FirstName = registrationInfo.FirstName,
+            Email = registrationInfo.Email,
+            MobilePhone = registrationInfo.MobilePhone,
             WorkFromDate = TenantUtil.DateTimeNow(tenant.TimeZone),
-            ActivationStatus = ri.ActivationStatus
+            ActivationStatus = registrationInfo.ActivationStatus
         };
 
         user = UserService.SaveUser(tenant.Id, user);
-        UserService.SetUserPasswordHash(tenant.Id, user.Id, ri.PasswordHash);
+        UserService.SetUserPasswordHash(tenant.Id, user.Id, registrationInfo.PasswordHash);
         UserService.SaveUserGroupRef(tenant.Id, new UserGroupRef(user.Id, Constants.GroupAdmin.ID, UserGroupRefType.Contains));
 
         // save tenant owner
         tenant.OwnerId = user.Id;
         tenant = TenantService.SaveTenant(CoreSettings, tenant);
 
-        SettingsManager.SaveSettings(new TenantControlPanelSettings { LimitedAccess = ri.LimitedControlPanel }, tenant.Id);
+        SettingsManager.SaveSettings(new TenantControlPanelSettings { LimitedAccess = registrationInfo.LimitedControlPanel }, tenant.Id);
     }
 
     public Tenant SaveTenant(Tenant tenant)
diff --git a/common/ASC.Core.Common/Notify/Channels/SenderChannel.cs b/common/ASC.Core.Common/Notify/Channels/SenderChannel.cs
index 933df862f7..3fd2d3e605 100644
--- a/common/ASC.Core.Common/Notify/Channels/SenderChannel.cs
+++ b/common/ASC.Core.Common/Notify/Channels/SenderChannel.cs
@@ -47,10 +47,7 @@ public class SenderChannel : ISenderChannel
 
     public void SendAsync(INoticeMessage message)
     {
-        if (message == null)
-        {
-            throw new ArgumentNullException(nameof(message));
-        }
+        ArgumentNullException.ThrowIfNull(message);
 
         _firstSink.ProcessMessageAsync(message);
     }
diff --git a/common/ASC.Core.Common/Notify/DirectSubscriptionProvider.cs b/common/ASC.Core.Common/Notify/DirectSubscriptionProvider.cs
index 156df0e0fc..63bbf0457f 100644
--- a/common/ASC.Core.Common/Notify/DirectSubscriptionProvider.cs
+++ b/common/ASC.Core.Common/Notify/DirectSubscriptionProvider.cs
@@ -34,7 +34,7 @@ class DirectSubscriptionProvider : ISubscriptionProvider
 
     public DirectSubscriptionProvider(string sourceID, SubscriptionManager subscriptionManager, IRecipientProvider recipientProvider)
     {
-        if (string.IsNullOrEmpty(sourceID)) throw new ArgumentNullException(nameof(sourceID));
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(sourceID);
         _sourceId = sourceID;
         _subscriptionManager = subscriptionManager ?? throw new ArgumentNullException(nameof(subscriptionManager));
         _recipientProvider = recipientProvider ?? throw new ArgumentNullException(nameof(recipientProvider));
@@ -43,40 +43,23 @@ class DirectSubscriptionProvider : ISubscriptionProvider
 
     public object GetSubscriptionRecord(INotifyAction action, IRecipient recipient, string objectID)
     {
-        if (action == null)
-        {
-            throw new ArgumentNullException(nameof(action));
-        }
-
-        if (recipient == null)
-        {
-            throw new ArgumentNullException(nameof(recipient));
-        }
+        ArgumentNullException.ThrowIfNull(action);
+        ArgumentNullException.ThrowIfNull(recipient);
 
         return _subscriptionManager.GetSubscriptionRecord(_sourceId, action.ID, recipient.ID, objectID);
     }
 
     public string[] GetSubscriptions(INotifyAction action, IRecipient recipient, bool checkSubscribe = true)
     {
-        if (action == null)
-        {
-            throw new ArgumentNullException(nameof(action));
-        }
-
-        if (recipient == null)
-        {
-            throw new ArgumentNullException(nameof(recipient));
-        }
+        ArgumentNullException.ThrowIfNull(action);
+        ArgumentNullException.ThrowIfNull(recipient);
 
         return _subscriptionManager.GetSubscriptions(_sourceId, action.ID, recipient.ID, checkSubscribe);
     }
 
     public IRecipient[] GetRecipients(INotifyAction action, string objectID)
     {
-        if (action == null)
-        {
-            throw new ArgumentNullException(nameof(action));
-        }
+        ArgumentNullException.ThrowIfNull(action);
 
         return _subscriptionManager.GetRecipients(_sourceId, action.ID, objectID)
             .Select(r => _recipientProvider.GetRecipient(r))
@@ -86,90 +69,54 @@ class DirectSubscriptionProvider : ISubscriptionProvider
 
     public string[] GetSubscriptionMethod(INotifyAction action, IRecipient recipient)
     {
-        if (action == null)
-        {
-            throw new ArgumentNullException(nameof(action));
-        }
-        if (recipient == null)
-        {
-            throw new ArgumentNullException(nameof(recipient));
-        }
+        ArgumentNullException.ThrowIfNull(action);
+        ArgumentNullException.ThrowIfNull(recipient);
 
         return _subscriptionManager.GetSubscriptionMethod(_sourceId, action.ID, recipient.ID);
     }
 
     public void UpdateSubscriptionMethod(INotifyAction action, IRecipient recipient, params string[] senderNames)
     {
-        if (action == null)
-        {
-            throw new ArgumentNullException(nameof(action));
-        }
-        if (recipient == null)
-        {
-            throw new ArgumentNullException(nameof(recipient));
-        }
+        ArgumentNullException.ThrowIfNull(action);
+        ArgumentNullException.ThrowIfNull(recipient);
 
         _subscriptionManager.UpdateSubscriptionMethod(_sourceId, action.ID, recipient.ID, senderNames);
     }
 
     public bool IsUnsubscribe(IDirectRecipient recipient, INotifyAction action, string objectID)
     {
-        if (recipient == null)
-        {
-            throw new ArgumentNullException(nameof(recipient));
-        }
-        if (action == null)
-        {
-            throw new ArgumentNullException(nameof(action));
-        }
+        ArgumentNullException.ThrowIfNull(recipient);
+        ArgumentNullException.ThrowIfNull(action);
 
         return _subscriptionManager.IsUnsubscribe(_sourceId, recipient.ID, action.ID, objectID);
     }
 
     public void Subscribe(INotifyAction action, string objectID, IRecipient recipient)
     {
-        if (action == null)
-        {
-            throw new ArgumentNullException(nameof(action));
-        }
-        if (recipient == null)
-        {
-            throw new ArgumentNullException(nameof(recipient));
-        }
+        ArgumentNullException.ThrowIfNull(action);
+        ArgumentNullException.ThrowIfNull(recipient);
 
         _subscriptionManager.Subscribe(_sourceId, action.ID, objectID, recipient.ID);
     }
 
     public void UnSubscribe(INotifyAction action, string objectID, IRecipient recipient)
     {
-        if (action == null)
-        {
-            throw new ArgumentNullException(nameof(action));
-        }
-        if (recipient == null)
-        {
-            throw new ArgumentNullException(nameof(recipient));
-        }
+        ArgumentNullException.ThrowIfNull(action);
+        ArgumentNullException.ThrowIfNull(recipient);
 
         _subscriptionManager.Unsubscribe(_sourceId, action.ID, objectID, recipient.ID);
     }
 
     public void UnSubscribe(INotifyAction action)
     {
-        if (action == null)
-        {
-            throw new ArgumentNullException(nameof(action));
-        }
+        ArgumentNullException.ThrowIfNull(action);
 
         _subscriptionManager.UnsubscribeAll(_sourceId, action.ID);
     }
 
     public void UnSubscribe(INotifyAction action, string objectID)
     {
-        if (action == null)
-        {
-            throw new ArgumentNullException(nameof(action));
-        }
+        ArgumentNullException.ThrowIfNull(action);
 
         _subscriptionManager.UnsubscribeAll(_sourceId, action.ID, objectID);
     }
diff --git a/common/ASC.Core.Common/Notify/Engine/InterceptorStorage.cs b/common/ASC.Core.Common/Notify/Engine/InterceptorStorage.cs
index 608bf11f09..8c2b4685f1 100644
--- a/common/ASC.Core.Common/Notify/Engine/InterceptorStorage.cs
+++ b/common/ASC.Core.Common/Notify/Engine/InterceptorStorage.cs
@@ -47,7 +47,7 @@ class InterceptorStorage
 
     public void Add(ISendInterceptor interceptor)
     {
-        if (interceptor == null) throw new ArgumentNullException(nameof(interceptor));
+        ArgumentNullException.ThrowIfNull(interceptor);
         if (string.IsNullOrEmpty(interceptor.Name)) throw new ArgumentException("empty name property", nameof(interceptor));
 
         switch (interceptor.Lifetime)
diff --git a/common/ASC.Core.Common/Notify/Engine/NotifyEngine.cs b/common/ASC.Core.Common/Notify/Engine/NotifyEngine.cs
index 7b48f2671f..ea45ab1fc4 100644
--- a/common/ASC.Core.Common/Notify/Engine/NotifyEngine.cs
+++ b/common/ASC.Core.Common/Notify/Engine/NotifyEngine.cs
@@ -73,15 +73,8 @@ public class NotifyEngine : INotifyEngine
 
     internal void RegisterSendMethod(Action<DateTime> method, string cron)
     {
-        if (method == null)
-        {
-            throw new ArgumentNullException(nameof(method));
-        }
-
-        if (string.IsNullOrEmpty(cron))
-        {
-            throw new ArgumentNullException(nameof(cron));
-        }
+        ArgumentNullException.ThrowIfNull(method);
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(cron);
 
         var w = new SendMethodWrapper(method, cron, _logger);
         lock (_sendMethods)
@@ -99,10 +92,7 @@ public class NotifyEngine : INotifyEngine
 
     internal void UnregisterSendMethod(Action<DateTime> method)
     {
-        if (method == null)
-        {
-            throw new ArgumentNullException(nameof(method));
-        }
+        ArgumentNullException.ThrowIfNull(method);
 
         lock (_sendMethods)
         {
@@ -418,10 +408,7 @@ public class NotifyEngine : INotifyEngine
 
     private SendResponse CreateNoticeMessageFromNotifyRequest(NotifyRequest request, string sender, IServiceScope serviceScope, out NoticeMessage noticeMessage)
     {
-        if (request == null)
-        {
-            throw new ArgumentNullException(nameof(request));
-        }
+        ArgumentNullException.ThrowIfNull(request);
 
         var recipientProvider = request.GetRecipientsProvider(serviceScope);
         var recipient = request.Recipient as IDirectRecipient;
diff --git a/common/ASC.Core.Common/Notify/Engine/NotifyRequest.cs b/common/ASC.Core.Common/Notify/Engine/NotifyRequest.cs
index 64262309f6..5c4c325030 100644
--- a/common/ASC.Core.Common/Notify/Engine/NotifyRequest.cs
+++ b/common/ASC.Core.Common/Notify/Engine/NotifyRequest.cs
@@ -100,10 +100,7 @@ public class NotifyRequest
 
     internal NotifyRequest Split(IRecipient recipient)
     {
-        if (recipient == null)
-        {
-            throw new ArgumentNullException(nameof(recipient));
-        }
+        ArgumentNullException.ThrowIfNull(recipient);
 
         var newRequest = new NotifyRequest(NotifySource, NotifyAction, ObjectID, recipient)
         {
diff --git a/common/ASC.Core.Common/Notify/Engine/SendInterceptorSkeleton.cs b/common/ASC.Core.Common/Notify/Engine/SendInterceptorSkeleton.cs
index f7f0ecefc2..103373fe7d 100644
--- a/common/ASC.Core.Common/Notify/Engine/SendInterceptorSkeleton.cs
+++ b/common/ASC.Core.Common/Notify/Engine/SendInterceptorSkeleton.cs
@@ -37,12 +37,9 @@ public class SendInterceptorSkeleton : ISendInterceptor
         if (string.IsNullOrEmpty(name))
         {
             throw new ArgumentException("Empty name.", nameof(name));
-        }
-
-        if (sendInterceptor == null)
-        {
-            throw new ArgumentNullException(nameof(sendInterceptor));
-        }
+        }
+
+        ArgumentNullException.ThrowIfNull(sendInterceptor);
 
         _method = sendInterceptor;
         Name = name;
diff --git a/common/ASC.Core.Common/Notify/Messages/NoticeMessage.cs b/common/ASC.Core.Common/Notify/Messages/NoticeMessage.cs
index 8e1ddf8798..3de048c790 100644
--- a/common/ASC.Core.Common/Notify/Messages/NoticeMessage.cs
+++ b/common/ASC.Core.Common/Notify/Messages/NoticeMessage.cs
@@ -76,7 +76,8 @@ public class NoticeMessage : INoticeMessage
 
     public void AddArgument(params ITagValue[] tagValues)
     {
-        if (tagValues == null) throw new ArgumentNullException(nameof(tagValues));
+        ArgumentNullException.ThrowIfNull(tagValues);
+
         Array.ForEach(tagValues,
             tagValue =>
             {
diff --git a/common/ASC.Core.Common/Notify/Model/NotifyClientImpl.cs b/common/ASC.Core.Common/Notify/Model/NotifyClientImpl.cs
index 87ba9b6fc8..22b482d2c1 100644
--- a/common/ASC.Core.Common/Notify/Model/NotifyClientImpl.cs
+++ b/common/ASC.Core.Common/Notify/Model/NotifyClientImpl.cs
@@ -98,10 +98,7 @@ class NotifyClientImpl : INotifyClient
 
     public void SendNoticeToAsync(INotifyAction action, string objectID, IRecipient[] recipients, string[] senderNames, bool checkSubsciption, params ITagValue[] args)
     {
-        if (recipients == null)
-        {
-            throw new ArgumentNullException(nameof(recipients));
-        }
+        ArgumentNullException.ThrowIfNull(recipients);
 
         BeginSingleRecipientEvent("__syspreventduplicateinterceptor");
 
@@ -120,14 +117,8 @@ class NotifyClientImpl : INotifyClient
 
     private NotifyRequest CreateRequest(INotifyAction action, string objectID, IRecipient recipient, ITagValue[] args, string[] senders, bool checkSubsciption)
     {
-        if (action == null)
-        {
-            throw new ArgumentNullException(nameof(action));
-        }
-        if (recipient == null)
-        {
-            throw new ArgumentNullException(nameof(recipient));
-        }
+        ArgumentNullException.ThrowIfNull(action);
+        ArgumentNullException.ThrowIfNull(recipient);
 
         var request = new NotifyRequest(_notifySource, action, objectID, recipient)
         {
diff --git a/common/ASC.Core.Common/Notify/NotifySource.cs b/common/ASC.Core.Common/Notify/NotifySource.cs
index e2ccf7303f..b1ec37b44f 100644
--- a/common/ASC.Core.Common/Notify/NotifySource.cs
+++ b/common/ASC.Core.Common/Notify/NotifySource.cs
@@ -41,10 +41,7 @@ public abstract class NotifySource : INotifySource
 
     protected NotifySource(string id, UserManager userManager, IRecipientProvider recipientsProvider, SubscriptionManager subscriptionManager)
     {
-        if (string.IsNullOrEmpty(id))
-        {
-            throw new ArgumentNullException(nameof(id));
-        }
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(id);
 
         Id = id;
         _userManager = userManager;
diff --git a/common/ASC.Core.Common/Notify/Patterns/PatternFormatter.cs b/common/ASC.Core.Common/Notify/Patterns/PatternFormatter.cs
index 18de0ab71d..427f7d48e3 100644
--- a/common/ASC.Core.Common/Notify/Patterns/PatternFormatter.cs
+++ b/common/ASC.Core.Common/Notify/Patterns/PatternFormatter.cs
@@ -52,11 +52,8 @@ public abstract class PatternFormatter : IPatternFormatter
     }
 
     public string[] GetTags(IPattern pattern)
-    {
-        if (pattern == null)
-        {
-            throw new ArgumentNullException(nameof(pattern));
-        }
+    {
+        ArgumentNullException.ThrowIfNull(pattern);
 
         var findedTags = new List<string>(SearchTags(pattern.Body));
         Array.ForEach(SearchTags(pattern.Subject), tag => { if (!findedTags.Contains(tag)) findedTags.Add(tag); });
@@ -64,19 +61,10 @@ public abstract class PatternFormatter : IPatternFormatter
     }
 
     public void FormatMessage(INoticeMessage message, ITagValue[] tagsValues)
-    {
-        if (message == null)
-        {
-            throw new ArgumentNullException(nameof(message));
-        }
-        if (message.Pattern == null)
-        {
-            throw new ArgumentException(nameof(message));
-        }
-        if (tagsValues == null)
-        {
-            throw new ArgumentNullException(nameof(tagsValues));
-        }
+    {
+        ArgumentNullException.ThrowIfNull(message);
+        ArgumentNullException.ThrowIfNull(message.Pattern);
+        ArgumentNullException.ThrowIfNull(tagsValues);
 
         BeforeFormat(message, tagsValues);
 
diff --git a/common/ASC.Core.Common/Notify/Patterns/TagValue.cs b/common/ASC.Core.Common/Notify/Patterns/TagValue.cs
index 3f653ebae5..5ce921a574 100644
--- a/common/ASC.Core.Common/Notify/Patterns/TagValue.cs
+++ b/common/ASC.Core.Common/Notify/Patterns/TagValue.cs
@@ -33,10 +33,7 @@ public class TagValue : ITagValue
 
     public TagValue(string tag, object value)
     {
-        if (string.IsNullOrEmpty(tag))
-        {
-            throw new ArgumentNullException(nameof(tag));
-        }
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(tag);
 
         Tag = tag;
         Value = value;
diff --git a/common/ASC.Core.Common/Notify/RecipientProviderImpl.cs b/common/ASC.Core.Common/Notify/RecipientProviderImpl.cs
index d6d39fe58b..acfc386a61 100644
--- a/common/ASC.Core.Common/Notify/RecipientProviderImpl.cs
+++ b/common/ASC.Core.Common/Notify/RecipientProviderImpl.cs
@@ -58,10 +58,7 @@ public class RecipientProviderImpl : IRecipientProvider
 
     public virtual IRecipient[] GetGroupEntries(IRecipientsGroup group)
     {
-        if (group == null)
-        {
-            throw new ArgumentNullException(nameof(group));
-        }
+        ArgumentNullException.ThrowIfNull(group);
 
         var result = new List<IRecipient>();
         if (TryParseGuid(group.ID, out var groupID))
@@ -79,10 +76,7 @@ public class RecipientProviderImpl : IRecipientProvider
 
     public virtual IRecipientsGroup[] GetGroups(IRecipient recipient)
     {
-        if (recipient == null)
-        {
-            throw new ArgumentNullException(nameof(recipient));
-        }
+        ArgumentNullException.ThrowIfNull(recipient);
 
         var result = new List<IRecipientsGroup>();
         if (TryParseGuid(recipient.ID, out var recID))
@@ -110,10 +104,7 @@ public class RecipientProviderImpl : IRecipientProvider
 
     public virtual string[] GetRecipientAddresses(IDirectRecipient recipient, string senderName)
     {
-        if (recipient == null)
-        {
-            throw new ArgumentNullException(nameof(recipient));
-        }
+        ArgumentNullException.ThrowIfNull(recipient);
 
         if (TryParseGuid(recipient.ID, out var userID))
         {
diff --git a/common/ASC.Core.Common/Notify/TopSubscriptionProvider.cs b/common/ASC.Core.Common/Notify/TopSubscriptionProvider.cs
index 162fae3d04..597ba338c8 100644
--- a/common/ASC.Core.Common/Notify/TopSubscriptionProvider.cs
+++ b/common/ASC.Core.Common/Notify/TopSubscriptionProvider.cs
@@ -47,14 +47,8 @@ public class TopSubscriptionProvider : ISubscriptionProvider
 
     public virtual string[] GetSubscriptionMethod(INotifyAction action, IRecipient recipient)
     {
-        if (action == null)
-        {
-            throw new ArgumentNullException(nameof(action));
-        }
-        if (recipient == null)
-        {
-            throw new ArgumentNullException(nameof(recipient));
-        }
+        ArgumentNullException.ThrowIfNull(action);
+        ArgumentNullException.ThrowIfNull(recipient);
 
         var senders = _subscriptionProvider.GetSubscriptionMethod(action, recipient);
         if (senders == null || senders.Length == 0)
@@ -75,10 +69,7 @@ public class TopSubscriptionProvider : ISubscriptionProvider
 
     public virtual IRecipient[] GetRecipients(INotifyAction action, string objectID)
     {
-        if (action == null)
-        {
-            throw new ArgumentNullException(nameof(action));
-        }
+        ArgumentNullException.ThrowIfNull(action);
 
         var recipents = new List<IRecipient>(5);
         var directRecipients = _subscriptionProvider.GetRecipients(action, objectID) ?? new IRecipient[0];
@@ -89,14 +80,8 @@ public class TopSubscriptionProvider : ISubscriptionProvider
 
     public virtual bool IsUnsubscribe(IDirectRecipient recipient, INotifyAction action, string objectID)
     {
-        if (action == null)
-        {
-            throw new ArgumentNullException(nameof(action));
-        }
-        if (recipient == null)
-        {
-            throw new ArgumentNullException(nameof(recipient));
-        }
+        ArgumentNullException.ThrowIfNull(action);
+        ArgumentNullException.ThrowIfNull(recipient);
 
         return _subscriptionProvider.IsUnsubscribe(recipient, action, objectID);
     }
@@ -104,48 +89,30 @@ public class TopSubscriptionProvider : ISubscriptionProvider
 
     public virtual void Subscribe(INotifyAction action, string objectID, IRecipient recipient)
     {
-        if (action == null)
-        {
-            throw new ArgumentNullException(nameof(action));
-        }
-        if (recipient == null)
-        {
-            throw new ArgumentNullException(nameof(recipient));
-        }
+        ArgumentNullException.ThrowIfNull(action);
+        ArgumentNullException.ThrowIfNull(recipient);
 
         _subscriptionProvider.Subscribe(action, objectID, recipient);
     }
 
     public virtual void UnSubscribe(INotifyAction action, string objectID, IRecipient recipient)
     {
-        if (action == null)
-        {
-            throw new ArgumentNullException(nameof(action));
-        }
-        if (recipient == null)
-        {
-            throw new ArgumentNullException(nameof(recipient));
-        }
+        ArgumentNullException.ThrowIfNull(action);
+        ArgumentNullException.ThrowIfNull(recipient);
 
         _subscriptionProvider.UnSubscribe(action, objectID, recipient);
     }
 
     public void UnSubscribe(INotifyAction action, string objectID)
     {
-        if (action == null)
-        {
-            throw new ArgumentNullException(nameof(action));
-        }
+        ArgumentNullException.ThrowIfNull(action);
 
         _subscriptionProvider.UnSubscribe(action, objectID);
     }
 
     public void UnSubscribe(INotifyAction action)
     {
-        if (action == null)
-        {
-            throw new ArgumentNullException(nameof(action));
-        }
+        ArgumentNullException.ThrowIfNull(action);
 
         _subscriptionProvider.UnSubscribe(action);
     }
@@ -161,32 +128,17 @@ public class TopSubscriptionProvider : ISubscriptionProvider
 
     public virtual void UpdateSubscriptionMethod(INotifyAction action, IRecipient recipient, params string[] senderNames)
     {
-        if (action == null)
-        {
-            throw new ArgumentNullException(nameof(action));
-        }
-        if (recipient == null)
-        {
-            throw new ArgumentNullException(nameof(recipient));
-        }
-        if (senderNames == null)
-        {
-            throw new ArgumentNullException(nameof(senderNames));
-        }
+        ArgumentNullException.ThrowIfNull(action);
+        ArgumentNullException.ThrowIfNull(recipient);
+        ArgumentNullException.ThrowIfNull(senderNames);
 
         _subscriptionProvider.UpdateSubscriptionMethod(action, recipient, senderNames);
     }
 
     public virtual object GetSubscriptionRecord(INotifyAction action, IRecipient recipient, string objectID)
     {
-        if (recipient == null)
-        {
-            throw new ArgumentNullException(nameof(recipient));
-        }
-        if (action == null)
-        {
-            throw new ArgumentNullException(nameof(action));
-        }
+        ArgumentNullException.ThrowIfNull(action);
+        ArgumentNullException.ThrowIfNull(recipient);
 
         var subscriptionRecord = _subscriptionProvider.GetSubscriptionRecord(action, recipient, objectID);
 
@@ -212,14 +164,8 @@ public class TopSubscriptionProvider : ISubscriptionProvider
 
     public virtual string[] GetSubscriptions(INotifyAction action, IRecipient recipient, bool checkSubscription = true)
     {
-        if (recipient == null)
-        {
-            throw new ArgumentNullException(nameof(recipient));
-        }
-        if (action == null)
-        {
-            throw new ArgumentNullException(nameof(action));
-        }
+        ArgumentNullException.ThrowIfNull(action);
+        ArgumentNullException.ThrowIfNull(recipient);
 
         var objects = new List<string>();
         var direct = _subscriptionProvider.GetSubscriptions(action, recipient, checkSubscription) ?? Array.Empty<string>();
diff --git a/common/ASC.Core.Common/Security/Authorizing/AzManager.cs b/common/ASC.Core.Common/Security/Authorizing/AzManager.cs
index 6c7bd3f3c9..4a9fadf8e9 100644
--- a/common/ASC.Core.Common/Security/Authorizing/AzManager.cs
+++ b/common/ASC.Core.Common/Security/Authorizing/AzManager.cs
@@ -44,15 +44,8 @@ public class AzManager
                                 ISecurityObjectProvider securityObjProvider, out ISubject denySubject,
                                 out IAction denyAction)
     {
-        if (subject == null)
-        {
-            throw new ArgumentNullException(nameof(subject));
-        }
-
-        if (action == null)
-        {
-            throw new ArgumentNullException(nameof(action));
-        }
+        ArgumentNullException.ThrowIfNull(action);
+        ArgumentNullException.ThrowIfNull(subject);
 
         var acl = GetAzManagerAcl(subject, action, objectId, securityObjProvider);
         denySubject = acl.DenySubject;
diff --git a/common/ASC.Core.Common/Security/Authorizing/PermissionProvider.cs b/common/ASC.Core.Common/Security/Authorizing/PermissionProvider.cs
index 8861304875..0a564e4603 100644
--- a/common/ASC.Core.Common/Security/Authorizing/PermissionProvider.cs
+++ b/common/ASC.Core.Common/Security/Authorizing/PermissionProvider.cs
@@ -35,15 +35,9 @@ class PermissionProvider : IPermissionProvider
     }
 
     public IEnumerable<Ace> GetAcl(ISubject subject, IAction action, ISecurityObjectId objectId, ISecurityObjectProvider secObjProvider)
-    {
-        if (subject == null)
-        {
-            throw new ArgumentNullException(nameof(subject));
-        }
-        if (action == null)
-        {
-            throw new ArgumentNullException(nameof(action));
-        }
+    {
+        ArgumentNullException.ThrowIfNull(subject);
+        ArgumentNullException.ThrowIfNull(action);
 
         return _authorizationManager
             .GetAcesWithInherits(subject.ID, action.ID, objectId, secObjProvider)
diff --git a/common/ASC.Core.Common/Security/EmailValidationKeyProvider.cs b/common/ASC.Core.Common/Security/EmailValidationKeyProvider.cs
index 29bad90ba2..6fb58fd7eb 100644
--- a/common/ASC.Core.Common/Security/EmailValidationKeyProvider.cs
+++ b/common/ASC.Core.Common/Security/EmailValidationKeyProvider.cs
@@ -23,8 +23,6 @@
  *
 */
 
-using static ASC.Security.Cryptography.EmailValidationKeyProvider;
-
 namespace ASC.Security.Cryptography;
 
 [Scope]
@@ -69,10 +67,7 @@ public class EmailValidationKeyProvider
 
     public string GetEmailKey(int tenantId, string email)
     {
-        if (string.IsNullOrEmpty(email))
-        {
-            throw new ArgumentNullException(nameof(email));
-        }
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(email);
 
         email = FormatEmail(tenantId, email);
 
@@ -84,10 +79,7 @@ public class EmailValidationKeyProvider
 
     private string FormatEmail(int tenantId, string email)
     {
-        if (email == null)
-        {
-            throw new ArgumentNullException(nameof(email));
-        }
+        ArgumentNullException.ThrowIfNull(email);
 
         try
         {
@@ -116,14 +108,8 @@ public class EmailValidationKeyProvider
 
     private ValidationResult ValidateEmailKeyInternal(string email, string key, TimeSpan validInterval)
     {
-        if (string.IsNullOrEmpty(email))
-        {
-            throw new ArgumentNullException(nameof(email));
-        }
-        if (key == null)
-        {
-            throw new ArgumentNullException(nameof(key));
-        }
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(email);
+        ArgumentNullException.ThrowIfNull(key);
 
         email = FormatEmail(_tenantManager.GetCurrentTenant().Id, email);
         var parts = key.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
diff --git a/common/ASC.Core.Common/Users/UserFormatter.cs b/common/ASC.Core.Common/Users/UserFormatter.cs
index f128205fc6..c1dcfe5066 100644
--- a/common/ASC.Core.Common/Users/UserFormatter.cs
+++ b/common/ASC.Core.Common/Users/UserFormatter.cs
@@ -41,10 +41,7 @@ public class UserFormatter : IComparer<UserInfo>
 
     public string GetUserName(UserInfo userInfo, DisplayUserNameFormat format)
     {
-        if (userInfo == null)
-        {
-            throw new ArgumentNullException(nameof(userInfo));
-        }
+        ArgumentNullException.ThrowIfNull(userInfo);
 
         return string.Format(GetUserDisplayFormat(format), userInfo.FirstName, userInfo.LastName);
     }
diff --git a/common/ASC.Data.Backup.Core/ActionInvoker.cs b/common/ASC.Data.Backup.Core/ActionInvoker.cs
index 0ed14d68c5..24f6de8853 100644
--- a/common/ASC.Data.Backup.Core/ActionInvoker.cs
+++ b/common/ASC.Data.Backup.Core/ActionInvoker.cs
@@ -46,11 +46,8 @@ public static class ActionInvoker
         Action<Exception> onAttemptFailure = null,
         int sleepMs = 1000,
         bool isSleepExponential = true)
-    {
-        if (action == null)
-        {
-            throw new ArgumentNullException(nameof(action));
-        }
+    {
+        ArgumentNullException.ThrowIfNull(action);
 
         var countAttempts = 0;
         while (countAttempts++ < maxAttempts)
diff --git a/common/ASC.Data.Backup.Core/Extensions/EnumerableExtensions.cs b/common/ASC.Data.Backup.Core/Extensions/EnumerableExtensions.cs
index 6982481188..8188d78709 100644
--- a/common/ASC.Data.Backup.Core/Extensions/EnumerableExtensions.cs
+++ b/common/ASC.Data.Backup.Core/Extensions/EnumerableExtensions.cs
@@ -49,15 +49,10 @@ public static class EnumerableExtensions
     public static IEnumerable<TreeNode<TEntry>> ToTree<TEntry, TKey>(this IEnumerable<TEntry> elements,
                                                                      Func<TEntry, TKey> keySelector,
                                                                      Func<TEntry, TKey> parentKeySelector)
-    {
-        if (elements == null)
-                throw new ArgumentNullException(nameof(elements));
-
-        if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-
-        if (parentKeySelector == null)
-                throw new ArgumentNullException(nameof(parentKeySelector));
+    {
+        ArgumentNullException.ThrowIfNull(elements);
+        ArgumentNullException.ThrowIfNull(keySelector);
+        ArgumentNullException.ThrowIfNull(parentKeySelector);
 
         var dic = elements.ToDictionary(keySelector, x => new TreeNode<TEntry>(x));
 
@@ -75,18 +70,17 @@ public static class EnumerableExtensions
     }
 
     public static IEnumerable<IEnumerable<TEntry>> MakeParts<TEntry>(this IEnumerable<TEntry> collection, int partLength)
+    {
+        ArgumentNullException.ThrowIfNull(collection);
+
+        if (partLength <= 0)
+            throw new ArgumentOutOfRangeException(nameof(partLength), partLength, "Length must be positive integer");
+
+        return MakePartsIterator(collection, partLength);
+    }
+
+    private static IEnumerable<IEnumerable<TEntry>> MakePartsIterator<TEntry>(this IEnumerable<TEntry> collection, int partLength)
     {
-        if (collection == null)
-                throw new ArgumentNullException(nameof(collection));
-
-        if (partLength <= 0)
-                throw new ArgumentOutOfRangeException(nameof(partLength), partLength, "Length must be positive integer");
-
-            return MakePartsIterator(collection, partLength);
-        }
-
-        private static IEnumerable<IEnumerable<TEntry>> MakePartsIterator<TEntry>(this IEnumerable<TEntry> collection, int partLength)
-        {
         var part = new List<TEntry>(partLength);
 
         foreach (var entry in collection)
diff --git a/common/ASC.Data.Backup.Core/Tasks/BackupPortalTask.cs b/common/ASC.Data.Backup.Core/Tasks/BackupPortalTask.cs
index c128c9b62c..2313f7ae8d 100644
--- a/common/ASC.Data.Backup.Core/Tasks/BackupPortalTask.cs
+++ b/common/ASC.Data.Backup.Core/Tasks/BackupPortalTask.cs
@@ -50,9 +50,9 @@ public class BackupPortalTask : PortalTaskBase
     }
 
     public void Init(int tenantId, string fromConfigPath, string toFilePath, int limit)
-    {
-        if (string.IsNullOrEmpty(toFilePath))
-                throw new ArgumentNullException(nameof(toFilePath));
+    {
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(toFilePath);
+
         BackupFilePath = toFilePath;
         Limit = limit;
         Init(tenantId, fromConfigPath);
@@ -124,24 +124,24 @@ public class BackupPortalTask : PortalTaskBase
             var command = connection.CreateCommand();
             command.CommandText = "show tables";
             tables = ExecuteList(command).Select(r => Convert.ToString(r[0])).ToList();
-        }
+        }
         /*  using (var dbManager = new DbManager("default", 100000))
           {
               tables = dbManager.ExecuteList("show tables;").Select(r => Convert.ToString(r[0])).ToList();
-          }*/
-
-            var stepscount = tables.Count * 4; // (schema + data) * (dump + zip)
-            if (ProcessStorage)
-            {
-                var tenants = _tenantManager.GetTenants(false).Select(r => r.Id);
-                foreach (var t in tenants)
-                {
-                    files.AddRange(GetFiles(t));
-                }
-
-                stepscount += files.Count * 2 + 1;
-                Logger.Debug("files:" + files.Count);
-            }
+          }*/
+
+        var stepscount = tables.Count * 4; // (schema + data) * (dump + zip)
+        if (ProcessStorage)
+        {
+            var tenants = _tenantManager.GetTenants(false).Select(r => r.Id);
+            foreach (var t in tenants)
+            {
+                files.AddRange(GetFiles(t));
+            }
+
+            stepscount += files.Count * 2 + 1;
+            Logger.Debug("files:" + files.Count);
+        }
 
         SetStepsCount(stepscount);
 
@@ -200,9 +200,9 @@ public class BackupPortalTask : PortalTaskBase
 
     private IEnumerable<BackupFileInfo> GetFiles(int tenantId)
     {
-        var files = GetFilesToProcess(tenantId).ToList();
-            var exclude = BackupRecordContext.Backups.AsQueryable().Where(b => b.TenantId == tenantId && b.StorageType == 0 && b.StoragePath != null).ToList();
-            files = files.Where(f => !exclude.Any(e => f.Path.Replace('\\', '/').Contains($"/file_{e.StoragePath}/"))).ToList();
+        var files = GetFilesToProcess(tenantId).ToList();
+        var exclude = BackupRecordContext.Backups.AsQueryable().Where(b => b.TenantId == tenantId && b.StorageType == 0 && b.StoragePath != null).ToList();
+        files = files.Where(f => !exclude.Any(e => f.Path.Replace('\\', '/').Contains($"/file_{e.StoragePath}/"))).ToList();
         return files;
 
     }
@@ -214,16 +214,16 @@ public class BackupPortalTask : PortalTaskBase
             Logger.DebugFormat("dump table scheme start {0}", t);
             using (var connection = DbFactory.OpenConnection())
             {
-                var command = connection.CreateCommand();
-                    command.CommandText = $"SHOW CREATE TABLE `{t}`";
+                var command = connection.CreateCommand();
+                command.CommandText = $"SHOW CREATE TABLE `{t}`";
                 var createScheme = ExecuteList(command);
-                var creates = new StringBuilder();
-                    creates.Append($"DROP TABLE IF EXISTS `{t}`;");
+                var creates = new StringBuilder();
+                creates.Append($"DROP TABLE IF EXISTS `{t}`;");
                 creates.AppendLine();
                 creates.Append(createScheme
                         .Select(r => Convert.ToString(r[1]))
-                        .FirstOrDefault());
-                    creates.Append(';');
+                        .FirstOrDefault());
+                creates.Append(';');
 
                 var path = CrossPlatform.PathCombine(dir, t);
                 using (var stream = File.OpenWrite(path))
@@ -278,8 +278,8 @@ public class BackupPortalTask : PortalTaskBase
                 return;
             }
 
-            Logger.DebugFormat("dump table data start {0}", t);
-                bool searchWithPrimary;
+            Logger.DebugFormat("dump table data start {0}", t);
+            bool searchWithPrimary;
             string primaryIndex;
             var primaryIndexStep = 0;
             var primaryIndexStart = 0;
@@ -288,8 +288,8 @@ public class BackupPortalTask : PortalTaskBase
 
             using (var connection = DbFactory.OpenConnection())
             {
-                var command = connection.CreateCommand();
-                    command.CommandText = string.Format($"SHOW COLUMNS FROM `{t}`");
+                var command = connection.CreateCommand();
+                command.CommandText = string.Format($"SHOW COLUMNS FROM `{t}`");
                 columns = ExecuteList(command).Select(r => "`" + Convert.ToString(r[0]) + "`").ToList();
                 if (command.CommandText.Contains("tenants_quota") || command.CommandText.Contains("webstudio_settings"))
                 {
@@ -299,16 +299,16 @@ public class BackupPortalTask : PortalTaskBase
 
             using (var connection = DbFactory.OpenConnection())
             {
-                var command = connection.CreateCommand();
-                    command.CommandText = $"select COLUMN_NAME from information_schema.`COLUMNS` where TABLE_SCHEMA = '{connection.Database}' and TABLE_NAME = '{t}' and COLUMN_KEY = 'PRI' and DATA_TYPE = 'int'";
+                var command = connection.CreateCommand();
+                command.CommandText = $"select COLUMN_NAME from information_schema.`COLUMNS` where TABLE_SCHEMA = '{connection.Database}' and TABLE_NAME = '{t}' and COLUMN_KEY = 'PRI' and DATA_TYPE = 'int'";
                 primaryIndex = ExecuteList(command).ConvertAll(r => Convert.ToString(r[0])).FirstOrDefault();
 
             }
 
             using (var connection = DbFactory.OpenConnection())
             {
-                var command = connection.CreateCommand();
-                    command.CommandText = $"SHOW INDEXES FROM {t} WHERE COLUMN_NAME='{primaryIndex}' AND seq_in_index=1";
+                var command = connection.CreateCommand();
+                command.CommandText = $"SHOW INDEXES FROM {t} WHERE COLUMN_NAME='{primaryIndex}' AND seq_in_index=1";
                 var isLeft = ExecuteList(command);
                 searchWithPrimary = isLeft.Count == 1;
             }
@@ -316,8 +316,8 @@ public class BackupPortalTask : PortalTaskBase
             if (searchWithPrimary)
             {
                 using var connection = DbFactory.OpenConnection();
-                var command = connection.CreateCommand();
-                    command.CommandText = $"select max({primaryIndex}), min({primaryIndex}) from {t}";
+                var command = connection.CreateCommand();
+                command.CommandText = $"select max({primaryIndex}), min({primaryIndex}) from {t}";
                 var minMax = ExecuteList(command).ConvertAll(r => new Tuple<int, int>(Convert.ToInt32(r[0]), Convert.ToInt32(r[1]))).FirstOrDefault();
                 primaryIndexStart = minMax.Item2;
                 primaryIndexStep = (minMax.Item1 - minMax.Item2) / count;
@@ -397,8 +397,8 @@ public class BackupPortalTask : PortalTaskBase
     private void SaveToFile(string path, string t, IReadOnlyCollection<string> columns, List<object[]> data)
     {
         Logger.DebugFormat("save to file {0}", t);
-        List<object[]> portion;
-            while ((portion = data.Take(BatchLimit).ToList()).Count > 0)
+        List<object[]> portion;
+        while ((portion = data.Take(BatchLimit).ToList()).Count > 0)
         {
             using (var sw = new StreamWriter(path, true))
             using (var writer = new JsonTextWriter(sw))
@@ -414,9 +414,9 @@ public class BackupPortalTask : PortalTaskBase
                     sw.Write("(");
 
                     for (var i = 0; i < obj.Length; i++)
-                    {
-                            var value = obj[i];
-                            if (value is byte[] byteArray)
+                    {
+                        var value = obj[i];
+                        if (value is byte[] byteArray)
                         {
                             sw.Write("0x");
                             foreach (var b in byteArray)
@@ -426,8 +426,8 @@ public class BackupPortalTask : PortalTaskBase
                         }
                         else
                         {
-                            var ser = new JsonSerializer();
-                                ser.Serialize(writer, value);
+                            var ser = new JsonSerializer();
+                            ser.Serialize(writer, value);
                         }
                         if (i != obj.Length - 1)
                         {
@@ -518,9 +518,9 @@ public class BackupPortalTask : PortalTaskBase
         if (!WorkContext.IsMono && filePath.Length > MaxLength)
         {
             filePath = @"\\?\" + filePath;
-        }
-
-            using (var fileStream = await storage.GetReadStreamAsync(file.Domain, file.Path))
+        }
+
+        using (var fileStream = await storage.GetReadStreamAsync(file.Domain, file.Path))
         using (var tmpFile = File.OpenWrite(filePath))
         {
             await fileStream.CopyToAsync(tmpFile);
@@ -553,10 +553,10 @@ public class BackupPortalTask : PortalTaskBase
 
     private List<IGrouping<string, BackupFileInfo>> GetFilesGroup()
     {
-        var files = GetFilesToProcess(TenantId).ToList();
-            var exclude = BackupRecordContext.Backups.AsQueryable().Where(b => b.TenantId == TenantId && b.StorageType == 0 && b.StoragePath != null).ToList();
-
-            files = files.Where(f => !exclude.Any(e => f.Path.Replace('\\', '/').Contains($"/file_{e.StoragePath}/"))).ToList();
+        var files = GetFilesToProcess(TenantId).ToList();
+        var exclude = BackupRecordContext.Backups.AsQueryable().Where(b => b.TenantId == TenantId && b.StorageType == 0 && b.StoragePath != null).ToList();
+
+        files = files.Where(f => !exclude.Any(e => f.Path.Replace('\\', '/').Contains($"/file_{e.StoragePath}/"))).ToList();
 
         return files.GroupBy(file => file.Module).ToList();
     }
@@ -616,9 +616,9 @@ public class BackupPortalTask : PortalTaskBase
                     }
 
                     Logger.DebugFormat("end saving table {0}", table.Name);
-                }
-
-                    SetCurrentStepProgress((int)(++tablesProcessed * 100 / (double)tablesCount));
+                }
+
+                SetCurrentStepProgress((int)(++tablesProcessed * 100 / (double)tablesCount));
             }
         }
 
@@ -640,8 +640,8 @@ public class BackupPortalTask : PortalTaskBase
                 var file1 = file;
                 ActionInvoker.Try(state =>
                 {
-                    var f = (BackupFileInfo)state;
-                        using var fileStream = storage.GetReadStreamAsync(f.Domain, f.Path).Result;
+                    var f = (BackupFileInfo)state;
+                    using var fileStream = storage.GetReadStreamAsync(f.Domain, f.Path).Result;
                     writer.WriteEntry(file1.GetZipKey(), fileStream);
                 }, file, 5, error => Logger.WarnFormat("can't backup file ({0}:{1}): {2}", file1.Module, file1.Path, error));
 
diff --git a/common/ASC.Data.Backup.Core/Tasks/RestorePortalTask.cs b/common/ASC.Data.Backup.Core/Tasks/RestorePortalTask.cs
index ead84b48e9..6197341a38 100644
--- a/common/ASC.Data.Backup.Core/Tasks/RestorePortalTask.cs
+++ b/common/ASC.Data.Backup.Core/Tasks/RestorePortalTask.cs
@@ -62,10 +62,7 @@ public class RestorePortalTask : PortalTaskBase
 
     public void Init(string toConfigPath, string fromFilePath, int tenantId = -1, ColumnMapper columnMapper = null, string upgradesPath = null)
     {
-        if (fromFilePath == null)
-        {
-            throw new ArgumentNullException(nameof(fromFilePath));
-        }
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(fromFilePath);
 
         if (!File.Exists(fromFilePath))
         {
@@ -291,8 +288,8 @@ public class RestorePortalTask : PortalTaskBase
                         }
                         using var stream = dataReader.GetEntry(key);
                         try
-                        {
-                                storage.SaveAsync(file.Domain, adjustedPath, module != null ? module.PrepareData(key, stream, _columnMapper) : stream).Wait();
+                        {
+                            storage.SaveAsync(file.Domain, adjustedPath, module != null ? module.PrepareData(key, stream, _columnMapper) : stream).Wait();
                         }
                         catch (Exception error)
                         {
@@ -322,14 +319,14 @@ public class RestorePortalTask : PortalTaskBase
 
     private void DoDeleteStorage(IEnumerable<string> storageModules, IEnumerable<Tenant> tenants)
     {
-        Logger.Debug("begin delete storage");
-
-            foreach (var tenant in tenants)
-            {
-                foreach (var module in storageModules)
-                {
-                    var storage = StorageFactory.GetStorage(ConfigPath, tenant.Id.ToString(), module);
-                    var domains = StorageFactoryConfig.GetDomainList(ConfigPath, module).ToList();
+        Logger.Debug("begin delete storage");
+
+        foreach (var tenant in tenants)
+        {
+            foreach (var module in storageModules)
+            {
+                var storage = StorageFactory.GetStorage(ConfigPath, tenant.Id.ToString(), module);
+                var domains = StorageFactoryConfig.GetDomainList(ConfigPath, module).ToList();
 
                 domains.Add(string.Empty); //instead storage.DeleteFiles("\\", "*.*", true);
 
@@ -337,10 +334,10 @@ public class RestorePortalTask : PortalTaskBase
                 {
                     ActionInvoker.Try(
                         state =>
-                        {
-                                if (storage.IsDirectoryAsync((string)state).Result)
-                            {
-                                    storage.DeleteFilesAsync((string)state, "\\", "*.*", true).Wait();
+                        {
+                            if (storage.IsDirectoryAsync((string)state).Result)
+                            {
+                                storage.DeleteFilesAsync((string)state, "\\", "*.*", true).Wait();
                             }
                         },
                         domain,
@@ -381,10 +378,10 @@ public class RestorePortalTask : PortalTaskBase
             "where id = '{2}'",
             (int)TenantStatus.Active,
             DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss"),
-            tenantId);
-
-            var command = connection.CreateCommand().WithTimeout(120);
-            command.CommandText = commandText;
-            command.ExecuteNonQuery();
+            tenantId);
+
+        var command = connection.CreateCommand().WithTimeout(120);
+        command.CommandText = commandText;
+        command.ExecuteNonQuery();
     }
 }
diff --git a/common/ASC.Data.Storage/BaseStorage.cs b/common/ASC.Data.Storage/BaseStorage.cs
index f2202ded11..168773da3e 100644
--- a/common/ASC.Data.Storage/BaseStorage.cs
+++ b/common/ASC.Data.Storage/BaseStorage.cs
@@ -71,26 +71,23 @@ public abstract class BaseStorage : IDataStore
         return DomainsExpires.ContainsKey(domain) ? DomainsExpires[domain] : DomainsExpires[string.Empty];
     }
 
-        public Task<Uri> GetUriAsync(string path)
+    public Task<Uri> GetUriAsync(string path)
     {
-            return GetUriAsync(string.Empty, path);
+        return GetUriAsync(string.Empty, path);
     }
 
-        public Task<Uri> GetUriAsync(string domain, string path)
+    public Task<Uri> GetUriAsync(string domain, string path)
     {
-            return GetPreSignedUriAsync(domain, path, TimeSpan.MaxValue, null);
+        return GetPreSignedUriAsync(domain, path, TimeSpan.MaxValue, null);
     }
 
-        public Task<Uri> GetPreSignedUriAsync(string domain, string path, TimeSpan expire, IEnumerable<string> headers)
+    public Task<Uri> GetPreSignedUriAsync(string domain, string path, TimeSpan expire, IEnumerable<string> headers)
     {
-        if (path == null)
-        {
-            throw new ArgumentNullException(nameof(path));
-        }
+        ArgumentNullException.ThrowIfNull(path);
 
         if (string.IsNullOrEmpty(Tenant) && IsSupportInternalUri)
         {
-                return GetInternalUriAsync(domain, path, expire, headers);
+            return GetInternalUriAsync(domain, path, expire, headers);
         }
 
         var headerAttr = string.Empty;
@@ -109,16 +106,16 @@ public abstract class BaseStorage : IDataStore
         {
             var expireString = expire.TotalMinutes.ToString(CultureInfo.InvariantCulture);
 
-                int currentTenantId;
-                var currentTenant = TenantManager.GetCurrentTenant(false);
-                if (currentTenant != null)
-                {
-                    currentTenantId = currentTenant.Id;
-                }
-                else if (!TenantPath.TryGetTenant(Tenant, out currentTenantId))
-                {
-                    currentTenantId = 0;
-                }
+            int currentTenantId;
+            var currentTenant = TenantManager.GetCurrentTenant(false);
+            if (currentTenant != null)
+            {
+                currentTenantId = currentTenant.Id;
+            }
+            else if (!TenantPath.TryGetTenant(Tenant, out currentTenantId))
+            {
+                currentTenantId = 0;
+            }
 
             var auth = TemailValidationKeyProvider.GetEmailKey(currentTenantId, path.Replace('/', Path.DirectorySeparatorChar).Replace('\\', Path.DirectorySeparatorChar) + "." + headerAttr + "." + expireString);
             query = $"{(path.IndexOf('?') >= 0 ? "&" : "?")}{Constants.QueryExpire}={expireString}&{Constants.QueryAuth}={auth}";
@@ -139,169 +136,169 @@ public abstract class BaseStorage : IDataStore
                       new MonoUri(virtualPath, virtualPath.LocalPath.TrimEnd('/') + EnsureLeadingSlash(path.Replace('\\', '/')) + query) :
                       new MonoUri(virtualPath.ToString().TrimEnd('/') + EnsureLeadingSlash(path.Replace('\\', '/')) + query, UriKind.Relative);
 
-            return Task.FromResult<Uri>(uri);
+        return Task.FromResult<Uri>(uri);
     }
 
-        public virtual Task<Uri> GetInternalUriAsync(string domain, string path, TimeSpan expire, IEnumerable<string> headers)
+    public virtual Task<Uri> GetInternalUriAsync(string domain, string path, TimeSpan expire, IEnumerable<string> headers)
     {
         return null;
     }
 
-        public abstract Task<Stream> GetReadStreamAsync(string domain, string path);
+    public abstract Task<Stream> GetReadStreamAsync(string domain, string path);
 
     public abstract Task<Stream> GetReadStreamAsync(string domain, string path, int offset);
 
-        public abstract Task<Uri> SaveAsync(string domain, string path, Stream stream);
-        public abstract Task<Uri> SaveAsync(string domain, string path, Stream stream, ACL acl);
+    public abstract Task<Uri> SaveAsync(string domain, string path, Stream stream);
+    public abstract Task<Uri> SaveAsync(string domain, string path, Stream stream, ACL acl);
 
-        public Task<Uri> SaveAsync(string domain, string path, Stream stream, string attachmentFileName)
+    public Task<Uri> SaveAsync(string domain, string path, Stream stream, string attachmentFileName)
     {
         if (!string.IsNullOrEmpty(attachmentFileName))
         {
-                return SaveWithAutoAttachmentAsync(domain, path, stream, attachmentFileName);
+            return SaveWithAutoAttachmentAsync(domain, path, stream, attachmentFileName);
         }
-            return SaveAsync(domain, path, stream);
+        return SaveAsync(domain, path, stream);
     }
 
-        protected abstract Task<Uri> SaveWithAutoAttachmentAsync(string domain, string path, Stream stream, string attachmentFileName);
+    protected abstract Task<Uri> SaveWithAutoAttachmentAsync(string domain, string path, Stream stream, string attachmentFileName);
 
 
-        public abstract Task<Uri> SaveAsync(string domain, string path, Stream stream, string contentType,
-                                string contentDisposition);
-        public abstract Task<Uri> SaveAsync(string domain, string path, Stream stream, string contentEncoding, int cacheDays);
+    public abstract Task<Uri> SaveAsync(string domain, string path, Stream stream, string contentType,
+                            string contentDisposition);
+    public abstract Task<Uri> SaveAsync(string domain, string path, Stream stream, string contentEncoding, int cacheDays);
 
     #region chunking
 
-        public virtual Task<string> InitiateChunkedUploadAsync(string domain, string path)
+    public virtual Task<string> InitiateChunkedUploadAsync(string domain, string path)
     {
         throw new NotImplementedException();
     }
 
-        public virtual Task<string> UploadChunkAsync(string domain, string path, string uploadId, Stream stream, long defaultChunkSize, int chunkNumber, long chunkLength)
+    public virtual Task<string> UploadChunkAsync(string domain, string path, string uploadId, Stream stream, long defaultChunkSize, int chunkNumber, long chunkLength)
     {
         throw new NotImplementedException();
     }
 
-        public virtual Task<Uri> FinalizeChunkedUploadAsync(string domain, string path, string uploadId, Dictionary<int, string> eTags)
+    public virtual Task<Uri> FinalizeChunkedUploadAsync(string domain, string path, string uploadId, Dictionary<int, string> eTags)
     {
         throw new NotImplementedException();
     }
 
-        public virtual Task AbortChunkedUploadAsync(string domain, string path, string uploadId)
+    public virtual Task AbortChunkedUploadAsync(string domain, string path, string uploadId)
     {
         throw new NotImplementedException();
     }
 
     #endregion
 
-        public abstract Task DeleteAsync(string domain, string path);
-        public abstract Task DeleteFilesAsync(string domain, string folderPath, string pattern, bool recursive);
-        public abstract Task DeleteFilesAsync(string domain, List<string> paths);
-        public abstract Task DeleteFilesAsync(string domain, string folderPath, DateTime fromDate, DateTime toDate);
-        public abstract Task MoveDirectoryAsync(string srcdomain, string srcdir, string newdomain, string newdir);
-        public abstract Task<Uri> MoveAsync(string srcdomain, string srcpath, string newdomain, string newpath, bool quotaCheckFileSize = true);
-        public abstract Task<Uri> SaveTempAsync(string domain, out string assignedPath, Stream stream);
-        public abstract IAsyncEnumerable<string> ListDirectoriesRelativeAsync(string domain, string path, bool recursive);
-        public abstract IAsyncEnumerable<string> ListFilesRelativeAsync(string domain, string path, string pattern, bool recursive);
+    public abstract Task DeleteAsync(string domain, string path);
+    public abstract Task DeleteFilesAsync(string domain, string folderPath, string pattern, bool recursive);
+    public abstract Task DeleteFilesAsync(string domain, List<string> paths);
+    public abstract Task DeleteFilesAsync(string domain, string folderPath, DateTime fromDate, DateTime toDate);
+    public abstract Task MoveDirectoryAsync(string srcdomain, string srcdir, string newdomain, string newdir);
+    public abstract Task<Uri> MoveAsync(string srcdomain, string srcpath, string newdomain, string newpath, bool quotaCheckFileSize = true);
+    public abstract Task<Uri> SaveTempAsync(string domain, out string assignedPath, Stream stream);
+    public abstract IAsyncEnumerable<string> ListDirectoriesRelativeAsync(string domain, string path, bool recursive);
+    public abstract IAsyncEnumerable<string> ListFilesRelativeAsync(string domain, string path, string pattern, bool recursive);
 
     public abstract Task<bool> IsFileAsync(string domain, string path);
-        public abstract Task<bool> IsDirectoryAsync(string domain, string path);
-        public abstract Task DeleteDirectoryAsync(string domain, string path);
-        public abstract Task<long> GetFileSizeAsync(string domain, string path);
-        public abstract Task<long> GetDirectorySizeAsync(string domain, string path);
-        public abstract Task<long> ResetQuotaAsync(string domain);
-        public abstract Task<long> GetUsedQuotaAsync(string domain);
-        public abstract Task<Uri> CopyAsync(string srcdomain, string path, string newdomain, string newpath);
-        public abstract Task CopyDirectoryAsync(string srcdomain, string dir, string newdomain, string newdir);
+    public abstract Task<bool> IsDirectoryAsync(string domain, string path);
+    public abstract Task DeleteDirectoryAsync(string domain, string path);
+    public abstract Task<long> GetFileSizeAsync(string domain, string path);
+    public abstract Task<long> GetDirectorySizeAsync(string domain, string path);
+    public abstract Task<long> ResetQuotaAsync(string domain);
+    public abstract Task<long> GetUsedQuotaAsync(string domain);
+    public abstract Task<Uri> CopyAsync(string srcdomain, string path, string newdomain, string newpath);
+    public abstract Task CopyDirectoryAsync(string srcdomain, string dir, string newdomain, string newdir);
 
-        public Task<Stream> GetReadStreamAsync(string path)
+    public Task<Stream> GetReadStreamAsync(string path)
     {
-            return GetReadStreamAsync(string.Empty, path);
+        return GetReadStreamAsync(string.Empty, path);
     }
 
-        public Task<Uri> SaveAsync(string path, Stream stream, string attachmentFileName)
+    public Task<Uri> SaveAsync(string path, Stream stream, string attachmentFileName)
     {
-            return SaveAsync(string.Empty, path, stream, attachmentFileName);
+        return SaveAsync(string.Empty, path, stream, attachmentFileName);
     }
 
-        public Task<Uri> SaveAsync(string path, Stream stream)
+    public Task<Uri> SaveAsync(string path, Stream stream)
     {
-            return SaveAsync(string.Empty, path, stream);
+        return SaveAsync(string.Empty, path, stream);
     }
 
-        public async Task DeleteAsync(string path)
+    public async Task DeleteAsync(string path)
     {
-            await DeleteAsync(string.Empty, path);
+        await DeleteAsync(string.Empty, path);
     }
 
-        public async Task DeleteFilesAsync(string folderPath, string pattern, bool recursive)
+    public async Task DeleteFilesAsync(string folderPath, string pattern, bool recursive)
     {
-            await DeleteFilesAsync(string.Empty, folderPath, pattern, recursive);
+        await DeleteFilesAsync(string.Empty, folderPath, pattern, recursive);
     }
 
-        public Task<Uri> MoveAsync(string srcpath, string newdomain, string newpath)
+    public Task<Uri> MoveAsync(string srcpath, string newdomain, string newpath)
     {
-            return MoveAsync(string.Empty, srcpath, newdomain, newpath);
+        return MoveAsync(string.Empty, srcpath, newdomain, newpath);
     }
 
-        public Task<Uri> SaveTempAsync(out string assignedPath, Stream stream)
+    public Task<Uri> SaveTempAsync(out string assignedPath, Stream stream)
     {
-            return SaveTempAsync(string.Empty, out assignedPath, stream);
+        return SaveTempAsync(string.Empty, out assignedPath, stream);
     }
 
-        public IAsyncEnumerable<string> ListDirectoriesRelativeAsync(string path, bool recursive)
+    public IAsyncEnumerable<string> ListDirectoriesRelativeAsync(string path, bool recursive)
     {
-            return ListDirectoriesRelativeAsync(string.Empty, path, recursive);
+        return ListDirectoriesRelativeAsync(string.Empty, path, recursive);
     }
 
-        public IAsyncEnumerable<Uri> ListFilesAsync(string path, string pattern, bool recursive)
+    public IAsyncEnumerable<Uri> ListFilesAsync(string path, string pattern, bool recursive)
     {
-            return ListFilesAsync(string.Empty, path, pattern, recursive);
+        return ListFilesAsync(string.Empty, path, pattern, recursive);
     }
 
-        public async IAsyncEnumerable<Uri> ListFilesAsync(string domain, string path, string pattern, bool recursive)
+    public async IAsyncEnumerable<Uri> ListFilesAsync(string domain, string path, string pattern, bool recursive)
     {
-            var filePaths = ListFilesRelativeAsync(domain, path, pattern, recursive);
+        var filePaths = ListFilesRelativeAsync(domain, path, pattern, recursive);
 
-            await foreach(var paths in filePaths)
-            {
-                yield return await GetUriAsync(domain, CrossPlatform.PathCombine(PathUtils.Normalize(path), paths));
-    }
+        await foreach (var paths in filePaths)
+        {
+            yield return await GetUriAsync(domain, CrossPlatform.PathCombine(PathUtils.Normalize(path), paths));
         }
-
-        public Task<bool> IsFileAsync(string path)
-    {
-            return IsFileAsync(string.Empty, path);
     }
 
-        public Task<bool> IsDirectoryAsync(string path)
+    public Task<bool> IsFileAsync(string path)
     {
-            return IsDirectoryAsync(string.Empty, path);
+        return IsFileAsync(string.Empty, path);
     }
 
-        public async Task DeleteDirectoryAsync(string path)
+    public Task<bool> IsDirectoryAsync(string path)
     {
-            await DeleteDirectoryAsync(string.Empty, path);
+        return IsDirectoryAsync(string.Empty, path);
     }
 
-        public Task<long> GetFileSizeAsync(string path)
+    public async Task DeleteDirectoryAsync(string path)
     {
-            return GetFileSizeAsync(string.Empty, path);
+        await DeleteDirectoryAsync(string.Empty, path);
     }
 
-        public Task<long> GetDirectorySizeAsync(string path)
+    public Task<long> GetFileSizeAsync(string path)
     {
-            return GetDirectorySizeAsync(string.Empty, path);
+        return GetFileSizeAsync(string.Empty, path);
     }
 
-        public Task<Uri> CopyAsync(string path, string newdomain, string newpath)
+    public Task<long> GetDirectorySizeAsync(string path)
     {
-            return CopyAsync(string.Empty, path, newdomain, newpath);
+        return GetDirectorySizeAsync(string.Empty, path);
     }
 
-        public async Task CopyDirectoryAsync(string dir, string newdomain, string newdir)
+    public Task<Uri> CopyAsync(string path, string newdomain, string newpath)
     {
-            await CopyDirectoryAsync(string.Empty, dir, newdomain, newdir);
+        return CopyAsync(string.Empty, path, newdomain, newpath);
+    }
+
+    public async Task CopyDirectoryAsync(string dir, string newdomain, string newdir)
+    {
+        await CopyDirectoryAsync(string.Empty, dir, newdomain, newdir);
     }
 
     public virtual IDataStore Configure(string tenant, Handler handlerConfig, Module moduleConfig, IDictionary<string, string> props)
@@ -316,13 +313,13 @@ public abstract class BaseStorage : IDataStore
         return this;
     }
 
-        public abstract Task<string> SavePrivateAsync(string domain, string path, Stream stream, DateTime expires);
-        public abstract Task DeleteExpiredAsync(string domain, string path, TimeSpan oldThreshold);
+    public abstract Task<string> SavePrivateAsync(string domain, string path, Stream stream, DateTime expires);
+    public abstract Task DeleteExpiredAsync(string domain, string path, TimeSpan oldThreshold);
 
     public abstract string GetUploadForm(string domain, string directoryPath, string redirectTo, long maxUploadSize,
                                          string contentType, string contentDisposition, string submitLabel);
 
-        public abstract Task<string> GetUploadedUrlAsync(string domain, string directoryPath);
+    public abstract Task<string> GetUploadedUrlAsync(string domain, string directoryPath);
     public abstract string GetUploadUrl();
 
     public abstract string GetPostParams(string domain, string directoryPath, long maxUploadSize, string contentType,
diff --git a/common/ASC.Data.Storage/CrossModuleTransferUtility.cs b/common/ASC.Data.Storage/CrossModuleTransferUtility.cs
index cfe4b6baa8..a8af15a9c9 100644
--- a/common/ASC.Data.Storage/CrossModuleTransferUtility.cs
+++ b/common/ASC.Data.Storage/CrossModuleTransferUtility.cs
@@ -55,25 +55,10 @@ public class CrossModuleTransferUtility
 
     public Task CopyFileAsync(string srcDomain, string srcPath, string destDomain, string destPath)
     {
-        if (srcDomain == null)
-        {
-            throw new ArgumentNullException(nameof(srcDomain));
-        }
-
-        if (srcPath == null)
-        {
-            throw new ArgumentNullException(nameof(srcPath));
-        }
-
-        if (destDomain == null)
-        {
-            throw new ArgumentNullException(nameof(destDomain));
-        }
-
-        if (destPath == null)
-        {
-            throw new ArgumentNullException(nameof(destPath));
-        }
+        ArgumentNullException.ThrowIfNull(srcDomain);
+        ArgumentNullException.ThrowIfNull(srcPath);
+        ArgumentNullException.ThrowIfNull(destDomain);
+        ArgumentNullException.ThrowIfNull(destPath);
 
         return InternalCopyFileAsync(srcDomain, srcPath, destDomain, destPath);
     }
diff --git a/common/ASC.Data.Storage/DiscStorage/DiscDataStore.cs b/common/ASC.Data.Storage/DiscStorage/DiscDataStore.cs
index 7b8cea0c73..7d6082ab06 100644
--- a/common/ASC.Data.Storage/DiscStorage/DiscDataStore.cs
+++ b/common/ASC.Data.Storage/DiscStorage/DiscDataStore.cs
@@ -82,27 +82,21 @@ public class DiscDataStore : BaseStorage
 
     public string GetPhysicalPath(string domain, string path)
     {
-        if (path == null)
-        {
-            throw new ArgumentNullException(nameof(path));
-        }
+        ArgumentNullException.ThrowIfNull(path);
 
         var pathMap = GetPath(domain);
 
         return (pathMap.PhysicalPath + EnsureLeadingSlash(path)).Replace('\\', '/');
     }
 
-        public override Task<Stream> GetReadStreamAsync(string domain, string path)
+    public override Task<Stream> GetReadStreamAsync(string domain, string path)
     {
-            return Task.FromResult(GetReadStream(domain, path, true));
+        return Task.FromResult(GetReadStream(domain, path, true));
     }
 
     public Stream GetReadStream(string domain, string path, bool withDecription)
     {
-        if (path == null)
-        {
-            throw new ArgumentNullException(nameof(path));
-        }
+        ArgumentNullException.ThrowIfNull(path);
 
         var target = GetTarget(domain, path);
 
@@ -116,10 +110,7 @@ public class DiscDataStore : BaseStorage
 
     public override Task<Stream> GetReadStreamAsync(string domain, string path, int offset)
     {
-        if (path == null)
-        {
-            throw new ArgumentNullException(nameof(path));
-        }
+        ArgumentNullException.ThrowIfNull(path);
 
         var target = GetTarget(domain, path);
 
@@ -131,24 +122,24 @@ public class DiscDataStore : BaseStorage
                 stream.Seek(offset, SeekOrigin.Begin);
             }
 
-                return Task.FromResult(stream);
+            return Task.FromResult(stream);
         }
 
         throw new FileNotFoundException("File not found", Path.GetFullPath(target));
     }
 
 
-        public override Task<Uri> SaveAsync(string domain, string path, Stream stream, string contentType, string contentDisposition)
+    public override Task<Uri> SaveAsync(string domain, string path, Stream stream, string contentType, string contentDisposition)
     {
-            return SaveAsync(domain, path, stream);
+        return SaveAsync(domain, path, stream);
     }
 
-        public override Task<Uri> SaveAsync(string domain, string path, Stream stream, string contentEncoding, int cacheDays)
+    public override Task<Uri> SaveAsync(string domain, string path, Stream stream, string contentEncoding, int cacheDays)
     {
-            return SaveAsync(domain, path, stream);
+        return SaveAsync(domain, path, stream);
     }
 
-        public override Task<Uri> SaveAsync(string domain, string path, Stream stream)
+    public override Task<Uri> SaveAsync(string domain, string path, Stream stream)
     {
         Logger.Debug("Save " + path);
 
@@ -158,23 +149,16 @@ public class DiscDataStore : BaseStorage
             QuotaController.QuotaUsedCheck(buffered.Length);
         }
 
-        if (path == null)
-        {
-            throw new ArgumentNullException(nameof(path));
-        }
-
-        if (buffered == null)
-        {
-            throw new ArgumentNullException(nameof(stream));
-        }
+        ArgumentNullException.ThrowIfNull(path);
+        ArgumentNullException.ThrowIfNull(stream);
 
         //Try seek to start
-            return InternalSaveAsync(domain, path, buffered);
-        }
+        return InternalSaveAsync(domain, path, buffered);
+    }
 
-        private async Task<Uri> InternalSaveAsync(string domain, string path, Stream buffered)
-        {
-            //Try seek to start
+    private async Task<Uri> InternalSaveAsync(string domain, string path, Stream buffered)
+    {
+        //Try seek to start
         if (buffered.CanSeek)
         {
             buffered.Seek(0, SeekOrigin.Begin);
@@ -195,7 +179,7 @@ public class DiscDataStore : BaseStorage
         else
         {
             using var fs = File.Open(target, FileMode.Create);
-                await buffered.CopyToAsync(fs);
+            await buffered.CopyToAsync(fs);
             fslen = fs.Length;
         }
 
@@ -203,30 +187,30 @@ public class DiscDataStore : BaseStorage
 
         _crypt.EncryptFile(target);
 
-            return await GetUriAsync(domain, path);
+        return await GetUriAsync(domain, path);
     }
 
-        public override Task<Uri> SaveAsync(string domain, string path, Stream stream, ACL acl)
+    public override Task<Uri> SaveAsync(string domain, string path, Stream stream, ACL acl)
     {
-            return SaveAsync(domain, path, stream);
+        return SaveAsync(domain, path, stream);
     }
 
     #region chunking
 
-        public override async Task<string> UploadChunkAsync(string domain, string path, string uploadId, Stream stream, long defaultChunkSize, int chunkNumber, long chunkLength)
+    public override async Task<string> UploadChunkAsync(string domain, string path, string uploadId, Stream stream, long defaultChunkSize, int chunkNumber, long chunkLength)
     {
         var target = GetTarget(domain, path);
         var mode = chunkNumber == 0 ? FileMode.Create : FileMode.Append;
 
         using (var fs = new FileStream(target, mode))
         {
-                await stream.CopyToAsync(fs);
+            await stream.CopyToAsync(fs);
         }
 
         return string.Format("{0}_{1}", chunkNumber, uploadId);
     }
 
-        public override Task<Uri> FinalizeChunkedUploadAsync(string domain, string path, string uploadId, Dictionary<int, string> eTags)
+    public override Task<Uri> FinalizeChunkedUploadAsync(string domain, string path, string uploadId, Dictionary<int, string> eTags)
     {
         var target = GetTarget(domain, path);
 
@@ -243,27 +227,24 @@ public class DiscDataStore : BaseStorage
 
         _crypt.EncryptFile(target);
 
-            return GetUriAsync(domain, path);
+        return GetUriAsync(domain, path);
     }
 
-        public override Task AbortChunkedUploadAsync(string domain, string path, string uploadId)
+    public override Task AbortChunkedUploadAsync(string domain, string path, string uploadId)
     {
         var target = GetTarget(domain, path);
         if (File.Exists(target))
         {
             File.Delete(target);
         }
-            return Task.CompletedTask;
+        return Task.CompletedTask;
     }
 
     #endregion
 
-        public override Task DeleteAsync(string domain, string path)
+    public override Task DeleteAsync(string domain, string path)
     {
-        if (path == null)
-        {
-            throw new ArgumentNullException(nameof(path));
-        }
+        ArgumentNullException.ThrowIfNull(path);
 
         var target = GetTarget(domain, path);
 
@@ -273,7 +254,7 @@ public class DiscDataStore : BaseStorage
             File.Delete(target);
 
             QuotaUsedDelete(domain, size);
-                return Task.CompletedTask; ;
+            return Task.CompletedTask; ;
         }
         else
         {
@@ -281,12 +262,9 @@ public class DiscDataStore : BaseStorage
         }
     }
 
-        public override Task DeleteFilesAsync(string domain, List<string> paths)
+    public override Task DeleteFilesAsync(string domain, List<string> paths)
     {
-        if (paths == null)
-        {
-            throw new ArgumentNullException(nameof(paths));
-        }
+        ArgumentNullException.ThrowIfNull(paths);
 
         foreach (var path in paths)
         {
@@ -303,15 +281,12 @@ public class DiscDataStore : BaseStorage
             QuotaUsedDelete(domain, size);
         }
 
-            return Task.CompletedTask;
+        return Task.CompletedTask;
     }
 
-        public override Task DeleteFilesAsync(string domain, string folderPath, string pattern, bool recursive)
+    public override Task DeleteFilesAsync(string domain, string folderPath, string pattern, bool recursive)
     {
-        if (folderPath == null)
-        {
-            throw new ArgumentNullException(nameof(folderPath));
-        }
+        ArgumentNullException.ThrowIfNull(folderPath);
 
         //Return dirs
         var targetDir = GetTarget(domain, folderPath);
@@ -324,20 +299,17 @@ public class DiscDataStore : BaseStorage
                 File.Delete(entry);
                 QuotaUsedDelete(domain, size);
             }
-                return Task.CompletedTask;
+            return Task.CompletedTask;
         }
         else
         {
-                throw new DirectoryNotFoundException($"Directory '{targetDir}' not found");
+            throw new DirectoryNotFoundException($"Directory '{targetDir}' not found");
         }
     }
 
-        public override Task DeleteFilesAsync(string domain, string folderPath, DateTime fromDate, DateTime toDate)
+    public override Task DeleteFilesAsync(string domain, string folderPath, DateTime fromDate, DateTime toDate)
     {
-        if (folderPath == null)
-        {
-            throw new ArgumentNullException(nameof(folderPath));
-        }
+        ArgumentNullException.ThrowIfNull(folderPath);
 
         //Return dirs
         var targetDir = GetTarget(domain, folderPath);
@@ -357,13 +329,13 @@ public class DiscDataStore : BaseStorage
         }
         else
         {
-                throw new DirectoryNotFoundException($"Directory '{targetDir}' not found");
+            throw new DirectoryNotFoundException($"Directory '{targetDir}' not found");
         }
 
-            return Task.CompletedTask;
+        return Task.CompletedTask;
     }
 
-        public override Task MoveDirectoryAsync(string srcdomain, string srcdir, string newdomain, string newdir)
+    public override Task MoveDirectoryAsync(string srcdomain, string srcdir, string newdomain, string newdir)
     {
         var target = GetTarget(srcdomain, srcdir);
         var newtarget = GetTarget(newdomain, newdir);
@@ -376,20 +348,13 @@ public class DiscDataStore : BaseStorage
 
         Directory.Move(target, newtarget);
 
-            return Task.CompletedTask;
+        return Task.CompletedTask;
     }
 
-        public override Task<Uri> MoveAsync(string srcdomain, string srcpath, string newdomain, string newpath, bool quotaCheckFileSize = true)
+    public override Task<Uri> MoveAsync(string srcdomain, string srcpath, string newdomain, string newpath, bool quotaCheckFileSize = true)
     {
-        if (srcpath == null)
-        {
-            throw new ArgumentNullException(nameof(srcpath));
-        }
-
-        if (newpath == null)
-        {
-            throw new ArgumentNullException(nameof(srcpath));
-        }
+        ArgumentNullException.ThrowIfNull(srcpath);
+        ArgumentNullException.ThrowIfNull(newpath);
 
         var target = GetTarget(srcdomain, srcpath);
         var newtarget = GetTarget(newdomain, newpath);
@@ -418,15 +383,12 @@ public class DiscDataStore : BaseStorage
         {
             throw new FileNotFoundException("File not found", Path.GetFullPath(target));
         }
-            return GetUriAsync(newdomain, newpath);
+        return GetUriAsync(newdomain, newpath);
     }
 
-        public override Task<bool> IsDirectoryAsync(string domain, string path)
+    public override Task<bool> IsDirectoryAsync(string domain, string path)
     {
-        if (path == null)
-        {
-            throw new ArgumentNullException(nameof(path));
-        }
+        ArgumentNullException.ThrowIfNull(path);
 
         //Return dirs
         var targetDir = GetTarget(domain, path);
@@ -434,15 +396,12 @@ public class DiscDataStore : BaseStorage
         {
             targetDir += Path.DirectorySeparatorChar;
         }
-            return Task.FromResult(!string.IsNullOrEmpty(targetDir) && Directory.Exists(targetDir));
+        return Task.FromResult(!string.IsNullOrEmpty(targetDir) && Directory.Exists(targetDir));
     }
 
-        public override Task DeleteDirectoryAsync(string domain, string path)
+    public override Task DeleteDirectoryAsync(string domain, string path)
     {
-        if (path == null)
-        {
-            throw new ArgumentNullException(nameof(path));
-        }
+        ArgumentNullException.ThrowIfNull(path);
 
         //Return dirs
         var targetDir = GetTarget(domain, path);
@@ -452,12 +411,12 @@ public class DiscDataStore : BaseStorage
             throw new Exception("targetDir is null");
         }
 
-            if (!targetDir.EndsWith(Path.DirectorySeparatorChar.ToString()))
+        if (!targetDir.EndsWith(Path.DirectorySeparatorChar.ToString()))
         {
             targetDir += Path.DirectorySeparatorChar;
         }
 
-            if (!Directory.Exists(targetDir)) return Task.CompletedTask;
+        if (!Directory.Exists(targetDir)) return Task.CompletedTask;
 
         var entries = Directory.GetFiles(targetDir, "*.*", SearchOption.AllDirectories);
         var size = entries.Select(entry => _crypt.GetFileSize(entry)).Sum();
@@ -469,59 +428,56 @@ public class DiscDataStore : BaseStorage
         Directory.Delete(targetDir, true);
 
         QuotaUsedDelete(domain, size);
-            return Task.CompletedTask;
+        return Task.CompletedTask;
     }
 
-        public override Task<long> GetFileSizeAsync(string domain, string path)
+    public override Task<long> GetFileSizeAsync(string domain, string path)
     {
         var target = GetTarget(domain, path);
 
         if (File.Exists(target))
         {
-                return Task.FromResult(_crypt.GetFileSize(target));
+            return Task.FromResult(_crypt.GetFileSize(target));
         }
 
         throw new FileNotFoundException("file not found " + target);
     }
 
-        public override Task<long> GetDirectorySizeAsync(string domain, string path)
+    public override Task<long> GetDirectorySizeAsync(string domain, string path)
     {
         var target = GetTarget(domain, path);
 
         if (Directory.Exists(target))
         {
-                return Task.FromResult(Directory.GetFiles(target, "*.*", SearchOption.AllDirectories)
-                .Select(entry => _crypt.GetFileSize(entry))
-                    .Sum());
+            return Task.FromResult(Directory.GetFiles(target, "*.*", SearchOption.AllDirectories)
+            .Select(entry => _crypt.GetFileSize(entry))
+                .Sum());
         }
 
         throw new FileNotFoundException("directory not found " + target);
     }
 
-        public override Task<Uri> SaveTempAsync(string domain, out string assignedPath, Stream stream)
+    public override Task<Uri> SaveTempAsync(string domain, out string assignedPath, Stream stream)
     {
         assignedPath = Guid.NewGuid().ToString();
-            return SaveAsync(domain, assignedPath, stream);
+        return SaveAsync(domain, assignedPath, stream);
     }
 
-        public override async Task<string> SavePrivateAsync(string domain, string path, Stream stream, DateTime expires)
+    public override async Task<string> SavePrivateAsync(string domain, string path, Stream stream, DateTime expires)
     {
-            var result = await SaveAsync(domain, path, stream);
-            return result.ToString();
+        var result = await SaveAsync(domain, path, stream);
+        return result.ToString();
     }
 
-        public override Task DeleteExpiredAsync(string domain, string folderPath, TimeSpan oldThreshold)
+    public override Task DeleteExpiredAsync(string domain, string folderPath, TimeSpan oldThreshold)
     {
-        if (folderPath == null)
-        {
-            throw new ArgumentNullException(nameof(folderPath));
-        }
+        ArgumentNullException.ThrowIfNull(folderPath);
 
         //Return dirs
         var targetDir = GetTarget(domain, folderPath);
         if (!Directory.Exists(targetDir))
         {
-                return Task.CompletedTask;
+            return Task.CompletedTask;
         }
 
         var entries = Directory.GetFiles(targetDir, "*.*", SearchOption.TopDirectoryOnly);
@@ -537,7 +493,7 @@ public class DiscDataStore : BaseStorage
             }
         }
 
-            return Task.CompletedTask;
+        return Task.CompletedTask;
     }
 
     public override string GetUploadForm(string domain, string directoryPath, string redirectTo, long maxUploadSize, string contentType, string contentDisposition, string submitLabel)
@@ -545,7 +501,7 @@ public class DiscDataStore : BaseStorage
         throw new NotSupportedException("This operation supported only on s3 storage");
     }
 
-        public override Task<string> GetUploadedUrlAsync(string domain, string directoryPath)
+    public override Task<string> GetUploadedUrlAsync(string domain, string directoryPath)
     {
         throw new NotSupportedException("This operation supported only on s3 storage");
     }
@@ -560,12 +516,9 @@ public class DiscDataStore : BaseStorage
         throw new NotSupportedException("This operation supported only on s3 storage");
     }
 
-        public override IAsyncEnumerable<string> ListDirectoriesRelativeAsync(string domain, string path, bool recursive)
+    public override IAsyncEnumerable<string> ListDirectoriesRelativeAsync(string domain, string path, bool recursive)
     {
-        if (path == null)
-        {
-            throw new ArgumentNullException(nameof(path));
-        }
+        ArgumentNullException.ThrowIfNull(path);
 
         //Return dirs
         var targetDir = GetTarget(domain, path);
@@ -577,20 +530,17 @@ public class DiscDataStore : BaseStorage
         if (Directory.Exists(targetDir))
         {
             var entries = Directory.GetDirectories(targetDir, "*", recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);
-                var tmp =  Array.ConvertAll(
-                entries,
-                x => x.Substring(targetDir.Length));
-                return tmp.ToAsyncEnumerable();
+            var tmp = Array.ConvertAll(
+            entries,
+            x => x.Substring(targetDir.Length));
+            return tmp.ToAsyncEnumerable();
         }
-            return AsyncEnumerable.Empty<string>();
+        return AsyncEnumerable.Empty<string>();
     }
 
-        public override IAsyncEnumerable<string> ListFilesRelativeAsync(string domain, string path, string pattern, bool recursive)
+    public override IAsyncEnumerable<string> ListFilesRelativeAsync(string domain, string path, string pattern, bool recursive)
     {
-        if (path == null)
-        {
-            throw new ArgumentNullException(nameof(path));
-        }
+        ArgumentNullException.ThrowIfNull(path);
 
         //Return dirs
         var targetDir = GetTarget(domain, path);
@@ -602,39 +552,36 @@ public class DiscDataStore : BaseStorage
         if (Directory.Exists(targetDir))
         {
             var entries = Directory.GetFiles(targetDir, pattern, recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);
-                var tmp = Array.ConvertAll(
-                entries,
-                x => x.Substring(targetDir.Length));
-                return tmp.ToAsyncEnumerable();
+            var tmp = Array.ConvertAll(
+            entries,
+            x => x.Substring(targetDir.Length));
+            return tmp.ToAsyncEnumerable();
         }
-            return AsyncEnumerable.Empty<string>();
+        return AsyncEnumerable.Empty<string>();
     }
 
-        public override Task<bool> IsFileAsync(string domain, string path)
+    public override Task<bool> IsFileAsync(string domain, string path)
     {
-        if (path == null)
-        {
-            throw new ArgumentNullException(nameof(path));
-        }
+        ArgumentNullException.ThrowIfNull(path);
 
         //Return dirs
         var target = GetTarget(domain, path);
         var result = File.Exists(target);
-            return Task.FromResult(result);
+        return Task.FromResult(result);
     }
 
-        public override async Task<long> ResetQuotaAsync(string domain)
+    public override async Task<long> ResetQuotaAsync(string domain)
     {
         if (QuotaController != null)
         {
-                var size = await GetUsedQuotaAsync(domain);
+            var size = await GetUsedQuotaAsync(domain);
             QuotaController.QuotaUsedSet(Modulename, domain, DataList.GetData(domain), size);
         }
 
         return 0;
     }
 
-        public override Task<long> GetUsedQuotaAsync(string domain)
+    public override Task<long> GetUsedQuotaAsync(string domain)
     {
         var target = GetTarget(domain, string.Empty);
         long size = 0;
@@ -644,20 +591,13 @@ public class DiscDataStore : BaseStorage
             var entries = Directory.GetFiles(target, "*.*", SearchOption.AllDirectories);
             size = entries.Select(entry => _crypt.GetFileSize(entry)).Sum();
         }
-            return Task.FromResult(size);
+        return Task.FromResult(size);
     }
 
-        public override Task<Uri> CopyAsync(string srcdomain, string srcpath, string newdomain, string newpath)
+    public override Task<Uri> CopyAsync(string srcdomain, string srcpath, string newdomain, string newpath)
     {
-        if (srcpath == null)
-        {
-            throw new ArgumentNullException(nameof(srcpath));
-        }
-
-        if (newpath == null)
-        {
-            throw new ArgumentNullException(nameof(srcpath));
-        }
+        ArgumentNullException.ThrowIfNull(srcpath);
+        ArgumentNullException.ThrowIfNull(newpath);
 
         var target = GetTarget(srcdomain, srcpath);
         var newtarget = GetTarget(newdomain, newpath);
@@ -678,10 +618,10 @@ public class DiscDataStore : BaseStorage
         {
             throw new FileNotFoundException("File not found", Path.GetFullPath(target));
         }
-            return GetUriAsync(newdomain, newpath);
+        return GetUriAsync(newdomain, newpath);
     }
 
-        public override Task CopyDirectoryAsync(string srcdomain, string srcdir, string newdomain, string newdir)
+    public override Task CopyDirectoryAsync(string srcdomain, string srcdir, string newdomain, string newdir)
     {
         var target = GetTarget(srcdomain, srcdir);
         var newtarget = GetTarget(newdomain, newdir);
@@ -690,7 +630,7 @@ public class DiscDataStore : BaseStorage
         var diTarget = new DirectoryInfo(newtarget);
 
         CopyAll(diSource, diTarget, newdomain);
-            return Task.CompletedTask;
+        return Task.CompletedTask;
     }
 
 
@@ -701,10 +641,7 @@ public class DiscDataStore : BaseStorage
 
     public Stream GetWriteStream(string domain, string path, FileMode fileMode)
     {
-        if (path == null)
-        {
-            throw new ArgumentNullException(nameof(path));
-        }
+        ArgumentNullException.ThrowIfNull(path);
 
         var target = GetTarget(domain, path);
         CreateDirectory(target);
@@ -714,10 +651,7 @@ public class DiscDataStore : BaseStorage
 
     public void Decrypt(string domain, string path)
     {
-        if (path == null)
-        {
-            throw new ArgumentNullException(nameof(path));
-        }
+        ArgumentNullException.ThrowIfNull(path);
 
         var target = GetTarget(domain, path);
 
@@ -731,10 +665,10 @@ public class DiscDataStore : BaseStorage
         }
     }
 
-        protected override Task<Uri> SaveWithAutoAttachmentAsync(string domain, string path, Stream stream, string attachmentFileName)
-        {
-            return SaveAsync(domain, path, stream);
-        }
+    protected override Task<Uri> SaveWithAutoAttachmentAsync(string domain, string path, Stream stream, string attachmentFileName)
+    {
+        return SaveAsync(domain, path, stream);
+    }
 
     private void CopyAll(DirectoryInfo source, DirectoryInfo target, string newdomain)
     {
@@ -765,7 +699,7 @@ public class DiscDataStore : BaseStorage
     {
         if (domain != null && _mappedPaths.TryGetValue(domain, out var value))
         {
-                    return value;
+            return value;
         }
 
         return _mappedPaths[string.Empty].AppendDomain(domain);
@@ -802,10 +736,7 @@ public class DiscDataStore : BaseStorage
 
     public void Encrypt(string domain, string path)
     {
-        if (path == null)
-        {
-            throw new ArgumentNullException(nameof(path));
-        }
+        ArgumentNullException.ThrowIfNull(path);
 
         var target = GetTarget(domain, path);
 
diff --git a/common/ASC.Data.Storage/TenantPath.cs b/common/ASC.Data.Storage/TenantPath.cs
index 3fc430f168..401f5cc829 100644
--- a/common/ASC.Data.Storage/TenantPath.cs
+++ b/common/ASC.Data.Storage/TenantPath.cs
@@ -29,10 +29,7 @@ public static class TenantPath
 {
     public static string CreatePath(string tenant)
     {
-        if (tenant == null)
-        {
-                throw new ArgumentNullException(nameof(tenant));
-        }
+        ArgumentNullException.ThrowIfNull(tenant);
 
         if (long.TryParse(tenant, NumberStyles.Integer, CultureInfo.InvariantCulture, out var tenantId))
         {
diff --git a/common/ASC.FederatedLogin/Helpers/OAuth20TokenHelper.cs b/common/ASC.FederatedLogin/Helpers/OAuth20TokenHelper.cs
index 1eb7698c91..e61ddc08fe 100644
--- a/common/ASC.FederatedLogin/Helpers/OAuth20TokenHelper.cs
+++ b/common/ASC.FederatedLogin/Helpers/OAuth20TokenHelper.cs
@@ -107,20 +107,9 @@ public class OAuth20TokenHelper
         var clientSecret = loginProvider.ClientSecret;
         var redirectUri = loginProvider.RedirectUri;
 
-        if (string.IsNullOrEmpty(authCode))
-        {
-            throw new ArgumentNullException(nameof(authCode));
-        }
-
-        if (string.IsNullOrEmpty(clientID))
-        {
-            throw new ArgumentNullException(nameof(clientID));
-        }
-
-        if (string.IsNullOrEmpty(clientSecret))
-        {
-            throw new ArgumentNullException(nameof(clientSecret));
-        }
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(authCode);
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(clientID);
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(clientSecret);
 
         var data = $"code={HttpUtility.UrlEncode(authCode)}&client_id={HttpUtility.UrlEncode(clientID)}&client_secret={HttpUtility.UrlEncode(clientSecret)}";
 
diff --git a/common/ASC.FederatedLogin/Helpers/RequestHelper.cs b/common/ASC.FederatedLogin/Helpers/RequestHelper.cs
index 1257bbf620..e40f37602c 100644
--- a/common/ASC.FederatedLogin/Helpers/RequestHelper.cs
+++ b/common/ASC.FederatedLogin/Helpers/RequestHelper.cs
@@ -31,10 +31,7 @@ public static class RequestHelper
 
     public static string PerformRequest(string uri, string contentType = "", string method = "GET", string body = "", Dictionary<string, string> headers = null, int timeout = 30000)
     {
-        if (string.IsNullOrEmpty(uri))
-        {
-            throw new ArgumentNullException(nameof(uri));
-        }
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(uri);
 
         var request = new HttpRequestMessage();
         request.RequestUri = new Uri(uri);
diff --git a/common/ASC.FederatedLogin/LoginProviders/DocuSignLoginProvider.cs b/common/ASC.FederatedLogin/LoginProviders/DocuSignLoginProvider.cs
index 9f7fcfb9b4..0e3ebd5149 100644
--- a/common/ASC.FederatedLogin/LoginProviders/DocuSignLoginProvider.cs
+++ b/common/ASC.FederatedLogin/LoginProviders/DocuSignLoginProvider.cs
@@ -73,20 +73,9 @@ public class DocuSignLoginProvider : Consumer, IOAuthProvider
 
     public OAuth20Token GetAccessToken(string authCode)
     {
-        if (string.IsNullOrEmpty(authCode))
-        {
-            throw new ArgumentNullException(nameof(authCode));
-        }
-
-        if (string.IsNullOrEmpty(ClientID))
-        {
-            throw new ArgumentException(nameof(ClientID));
-        }
-
-        if (string.IsNullOrEmpty(ClientSecret))
-        {
-            throw new ArgumentException(nameof(ClientSecret));
-        }
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(authCode);
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(ClientID);
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(ClientSecret);
 
         var data = $"grant_type=authorization_code&code={authCode}";
         var headers = new Dictionary<string, string> { { "Authorization", AuthHeader } };
diff --git a/common/ASC.FederatedLogin/Profile/LoginProfile.cs b/common/ASC.FederatedLogin/Profile/LoginProfile.cs
index 290830561b..f6085ec483 100644
--- a/common/ASC.FederatedLogin/Profile/LoginProfile.cs
+++ b/common/ASC.FederatedLogin/Profile/LoginProfile.cs
@@ -204,10 +204,7 @@ public class LoginProfile
 
     public static bool HasProfile(HttpRequest request)
     {
-        if (request == null)
-        {
-            throw new ArgumentNullException(nameof(request));
-        }
+        ArgumentNullException.ThrowIfNull(request);
 
         return new Uri(request.GetDisplayUrl()).HasProfile();
     }
@@ -239,10 +236,7 @@ public class LoginProfile
 
     internal void SetField(string name, string value)
     {
-        if (name == null)
-        {
-            throw new ArgumentNullException(nameof(name));
-        }
+        ArgumentNullException.ThrowIfNull(name);
 
         if (!string.IsNullOrEmpty(value))
         {
@@ -328,10 +322,7 @@ public class LoginProfile
 
     internal void FromSerializedString(string serialized)
     {
-        if (serialized == null)
-        {
-            throw new ArgumentNullException(nameof(serialized));
-        }
+        ArgumentNullException.ThrowIfNull(serialized);
 
         _fields = serialized.Split(PairSeparator).ToDictionary(x => x.Split(KeyValueSeparator)[0], y => y.Split(KeyValueSeparator)[1]);
     }
@@ -355,10 +346,7 @@ public class LoginProfile
 
     protected LoginProfile(Signature signature, InstanceCrypto instanceCrypto, SerializationInfo info) : this(signature, instanceCrypto)
     {
-        if (info == null)
-        {
-            throw new ArgumentNullException(nameof(info));
-        }
+        ArgumentNullException.ThrowIfNull(info);
 
         var transformed = (string)info.GetValue(QueryParamName, typeof(string));
         FromTransport(transformed);
diff --git a/common/ASC.VoipService/Twilio/TwilioProvider.cs b/common/ASC.VoipService/Twilio/TwilioProvider.cs
index 6dd2f9bdfe..a4acab3dc1 100644
--- a/common/ASC.VoipService/Twilio/TwilioProvider.cs
+++ b/common/ASC.VoipService/Twilio/TwilioProvider.cs
@@ -41,8 +41,8 @@ public class TwilioProvider : IVoipProvider
 
     public TwilioProvider(string accountSid, string authToken, AuthContext authContext, TenantUtil tenantUtil, SecurityContext securityContext, BaseCommonLinkUtility baseCommonLinkUtility)
     {
-        if (string.IsNullOrEmpty(accountSid)) throw new ArgumentNullException(nameof(accountSid));
-        if (string.IsNullOrEmpty(authToken)) throw new ArgumentNullException(nameof(authToken));
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(accountSid);
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(authToken);
 
         _authToken = authToken;
         _authContext = authContext;
diff --git a/products/ASC.Files/Core/ApiModels/Binders.cs b/products/ASC.Files/Core/ApiModels/Binders.cs
index 3474267442..bfc4f33cdc 100644
--- a/products/ASC.Files/Core/ApiModels/Binders.cs
+++ b/products/ASC.Files/Core/ApiModels/Binders.cs
@@ -71,10 +71,7 @@ public class BaseBatchModelBinder : IModelBinder
 {
     public virtual Task BindModelAsync(ModelBindingContext bindingContext)
     {
-        if (bindingContext == null)
-        {
-            throw new ArgumentNullException(nameof(bindingContext));
-        }
+        ArgumentNullException.ThrowIfNull(bindingContext);
 
         var result = new BaseBatchRequestDto();
 
@@ -92,10 +89,7 @@ public class DeleteBatchModelBinder : BaseBatchModelBinder
     public override Task BindModelAsync(ModelBindingContext bindingContext)
     {
         base.BindModelAsync(bindingContext);
-        if (bindingContext == null)
-        {
-            throw new ArgumentNullException(nameof(bindingContext));
-        }
+        ArgumentNullException.ThrowIfNull(bindingContext);
 
         var result = new DeleteBatchRequestDto();
 
@@ -132,10 +126,7 @@ public class BatchModelBinder : BaseBatchModelBinder
     public override Task BindModelAsync(ModelBindingContext bindingContext)
     {
         base.BindModelAsync(bindingContext);
-        if (bindingContext == null)
-        {
-            throw new ArgumentNullException(nameof(bindingContext));
-        }
+        ArgumentNullException.ThrowIfNull(bindingContext);
 
         var result = new BatchRequestDto();
 
@@ -179,10 +170,7 @@ public class InsertFileModelBinder : IModelBinder
 {
     public async Task BindModelAsync(ModelBindingContext bindingContext)
     {
-        if (bindingContext == null)
-        {
-            throw new ArgumentNullException(nameof(bindingContext));
-        }
+        ArgumentNullException.ThrowIfNull(bindingContext);
 
         var defaultBindingContext = bindingContext as DefaultModelBindingContext;
         var composite = bindingContext.ValueProvider as CompositeValueProvider;
@@ -225,10 +213,7 @@ public class UploadModelBinder : IModelBinder
 {
     public Task BindModelAsync(ModelBindingContext bindingContext)
     {
-        if (bindingContext == null)
-        {
-            throw new ArgumentNullException(nameof(bindingContext));
-        }
+        ArgumentNullException.ThrowIfNull(bindingContext);
 
         var defaultBindingContext = bindingContext as DefaultModelBindingContext;
         var composite = bindingContext.ValueProvider as CompositeValueProvider;
diff --git a/products/ASC.Files/Core/Core/Dao/TeamlabDao/FileDao.cs b/products/ASC.Files/Core/Core/Dao/TeamlabDao/FileDao.cs
index e0ea6f8cba..a5c5baf7a9 100644
--- a/products/ASC.Files/Core/Core/Dao/TeamlabDao/FileDao.cs
+++ b/products/ASC.Files/Core/Core/Dao/TeamlabDao/FileDao.cs
@@ -120,10 +120,7 @@ internal class FileDao : AbstractDao, IFileDao<int>
 
     public Task<File<int>> GetFileAsync(int parentId, string title)
     {
-        if (string.IsNullOrEmpty(title))
-        {
-            throw new ArgumentNullException(title);
-        }
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(title);
 
         return InternalGetFileAsync(parentId, title);
     }
@@ -354,10 +351,7 @@ internal class FileDao : AbstractDao, IFileDao<int>
 
     public Task<File<int>> SaveFileAsync(File<int> file, Stream fileStream, bool checkQuota = true)
     {
-        if (file == null)
-        {
-            throw new ArgumentNullException(nameof(file));
-        }
+        ArgumentNullException.ThrowIfNull(file);
 
         var maxChunkedUploadSize = SetupInfo.MaxChunkedUploadSize(TenantExtra, TenantStatisticProvider);
         if (checkQuota && maxChunkedUploadSize < file.ContentLength)
@@ -516,10 +510,8 @@ internal class FileDao : AbstractDao, IFileDao<int>
 
     public Task<File<int>> ReplaceFileVersionAsync(File<int> file, Stream fileStream)
     {
-        if (file == null)
-        {
-            throw new ArgumentNullException(nameof(file));
-        }
+        ArgumentNullException.ThrowIfNull(file);
+
         if (file.ID == default)
         {
             throw new ArgumentException("No file id or folder id toFolderId determine provider");
@@ -1252,18 +1244,10 @@ internal class FileDao : AbstractDao, IFileDao<int>
 
     public Task SaveEditHistoryAsync(File<int> file, string changes, Stream differenceStream)
     {
-        if (file == null)
-        {
-            throw new ArgumentNullException(nameof(file));
-        }
-        if (string.IsNullOrEmpty(changes))
-        {
-            throw new ArgumentNullException(nameof(changes));
-        }
-        if (differenceStream == null)
-        {
-            throw new ArgumentNullException(nameof(differenceStream));
-        }
+        ArgumentNullException.ThrowIfNull(file);
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(changes);
+
+        ArgumentNullException.ThrowIfNull(differenceStream);
 
         return InternalSaveEditHistoryAsync(file, changes, differenceStream);
     }
@@ -1471,10 +1455,10 @@ internal class FileDao : AbstractDao, IFileDao<int>
                    case SortedByType.Size:
                        result.Sort(r => r.ContentLength, orderBy.IsAsc);
                        break;
-                       //case SortedByType.AZ:
-                       //    result.Sort(r => r.Title, orderBy.IsAsc);
-                       //    break;
-                       case SortedByType.DateAndTime:
+                   //case SortedByType.AZ:
+                   //    result.Sort(r => r.Title, orderBy.IsAsc);
+                   //    break;
+                   case SortedByType.DateAndTime:
                        result.Sort(r => r.ModifiedOn, orderBy.IsAsc);
                        break;
                    case SortedByType.DateAndTimeCreation:
diff --git a/products/ASC.Files/Core/Core/Dao/TeamlabDao/FolderDao.cs b/products/ASC.Files/Core/Core/Dao/TeamlabDao/FolderDao.cs
index 854ade3873..be035cdf81 100644
--- a/products/ASC.Files/Core/Core/Dao/TeamlabDao/FolderDao.cs
+++ b/products/ASC.Files/Core/Core/Dao/TeamlabDao/FolderDao.cs
@@ -94,10 +94,7 @@ internal class FolderDao : AbstractDao, IFolderDao<int>
 
     public Task<Folder<int>> GetFolderAsync(string title, int parentId)
     {
-        if (string.IsNullOrEmpty(title))
-        {
-            throw new ArgumentNullException(title);
-        }
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(title);
 
         return InternalGetFolderAsync(title, parentId);
     }
@@ -284,10 +281,7 @@ internal class FolderDao : AbstractDao, IFolderDao<int>
 
     public Task<int> SaveFolderAsync(Folder<int> folder, IDbContextTransaction transaction)
     {
-        if (folder == null)
-        {
-            throw new ArgumentNullException(nameof(folder));
-        }
+        ArgumentNullException.ThrowIfNull(folder);
 
         return InternalSaveFolderAsync(folder, transaction);
     }
@@ -568,7 +562,7 @@ internal class FolderDao : AbstractDao, IFolderDao<int>
                         Level = subfolder.Value + 1 + f.Level
                     };
                     await FilesDbContext.AddOrUpdateAsync(r => r.Tree, newTree).ConfigureAwait(false);
-                }   
+                }
             }
 
             await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
@@ -889,15 +883,8 @@ internal class FolderDao : AbstractDao, IFolderDao<int>
 
     public Task<IEnumerable<int>> GetFolderIDsAsync(string module, string bunch, IEnumerable<string> data, bool createIfNotExists)
     {
-        if (string.IsNullOrEmpty(module))
-        {
-            throw new ArgumentNullException(nameof(module));
-        }
-
-        if (string.IsNullOrEmpty(bunch))
-        {
-            throw new ArgumentNullException(nameof(bunch));
-        }
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(module);
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(bunch);
 
         return InternalGetFolderIDsAsync(module, bunch, data, createIfNotExists);
     }
@@ -988,14 +975,8 @@ internal class FolderDao : AbstractDao, IFolderDao<int>
 
     public Task<int> GetFolderIDAsync(string module, string bunch, string data, bool createIfNotExists)
     {
-        if (string.IsNullOrEmpty(module))
-        {
-            throw new ArgumentNullException(nameof(module));
-        }
-        if (string.IsNullOrEmpty(bunch))
-        {
-            throw new ArgumentNullException(nameof(bunch));
-        }
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(module);
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(bunch);
 
         return InternalGetFolderIDAsync(module, bunch, data, createIfNotExists);
     }
diff --git a/products/ASC.Files/Core/Core/Dao/TeamlabDao/TagDao.cs b/products/ASC.Files/Core/Core/Dao/TeamlabDao/TagDao.cs
index ff96830da8..ea49f6dde8 100644
--- a/products/ASC.Files/Core/Core/Dao/TeamlabDao/TagDao.cs
+++ b/products/ASC.Files/Core/Core/Dao/TeamlabDao/TagDao.cs
@@ -163,10 +163,7 @@ internal class TagDao<T> : AbstractDao, ITagDao<T>
 
     public IAsyncEnumerable<Tag> GetTagsAsync(string[] names, TagType tagType)
     {
-        if (names == null)
-        {
-            throw new ArgumentNullException(nameof(names));
-        }
+        ArgumentNullException.ThrowIfNull(names);
 
         return InternalGetTagsAsync(names, tagType);
     }
@@ -188,10 +185,7 @@ internal class TagDao<T> : AbstractDao, ITagDao<T>
 
     public IAsyncEnumerable<Tag> GetTagsAsync(string name, TagType tagType)
     {
-        if (string.IsNullOrEmpty(name))
-        {
-            throw new ArgumentNullException(nameof(name));
-        }
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(name);
 
         return GetTagsAsync(new[] { name }, tagType);
     }
diff --git a/products/ASC.Files/Core/Core/Entries/EncryptionKeyPair.cs b/products/ASC.Files/Core/Core/Entries/EncryptionKeyPair.cs
index fdf6312cea..dd77a3d2bb 100644
--- a/products/ASC.Files/Core/Core/Entries/EncryptionKeyPair.cs
+++ b/products/ASC.Files/Core/Core/Entries/EncryptionKeyPair.cs
@@ -57,14 +57,8 @@ public class EncryptionKeyPairHelper
 
     public void SetKeyPair(string publicKey, string privateKeyEnc)
     {
-        if (string.IsNullOrEmpty(publicKey))
-        {
-            throw new ArgumentNullException(nameof(publicKey));
-        }
-        if (string.IsNullOrEmpty(privateKeyEnc))
-        {
-            throw new ArgumentNullException(nameof(privateKeyEnc));
-        }
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(publicKey);
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(privateKeyEnc);
 
         var user = _userManager.GetUsers(_authContext.CurrentAccount.ID);
         if (!_authContext.IsAuthenticated || user.IsVisitor(_userManager))
diff --git a/products/ASC.Files/Core/Core/FilesIntegration.cs b/products/ASC.Files/Core/Core/FilesIntegration.cs
index 741b83b23c..e4a831d9d2 100644
--- a/products/ASC.Files/Core/Core/FilesIntegration.cs
+++ b/products/ASC.Files/Core/Core/FilesIntegration.cs
@@ -46,10 +46,7 @@ public class FilesIntegration
 
     public Task<IEnumerable<T>> RegisterBunchFoldersAsync<T>(string module, string bunch, IEnumerable<string> data)
     {
-        if (data == null)
-        {
-            throw new ArgumentNullException(nameof(data));
-        }
+        ArgumentNullException.ThrowIfNull(data);
 
         data = data.ToList();
         if (!data.Any())
diff --git a/products/ASC.Files/Core/Core/Thirdparty/Box/BoxFileDao.cs b/products/ASC.Files/Core/Core/Thirdparty/Box/BoxFileDao.cs
index bbbeeeadd4..17282dff06 100644
--- a/products/ASC.Files/Core/Core/Thirdparty/Box/BoxFileDao.cs
+++ b/products/ASC.Files/Core/Core/Thirdparty/Box/BoxFileDao.cs
@@ -293,14 +293,8 @@ internal class BoxFileDao : BoxDaoBase, IFileDao<string>
 
     public Task<File<string>> SaveFileAsync(File<string> file, Stream fileStream)
     {
-        if (file == null)
-        {
-            throw new ArgumentNullException(nameof(file));
-        }
-        if (fileStream == null)
-        {
-            throw new ArgumentNullException(nameof(fileStream));
-        }
+        ArgumentNullException.ThrowIfNull(file);
+        ArgumentNullException.ThrowIfNull(fileStream);
 
         return InternalSaveFileAsync(file, fileStream);
     }
diff --git a/products/ASC.Files/Core/Core/Thirdparty/Box/BoxFolderDao.cs b/products/ASC.Files/Core/Core/Thirdparty/Box/BoxFolderDao.cs
index 916fd7fbe0..ca742a54a5 100644
--- a/products/ASC.Files/Core/Core/Thirdparty/Box/BoxFolderDao.cs
+++ b/products/ASC.Files/Core/Core/Thirdparty/Box/BoxFolderDao.cs
@@ -177,10 +177,7 @@ internal class BoxFolderDao : BoxDaoBase, IFolderDao<string>
 
     public Task<string> SaveFolderAsync(Folder<string> folder)
     {
-        if (folder == null)
-        {
-            throw new ArgumentNullException(nameof(folder));
-        }
+        ArgumentNullException.ThrowIfNull(folder);
 
         return InternalSaveFolderAsync(folder);
     }
diff --git a/products/ASC.Files/Core/Core/Thirdparty/Box/BoxStorage.cs b/products/ASC.Files/Core/Core/Thirdparty/Box/BoxStorage.cs
index 27f890d08b..0264833209 100644
--- a/products/ASC.Files/Core/Core/Thirdparty/Box/BoxStorage.cs
+++ b/products/ASC.Files/Core/Core/Thirdparty/Box/BoxStorage.cs
@@ -111,10 +111,7 @@ internal class BoxStorage
 
     public Task<Stream> DownloadStreamAsync(BoxFile file, int offset = 0)
     {
-        if (file == null)
-        {
-            throw new ArgumentNullException(nameof(file));
-        }
+        ArgumentNullException.ThrowIfNull(file);
 
         return InternalDownloadStreamAsync(file, offset);
     }
diff --git a/products/ASC.Files/Core/Core/Thirdparty/Dropbox/DropboxFileDao.cs b/products/ASC.Files/Core/Core/Thirdparty/Dropbox/DropboxFileDao.cs
index 3d93392c18..7fc2727e5b 100644
--- a/products/ASC.Files/Core/Core/Thirdparty/Dropbox/DropboxFileDao.cs
+++ b/products/ASC.Files/Core/Core/Thirdparty/Dropbox/DropboxFileDao.cs
@@ -294,14 +294,8 @@ internal class DropboxFileDao : DropboxDaoBase, IFileDao<string>
 
     public Task<File<string>> SaveFileAsync(File<string> file, Stream fileStream)
     {
-        if (file == null)
-        {
-            throw new ArgumentNullException(nameof(file));
-        }
-        if (fileStream == null)
-        {
-            throw new ArgumentNullException(nameof(fileStream));
-        }
+        ArgumentNullException.ThrowIfNull(file);
+        ArgumentNullException.ThrowIfNull(fileStream);
 
         return InternalSaveFileAsync(file, fileStream);
     }
diff --git a/products/ASC.Files/Core/Core/Thirdparty/Dropbox/DropboxFolderDao.cs b/products/ASC.Files/Core/Core/Thirdparty/Dropbox/DropboxFolderDao.cs
index 87c2e88c78..66999ada29 100644
--- a/products/ASC.Files/Core/Core/Thirdparty/Dropbox/DropboxFolderDao.cs
+++ b/products/ASC.Files/Core/Core/Thirdparty/Dropbox/DropboxFolderDao.cs
@@ -178,10 +178,7 @@ internal class DropboxFolderDao : DropboxDaoBase, IFolderDao<string>
 
     public Task<string> SaveFolderAsync(Folder<string> folder)
     {
-        if (folder == null)
-        {
-            throw new ArgumentNullException(nameof(folder));
-        }
+        ArgumentNullException.ThrowIfNull(folder);
 
         return InternalSaveFolderAsync(folder);
     }
diff --git a/products/ASC.Files/Core/Core/Thirdparty/Dropbox/DropboxStorage.cs b/products/ASC.Files/Core/Core/Thirdparty/Dropbox/DropboxStorage.cs
index 27369a44e2..9927b07c9a 100644
--- a/products/ASC.Files/Core/Core/Thirdparty/Dropbox/DropboxStorage.cs
+++ b/products/ASC.Files/Core/Core/Thirdparty/Dropbox/DropboxStorage.cs
@@ -140,10 +140,7 @@ internal class DropboxStorage : IDisposable
 
     public Task<Stream> DownloadStreamAsync(string filePath, int offset = 0)
     {
-        if (string.IsNullOrEmpty(filePath))
-        {
-            throw new ArgumentNullException(nameof(filePath));
-        }
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(filePath);
 
         return InternalDownloadStreamAsync(filePath, offset);
     }
diff --git a/products/ASC.Files/Core/Core/Thirdparty/GoogleDrive/GoogleDriveFileDao.cs b/products/ASC.Files/Core/Core/Thirdparty/GoogleDrive/GoogleDriveFileDao.cs
index 53856a38db..8d711db338 100644
--- a/products/ASC.Files/Core/Core/Thirdparty/GoogleDrive/GoogleDriveFileDao.cs
+++ b/products/ASC.Files/Core/Core/Thirdparty/GoogleDrive/GoogleDriveFileDao.cs
@@ -299,15 +299,8 @@ internal class GoogleDriveFileDao : GoogleDriveDaoBase, IFileDao<string>
 
     public Task<File<string>> SaveFileAsync(File<string> file, Stream fileStream)
     {
-        if (file == null)
-        {
-            throw new ArgumentNullException(nameof(file));
-        }
-
-        if (fileStream == null)
-        {
-            throw new ArgumentNullException(nameof(fileStream));
-        }
+        ArgumentNullException.ThrowIfNull(file);
+        ArgumentNullException.ThrowIfNull(fileStream);
 
         return InternalSaveFileAsync(file, fileStream);
     }
diff --git a/products/ASC.Files/Core/Core/Thirdparty/GoogleDrive/GoogleDriveFolderDao.cs b/products/ASC.Files/Core/Core/Thirdparty/GoogleDrive/GoogleDriveFolderDao.cs
index 637356b5c7..afd85cd823 100644
--- a/products/ASC.Files/Core/Core/Thirdparty/GoogleDrive/GoogleDriveFolderDao.cs
+++ b/products/ASC.Files/Core/Core/Thirdparty/GoogleDrive/GoogleDriveFolderDao.cs
@@ -176,10 +176,7 @@ internal class GoogleDriveFolderDao : GoogleDriveDaoBase, IFolderDao<string>
 
     public Task<string> SaveFolderAsync(Folder<string> folder)
     {
-        if (folder == null)
-        {
-            throw new ArgumentNullException(nameof(folder));
-        }
+        ArgumentNullException.ThrowIfNull(folder);
 
         return InternalSaveFolderAsync(folder);
     }
diff --git a/products/ASC.Files/Core/Core/Thirdparty/GoogleDrive/GoogleDriveStorage.cs b/products/ASC.Files/Core/Core/Thirdparty/GoogleDrive/GoogleDriveStorage.cs
index 4a4b0a1f0b..e276ebea81 100644
--- a/products/ASC.Files/Core/Core/Thirdparty/GoogleDrive/GoogleDriveStorage.cs
+++ b/products/ASC.Files/Core/Core/Thirdparty/GoogleDrive/GoogleDriveStorage.cs
@@ -239,10 +239,7 @@ internal class GoogleDriveStorage : IDisposable
 
     public Task<Stream> DownloadStreamAsync(DriveFile file, int offset = 0)
     {
-        if (file == null)
-        {
-            throw new ArgumentNullException(nameof(file));
-        }
+        ArgumentNullException.ThrowIfNull(file);
 
         return InternalDownloadStreamAsync(file, offset);
     }
@@ -517,10 +514,7 @@ internal class GoogleDriveStorage : IDisposable
 
     public Task<ResumableUploadSession> CreateResumableSessionAsync(DriveFile driveFile, long contentLength)
     {
-        if (driveFile == null)
-        {
-            throw new ArgumentNullException(nameof(driveFile));
-        }
+        ArgumentNullException.ThrowIfNull(driveFile);
 
         return InternalCreateResumableSessionAsync(driveFile, contentLength);
     }
@@ -566,10 +560,7 @@ internal class GoogleDriveStorage : IDisposable
 
     public Task TransferAsync(ResumableUploadSession googleDriveSession, Stream stream, long chunkLength)
     {
-        if (stream == null)
-        {
-            throw new ArgumentNullException(nameof(stream));
-        }
+        ArgumentNullException.ThrowIfNull(stream);
 
         if (googleDriveSession.Status != ResumableUploadSessionStatus.Started)
         {
diff --git a/products/ASC.Files/Core/Core/Thirdparty/OneDrive/OneDriveFileDao.cs b/products/ASC.Files/Core/Core/Thirdparty/OneDrive/OneDriveFileDao.cs
index 4dd0a52a58..517ec3727d 100644
--- a/products/ASC.Files/Core/Core/Thirdparty/OneDrive/OneDriveFileDao.cs
+++ b/products/ASC.Files/Core/Core/Thirdparty/OneDrive/OneDriveFileDao.cs
@@ -294,14 +294,8 @@ internal class OneDriveFileDao : OneDriveDaoBase, IFileDao<string>
 
     public Task<File<string>> SaveFileAsync(File<string> file, Stream fileStream)
     {
-        if (file == null)
-        {
-            throw new ArgumentNullException(nameof(file));
-        }
-        if (fileStream == null)
-        {
-            throw new ArgumentNullException(nameof(fileStream));
-        }
+        ArgumentNullException.ThrowIfNull(file);
+        ArgumentNullException.ThrowIfNull(fileStream);
 
         return InternalSaveFileAsync(file, fileStream);
     }
diff --git a/products/ASC.Files/Core/Core/Thirdparty/OneDrive/OneDriveFolderDao.cs b/products/ASC.Files/Core/Core/Thirdparty/OneDrive/OneDriveFolderDao.cs
index 17ce5f9bd8..5e12186b2f 100644
--- a/products/ASC.Files/Core/Core/Thirdparty/OneDrive/OneDriveFolderDao.cs
+++ b/products/ASC.Files/Core/Core/Thirdparty/OneDrive/OneDriveFolderDao.cs
@@ -166,7 +166,8 @@ internal class OneDriveFolderDao : OneDriveDaoBase, IFolderDao<string>
 
     public Task<string> SaveFolderAsync(Folder<string> folder)
     {
-        if (folder == null) throw new ArgumentNullException(nameof(folder));
+        ArgumentNullException.ThrowIfNull(folder);
+
         if (folder.ID != null)
         {
             return RenameFolderAsync(folder, folder.Title);
diff --git a/products/ASC.Files/Core/Core/Thirdparty/OneDrive/OneDriveStorage.cs b/products/ASC.Files/Core/Core/Thirdparty/OneDrive/OneDriveStorage.cs
index 15774a151e..f12114bd9a 100644
--- a/products/ASC.Files/Core/Core/Thirdparty/OneDrive/OneDriveStorage.cs
+++ b/products/ASC.Files/Core/Core/Thirdparty/OneDrive/OneDriveStorage.cs
@@ -132,10 +132,8 @@ internal class OneDriveStorage
 
     public Task<Stream> DownloadStreamAsync(Item file, int offset = 0)
     {
-        if (file == null || file.File == null)
-        {
-            throw new ArgumentNullException(nameof(file));
-        }
+        ArgumentNullException.ThrowIfNull(file);
+        ArgumentNullException.ThrowIfNull(file.File);
 
         return InternalDownloadStreamAsync(file, offset);
     }
@@ -245,10 +243,7 @@ internal class OneDriveStorage
 
     public Task<ResumableUploadSession> CreateResumableSessionAsync(Item onedriveFile, long contentLength)
     {
-        if (onedriveFile == null)
-        {
-            throw new ArgumentNullException(nameof(onedriveFile));
-        }
+        ArgumentNullException.ThrowIfNull(onedriveFile);
 
         return InternalCreateResumableSessionAsync(onedriveFile, contentLength);
     }
@@ -294,10 +289,7 @@ internal class OneDriveStorage
 
     public Task TransferAsync(ResumableUploadSession oneDriveSession, Stream stream, long chunkLength)
     {
-        if (stream == null)
-        {
-            throw new ArgumentNullException(nameof(stream));
-        }
+        ArgumentNullException.ThrowIfNull(stream);
 
         if (oneDriveSession.Status != ResumableUploadSessionStatus.Started)
         {
diff --git a/products/ASC.Files/Core/Core/Thirdparty/ProviderDao/ProviderFileDao.cs b/products/ASC.Files/Core/Core/Thirdparty/ProviderDao/ProviderFileDao.cs
index 30af1d5aab..d200c0bd5c 100644
--- a/products/ASC.Files/Core/Core/Thirdparty/ProviderDao/ProviderFileDao.cs
+++ b/products/ASC.Files/Core/Core/Thirdparty/ProviderDao/ProviderFileDao.cs
@@ -210,10 +210,7 @@ internal class ProviderFileDao : ProviderDaoBase, IFileDao<string>
     /// <returns>Stream</returns>
     public Task<Stream> GetFileStreamAsync(File<string> file, long offset)
     {
-        if (file == null)
-        {
-            throw new ArgumentNullException(nameof(file));
-        }
+        ArgumentNullException.ThrowIfNull(file);
 
         return InternalGetFileStreamAsync(file, offset);
     }
@@ -233,10 +230,7 @@ internal class ProviderFileDao : ProviderDaoBase, IFileDao<string>
 
     public Task<bool> IsSupportedPreSignedUriAsync(File<string> file)
     {
-        if (file == null)
-        {
-            throw new ArgumentNullException(nameof(file));
-        }
+        ArgumentNullException.ThrowIfNull(file);
 
         return InternalIsSupportedPreSignedUriAsync(file);
     }
@@ -256,10 +250,7 @@ internal class ProviderFileDao : ProviderDaoBase, IFileDao<string>
 
     public Task<Uri> GetPreSignedUriAsync(File<string> file, TimeSpan expires)
     {
-        if (file == null)
-        {
-            throw new ArgumentNullException(nameof(file));
-        }
+        ArgumentNullException.ThrowIfNull(file);
 
         return InternalGetPreSignedUriAsync(file, expires);
     }
@@ -279,10 +270,7 @@ internal class ProviderFileDao : ProviderDaoBase, IFileDao<string>
 
     public Task<File<string>> SaveFileAsync(File<string> file, Stream fileStream)
     {
-        if (file == null)
-        {
-            throw new ArgumentNullException(nameof(file));
-        }
+        ArgumentNullException.ThrowIfNull(file);
 
         return InternalSaveFileAsync(file, fileStream);
     }
@@ -325,10 +313,8 @@ internal class ProviderFileDao : ProviderDaoBase, IFileDao<string>
 
     public Task<File<string>> ReplaceFileVersionAsync(File<string> file, Stream fileStream)
     {
-        if (file == null)
-        {
-            throw new ArgumentNullException(nameof(file));
-        }
+        ArgumentNullException.ThrowIfNull(file);
+
         if (file.ID == null)
         {
             throw new ArgumentException("No file id or folder id toFolderId determine provider");
diff --git a/products/ASC.Files/Core/Core/Thirdparty/ProviderDao/ProviderFolderDao.cs b/products/ASC.Files/Core/Core/Thirdparty/ProviderDao/ProviderFolderDao.cs
index a89979d710..e365e7bc19 100644
--- a/products/ASC.Files/Core/Core/Thirdparty/ProviderDao/ProviderFolderDao.cs
+++ b/products/ASC.Files/Core/Core/Thirdparty/ProviderDao/ProviderFolderDao.cs
@@ -149,10 +149,7 @@ internal class ProviderFolderDao : ProviderDaoBase, IFolderDao<string>
 
     public Task<string> SaveFolderAsync(Folder<string> folder)
     {
-        if (folder == null)
-        {
-            throw new ArgumentNullException(nameof(folder));
-        }
+        ArgumentNullException.ThrowIfNull(folder);
 
         return InternalSaveFolderAsync(folder);
     }
diff --git a/products/ASC.Files/Core/Core/Thirdparty/RegexDaoSelectorBase.cs b/products/ASC.Files/Core/Core/Thirdparty/RegexDaoSelectorBase.cs
index 95417716d9..dd4111e129 100644
--- a/products/ASC.Files/Core/Core/Thirdparty/RegexDaoSelectorBase.cs
+++ b/products/ASC.Files/Core/Core/Thirdparty/RegexDaoSelectorBase.cs
@@ -126,10 +126,7 @@ internal abstract class RegexDaoSelectorBase<T> : IDaoSelector<T> where T : clas
 
     internal BaseProviderInfo<T> GetInfo(string objectId)
     {
-        if (objectId == null)
-        {
-            throw new ArgumentNullException(nameof(objectId));
-        }
+        ArgumentNullException.ThrowIfNull(objectId);
 
         var id = objectId;
         var match = Selector.Match(id);
diff --git a/products/ASC.Files/Core/Core/Thirdparty/SharePoint/SharePointFileDao.cs b/products/ASC.Files/Core/Core/Thirdparty/SharePoint/SharePointFileDao.cs
index 7b130fdf2f..ba70a65343 100644
--- a/products/ASC.Files/Core/Core/Thirdparty/SharePoint/SharePointFileDao.cs
+++ b/products/ASC.Files/Core/Core/Thirdparty/SharePoint/SharePointFileDao.cs
@@ -276,10 +276,7 @@ internal class SharePointFileDao : SharePointDaoBase, IFileDao<string>
 
     public Task<File<string>> SaveFileAsync(File<string> file, Stream fileStream)
     {
-        if (fileStream == null)
-        {
-            throw new ArgumentNullException(nameof(fileStream));
-        }
+        ArgumentNullException.ThrowIfNull(fileStream);
 
         return internalSaveFileAsync(file, fileStream);
     }
diff --git a/products/ASC.Files/Core/Core/Thirdparty/Sharpbox/SharpBoxFileDao.cs b/products/ASC.Files/Core/Core/Thirdparty/Sharpbox/SharpBoxFileDao.cs
index 857694e5c9..db1b8a04ec 100644
--- a/products/ASC.Files/Core/Core/Thirdparty/Sharpbox/SharpBoxFileDao.cs
+++ b/products/ASC.Files/Core/Core/Thirdparty/Sharpbox/SharpBoxFileDao.cs
@@ -298,10 +298,7 @@ internal class SharpBoxFileDao : SharpBoxDaoBase, IFileDao<string>
 
     public async Task<File<string>> SaveFileAsync(File<string> file, Stream fileStream)
     {
-        if (fileStream == null)
-        {
-            throw new ArgumentNullException(nameof(fileStream));
-        }
+        ArgumentNullException.ThrowIfNull(fileStream);
 
         ICloudFileSystemEntry entry = null;
         if (file.ID != null)
diff --git a/products/ASC.Files/Core/Helpers/DocuSignHelper.cs b/products/ASC.Files/Core/Helpers/DocuSignHelper.cs
index d8bbadb6ba..c2d88d513b 100644
--- a/products/ASC.Files/Core/Helpers/DocuSignHelper.cs
+++ b/products/ASC.Files/Core/Helpers/DocuSignHelper.cs
@@ -63,10 +63,7 @@ public class DocuSignToken
 
     public void SaveToken(OAuth20Token token)
     {
-        if (token == null)
-        {
-            throw new ArgumentNullException(nameof(token));
-        }
+        ArgumentNullException.ThrowIfNull(token);
 
         _tokenHelper.SaveToken(new Token(token, AppAttr));
     }
@@ -176,10 +173,7 @@ public class DocuSignHelper
 
     public async Task<string> SendDocuSignAsync<T>(T fileId, DocuSignData docuSignData, IDictionary<string, StringValues> requestHeaders)
     {
-        if (docuSignData == null)
-        {
-            throw new ArgumentNullException(nameof(docuSignData));
-        }
+        ArgumentNullException.ThrowIfNull(docuSignData);
 
         var token = _docuSignToken.GetToken();
         var account = GetDocuSignAccount(token);
@@ -196,10 +190,7 @@ public class DocuSignHelper
 
     private DocuSignAccount GetDocuSignAccount(OAuth20Token token)
     {
-        if (token == null)
-        {
-            throw new ArgumentNullException(nameof(token));
-        }
+        ArgumentNullException.ThrowIfNull(token);
 
         var userInfoString = RequestHelper.PerformRequest(_consumerFactory.Get<DocuSignLoginProvider>().DocuSignHost + "/oauth/userinfo",
                                                           headers: new Dictionary<string, string> { { "Authorization", "Bearer " + _docuSignToken.GetRefreshedToken(token) } });
@@ -220,15 +211,8 @@ public class DocuSignHelper
 
     private DocuSign.eSign.Client.Configuration GetConfiguration(DocuSignAccount account, OAuth20Token token)
     {
-        if (account == null)
-        {
-            throw new ArgumentNullException(nameof(account));
-        }
-
-        if (token == null)
-        {
-            throw new ArgumentNullException(nameof(token));
-        }
+        ArgumentNullException.ThrowIfNull(account);
+        ArgumentNullException.ThrowIfNull(token);
 
         var apiClient = new ApiClient(account.BaseUri + "/restapi");
 
@@ -377,14 +361,8 @@ public class DocuSignHelper
 
     public async Task<File<T>> SaveDocumentAsync<T>(string envelopeId, string documentId, string documentName, T folderId)
     {
-        if (string.IsNullOrEmpty(envelopeId))
-        {
-            throw new ArgumentNullException(nameof(envelopeId));
-        }
-        if (string.IsNullOrEmpty(documentId))
-        {
-            throw new ArgumentNullException(nameof(documentId));
-        }
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(envelopeId);
+        ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(documentId);
 
         var token = _docuSignToken.GetToken();
         var account = GetDocuSignAccount(token);
diff --git a/products/ASC.Files/Core/Helpers/PathProvider.cs b/products/ASC.Files/Core/Helpers/PathProvider.cs
index d7941e0704..49a73d9825 100644
--- a/products/ASC.Files/Core/Helpers/PathProvider.cs
+++ b/products/ASC.Files/Core/Helpers/PathProvider.cs
@@ -172,10 +172,7 @@ public class PathProvider
 
     public async Task<string> GetTempUrlAsync(Stream stream, string ext)
     {
-        if (stream == null)
-        {
-            throw new ArgumentNullException(nameof(stream));
-        }
+        ArgumentNullException.ThrowIfNull(stream);
 
         var store = _globalStore.GetStore();
         var fileName = string.Format("{0}{1}", Guid.NewGuid(), ext);
diff --git a/products/ASC.Files/Core/Helpers/WordpressHelper.cs b/products/ASC.Files/Core/Helpers/WordpressHelper.cs
index 22e57ca8a8..7b3e1a81e3 100644
--- a/products/ASC.Files/Core/Helpers/WordpressHelper.cs
+++ b/products/ASC.Files/Core/Helpers/WordpressHelper.cs
@@ -48,10 +48,7 @@ public class WordpressToken
 
     public void SaveToken(OAuth20Token token)
     {
-        if (token == null)
-        {
-            throw new ArgumentNullException(nameof(token));
-        }
+        ArgumentNullException.ThrowIfNull(token);
 
         _tokenHelper.SaveToken(new Token(token, AppAttr));
     }
@@ -59,10 +56,7 @@ public class WordpressToken
     public OAuth20Token SaveTokenFromCode(string code)
     {
         var token = OAuth20TokenHelper.GetAccessToken<WordpressLoginProvider>(ConsumerFactory, code);
-        if (token == null)
-        {
-            throw new ArgumentNullException("token");
-        }
+        ArgumentNullException.ThrowIfNull(token);
 
         _tokenHelper.SaveToken(new Token(token, AppAttr));
 
@@ -71,10 +65,7 @@ public class WordpressToken
 
     public void DeleteToken(OAuth20Token token)
     {
-        if (token == null)
-        {
-            throw new ArgumentNullException(nameof(token));
-        }
+        ArgumentNullException.ThrowIfNull(token);
 
         _tokenHelper.DeleteToken(AppAttr);
 
diff --git a/products/ASC.Files/Core/Services/FFmpegService/FFmpeg.cs b/products/ASC.Files/Core/Services/FFmpegService/FFmpeg.cs
index 5a0e4b00cd..d68dac3bc7 100644
--- a/products/ASC.Files/Core/Services/FFmpegService/FFmpeg.cs
+++ b/products/ASC.Files/Core/Services/FFmpegService/FFmpeg.cs
@@ -131,15 +131,8 @@ public class FFmpegService
 
     private static Task<int> StreamCopyToAsync(Stream srcStream, Stream dstStream, bool closeSrc = false, bool closeDst = false)
     {
-        if (srcStream == null)
-        {
-            throw new ArgumentNullException(nameof(srcStream));
-        }
-
-        if (dstStream == null)
-        {
-            throw new ArgumentNullException(nameof(dstStream));
-        }
+        ArgumentNullException.ThrowIfNull(srcStream);
+        ArgumentNullException.ThrowIfNull(dstStream);
 
         return StreamCopyToAsyncInternal(srcStream, dstStream, closeSrc, closeDst);
     }
diff --git a/products/ASC.Files/Server/Helpers/FilesControllerHelper.cs b/products/ASC.Files/Server/Helpers/FilesControllerHelper.cs
index 80e11ae791..367512a009 100644
--- a/products/ASC.Files/Server/Helpers/FilesControllerHelper.cs
+++ b/products/ASC.Files/Server/Helpers/FilesControllerHelper.cs
@@ -136,7 +136,7 @@ namespace ASC.Files.Helpers
                 foreach (var postedFile in uploadModel.Files)
                 {
                     result.Add(await InsertFileAsync(folderId, postedFile.OpenReadStream(), postedFile.FileName, uploadModel.CreateNewIfExist, uploadModel.KeepConvertStatus));
-            }
+                }
 
                 return result;
             }
@@ -275,7 +275,7 @@ namespace ASC.Files.Helpers
 
         public Task<FileDto<T>> CreateTextFileAsync(T folderId, string title, string content)
         {
-            if (title == null) throw new ArgumentNullException(nameof(title));
+            ArgumentNullException.ThrowIfNull(title);
             //Try detect content
             var extension = ".txt";
             if (!string.IsNullOrEmpty(content))
@@ -299,7 +299,7 @@ namespace ASC.Files.Helpers
 
         public Task<FileDto<T>> CreateHtmlFileAsync(T folderId, string title, string content)
         {
-            if (title == null) throw new ArgumentNullException(nameof(title));
+            ArgumentNullException.ThrowIfNull(title);
             return CreateFileAsync(folderId, title, content, ".html");
         }
 
@@ -350,7 +350,7 @@ namespace ASC.Files.Helpers
             foreach (var e in breadCrumbs)
             {
                 yield return await GetFileEntryWrapperAsync(e);
-        }
+            }
         }
 
         public async Task<FileDto<T>> GetFileInfoAsync(T fileId, int version = -1)
@@ -395,7 +395,7 @@ namespace ASC.Files.Helpers
             foreach (var e in newItems)
             {
                 result.Add(await GetFileEntryWrapperAsync(e));
-        }
+            }
 
             return result;
         }
@@ -418,7 +418,7 @@ namespace ASC.Files.Helpers
             foreach (var e in FileStorageService.DeleteFile("delete", fileId, false, deleteAfter, immediately))
             {
                 result.Add(await FileOperationWraperHelper.GetAsync(e));
-        }
+            }
 
             return result;
         }
@@ -463,7 +463,7 @@ namespace ASC.Files.Helpers
                     }
                 }
                 yield return o;
-        }
+            }
         }
 
         public Task<string> CheckFillFormDraftAsync(T fileId, int version, string doc, bool editPossible, bool view)
@@ -478,7 +478,7 @@ namespace ASC.Files.Helpers
             foreach (var e in FileStorageService.DeleteFolder("delete", folderId, false, deleteAfter, immediately))
             {
                 result.Add(await FileOperationWraperHelper.GetAsync(e));
-        }
+            }
 
             return result;
         }
@@ -504,7 +504,7 @@ namespace ASC.Files.Helpers
             foreach (var e in entries)
             {
                 yield return await GetFileEntryWrapperAsync(e);
-        }
+            }
         }
 
         public async Task<IEnumerable<FileOperationDto>> MoveBatchItemsAsync(BatchRequestDto batchModel)
@@ -514,7 +514,7 @@ namespace ASC.Files.Helpers
             foreach (var e in FileStorageService.MoveOrCopyItems(batchModel.FolderIds.ToList(), batchModel.FileIds.ToList(), batchModel.DestFolderId, batchModel.ConflictResolveType, false, batchModel.DeleteAfter))
             {
                 result.Add(await FileOperationWraperHelper.GetAsync(e));
-        }
+            }
 
             return result;
         }
@@ -526,7 +526,7 @@ namespace ASC.Files.Helpers
             foreach (var e in FileStorageService.MoveOrCopyItems(batchModel.FolderIds.ToList(), batchModel.FileIds.ToList(), batchModel.DestFolderId, batchModel.ConflictResolveType, true, batchModel.DeleteAfter))
             {
                 result.Add(await FileOperationWraperHelper.GetAsync(e));
-        }
+            }
 
             return result;
         }
@@ -538,7 +538,7 @@ namespace ASC.Files.Helpers
             foreach (var e in FileStorageService.MarkAsRead(model.FolderIds.ToList(), model.FileIds.ToList()))
             {
                 result.Add(await FileOperationWraperHelper.GetAsync(e));
-        }
+            }
 
             return result;
         }
@@ -550,7 +550,7 @@ namespace ASC.Files.Helpers
             foreach (var e in FileStorageService.TerminateTasks())
             {
                 result.Add(await FileOperationWraperHelper.GetAsync(e));
-        }
+            }
 
             return result;
         }
@@ -562,7 +562,7 @@ namespace ASC.Files.Helpers
             foreach (var e in FileStorageService.GetTasksStatuses())
             {
                 result.Add(await FileOperationWraperHelper.GetAsync(e));
-        }
+            }
 
             return result;
         }
@@ -592,7 +592,7 @@ namespace ASC.Files.Helpers
             foreach (var e in FileStorageService.BulkDownload(folders, files))
             {
                 result.Add(await FileOperationWraperHelper.GetAsync(e));
-        }
+            }
 
             return result;
         }
@@ -605,7 +605,7 @@ namespace ASC.Files.Helpers
             foreach (var e in emptyTrash)
             {
                 result.Add(await FileOperationWraperHelper.GetAsync(e));
-        }
+            }
 
             return result;
         }
@@ -618,7 +618,7 @@ namespace ASC.Files.Helpers
             foreach (var e in files)
             {
                 result.Add(await FileWrapperHelper.GetAsync(e));
-        }
+            }
 
             return result;
         }
@@ -633,7 +633,7 @@ namespace ASC.Files.Helpers
             foreach (var e in history)
             {
                 result.Add(await FileWrapperHelper.GetAsync(e));
-        }
+            }
 
             return result;
         }
@@ -687,7 +687,7 @@ namespace ASC.Files.Helpers
             foreach (var folder in folders)
             {
                 yield return await GetFileEntryWrapperAsync(folder);
-        }
+            }
         }
 
         public async Task<IEnumerable<FileShareDto>> GetSecurityInfoAsync(IEnumerable<T> fileIds, IEnumerable<T> folderIds)
diff --git a/web/ASC.Web.Api/Controllers/SettingsController.cs b/web/ASC.Web.Api/Controllers/SettingsController.cs
index 91ed3182e8..78ab4be070 100644
--- a/web/ASC.Web.Api/Controllers/SettingsController.cs
+++ b/web/ASC.Web.Api/Controllers/SettingsController.cs
@@ -469,23 +469,23 @@ namespace ASC.Api.Settings
                 switch (Tenant.TrustedDomainsType)
                 {
                     case TenantTrustedDomainsType.Custom:
-                    {
-                        var address = new MailAddress(email);
-                        if (Tenant.TrustedDomains.Any(d => address.Address.EndsWith("@" + d.Replace("*", ""), StringComparison.InvariantCultureIgnoreCase)))
+                        {
+                            var address = new MailAddress(email);
+                            if (Tenant.TrustedDomains.Any(d => address.Address.EndsWith("@" + d.Replace("*", ""), StringComparison.InvariantCultureIgnoreCase)))
+                            {
+                                StudioNotifyService.SendJoinMsg(email, emplType);
+                                MessageService.Send(MessageInitiator.System, MessageAction.SentInviteInstructions, email);
+                                return Resource.FinishInviteJoinEmailMessage;
+                            }
+
+                            throw new Exception(Resource.ErrorEmailDomainNotAllowed);
+                        }
+                    case TenantTrustedDomainsType.All:
                         {
                             StudioNotifyService.SendJoinMsg(email, emplType);
                             MessageService.Send(MessageInitiator.System, MessageAction.SentInviteInstructions, email);
                             return Resource.FinishInviteJoinEmailMessage;
                         }
-
-                        throw new Exception(Resource.ErrorEmailDomainNotAllowed);
-                    }
-                    case TenantTrustedDomainsType.All:
-                    {
-                        StudioNotifyService.SendJoinMsg(email, emplType);
-                        MessageService.Send(MessageInitiator.System, MessageAction.SentInviteInstructions, email);
-                        return Resource.FinishInviteJoinEmailMessage;
-                    }
                     default:
                         throw new Exception(Resource.ErrorNotCorrectEmail);
                 }
@@ -1042,7 +1042,7 @@ namespace ASC.Api.Settings
             {
                 var logoDict = new Dictionary<int, string>();
 
-                foreach(var l in model.Logo)
+                foreach (var l in model.Logo)
                 {
                     logoDict.Add(Int32.Parse(l.Key), l.Value);
                 }
@@ -2109,17 +2109,17 @@ namespace ASC.Api.Settings
         }
 
         private async Task<List<UsageSpaceStatItemWrapper>> InternalGetSpaceUsageStatistics(IWebItem webitem)
-                         {
+        {
             var statData = await webitem.Context.SpaceUsageStatManager.GetStatDataAsync();
 
             return statData.ConvertAll(it => new UsageSpaceStatItemWrapper
             {
-                             Name = it.Name.HtmlEncode(),
-                             Icon = it.ImgUrl,
-                             Disabled = it.Disabled,
-                             Size = FileSizeComment.FilesSizeToString(it.SpaceUsage),
-                             Url = it.Url
-                         });
+                Name = it.Name.HtmlEncode(),
+                Icon = it.ImgUrl,
+                Disabled = it.Disabled,
+                Size = FileSizeComment.FilesSizeToString(it.SpaceUsage),
+                Url = it.Url
+            });
         }
 
         [Read("statistics/visit")]
@@ -2694,7 +2694,7 @@ namespace ASC.Api.Settings
 
         private bool SaveMailWhiteLabelSettings(MailWhiteLabelSettings settings)
         {
-            if (settings == null) throw new ArgumentNullException(nameof(settings));
+            ArgumentNullException.ThrowIfNull(settings);
 
             DemandRebrandingPermission();
 
diff --git a/web/ASC.Web.Api/Controllers/SmtpSettingsController.cs b/web/ASC.Web.Api/Controllers/SmtpSettingsController.cs
index 90782e6c86..019e698096 100644
--- a/web/ASC.Web.Api/Controllers/SmtpSettingsController.cs
+++ b/web/ASC.Web.Api/Controllers/SmtpSettingsController.cs
@@ -64,7 +64,7 @@ namespace ASC.Api.Settings
         }
 
         [Create("smtp")]
-        public SmtpSettingsWrapper SaveSmtpSettingsFromBody([FromBody]SmtpSettingsWrapper smtpSettings)
+        public SmtpSettingsWrapper SaveSmtpSettingsFromBody([FromBody] SmtpSettingsWrapper smtpSettings)
         {
             return SaveSmtpSettings(smtpSettings);
         }
@@ -78,12 +78,11 @@ namespace ASC.Api.Settings
 
         private SmtpSettingsWrapper SaveSmtpSettings(SmtpSettingsWrapper smtpSettings)
         {
-            CheckSmtpPermissions();
-
-            //TODO: Add validation check
-
-            if (smtpSettings == null)
-                throw new ArgumentNullException(nameof(smtpSettings));
+            CheckSmtpPermissions();
+
+            //TODO: Add validation check
+
+            ArgumentNullException.ThrowIfNull(smtpSettings);
 
             PermissionContext.DemandPermissions(SecutiryConstants.EditPortalSettings);
 
diff --git a/web/ASC.Web.Core/Files/DocumentService.cs b/web/ASC.Web.Core/Files/DocumentService.cs
index ac7c3bccfd..2b21e1d3e3 100644
--- a/web/ASC.Web.Core/Files/DocumentService.cs
+++ b/web/ASC.Web.Core/Files/DocumentService.cs
@@ -76,7 +76,7 @@ namespace ASC.Web.Core.Files
         /// </example>
         /// <exception>
         /// </exception>
-        
+
         public static Task<(int ResultPercent, string ConvertedDocumentUri)> GetConvertedUriAsync(
             FileUtility fileUtility,
             string documentConverterUrl,
@@ -296,7 +296,7 @@ namespace ASC.Web.Core.Files
             }
         }
 
-        public static Task<(string DocBuilderKey, Dictionary<string, string>  Urls)> DocbuilderRequestAsync(
+        public static Task<(string DocBuilderKey, Dictionary<string, string> Urls)> DocbuilderRequestAsync(
             FileUtility fileUtility,
             string docbuilderUrl,
             string requestKey,
@@ -305,8 +305,7 @@ namespace ASC.Web.Core.Files
             string signatureSecret,
            IHttpClientFactory clientFactory)
         {
-            if (string.IsNullOrEmpty(docbuilderUrl))
-                throw new ArgumentNullException(nameof(docbuilderUrl));
+            ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(docbuilderUrl);
 
             if (string.IsNullOrEmpty(requestKey) && string.IsNullOrEmpty(scriptUrl))
                 throw new ArgumentException("requestKey or inputScript is empty");
@@ -398,8 +397,7 @@ namespace ASC.Web.Core.Files
 
         public static Task<bool> HealthcheckRequestAsync(string healthcheckUrl, IHttpClientFactory clientFactory)
         {
-            if (string.IsNullOrEmpty(healthcheckUrl))
-                throw new ArgumentNullException(nameof(healthcheckUrl));
+            ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(healthcheckUrl);
 
             return InternalHealthcheckRequestAsync(healthcheckUrl, clientFactory);
         }
diff --git a/web/ASC.Web.Core/Notify/StudioNotifyService.cs b/web/ASC.Web.Core/Notify/StudioNotifyService.cs
index dd8f3065be..06d5252bdc 100644
--- a/web/ASC.Web.Core/Notify/StudioNotifyService.cs
+++ b/web/ASC.Web.Core/Notify/StudioNotifyService.cs
@@ -99,18 +99,23 @@ namespace ASC.Web.Studio.Core.Notify
         public void SendRequestTariff(bool license, string fname, string lname, string title, string email, string phone, string ctitle, string csize, string site, string message)
         {
             fname = (fname ?? "").Trim();
-            if (string.IsNullOrEmpty(fname)) throw new ArgumentNullException(nameof(fname));
+            ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(fname);
+
             lname = (lname ?? "").Trim();
-            if (string.IsNullOrEmpty(lname)) throw new ArgumentNullException(nameof(lname));
+            ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(lname);
+
             title = (title ?? "").Trim();
             email = (email ?? "").Trim();
-            if (string.IsNullOrEmpty(email)) throw new ArgumentNullException(nameof(email));
+            ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(email);
+
             phone = (phone ?? "").Trim();
-            if (string.IsNullOrEmpty(phone)) throw new ArgumentNullException(nameof(phone));
+            ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(phone);
+
             ctitle = (ctitle ?? "").Trim();
-            if (string.IsNullOrEmpty(ctitle)) throw new ArgumentNullException(nameof(ctitle));
+            ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(ctitle);
+
             csize = (csize ?? "").Trim();
-            if (string.IsNullOrEmpty(csize)) throw new ArgumentNullException(nameof(csize));
+            ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(csize);
             site = (site ?? "").Trim();
             if (string.IsNullOrEmpty(site) && !CoreBaseSettings.CustomMode) throw new ArgumentNullException(nameof(site));
             message = (message ?? "").Trim();
diff --git a/web/ASC.Web.Core/Sms/SmsKeyStorage.cs b/web/ASC.Web.Core/Sms/SmsKeyStorage.cs
index 716a53c147..3ca28fcd9d 100644
--- a/web/ASC.Web.Core/Sms/SmsKeyStorage.cs
+++ b/web/ASC.Web.Core/Sms/SmsKeyStorage.cs
@@ -93,10 +93,7 @@ namespace ASC.Web.Core.Sms
 
         public bool GenerateKey(string phone, out string key)
         {
-            if (string.IsNullOrEmpty(phone))
-            {
-                throw new ArgumentNullException(nameof(phone));
-            }
+            ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(phone);
 
             lock (KeyLocker)
             {
diff --git a/web/ASC.Web.Core/Sms/SmsSender.cs b/web/ASC.Web.Core/Sms/SmsSender.cs
index 55d6c2880f..d57f413aae 100644
--- a/web/ASC.Web.Core/Sms/SmsSender.cs
+++ b/web/ASC.Web.Core/Sms/SmsSender.cs
@@ -47,14 +47,9 @@ namespace ASC.Web.Core.Sms
 
         public Task<bool> SendSMSAsync(string number, string message)
         {
-            if (string.IsNullOrEmpty(number))
-            {
-                throw new ArgumentNullException(nameof(number));
-            }
-            if (string.IsNullOrEmpty(message))
-            {
-                throw new ArgumentNullException(nameof(message));
-            }
+            ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(number);
+            ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(message);
+
             if (!SmsProviderManager.Enabled())
             {
                 throw new MethodAccessException();
@@ -99,7 +94,7 @@ namespace ASC.Web.Core.Sms
             {
                 sb.Append('*');
             }
-            sb.Append(mobilePhone, mobilePhone.Length - endLen, mobilePhone.Length - (endLen +1));
+            sb.Append(mobilePhone, mobilePhone.Length - endLen, mobilePhone.Length - (endLen + 1));
             return sb.ToString();
         }
     }
diff --git a/web/ASC.Web.Core/Users/UserManagerWrapper.cs b/web/ASC.Web.Core/Users/UserManagerWrapper.cs
index 20bd4248ff..3baedd2aa7 100644
--- a/web/ASC.Web.Core/Users/UserManagerWrapper.cs
+++ b/web/ASC.Web.Core/Users/UserManagerWrapper.cs
@@ -103,7 +103,7 @@ namespace ASC.Web.Core.Users
 
         public UserInfo AddUser(UserInfo userInfo, string passwordHash, bool afterInvite = false, bool notify = true, bool isVisitor = false, bool fromInviteLink = false, bool makeUniqueName = true)
         {
-            if (userInfo == null) throw new ArgumentNullException(nameof(userInfo));
+            ArgumentNullException.ThrowIfNull(userInfo);
 
             if (!UserFormatter.IsValidUserName(userInfo.FirstName, userInfo.LastName))
                 throw new Exception(Resource.ErrorIncorrectUserName);
diff --git a/web/ASC.Web.Core/WebItemSecurity.cs b/web/ASC.Web.Core/WebItemSecurity.cs
index 4db9cc316d..faff7d0190 100644
--- a/web/ASC.Web.Core/WebItemSecurity.cs
+++ b/web/ASC.Web.Core/WebItemSecurity.cs
@@ -384,10 +384,7 @@ namespace ASC.Web.Core
 
             public static WebItemSecurityObject Create(string id, WebItemManager webItemManager)
             {
-                if (string.IsNullOrEmpty(id))
-                {
-                    throw new ArgumentNullException(nameof(id));
-                }
+                ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(id);
 
                 var itemId = Guid.Empty;
                 if (32 <= id.Length)