diff --git a/packages/services/src/Domain/SharedVaults/SharedVaultServiceInterface.ts b/packages/services/src/Domain/SharedVaults/SharedVaultServiceInterface.ts index 2127698cd..e61c55a8f 100644 --- a/packages/services/src/Domain/SharedVaults/SharedVaultServiceInterface.ts +++ b/packages/services/src/Domain/SharedVaults/SharedVaultServiceInterface.ts @@ -5,6 +5,8 @@ import { SharedVaultListingInterface, VaultListingInterface, KeySystemRootKeyStorageMode, + EmojiString, + IconType, } from '@standardnotes/models' import { AbstractService } from '../Service/AbstractService' import { SharedVaultServiceEvent, SharedVaultServiceEventPayload } from './SharedVaultServiceEvent' @@ -14,6 +16,7 @@ export interface SharedVaultServiceInterface createSharedVault(dto: { name: string description?: string + iconString: IconType | EmojiString userInputtedPassword: string | undefined storagePreference?: KeySystemRootKeyStorageMode }): Promise diff --git a/packages/services/src/Domain/VaultUser/VaultUserService.ts b/packages/services/src/Domain/VaultUser/VaultUserService.ts index 3cd2571e8..6e6237b90 100644 --- a/packages/services/src/Domain/VaultUser/VaultUserService.ts +++ b/packages/services/src/Domain/VaultUser/VaultUserService.ts @@ -51,12 +51,12 @@ export class VaultUserService extends AbstractService imp return result.getValue() } - public isCurrentUserSharedVaultAdmin(sharedVault: SharedVaultListingInterface): boolean { + public isCurrentUserSharedVaultOwner(sharedVault: SharedVaultListingInterface): boolean { return this._isVaultOwner.execute(sharedVault).getValue() } async removeUserFromSharedVault(sharedVault: SharedVaultListingInterface, userUuid: string): Promise> { - if (!this.isCurrentUserSharedVaultAdmin(sharedVault)) { + if (!this.isCurrentUserSharedVaultOwner(sharedVault)) { throw new Error('Only vault admins can remove users') } diff --git a/packages/services/src/Domain/VaultUser/VaultUserServiceInterface.ts b/packages/services/src/Domain/VaultUser/VaultUserServiceInterface.ts index c514f1fb1..e4f3e7281 100644 --- a/packages/services/src/Domain/VaultUser/VaultUserServiceInterface.ts +++ b/packages/services/src/Domain/VaultUser/VaultUserServiceInterface.ts @@ -6,7 +6,7 @@ import { Result } from '@standardnotes/domain-core' export interface VaultUserServiceInterface extends ApplicationServiceInterface { getSharedVaultUsers(sharedVault: SharedVaultListingInterface): Promise - isCurrentUserSharedVaultAdmin(sharedVault: SharedVaultListingInterface): boolean + isCurrentUserSharedVaultOwner(sharedVault: SharedVaultListingInterface): boolean removeUserFromSharedVault(sharedVault: SharedVaultListingInterface, userUuid: string): Promise> leaveSharedVault(sharedVault: SharedVaultListingInterface): Promise isVaultUserOwner(user: SharedVaultUserServerHash): boolean diff --git a/packages/web/src/javascripts/Components/Preferences/Panes/Vaults/Vaults.tsx b/packages/web/src/javascripts/Components/Preferences/Panes/Vaults/Vaults.tsx index c40fe49f6..953ab00a5 100644 --- a/packages/web/src/javascripts/Components/Preferences/Panes/Vaults/Vaults.tsx +++ b/packages/web/src/javascripts/Components/Preferences/Panes/Vaults/Vaults.tsx @@ -37,8 +37,12 @@ const Vaults = () => { const [isAddContactModalOpen, setIsAddContactModalOpen] = useState(false) const closeAddContactModal = () => setIsAddContactModalOpen(false) + const [isCreatingSharedVault, setIsCreatingSharedVault] = useState(false) const [isVaultModalOpen, setIsVaultModalOpen] = useState(false) - const closeVaultModal = () => setIsVaultModalOpen(false) + const closeVaultModal = () => { + setIsVaultModalOpen(false) + setIsCreatingSharedVault(false) + } const vaultService = application.vaults const contactService = application.contacts @@ -46,17 +50,20 @@ const Vaults = () => { const updateVaults = useCallback(async () => { const vaults = vaultService.getVaults() + const ownedVaults = vaults.filter((vault) => { + return !vault.isSharedVaultListing() ? true : application.vaultUsers.isCurrentUserSharedVaultOwner(vault) + }) if (featuresService.hasMinimumRole(RoleName.NAMES.ProUser)) { setCanCreateMoreVaults(true) } else if (featuresService.hasMinimumRole(RoleName.NAMES.PlusUser)) { - setCanCreateMoreVaults(vaults.length < 3) + setCanCreateMoreVaults(ownedVaults.length < 3) } else { - setCanCreateMoreVaults(vaults.length < 1) + setCanCreateMoreVaults(ownedVaults.length < 1) } setVaults(vaults) - }, [vaultService, featuresService]) + }, [vaultService, featuresService, application.vaultUsers]) const updateInvites = useCallback(async () => { setInvites(application.vaultInvites.getCachedPendingInviteRecords()) @@ -115,6 +122,11 @@ const Vaults = () => { setIsVaultModalOpen(true) }, []) + const createNewSharedVault = useCallback(async () => { + setIsCreatingSharedVault(true) + setIsVaultModalOpen(true) + }, []) + const createNewContact = useCallback(() => { setIsAddContactModalOpen(true) }, []) @@ -125,7 +137,11 @@ const Vaults = () => { - + {invites.length > 0 && ( @@ -169,8 +185,9 @@ const Vaults = () => { )} {canCreateMoreVaults ? ( -
-
) : (
diff --git a/packages/web/src/javascripts/Components/Preferences/Panes/Vaults/Vaults/VaultModal/EditVaultModal.tsx b/packages/web/src/javascripts/Components/Preferences/Panes/Vaults/Vaults/VaultModal/EditVaultModal.tsx index f1df6da79..6a805ab16 100644 --- a/packages/web/src/javascripts/Components/Preferences/Panes/Vaults/Vaults/VaultModal/EditVaultModal.tsx +++ b/packages/web/src/javascripts/Components/Preferences/Panes/Vaults/Vaults/VaultModal/EditVaultModal.tsx @@ -28,8 +28,9 @@ import Spinner from '@/Components/Spinner/Spinner' const EditVaultModalContent: FunctionComponent<{ existingVaultUuid?: string + creatingSharedVault?: boolean onCloseDialog: () => void -}> = ({ onCloseDialog, existingVaultUuid }) => { +}> = ({ onCloseDialog, existingVaultUuid, creatingSharedVault }) => { const application = useApplication() const existingVault = useItem(existingVaultUuid) @@ -65,7 +66,7 @@ const EditVaultModalContent: FunctionComponent<{ if (existingVault.isSharedVaultListing()) { setIsAdmin( - existingVault.isSharedVaultListing() && application.vaultUsers.isCurrentUserSharedVaultAdmin(existingVault), + existingVault.isSharedVaultListing() && application.vaultUsers.isCurrentUserSharedVaultOwner(existingVault), ) setIsLoadingCollaborationInfo(true) @@ -160,12 +161,30 @@ const EditVaultModalContent: FunctionComponent<{ if (!customPassword) { throw new Error('Custom key is not set') } - await application.vaults.createUserInputtedPasswordVault({ + if (creatingSharedVault) { + await application.sharedVaults.createSharedVault({ + name, + description, + iconString: iconString, + storagePreference: keyStorageMode, + userInputtedPassword: customPassword, + }) + } else { + await application.vaults.createUserInputtedPasswordVault({ + name, + description, + iconString: iconString, + storagePreference: keyStorageMode, + userInputtedPassword: customPassword, + }) + } + } else if (creatingSharedVault) { + await application.sharedVaults.createSharedVault({ name, description, iconString: iconString, storagePreference: keyStorageMode, - userInputtedPassword: customPassword, + userInputtedPassword: undefined, }) } else { await application.vaults.createRandomizedVault({ @@ -177,7 +196,9 @@ const EditVaultModalContent: FunctionComponent<{ handleDialogClose() }, [ + application.sharedVaults, application.vaults, + creatingSharedVault, customPassword, description, handleDialogClose, @@ -203,7 +224,7 @@ const EditVaultModalContent: FunctionComponent<{ const modalActions = useMemo( (): ModalAction[] => [ { - label: existingVault ? 'Save Vault' : 'Create Vault', + label: existingVault ? 'Save Vault' : creatingSharedVault ? 'Create Shared Vault' : 'Create Vault', onClick: handleSubmit, type: 'primary', mobileSlot: 'right', @@ -216,7 +237,7 @@ const EditVaultModalContent: FunctionComponent<{ mobileSlot: 'left', }, ], - [existingVault, handleDialogClose, handleSubmit, isSubmitting], + [creatingSharedVault, existingVault, handleDialogClose, handleSubmit, isSubmitting], ) const [shouldShowIconPicker, setShouldShowIconPicker] = useState(false) @@ -334,14 +355,20 @@ const EditVaultModal = ({ isVaultModalOpen, closeVaultModal, vault, + creatingSharedVault, }: { isVaultModalOpen: boolean closeVaultModal: () => void vault?: VaultListingInterface + creatingSharedVault?: boolean }) => { return ( - + ) } diff --git a/packages/web/src/javascripts/Hooks/useVault.ts b/packages/web/src/javascripts/Hooks/useVault.ts index b7c724c76..7ee024abf 100644 --- a/packages/web/src/javascripts/Hooks/useVault.ts +++ b/packages/web/src/javascripts/Hooks/useVault.ts @@ -38,7 +38,7 @@ export const useVault = (vault: VaultListingInterface) => { const isCurrentUserAdmin = !vault.isSharedVaultListing() ? true - : application.vaultUsers.isCurrentUserSharedVaultAdmin(vault) + : application.vaultUsers.isCurrentUserSharedVaultOwner(vault) const ensureVaultIsUnlocked = useCallback(async () => { if (!application.vaultLocks.isVaultLocked(vault)) {