1 import { c } from 'ttag';
3 import DropdownActions from '@proton/components/components/dropdown/DropdownActions';
4 import { useLoading } from '@proton/hooks';
5 import type { APP_NAMES } from '@proton/shared/lib/constants';
6 import { APPS, MEMBER_PRIVATE, MEMBER_TYPE, ORGANIZATION_STATE } from '@proton/shared/lib/constants';
7 import { hasOrganizationSetup, hasOrganizationSetupWithKeys } from '@proton/shared/lib/helpers/organization';
15 } from '@proton/shared/lib/interfaces';
16 import { MemberUnprivatizationState } from '@proton/shared/lib/interfaces';
17 import { getCanGenerateMemberKeysPermissions, getShouldSetupMemberKeys } from '@proton/shared/lib/keys/memberKeys';
18 import isTruthy from '@proton/utils/isTruthy';
20 export const MagicLinkMemberActions = ({
26 state?: MemberUnprivatizationState;
27 onResend?: () => void;
28 onDelete?: () => Promise<void>;
31 const [loadingDelete, withLoadingDelete] = useLoading();
37 text: c('Member action').t`Edit`,
38 onClick: () => onEdit(),
41 text: c('Member action').t`Resend invite link`,
42 onClick: () => onResend(),
45 actionType: 'delete' as const,
47 state === MemberUnprivatizationState.Pending
48 ? c('Member action').t`Delete and revoke invite`
49 : c('Member action').t`Delete`,
50 loading: loadingDelete,
51 onClick: () => withLoadingDelete(onDelete()),
59 export const getMemberPermissions = ({
68 addresses: PartialMemberAddress[] | undefined;
72 organization?: Organization;
73 organizationKey?: CachedOrganizationKey;
74 disableMemberSignIn: boolean;
76 const hasSetupOrganizationWithKeys = hasOrganizationSetupWithKeys(organization);
77 const hasSetupOrganization = hasOrganizationSetup(organization);
78 const isOrganizationDelinquent = organization?.State === ORGANIZATION_STATE.DELINQUENT;
80 const canDelete = !member.Self;
81 const canEdit = hasSetupOrganization || hasSetupOrganizationWithKeys;
82 const canRevokeSessions = !member.Self && member.Type === MEMBER_TYPE.MANAGED;
84 const hasUnprivatization = Boolean(member.Unprivatization);
86 const canSetupMember =
87 !hasUnprivatization &&
88 getCanGenerateMemberKeysPermissions(user, organizationKey) &&
89 getShouldSetupMemberKeys(member) &&
93 !disableMemberSignIn &&
94 appName !== APPS.PROTONVPN_SETTINGS &&
95 hasSetupOrganizationWithKeys &&
97 member.Private === MEMBER_PRIVATE.READABLE &&
98 member.Keys.length > 0 &&
99 !!organizationKey?.privateKey &&
101 addresses?.length > 0;
103 const canChangePassword =
104 hasSetupOrganizationWithKeys &&
106 member.Private === MEMBER_PRIVATE.READABLE &&
107 member.Keys.length > 0 &&
108 !!organizationKey?.privateKey &&
110 addresses.length > 0;
112 const canAddAddress = !member.SSO && addresses && addresses.length === 0;
122 isOrganizationDelinquent,
127 member: EnhancedMember;
128 onLogin: (member: EnhancedMember) => void;
129 onAddAddress: (member: EnhancedMember) => void;
130 onChangePassword: (member: EnhancedMember) => void;
131 onEdit: (member: EnhancedMember) => void;
132 onDelete: (member: EnhancedMember) => void;
133 onRevoke: (member: EnhancedMember) => Promise<void>;
134 onSetup: (member: EnhancedMember) => void;
135 permissions: ReturnType<typeof getMemberPermissions>;
136 disableEdit: boolean;
139 const MemberActions = ({
157 isOrganizationDelinquent,
160 const [loading, withLoading] = useLoading();
164 text: c('Member action').t`Edit`,
165 disabled: isOrganizationDelinquent || disableEdit,
171 text: c('Member action').t`Sign in`,
172 disabled: isOrganizationDelinquent,
178 text: c('Member action').t`Add address`,
179 disabled: isOrganizationDelinquent,
181 onAddAddress(member);
185 text: c('Member action').t`Activate user`,
186 disabled: isOrganizationDelinquent,
191 canChangePassword && {
192 text: c('Member action').t`Change password`,
193 disabled: isOrganizationDelinquent,
195 onChangePassword(member);
198 canRevokeSessions && {
199 text: c('Member action').t`Revoke sessions`,
200 disabled: isOrganizationDelinquent,
202 void withLoading(onRevoke(member));
207 text: canRevokeSessions ? c('Member action').t`Delete` : c('Member action').t`Remove`,
208 actionType: 'delete',
215 return <DropdownActions loading={loading} list={list} size="small" />;
218 export default MemberActions;