Merge branch 'release/rc-v1.2.0' of github.com:ONLYOFFICE/DocSpace into release/rc-v1.2.0
This commit is contained in:
commit
2684249dfa
@ -44,6 +44,7 @@ CORE=" --core:products:folder=${BASE_DIR}/products --core:products:subfolder=ser
|
||||
|
||||
SERVICE_NAME=(
|
||||
api
|
||||
api-system
|
||||
socket
|
||||
studio-notify
|
||||
notify
|
||||
@ -67,6 +68,11 @@ reassign_values (){
|
||||
WORK_DIR="${BASE_DIR}/studio/ASC.Web.Api/"
|
||||
EXEC_FILE="ASC.Web.Api.dll"
|
||||
;;
|
||||
api-system )
|
||||
SERVICE_PORT="5010"
|
||||
WORK_DIR="${BASE_DIR}/services/ASC.ApiSystem/"
|
||||
EXEC_FILE="ASC.ApiSystem.dll"
|
||||
;;
|
||||
socket )
|
||||
SERVICE_PORT="5028"
|
||||
WORK_DIR="${BASE_DIR}/services/ASC.Socket.IO/"
|
||||
|
@ -105,6 +105,14 @@ Depends: {{product}}-common (= {{package_header_tag_version}}),
|
||||
${shlibs:Depends}
|
||||
Description: Description
|
||||
|
||||
Package: {{product}}-api-system
|
||||
Architecture: any
|
||||
Depends: {{product}}-common (= {{package_header_tag_version}}),
|
||||
dotnet-sdk-6.0,
|
||||
${misc:Depends},
|
||||
${shlibs:Depends}
|
||||
Description: Description
|
||||
|
||||
Package: {{product}}-studio
|
||||
Architecture: any
|
||||
Depends: {{product}}-common (= {{package_header_tag_version}}),
|
||||
|
@ -150,7 +150,7 @@ RUN dos2unix /docker-entrypoint.d/prepare-nginx-proxy.sh && \
|
||||
RUN chown nginx:nginx /etc/nginx/* -R && \
|
||||
chown nginx:nginx /docker-entrypoint.d/* && \
|
||||
# changes for upstream configure
|
||||
# sed -i 's/127.0.0.1:5010/$service_api_system/' /etc/nginx/conf.d/onlyoffice.conf && \
|
||||
sed -i 's/127.0.0.1:5010/$service_api_system/' /etc/nginx/conf.d/onlyoffice.conf && \
|
||||
sed -i 's/127.0.0.1:5012/$service_backup/' /etc/nginx/conf.d/onlyoffice.conf && \
|
||||
sed -i 's/127.0.0.1:5007/$service_files/' /etc/nginx/conf.d/onlyoffice.conf && \
|
||||
sed -i 's/127.0.0.1:5004/$service_people_server/' /etc/nginx/conf.d/onlyoffice.conf && \
|
||||
@ -175,13 +175,13 @@ COPY --from=base --chown=onlyoffice:onlyoffice ${BUILD_PATH}/services/ASC.Data.B
|
||||
CMD ["ASC.Data.Backup.BackgroundTasks.dll", "ASC.Data.Backup.BackgroundTasks"]
|
||||
|
||||
# ASC.ApiSystem ##
|
||||
# FROM dotnetrun AS api_system
|
||||
# WORKDIR ${BUILD_PATH}/services/ASC.ApiSystem/
|
||||
FROM dotnetrun AS api_system
|
||||
WORKDIR ${BUILD_PATH}/services/ASC.ApiSystem/
|
||||
|
||||
# COPY --chown=onlyoffice:onlyoffice docker-entrypoint.py ./docker-entrypoint.py
|
||||
# COPY --from=base --chown=onlyoffice:onlyoffice ${BUILD_PATH}/services/ASC.ApiSystem/service/ .
|
||||
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.py ./docker-entrypoint.py
|
||||
COPY --from=base --chown=onlyoffice:onlyoffice ${BUILD_PATH}/services/ASC.ApiSystem/service/ .
|
||||
|
||||
# CMD ["ASC.ApiSystem.dll", "ASC.ApiSystem"]
|
||||
CMD ["ASC.ApiSystem.dll", "ASC.ApiSystem"]
|
||||
|
||||
## ASC.ClearEvents ##
|
||||
FROM dotnetrun AS clear-events
|
||||
|
@ -92,12 +92,12 @@ services:
|
||||
target: api
|
||||
image: "${REPO}/${DOCKER_IMAGE_PREFIX}-api:${DOCKER_TAG}"
|
||||
|
||||
# onlyoffice-api-system:
|
||||
# build:
|
||||
# context: ./
|
||||
# dockerfile: "${DOCKERFILE}"
|
||||
# target: api_system
|
||||
# image: "${REPO}/${DOCKER_IMAGE_PREFIX}-api-system:${DOCKER_TAG}"
|
||||
onlyoffice-api-system:
|
||||
build:
|
||||
context: ./
|
||||
dockerfile: "${DOCKERFILE}"
|
||||
target: api_system
|
||||
image: "${REPO}/${DOCKER_IMAGE_PREFIX}-api-system:${DOCKER_TAG}"
|
||||
|
||||
onlyoffice-studio:
|
||||
build:
|
||||
|
@ -29,6 +29,7 @@ x-service: &x-service-base
|
||||
- files_data:/var/www/products/ASC.Files/server/
|
||||
- people_data:/var/www/products/ASC.People/server/
|
||||
- ${ROOT_DIR}/config/appsettings.${ENV_EXTENSION}.json:/app/onlyoffice/config/appsettings.${ENV_EXTENSION}.json
|
||||
- ${ROOT_DIR}/config/apisystem.${ENV_EXTENSION}.json:/app/onlyoffice/config/apisystem.${ENV_EXTENSION}.json
|
||||
|
||||
services:
|
||||
onlyoffice-elasticsearch:
|
||||
@ -116,10 +117,10 @@ services:
|
||||
image: "${REPO}/${DOCKER_IMAGE_PREFIX}-api:${DOCKER_TAG}"
|
||||
container_name: ${API_HOST}
|
||||
|
||||
# onlyoffice-api-system:
|
||||
# <<: *x-service-base
|
||||
# image: "${REPO}/${DOCKER_IMAGE_PREFIX}-api-system:${DOCKER_TAG}"
|
||||
# container_name: ${API_SYSTEM_HOST}
|
||||
onlyoffice-api-system:
|
||||
<<: *x-service-base
|
||||
image: "${REPO}/${DOCKER_IMAGE_PREFIX}-api-system:${DOCKER_TAG}"
|
||||
container_name: ${API_SYSTEM_HOST}
|
||||
|
||||
onlyoffice-studio:
|
||||
<<: *x-service-base
|
||||
@ -163,7 +164,7 @@ services:
|
||||
# - onlyoffice-telegram-service
|
||||
# - onlyoffice-urlshortener
|
||||
- onlyoffice-api
|
||||
# - onlyoffice-api-system
|
||||
- onlyoffice-api-system
|
||||
- onlyoffice-studio
|
||||
- onlyoffice-ssoauth
|
||||
environment:
|
||||
|
@ -84,6 +84,14 @@ Requires: dotnet-sdk-6.0
|
||||
AutoReqProv: no
|
||||
%description api
|
||||
|
||||
%package api-system
|
||||
Summary: api-system
|
||||
Group: Applications/Internet
|
||||
Requires: %name-common = %version-%release
|
||||
Requires: dotnet-sdk-6.0
|
||||
AutoReqProv: no
|
||||
%description api-system
|
||||
|
||||
%package ssoauth
|
||||
Summary: ssoauth
|
||||
Group: Applications/Internet
|
||||
|
@ -34,7 +34,7 @@ public abstract class BaseStartup
|
||||
private const string BasicAuthScheme = "Basic";
|
||||
private const string MultiAuthSchemes = "MultiAuthSchemes";
|
||||
|
||||
private readonly IConfiguration _configuration;
|
||||
protected readonly IConfiguration _configuration;
|
||||
private readonly IHostEnvironment _hostEnvironment;
|
||||
private readonly string _corsOrigin;
|
||||
|
||||
|
@ -248,6 +248,7 @@ public class DbTenantService : ITenantService
|
||||
dbTenant.Industry = tenant.Industry;
|
||||
dbTenant.Spam = tenant.Spam;
|
||||
dbTenant.Calls = tenant.Calls;
|
||||
dbTenant.OwnerId = tenant.OwnerId;
|
||||
}
|
||||
|
||||
tenantDbContext.SaveChanges();
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
namespace ASC.Core.Notify.Socket;
|
||||
|
||||
[Singletone]
|
||||
[Scope]
|
||||
public class SocketServiceClient
|
||||
{
|
||||
private readonly TimeSpan _timeout = TimeSpan.FromSeconds(1);
|
||||
|
@ -15,6 +15,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\migrations\mysql\ASC.Migrations.MySql.csproj" />
|
||||
<ProjectReference Include="..\..\..\web\ASC.Web.Api\ASC.Web.Api.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
@ -46,16 +46,15 @@ class ApiApplication : WebApplicationFactory<Program>
|
||||
builder.UseSetting(s.Key, s.Value);
|
||||
}
|
||||
|
||||
builder.ConfigureAppConfiguration((context, a) =>
|
||||
{
|
||||
(a.Sources[0] as ChainedConfigurationSource).Configuration["pathToConf"] = a.Build()["pathToConf"];
|
||||
});
|
||||
|
||||
builder.ConfigureServices(services =>
|
||||
{
|
||||
services.AddBaseDbContext<UserDbContext>();
|
||||
services.AddBaseDbContext<TenantDbContext>();
|
||||
services.AddBaseDbContext<WebstudioDbContext>();
|
||||
|
||||
var DIHelper = new ASC.Common.DIHelper();
|
||||
DIHelper.Configure(services);
|
||||
foreach (var a in Assembly.Load("ASC.Files").GetTypes().Where(r => r.IsAssignableTo<ControllerBase>()))
|
||||
foreach (var a in Assembly.Load("ASC.Web.Api").GetTypes().Where(r => r.IsAssignableTo<ControllerBase>()))
|
||||
{
|
||||
DIHelper.TryAdd(a);
|
||||
}
|
||||
@ -73,19 +72,18 @@ public class MySetUpClass
|
||||
[OneTimeSetUp]
|
||||
public void CreateDb()
|
||||
{
|
||||
var host = new ApiApplication(new Dictionary<string, string>
|
||||
var args = new Dictionary<string, string>
|
||||
{
|
||||
{ "pathToConf", Path.Combine("..","..", "..", "config") },
|
||||
{ "ConnectionStrings:default:connectionString", BaseApiTests.TestConnection },
|
||||
{ "migration:enabled", "true" },
|
||||
{ "core:products:folder", Path.Combine("..","..", "..", "products") },
|
||||
{ "web:hub::internal", "" }
|
||||
})
|
||||
.WithWebHostBuilder(builder =>
|
||||
{
|
||||
});
|
||||
|
||||
Migrate(host.Services);
|
||||
{ "web:hub::internal", "" },
|
||||
{ "disableLdapNotifyService", "true" }
|
||||
};
|
||||
|
||||
var host = new ApiApplication(args);
|
||||
Migrate(host.Services, "ASC.Migrations.MySql");
|
||||
|
||||
host = new ApiApplication(args);
|
||||
Migrate(host.Services, Assembly.GetExecutingAssembly().GetName().Name);
|
||||
|
||||
_scope = host.Services.CreateScope();
|
||||
@ -99,18 +97,21 @@ public class MySetUpClass
|
||||
}
|
||||
|
||||
|
||||
private void Migrate(IServiceProvider serviceProvider, string testAssembly = null)
|
||||
private void Migrate(IServiceProvider serviceProvider, string testAssembly )
|
||||
{
|
||||
using var scope = serviceProvider.CreateScope();
|
||||
using var scope = serviceProvider.CreateScope();
|
||||
|
||||
var configuration = scope.ServiceProvider.GetService<IConfiguration>();
|
||||
configuration["testAssembly"] = testAssembly;
|
||||
|
||||
if (!string.IsNullOrEmpty(testAssembly))
|
||||
{
|
||||
var configuration = scope.ServiceProvider.GetService<IConfiguration>();
|
||||
configuration["testAssembly"] = testAssembly;
|
||||
}
|
||||
|
||||
using var db = scope.ServiceProvider.GetService<IDbContextFactory<UserDbContext>>().CreateDbContext();
|
||||
db.Database.Migrate();
|
||||
using var userDbContext = scope.ServiceProvider.GetService<UserDbContext>();
|
||||
userDbContext.Database.Migrate();
|
||||
|
||||
using var tenantDbContext = scope.ServiceProvider.GetService<TenantDbContext>();
|
||||
tenantDbContext.Database.Migrate();
|
||||
|
||||
using var webstudioDbContext = scope.ServiceProvider.GetService<WebstudioDbContext>();
|
||||
webstudioDbContext.Database.Migrate();
|
||||
}
|
||||
}
|
||||
|
||||
@ -131,10 +132,10 @@ class BaseApiTests
|
||||
{
|
||||
var host = new ApiApplication(new Dictionary<string, string>
|
||||
{
|
||||
{ "pathToConf", Path.Combine("..","..", "..", "config") },
|
||||
{ "ConnectionStrings:default:connectionString", TestConnection },
|
||||
{ "migration:enabled", "true" },
|
||||
{ "web:hub:internal", "" }
|
||||
{ "web:hub:internal", "" },
|
||||
{ "disableLdapNotifyService", "true" }
|
||||
})
|
||||
.WithWebHostBuilder(a => { });
|
||||
|
||||
|
@ -28,7 +28,7 @@ using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace ASC.Core.Common.Migrations;
|
||||
|
||||
public partial class TestMigration : Microsoft.EntityFrameworkCore.Migrations.Migration
|
||||
public partial class TestMigration : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
@ -41,8 +41,8 @@ public partial class TestMigration : Microsoft.EntityFrameworkCore.Migrations.Mi
|
||||
|
||||
migrationBuilder.InsertData(
|
||||
table: "core_user",
|
||||
columns: new[] { "id", "activation_status", "bithdate", "contacts", "culture", "email", "firstname", "last_modified", "lastname", "location", "notes", "phone", "phone_activation", "removed", "sex", "sid", "sso_name_id", "sso_session_id", "status", "tenant", "terminateddate", "title", "username", "workfromdate" },
|
||||
values: new object[] { "99223c7b-e3c9-11eb-9063-982cbc0ea1e5", 0, null, null, null, "test@gmail.com", "Test", new DateTime(2021, 8, 4, 11, 1, 4, 513, DateTimeKind.Utc).AddTicks(2928), "User", null, null, null, 0, false, null, null, null, null, 1, 1, null, null, "TestUser", new DateTime(2021, 8, 4, 11, 1, 4, 513, DateTimeKind.Utc).AddTicks(2940) });
|
||||
columns: new[] { "id", "activation_status", "bithdate", "contacts", "culture", "email", "firstname", "last_modified", "lastname", "location", "notes", "phone", "phone_activation", "removed", "sex", "sid", "sso_name_id", "sso_session_id", "status", "tenant", "terminateddate", "title", "username", "workfromdate", "create_on" },
|
||||
values: new object[] { "99223c7b-e3c9-11eb-9063-982cbc0ea1e5", 0, null, null, null, "test@gmail.com", "Test", new DateTime(2021, 8, 4, 11, 1, 4, 513, DateTimeKind.Utc).AddTicks(2928), "User", null, null, null, 0, false, null, null, null, null, 1, 1, null, null, "TestUser", new DateTime(2021, 8, 4, 11, 1, 4, 513, DateTimeKind.Utc).AddTicks(2940), DateTime.UtcNow });
|
||||
|
||||
migrationBuilder.InsertData(
|
||||
table: "core_usersecurity",
|
||||
@ -69,4 +69,4 @@ public partial class TestMigration : Microsoft.EntityFrameworkCore.Migrations.Mi
|
||||
columns: new[] { "last_modified", "workfromdate" },
|
||||
values: new object[] { new DateTime(2021, 8, 3, 21, 35, 0, 522, DateTimeKind.Utc).AddTicks(6893), new DateTime(2021, 8, 3, 21, 35, 0, 522, DateTimeKind.Utc).AddTicks(5587) });
|
||||
}
|
||||
}
|
||||
}
|
@ -82,7 +82,6 @@ class WizardTest : BaseApiTests
|
||||
PasswordHash = passwordHash,
|
||||
Lng = lng,
|
||||
TimeZone = timeZone,
|
||||
Promocode = promocode,
|
||||
AmiId = amiid,
|
||||
SubscribeFromSite = subscribeFromSite
|
||||
};
|
||||
|
@ -16,6 +16,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\migrations\mysql\ASC.Migrations.MySql.csproj" />
|
||||
<ProjectReference Include="..\..\ASC.Api.Core\ASC.Api.Core.csproj" />
|
||||
<ProjectReference Include="..\..\services\ASC.Webhooks.Service\ASC.Webhooks.Service.csproj" />
|
||||
</ItemGroup>
|
||||
|
@ -29,14 +29,18 @@ using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using ASC.Api.Core;
|
||||
using ASC.Api.Core.Extensions;
|
||||
using ASC.Common;
|
||||
using ASC.Common.Caching;
|
||||
using ASC.Common.Logging;
|
||||
using ASC.Common.Utils;
|
||||
using ASC.Core.Common.EF;
|
||||
using ASC.Core.Common.EF.Context;
|
||||
using ASC.Webhooks.Core;
|
||||
using ASC.Webhooks.Core.EF.Context;
|
||||
using ASC.Webhooks.Service;
|
||||
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
@ -47,108 +51,119 @@ using Microsoft.Extensions.Hosting;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace ASC.Webhooks.Tests
|
||||
namespace ASC.Webhooks.Tests;
|
||||
|
||||
public class BaseSetUp
|
||||
{
|
||||
public class BaseSetUp
|
||||
private IServiceProvider _serviceProvider;
|
||||
protected IHost _host;
|
||||
protected WebhookSender _webhookSender;
|
||||
protected RequestHistory _requestHistory;
|
||||
protected Settings _settings;
|
||||
protected IHttpClientFactory _httpClientFactory;
|
||||
protected string _testConnection = "Server=localhost;Database=onlyoffice_test;User ID=dev;Password=dev;Pooling=true;Character Set=utf8;AutoEnlist=false;SSL Mode=none;AllowPublicKeyRetrieval=True";
|
||||
protected static int _port = 8867;
|
||||
|
||||
[OneTimeSetUp]
|
||||
public async Task CreateDb()
|
||||
{
|
||||
private IServiceProvider serviceProvider;
|
||||
protected IHost host;
|
||||
protected WebhookSender webhookSender;
|
||||
protected RequestHistory requestHistory;
|
||||
protected Settings settings;
|
||||
protected IHttpClientFactory httpClientFactory;
|
||||
protected string TestConnection = "Server=localhost;Database=onlyoffice_test;User ID=dev;Password=dev;Pooling=true;Character Set=utf8;AutoEnlist=false;SSL Mode=none;AllowPublicKeyRetrieval=True";
|
||||
protected static int port = 8867;
|
||||
var args = new string[] {
|
||||
"--pathToConf", Path.Combine( "..", "..", "..", "..", "..", "..", "config"),
|
||||
"--ConnectionStrings:default:connectionString", _testConnection,
|
||||
"--migration:enabled", "true"};
|
||||
|
||||
[OneTimeSetUp]
|
||||
public async Task CreateDb()
|
||||
{
|
||||
var args = new string[] {
|
||||
"--pathToConf", Path.Combine( "..", "..", "..", "..", "..", "..", "config"),
|
||||
"--ConnectionStrings:default:connectionString", TestConnection,
|
||||
"--migration:enabled", "true"};
|
||||
await StartHost(args);
|
||||
|
||||
await StartHost(args);
|
||||
Migrate(_serviceProvider, "ASC.Migrations.MySql");
|
||||
Migrate(_serviceProvider, Assembly.GetExecutingAssembly().GetName().Name);
|
||||
}
|
||||
|
||||
Migrate(serviceProvider);
|
||||
Migrate(serviceProvider, Assembly.GetExecutingAssembly().GetName().Name);
|
||||
}
|
||||
[OneTimeTearDown]
|
||||
public async Task DropDb()
|
||||
{
|
||||
var scope = _serviceProvider.CreateScope();
|
||||
var context = scope.ServiceProvider.GetService<IDbContextFactory<WebhooksDbContext>>().CreateDbContext();
|
||||
context.Database.EnsureDeleted();
|
||||
await _host.StopAsync();
|
||||
}
|
||||
|
||||
[OneTimeTearDown]
|
||||
public async Task DropDb()
|
||||
{
|
||||
var scope = serviceProvider.CreateScope();
|
||||
var context = scope.ServiceProvider.GetService<IDbContextFactory<WebhooksDbContext>>().CreateDbContext();
|
||||
context.Database.EnsureDeleted();
|
||||
await host.StopAsync();
|
||||
}
|
||||
|
||||
private async Task StartHost(string[] args)
|
||||
{
|
||||
host = await Host.CreateDefaultBuilder(args)
|
||||
.ConfigureWebHostDefaults(webBuilder =>
|
||||
private async Task StartHost(string[] args)
|
||||
{
|
||||
IConfiguration configuration = null;
|
||||
_host = await Host.CreateDefaultBuilder(args)
|
||||
.ConfigureWebHostDefaults(webBuilder =>
|
||||
{
|
||||
webBuilder
|
||||
.UseKestrel(options =>
|
||||
{
|
||||
webBuilder
|
||||
.UseKestrel(options =>
|
||||
{
|
||||
options.Listen(IPAddress.Loopback, port);
|
||||
})
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.AddControllers();
|
||||
services.AddMemoryCache();
|
||||
services.AddHttpClient();
|
||||
|
||||
var dIHelper = new DIHelper();
|
||||
dIHelper.Configure(services);
|
||||
dIHelper.TryAdd<DbWorker>();
|
||||
dIHelper.TryAdd<TestController>();
|
||||
dIHelper.TryAdd<WebhookSender>();
|
||||
dIHelper.TryAdd(typeof(ICacheNotify<>), typeof(KafkaCacheNotify<>));
|
||||
})
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseRouting();
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapControllers();
|
||||
});
|
||||
});
|
||||
})
|
||||
options.Listen(IPAddress.Loopback, _port);
|
||||
})
|
||||
.ConfigureAppConfiguration((hostingContext, config) =>
|
||||
{
|
||||
var buided = config.Build();
|
||||
var path = buided["pathToConf"];
|
||||
configuration = config.Build();
|
||||
var path = configuration["pathToConf"];
|
||||
if (!Path.IsPathRooted(path))
|
||||
{
|
||||
path = Path.GetFullPath(CrossPlatform.PathCombine(hostingContext.HostingEnvironment.ContentRootPath, path));
|
||||
}
|
||||
|
||||
config.SetBasePath(path);
|
||||
config
|
||||
.AddJsonFile("appsettings.json")
|
||||
.AddCommandLine(args);
|
||||
})
|
||||
.StartAsync();
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.AddControllers();
|
||||
services.AddMemoryCache();
|
||||
services.AddHttpClient();
|
||||
|
||||
services.AddScoped<EFLoggerFactory>();
|
||||
services.AddBaseDbContextPool<WebhooksDbContext>();
|
||||
services.AddBaseDbContextPool<TenantDbContext>();
|
||||
services.AddBaseDbContextPool<UserDbContext>();
|
||||
services.AddBaseDbContextPool<CoreDbContext>();
|
||||
|
||||
services.AddDistributedCache(configuration);
|
||||
services.AddDistributedTaskQueue();
|
||||
services.AddCacheNotify(configuration);
|
||||
services.AddAutoMapper(BaseStartup.GetAutoMapperProfileAssemblies());
|
||||
|
||||
serviceProvider = host.Services;
|
||||
webhookSender = serviceProvider.GetService<WebhookSender>();
|
||||
requestHistory = serviceProvider.GetService<RequestHistory>();
|
||||
settings = serviceProvider.GetService<Settings>();
|
||||
httpClientFactory = serviceProvider.GetService<IHttpClientFactory>();
|
||||
}
|
||||
|
||||
private void Migrate(IServiceProvider serviceProvider, string testAssembly = null)
|
||||
var dIHelper = new DIHelper();
|
||||
dIHelper.Configure(services);
|
||||
dIHelper.TryAdd<DbWorker>();
|
||||
dIHelper.TryAdd<TestController>();
|
||||
dIHelper.TryAdd<WebhookSender>();
|
||||
dIHelper.TryAdd(typeof(ICacheNotify<>), typeof(KafkaCacheNotify<>));
|
||||
})
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseRouting();
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapControllers();
|
||||
});
|
||||
});
|
||||
})
|
||||
.StartAsync();
|
||||
|
||||
_serviceProvider = _host.Services;
|
||||
_webhookSender = _serviceProvider.GetService<WebhookSender>();
|
||||
_requestHistory = _serviceProvider.GetService<RequestHistory>();
|
||||
_settings = _serviceProvider.GetService<Settings>();
|
||||
_httpClientFactory = _serviceProvider.GetService<IHttpClientFactory>();
|
||||
}
|
||||
|
||||
private void Migrate(IServiceProvider serviceProvider, string testAssembly = null)
|
||||
{
|
||||
|
||||
if (!string.IsNullOrEmpty(testAssembly))
|
||||
{
|
||||
|
||||
if (!string.IsNullOrEmpty(testAssembly))
|
||||
{
|
||||
var configuration = serviceProvider.GetService<IConfiguration>();
|
||||
configuration["testAssembly"] = testAssembly;
|
||||
}
|
||||
|
||||
using var db = serviceProvider.GetService<IDbContextFactory<WebhooksDbContext>>().CreateDbContext();
|
||||
db.Database.Migrate();
|
||||
var configuration = serviceProvider.GetService<IConfiguration>();
|
||||
configuration["testAssembly"] = testAssembly;
|
||||
}
|
||||
|
||||
using var db = serviceProvider.GetService<IDbContextFactory<WebhooksDbContext>>().CreateDbContext();
|
||||
db.Database.Migrate();
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@ -59,120 +60,93 @@ namespace ASC.Webhooks.Tests
|
||||
[TestFixture]
|
||||
public class CommonWebhooksTests : BaseSetUp
|
||||
{
|
||||
private readonly string EventName = "testEvent";
|
||||
private readonly string secretKey = "testSecretKey";
|
||||
private readonly string content = JsonSerializer.Serialize("testContent");
|
||||
private readonly string headers = JsonSerializer.Serialize(new { Host = new StringValues("localhost") });
|
||||
private readonly string URI = $"http://localhost:{port}/api/2.0/Test/";
|
||||
private readonly DateTime creationTime = DateTime.Now;
|
||||
private readonly CacheNotifyAction testCacheNotifyAction = CacheNotifyAction.Update;
|
||||
private readonly string _eventName = "testEvent";
|
||||
private readonly string _secretKey = "testSecretKey";
|
||||
private readonly string _content = "testContent";
|
||||
private readonly string _contentSerialize = JsonSerializer.Serialize("testContent");
|
||||
private readonly string _uri = $"http://localhost:{_port}/api/2.0/Test/";
|
||||
private readonly DateTime _creationTime = DateTime.Now;
|
||||
private readonly CacheNotifyAction _testCacheNotifyAction = CacheNotifyAction.Update;
|
||||
|
||||
[Order(1)]
|
||||
[Test]
|
||||
public void Publisher()
|
||||
public async Task Publisher()
|
||||
{
|
||||
var scope = host.Services.CreateScope();
|
||||
var scope = _host.Services.CreateScope();
|
||||
var dbWorker = scope.ServiceProvider.GetService<DbWorker>();
|
||||
var tenantManager = scope.ServiceProvider.GetService<TenantManager>();
|
||||
|
||||
var id = 1;
|
||||
var testWebhookRequest = new WebhookRequest { Id = id };
|
||||
var testTenant = new Tenant(1, "testWebhooksPublisher");
|
||||
var testWebhookConfig = new WebhooksConfig()
|
||||
{
|
||||
SecretKey = secretKey,
|
||||
TenantId = testTenant.Id,
|
||||
Uri = URI
|
||||
};
|
||||
var testWebhooksEntry = new WebhookEntry()
|
||||
{
|
||||
Id = id,
|
||||
Payload = content,
|
||||
SecretKey = secretKey,
|
||||
Uri = URI
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
tenantManager.SetCurrentTenant(testTenant);
|
||||
|
||||
dbWorker.AddWebhookConfig(testWebhookConfig);
|
||||
await dbWorker.AddWebhookConfig(_eventName, _uri, _secretKey);
|
||||
|
||||
var mockedKafkaCaches = new Mock<ICacheNotify<WebhookRequest>>();
|
||||
mockedKafkaCaches.Setup(a => a.Publish(testWebhookRequest, testCacheNotifyAction)).Verifiable();
|
||||
mockedKafkaCaches.Setup(a => a.Publish(testWebhookRequest, _testCacheNotifyAction)).Verifiable();
|
||||
|
||||
var publisher = new WebhookPublisher(dbWorker, tenantManager, mockedKafkaCaches.Object);
|
||||
publisher.Publish(EventName, content);
|
||||
var publisher = new WebhookPublisher(dbWorker, mockedKafkaCaches.Object);
|
||||
await publisher.PublishAsync(_eventName, "", _contentSerialize);
|
||||
|
||||
mockedKafkaCaches.Verify(a => a.Publish(testWebhookRequest, testCacheNotifyAction), Times.Once);
|
||||
mockedKafkaCaches.Verify(a => a.Publish(testWebhookRequest, _testCacheNotifyAction), Times.Once);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Assert.Fail(ex.ToString());
|
||||
}
|
||||
Assert.AreEqual(dbWorker.ReadFromJournal(id), testWebhooksEntry);
|
||||
Assert.AreEqual((await dbWorker.ReadJournal(id)).RequestPayload, _contentSerialize);
|
||||
}
|
||||
|
||||
|
||||
[Order(2)]
|
||||
[Test]
|
||||
public async Task Sender()
|
||||
{
|
||||
var scope = host.Services.CreateScope();
|
||||
var scope = _host.Services.CreateScope();
|
||||
var serviceProvider = scope.ServiceProvider;
|
||||
var dbWorker = serviceProvider.GetService<DbWorker>();
|
||||
var tenantManager = serviceProvider.GetService<TenantManager>();
|
||||
|
||||
var successedId = dbWorker.ConfigsNumber() + 1;
|
||||
var failedId = successedId + 1;
|
||||
var testTenant = new Tenant(2, "testWebhooksSender");
|
||||
|
||||
tenantManager.SetCurrentTenant(testTenant);
|
||||
|
||||
|
||||
var successWebhookConfig = new WebhooksConfig { ConfigId = successedId, SecretKey = secretKey, Uri = $"{URI}SuccessRequest/" };
|
||||
var failedWebhookConfig = new WebhooksConfig { ConfigId = failedId, SecretKey = secretKey, Uri = $"{URI}FailedRequest/" };
|
||||
dbWorker.AddWebhookConfig(successWebhookConfig);
|
||||
dbWorker.AddWebhookConfig(failedWebhookConfig);
|
||||
var successedId = (await dbWorker.AddWebhookConfig(_eventName, $"{_uri}SuccessRequest/", _secretKey)).Id;
|
||||
var failedId = (await dbWorker.AddWebhookConfig(_eventName, $"{_uri}FailedRequest/", _secretKey)).Id;
|
||||
|
||||
var successWebhookPayload = new WebhooksLog { ConfigId = successedId, Status = ProcessStatus.InProcess, CreationTime = creationTime, RequestPayload = content };
|
||||
var failedWebhookPayload = new WebhooksLog { ConfigId = failedId, Status = ProcessStatus.InProcess, CreationTime = creationTime, RequestPayload = content };
|
||||
var successWebhookPayloadId = dbWorker.WriteToJournal(successWebhookPayload);
|
||||
var failedWebhookPayloadId = dbWorker.WriteToJournal(failedWebhookPayload);
|
||||
|
||||
var mockedLog = new Mock<ILoggerProvider>();
|
||||
//mockedLog.Setup(a => a.Error(It.IsAny<string>())).Verifiable();
|
||||
|
||||
//var mockedLogOptions = new Mock<IOptionsMonitor<ILog>>();
|
||||
//mockedLogOptions.Setup(a => a.Get("ASC.Webhooks.Core")).Returns(mockedLog.Object).Verifiable();
|
||||
var successWebhookPayload = new WebhooksLog { ConfigId = successedId, Status = 200, CreationTime = _creationTime, RequestPayload = _contentSerialize };
|
||||
var failedWebhookPayload = new WebhooksLog { ConfigId = failedId, Status = 400, CreationTime = _creationTime, RequestPayload = _contentSerialize };
|
||||
var successWebhookPayloadId = (await dbWorker.WriteToJournal(successWebhookPayload)).Id;
|
||||
var failedWebhookPayloadId = (await dbWorker.WriteToJournal(failedWebhookPayload)).Id;
|
||||
|
||||
var source = new CancellationTokenSource();
|
||||
var token = source.Token;
|
||||
|
||||
var SuccessedWebhookRequest = new WebhookRequest { Id = successWebhookPayloadId };
|
||||
var FailedWebhookRequest = new WebhookRequest { Id = failedWebhookPayloadId };
|
||||
var FailedWebhookRequest = new WebhookRequest { Id = failedWebhookPayloadId };
|
||||
|
||||
var sender = new WebhookSender(mockedLog.Object, serviceProvider.GetRequiredService<IServiceScopeFactory>(), settings, httpClientFactory);
|
||||
var sender = new WebhookSender(serviceProvider.GetService<ILoggerProvider>(), serviceProvider.GetRequiredService<IServiceScopeFactory>(), _httpClientFactory);
|
||||
await sender.Send(SuccessedWebhookRequest, token);
|
||||
await sender.Send(FailedWebhookRequest, token);
|
||||
|
||||
var asd = requestHistory.SuccessCounter;
|
||||
|
||||
Assert.IsTrue(requestHistory.SuccessCounter == 1, "Problem with successed request");
|
||||
Assert.IsTrue(requestHistory.FailedCounter == webhookSender.RepeatCount, "Problem with failed request");
|
||||
Assert.IsTrue(requestHistory.СorrectSignature, "Problem with signature");
|
||||
Assert.IsTrue(_requestHistory.SuccessCounter == 1, "Problem with successed request");
|
||||
Assert.IsTrue(_requestHistory.FailedCounter == 1, "Problem with failed request");
|
||||
Assert.IsTrue(_requestHistory.СorrectSignature, "Problem with signature");
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public async Task GlobalFilter()
|
||||
{
|
||||
try
|
||||
{
|
||||
var controllerAddress = "api/2.0/Test/testMethod";
|
||||
var getEventName = $"method: GET, route: {controllerAddress}";
|
||||
var postEventName = $"method: POST, route: {controllerAddress}";
|
||||
|
||||
var mockedWebhookPubslisher = new Mock<IWebhookPublisher>();
|
||||
mockedWebhookPubslisher.Setup(a => a.Publish(getEventName, content)).Verifiable();
|
||||
mockedWebhookPubslisher.Setup(a => a.Publish(postEventName, content)).Verifiable();
|
||||
mockedWebhookPubslisher.Setup(a => a.PublishAsync("GET", controllerAddress, _content)).Verifiable();
|
||||
mockedWebhookPubslisher.Setup(a => a.PublishAsync("POST", controllerAddress, _content)).Verifiable();
|
||||
|
||||
|
||||
using var host = await new HostBuilder()
|
||||
@ -185,7 +159,7 @@ namespace ASC.Webhooks.Tests
|
||||
services.AddSingleton(mockedWebhookPubslisher.Object);
|
||||
services.AddControllers();
|
||||
|
||||
services.AddSingleton(new Action<JsonOptions>(opt => opt.JsonSerializerOptions.IgnoreNullValues = false));
|
||||
services.AddSingleton(new Action<JsonOptions>(opt => opt.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.Never));
|
||||
|
||||
var dIHelper = new DIHelper();
|
||||
dIHelper.Configure(services);
|
||||
@ -211,12 +185,12 @@ namespace ASC.Webhooks.Tests
|
||||
.StartAsync();
|
||||
|
||||
var getResponse = await host.GetTestClient().GetAsync(controllerAddress);
|
||||
mockedWebhookPubslisher.Verify(a => a.Publish(getEventName, content), Times.Never);
|
||||
mockedWebhookPubslisher.Verify(a => a.PublishAsync("GET", controllerAddress, _content), Times.Never);
|
||||
|
||||
StringContent stringContent = new StringContent(content);
|
||||
var stringContent = new StringContent(_content);
|
||||
|
||||
var postResponse = await host.GetTestClient().PostAsync(controllerAddress, stringContent);
|
||||
mockedWebhookPubslisher.Verify(a => a.Publish(postEventName, content), Times.Once);
|
||||
mockedWebhookPubslisher.Verify(a => a.PublishAsync("POST", controllerAddress, _content), Times.Once);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -31,16 +31,12 @@ public class FeedAggregatorService : FeedBaseService
|
||||
{
|
||||
protected override string LoggerName { get; set; } = "ASC.Feed.Aggregator";
|
||||
|
||||
private readonly SocketServiceClient _socketServiceClient;
|
||||
|
||||
public FeedAggregatorService(
|
||||
FeedSettings feedSettings,
|
||||
IServiceScopeFactory serviceScopeFactory,
|
||||
ILoggerProvider optionsMonitor,
|
||||
SocketServiceClient socketServiceClient)
|
||||
ILoggerProvider optionsMonitor)
|
||||
: base(feedSettings, serviceScopeFactory, optionsMonitor)
|
||||
{
|
||||
_socketServiceClient = socketServiceClient;
|
||||
}
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
@ -112,6 +108,7 @@ public class FeedAggregatorService : FeedBaseService
|
||||
var userManager = scope.ServiceProvider.GetService<UserManager>();
|
||||
var authManager = scope.ServiceProvider.GetService<AuthManager>();
|
||||
var securityContext = scope.ServiceProvider.GetService<SecurityContext>();
|
||||
var socketServiceClient = scope.ServiceProvider.GetRequiredService<SocketServiceClient>();
|
||||
|
||||
foreach (var module in modules)
|
||||
{
|
||||
@ -200,7 +197,7 @@ public class FeedAggregatorService : FeedBaseService
|
||||
}
|
||||
}
|
||||
|
||||
await _socketServiceClient.MakeRequest("sendUnreadUsers", unreadUsers);
|
||||
await socketServiceClient.MakeRequest("sendUnreadUsers", unreadUsers);
|
||||
|
||||
_logger.DebugTimeCollectingNews(DateTime.UtcNow - start);
|
||||
}
|
||||
|
49
config/apisystem.dev.json
Normal file
49
config/apisystem.dev.json
Normal file
@ -0,0 +1,49 @@
|
||||
{
|
||||
"core": {
|
||||
"base-domain": "localhost",
|
||||
"machinekey": "your_core_machinekey",
|
||||
"notify": {
|
||||
"postman": "log"
|
||||
},
|
||||
"payment-partners": "",
|
||||
"username": {
|
||||
"regex": "^[\\p{L}\\p{M}' \\-]+$"
|
||||
}
|
||||
},
|
||||
"web": {
|
||||
"alias": {
|
||||
"min": 3
|
||||
},
|
||||
"api-cache": "",
|
||||
"autotest": {
|
||||
"secret-email": ""
|
||||
},
|
||||
"app": {
|
||||
"keys": ""
|
||||
}
|
||||
},
|
||||
"recaptcha": {
|
||||
"required": false,
|
||||
"private-key": {
|
||||
"default": "",
|
||||
"android": "",
|
||||
"ios": ""
|
||||
}
|
||||
},
|
||||
"auth": {
|
||||
"allowskip": {
|
||||
"default": false,
|
||||
"registerportal": true
|
||||
}
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"default": {
|
||||
"name": "default",
|
||||
"connectionString": "Server=onlyoffice-mysql-server;Port=3306;Database=onlyoffice;User ID=onlyoffice_user;Password=onlyoffice_pass;Pooling=true;Character Set=utf8;AutoEnlist=false;SSL Mode=none;ConnectionReset=false",
|
||||
"providerName": "MySql.Data.MySqlClient"
|
||||
}
|
||||
},
|
||||
"quota": {
|
||||
"id": -3
|
||||
}
|
||||
}
|
@ -249,15 +249,18 @@ server {
|
||||
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
|
||||
}
|
||||
|
||||
location /products {
|
||||
location ~* /files {
|
||||
location ~* (/httphandlers/filehandler.ashx|ChunkedUploader.ashx) {
|
||||
proxy_pass http://127.0.0.1:5007;
|
||||
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
|
||||
}
|
||||
}
|
||||
|
||||
location /filehandler.ashx {
|
||||
proxy_pass http://127.0.0.1:5007;
|
||||
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
|
||||
}
|
||||
|
||||
|
||||
location /ChunkedUploader.ashx {
|
||||
proxy_pass http://127.0.0.1:5007;
|
||||
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
|
||||
}
|
||||
|
||||
location /Products {
|
||||
location ~* /Files {
|
||||
rewrite ^/Products/Files(.*)$ $1 redirect;
|
||||
|
@ -10,6 +10,7 @@
|
||||
"InviteUsersToRoom": "Invite users to room",
|
||||
"Invited": "Invited",
|
||||
"LinkCopySuccess": "Link has been copied",
|
||||
"SearchPlaceholder": "Invite people by name or email",
|
||||
"InviteRoomSearchPlaceholder": "Invite people by name or email",
|
||||
"InviteAccountSearchPlaceholder": "Invite people by email",
|
||||
"SendInvitation": "Send invitation"
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ import { inject, observer } from "mobx-react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { CreateRoomDialog } from "../dialogs";
|
||||
import { toastr } from "@docspace/components";
|
||||
import { isMobile } from "react-device-detect";
|
||||
|
||||
const CreateRoomEvent = ({
|
||||
visible,
|
||||
@ -38,7 +39,7 @@ const CreateRoomEvent = ({
|
||||
setView("info_members");
|
||||
fetchFiles(id)
|
||||
.then(() => {
|
||||
setInfoPanelIsVisible(true);
|
||||
!isMobile && setInfoPanelIsVisible(true);
|
||||
})
|
||||
.finally(() => {
|
||||
setIsLoading(false);
|
||||
|
@ -35,9 +35,9 @@ const DeleteDialogComponent = (props) => {
|
||||
const item = props.selection[i];
|
||||
|
||||
if (!item?.isEditing) {
|
||||
if (item?.access === 0 || item?.access === 1 || unsubscribe) {
|
||||
selection.push(item);
|
||||
}
|
||||
// if (item?.access === 0 || item?.access === 1 || unsubscribe) {
|
||||
selection.push(item);
|
||||
// }
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ const StyledSubHeader = styled(Heading)`
|
||||
font-size: 16px;
|
||||
padding-left: 16px;
|
||||
padding-right: 16px;
|
||||
margin: 20px 0;
|
||||
margin: 16px 0;
|
||||
|
||||
${(props) =>
|
||||
props.inline &&
|
||||
|
@ -97,12 +97,15 @@ const InviteInput = ({
|
||||
const value = e.target.value;
|
||||
const clearValue = value.trim();
|
||||
|
||||
if ((!!usersList.length || clearValue.length > 1) && !searchPanelVisible) {
|
||||
if ((!!usersList.length || clearValue.length > 2) && !searchPanelVisible) {
|
||||
openInviteInputPanel();
|
||||
}
|
||||
|
||||
setInputValue(value);
|
||||
debouncedSearch(clearValue);
|
||||
|
||||
if (roomId !== -1) {
|
||||
debouncedSearch(clearValue);
|
||||
}
|
||||
};
|
||||
|
||||
const removeExist = (items) => {
|
||||
@ -238,33 +241,39 @@ const InviteInput = ({
|
||||
<TextInput
|
||||
scale
|
||||
onChange={onChange}
|
||||
placeholder={t("SearchPlaceholder")}
|
||||
placeholder={
|
||||
roomId === -1
|
||||
? t("InviteAccountSearchPlaceholder")
|
||||
: t("InviteRoomSearchPlaceholder")
|
||||
}
|
||||
value={inputValue}
|
||||
onFocus={openInviteInputPanel}
|
||||
/>
|
||||
</StyledInviteInput>
|
||||
<StyledDropDown
|
||||
width={searchRef?.current?.offsetWidth}
|
||||
isDefaultMode={false}
|
||||
open={searchPanelVisible}
|
||||
manualX="16px"
|
||||
showDisabledItems
|
||||
clickOutsideAction={closeInviteInputPanel}
|
||||
{...dropDownMaxHeight}
|
||||
>
|
||||
{!!usersList.length
|
||||
? foundUsers
|
||||
: inputValue.length > 2 && (
|
||||
<DropDownItem
|
||||
style={{ width: "inherit" }}
|
||||
textOverflow
|
||||
onClick={addEmail}
|
||||
height={48}
|
||||
>
|
||||
{t("Add")} «{inputValue}»
|
||||
</DropDownItem>
|
||||
)}
|
||||
</StyledDropDown>
|
||||
{inputValue.length > 2 && (
|
||||
<StyledDropDown
|
||||
width={searchRef?.current?.offsetWidth}
|
||||
isDefaultMode={false}
|
||||
open={searchPanelVisible}
|
||||
manualX="16px"
|
||||
showDisabledItems
|
||||
clickOutsideAction={closeInviteInputPanel}
|
||||
{...dropDownMaxHeight}
|
||||
>
|
||||
{!!usersList.length ? (
|
||||
foundUsers
|
||||
) : (
|
||||
<DropDownItem
|
||||
style={{ width: "inherit" }}
|
||||
textOverflow
|
||||
onClick={addEmail}
|
||||
height={48}
|
||||
>
|
||||
{t("Add")} «{inputValue}»
|
||||
</DropDownItem>
|
||||
)}
|
||||
</StyledDropDown>
|
||||
)}
|
||||
|
||||
<AccessSelector
|
||||
t={t}
|
||||
|
@ -21,7 +21,6 @@ class PeopleTableHeader extends React.Component {
|
||||
enable: true,
|
||||
default: true,
|
||||
sortBy: "AZ",
|
||||
active: true,
|
||||
minWidth: 210,
|
||||
onClick: this.onFilter,
|
||||
onIconClick: this.onIconClick,
|
||||
@ -30,8 +29,10 @@ class PeopleTableHeader extends React.Component {
|
||||
key: "Type",
|
||||
title: t("Common:Type"),
|
||||
enable: true,
|
||||
sortBy: "type",
|
||||
resizable: true,
|
||||
onChange: this.onColumnChange,
|
||||
onClick: this.onFilter,
|
||||
},
|
||||
// {
|
||||
// key: "Room",
|
||||
@ -45,7 +46,9 @@ class PeopleTableHeader extends React.Component {
|
||||
title: t("Common:Email"),
|
||||
enable: true,
|
||||
resizable: true,
|
||||
sortBy: "email",
|
||||
onChange: this.onColumnChange,
|
||||
onClick: this.onFilter,
|
||||
},
|
||||
];
|
||||
|
||||
@ -88,32 +91,43 @@ class PeopleTableHeader extends React.Component {
|
||||
localStorage.setItem(`${TABLE_COLUMNS}=${this.props.userId}`, tableColumns);
|
||||
};
|
||||
|
||||
onFilter = () => {
|
||||
onFilter = (sortBy) => {
|
||||
const { filter, setIsLoading, fetchPeople } = this.props;
|
||||
const newFilter = filter.clone();
|
||||
|
||||
if (newFilter.sortBy === "lastname") {
|
||||
newFilter.sortBy = "firstname";
|
||||
if (newFilter.sortBy === sortBy && sortBy !== "AZ") {
|
||||
newFilter.sortOrder =
|
||||
newFilter.sortOrder === "ascending" ? "descending" : "ascending";
|
||||
} else {
|
||||
newFilter.sortBy = "lastname";
|
||||
newFilter.sortBy = sortBy;
|
||||
|
||||
if (sortBy === "AZ") {
|
||||
if (
|
||||
newFilter.sortBy !== "lastname" &&
|
||||
newFilter.sortBy !== "firstname"
|
||||
) {
|
||||
newFilter.sortBy = "firstname";
|
||||
} else if (newFilter.sortBy === "lastname") {
|
||||
newFilter.sortBy = "firstname";
|
||||
} else {
|
||||
newFilter.sortBy = "lastname";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setIsLoading(true);
|
||||
fetchPeople(newFilter).finally(() => setIsLoading(false));
|
||||
fetchPeople(newFilter, true).finally(() => setIsLoading(false));
|
||||
};
|
||||
|
||||
onIconClick = () => {
|
||||
const { filter, setIsLoading, fetchPeople } = this.props;
|
||||
const newFilter = filter.clone();
|
||||
|
||||
if (newFilter.sortOrder === "ascending") {
|
||||
newFilter.sortOrder = "descending";
|
||||
} else {
|
||||
newFilter.sortOrder = "ascending";
|
||||
}
|
||||
newFilter.sortOrder =
|
||||
newFilter.sortOrder === "ascending" ? "descending" : "ascending";
|
||||
|
||||
setIsLoading(true);
|
||||
fetchPeople(newFilter).finally(() => setIsLoading(false));
|
||||
fetchPeople(newFilter, true).finally(() => setIsLoading(false));
|
||||
};
|
||||
|
||||
render() {
|
||||
@ -129,10 +143,16 @@ class PeopleTableHeader extends React.Component {
|
||||
} = this.props;
|
||||
const { sortOrder } = filter;
|
||||
|
||||
const sortBy =
|
||||
filter.sortBy === "firstname" || filter.sortBy === "lastname"
|
||||
? "AZ"
|
||||
: filter.sortBy;
|
||||
|
||||
return (
|
||||
<TableHeader
|
||||
checkboxSize="48px"
|
||||
sorted={sortOrder === "descending"}
|
||||
sortBy={sortBy}
|
||||
containerRef={containerRef}
|
||||
columns={columns}
|
||||
columnStorageName={columnStorageName}
|
||||
|
@ -258,6 +258,12 @@ const SectionFilterContent = ({
|
||||
label: t("Common:Type"),
|
||||
default: true,
|
||||
},
|
||||
{
|
||||
id: "sory-by_email",
|
||||
key: "email",
|
||||
label: t("Common:Email"),
|
||||
default: true,
|
||||
},
|
||||
];
|
||||
}, [t]);
|
||||
|
||||
|
@ -2,15 +2,26 @@ import React, { useEffect } from "react";
|
||||
import { withRouter } from "react-router";
|
||||
import Loader from "@docspace/components/loader";
|
||||
import Section from "@docspace/common/components/Section";
|
||||
import { combineUrl } from "@docspace/common/utils";
|
||||
import tryRedirectTo from "@docspace/common/utils/tryRedirectTo";
|
||||
import { AppServerConfig } from "@docspace/common/constants";
|
||||
import { loginWithConfirmKey } from "@docspace/common/api/user";
|
||||
import toastr from "@docspace/components/toast/toastr";
|
||||
|
||||
const Auth = (props) => {
|
||||
console.log("Auth render");
|
||||
const { linkData } = props;
|
||||
|
||||
useEffect(() => {
|
||||
tryRedirectTo(combineUrl(AppServerConfig.proxyURL, `/login`));
|
||||
loginWithConfirmKey({
|
||||
ConfirmData: {
|
||||
Email: linkData.email,
|
||||
Key: linkData.confirmHeader,
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
console.log("Login with confirm key success", res);
|
||||
if (typeof res === "string") window.location.replace(res);
|
||||
else window.location.replace("/");
|
||||
})
|
||||
.catch((error) => toastr.error(error));
|
||||
});
|
||||
|
||||
return <Loader className="pageLoader" type="rombs" size="40px" />;
|
||||
|
@ -84,6 +84,23 @@ const StyledUser = styled.div`
|
||||
props.theme.infoPanel.members.disabledRoleSelectorColor};
|
||||
}
|
||||
}
|
||||
|
||||
.role-view_remove-icon {
|
||||
cursor: pointer;
|
||||
svg {
|
||||
path {
|
||||
fill: ${(props) => props.theme.iconButton.color};
|
||||
}
|
||||
}
|
||||
|
||||
:hover {
|
||||
svg {
|
||||
path {
|
||||
fill: ${(props) => props.theme.iconButton.hoverColor};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
StyledUserTypeHeader.defaultProps = { theme: Base };
|
||||
|
@ -4,6 +4,8 @@ import { StyledUser } from "../../styles/members";
|
||||
import Avatar from "@docspace/components/avatar";
|
||||
import { ComboBox } from "@docspace/components";
|
||||
|
||||
import { ReactSVG } from "react-svg";
|
||||
import { FolderType } from "@docspace/common/constants";
|
||||
const User = ({
|
||||
t,
|
||||
user,
|
||||
@ -84,6 +86,29 @@ const User = ({
|
||||
}
|
||||
};
|
||||
|
||||
const isArchiveRoot = rootFolderType === FolderType.Archive;
|
||||
|
||||
const changingMemberInfo = isArchiveRoot ? (
|
||||
<ReactSVG
|
||||
className="role-view_remove-icon"
|
||||
src="images/remove.session.svg"
|
||||
onClick={() => onOptionClick({ key: "remove" })}
|
||||
/>
|
||||
) : (
|
||||
<ComboBox
|
||||
className="role-combobox"
|
||||
selectedOption={userRole}
|
||||
options={userRoleOptions}
|
||||
onSelect={onOptionClick}
|
||||
scaled={false}
|
||||
withBackdrop={false}
|
||||
size="content"
|
||||
modernView
|
||||
title={t("Common:Role")}
|
||||
manualWidth={"fit-content"}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<StyledUser isExpect={isExpect} key={user.id}>
|
||||
<Avatar
|
||||
@ -104,18 +129,7 @@ const User = ({
|
||||
{userRole && userRoleOptions && (
|
||||
<div className="role-wrapper">
|
||||
{canChangeUserRole || canDeleteUser ? (
|
||||
<ComboBox
|
||||
className="role-combobox"
|
||||
selectedOption={userRole}
|
||||
options={userRoleOptions}
|
||||
onSelect={onOptionClick}
|
||||
scaled={false}
|
||||
withBackdrop={false}
|
||||
size="content"
|
||||
modernView
|
||||
title={t("Common:Role")}
|
||||
manualWidth={"fit-content"}
|
||||
/>
|
||||
changingMemberInfo
|
||||
) : (
|
||||
<div className="disabled-role-combobox" title={t("Common:Role")}>
|
||||
{userRole.label}
|
||||
|
@ -85,6 +85,11 @@ const InterfaceTheme = (props) => {
|
||||
};
|
||||
|
||||
const isSystemTheme = currentTheme === ThemeKeys.SystemStr;
|
||||
const systemThemeValue =
|
||||
window.matchMedia &&
|
||||
window.matchMedia("(prefers-color-scheme: dark)").matches
|
||||
? ThemeKeys.DarkStr
|
||||
: ThemeKeys.BaseStr;
|
||||
|
||||
return (
|
||||
<StyledWrapper>
|
||||
@ -111,7 +116,10 @@ const InterfaceTheme = (props) => {
|
||||
accentColor={currentColorScheme.main.accent}
|
||||
themeId={selectedThemeId}
|
||||
value={ThemeKeys.BaseStr}
|
||||
isChecked={currentTheme === ThemeKeys.BaseStr}
|
||||
isChecked={
|
||||
currentTheme === ThemeKeys.BaseStr ||
|
||||
(isSystemTheme && systemThemeValue === ThemeKeys.BaseStr)
|
||||
}
|
||||
onChangeTheme={onChangeTheme}
|
||||
/>
|
||||
<ThemePreview
|
||||
@ -121,7 +129,10 @@ const InterfaceTheme = (props) => {
|
||||
accentColor={currentColorScheme.main.accent}
|
||||
themeId={selectedThemeId}
|
||||
value={ThemeKeys.DarkStr}
|
||||
isChecked={currentTheme === ThemeKeys.DarkStr}
|
||||
isChecked={
|
||||
currentTheme === ThemeKeys.DarkStr ||
|
||||
(isSystemTheme && systemThemeValue === ThemeKeys.DarkStr)
|
||||
}
|
||||
onChangeTheme={onChangeTheme}
|
||||
/>
|
||||
</div>
|
||||
|
@ -89,13 +89,11 @@ const LanguagesCombo = (props) => {
|
||||
/>
|
||||
</Text>
|
||||
<ComboBox
|
||||
className="combo"
|
||||
directionY="both"
|
||||
options={cultureNames}
|
||||
selectedOption={selectedLanguage}
|
||||
onSelect={onLanguageSelect}
|
||||
isDisabled={false}
|
||||
noBorder={!isMobileOnly}
|
||||
scaled={isMobileOnly}
|
||||
scaledOptions={false}
|
||||
size="content"
|
||||
@ -105,6 +103,7 @@ const LanguagesCombo = (props) => {
|
||||
isDefaultMode={!isMobileOnly}
|
||||
withBlur={isMobileOnly}
|
||||
fillIcon={false}
|
||||
modernView={!isMobileOnly}
|
||||
/>
|
||||
</StyledRow>
|
||||
);
|
||||
|
@ -206,12 +206,7 @@ export const StyledRow = styled.div`
|
||||
|
||||
@media ${desktop} {
|
||||
height: 28px;
|
||||
}
|
||||
|
||||
.combo {
|
||||
& > div {
|
||||
justify-content: flex-start !important;
|
||||
}
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.label {
|
||||
|
@ -1260,7 +1260,6 @@ class FilesActionStore {
|
||||
|
||||
isAvailableOption = (option) => {
|
||||
const {
|
||||
isAccessedSelected,
|
||||
canConvertSelected,
|
||||
hasSelection,
|
||||
allFilesIsEditing,
|
||||
@ -1292,7 +1291,7 @@ class FilesActionStore {
|
||||
rootFolderType,
|
||||
editing: allFilesIsEditing,
|
||||
});
|
||||
return hasSelection && isAccessedSelected && canMove;
|
||||
return hasSelection && canMove;
|
||||
|
||||
case "archive":
|
||||
case "unarchive":
|
||||
@ -1314,9 +1313,8 @@ class FilesActionStore {
|
||||
rootFolderType,
|
||||
editing: allFilesIsEditing,
|
||||
});
|
||||
const deleteCondition = hasSelection && isAccessedSelected;
|
||||
|
||||
return canDelete && deleteCondition;
|
||||
return canDelete && hasSelection;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -63,3 +63,12 @@ export function loginWithTfaCode(userName, passwordHash, code) {
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export function loginWithConfirmKey(data) {
|
||||
return request({
|
||||
method: "post",
|
||||
url: `/authentication.json`,
|
||||
skipLogout: true,
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import styled, { css } from "styled-components";
|
||||
import { isMobileOnly } from "react-device-detect";
|
||||
import Base from "../../themes/base";
|
||||
import NoUserSelect from "../../utils/commonStyles";
|
||||
|
||||
@ -218,6 +219,11 @@ const StyledArrowIcon = styled.div`
|
||||
`
|
||||
transform: scale(1, -1);
|
||||
`}
|
||||
|
||||
${isMobileOnly &&
|
||||
css`
|
||||
margin-left: auto;
|
||||
`}
|
||||
`;
|
||||
StyledArrowIcon.defaultProps = { theme: Base };
|
||||
|
||||
|
@ -129,6 +129,7 @@ const StyledDropdownItem = styled.div`
|
||||
props.isActive &&
|
||||
css`
|
||||
transform: rotate(90deg);
|
||||
height: auto;
|
||||
`}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import PropTypes from "prop-types";
|
||||
import { mobile } from "../../utils/device";
|
||||
|
||||
const StyledModalBackdrop = styled.div.attrs((props) => ({
|
||||
style: {
|
||||
@ -26,12 +27,16 @@ const StyledModalBackdrop = styled.div.attrs((props) => ({
|
||||
min-height: fill-available;
|
||||
max-height: 100vh;
|
||||
width: 100vw;
|
||||
|
||||
overflow: hidden;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: ${(props) => props.zIndex};
|
||||
|
||||
@media ${mobile} {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
transition: 0.2s;
|
||||
opacity: 0;
|
||||
&.modal-backdrop-active {
|
||||
|
@ -488,10 +488,10 @@ const Dark = {
|
||||
marginRight: "8px",
|
||||
|
||||
background: "#292929",
|
||||
disableBackground: "#646464",
|
||||
disableBackground: "#545454",
|
||||
|
||||
fillColor: grayMaxLight,
|
||||
disableFillColor: "#646464",
|
||||
disableFillColor: "#474747",
|
||||
|
||||
borderColor: "#646464",
|
||||
disableBorderColor: "none",
|
||||
|
@ -29,7 +29,7 @@ namespace ASC.Web.Files.Configuration;
|
||||
[Scope]
|
||||
public class ProductEntryPoint : Product
|
||||
{
|
||||
internal const string ProductPath = "/products/files/";
|
||||
internal const string ProductPath = "/";
|
||||
|
||||
private readonly FilesSpaceUsageStatManager _filesSpaceUsageStatManager;
|
||||
private readonly CoreBaseSettings _coreBaseSettings;
|
||||
|
@ -29,7 +29,7 @@ namespace ASC.Files.Core.Helpers;
|
||||
[Scope]
|
||||
public class FilesLinkUtility
|
||||
{
|
||||
public const string FilesBaseVirtualPath = "~/products/files/";
|
||||
public const string FilesBaseVirtualPath = "~/";
|
||||
public const string EditorPage = "doceditor";
|
||||
private readonly string _filesUploaderURL;
|
||||
|
||||
@ -77,7 +77,7 @@ public class FilesLinkUtility
|
||||
|
||||
public string FileHandlerPath
|
||||
{
|
||||
get { return FilesBaseAbsolutePath + "httphandlers/filehandler.ashx"; }
|
||||
get { return FilesBaseAbsolutePath + "filehandler.ashx"; }
|
||||
}
|
||||
|
||||
public string DocServiceUrl
|
||||
@ -276,24 +276,11 @@ public class FilesLinkUtility
|
||||
get { return $"{FileWebEditorUrlString}&{Action}=view"; }
|
||||
}
|
||||
|
||||
public string GetFileWebViewerUrlForMobile(object fileId, int fileVersion)
|
||||
{
|
||||
var viewerUrl = _commonLinkUtility.ToAbsolute("~/../products/files/") + EditorPage + "?" + FileId + "={0}";
|
||||
|
||||
return string.Format(viewerUrl, HttpUtility.UrlEncode(fileId.ToString()))
|
||||
+ (fileVersion > 0 ? "&" + Version + "=" + fileVersion : string.Empty);
|
||||
}
|
||||
|
||||
public string FileWebViewerExternalUrlString
|
||||
{
|
||||
get { return FilesBaseAbsolutePath + EditorPage + "?" + FileUri + "={0}&" + FileTitle + "={1}&" + FolderUrl + "={2}"; }
|
||||
}
|
||||
|
||||
public string GetFileWebViewerExternalUrl(string fileUri, string fileTitle, string refererUrl = "")
|
||||
{
|
||||
return string.Format(FileWebViewerExternalUrlString, HttpUtility.UrlEncode(fileUri), HttpUtility.UrlEncode(fileTitle), HttpUtility.UrlEncode(refererUrl));
|
||||
}
|
||||
|
||||
public string FileWebEditorUrlString
|
||||
{
|
||||
get { return $"/{EditorPage}?{FileId}={{0}}"; }
|
||||
|
@ -30,9 +30,7 @@ namespace ASC.Web.Files.Classes;
|
||||
public class PathProvider
|
||||
{
|
||||
public static readonly string ProjectVirtualPath = "~/Products/Projects/TMDocs.aspx";
|
||||
public static readonly string TemplatePath = "/Products/Files/Templates/";
|
||||
public static readonly string StartURL = FilesLinkUtility.FilesBaseVirtualPath;
|
||||
public readonly string GetFileServicePath;
|
||||
|
||||
private readonly WebImageSupplier _webImageSupplier;
|
||||
private readonly IDaoFactory _daoFactory;
|
||||
@ -58,7 +56,6 @@ public class PathProvider
|
||||
_emailValidationKeyProvider = emailValidationKeyProvider;
|
||||
_globalStore = globalStore;
|
||||
_baseCommonLinkUtility = baseCommonLinkUtility;
|
||||
GetFileServicePath = _baseCommonLinkUtility.ToAbsolute("~/Products/Files/Services/WCFService/service.svc/");
|
||||
}
|
||||
|
||||
public string GetImagePath(string imgFileName)
|
||||
@ -66,26 +63,6 @@ public class PathProvider
|
||||
return _webImageSupplier.GetAbsoluteWebPath(imgFileName, ProductEntryPoint.ID);
|
||||
}
|
||||
|
||||
public string GetFileStaticRelativePath(string fileName)
|
||||
{
|
||||
var ext = FileUtility.GetFileExtension(fileName);
|
||||
|
||||
return ext switch
|
||||
{
|
||||
//Attention: Only for ResourceBundleControl
|
||||
".js" => VirtualPathUtility.ToAbsolute("~/Products/Files/js/" + fileName),
|
||||
".ascx" => _baseCommonLinkUtility.ToAbsolute("~/Products/Files/Controls/" + fileName),
|
||||
//Attention: Only for ResourceBundleControl
|
||||
".css" => VirtualPathUtility.ToAbsolute("~/Products/Files/App_Themes/default/" + fileName),
|
||||
_ => fileName,
|
||||
};
|
||||
}
|
||||
|
||||
public string GetFileControlPath(string fileName)
|
||||
{
|
||||
return _baseCommonLinkUtility.ToAbsolute("~/Products/Files/Controls/" + fileName);
|
||||
}
|
||||
|
||||
public async Task<string> GetFolderUrlAsync<T>(Folder<T> folder, int projectID = 0)
|
||||
{
|
||||
if (folder == null)
|
||||
|
@ -43,7 +43,7 @@ public class DocuSignHandlerService
|
||||
{
|
||||
public static string Path(FilesLinkUtility filesLinkUtility)
|
||||
{
|
||||
return filesLinkUtility.FilesBaseAbsolutePath + "httphandlers/docusignhandler.ashx";
|
||||
return filesLinkUtility.FilesBaseAbsolutePath + "docusignhandler.ashx";
|
||||
}
|
||||
|
||||
private readonly ILogger<DocuSignHandlerService> _log;
|
||||
|
@ -224,7 +224,6 @@ abstract class FileOperation<T, TId> : FileOperation where T : FileOperationData
|
||||
var (tenantManager, daoFactory, fileSecurity, logger) = scopeClass;
|
||||
tenantManager.SetCurrentTenant(CurrentTenant);
|
||||
|
||||
|
||||
Thread.CurrentPrincipal = _principal;
|
||||
Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo(_culture);
|
||||
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(_culture);
|
||||
|
@ -75,7 +75,7 @@ public class Startup : BaseStartup
|
||||
base.Configure(app, env);
|
||||
|
||||
app.MapWhen(
|
||||
context => context.Request.Path.ToString().EndsWith("httphandlers/filehandler.ashx", StringComparison.OrdinalIgnoreCase),
|
||||
context => context.Request.Path.ToString().EndsWith("filehandler.ashx", StringComparison.OrdinalIgnoreCase),
|
||||
appBranch =>
|
||||
{
|
||||
appBranch.UseFileHandler();
|
||||
@ -96,7 +96,7 @@ public class Startup : BaseStartup
|
||||
});
|
||||
|
||||
app.MapWhen(
|
||||
context => context.Request.Path.ToString().EndsWith("httphandlers/DocuSignHandler.ashx", StringComparison.OrdinalIgnoreCase),
|
||||
context => context.Request.Path.ToString().EndsWith("DocuSignHandler.ashx", StringComparison.OrdinalIgnoreCase),
|
||||
appBranch =>
|
||||
{
|
||||
appBranch.UseDocuSignHandler();
|
||||
|
@ -41,6 +41,7 @@ global using ASC.Core.Common;
|
||||
global using ASC.Core.Common.EF;
|
||||
global using ASC.Core.Common.Hosting;
|
||||
global using ASC.Core.Common.Hosting.Interfaces;
|
||||
global using ASC.Core.Notify.Socket;
|
||||
global using ASC.Core.Tenants;
|
||||
global using ASC.ElasticSearch;
|
||||
global using ASC.ElasticSearch.Service;
|
||||
|
@ -91,6 +91,7 @@ public class Startup : BaseWorkerStartup
|
||||
DIHelper.TryAdd<SecurityContext>();
|
||||
DIHelper.TryAdd<TenantManager>();
|
||||
DIHelper.TryAdd<UserManager>();
|
||||
DIHelper.TryAdd<SocketServiceClient>();
|
||||
|
||||
services.AddBaseDbContextPool<FilesDbContext>();
|
||||
|
||||
|
@ -31,7 +31,6 @@
|
||||
<PackageReference Include="Moq" Version="4.14.7" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="2.1.2" />
|
||||
<PackageReference Include="NEST" Version="7.15.2" />
|
||||
<PackageReference Include="NLog" Version="5.0.1" />
|
||||
<PackageReference Include="nunit" Version="3.13.3" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.2.0" />
|
||||
@ -48,7 +47,6 @@
|
||||
<ProjectReference Include="..\..\..\common\services\ASC.ElasticSearch\ASC.ElasticSearch.csproj" />
|
||||
<ProjectReference Include="..\..\..\migrations\mysql\ASC.Migrations.MySql.csproj" />
|
||||
<ProjectReference Include="..\..\..\web\ASC.Web.Core\ASC.Web.Core.csproj" />
|
||||
<ProjectReference Include="..\..\ASC.People\Server\ASC.People.csproj" />
|
||||
<ProjectReference Include="..\Core\ASC.Files.Core.csproj" />
|
||||
<ProjectReference Include="..\Server\ASC.Files.csproj" />
|
||||
</ItemGroup>
|
||||
|
@ -27,7 +27,9 @@
|
||||
|
||||
|
||||
using ASC.Files.Core.EF;
|
||||
using ASC.MessagingSystem.Core;
|
||||
using ASC.MessagingSystem.EF.Context;
|
||||
using ASC.Web.Core;
|
||||
using ASC.Webhooks.Core.EF.Context;
|
||||
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
@ -50,11 +52,6 @@ class FilesApplication : WebApplicationFactory<Program>
|
||||
builder.UseSetting(s.Key, s.Value);
|
||||
}
|
||||
|
||||
builder.ConfigureAppConfiguration((context, a) =>
|
||||
{
|
||||
(a.Sources[0] as ChainedConfigurationSource).Configuration["pathToConf"] = a.Build()["pathToConf"];
|
||||
});
|
||||
|
||||
builder.ConfigureServices(services =>
|
||||
{
|
||||
services.AddBaseDbContext<UserDbContext>();
|
||||
@ -86,7 +83,6 @@ public class MySetUpClass
|
||||
{
|
||||
var args = new Dictionary<string, string>
|
||||
{
|
||||
{ "pathToConf", Path.Combine("..","..", "..", "config") },
|
||||
{ "ConnectionStrings:default:connectionString", BaseFilesTests.TestConnection },
|
||||
{ "migration:enabled", "true" },
|
||||
{ "core:products:folder", Path.Combine("..", "..", "..", "products") },
|
||||
@ -175,7 +171,6 @@ public partial class BaseFilesTests
|
||||
{
|
||||
var host = new FilesApplication(new Dictionary<string, string>
|
||||
{
|
||||
{ "pathToConf", Path.Combine("..","..", "..", "config") },
|
||||
{ "ConnectionStrings:default:connectionString", TestConnection },
|
||||
{ "migration:enabled", "true" },
|
||||
{ "web:hub:internal", "" },
|
||||
@ -197,8 +192,9 @@ public partial class BaseFilesTests
|
||||
var tenant = tenantManager.GetTenant(1);
|
||||
tenantManager.SetCurrentTenant(tenant);
|
||||
|
||||
var securityContext = scope.ServiceProvider.GetService<SecurityContext>();
|
||||
_cookie = securityContext.AuthenticateMe(tenant.OwnerId);
|
||||
var _cookiesManager = scope.ServiceProvider.GetService<CookiesManager>();
|
||||
var action = MessageAction.LoginSuccessViaApi;
|
||||
_cookie = _cookiesManager.AuthenticateMeAndSetCookies(tenant.Id, tenant.OwnerId, action);
|
||||
|
||||
_client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _cookie);
|
||||
_client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
|
||||
|
@ -1,68 +0,0 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL 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 details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.Files.Tests;
|
||||
|
||||
[TestFixture]
|
||||
public partial class BaseFilesTests
|
||||
{
|
||||
[TestCase(DataTests.FileIdForRecent, DataTests.FileNameForRecent)]
|
||||
[Category("File")]
|
||||
[Order(1)]
|
||||
[Description("post - file/{fileId}/recent - add file to recent")]
|
||||
public async Task RecentFileReturnsFolderWrapper(int fileId, string fileName)
|
||||
{
|
||||
var file = await PostAsync<FileDto<int>>($"file/{fileId}/recent");
|
||||
Assert.IsNotNull(file);
|
||||
Assert.AreEqual(fileName, file.Title);
|
||||
}
|
||||
|
||||
[TestCase(DataTests.FileIdForRecent, DataTests.FileNameForRecent)]
|
||||
[Category("File")]
|
||||
[Order(2)]
|
||||
[Description("delete - file/{fileId}/recent - delete file which added to recent")]
|
||||
public async Task DeleteRecentFileReturnsFolderWrapper(int fileId, string fileTitleExpected)
|
||||
{
|
||||
await PostAsync<FileDto<int>>($"file/{fileId}/recent");
|
||||
|
||||
await DeleteAsync($"file/{fileId}", new { DeleteAfter = false, Immediately = true });
|
||||
await WaitLongOperation();
|
||||
|
||||
var recents = await GetAsync<FolderContentDto<int>>("@recent");
|
||||
Assert.IsTrue(!recents.Files.Any(r => r.Title == fileTitleExpected + ".docx"));
|
||||
}
|
||||
|
||||
[TestCase(DataTests.SharedForReadFileId, DataTests.FileName)]
|
||||
[Category("File")]
|
||||
[Order(3)]
|
||||
public async Task ShareFileToAnotherUserAddToRecent(int fileId, string fileName)
|
||||
{
|
||||
var file = await PostAsync<FileDto<int>>($"file/{fileId}/recent");
|
||||
|
||||
Assert.IsNotNull(file);
|
||||
Assert.AreEqual(fileName, file.Title);
|
||||
}
|
||||
}
|
@ -157,33 +157,6 @@ public partial class BaseFilesTests
|
||||
{
|
||||
var folder = await PutAsync<FolderDto<int>>($"rooms/{id}/unpin");
|
||||
Assert.IsFalse(folder.Pinned);
|
||||
}
|
||||
|
||||
[TestCase(DataTests.RoomId, DataTests.Email)]
|
||||
[Category("Room")]
|
||||
[Order(13)]
|
||||
[Description("put - rooms/{id}/links/send - send invitation links to email")]
|
||||
public async Task SendLink(int id, string email)
|
||||
{
|
||||
var invites = await PutAsync<IEnumerable<InviteResultDto>>($"rooms/{id}/links/send", new { Emails = new List<string>() { email }, EmployeeType = EmployeeType.All, Access = Core.Security.FileShare.Read });
|
||||
Assert.IsTrue(invites.First().Success);
|
||||
}
|
||||
|
||||
[TestCase(DataTests.RoomId)]
|
||||
[Category("Room")]
|
||||
[Order(15)]
|
||||
[Description("get - rooms/{id}/links - get invitation links /// put - rooms/{id}/share - share a room by link")]
|
||||
public async Task GetLinkAndShareRoomByLink(int id)
|
||||
{
|
||||
var invite = await GetAsync<string>($"rooms/{id}/links?access=2");
|
||||
Assert.IsNotNull(invite);
|
||||
Assert.IsNotEmpty(invite);
|
||||
|
||||
var key = invite.Substring(invite.IndexOf("&key=") + 5);
|
||||
key = key.Substring(0, key.IndexOf('&'));
|
||||
|
||||
var share = await PutAsync<IEnumerable<FileShareDto>>($"rooms/{id}/share", new { Access = Core.Security.FileShare.Read, Key = key });
|
||||
Assert.IsNotNull(share);
|
||||
}
|
||||
|
||||
//[TestCase(DataTests.RoomId, DataTests.Image)]
|
||||
|
@ -1,200 +0,0 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL 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 details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.Files.Tests;
|
||||
|
||||
[TestFixture]
|
||||
public partial class BaseFilesTests
|
||||
{
|
||||
private IEnumerable<FileShareParams> _testFolderParamRead;
|
||||
private IEnumerable<FileShareParams> _testFolderParamReadAndWrite;
|
||||
|
||||
|
||||
[OneTimeSetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
var newUser = _userManager.GetUsers(Guid.Parse("005bb3ff-7de3-47d2-9b3d-61b9ec8a76a5"));
|
||||
_testFolderParamRead = new List<FileShareParams> { new FileShareParams { Access = Core.Security.FileShare.Read, ShareTo = newUser.Id } };
|
||||
_testFolderParamReadAndWrite = new List<FileShareParams> { new FileShareParams { Access = Core.Security.FileShare.ReadWrite, ShareTo = newUser.Id } };
|
||||
}
|
||||
|
||||
#region Shared Folder and File (Read)
|
||||
|
||||
[TestCase(DataTests.SubFolderId, DataTests.Notify, DataTests.Message)]
|
||||
[Category("Folder Read")]
|
||||
[Order(2)]
|
||||
[Description("put - files/folder/{folderId}/share - share folder to another user for read")]
|
||||
public async Task ShareFolderToAnotherUserRead(int folderId, bool notify, string message)
|
||||
{
|
||||
var share = await PutAsync<IEnumerable<FileShareDto>>($"folder/{folderId}/share", new { Share = _testFolderParamRead, Notify = notify, SharingMessage = message });
|
||||
Assert.IsNotNull(share);
|
||||
}
|
||||
|
||||
[TestCase(DataTests.SharedForReadFolderId)]
|
||||
[Category("Folder Read")]
|
||||
[Order(4)]
|
||||
[Description("put - files/folder/{folderId} - try to update folder which can only read")]
|
||||
public async Task RenameSharedFolderReturnsFolderWrapperReadAsync(int folderId)
|
||||
{
|
||||
var result = await SendAsync(HttpMethod.Put, "folder/" + folderId, new { Title = "newName" });
|
||||
Assert.AreEqual(HttpStatusCode.Forbidden, result.StatusCode);
|
||||
}
|
||||
|
||||
[TestCase(DataTests.FileId, DataTests.Notify, DataTests.Message)]
|
||||
[Category("File Read")]
|
||||
[Order(7)]
|
||||
[Description("put - file/{fileId}/share - share file to another user for read")]
|
||||
public async Task ShareFileToAnotherUserRead(int fileId, bool notify, string message)
|
||||
{
|
||||
var share = await PutAsync<IEnumerable<FileShareDto>>($"file/{fileId}/share", new { Share = _testFolderParamRead, Notify = notify, SharingMessage = message });
|
||||
Assert.IsNotNull(share);
|
||||
}
|
||||
|
||||
[TestCase(DataTests.SharedForReadFileId)]
|
||||
[Category("File Read")]
|
||||
[Order(9)]
|
||||
[Description("put - files/file/{fileId} - try to update file which can only read")]
|
||||
public async Task UpdateSharedFileReturnsFolderWrapperReadAsync(int fileId)
|
||||
{
|
||||
var result = await SendAsync(HttpMethod.Put, "file/" + fileId, new { Title = "newName", LastVersion = 0 });
|
||||
Assert.That(HttpStatusCode.Forbidden == result.StatusCode);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Shared Folder and File (Read and Write)
|
||||
|
||||
[TestCase(DataTests.SubFolderId, DataTests.Notify, DataTests.Message)]
|
||||
[Category("Folder Read and Write")]
|
||||
[Order(11)]
|
||||
[Description("put - files/folder/{folderId}/share - share folder to another user for read and write")]
|
||||
public async Task ShareFolderToAnotherUserReadAndWrite(int folderId, bool notify, string message)
|
||||
{
|
||||
var share = await PutAsync<IEnumerable<FileShareDto>>($"folder/{folderId}/share", new { Share = _testFolderParamReadAndWrite, Notify = notify, SharingMessage = message });
|
||||
Assert.IsNotNull(share);
|
||||
}
|
||||
|
||||
[TestCase(DataTests.SharedForReadAndWriteFolderId, DataTests.NewTitle)]
|
||||
[Category("Folder Read and Write")]
|
||||
[Order(13)]
|
||||
[Description("put - files/folder/{folderId} - rename shared for read and write folder")]
|
||||
public async Task RenameSharedFolderReturnsFolderWrapperReadAndWrite(int folderId, string newTitle)
|
||||
{
|
||||
var sharedFolder = await PutAsync<FolderDto<int>>($"folder/{folderId}", new { Title = newTitle });
|
||||
|
||||
Assert.IsNotNull(sharedFolder);
|
||||
Assert.AreEqual(newTitle, sharedFolder.Title);
|
||||
}
|
||||
|
||||
[TestCase(DataTests.FileId, DataTests.Notify, DataTests.Message)]
|
||||
[Category("File Read and Write")]
|
||||
[Order(15)]
|
||||
[Description("put - files/file/{fileId}/share - share file to another user for read and write")]
|
||||
public async Task ShareFileToAnotherUserReadAndWrite(int fileId, bool notify, string message)
|
||||
{
|
||||
var share = await PutAsync<IEnumerable<FileShareDto>>($"file/{fileId}/share", new { Share = _testFolderParamReadAndWrite, Notify = notify, SharingMessage = message });
|
||||
Assert.IsNotNull(share);
|
||||
}
|
||||
|
||||
[TestCase(DataTests.SharedForReadAndWriteFileId, DataTests.NewTitle, 0)]
|
||||
[Category("File Read and Write")]
|
||||
[Order(17)]
|
||||
[Description("put - files/file/{fileId} - update shared for read and write file")]
|
||||
public async Task UpdateSharedFileReturnsFolderWrapperReadAndWrite(int fileId, string fileTitle, int lastVersion)
|
||||
{
|
||||
var sharedFile = await PutAsync<FolderDto<int>>($"file/{fileId}", new { Title = fileTitle, LastVersion = lastVersion });
|
||||
|
||||
Assert.IsNotNull(sharedFile);
|
||||
Assert.AreEqual(fileTitle + ".docx", sharedFile.Title);
|
||||
}
|
||||
#endregion
|
||||
|
||||
[TestCase(DataTests.SharedForReadFolderId, DataTests.SharedForReadFolderName, DataTests.ShareId)]
|
||||
[TestCase(DataTests.SharedForReadAndWriteFolderId, DataTests.SharedForReadAndWriteFolderName, DataTests.ShareId)]
|
||||
[Category("Folder")]
|
||||
[Order(3)]
|
||||
[Description("get - files/folder/{folderId} - get shared folder")]
|
||||
public async Task GetSharedFolderInfoReturnsFolderWrapperRead(int folderId, string folderName, int parentId)
|
||||
{
|
||||
var sharedFolder = await GetAsync<FolderDto<int>>($"folder/{folderId}");
|
||||
|
||||
Assert.IsNotNull(sharedFolder);
|
||||
Assert.AreEqual(folderName, sharedFolder.Title);
|
||||
Assert.AreEqual(folderId, sharedFolder.Id);
|
||||
Assert.AreEqual(parentId, sharedFolder.ParentId);
|
||||
}
|
||||
|
||||
[TestCase(DataTests.SharedForReadFileId, DataTests.SharedForReadFileName)]
|
||||
[TestCase(DataTests.SharedForReadAndWriteFileId, DataTests.SharedForReadAndWriteFileName)]
|
||||
[Category("File")]
|
||||
[Order(8)]
|
||||
[Description("get - files/file/{fileId} - get shared file")]
|
||||
public async Task GetSharedFileInfoReturnsFolderWrapperRead(int fileId, string fileName)
|
||||
{
|
||||
var sharedFile = await GetAsync<FolderDto<int>>($"file/{fileId}");
|
||||
|
||||
Assert.IsNotNull(sharedFile);
|
||||
Assert.AreEqual(fileName, sharedFile.Title);
|
||||
}
|
||||
|
||||
[TestCase(DataTests.SharedForReadFileId, DataTests.DeleteAfter, DataTests.Immediately)]
|
||||
[TestCase(DataTests.SharedForReadAndWriteFileId, DataTests.DeleteAfter, DataTests.Immediately)]
|
||||
[Category("File")]
|
||||
[Order(10)]
|
||||
[Description("delete - files/file/{fileId} - try delete shared file")]
|
||||
public async Task DeleteSharedFileReturnsFolderWrapperRead(int fileId, bool deleteAfter, bool immediately)
|
||||
{
|
||||
var result = (await DeleteAsync<IEnumerable<FileOperationDto>>($"file/{fileId}", new { DeleteAfter = deleteAfter, Immediately = immediately })).FirstOrDefault();
|
||||
|
||||
await WaitLongOperation(result, FilesCommonResource.ErrorMassage_SecurityException_DeleteFile);
|
||||
}
|
||||
|
||||
[TestCase(DataTests.SharedForReadFolderId, DataTests.DeleteAfter, DataTests.Immediately)]
|
||||
[TestCase(DataTests.SharedForReadAndWriteFolderId, DataTests.DeleteAfter, DataTests.Immediately)]
|
||||
[Category("Folder")]
|
||||
[Order(50)]
|
||||
[Description("delete - files/folder/{folderId} - try delete shared folder")]
|
||||
public async Task DeleteSharedFolderReturnsFolderWrapperRead(int folderId, bool deleteAfter, bool immediately)
|
||||
{
|
||||
var result = (await DeleteAsync<IEnumerable<FileOperationDto>>($"folder/{folderId}", new { DeleteAfter = deleteAfter, Immediately = immediately })).FirstOrDefault();
|
||||
|
||||
await WaitLongOperation(result, FilesCommonResource.ErrorMassage_SecurityException_DeleteFolder);
|
||||
}
|
||||
|
||||
private async Task WaitLongOperation(FileOperationDto result, string assertError)
|
||||
{
|
||||
if (result != null && result.Finished)
|
||||
{
|
||||
Assert.That(result.Error == assertError, result.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
var statuses = await WaitLongOperation();
|
||||
|
||||
var error = string.Join(",", statuses.Select(r => r.Error));
|
||||
Assert.That(error == assertError, error);
|
||||
}
|
||||
}
|
@ -42,7 +42,8 @@ public class AuthenticationController : ControllerBase
|
||||
private readonly CookiesManager _cookiesManager;
|
||||
private readonly PasswordHasher _passwordHasher;
|
||||
private readonly EmailValidationKeyModelHelper _emailValidationKeyModelHelper;
|
||||
private readonly ICache _cache;
|
||||
private readonly ICache _cache;
|
||||
private readonly SetupInfo _setupInfo;
|
||||
private readonly MessageService _messageService;
|
||||
private readonly ProviderManager _providerManager;
|
||||
private readonly AccountLinker _accountLinker;
|
||||
@ -66,7 +67,8 @@ public class AuthenticationController : ControllerBase
|
||||
private readonly CookieStorage _cookieStorage;
|
||||
private readonly DbLoginEventsManager _dbLoginEventsManager;
|
||||
private readonly UserManagerWrapper _userManagerWrapper;
|
||||
private readonly TfaAppAuthSettingsHelper _tfaAppAuthSettingsHelper;
|
||||
private readonly TfaAppAuthSettingsHelper _tfaAppAuthSettingsHelper;
|
||||
private readonly EmailValidationKeyProvider _emailValidationKeyProvider;
|
||||
private readonly BruteForceLoginManager _bruteForceLoginManager;
|
||||
|
||||
public AuthenticationController(
|
||||
@ -103,7 +105,8 @@ public class AuthenticationController : ControllerBase
|
||||
CookieStorage cookieStorage,
|
||||
DbLoginEventsManager dbLoginEventsManager,
|
||||
BruteForceLoginManager bruteForceLoginManager,
|
||||
TfaAppAuthSettingsHelper tfaAppAuthSettingsHelper)
|
||||
TfaAppAuthSettingsHelper tfaAppAuthSettingsHelper,
|
||||
EmailValidationKeyProvider emailValidationKeyProvider)
|
||||
{
|
||||
_userManager = userManager;
|
||||
_tenantManager = tenantManager;
|
||||
@ -112,7 +115,8 @@ public class AuthenticationController : ControllerBase
|
||||
_cookiesManager = cookiesManager;
|
||||
_passwordHasher = passwordHasher;
|
||||
_emailValidationKeyModelHelper = emailValidationKeyModelHelper;
|
||||
_cache = cache;
|
||||
_cache = cache;
|
||||
_setupInfo = setupInfo;
|
||||
_messageService = messageService;
|
||||
_providerManager = providerManager;
|
||||
_accountLinker = accountLinker;
|
||||
@ -137,7 +141,8 @@ public class AuthenticationController : ControllerBase
|
||||
_dbLoginEventsManager = dbLoginEventsManager;
|
||||
_userManagerWrapper = userManagerWrapper;
|
||||
_bruteForceLoginManager = bruteForceLoginManager;
|
||||
_tfaAppAuthSettingsHelper = tfaAppAuthSettingsHelper;
|
||||
_tfaAppAuthSettingsHelper = tfaAppAuthSettingsHelper;
|
||||
_emailValidationKeyProvider = emailValidationKeyProvider;
|
||||
}
|
||||
|
||||
[AllowNotPayment]
|
||||
@ -215,7 +220,12 @@ public class AuthenticationController : ControllerBase
|
||||
{
|
||||
var wrapper = await GetUser(inDto);
|
||||
var viaEmail = wrapper.ViaEmail;
|
||||
var user = wrapper.UserInfo;
|
||||
var user = wrapper.UserInfo;
|
||||
|
||||
if (user == null || Equals(user, Constants.LostUser))
|
||||
{
|
||||
throw new Exception(Resource.ErrorUserNotFound);
|
||||
}
|
||||
|
||||
if (_studioSmsNotificationSettingsHelper.IsVisibleAndAvailableSettings() && _studioSmsNotificationSettingsHelper.TfaEnabledForUser(user.Id))
|
||||
{
|
||||
@ -347,12 +357,34 @@ public class AuthenticationController : ControllerBase
|
||||
var wrapper = new UserInfoWrapper
|
||||
{
|
||||
ViaEmail = true
|
||||
};
|
||||
};
|
||||
|
||||
var action = MessageAction.LoginFailViaApi;
|
||||
UserInfo user;
|
||||
UserInfo user = null;
|
||||
|
||||
try
|
||||
{
|
||||
if ((string.IsNullOrEmpty(inDto.Provider) && string.IsNullOrEmpty(inDto.SerializedProfile)) || inDto.Provider == "email")
|
||||
{
|
||||
if (inDto.ConfirmData != null)
|
||||
{
|
||||
var email = inDto.ConfirmData.Email;
|
||||
|
||||
var checkKeyResult = _emailValidationKeyProvider.ValidateEmailKey(email + ConfirmType.Auth + inDto.ConfirmData.First + inDto.ConfirmData.Module + inDto.ConfirmData.Sms, inDto.ConfirmData.Key, _setupInfo.ValidAuthKeyInterval);
|
||||
|
||||
if (checkKeyResult == ValidationResult.Ok)
|
||||
{
|
||||
user = email.Contains("@")
|
||||
? _userManager.GetUserByEmail(email)
|
||||
: _userManager.GetUsers(new Guid(email));
|
||||
|
||||
if (_securityContext.IsAuthenticated && _securityContext.CurrentAccount.ID != user.Id)
|
||||
{
|
||||
_securityContext.Logout();
|
||||
_cookiesManager.ClearCookies(CookiesType.AuthKey);
|
||||
_cookiesManager.ClearCookies(CookiesType.SocketIO);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((string.IsNullOrEmpty(inDto.Provider) && string.IsNullOrEmpty(inDto.SerializedProfile)) || inDto.Provider == "email")
|
||||
{
|
||||
inDto.UserName.ThrowIfNull(new ArgumentException(@"userName empty", "userName"));
|
||||
if (!string.IsNullOrEmpty(inDto.Password))
|
||||
|
@ -36,10 +36,21 @@ public class AuthRequestsDto
|
||||
public string SerializedProfile { get; set; }
|
||||
public string Code { get; set; }
|
||||
public string CodeOAuth { get; set; }
|
||||
public bool Session { get; set; }
|
||||
public bool Session { get; set; }
|
||||
|
||||
public ConfirmData ConfirmData { get; set; }
|
||||
}
|
||||
|
||||
public class MobileRequestsDto
|
||||
{
|
||||
public string MobilePhone { get; set; }
|
||||
}
|
||||
|
||||
public class ConfirmData
|
||||
{
|
||||
public string Email { get; set; }
|
||||
public string Module { get; set; }
|
||||
public bool? First { get; set; }
|
||||
public bool? Sms { get; set; }
|
||||
public string Key { get; set; }
|
||||
}
|
||||
|
@ -39,8 +39,11 @@ public class Startup : BaseStartup
|
||||
{
|
||||
base.ConfigureServices(services);
|
||||
|
||||
services.AddHostedService<LdapNotifyService>();
|
||||
DIHelper.TryAdd<LdapNotifyService>();
|
||||
if (!_configuration.GetValue<bool>("disableLdapNotifyService"))
|
||||
{
|
||||
services.AddHostedService<LdapNotifyService>();
|
||||
DIHelper.TryAdd<LdapNotifyService>();
|
||||
}
|
||||
services.AddBaseDbContextPool<FilesDbContext>();
|
||||
services.AddBaseDbContextPool<BackupsContext>();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user