Merge branch 'paullessing-issue-3655-allowed-domains-save-no-change'

This commit is contained in:
Tom Moor
2022-07-16 00:38:28 +01:00
3 changed files with 74 additions and 48 deletions

View File

@@ -36,9 +36,17 @@ function Security() {
defaultUserRole: team.defaultUserRole, defaultUserRole: team.defaultUserRole,
memberCollectionCreate: team.memberCollectionCreate, memberCollectionCreate: team.memberCollectionCreate,
inviteRequired: team.inviteRequired, inviteRequired: team.inviteRequired,
allowedDomains: team.allowedDomains,
}); });
const [allowedDomains, setAllowedDomains] = useState([
...(team.allowedDomains ?? []),
]);
const [lastKnownDomainCount, updateLastKnownDomainCount] = useState(
allowedDomains.length
);
const [existingDomainsTouched, setExistingDomainsTouched] = useState(false);
const authenticationMethods = team.signinMethods; const authenticationMethods = team.signinMethods;
const showSuccessMessage = React.useMemo( const showSuccessMessage = React.useMemo(
@@ -51,17 +59,13 @@ function Security() {
[showToast, t] [showToast, t]
); );
const [domainsChanged, setDomainsChanged] = useState(false);
const saveData = React.useCallback( const saveData = React.useCallback(
async (newData) => { async (newData) => {
try { try {
setData(newData); setData(newData);
await auth.updateTeam(newData); await auth.updateTeam(newData);
showSuccessMessage(); showSuccessMessage();
setDomainsChanged(false);
} catch (err) { } catch (err) {
setDomainsChanged(true);
showToast(err.message, { showToast(err.message, {
type: "error", type: "error",
}); });
@@ -77,6 +81,21 @@ function Security() {
[data, saveData] [data, saveData]
); );
const handleSaveDomains = React.useCallback(async () => {
try {
await auth.updateTeam({
allowedDomains,
});
showSuccessMessage();
setExistingDomainsTouched(false);
updateLastKnownDomainCount(allowedDomains.length);
} catch (err) {
showToast(err.message, {
type: "error",
});
}
}, [auth, allowedDomains, showSuccessMessage, showToast]);
const handleDefaultRoleChange = React.useCallback( const handleDefaultRoleChange = React.useCallback(
async (newDefaultRole: string) => { async (newDefaultRole: string) => {
await saveData({ ...data, defaultUserRole: newDefaultRole }); await saveData({ ...data, defaultUserRole: newDefaultRole });
@@ -123,34 +142,41 @@ function Security() {
); );
const handleRemoveDomain = async (index: number) => { const handleRemoveDomain = async (index: number) => {
const newData = { const newDomains = allowedDomains.filter((_, i) => index !== i);
...data,
};
newData.allowedDomains && newData.allowedDomains.splice(index, 1);
setData(newData); setAllowedDomains(newDomains);
setDomainsChanged(true);
const touchedExistingDomain = index < lastKnownDomainCount;
if (touchedExistingDomain) {
setExistingDomainsTouched(true);
}
}; };
const handleAddDomain = () => { const handleAddDomain = () => {
const newData = { const newDomains = [...allowedDomains, ""];
...data,
allowedDomains: [...(data.allowedDomains || []), ""],
};
setData(newData); setAllowedDomains(newDomains);
}; };
const createOnDomainChangedHandler = (index: number) => ( const createOnDomainChangedHandler = (index: number) => (
ev: React.ChangeEvent<HTMLInputElement> ev: React.ChangeEvent<HTMLInputElement>
) => { ) => {
const newData = { ...data }; const newDomains = allowedDomains.slice();
newData.allowedDomains![index] = ev.currentTarget.value; newDomains[index] = ev.currentTarget.value;
setData(newData); setAllowedDomains(newDomains);
setDomainsChanged(true);
const touchedExistingDomain = index < lastKnownDomainCount;
if (touchedExistingDomain) {
setExistingDomainsTouched(true);
}
}; };
const showSaveChanges =
existingDomainsTouched ||
allowedDomains.filter((value: string) => value !== "").length > // New domains were added
lastKnownDomainCount;
return ( return (
<Scene title={t("Security")} icon={<PadlockIcon color="currentColor" />}> <Scene title={t("Security")} icon={<PadlockIcon color="currentColor" />}>
<Heading>{t("Security")}</Heading> <Heading>{t("Security")}</Heading>
@@ -264,35 +290,34 @@ function Security() {
"The domains which should be allowed to create new accounts using SSO. Changing this setting does not affect existing user accounts." "The domains which should be allowed to create new accounts using SSO. Changing this setting does not affect existing user accounts."
)} )}
> >
{data.allowedDomains && {allowedDomains.map((domain, index) => (
data.allowedDomains.map((domain, index) => ( <Flex key={index} gap={4}>
<Flex key={index} gap={4}> <Input
<Input key={index}
key={index} id={`allowedDomains${index}`}
id={`allowedDomains${index}`} value={domain}
value={domain} autoFocus={!domain}
autoFocus={!domain} placeholder="example.com"
placeholder="example.com" required
required flex
flex onChange={createOnDomainChangedHandler(index)}
onChange={createOnDomainChangedHandler(index)} />
/> <Remove>
<Remove> <Tooltip tooltip={t("Remove domain")} placement="top">
<Tooltip tooltip={t("Remove domain")} placement="top"> <NudeButton onClick={() => handleRemoveDomain(index)}>
<NudeButton onClick={() => handleRemoveDomain(index)}> <CloseIcon />
<CloseIcon /> </NudeButton>
</NudeButton> </Tooltip>
</Tooltip> </Remove>
</Remove> </Flex>
</Flex> ))}
))}
<Flex justify="space-between" gap={4} style={{ flexWrap: "wrap" }}> <Flex justify="space-between" gap={4} style={{ flexWrap: "wrap" }}>
{!data.allowedDomains?.length || {!allowedDomains.length ||
data.allowedDomains[data.allowedDomains.length - 1] !== "" ? ( allowedDomains[allowedDomains.length - 1] !== "" ? (
<Fade> <Fade>
<Button type="button" onClick={handleAddDomain} neutral> <Button type="button" onClick={handleAddDomain} neutral>
{data.allowedDomains?.length ? ( {allowedDomains.length ? (
<Trans>Add another</Trans> <Trans>Add another</Trans>
) : ( ) : (
<Trans>Add a domain</Trans> <Trans>Add a domain</Trans>
@@ -303,11 +328,11 @@ function Security() {
<span /> <span />
)} )}
{domainsChanged && ( {showSaveChanges && (
<Fade> <Fade>
<Button <Button
type="button" type="button"
onClick={handleChange} onClick={handleSaveDomains}
disabled={auth.isSaving} disabled={auth.isSaving}
> >
<Trans>Save changes</Trans> <Trans>Save changes</Trans>

View File

@@ -237,6 +237,7 @@ export default class AuthStore {
collaborativeEditing?: boolean; collaborativeEditing?: boolean;
defaultCollectionId?: string | null; defaultCollectionId?: string | null;
subdomain?: string | null | undefined; subdomain?: string | null | undefined;
allowedDomains?: string[] | null | undefined;
}) => { }) => {
this.isSaving = true; this.isSaving = true;

View File

@@ -670,7 +670,7 @@
"Delete account": "Delete account", "Delete account": "Delete account",
"Are you sure you want to require invites?": "Are you sure you want to require invites?", "Are you sure you want to require invites?": "Are you sure you want to require invites?",
"Im sure": "Im sure", "Im sure": "Im sure",
"New users will first need to be invited to create an account using <em>{{ authenticationMethods }}</em>. <em>Default role</em> and <em>Allowed domains</em> will no longer apply.": "New users will first need to be invited to create an account using <em>{{ authenticationMethods }}</em>. <em>Default role</em> and <em>Allowed domains</em> will no longer apply.", "New users will first need to be invited to create an account. <em>Default role</em> and <em>Allowed domains</em> will no longer apply.": "New users will first need to be invited to create an account. <em>Default role</em> and <em>Allowed domains</em> will no longer apply.",
"Settings that impact the access, security, and content of your knowledge base.": "Settings that impact the access, security, and content of your knowledge base.", "Settings that impact the access, security, and content of your knowledge base.": "Settings that impact the access, security, and content of your knowledge base.",
"Allow email authentication": "Allow email authentication", "Allow email authentication": "Allow email authentication",
"When enabled, users can sign-in using their email address": "When enabled, users can sign-in using their email address", "When enabled, users can sign-in using their email address": "When enabled, users can sign-in using their email address",