Merge branch 'develop' into feature/new-profile-loader

This commit is contained in:
Viktor Fomin 2022-11-11 03:42:47 +05:00
commit ae692869b4
16 changed files with 321 additions and 116 deletions

View File

@ -92,9 +92,9 @@ public class CommonMethods
};
}
public string CreateReference(string requestUriScheme, string tenantDomain, string email, bool first = false, string module = "", bool sms = false)
public string CreateReference(int tenantId,string requestUriScheme, string tenantDomain, string email, bool first = false, string module = "", bool sms = false)
{
var url = _commonLinkUtility.GetConfirmationUrlRelative(email, ConfirmType.Auth, (first ? "true" : "") + module + (sms ? "true" : ""));
var url = _commonLinkUtility.GetConfirmationUrlRelative(tenantId, email, ConfirmType.Auth, (first ? "true" : "") + module + (sms ? "true" : ""));
return $"{requestUriScheme}{Uri.SchemeDelimiter}{tenantDomain}/{url}{(first ? "&first=true" : "")}{(string.IsNullOrEmpty(module) ? "" : "&module=" + module)}{(sms ? "&sms=true" : "")}";
}

View File

@ -309,26 +309,17 @@ public class PortalController : ControllerBase
}
}
try
var reference = _commonMethods.CreateReference(t.Id, Request.Scheme, t.GetTenantDomain(_coreSettings), info.Email, isFirst);
_log.LogDebug("PortalName = {0}; Elapsed ms. CreateReferenceByCookie...: {1}", model.PortalName, sw.ElapsedMilliseconds);
sw.Stop();
return Ok(new
{
_log.LogDebug("try CreateReference");
var reference = _commonMethods.CreateReference(Request.Scheme, t.GetTenantDomain(_coreSettings), info.Email, isFirst);
_log.LogDebug("PortalName = {0}; Elapsed ms. CreateReferenceByCookie...: {1}", model.PortalName, sw.ElapsedMilliseconds);
sw.Stop();
return Ok(new
{
reference,
tenant = _commonMethods.ToTenantWrapper(t),
referenceWelcome = sendCongratulationsAddress
});
}catch (Exception e)
{
_log.LogError(e, "CreateReference error");
return BadRequest(error);
}
reference,
tenant = _commonMethods.ToTenantWrapper(t),
referenceWelcome = sendCongratulationsAddress
});
}
[HttpDelete("remove")]

View File

@ -0,0 +1,8 @@
{
"ArchiveHeader": "Move to Archived?",
"ArchiveRoom": "You are about to archive a room.",
"ArchiveRooms": "You are about to archive rooms.",
"RestoreRoom": "Are you sure you want to restore room?",
"RestoreRooms": "Are you sure you want to restore rooms?",
"RestoreAllRooms": "Are you sure you want to restore all rooms?"
}

View File

@ -1,4 +1,6 @@
{
"DeleteRoom": "You are about to delete this room? You wont be able to restore her.",
"DeleteRooms": "You are about to delete these rooms? You wont be able to restore it.",
"MoveToTrashButton": "Move to Trash",
"MoveToTrashFile": "You are about to delete this file? Please note, that if you have shared it with someone, it will become unavailable. Are you sure you want to continue?",
"MoveToTrashFolder": "You are about to delete this folder? Please note, that if you have shared it with someone, it will become unavailable. Are you sure you want to continue?",

View File

@ -1,6 +1,6 @@
{
"All": "All",
"Archived": "Archived",
"Archived": "Move to archive",
"ArchiveAction": "Empty archive",
"ArchivedRoomAction": "The room '{{name}}' is archived",
"ArchivedRoomsAction": "The rooms are archived",
@ -94,7 +94,6 @@
"RoomRemoved": "Room removed",
"RoomsRemoved": "Rooms removed",
"RestoreAll": "Restore all",
"RestoreAllArchive": "Are you sure you want to restore all rooms?",
"SearchByContent": "Search by file contents",
"SendByEmail": "Send by email",
"Share": "Share",

View File

@ -55,7 +55,7 @@ const withHotkeys = (Component) => {
isVisitor,
deleteRooms,
moveRoomsToArchive,
archiveRooms,
} = props;
const hotkeysFilter = {
@ -260,7 +260,7 @@ const withHotkeys = (Component) => {
}
if (isRoomsFolder) {
isAvailableOption("archive") && moveRoomsToArchive(t);
isAvailableOption("archive") && archiveRooms("archive");
return;
}
@ -394,7 +394,7 @@ const withHotkeys = (Component) => {
backToParentFolder,
setFavoriteAction,
deleteRooms,
moveRoomsToArchive,
archiveRooms,
} = filesActionsStore;
const { visible: mediaViewerIsVisible } = mediaViewerDataStore;
@ -456,7 +456,7 @@ const withHotkeys = (Component) => {
isVisitor,
deleteRooms,
moveRoomsToArchive,
archiveRooms,
};
}
)(observer(WithHotkeys));

View File

@ -26,7 +26,7 @@ import {
InviteUsersWarningDialog,
} from "../dialogs";
import ConvertPasswordDialog from "../dialogs/ConvertPasswordDialog";
import RestoreAllArchiveDialog from "../dialogs/RestoreAllArchiveDialog";
import ArchiveDialog from "../dialogs/ArchiveDialog";
const Panels = (props) => {
const {
@ -54,7 +54,7 @@ const Panels = (props) => {
convertPasswordDialogVisible,
createRoomDialogVisible,
restoreAllPanelVisible,
restoreAllArchiveDialogVisible,
archiveDialogVisible,
inviteUsersWarningDialogVisible,
} = props;
@ -121,9 +121,7 @@ const Panels = (props) => {
convertPasswordDialogVisible && (
<ConvertPasswordDialog key="convert-password-dialog" />
),
restoreAllArchiveDialogVisible && (
<RestoreAllArchiveDialog key="restore-all-archive-dialog" />
),
archiveDialogVisible && <ArchiveDialog key="archive-dialog" />,
inviteUsersWarningDialogVisible && (
<InviteUsersWarningDialog key="invite-users-warning-dialog" />
),
@ -151,7 +149,7 @@ export default inject(
convertPasswordDialogVisible,
connectItem, //TODO:
restoreAllPanelVisible,
restoreAllArchiveDialogVisible,
archiveDialogVisible,
createMasterForm,
selectFileDialogVisible,
@ -189,7 +187,7 @@ export default inject(
hotkeyPanelVisible,
restoreAllPanelVisible,
invitePanelVisible: invitePanelOptions.visible,
restoreAllArchiveDialogVisible,
archiveDialogVisible,
inviteUsersWarningDialogVisible,
};
}

View File

@ -17,16 +17,21 @@ const StyledModal = styled(ModalDialogContainer)`
}
`;
const RestoreAllArchiveDialogComponent = (props) => {
const ArchiveDialogComponent = (props) => {
const {
visible,
t,
tReady,
setRestoreAllArchiveDialogVisible,
visible,
restoreAll,
action,
setArchiveDialogVisible,
setRestoreAllArchive,
setArchiveActionType,
setArchiveAction,
folders,
items,
} = props;
const [requestRunning, setRequestRunning] = React.useState(false);
@ -38,13 +43,17 @@ const RestoreAllArchiveDialogComponent = (props) => {
}, []);
const onClose = () => {
!requestRunning && setRestoreAllArchiveDialogVisible(false);
if (!requestRunning) {
setRestoreAllArchive(false);
setArchiveActionType(null);
setArchiveDialogVisible(false);
}
};
const onRestore = () => {
const onAction = () => {
setRequestRunning(true);
setArchiveAction("unarchive", folders, t).then(() => {
setArchiveAction(action, items, t).then(() => {
setRequestRunning(false);
onClose();
});
@ -52,10 +61,34 @@ const RestoreAllArchiveDialogComponent = (props) => {
const onKeyPress = (e) => {
if (e.keyCode === 13) {
onRestore();
onAction();
}
};
const getDescription = () => {
if (restoreAll) return t("ArchiveDialog:RestoreAllRooms");
if (action === "archive") {
return items.length > 1
? `${t("ArchiveDialog:ArchiveRooms")} ${t("Common:WantToContinue")}`
: `${t("ArchiveDialog:ArchiveRoom")} ${t("Common:WantToContinue")}`;
}
if (action === "unarchive") {
return items.length > 1
? t("ArchiveDialog:RestoreRooms")
: t("ArchiveDialog:RestoreRoom");
}
};
const header =
action === "archive"
? t("ArchiveDialog:ArchiveHeader")
: t("Common:Restore");
const description = getDescription();
const acceptButton =
action === "archive" ? t("Common:OKButton") : t("Common:Restore");
return (
<StyledModal
isLoading={!tReady}
@ -63,17 +96,17 @@ const RestoreAllArchiveDialogComponent = (props) => {
onClose={onClose}
displayType="modal"
>
<ModalDialog.Header>{t("Common:Restore")}</ModalDialog.Header>
<ModalDialog.Header>{header}</ModalDialog.Header>
<ModalDialog.Body>
<Text>{t("RestoreAllArchive")}</Text>
<Text>{description}</Text>
</ModalDialog.Body>
<ModalDialog.Footer>
<Button
key="OkButton"
label={t("Common:Restore")}
label={acceptButton}
size="normal"
primary
onClick={onRestore}
onClick={onAction}
isLoading={requestRunning}
scale
/>
@ -90,27 +123,40 @@ const RestoreAllArchiveDialogComponent = (props) => {
);
};
const RestoreAllArchiveDialog = withTranslation([
"Files",
"Common",
"Translations",
])(RestoreAllArchiveDialogComponent);
const ArchiveDialog = withTranslation(["Files", "ArchiveDialog", "Common"])(
ArchiveDialogComponent
);
export default inject(({ filesStore, filesActionsStore, dialogsStore }) => {
const { folders } = filesStore;
const { folders, selection, bufferSelection } = filesStore;
const { setArchiveAction } = filesActionsStore;
const {
restoreAllArchiveDialogVisible: visible,
setRestoreAllArchiveDialogVisible,
archiveDialogVisible: visible,
restoreAllArchive: restoreAll,
archiveAction: action,
setArchiveDialogVisible,
setRestoreAllArchive,
setArchiveAction: setArchiveActionType,
} = dialogsStore;
const items = restoreAll
? folders
: selection.length > 0
? selection
: [bufferSelection];
return {
visible,
restoreAll,
action,
setRestoreAllArchiveDialogVisible,
setArchiveDialogVisible,
setRestoreAllArchive,
setArchiveActionType,
setArchiveAction,
folders,
items,
};
})(withRouter(observer(RestoreAllArchiveDialog)));
})(withRouter(observer(ArchiveDialog)));

View File

@ -7,6 +7,7 @@ import Text from "@docspace/components/text";
import { withTranslation } from "react-i18next";
import toastr from "@docspace/components/toast/toastr";
import { inject, observer } from "mobx-react";
import { TIMEOUT } from "@docspace/client/src/helpers/filesConstants";
const DeleteDialogComponent = (props) => {
const {
@ -24,6 +25,10 @@ const DeleteDialogComponent = (props) => {
isPrivacyFolder,
isRecycleBinFolder,
isRootFolder,
isRoomDelete,
setIsRoomDelete,
deleteRoomsAction,
} = props;
const selection = [];
@ -83,9 +88,26 @@ const DeleteDialogComponent = (props) => {
unsubscribeAction(filesId, foldersId).catch((err) => toastr.error(err));
};
const onDeleteRoom = async () => {
const translations = {
deleteOperation: t("Translations:DeleteOperation"),
successRemoveFile: t("Files:FileRemoved"),
successRemoveFolder: t("Files:FolderRemoved"),
successRemoveRoom: t("Files:RoomRemoved"),
successRemoveRooms: t("Files:RoomsRemoved"),
};
const itemId = selection.map((s) => s.id);
await deleteRoomsAction(itemId, translations);
onClose();
};
const onClose = () => {
setBufferSelection(null);
setRemoveMediaItem(null);
setIsRoomDelete(false);
setDeleteDialogVisible(false);
};
@ -98,8 +120,13 @@ const DeleteDialogComponent = (props) => {
const isFolder = selection[0]?.isFolder || !!selection[0]?.parentId;
if (selection.length > 1) {
if (isRoomDelete)
return `${t("DeleteRooms")} ${t("Common:WantToContinue")}`;
return t("MoveToTrashItems");
} else {
if (isRoomDelete)
return `${t("DeleteRoom")} ${t("Common:WantToContinue")}`;
return !isFolder
? t("MoveToTrashFile")
: personal
@ -108,19 +135,21 @@ const DeleteDialogComponent = (props) => {
}
};
const title =
isPrivacyFolder || isRecycleBinFolder || selection[0]?.providerKey
? t("Common:Confirmation")
: moveToTrashTitle();
const title = isRoomDelete
? t("EmptyTrashDialog:DeleteForeverTitle")
: isPrivacyFolder || isRecycleBinFolder || selection[0]?.providerKey
? t("Common:Confirmation")
: moveToTrashTitle();
const noteText = unsubscribe ? t("UnsubscribeNote") : moveToTrashNoteText();
const accessButtonLabel =
isPrivacyFolder || isRecycleBinFolder || selection[0]?.providerKey
? t("Common:OKButton")
: unsubscribe
? t("UnsubscribeButton")
: t("MoveToTrashButton");
const accessButtonLabel = isRoomDelete
? t("EmptyTrashDialog:DeleteForeverButton")
: isPrivacyFolder || isRecycleBinFolder || selection[0]?.providerKey
? t("Common:OKButton")
: unsubscribe
? t("UnsubscribeButton")
: t("MoveToTrashButton");
return (
<StyledDeleteDialog isLoading={!tReady} visible={visible} onClose={onClose}>
@ -137,7 +166,9 @@ const DeleteDialogComponent = (props) => {
size="normal"
primary
scale
onClick={unsubscribe ? onUnsubscribe : onDelete}
onClick={
isRoomDelete ? onDeleteRoom : unsubscribe ? onUnsubscribe : onDelete
}
isLoading={isLoading}
isDisabled={!selection.length}
/>
@ -159,6 +190,7 @@ const DeleteDialog = withTranslation([
"Common",
"Translations",
"Files",
"EmptyTrashDialog",
])(DeleteDialogComponent);
export default inject(
@ -169,6 +201,7 @@ export default inject(
filesActionsStore,
treeFoldersStore,
auth,
uploadDataStore,
}) => {
const {
selection,
@ -176,7 +209,11 @@ export default inject(
bufferSelection,
setBufferSelection,
} = filesStore;
const { deleteAction, unsubscribeAction } = filesActionsStore;
const {
deleteAction,
unsubscribeAction,
deleteRoomsAction,
} = filesActionsStore;
const { isPrivacyFolder, isRecycleBinFolder } = treeFoldersStore;
const {
@ -185,6 +222,8 @@ export default inject(
removeMediaItem,
setRemoveMediaItem,
unsubscribe,
isRoomDelete,
setIsRoomDelete,
} = dialogsStore;
const { personal } = auth.settingsStore;
@ -210,6 +249,10 @@ export default inject(
personal,
setBufferSelection,
isRoomDelete,
setIsRoomDelete,
deleteRoomsAction,
};
}
)(withRouter(observer(DeleteDialog)));

View File

@ -317,7 +317,9 @@ class SectionHeaderContent extends React.Component {
if (isExistActiveItems) return;
this.props.setRestoreAllArchiveDialogVisible(true);
this.props.setArchiveAction("unarchive");
this.props.setRestoreAllArchive(true);
this.props.setArchiveDialogVisible(true);
};
onShowInfo = () => {
@ -717,7 +719,9 @@ export default inject(
setSelectFileDialogVisible,
setIsFolderActions,
setRestoreAllPanelVisible,
setRestoreAllArchiveDialogVisible,
setArchiveDialogVisible,
setRestoreAllArchive,
setArchiveAction,
} = dialogsStore;
const {
@ -824,7 +828,9 @@ export default inject(
setRestoreAllPanelVisible,
isEmptyPage,
setRestoreAllArchiveDialogVisible,
setArchiveDialogVisible,
setRestoreAllArchive,
setArchiveAction,
selectedFolder,

View File

@ -438,13 +438,14 @@ class ContextOptionsStore {
this.filesActionsStore.setPinAction(action, id, t);
};
onClickArchive = (e, item, t) => {
onClickArchive = (e) => {
const data = (e.currentTarget && e.currentTarget.dataset) || e;
const { action } = data;
this.filesActionsStore
.setArchiveAction(action, item, t)
.catch((err) => toastr.error(err));
const { setArchiveDialogVisible, setArchiveAction } = this.dialogsStore;
setArchiveAction(action);
setArchiveDialogVisible(true);
};
onSelect = (item) => {
@ -799,7 +800,7 @@ class ContextOptionsStore {
key: "archive-room",
label: t("Archived"),
icon: "/static/images/room.archive.svg",
onClick: (e) => this.onClickArchive(e, item, t),
onClick: (e) => this.onClickArchive(e),
disabled: false,
"data-action": "archive",
action: "archive",
@ -808,7 +809,7 @@ class ContextOptionsStore {
key: "unarchive-room",
label: t("Common:Restore"),
icon: "images/subtract.react.svg",
onClick: (e) => this.onClickArchive(e, item, t),
onClick: (e) => this.onClickArchive(e),
disabled: false,
"data-action": "unarchive",
action: "unarchive",
@ -866,8 +867,7 @@ class ContextOptionsStore {
const {
pinRooms,
unpinRooms,
moveRoomsToArchive,
moveRoomsFromArchive,
deleteRooms,
} = this.filesActionsStore;
@ -895,15 +895,19 @@ class ContextOptionsStore {
key: "archive-room",
label: t("Archived"),
icon: "/static/images/room.archive.svg",
onClick: () => moveRoomsToArchive(t),
onClick: (e) => this.onClickArchive(e),
disabled: false,
"data-action": "archive",
action: "archive",
}
: {
key: "unarchive-room",
label: t("Common:Restore"),
icon: "images/subtract.react.svg",
onClick: () => moveRoomsFromArchive(t),
onClick: (e) => this.onClickArchive(e),
disabled: false,
"data-action": "unarchive",
action: "unarchive",
};
const options = [];

View File

@ -35,7 +35,7 @@ class DialogsStore {
defaultAccess: ShareAccessRights.FullAccess,
};
restoreAllPanelVisible = false;
restoreAllArchiveDialogVisible = false;
archiveDialogVisible = false;
eventDialogVisible = false;
removeItem = null;
@ -47,11 +47,13 @@ class DialogsStore {
conflictResolveDialogItems = null;
removeMediaItem = null;
unsubscribe = null;
isRoomDelete = false;
archiveAction = null;
convertItem = null;
formCreationInfo = null;
saveThirdpartyResponse = null;
inviteItems = [];
restoreAllArchive = false;
isConnectDialogReconnect = false;
saveAfterReconnectOAuth = false;
@ -71,8 +73,20 @@ class DialogsStore {
this.versionHistoryStore = versionHistoryStore;
}
setRestoreAllArchiveDialogVisible = (restoreAllArchiveDialogVisible) => {
this.restoreAllArchiveDialogVisible = restoreAllArchiveDialogVisible;
setIsRoomDelete = (isRoomDelete) => {
this.isRoomDelete = isRoomDelete;
};
setArchiveAction = (archiveAction) => {
this.archiveAction = archiveAction;
};
setRestoreAllArchive = (restoreAllArchive) => {
this.restoreAllArchive = restoreAllArchive;
};
setArchiveDialogVisible = (archiveDialogVisible) => {
this.archiveDialogVisible = archiveDialogVisible;
};
setSharingPanelVisible = (sharingPanelVisible) => {
@ -313,7 +327,7 @@ class DialogsStore {
this.versionHistoryStore.isVisible ||
this.eventDialogVisible ||
this.invitePanelOptions.visible ||
this.restoreAllArchiveDialogVisible ||
this.archiveDialogVisible ||
this.restoreAllPanelVisible ||
this.inviteUsersWarningDialogVisible
);

View File

@ -633,11 +633,11 @@ class FilesActionStore {
clearSecondaryProgressData,
} = secondaryProgressDataStore;
if (
(this.settingsStore.confirmDelete ||
this.treeFoldersStore.isPrivacyFolder ||
isThirdParty) &&
!isRoom
this.settingsStore.confirmDelete ||
this.treeFoldersStore.isPrivacyFolder ||
isThirdParty
) {
this.dialogsStore.setIsRoomDelete(isRoom);
this.dialogsStore.setDeleteDialogVisible(true);
} else {
setSecondaryProgressBarData({
@ -1358,28 +1358,11 @@ class FilesActionStore {
this.setPinAction("unpin", items);
};
moveRoomsToArchive = (t) => {
const { selection } = this.filesStore;
archiveRooms = (action) => {
const { setArchiveAction, setArchiveDialogVisible } = this.dialogsStore;
const items = [];
selection.forEach((item) => {
items.push(item);
});
this.setArchiveAction("archive", items, t);
};
moveRoomsFromArchive = (t) => {
const { selection } = this.filesStore;
const items = [];
selection.forEach((item) => {
items.push(item);
});
this.setArchiveAction("unarchive", items, t);
setArchiveAction(action);
setArchiveDialogVisible(true);
};
deleteRooms = (t) => {
@ -1402,6 +1385,44 @@ class FilesActionStore {
this.deleteItemAction(items, translations, null, null, true);
};
deleteRoomsAction = async (itemId, translations) => {
const {
secondaryProgressDataStore,
clearActiveOperations,
} = this.uploadDataStore;
const {
setSecondaryProgressBarData,
clearSecondaryProgressData,
} = secondaryProgressDataStore;
setSecondaryProgressBarData({
icon: "trash",
visible: true,
percent: 0,
label: translations?.deleteOperation,
alert: false,
});
try {
await this.deleteItemOperation(false, itemId, translations, true);
const id = Array.isArray(itemId) ? itemId : [itemId];
clearActiveOperations(null, id);
} catch (err) {
console.log(err);
clearActiveOperations(null, [itemId]);
setSecondaryProgressBarData({
visible: true,
alert: true,
});
setTimeout(() => clearSecondaryProgressData(), TIMEOUT);
onClose();
return toastr.error(err.message ? err.message : err);
}
};
onShowInfoPanel = () => {
const { selection } = this.filesStore;
const { setSelection, setIsVisible } = this.authStore.infoPanelStore;
@ -1490,7 +1511,7 @@ class FilesActionStore {
key: "archive",
label: t("Archived"),
iconUrl: "/static/images/room.archive.svg",
onClick: () => this.moveRoomsToArchive(t),
onClick: () => this.archiveRooms("archive"),
disabled: false,
};
case "unarchive":
@ -1500,7 +1521,7 @@ class FilesActionStore {
key: "unarchive",
label: t("Common:Restore"),
iconUrl: "images/subtract.react.svg",
onClick: () => this.moveRoomsFromArchive(t),
onClick: () => this.archiveRooms("unarchive"),
disabled: false,
};
case "delete-room":

View File

@ -203,6 +203,7 @@
"Video": "Video",
"View": "View",
"ViewWeb": "View web version",
"WantToContinue": "Are you sure you want to continue?",
"Warning": "Warning",
"Website": "Website",
"Hotkeys": "Hotkeys",

View File

@ -59,6 +59,9 @@ public class PortalController : ControllerBase
private readonly MessageService _messageService;
private readonly MessageTarget _messageTarget;
private readonly DisplayUserSettingsHelper _displayUserSettingsHelper;
private readonly EmailValidationKeyProvider _emailValidationKeyProvider;
private readonly StudioSmsNotificationSettingsHelper _studioSmsNotificationSettingsHelper;
private readonly TfaAppAuthSettingsHelper _tfaAppAuthSettingsHelper;
public PortalController(
ILogger<PortalController> logger,
@ -86,8 +89,9 @@ public class PortalController : ControllerBase
StudioNotifyService studioNotifyService,
MessageService messageService,
MessageTarget messageTarget,
DisplayUserSettingsHelper displayUserSettingsHelper
)
DisplayUserSettingsHelper displayUserSettingsHelper,
EmailValidationKeyProvider emailValidationKeyProvider,
StudioSmsNotificationSettingsHelper studioSmsNotificationSettingsHelper, TfaAppAuthSettingsHelper tfaAppAuthSettingsHelper)
{
_log = logger;
_apiContext = apiContext;
@ -115,6 +119,9 @@ public class PortalController : ControllerBase
_messageService = messageService;
_messageTarget = messageTarget;
_displayUserSettingsHelper = displayUserSettingsHelper;
_emailValidationKeyProvider = emailValidationKeyProvider;
_studioSmsNotificationSettingsHelper = studioSmsNotificationSettingsHelper;
_tfaAppAuthSettingsHelper = tfaAppAuthSettingsHelper;
}
[HttpGet("")]
@ -484,5 +491,37 @@ public class PortalController : ControllerBase
_studioNotifyService.SendMsgPortalDeletionSuccess(owner, redirectLink);
return redirectLink;
}
[AllowAnonymous]
[HttpPost("sendcongratulations")]
public void SendCongratulations([FromQuery] SendCongratulationsDto inDto)
{
var authInterval = TimeSpan.FromHours(1);
var checkKeyResult = _emailValidationKeyProvider.ValidateEmailKey(inDto.Userid.ToString() + ConfirmType.Auth, inDto.Key, authInterval);
switch (checkKeyResult)
{
case ValidationResult.Ok:
var currentUser = _userManager.GetUsers(inDto.Userid);
_studioNotifyService.SendCongratulations(currentUser);
_studioNotifyService.SendRegData(currentUser);
if (!SetupInfo.IsSecretEmail(currentUser.Email))
{
if (_setupInfo.TfaRegistration == "sms")
{
_studioSmsNotificationSettingsHelper.Enable = true;
}
else if (_setupInfo.TfaRegistration == "code")
{
_tfaAppAuthSettingsHelper.Enable = true;
}
}
break;
default:
throw new SecurityException("Access Denied.");
}
}
}

View File

@ -0,0 +1,33 @@
// (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.Web.Api.ApiModels.RequestsDto;
public class SendCongratulationsDto
{
public Guid Userid { get; set; }
public string Key { get; set; }
}