diff --git a/build/install/docker/Dockerfile.dev b/build/install/docker/Dockerfile.dev index 63fdf1c20f..365c287085 100644 --- a/build/install/docker/Dockerfile.dev +++ b/build/install/docker/Dockerfile.dev @@ -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 diff --git a/build/install/docker/build.dev.yml b/build/install/docker/build.dev.yml index 34b3811d7b..6a3fc51d5e 100644 --- a/build/install/docker/build.dev.yml +++ b/build/install/docker/build.dev.yml @@ -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: diff --git a/build/install/docker/docspace.dev.yml b/build/install/docker/docspace.dev.yml index e8a89e3988..1b69434a79 100644 --- a/build/install/docker/docspace.dev.yml +++ b/build/install/docker/docspace.dev.yml @@ -116,10 +116,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 +163,7 @@ services: # - onlyoffice-telegram-service # - onlyoffice-urlshortener - onlyoffice-api - # - onlyoffice-api-system + - onlyoffice-api-system - onlyoffice-studio - onlyoffice-ssoauth environment: diff --git a/packages/client/src/pages/Confirm/index.js b/packages/client/src/pages/Confirm/index.js index ecc4ce66bf..0e35bb6209 100644 --- a/packages/client/src/pages/Confirm/index.js +++ b/packages/client/src/pages/Confirm/index.js @@ -20,6 +20,7 @@ const DeactivatePortal = lazy(() => import("./sub-components/deactivatePortal") ); const ContinuePortal = lazy(() => import("./sub-components/continuePortal")); +const Auth = lazy(() => import("./sub-components/auth")); const Confirm = ({ match }) => { //console.log("Confirm render"); @@ -88,6 +89,7 @@ const Confirm = ({ match }) => { path={`${path}/PortalContinue`} component={ContinuePortal} /> + {/* */} diff --git a/packages/client/src/pages/Confirm/sub-components/auth.js b/packages/client/src/pages/Confirm/sub-components/auth.js new file mode 100644 index 0000000000..7a8385d78c --- /dev/null +++ b/packages/client/src/pages/Confirm/sub-components/auth.js @@ -0,0 +1,38 @@ +import React, { useEffect } from "react"; +import { withRouter } from "react-router"; +import Loader from "@docspace/components/loader"; +import Section from "@docspace/common/components/Section"; +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(() => { + 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 ; +}; + +const AuthPage = (props) => ( +
+ + + +
+); + +export default withRouter(AuthPage); diff --git a/packages/common/api/user/index.js b/packages/common/api/user/index.js index 4aa6b18133..2da5b878b1 100644 --- a/packages/common/api/user/index.js +++ b/packages/common/api/user/index.js @@ -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, + }); +} diff --git a/web/ASC.Web.Api/Api/AuthenticationController.cs b/web/ASC.Web.Api/Api/AuthenticationController.cs index 6b30e01119..6ad39bd2a5 100644 --- a/web/ASC.Web.Api/Api/AuthenticationController.cs +++ b/web/ASC.Web.Api/Api/AuthenticationController.cs @@ -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)) diff --git a/web/ASC.Web.Api/ApiModels/RequestsDto/AuthRequestsDto.cs b/web/ASC.Web.Api/ApiModels/RequestsDto/AuthRequestsDto.cs index 0c77cf38e4..c4c818cf0d 100644 --- a/web/ASC.Web.Api/ApiModels/RequestsDto/AuthRequestsDto.cs +++ b/web/ASC.Web.Api/ApiModels/RequestsDto/AuthRequestsDto.cs @@ -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; } }