Web:Common:Store: add array for available themes

This commit is contained in:
Timofey Boyko 2021-12-28 21:35:56 +08:00
commit 9557ad7abb
30 changed files with 1396 additions and 1459 deletions

8
build/Jenkinsfile vendored
View File

@ -13,7 +13,7 @@ pipeline {
}
stage('Backend') {
steps {
sh 'dotnet build -c Release ASC.Web.sln'
sh 'dotnet build -c Release ASC.Web.slnf'
}
}
}
@ -28,7 +28,7 @@ pipeline {
}
stage('Backend') {
steps {
bat 'dotnet build -c Release ASC.Web.sln'
bat 'dotnet build -c Release ASC.Web.slnf'
}
}
}
@ -62,7 +62,7 @@ pipeline {
}
stage('Files') {
steps {
sh "git submodule update --progress --init -- products/ASC.Files/Server/DocStore && dotnet build ASC.Web.sln && cd ${env.WORKSPACE}/products/ASC.Files/Tests/ && dotnet test ASC.Files.Tests.csproj -r linux-x64 -l \"console;verbosity=detailed\""
sh "git submodule update --progress --init -- products/ASC.Files/Server/DocStore && dotnet build ASC.Web.slnf && cd ${env.WORKSPACE}/products/ASC.Files/Tests/ && dotnet test ASC.Files.Tests.csproj -r linux-x64 -l \"console;verbosity=detailed\""
}
}
}
@ -90,7 +90,7 @@ pipeline {
}
stage('Files') {
steps {
bat "git submodule update --progress --init -- products\\ASC.Files\\Server\\DocStore && dotnet build ASC.Web.sln && cd ${env.WORKSPACE}\\products\\ASC.Files\\Tests\\ && dotnet test ASC.Files.Tests.csproj"
bat "git submodule update --progress --init -- products\\ASC.Files\\Server\\DocStore && dotnet build ASC.Web.slnf && cd ${env.WORKSPACE}\\products\\ASC.Files\\Tests\\ && dotnet test ASC.Files.Tests.csproj"
}
}
}

View File

@ -6,6 +6,7 @@
ELK_VERSION=7.13.1
SERVICE_PORT=5050
CONTAINER_PREFIX=${PRODUCT}-
DOCUMENT_SERVER_IMAGE_NAME=onlyoffice/4testing-documentserver-ee:latest
DOCKER_TAG=latest
DOCKERFILE=Dockerfile.app

View File

@ -1,7 +1,7 @@
version: '3.6'
services:
onlyoffice-document-server:
image: "${REPO}/${STATUS}documentserver:latest"
image: "${DOCUMENT_SERVER_IMAGE_NAME}"
container_name: ${DOCUMENT_SERVER_HOST}
# Strings below enable the JSON Web Token validation.
environment:

View File

@ -46,13 +46,15 @@ namespace ASC.Api.Core.Middleware
base.OnResultExecuted(context);
return;
}
var result = (ObjectResult)context.Result;
var resultContent = JsonSerializer.Serialize(result.Value, jsonSerializerOptions);
var eventName = $"method: {method}, route: {routePattern}";
WebhookPublisher.Publish(eventName, resultContent);
if (context.Result is ObjectResult objectResult)
{
var resultContent = JsonSerializer.Serialize(objectResult.Value, jsonSerializerOptions);
var eventName = $"method: {method}, route: {routePattern}";
WebhookPublisher.Publish(eventName, resultContent);
}
base.OnResultExecuted(context);
}

View File

@ -36,11 +36,11 @@ namespace ASC.Security.Cryptography
[Singletone]
public class InstanceCrypto
{
private MachinePseudoKeys MachinePseudoKeys { get; }
private byte[] EKey { get; }
public InstanceCrypto(MachinePseudoKeys machinePseudoKeys)
{
MachinePseudoKeys = machinePseudoKeys;
EKey = machinePseudoKeys.GetMachineConstant(32);
}
public string Encrypt(string data)
@ -50,8 +50,8 @@ namespace ASC.Security.Cryptography
public byte[] Encrypt(byte[] data)
{
var hasher = Aes.Create();
hasher.Key = EKey();
using var hasher = Aes.Create();
hasher.Key = EKey;
hasher.IV = new byte[hasher.BlockSize >> 3];
using var ms = new MemoryStream();
@ -70,24 +70,17 @@ namespace ASC.Security.Cryptography
public string Decrypt(byte[] data)
{
var hasher = Aes.Create();
hasher.Key = EKey();
using var hasher = Aes.Create();
hasher.Key = EKey;
hasher.IV = new byte[hasher.BlockSize >> 3];
using (MemoryStream msDecrypt = new MemoryStream(data))
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, hasher.CreateDecryptor(), CryptoStreamMode.Read))
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
using var msDecrypt = new MemoryStream(data);
using var csDecrypt = new CryptoStream(msDecrypt, hasher.CreateDecryptor(), CryptoStreamMode.Read);
using var srDecrypt = new StreamReader(csDecrypt);
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
return srDecrypt.ReadToEnd();
}
}
private byte[] EKey()
{
return MachinePseudoKeys.GetMachineConstant(32);
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
return srDecrypt.ReadToEnd();
}
}
}

View File

@ -1,145 +1,149 @@
/*
*
* (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 System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
/*
*
* (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 ASC.Common;
using ASC.Common.Caching;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using ASC.Common;
using ASC.Common.Caching;
using ASC.Core.Common.EF;
using ASC.Core.Data;
using ASC.Core.Tenants;
using ASC.Core.Data;
using ASC.Core.Users;
using Microsoft.Extensions.Options;
namespace ASC.Core.Caching
namespace ASC.Core.Caching
{
[Singletone]
public class UserServiceCache
{
public const string USERS = "users";
private const string GROUPS = "groups";
public const string REFS = "refs";
public TrustInterval TrustInterval { get; set; }
internal ICache Cache { get; }
internal CoreBaseSettings CoreBaseSettings { get; }
internal ICacheNotify<UserInfoCacheItem> CacheUserInfoItem { get; }
internal ICacheNotify<UserPhotoCacheItem> CacheUserPhotoItem { get; }
internal ICacheNotify<GroupCacheItem> CacheGroupCacheItem { get; }
internal ICacheNotify<UserGroupRefCacheItem> CacheUserGroupRefItem { get; }
public UserServiceCache(
CoreBaseSettings coreBaseSettings,
ICacheNotify<UserInfoCacheItem> cacheUserInfoItem,
ICacheNotify<UserPhotoCacheItem> cacheUserPhotoItem,
ICacheNotify<GroupCacheItem> cacheGroupCacheItem,
ICacheNotify<UserGroupRefCacheItem> cacheUserGroupRefItem,
ICache cache)
{
TrustInterval = new TrustInterval();
Cache = cache;
CoreBaseSettings = coreBaseSettings;
CacheUserInfoItem = cacheUserInfoItem;
CacheUserPhotoItem = cacheUserPhotoItem;
CacheGroupCacheItem = cacheGroupCacheItem;
CacheUserGroupRefItem = cacheUserGroupRefItem;
cacheUserInfoItem.Subscribe((u) => InvalidateCache(u), CacheNotifyAction.Any);
cacheUserPhotoItem.Subscribe((p) => Cache.Remove(p.Key), CacheNotifyAction.Remove);
cacheGroupCacheItem.Subscribe((g) => InvalidateCache(), CacheNotifyAction.Any);
cacheUserGroupRefItem.Subscribe((r) => UpdateUserGroupRefCache(r, true), CacheNotifyAction.Remove);
cacheUserGroupRefItem.Subscribe((r) => UpdateUserGroupRefCache(r, false), CacheNotifyAction.InsertOrUpdate);
}
public void InvalidateCache()
{
InvalidateCache(null);
}
private void InvalidateCache(UserInfoCacheItem userInfo)
{
if (CoreBaseSettings.Personal && userInfo != null)
{
var key = GetUserCacheKeyForPersonal(userInfo.Tenant, userInfo.ID.FromByteString());
Cache.Remove(key);
}
TrustInterval.Expire();
}
private void UpdateUserGroupRefCache(UserGroupRef r, bool remove)
{
var key = GetRefCacheKey(r.Tenant);
var refs = Cache.Get<UserGroupRefStore>(key);
if (!remove && refs != null)
{
lock (refs)
{
refs[r.CreateKey()] = r;
}
}
else
{
InvalidateCache();
}
}
public static string GetUserPhotoCacheKey(int tenant, Guid userId)
{
return tenant.ToString() + "userphoto" + userId.ToString();
}
public static string GetGroupCacheKey(int tenant)
{
return tenant.ToString() + GROUPS;
}
public static string GetRefCacheKey(int tenant)
{
return tenant.ToString() + REFS;
}
public static string GetUserCacheKey(int tenant)
{
return tenant.ToString() + USERS;
}
public static string GetUserCacheKeyForPersonal(int tenant, Guid userId)
{
return tenant.ToString() + USERS + userId;
}
[Singletone]
public class UserServiceCache
{
public const string USERS = "users";
private const string GROUPS = "groups";
public const string REFS = "refs";
internal ICache Cache { get; }
internal CoreBaseSettings CoreBaseSettings { get; }
internal ICacheNotify<UserInfoCacheItem> CacheUserInfoItem { get; }
internal ICacheNotify<UserPhotoCacheItem> CacheUserPhotoItem { get; }
internal ICacheNotify<GroupCacheItem> CacheGroupCacheItem { get; }
internal ICacheNotify<UserGroupRefCacheItem> CacheUserGroupRefItem { get; }
public UserServiceCache(
CoreBaseSettings coreBaseSettings,
ICacheNotify<UserInfoCacheItem> cacheUserInfoItem,
ICacheNotify<UserPhotoCacheItem> cacheUserPhotoItem,
ICacheNotify<GroupCacheItem> cacheGroupCacheItem,
ICacheNotify<UserGroupRefCacheItem> cacheUserGroupRefItem,
ICache cache)
{
Cache = cache;
CoreBaseSettings = coreBaseSettings;
CacheUserInfoItem = cacheUserInfoItem;
CacheUserPhotoItem = cacheUserPhotoItem;
CacheGroupCacheItem = cacheGroupCacheItem;
CacheUserGroupRefItem = cacheUserGroupRefItem;
cacheUserInfoItem.Subscribe((u) => InvalidateCache(u), CacheNotifyAction.Any);
cacheUserPhotoItem.Subscribe((p) => Cache.Remove(p.Key), CacheNotifyAction.Remove);
cacheGroupCacheItem.Subscribe((g) => InvalidateCache(), CacheNotifyAction.Any);
cacheUserGroupRefItem.Subscribe((r) => UpdateUserGroupRefCache(r, true), CacheNotifyAction.Remove);
cacheUserGroupRefItem.Subscribe((r) => UpdateUserGroupRefCache(r, false), CacheNotifyAction.InsertOrUpdate);
}
public void InvalidateCache()
{
InvalidateCache(null);
}
private void InvalidateCache(UserInfoCacheItem userInfo)
{
if (userInfo != null)
{
var key = GetUserCacheKey(userInfo.Tenant, userInfo.ID.FromByteString());
Cache.Remove(key);
}
}
private void UpdateUserGroupRefCache(UserGroupRef r, bool remove)
{
var key = GetRefCacheKey(r.Tenant);
var refs = Cache.Get<UserGroupRefStore>(key);
if (!remove && refs != null)
{
lock (refs)
{
refs[r.CreateKey()] = r;
}
}
else
{
InvalidateCache();
}
}
public static string GetUserPhotoCacheKey(int tenant, Guid userId)
{
return tenant.ToString() + "userphoto" + userId.ToString();
}
public static string GetGroupCacheKey(int tenant)
{
return tenant.ToString() + GROUPS;
}
public static string GetGroupCacheKey(int tenant, Guid groupId)
{
return tenant.ToString() + GROUPS + groupId;
}
public static string GetRefCacheKey(int tenant)
{
return tenant.ToString() + REFS;
}
public static string GetRefCacheKey(int tenant, Guid groupId, UserGroupRefType refType)
{
return tenant.ToString() + groupId + (int)refType;
}
public static string GetUserCacheKey(int tenant)
{
return tenant.ToString() + USERS;
}
public static string GetUserCacheKey(int tenant, Guid userId)
{
return tenant.ToString() + USERS + userId;
}
}
[Scope]
class ConfigureCachedUserService : IConfigureNamedOptions<CachedUserService>
class ConfigureCachedUserService : IConfigureNamedOptions<CachedUserService>
{
internal IOptionsSnapshot<EFUserService> Service { get; }
internal UserServiceCache UserServiceCache { get; }
@ -163,42 +167,38 @@ namespace ASC.Core.Caching
public void Configure(CachedUserService options)
{
options.Service = Service.Value;
options.CoreBaseSettings = CoreBaseSettings;
options.UserServiceCache = UserServiceCache;
options.Cache = UserServiceCache.Cache;
options.CacheUserInfoItem = UserServiceCache.CacheUserInfoItem;
options.CacheUserPhotoItem = UserServiceCache.CacheUserPhotoItem;
options.CacheGroupCacheItem = UserServiceCache.CacheGroupCacheItem;
options.CacheUserGroupRefItem = UserServiceCache.CacheUserGroupRefItem;
options.TrustInterval = UserServiceCache.TrustInterval;
options.Service = Service.Value;
options.CoreBaseSettings = CoreBaseSettings;
options.UserServiceCache = UserServiceCache;
options.Cache = UserServiceCache.Cache;
options.CacheUserInfoItem = UserServiceCache.CacheUserInfoItem;
options.CacheUserPhotoItem = UserServiceCache.CacheUserPhotoItem;
options.CacheGroupCacheItem = UserServiceCache.CacheGroupCacheItem;
options.CacheUserGroupRefItem = UserServiceCache.CacheUserGroupRefItem;
}
}
[Scope]
public class CachedUserService : IUserService, ICachedService
{
internal IUserService Service { get; set; }
internal ICache Cache { get; set; }
internal TrustInterval TrustInterval { get; set; }
private int getchanges;
private TimeSpan CacheExpiration { get; set; }
private TimeSpan DbExpiration { get; set; }
private TimeSpan PhotoExpiration { get; set; }
internal CoreBaseSettings CoreBaseSettings { get; set; }
internal UserServiceCache UserServiceCache { get; set; }
internal ICacheNotify<UserInfoCacheItem> CacheUserInfoItem { get; set; }
internal ICacheNotify<UserPhotoCacheItem> CacheUserPhotoItem { get; set; }
internal ICacheNotify<GroupCacheItem> CacheGroupCacheItem { get; set; }
internal ICacheNotify<UserGroupRefCacheItem> CacheUserGroupRefItem { get; set; }
public CachedUserService()
{
CacheExpiration = TimeSpan.FromMinutes(20);
DbExpiration = TimeSpan.FromMinutes(1);
PhotoExpiration = TimeSpan.FromMinutes(10);
[Scope]
public class CachedUserService : IUserService, ICachedService
{
internal IUserService Service { get; set; }
internal ICache Cache { get; set; }
internal TrustInterval TrustInterval { get; set; }
private TimeSpan CacheExpiration { get; set; }
private TimeSpan PhotoExpiration { get; set; }
internal CoreBaseSettings CoreBaseSettings { get; set; }
internal UserServiceCache UserServiceCache { get; set; }
internal ICacheNotify<UserInfoCacheItem> CacheUserInfoItem { get; set; }
internal ICacheNotify<UserPhotoCacheItem> CacheUserPhotoItem { get; set; }
internal ICacheNotify<GroupCacheItem> CacheGroupCacheItem { get; set; }
internal ICacheNotify<UserGroupRefCacheItem> CacheUserGroupRefItem { get; set; }
public CachedUserService()
{
CacheExpiration = TimeSpan.FromMinutes(20);
PhotoExpiration = TimeSpan.FromMinutes(10);
}
public CachedUserService(
@ -215,18 +215,8 @@ namespace ASC.Core.Caching
CacheUserPhotoItem = userServiceCache.CacheUserPhotoItem;
CacheGroupCacheItem = userServiceCache.CacheGroupCacheItem;
CacheUserGroupRefItem = userServiceCache.CacheUserGroupRefItem;
TrustInterval = userServiceCache.TrustInterval;
}
public IDictionary<Guid, UserInfo> GetUsers(int tenant, DateTime from)
{
var users = GetUsers(tenant);
lock (users)
{
return (from == default ? users.Values : users.Values.Where(u => u.LastModified >= from)).ToDictionary(u => u.ID);
}
}
public IQueryable<UserInfo> GetUsers(
int tenant,
bool isAdmin,
@ -240,26 +230,27 @@ namespace ASC.Core.Caching
long limit,
long offset,
out int total,
out int count)
{
return Service.GetUsers(tenant, isAdmin, employeeStatus, includeGroups, excludeGroups, activationStatus, text, sortBy, sortOrderAsc, limit, offset, out total, out count);
}
public UserInfo GetUser(int tenant, Guid id)
out int count)
{
if (id.Equals(Guid.Empty)) return null;
if (CoreBaseSettings.Personal)
{
return GetUserForPersonal(tenant, id);
}
var users = GetUsers(tenant);
lock (users)
{
users.TryGetValue(id, out var u);
return u;
}
return Service.GetUsers(tenant, isAdmin, employeeStatus, includeGroups, excludeGroups, activationStatus, text, sortBy, sortOrderAsc, limit, offset, out total, out count);
}
public UserInfo GetUser(int tenant, Guid id)
{
var key = UserServiceCache.GetUserCacheKey(tenant, id);
var user = Cache.Get<UserInfo>(key);
if (user == null)
{
user = Service.GetUser(tenant, id);
if (user != null)
{
Cache.Insert(key, user, CacheExpiration);
}
}
return user;
}
public UserInfo GetUser(int tenant, string email)
@ -272,68 +263,41 @@ namespace ASC.Core.Caching
return Service.GetUserByUserName(tenant, userName);
}
/// <summary>
/// For Personal only
/// </summary>
/// <param name="tenant"></param>
/// <param name="id"></param>
/// <returns></returns>
private UserInfo GetUserForPersonal(int tenant, Guid id)
{
if (!CoreBaseSettings.Personal) return GetUser(tenant, id);
var key = UserServiceCache.GetUserCacheKeyForPersonal(tenant, id);
var user = Cache.Get<UserInfo>(key);
if (user == null)
{
user = Service.GetUser(tenant, id);
if (user != null)
{
Cache.Insert(key, user, CacheExpiration);
}
}
return user;
}
public UserInfo GetUserByPasswordHash(int tenant, string login, string passwordHash)
{
return Service.GetUserByPasswordHash(tenant, login, passwordHash);
}
public UserInfo SaveUser(int tenant, UserInfo user)
{
user = Service.SaveUser(tenant, user);
CacheUserInfoItem.Publish(new UserInfoCacheItem { ID = user.ID.ToByteString(), Tenant = tenant }, CacheNotifyAction.Any);
return user;
}
public void RemoveUser(int tenant, Guid id)
{
Service.RemoveUser(tenant, id);
CacheUserInfoItem.Publish(new UserInfoCacheItem { Tenant = tenant, ID = id.ToByteString() }, CacheNotifyAction.Any);
}
public byte[] GetUserPhoto(int tenant, Guid id)
{
var photo = Cache.Get<byte[]>(UserServiceCache.GetUserPhotoCacheKey(tenant, id));
if (photo == null)
{
photo = Service.GetUserPhoto(tenant, id);
Cache.Insert(UserServiceCache.GetUserPhotoCacheKey(tenant, id), photo, PhotoExpiration);
}
return photo;
}
public void SetUserPhoto(int tenant, Guid id, byte[] photo)
{
Service.SetUserPhoto(tenant, id, photo);
CacheUserPhotoItem.Publish(new UserPhotoCacheItem { Key = UserServiceCache.GetUserPhotoCacheKey(tenant, id) }, CacheNotifyAction.Remove);
}
}
public UserInfo SaveUser(int tenant, UserInfo user)
{
user = Service.SaveUser(tenant, user);
CacheUserInfoItem.Publish(new UserInfoCacheItem { ID = user.ID.ToByteString(), Tenant = tenant }, CacheNotifyAction.Any);
return user;
}
public void RemoveUser(int tenant, Guid id)
{
Service.RemoveUser(tenant, id);
CacheUserInfoItem.Publish(new UserInfoCacheItem { Tenant = tenant, ID = id.ToByteString() }, CacheNotifyAction.Any);
}
public byte[] GetUserPhoto(int tenant, Guid id)
{
var photo = Cache.Get<byte[]>(UserServiceCache.GetUserPhotoCacheKey(tenant, id));
if (photo == null)
{
photo = Service.GetUserPhoto(tenant, id);
Cache.Insert(UserServiceCache.GetUserPhotoCacheKey(tenant, id), photo, PhotoExpiration);
}
return photo;
}
public void SetUserPhoto(int tenant, Guid id, byte[] photo)
{
Service.SetUserPhoto(tenant, id, photo);
CacheUserPhotoItem.Publish(new UserPhotoCacheItem { Key = UserServiceCache.GetUserPhotoCacheKey(tenant, id) }, CacheNotifyAction.Remove);
}
public DateTime GetUserPasswordStamp(int tenant, Guid id)
{
return Service.GetUserPasswordStamp(tenant, id);
@ -343,201 +307,114 @@ namespace ASC.Core.Caching
{
Service.SetUserPasswordHash(tenant, id, passwordHash);
}
public IDictionary<Guid, Group> GetGroups(int tenant, DateTime from)
{
var groups = GetGroups(tenant);
lock (groups)
{
return (from == default ? groups.Values : groups.Values.Where(g => g.LastModified >= from)).ToDictionary(g => g.Id);
}
}
public Group GetGroup(int tenant, Guid id)
{
var groups = GetGroups(tenant);
lock (groups)
{
groups.TryGetValue(id, out var g);
return g;
}
}
public Group SaveGroup(int tenant, Group group)
{
group = Service.SaveGroup(tenant, group);
CacheGroupCacheItem.Publish(new GroupCacheItem { ID = group.Id.ToString() }, CacheNotifyAction.Any);
return group;
}
public void RemoveGroup(int tenant, Guid id)
{
Service.RemoveGroup(tenant, id);
CacheGroupCacheItem.Publish(new GroupCacheItem { ID = id.ToString() }, CacheNotifyAction.Any);
}
public IDictionary<string, UserGroupRef> GetUserGroupRefs(int tenant, DateTime from)
public Group GetGroup(int tenant, Guid id)
{
if (CoreBaseSettings.Personal)
var key = UserServiceCache.GetGroupCacheKey(tenant, id);
var group = Cache.Get<Group>(key);
if (group == null)
{
return new Dictionary<string, UserGroupRef>();
group = Service.GetGroup(tenant, id);
if (group != null) Cache.Insert(key, group, CacheExpiration);
};
return group;
}
public Group SaveGroup(int tenant, Group group)
{
group = Service.SaveGroup(tenant, group);
CacheGroupCacheItem.Publish(new GroupCacheItem { ID = group.Id.ToString() }, CacheNotifyAction.Any);
return group;
}
public void RemoveGroup(int tenant, Guid id)
{
Service.RemoveGroup(tenant, id);
CacheGroupCacheItem.Publish(new GroupCacheItem { ID = id.ToString() }, CacheNotifyAction.Any);
}
public IDictionary<string, UserGroupRef> GetUserGroupRefs(int tenant)
{
var key = UserServiceCache.GetRefCacheKey(tenant);
if (!(Cache.Get<UserGroupRefStore>(key) is IDictionary<string, UserGroupRef> refs))
{
refs = Service.GetUserGroupRefs(tenant);
Cache.Insert(key, new UserGroupRefStore(refs), CacheExpiration);
}
GetChangesFromDb();
var key = UserServiceCache.GetRefCacheKey(tenant);
if (!(Cache.Get<UserGroupRefStore>(key) is IDictionary<string, UserGroupRef> refs))
{
refs = Service.GetUserGroupRefs(tenant, default);
Cache.Insert(key, new UserGroupRefStore(refs), CacheExpiration);
}
lock (refs)
{
return from == default ? refs : refs.Values.Where(r => r.LastModified >= from).ToDictionary(r => r.CreateKey());
}
}
public UserGroupRef SaveUserGroupRef(int tenant, UserGroupRef r)
{
r = Service.SaveUserGroupRef(tenant, r);
CacheUserGroupRefItem.Publish(r, CacheNotifyAction.InsertOrUpdate);
return r;
}
public void RemoveUserGroupRef(int tenant, Guid userId, Guid groupId, UserGroupRefType refType)
{
Service.RemoveUserGroupRef(tenant, userId, groupId, refType);
var r = new UserGroupRef(userId, groupId, refType) { Tenant = tenant };
CacheUserGroupRefItem.Publish(r, CacheNotifyAction.Remove);
}
private IDictionary<Guid, UserInfo> GetUsers(int tenant)
{
GetChangesFromDb();
var key = UserServiceCache.GetUserCacheKey(tenant);
var users = Cache.Get<IDictionary<Guid, UserInfo>>(key);
if (users == null)
{
users = Service.GetUsers(tenant, default);
Cache.Insert(key, users, CacheExpiration);
}
return users;
}
private IDictionary<Guid, Group> GetGroups(int tenant)
{
GetChangesFromDb();
var key = UserServiceCache.GetGroupCacheKey(tenant);
var groups = Cache.Get<IDictionary<Guid, Group>>(key);
if (groups == null)
{
groups = Service.GetGroups(tenant, default);
Cache.Insert(key, groups, CacheExpiration);
}
return groups;
}
private void GetChangesFromDb()
{
if (!TrustInterval.Expired)
{
return;
}
if (Interlocked.CompareExchange(ref getchanges, 1, 0) == 0)
{
try
{
if (!TrustInterval.Expired)
{
return;
}
var starttime = TrustInterval.StartTime;
if (starttime != default)
{
var correction = TimeSpan.FromTicks(DbExpiration.Ticks * 3);
starttime = TrustInterval.StartTime.Subtract(correction);
}
TrustInterval.Start(DbExpiration);
//get and merge changes in cached tenants
foreach (var tenantGroup in Service.GetUsers(Tenant.DEFAULT_TENANT, starttime).Values.GroupBy(u => u.Tenant))
{
var users = Cache.Get<IDictionary<Guid, UserInfo>>(UserServiceCache.GetUserCacheKey(tenantGroup.Key));
if (users != null)
{
lock (users)
{
foreach (var u in tenantGroup)
{
users[u.ID] = u;
}
}
}
}
foreach (var tenantGroup in Service.GetGroups(Tenant.DEFAULT_TENANT, starttime).Values.GroupBy(g => g.Tenant))
{
var groups = Cache.Get<IDictionary<Guid, Group>>(UserServiceCache.GetGroupCacheKey(tenantGroup.Key));
if (groups != null)
{
lock (groups)
{
foreach (var g in tenantGroup)
{
groups[g.Id] = g;
}
}
}
}
foreach (var tenantGroup in Service.GetUserGroupRefs(Tenant.DEFAULT_TENANT, starttime).Values.GroupBy(r => r.Tenant))
{
var refs = Cache.Get<UserGroupRefStore>(UserServiceCache.GetRefCacheKey(tenantGroup.Key));
if (refs != null)
{
lock (refs)
{
foreach (var r in tenantGroup)
{
refs[r.CreateKey()] = r;
}
}
}
}
}
finally
{
Volatile.Write(ref getchanges, 0);
}
}
}
public void InvalidateCache()
{
UserServiceCache.InvalidateCache();
return refs;
}
public UserGroupRef GetUserGroupRef(int tenant, Guid groupId, UserGroupRefType refType)
{
var key = UserServiceCache.GetRefCacheKey(tenant, groupId, refType);
var groupRef = Cache.Get<UserGroupRef>(key);
if (groupRef == null)
{
groupRef = Service.GetUserGroupRef(tenant, groupId, refType);
if (groupRef != null) Cache.Insert(key, groupRef, CacheExpiration);
}
return groupRef;
}
public UserGroupRef SaveUserGroupRef(int tenant, UserGroupRef r)
{
r = Service.SaveUserGroupRef(tenant, r);
CacheUserGroupRefItem.Publish(r, CacheNotifyAction.InsertOrUpdate);
return r;
}
public void RemoveUserGroupRef(int tenant, Guid userId, Guid groupId, UserGroupRefType refType)
{
Service.RemoveUserGroupRef(tenant, userId, groupId, refType);
var r = new UserGroupRef(userId, groupId, refType) { Tenant = tenant };
CacheUserGroupRefItem.Publish(r, CacheNotifyAction.Remove);
}
public IEnumerable<UserInfo> GetUsers(int tenant)
{
var key = UserServiceCache.GetUserCacheKey(tenant);
var users = Cache.Get<IEnumerable<UserInfo>>(key);
if (users == null)
{
users = Service.GetUsers(tenant);
Cache.Insert(key, users, CacheExpiration);
}
return users;
}
public IEnumerable<Group> GetGroups(int tenant)
{
var key = UserServiceCache.GetGroupCacheKey(tenant);
var groups = Cache.Get<IEnumerable<Group>>(key);
if (groups == null)
{
groups = Service.GetGroups(tenant);
Cache.Insert(key, groups, CacheExpiration);
}
return groups;
}
public void InvalidateCache()
{
UserServiceCache.InvalidateCache();
}
public UserInfo GetUser(int tenant, Guid id, Expression<Func<User, UserInfo>> exp)
{
if (exp == null) return GetUser(tenant, id);
return Service.GetUser(tenant, id, exp);
}
[Serializable]
class UserPhoto
{
public string Key { get; set; }
}
}
}
}
}

View File

@ -158,15 +158,6 @@ namespace ASC.Core
return UserService.GetUsers(Tenant.TenantId, isAdmin, employeeStatus, includeGroups, excludeGroups, activationStatus, text, sortBy, sortOrderAsc, limit, offset, out total, out count);
}
public DateTime GetMaxUsersLastModified()
{
return UserService.GetUsers(Tenant.TenantId, default)
.Values
.Select(g => g.LastModified)
.DefaultIfEmpty()
.Max();
}
public string[] GetUserNames(EmployeeStatus status)
{
return GetUsers(status)
@ -177,14 +168,8 @@ namespace ASC.Core
public UserInfo GetUserByUserName(string username)
{
if (CoreBaseSettings.Personal)
{
var u = UserService.GetUserByUserName(TenantManager.GetCurrentTenant().TenantId, username);
return u ?? Constants.LostUser;
}
return GetUsersInternal()
.FirstOrDefault(u => string.Compare(u.UserName, username, StringComparison.CurrentCultureIgnoreCase) == 0) ?? Constants.LostUser;
var u = UserService.GetUserByUserName(TenantManager.GetCurrentTenant().TenantId, username);
return u ?? Constants.LostUser;
}
public UserInfo GetUserBySid(string sid)
@ -209,7 +194,8 @@ namespace ASC.Core
if (IsSystemUser(id)) return SystemUsers[id];
var u = UserService.GetUser(Tenant.TenantId, id);
return u != null && !u.Removed ? u : Constants.LostUser;
}
}
public UserInfo GetUser(Guid id, Expression<Func<User, UserInfo>> exp)
{
if (IsSystemUser(id)) return SystemUsers[id];
@ -242,15 +228,8 @@ namespace ASC.Core
{
if (string.IsNullOrEmpty(email)) return Constants.LostUser;
if (CoreBaseSettings.Personal)
{
var u = UserService.GetUser(Tenant.TenantId, email);
return u != null && !u.Removed ? u : Constants.LostUser;
}
return GetUsersInternal()
.FirstOrDefault(u => string.Compare(u.Email, email, StringComparison.CurrentCultureIgnoreCase) == 0) ?? Constants.LostUser;
var u = UserService.GetUser(Tenant.TenantId, email);
return u != null && !u.Removed ? u : Constants.LostUser;
}
public UserInfo[] Search(string text, EmployeeStatus status)
@ -326,7 +305,7 @@ namespace ASC.Core
if (u.Status == EmployeeStatus.Terminated && u.ID == TenantManager.GetCurrentTenant().OwnerId)
{
throw new InvalidOperationException("Can not disable tenant owner.");
}
}
var newUser = UserService.SaveUser(TenantManager.GetCurrentTenant().TenantId, u);
@ -359,11 +338,6 @@ namespace ASC.Core
return UserService.GetUserPhoto(Tenant.TenantId, id);
}
public IEnumerable<Guid> GetUserGroupsId(Guid id)
{
return GetUserGroupsGuids(id);
}
public List<GroupInfo> GetUserGroups(Guid id)
{
return GetUserGroups(id, IncludeType.Distinct, Guid.Empty);
@ -436,38 +410,6 @@ namespace ASC.Core
return result;
}
internal IEnumerable<Guid> GetUserGroupsGuids(Guid userID)
{
var httpRequestDictionary = new HttpRequestDictionary<List<Guid>>(Accessor?.HttpContext, "GroupInfoID");
var fromCache = httpRequestDictionary.Get(userID.ToString());
if (fromCache != null)
{
return fromCache;
}
var result = new List<Guid>();
var refs = GetRefsInternal();
if (refs is UserGroupRefStore store)
{
var userRefs = store.GetRefsByUser(userID);
if (userRefs != null)
{
var toAdd = userRefs.Where(r => !r.Removed &&
r.RefType == UserGroupRefType.Contains &&
!Constants.BuildinGroups.Any(g => g.ID.Equals(r.GroupId)))
.Select(r => r.GroupId);
result.AddRange(toAdd);
}
}
httpRequestDictionary.Add(userID.ToString(), result);
return result;
}
public bool IsUserInGroup(Guid userId, Guid groupId)
{
return IsUserInGroupInternal(userId, groupId, GetRefsInternal());
@ -520,11 +462,11 @@ namespace ASC.Core
public Guid GetDepartmentManager(Guid deparmentID)
{
return GetRefsInternal()
.Values
.Where(r => r.RefType == UserGroupRefType.Manager && r.GroupId == deparmentID && !r.Removed)
.Select(r => r.UserId)
.SingleOrDefault();
var groupRef = UserService.GetUserGroupRef(Tenant.TenantId, deparmentID, UserGroupRefType.Manager);
if (groupRef == null) return Guid.Empty;
return groupRef.UserId;
}
public void SetDepartmentManager(Guid deparmentID, Guid userID)
@ -573,9 +515,16 @@ namespace ASC.Core
}
public GroupInfo GetGroupInfo(Guid groupID)
{
return GetGroupsInternal()
.SingleOrDefault(g => g.ID == groupID) ?? Constants.LostGroupInfo;
{
var group = UserService.GetGroup(Tenant.TenantId, groupID);
return new GroupInfo
{
ID = group.Id,
CategoryID = group.CategoryId,
Name = group.Name,
Sid = group.Sid
};
}
public GroupInfo GetGroupInfoBySid(string sid)
@ -584,15 +533,6 @@ namespace ASC.Core
.SingleOrDefault(g => g.Sid == sid) ?? Constants.LostGroupInfo;
}
public DateTime GetMaxGroupsLastModified()
{
return UserService.GetGroups(Tenant.TenantId, default)
.Values
.Select(g => g.LastModified)
.DefaultIfEmpty()
.Max();
}
public GroupInfo SaveGroupInfo(GroupInfo g)
{
if (Constants.LostGroupInfo.Equals(g)) return Constants.LostGroupInfo;
@ -633,23 +573,22 @@ namespace ASC.Core
private IEnumerable<UserInfo> GetUsersInternal()
{
return UserService.GetUsers(Tenant.TenantId, default)
.Values
return UserService.GetUsers(Tenant.TenantId)
.Where(u => !u.Removed);
}
private IEnumerable<GroupInfo> GetGroupsInternal()
{
return UserService.GetGroups(Tenant.TenantId, default)
.Values
return UserService.GetGroups(Tenant.TenantId)
.Where(g => !g.Removed)
.Select(g => new GroupInfo(g.CategoryId) { ID = g.Id, Name = g.Name, Sid = g.Sid })
.Concat(Constants.BuildinGroups);
.Concat(Constants.BuildinGroups)
.ToList();
}
private IDictionary<string, UserGroupRef> GetRefsInternal()
{
return UserService.GetUserGroupRefs(Tenant.TenantId, default);
return UserService.GetUserGroupRefs(Tenant.TenantId);
}
private bool IsUserInGroupInternal(Guid userId, Guid groupId, IDictionary<string, UserGroupRef> refs)

View File

@ -40,7 +40,7 @@ namespace ASC.Core
[Scope(typeof(ConfigureEFUserService), typeof(ConfigureCachedUserService))]
public interface IUserService
{
IDictionary<Guid, UserInfo> GetUsers(int tenant, DateTime from);
IEnumerable<UserInfo> GetUsers(int tenant);
IQueryable<UserInfo> GetUsers(int tenant, bool isAdmin,
EmployeeStatus? employeeStatus,
@ -78,7 +78,7 @@ namespace ASC.Core
void SetUserPasswordHash(int tenant, Guid id, string passwordHash);
IDictionary<Guid, Group> GetGroups(int tenant, DateTime from);
IEnumerable<Group> GetGroups(int tenant);
Group GetGroup(int tenant, Guid id);
@ -86,8 +86,8 @@ namespace ASC.Core
void RemoveGroup(int tenant, Guid id);
IDictionary<string, UserGroupRef> GetUserGroupRefs(int tenant, DateTime from);
UserGroupRef GetUserGroupRef(int tenant, Guid groupId, UserGroupRefType refType);
IDictionary<string, UserGroupRef> GetUserGroupRefs(int tenant);
UserGroupRef SaveUserGroupRef(int tenant, UserGroupRef r);

View File

@ -62,12 +62,12 @@ namespace ASC.Core.Data
[Scope]
class DbQuotaService : IQuotaService
{
private Expression<Func<DbQuota, TenantQuota>> FromDbQuotaToTenantQuota { get; set; }
private Expression<Func<DbQuotaRow, TenantQuotaRow>> FromDbQuotaRowToTenantQuotaRow { get; set; }
private static Expression<Func<DbQuota, TenantQuota>> FromDbQuotaToTenantQuota { get; set; }
private static Expression<Func<DbQuotaRow, TenantQuotaRow>> FromDbQuotaRowToTenantQuotaRow { get; set; }
internal CoreDbContext CoreDbContext { get => LazyCoreDbContext.Value; }
internal Lazy<CoreDbContext> LazyCoreDbContext { get; set; }
public DbQuotaService()
static DbQuotaService()
{
FromDbQuotaToTenantQuota = r => new TenantQuota()
{
@ -91,7 +91,7 @@ namespace ASC.Core.Data
};
}
public DbQuotaService(DbContextManager<CoreDbContext> dbContextManager) : this()
public DbQuotaService(DbContextManager<CoreDbContext> dbContextManager)
{
LazyCoreDbContext = new Lazy<CoreDbContext>(() => dbContextManager.Value);
}

View File

@ -208,11 +208,11 @@ namespace ASC.Core.Data
.FirstOrDefault();
}
public IDictionary<Guid, Group> GetGroups(int tenant, DateTime from)
public IEnumerable<Group> GetGroups(int tenant)
{
return GetGroupQuery(tenant, from)
return GetGroupQuery(tenant)
.Select(FromDbGroupToGroup)
.ToDictionary(r => r.Id, r => r);
.ToList();
}
public UserInfo GetUser(int tenant, Guid id)
@ -225,14 +225,14 @@ namespace ASC.Core.Data
public UserInfo GetUser(int tenant, string email)
{
return GetUserQuery(tenant, default(DateTime))
return GetUserQuery(tenant)
.Select(FromUserToUserInfo)
.FirstOrDefault(r => r.Email == email && !r.Removed);
}
public UserInfo GetUserByUserName(int tenant, string userName)
{
return GetUserQuery(tenant, default(DateTime))
return GetUserQuery(tenant)
.Select(FromUserToUserInfo)
.FirstOrDefault(r => r.UserName == userName && !r.Removed);
}
@ -321,7 +321,7 @@ namespace ASC.Core.Data
SetUserPasswordHash(h2.Tenant, userId, passwordHash);
}
public IDictionary<string, UserGroupRef> GetUserGroupRefs(int tenant, DateTime from)
public UserGroupRef GetUserGroupRef(int tenant, Guid groupId, UserGroupRefType refType)
{
IQueryable<UserGroup> q = UserDbContext.UserGroups;
@ -330,9 +330,17 @@ namespace ASC.Core.Data
q = q.Where(r => r.Tenant == tenant);
}
if (from != default)
return q.Where(r => r.GroupId == groupId && r.RefType == refType && !r.Removed)
.Select(FromUserGroupToUserGroupRef).SingleOrDefault();
}
public IDictionary<string, UserGroupRef> GetUserGroupRefs(int tenant)
{
IQueryable<UserGroup> q = UserDbContext.UserGroups;
if (tenant != Tenant.DEFAULT_TENANT)
{
q = q.Where(r => r.LastModified >= from);
q = q.Where(r => r.Tenant == tenant);
}
return q.Select(FromUserGroupToUserGroupRef).AsEnumerable().ToDictionary(r => r.CreateKey(), r => r);
@ -360,12 +368,11 @@ namespace ASC.Core.Data
return photo ?? new byte[0];
}
public IDictionary<Guid, UserInfo> GetUsers(int tenant, DateTime from)
public IEnumerable<UserInfo> GetUsers(int tenant)
{
return GetUserQuery(tenant, from)
return GetUserQuery(tenant)
.Select(FromUserToUserInfo)
.AsEnumerable()
.ToDictionary(r => r.ID, r => r);
.ToList();
}
public IQueryable<UserInfo> GetUsers(int tenant, bool isAdmin, EmployeeStatus? employeeStatus, List<List<Guid>> includeGroups, List<Guid> excludeGroups, EmployeeActivationStatus? activationStatus, string text, string sortBy, bool sortOrderAsc, long limit, long offset, out int total, out int count)
@ -646,12 +653,12 @@ namespace ASC.Core.Data
tr.Commit();
}
private IQueryable<User> GetUserQuery(int tenant, DateTime from = default)
private IQueryable<User> GetUserQuery(int tenant)
{
return GetUserQuery(UserDbContext, tenant, from);
return GetUserQuery(UserDbContext, tenant);
}
private IQueryable<User> GetUserQuery(UserDbContext userDbContext, int tenant, DateTime from = default)
private IQueryable<User> GetUserQuery(UserDbContext userDbContext, int tenant)
{
var q = userDbContext.Users.AsQueryable();
var where = false;
@ -662,12 +669,6 @@ namespace ASC.Core.Data
where = true;
}
if (from != default)
{
q = q.Where(r => r.LastModified >= from);
where = true;
}
if (!where)
{
q = q.Where(r => 1 == 0);
@ -676,7 +677,7 @@ namespace ASC.Core.Data
return q;
}
private IQueryable<DbGroup> GetGroupQuery(int tenant, DateTime from = default)
private IQueryable<DbGroup> GetGroupQuery(int tenant)
{
var q = UserDbContext.Groups.Where(r => true);
@ -685,11 +686,6 @@ namespace ASC.Core.Data
q = q.Where(r => r.Tenant == tenant);
}
if (from != default)
{
q = q.Where(r => r.LastModified >= from);
}
return q;
}

View File

@ -58,7 +58,7 @@ namespace ASC.Core.Common.EF
{
optionsBuilder.UseLoggerFactory(LoggerFactory);
optionsBuilder.EnableSensitiveDataLogging();
Provider = GetProviderByConnectionString();
Provider = GetProviderByConnectionString();
switch (Provider)
{
case Provider.MySql:

View File

@ -15,18 +15,20 @@ namespace ASC.Core.Common.EF
public const string baseName = "default";
private EFLoggerFactory LoggerFactory { get; }
private ConfigurationExtension Configuration { get; }
private string MigrateAssembly { get; }
public ConfigureDbContext(EFLoggerFactory loggerFactory, ConfigurationExtension configuration)
{
LoggerFactory = loggerFactory;
Configuration = configuration;
MigrateAssembly = Configuration["testAssembly"];
}
public void Configure(string name, T context)
{
context.LoggerFactory = LoggerFactory;
context.ConnectionStringSettings = Configuration.GetConnectionStrings(name) ?? Configuration.GetConnectionStrings(baseName);
context.MigrateAssembly = Configuration["testAssembly"];
context.MigrateAssembly = MigrateAssembly;
}
public void Configure(T context)

View File

@ -83,7 +83,7 @@ namespace ASC.Data.Storage
virtPath = "";
}
if (virtPath.StartsWith("~") && !Uri.IsWellFormedUriString(virtPath, UriKind.Absolute))
if (virtPath.StartsWith('~') && !Uri.IsWellFormedUriString(virtPath, UriKind.Absolute))
{
var rootPath = "/";
if (!string.IsNullOrEmpty(WebHostEnvironment?.WebRootPath) && WebHostEnvironment?.WebRootPath.Length > 1)

View File

@ -26,30 +26,37 @@
using System;
using System.Diagnostics;
using System.Globalization;
using System.Text;
using Newtonsoft.Json.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace ASC.FederatedLogin
{
[DebuggerDisplay("{AccessToken} (expired: {IsExpired})")]
public class OAuth20Token
{
[JsonPropertyName("access_token")]
public string AccessToken { get; set; }
[JsonPropertyName("refresh_token")]
public string RefreshToken { get; set; }
[JsonPropertyName("expires_in")]
[JsonNumberHandling(JsonNumberHandling.AllowReadingFromString)]
public long ExpiresIn { get; set; }
[JsonPropertyName("client_id")]
public string ClientID { get; set; }
[JsonPropertyName("client_secret")]
public string ClientSecret { get; set; }
[JsonPropertyName("redirect_uri")]
public string RedirectUri { get; set; }
[JsonPropertyName("timestamp")]
public DateTime Timestamp { get; set; }
[JsonIgnore]
public string OriginJson { get; set; }
public OAuth20Token()
@ -92,55 +99,19 @@ namespace ASC.FederatedLogin
public static OAuth20Token FromJson(string json)
{
if (string.IsNullOrEmpty(json)) return null;
var parser = JObject.Parse(json);
if (parser == null) return null;
var accessToken = parser.Value<string>("access_token");
if (string.IsNullOrEmpty(accessToken))
return null;
var token = new OAuth20Token
{
AccessToken = accessToken,
RefreshToken = parser.Value<string>("refresh_token"),
ClientID = parser.Value<string>("client_id"),
ClientSecret = parser.Value<string>("client_secret"),
RedirectUri = parser.Value<string>("redirect_uri"),
OriginJson = json,
};
if (long.TryParse(parser.Value<string>("expires_in"), out var expiresIn))
token.ExpiresIn = expiresIn;
try
{
token.Timestamp =
!string.IsNullOrEmpty(parser.Value<string>("timestamp"))
? parser.Value<DateTime>("timestamp")
: DateTime.UtcNow;
return JsonSerializer.Deserialize<OAuth20Token>(json);
}
catch (Exception)
{
token.Timestamp = DateTime.MinValue;
return null;
}
return token;
}
public string ToJson()
{
var sb = new StringBuilder();
sb.Append("{");
sb.AppendFormat(" \"access_token\": \"{0}\"", AccessToken);
sb.AppendFormat(", \"refresh_token\": \"{0}\"", RefreshToken);
sb.AppendFormat(", \"expires_in\": \"{0}\"", ExpiresIn);
sb.AppendFormat(", \"client_id\": \"{0}\"", ClientID);
sb.AppendFormat(", \"client_secret\": \"{0}\"", ClientSecret);
sb.AppendFormat(", \"redirect_uri\": \"{0}\"", RedirectUri);
sb.AppendFormat(", \"timestamp\": \"{0}\"", Timestamp.ToString("o", new CultureInfo("en-US")));
sb.Append("}");
return sb.ToString();
return JsonSerializer.Serialize(this);
}
public override string ToString()

View File

@ -36,7 +36,6 @@ using System.Threading.Tasks;
using ASC.Common;
using ASC.Common.Caching;
using ASC.Common.Logging;
using ASC.Common.Utils;
using ASC.Core;
using ASC.Core.Common.EF;
using ASC.Core.Common.EF.Context;
@ -103,14 +102,14 @@ namespace ASC.ElasticSearch
DbContextManager<WebstudioDbContext> dbContextManager,
TenantManager tenantManager,
BaseIndexerHelper baseIndexerHelper,
ConfigurationExtension configurationExtension,
SettingsHelper settingsHelper,
IServiceProvider serviceProvider)
{
Client = client;
Log = log.CurrentValue;
TenantManager = tenantManager;
BaseIndexerHelper = baseIndexerHelper;
Settings = Settings.GetInstance(configurationExtension);
Settings = settingsHelper.Settings;
ServiceProvider = serviceProvider;
LazyWebstudioDbContext = new Lazy<WebstudioDbContext>(() => dbContextManager.Value);
}

View File

@ -29,7 +29,6 @@ using System.Text;
using ASC.Common;
using ASC.Common.Logging;
using ASC.Common.Utils;
using ASC.Core;
using ASC.Core.Tenants;
using ASC.ElasticSearch.Service;
@ -54,11 +53,11 @@ namespace ASC.ElasticSearch
private CoreConfiguration CoreConfiguration { get; }
private Settings Settings { get; }
public Client(IOptionsMonitor<ILog> option, CoreConfiguration coreConfiguration, ConfigurationExtension configurationExtension)
public Client(IOptionsMonitor<ILog> option, CoreConfiguration coreConfiguration, SettingsHelper settingsHelper)
{
Log = option.Get("ASC.Indexer");
CoreConfiguration = coreConfiguration;
Settings = Settings.GetInstance(configurationExtension);
Settings = settingsHelper.Settings;
}
public ElasticClient Instance

View File

@ -32,7 +32,6 @@ using System.Threading.Tasks;
using ASC.Common;
using ASC.Common.Caching;
using ASC.Common.Logging;
using ASC.Common.Utils;
using ASC.ElasticSearch.Service;
using Microsoft.Extensions.DependencyInjection;
@ -58,14 +57,14 @@ namespace ASC.ElasticSearch
ICacheNotify<AscCacheItem> notify,
ICacheNotify<IndexAction> indexNotify,
IServiceProvider serviceProvider,
ConfigurationExtension configurationExtension)
SettingsHelper settingsHelper)
{
Log = options.Get("ASC.Indexer");
Notify = notify;
IndexNotify = indexNotify;
ServiceProvider = serviceProvider;
CancellationTokenSource = new CancellationTokenSource();
var settings = Settings.GetInstance(configurationExtension);
var settings = settingsHelper.Settings;
Period = TimeSpan.FromMinutes(settings.Period.Value);
}

View File

@ -30,23 +30,29 @@ using ASC.Common.Utils;
namespace ASC.ElasticSearch.Service
{
[Singletone]
public class SettingsHelper
{
public Settings Settings { get; set; }
public SettingsHelper(ConfigurationExtension configuration)
{
var cfg = configuration.GetSetting<Settings>("elastic");
Settings = new Settings
{
Scheme = cfg.Scheme ?? "http",
Host = cfg.Host ?? "localhost",
Port = cfg.Port ?? 9200,
Period = cfg.Period ?? 1,
MaxContentLength = cfg.MaxContentLength ?? 100 * 1024 * 1024L,
MaxFileSize = cfg.MaxFileSize ?? 10 * 1024 * 1024L,
Threads = cfg.Threads ?? 1,
HttpCompression = cfg.HttpCompression ?? true
};
}
}
public class Settings
{
public static Settings GetInstance(ConfigurationExtension configuration)
{
var result = new Settings();
var cfg = configuration.GetSetting<Settings>("elastic");
result.Scheme = cfg.Scheme ?? "http";
result.Host = cfg.Host ?? "localhost";
result.Port = cfg.Port ?? 9200;
result.Period = cfg.Period ?? 1;
result.MaxContentLength = cfg.MaxContentLength ?? 100 * 1024 * 1024L;
result.MaxFileSize = cfg.MaxFileSize ?? 10 * 1024 * 1024L;
result.Threads = cfg.Threads ?? 1;
result.HttpCompression = cfg.HttpCompression ?? true;
return result;
}
public string Host { get; set; }
public int? Port { get; set; }

View File

@ -3,7 +3,6 @@
<extensions>
<add assembly="NLog.Web.AspNetCore"/>
<add assembly="ASC.Common"/>
</extensions>
<variable name="dir" value="..\Logs\"/>
@ -11,9 +10,9 @@
<conversionPattern value=""/>
<targets async="true">
<default-target-parameters type="SelfCleaning" encoding="utf-8" archiveNumbering="DateAndSequence" archiveEvery="Day" enableArchiveFileCompression="true" archiveAboveSize="52428800" keepFileOpen="true" archiveDateFormat="MM-dd" layout="${date:format=yyyy-MM-dd HH\:mm\:ss,fff} ${level:uppercase=true} [${threadid}] ${logger} - ${message} ${exception:format=ToString}"/>
<target name="web" type="SelfCleaning" fileName="${var:dir}${var:name}.log" />
<target name="sql" type="SelfCleaning" fileName="${var:dir}${var:name}.sql.log" layout="${date:universalTime=true:format=yyyy-MM-dd HH\:mm\:ss,fff}|${threadid}|${event-properties:item=elapsed}|${message}|${replace:inner=${event-properties:item=commandText}:searchFor=\\r\\n|\\s:replaceWith= :regex=true}|${event-properties:item=parameters}"/>
<default-target-parameters type="File" encoding="utf-8" maxArchiveDays="30" archiveNumbering="DateAndSequence" archiveEvery="Day" enableArchiveFileCompression="true" archiveAboveSize="52428800" keepFileOpen="true" archiveDateFormat="MM-dd" layout="${date:format=yyyy-MM-dd HH\:mm\:ss,fff} ${level:uppercase=true} [${threadid}] ${logger} - ${message} ${exception:format=ToString}"/>
<target name="web" type="File" fileName="${var:dir}${var:name}.log" />
<target name="sql" type="File" fileName="${var:dir}${var:name}.sql.log" layout="${date:universalTime=true:format=yyyy-MM-dd HH\:mm\:ss,fff}|${threadid}|${event-properties:item=elapsed}|${message}|${replace:inner=${event-properties:item=commandText}:searchFor=\\r\\n|\\s:replaceWith= :regex=true}|${event-properties:item=parameters}"/>
<target name="ownFile-web" type="File" fileName="${var:dir}${var:name}.asp.log" layout="${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}|url: ${aspnet-request-url}|action: ${aspnet-mvc-action}" />
</targets>

View File

@ -82,7 +82,7 @@ namespace ASC.Files.Core.Data
CoreConfiguration coreConfiguration,
SettingsManager settingsManager,
AuthContext authContext,
IServiceProvider serviceProvider,
IServiceProvider serviceProvider,
ICache cache)
{
this.cache = cache;
@ -128,7 +128,7 @@ namespace ASC.Files.Core.Data
.Join(FilesDbContext.Tree, a => a.FolderId, b => b.FolderId, (file, tree) => new { file, tree })
.Where(r => r.file.TenantId == f.TenantId)
.Where(r => r.tree.ParentId == f.Id)
.Select(r=> r.file.Id)
.Select(r => r.file.Id)
.Distinct()
.Count();
@ -191,7 +191,7 @@ namespace ASC.Files.Core.Data
internal static IQueryable<T> BuildSearch<T>(IQueryable<T> query, string text, SearhTypeEnum searhTypeEnum) where T : IDbSearch
{
var lowerText = text.ToLower().Trim().Replace("%", "\\%").Replace("_", "\\_");
var lowerText = GetSearchText(text);
return searhTypeEnum switch
{
@ -200,7 +200,9 @@ namespace ASC.Files.Core.Data
SearhTypeEnum.Any => query.Where(r => r.Title.ToLower().Contains(lowerText)),
_ => query,
};
}
}
internal static string GetSearchText(string text) => (text ?? "").ToLower().Trim().Replace("%", "\\%").Replace("_", "\\_");
internal enum SearhTypeEnum
{

View File

@ -34,7 +34,6 @@ using System.Threading.Tasks;
using ASC.Common;
using ASC.Common.Caching;
using ASC.Common.Utils;
using ASC.Core;
using ASC.Core.Common.EF;
using ASC.Core.Common.EF.Context;
@ -100,7 +99,7 @@ namespace ASC.Files.Core.Data
ChunkedUploadSessionHolder chunkedUploadSessionHolder,
ProviderFolderDao providerFolderDao,
CrossDao crossDao,
ConfigurationExtension configurationExtension)
SettingsHelper settingsHelper)
: base(
dbContextManager,
dbContextManager1,
@ -126,7 +125,7 @@ namespace ASC.Files.Core.Data
ChunkedUploadSessionHolder = chunkedUploadSessionHolder;
ProviderFolderDao = providerFolderDao;
CrossDao = crossDao;
Settings = Settings.GetInstance(configurationExtension);
Settings = settingsHelper.Settings;
}
public void InvalidateCache(int fileId)

File diff suppressed because it is too large Load Diff

View File

@ -31,7 +31,6 @@ using System.Threading.Tasks;
using ASC.Common;
using ASC.Common.Caching;
using ASC.Common.Logging;
using ASC.Common.Utils;
using ASC.Core;
using ASC.Core.Common.EF.Model;
using ASC.ElasticSearch;
@ -60,11 +59,11 @@ namespace ASC.Web.Files.Core.Search
IServiceProvider serviceProvider,
IDaoFactory daoFactory,
ICache cache,
ConfigurationExtension configurationExtension)
SettingsHelper settingsHelper)
: base(options, tenantManager, searchSettingsHelper, factoryIndexer, baseIndexer, serviceProvider, cache)
{
DaoFactory = daoFactory;
Settings = Settings.GetInstance(configurationExtension);
Settings = settingsHelper.Settings;
}
public override void IndexAll()

View File

@ -32,7 +32,6 @@ using System.Threading.Tasks;
using ASC.Common;
using ASC.Common.Caching;
using ASC.Common.Logging;
using ASC.Common.Utils;
using ASC.Core;
using ASC.Core.Common.EF.Model;
using ASC.ElasticSearch;
@ -61,11 +60,11 @@ namespace ASC.Web.Files.Core.Search
IServiceProvider serviceProvider,
IDaoFactory daoFactory,
ICache cache,
ConfigurationExtension configurationExtension)
SettingsHelper settingsHelper)
: base(options, tenantManager, searchSettingsHelper, factoryIndexer, baseIndexer, serviceProvider, cache)
{
DaoFactory = daoFactory;
Settings = Settings.GetInstance(configurationExtension);
Settings = settingsHelper.Settings;
}
public override void IndexAll()

View File

@ -53,6 +53,7 @@ using ASC.Security.Cryptography;
using ASC.Web.Files.Classes;
using ASC.Web.Files.Helpers;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
@ -136,7 +137,7 @@ namespace ASC.Files.Thirdparty
return FilesDbContext.ThirdpartyAccount
.Where(r => r.TenantId == TenantID)
.Where(r => r.UserId == userId)
.ToList()
.AsEnumerable()
.Select(ToProviderInfo)
.ToList();
}
@ -145,35 +146,25 @@ namespace ASC.Files.Thirdparty
Logger.Error(string.Format("GetProvidersInfoInternal: user = {0}", userId), e);
return new List<IProviderInfo>();
}
}
}
static Func<FilesDbContext, int, int, FolderType, Guid, string, IEnumerable<DbFilesThirdpartyAccount>> getProvidersInfoQuery =
EF.CompileQuery((FilesDbContext ctx, int tenantId, int linkId, FolderType folderType, Guid userId, string searchText) =>
ctx.ThirdpartyAccount
.AsNoTracking()
.Where(r => r.TenantId == tenantId)
.Where(r => !(folderType == FolderType.USER || folderType == FolderType.DEFAULT && linkId == -1) || r.UserId == userId)
.Where(r => linkId == -1 || r.Id == linkId)
.Where(r => folderType == FolderType.DEFAULT || r.FolderType == folderType)
.Where(r => searchText == "" || r.Title.ToLower().Contains(searchText))
);
private List<IProviderInfo> GetProvidersInfoInternal(int linkId = -1, FolderType folderType = FolderType.DEFAULT, string searchText = null)
{
var querySelect = FilesDbContext.ThirdpartyAccount.Where(r => r.TenantId == TenantID);
if (folderType == FolderType.USER || folderType == FolderType.DEFAULT && linkId == -1)
{
querySelect = querySelect.Where(r => r.UserId == SecurityContext.CurrentAccount.ID);
}
if (linkId != -1)
{
querySelect = querySelect.Where(r => r.Id == linkId);
}
if (folderType != FolderType.DEFAULT)
{
querySelect = querySelect.Where(r => r.FolderType == folderType);
}
if (!string.IsNullOrEmpty(searchText))
{
querySelect = BuildSearch(querySelect, searchText, SearhTypeEnum.Any);
}
try
{
return querySelect.ToList()
return getProvidersInfoQuery(FilesDbContext, TenantID, linkId, folderType, SecurityContext.CurrentAccount.ID, GetSearchText(searchText))
.AsEnumerable()
.Select(ToProviderInfo)
.ToList();
}

View File

@ -46,7 +46,20 @@ namespace ASC.Files.Thirdparty.ProviderDao
{
internal class ProviderDaoBase : ThirdPartyProviderDao, IDisposable
{
private readonly List<IDaoSelector> Selectors;
private List<IDaoSelector> selectors;
private List<IDaoSelector> Selectors
{
get => selectors ??= new List<IDaoSelector>
{
//Fill in selectors
ServiceProvider.GetService<SharpBoxDaoSelector>(),
ServiceProvider.GetService<SharePointDaoSelector>(),
ServiceProvider.GetService<GoogleDriveDaoSelector>(),
ServiceProvider.GetService<BoxDaoSelector>(),
ServiceProvider.GetService<DropboxDaoSelector>(),
ServiceProvider.GetService<OneDriveDaoSelector>()
};
}
private int tenantID;
private int TenantID { get => tenantID != 0 ? tenantID : (tenantID = TenantManager.GetCurrentTenant().TenantId); }
@ -63,17 +76,6 @@ namespace ASC.Files.Thirdparty.ProviderDao
SecurityDao = securityDao;
TagDao = tagDao;
CrossDao = crossDao;
Selectors = new List<IDaoSelector>
{
//Fill in selectors
ServiceProvider.GetService<SharpBoxDaoSelector>(),
ServiceProvider.GetService<SharePointDaoSelector>(),
ServiceProvider.GetService<GoogleDriveDaoSelector>(),
ServiceProvider.GetService<BoxDaoSelector>(),
ServiceProvider.GetService<DropboxDaoSelector>(),
ServiceProvider.GetService<OneDriveDaoSelector>()
};
}
protected IServiceProvider ServiceProvider { get; }
@ -160,8 +162,11 @@ namespace ASC.Files.Thirdparty.ProviderDao
}
public void Dispose()
{
Selectors.ForEach(r => r.Dispose());
{
if (selectors != null)
{
selectors.ForEach(r => r.Dispose());
}
}
}
}

View File

@ -40,9 +40,10 @@ namespace ASC.Files.Thirdparty
{
private IServiceProvider ServiceProvider { get; }
private IDaoFactory DaoFactory { get; }
public Regex Selector { get; set; }
protected internal abstract string Name { get; }
protected internal abstract string Id { get; }
protected internal abstract string Id { get; }
public Regex Selector { get => selector ??= new Regex(@"^" + Id + @"-(?'id'\d+)(-(?'path'.*)){0,1}$", RegexOptions.Singleline | RegexOptions.Compiled); }
private Regex selector;
private Dictionary<string, ThirdPartyProviderDao<T>> Providers { get; set; }
@ -52,7 +53,6 @@ namespace ASC.Files.Thirdparty
{
ServiceProvider = serviceProvider;
DaoFactory = daoFactory;
Selector = new Regex(@"^" + Id + @"-(?'id'\d+)(-(?'path'.*)){0,1}$", RegexOptions.Singleline | RegexOptions.Compiled);
Providers = new Dictionary<string, ThirdPartyProviderDao<T>>();
}

View File

@ -37,10 +37,29 @@ using Microsoft.Extensions.Configuration;
namespace ASC.Web.Files.Helpers
{
[Singletone]
public class ThirdpartyConfigurationData
{
private IConfiguration Configuration { get; }
private List<string> thirdPartyProviders;
public List<string> ThirdPartyProviders
{
get
{
return thirdPartyProviders ??= (Configuration.GetSection("files:thirdparty:enable").Get<string[]>() ?? new string[] { }).ToList();
}
}
public ThirdpartyConfigurationData(IConfiguration configuration)
{
Configuration = configuration;
}
}
[Scope(Additional = typeof(BaseLoginProviderExtension))]
public class ThirdpartyConfiguration
{
private IConfiguration Configuration { get; }
private ThirdpartyConfigurationData Configuration { get; }
private Lazy<BoxLoginProvider> BoxLoginProvider { get; }
private Lazy<DropboxLoginProvider> DropboxLoginProvider { get; }
private Lazy<OneDriveLoginProvider> OneDriveLoginProvider { get; }
@ -48,7 +67,7 @@ namespace ASC.Web.Files.Helpers
private Lazy<GoogleLoginProvider> GoogleLoginProvider { get; }
public ThirdpartyConfiguration(
IConfiguration configuration,
ThirdpartyConfigurationData configuration,
ConsumerFactory consumerFactory)
{
Configuration = configuration;
@ -58,14 +77,10 @@ namespace ASC.Web.Files.Helpers
DocuSignLoginProvider = new Lazy<DocuSignLoginProvider>(() => consumerFactory.Get<DocuSignLoginProvider>());
GoogleLoginProvider = new Lazy<GoogleLoginProvider>(() => consumerFactory.Get<GoogleLoginProvider>());
}
private IEnumerable<string> thirdPartyProviders;
public IEnumerable<string> ThirdPartyProviders
public List<string> ThirdPartyProviders
{
get
{
return thirdPartyProviders ??= (Configuration.GetSection("files:thirdparty:enable").Get<string[]>() ?? new string[] { }).ToList();
}
get => Configuration.ThirdPartyProviders;
}
public bool SupportInclusion(IDaoFactory daoFactory)
@ -80,7 +95,7 @@ namespace ASC.Web.Files.Helpers
{
get
{
return ThirdPartyProviders.Contains("box") && BoxLoginProvider.Value.IsEnabled;
return ThirdPartyProviders.Exists(r => r == "box") && BoxLoginProvider.Value.IsEnabled;
}
}
@ -88,7 +103,7 @@ namespace ASC.Web.Files.Helpers
{
get
{
return ThirdPartyProviders.Contains("dropboxv2") && DropboxLoginProvider.Value.IsEnabled;
return ThirdPartyProviders.Exists(r => r == "dropboxv2") && DropboxLoginProvider.Value.IsEnabled;
}
}
@ -96,38 +111,38 @@ namespace ASC.Web.Files.Helpers
{
get
{
return ThirdPartyProviders.Contains("onedrive") && OneDriveLoginProvider.Value.IsEnabled;
return ThirdPartyProviders.Exists(r => r == "onedrive") && OneDriveLoginProvider.Value.IsEnabled;
}
}
public bool SupportSharePointInclusion
{
get { return ThirdPartyProviders.Contains("sharepoint"); }
get { return ThirdPartyProviders.Exists(r => r == "sharepoint"); }
}
public bool SupportWebDavInclusion
{
get { return ThirdPartyProviders.Contains("webdav"); }
get { return ThirdPartyProviders.Exists(r => r == "webdav"); }
}
public bool SupportNextcloudInclusion
{
get { return ThirdPartyProviders.Contains("nextcloud"); }
get { return ThirdPartyProviders.Exists(r => r == "nextcloud"); }
}
public bool SupportOwncloudInclusion
{
get { return ThirdPartyProviders.Contains("owncloud"); }
get { return ThirdPartyProviders.Exists(r => r == "owncloud"); }
}
public bool SupportkDriveInclusion
{
get { return ThirdPartyProviders.Contains("kdrive"); }
get { return ThirdPartyProviders.Exists(r => r == "kdrive"); }
}
public bool SupportYandexInclusion
{
get { return ThirdPartyProviders.Contains("yandex"); }
get { return ThirdPartyProviders.Exists(r => r == "yandex"); }
}
public string DropboxAppKey
@ -144,7 +159,7 @@ namespace ASC.Web.Files.Helpers
{
get
{
return ThirdPartyProviders.Contains("docusign") && DocuSignLoginProvider.Value.IsEnabled;
return ThirdPartyProviders.Exists(r => r == "docusign") && DocuSignLoginProvider.Value.IsEnabled;
}
}
@ -152,7 +167,7 @@ namespace ASC.Web.Files.Helpers
{
get
{
return ThirdPartyProviders.Contains("google") && GoogleLoginProvider.Value.IsEnabled;
return ThirdPartyProviders.Exists(r => r == "google") && GoogleLoginProvider.Value.IsEnabled;
}
}

View File

@ -143,9 +143,8 @@ const checkTheme = () => {
const theme = localStorage.getItem('theme');
if (theme) return theme;
console.log(theme);
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
console.log(window.matchMedia('(prefers-color-scheme: light)').matches);
return 'Dark';
}

View File

@ -38,6 +38,143 @@ using Microsoft.Extensions.Configuration;
namespace ASC.Web.Core.Files
{
[Singletone]
public class FileUtilityConfiguration
{
private IConfiguration Configuration { get; }
public FileUtilityConfiguration(IConfiguration configuration)
{
Configuration = configuration;
}
private List<string> extsIndexing;
public List<string> ExtsIndexing { get => extsIndexing ??= (Configuration.GetSection("files:index").Get<string[]>() ?? new string[] { }).ToList(); }
private List<string> extsImagePreviewed;
public List<string> ExtsImagePreviewed { get => extsImagePreviewed ??= (Configuration.GetSection("files:viewed-images").Get<string[]>() ?? new string[] { }).ToList(); }
private List<string> extsMediaPreviewed;
public List<string> ExtsMediaPreviewed { get => extsMediaPreviewed ??= (Configuration.GetSection("files:viewed-media").Get<string[]>() ?? new string[] { }).ToList(); }
private List<string> extsWebPreviewed;
public List<string> ExtsWebPreviewed
{
get
{
return extsWebPreviewed ??= (Configuration.GetSection("files:docservice:viewed-docs").Get<string[]>() ?? new string[] { }).ToList();
}
}
private List<string> extsWebEdited;
public List<string> ExtsWebEdited
{
get
{
return extsWebEdited ??= (Configuration.GetSection("files:docservice:edited-docs").Get<string[]>() ?? new string[] { }).ToList();
}
}
private List<string> extsWebEncrypt;
public List<string> ExtsWebEncrypt { get => extsWebEncrypt ??= (Configuration.GetSection("files:docservice:encrypted-docs").Get<string[]>() ?? new string[] { }).ToList(); }
private List<string> extsWebReviewed;
public List<string> ExtsWebReviewed
{
get
{
return extsWebReviewed ??= (Configuration.GetSection("files:docservice:reviewed-docs").Get<string[]>() ?? new string[] { }).ToList();
}
}
private List<string> extsWebCustomFilterEditing;
public List<string> ExtsWebCustomFilterEditing
{
get
{
return extsWebCustomFilterEditing ??= (Configuration.GetSection("files:docservice:customfilter-docs").Get<string[]>() ?? new string[] { }).ToList();
}
}
private List<string> extsWebRestrictedEditing;
public List<string> ExtsWebRestrictedEditing
{
get
{
return extsWebRestrictedEditing ??= (Configuration.GetSection("files:docservice:formfilling-docs").Get<string[]>() ?? new string[] { }).ToList();
}
}
private List<string> extsWebCommented;
public List<string> ExtsWebCommented
{
get
{
return extsWebCommented ??= (Configuration.GetSection("files:docservice:commented-docs").Get<string[]>() ?? new string[] { }).ToList();
}
}
private List<string> extsWebTemplate;
public List<string> ExtsWebTemplate
{
get
{
return extsWebTemplate ??= (Configuration.GetSection("files:docservice:template-docs").Get<string[]>() ?? new string[] { }).ToList();
}
}
private List<string> extsMustConvert;
public List<string> ExtsMustConvert
{
get
{
return extsMustConvert ??= (Configuration.GetSection("files:docservice:convert-docs").Get<string[]>() ?? new string[] { }).ToList();
}
}
private List<string> extsCoAuthoring;
public List<string> ExtsCoAuthoring
{
get => extsCoAuthoring ??= (Configuration.GetSection("files:docservice:coauthor-docs").Get<string[]>() ?? new string[] { }).ToList();
}
public Dictionary<FileType, string> InternalExtension
{
get => new Dictionary<FileType, string>
{
{ FileType.Document, Configuration["files:docservice:internal-doc"] ?? ".docx" },
{ FileType.Spreadsheet, Configuration["files:docservice:internal-xls"] ?? ".xlsx" },
{ FileType.Presentation, Configuration["files:docservice:internal-ppt"] ?? ".pptx" }
};
}
internal string GetSignatureSecret()
{
var result = Configuration["files:docservice:secret:value"] ?? "";
var regex = new Regex(@"^\s+$");
if (regex.IsMatch(result))
result = "";
return result;
}
internal string GetSignatureHeader()
{
var result = (Configuration["files:docservice:secret:header"] ?? "").Trim();
if (string.IsNullOrEmpty(result))
result = "Authorization";
return result;
}
internal bool GetCanForcesave()
{
return !bool.TryParse(Configuration["files:docservice:forcesave"] ?? "", out var canForcesave) || canForcesave;
}
}
[Scope]
public class FileUtility
{
@ -45,11 +182,11 @@ namespace ASC.Web.Core.Files
private FilesDbContext FilesDbContext { get => LazyFilesDbContext.Value; }
public FileUtility(
IConfiguration configuration,
FileUtilityConfiguration fileUtilityConfiguration,
FilesLinkUtility filesLinkUtility,
DbContextManager<FilesDbContext> dbContextManager)
{
Configuration = configuration;
FileUtilityConfiguration = fileUtilityConfiguration;
FilesLinkUtility = filesLinkUtility;
LazyFilesDbContext = new Lazy<FilesDbContext>(() => dbContextManager.Get("files"));
CanForcesave = GetCanForcesave();
@ -117,52 +254,62 @@ namespace ASC.Web.Core.Files
public bool CanImageView(string fileName)
{
return ExtsImagePreviewed.Contains(GetFileExtension(fileName), StringComparer.CurrentCultureIgnoreCase);
var ext = GetFileExtension(fileName);
return ExtsImagePreviewed.Exists(r => r.Equals(ext, StringComparison.OrdinalIgnoreCase));
}
public bool CanMediaView(string fileName)
{
return ExtsMediaPreviewed.Contains(GetFileExtension(fileName), StringComparer.CurrentCultureIgnoreCase);
var ext = GetFileExtension(fileName);
return ExtsMediaPreviewed.Exists(r => r.Equals(ext, StringComparison.OrdinalIgnoreCase));
}
public bool CanWebView(string fileName)
{
return ExtsWebPreviewed.Contains(GetFileExtension(fileName), StringComparer.CurrentCultureIgnoreCase);
var ext = GetFileExtension(fileName);
return ExtsWebPreviewed.Exists(r => r.Equals(ext, StringComparison.OrdinalIgnoreCase));
}
public bool CanWebEdit(string fileName)
{
return ExtsWebEdited.Contains(GetFileExtension(fileName), StringComparer.CurrentCultureIgnoreCase);
var ext = GetFileExtension(fileName);
return ExtsWebEdited.Exists(r => r.Equals(ext, StringComparison.OrdinalIgnoreCase));
}
public bool CanWebReview(string fileName)
{
return ExtsWebReviewed.Contains(GetFileExtension(fileName), StringComparer.CurrentCultureIgnoreCase);
var ext = GetFileExtension(fileName);
return ExtsWebReviewed.Exists(r => r.Equals(ext, StringComparison.OrdinalIgnoreCase));
}
public bool CanWebCustomFilterEditing(string fileName)
{
return ExtsWebCustomFilterEditing.Contains(GetFileExtension(fileName), StringComparer.CurrentCultureIgnoreCase);
var ext = GetFileExtension(fileName);
return ExtsWebCustomFilterEditing.Exists(r => r.Equals(ext, StringComparison.OrdinalIgnoreCase));
}
public bool CanWebRestrictedEditing(string fileName)
{
return ExtsWebRestrictedEditing.Contains(GetFileExtension(fileName), StringComparer.CurrentCultureIgnoreCase);
var ext = GetFileExtension(fileName);
return ExtsWebRestrictedEditing.Exists(r => r.Equals(ext, StringComparison.OrdinalIgnoreCase));
}
public bool CanWebComment(string fileName)
{
return ExtsWebCommented.Contains(GetFileExtension(fileName), StringComparer.CurrentCultureIgnoreCase);
var ext = GetFileExtension(fileName);
return ExtsWebCommented.Exists(r => r.Equals(ext, StringComparison.OrdinalIgnoreCase));
}
public bool CanCoAuhtoring(string fileName)
{
return ExtsCoAuthoring.Contains(GetFileExtension(fileName), StringComparer.CurrentCultureIgnoreCase);
var ext = GetFileExtension(fileName);
return ExtsCoAuthoring.Exists(r => r.Equals(ext, StringComparison.OrdinalIgnoreCase));
}
public bool CanIndex(string fileName)
{
return ExtsIndexing.Contains(GetFileExtension(fileName), StringComparer.CurrentCultureIgnoreCase);
var ext = GetFileExtension(fileName);
return ExtsIndexing.Exists(r => r.Equals(ext, StringComparison.OrdinalIgnoreCase));
}
#endregion
@ -219,16 +366,12 @@ namespace ASC.Web.Core.Files
}
}
private List<string> extsIndexing;
private List<string> ExtsIndexing { get => extsIndexing ??= (Configuration.GetSection("files:index").Get<string[]>() ?? new string[] { }).ToList(); }
private List<string> ExtsIndexing { get => FileUtilityConfiguration.ExtsIndexing; }
private List<string> extsImagePreviewed;
public List<string> ExtsImagePreviewed { get => extsImagePreviewed ??= (Configuration.GetSection("files:viewed-images").Get<string[]>() ?? new string[] { }).ToList(); }
public List<string> ExtsImagePreviewed { get => FileUtilityConfiguration.ExtsImagePreviewed; }
private List<string> extsMediaPreviewed;
public List<string> ExtsMediaPreviewed { get => extsMediaPreviewed ??= (Configuration.GetSection("files:viewed-media").Get<string[]>() ?? new string[] { }).ToList(); }
public List<string> ExtsMediaPreviewed { get => FileUtilityConfiguration.ExtsMediaPreviewed; }
private List<string> extsWebPreviewed;
public List<string> ExtsWebPreviewed
{
get
@ -238,11 +381,10 @@ namespace ASC.Web.Core.Files
return new List<string>();
}
return extsWebPreviewed ??= (Configuration.GetSection("files:docservice:viewed-docs").Get<string[]>() ?? new string[] { }).ToList();
return FileUtilityConfiguration.ExtsWebPreviewed;
}
}
private List<string> extsWebEdited;
public List<string> ExtsWebEdited
{
get
@ -252,14 +394,12 @@ namespace ASC.Web.Core.Files
return new List<string>();
}
return extsWebEdited ??= (Configuration.GetSection("files:docservice:edited-docs").Get<string[]>() ?? new string[] { }).ToList();
return FileUtilityConfiguration.ExtsWebEdited;
}
}
private List<string> extsWebEncrypt;
public List<string> ExtsWebEncrypt { get => extsWebEncrypt ??= (Configuration.GetSection("files:docservice:encrypted-docs").Get<string[]>() ?? new string[] { }).ToList(); }
public List<string> ExtsWebEncrypt { get => FileUtilityConfiguration.ExtsWebEncrypt; }
private List<string> extsWebReviewed;
public List<string> ExtsWebReviewed
{
get
@ -269,11 +409,10 @@ namespace ASC.Web.Core.Files
return new List<string>();
}
return extsWebReviewed ??= (Configuration.GetSection("files:docservice:reviewed-docs").Get<string[]>() ?? new string[] { }).ToList();
return FileUtilityConfiguration.ExtsWebReviewed;
}
}
private List<string> extsWebCustomFilterEditing;
public List<string> ExtsWebCustomFilterEditing
{
get
@ -283,11 +422,10 @@ namespace ASC.Web.Core.Files
return new List<string>();
}
return extsWebCustomFilterEditing ??= (Configuration.GetSection("files:docservice:customfilter-docs").Get<string[]>() ?? new string[] { }).ToList();
return FileUtilityConfiguration.ExtsWebCustomFilterEditing;
}
}
private List<string> extsWebRestrictedEditing;
public List<string> ExtsWebRestrictedEditing
{
get
@ -297,11 +435,10 @@ namespace ASC.Web.Core.Files
return new List<string>();
}
return extsWebRestrictedEditing ??= (Configuration.GetSection("files:docservice:formfilling-docs").Get<string[]>() ?? new string[] { }).ToList();
return FileUtilityConfiguration.ExtsWebRestrictedEditing;
}
}
private List<string> extsWebCommented;
public List<string> ExtsWebCommented
{
get
@ -311,20 +448,15 @@ namespace ASC.Web.Core.Files
return new List<string>();
}
return extsWebCommented ??= (Configuration.GetSection("files:docservice:commented-docs").Get<string[]>() ?? new string[] { }).ToList();
return FileUtilityConfiguration.ExtsWebCommented;
}
}
private List<string> extsWebTemplate;
public List<string> ExtsWebTemplate
{
get
{
return extsWebTemplate ??= (Configuration.GetSection("files:docservice:template-docs").Get<string[]>() ?? new string[] { }).ToList();
}
get => FileUtilityConfiguration.ExtsWebTemplate;
}
private List<string> extsMustConvert;
public List<string> ExtsMustConvert
{
get
@ -334,17 +466,16 @@ namespace ASC.Web.Core.Files
return new List<string>();
}
return extsMustConvert ??= (Configuration.GetSection("files:docservice:convert-docs").Get<string[]>() ?? new string[] { }).ToList();
return FileUtilityConfiguration.ExtsMustConvert;
}
}
private List<string> extsCoAuthoring;
public List<string> ExtsCoAuthoring
{
get => extsCoAuthoring ??= (Configuration.GetSection("files:docservice:coauthor-docs").Get<string[]>() ?? new string[] { }).ToList();
get => FileUtilityConfiguration.ExtsCoAuthoring;
}
private IConfiguration Configuration { get; }
private FileUtilityConfiguration FileUtilityConfiguration { get; }
private FilesLinkUtility FilesLinkUtility { get; }
public static readonly List<string> ExtsArchive = new List<string>
@ -419,15 +550,7 @@ namespace ASC.Web.Core.Files
".xlt", ".xltm", ".xltx",
".pot", ".potm", ".potx",
};
public Dictionary<FileType, string> InternalExtension
{
get => new Dictionary<FileType, string>
{
{ FileType.Document, Configuration["files:docservice:internal-doc"] ?? ".docx" },
{ FileType.Spreadsheet, Configuration["files:docservice:internal-xls"] ?? ".xlsx" },
{ FileType.Presentation, Configuration["files:docservice:internal-ppt"] ?? ".pptx" }
};
}
public Dictionary<FileType, string> InternalExtension => FileUtilityConfiguration.InternalExtension;
public enum CsvDelimiter
{
@ -441,32 +564,13 @@ namespace ASC.Web.Core.Files
public string SignatureSecret { get => GetSignatureSecret(); }
public string SignatureHeader { get => GetSignatureHeader(); }
private string GetSignatureSecret()
{
var result = Configuration["files:docservice:secret:value"] ?? "";
private string GetSignatureSecret() => FileUtilityConfiguration.GetSignatureSecret();
var regex = new Regex(@"^\s+$");
if (regex.IsMatch(result))
result = "";
return result;
}
private string GetSignatureHeader()
{
var result = (Configuration["files:docservice:secret:header"] ?? "").Trim();
if (string.IsNullOrEmpty(result))
result = "Authorization";
return result;
}
private string GetSignatureHeader() => FileUtilityConfiguration.GetSignatureHeader();
public readonly bool CanForcesave;
private bool GetCanForcesave()
{
return !bool.TryParse(Configuration["files:docservice:forcesave"] ?? "", out var canForcesave) || canForcesave;
}
private bool GetCanForcesave() => FileUtilityConfiguration.GetCanForcesave();
#endregion
}