Merge branch 'issue-3655-allowed-domains-save-no-change' of github.com:paullessing/outline into paullessing-issue-3655-allowed-domains-save-no-change
This commit is contained in:
@@ -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,8 +290,7 @@ 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}
|
||||||
@@ -288,11 +313,11 @@ function Security() {
|
|||||||
))}
|
))}
|
||||||
|
|
||||||
<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>
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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?",
|
||||||
"I’m sure": "I’m sure",
|
"I’m sure": "I’m 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",
|
||||||
|
|||||||
Reference in New Issue
Block a user