feat: Add disconnect button on auth config pages and form login callout banner (#11389)

* added form login callout banner

* form login config page changes

* form login config page changes

* added redirecturl and uneditable field components

* added disconnect button on auth pages

* Added env variables for form login auth page

* added disconnect button on auth pages

* updated docs link for dform login callout doc

* added condition for disconnect button

* added ce changes done on ee

* updated css

* suggested changes in PR review

* suggested changes in PR review

* suggested changes in PR review

* reverted gitignore files changes

* reverted gitignore files changes

* updated logic for saving admin settings

* removed unused imports

* added changes for taginput field

* removed console

* removed warning

* removed unwanted changes
This commit is contained in:
Ankita Kinger 2022-03-02 23:48:50 +05:30 committed by GitHub
parent 18104b9291
commit 13fe125a0c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 569 additions and 35 deletions

View File

@ -15,6 +15,10 @@ APPSMITH_OAUTH2_GOOGLE_CLIENT_SECRET=
APPSMITH_OAUTH2_GITHUB_CLIENT_ID=
APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET=
# Form Login/Signup
APPSMITH_FORM_LOGIN_DISABLED=
APPSMITH_SIGNUP_DISABLED=
# Segment
APPSMITH_SEGMENT_KEY=

View File

@ -71,8 +71,12 @@ export const getConfigsFromEnvVars = (): INJECTED_CONFIGS => {
enableGithubOAuth: process.env.REACT_APP_OAUTH2_GITHUB_CLIENT_ID
? process.env.REACT_APP_OAUTH2_GITHUB_CLIENT_ID.length > 0
: false,
disableLoginForm: !!process.env.APPSMITH_FORM_LOGIN_DISABLED,
disableSignup: !!process.env.APPSMITH_SIGNUP_DISABLED,
disableLoginForm: process.env.APPSMITH_FORM_LOGIN_DISABLED
? process.env.APPSMITH_FORM_LOGIN_DISABLED.length > 0
: false,
disableSignup: process.env.APPSMITH_SIGNUP_DISABLED
? process.env.APPSMITH_SIGNUP_DISABLED.length > 0
: false,
segment: {
apiKey: process.env.REACT_APP_SEGMENT_KEY || "",
ceKey: process.env.REACT_APP_SEGMENT_CE_KEY || "",

View File

@ -633,6 +633,11 @@ export const CANNOT_PULL_WITH_LOCAL_UNCOMMITTED_CHANGES = () =>
export const CANNOT_MERGE_DUE_TO_UNCOMMITTED_CHANGES = () =>
"Your current branch has uncommitted changes. Please commit before proceeding to merge";
export const DISCONNECT_SERVICE_SUBHEADER = () =>
"Changes to this section can disrupt user authentication. Proceed with caution.";
export const DISCONNECT_SERVICE_WARNING = () =>
"will be removed as primary method of authentication";
export const DISCONNECT_EXISTING_REPOSITORIES = () =>
"Disconnect existing Repositories";
export const DISCONNECT_EXISTING_REPOSITORIES_INFO = () =>
@ -1034,3 +1039,6 @@ export const CONTEXT_DELETE = () => "Delete";
export const CONTEXT_NO_PAGE = () => "No pages";
export const IMAGE_LOAD_ERROR = () => "Unable to display the image";
export const REDIRECT_URL_TOOLTIP = () =>
"This URL will be used while configuring your Identity Provider's Callback/Redirect URL";

View File

@ -2,6 +2,7 @@ import React from "react";
import {
GOOGLE_SIGNUP_SETUP_DOC,
GITHUB_SIGNUP_SETUP_DOC,
SIGNUP_RESTRICTION_DOC,
} from "constants/ThirdPartyConstants";
import {
SettingCategories,
@ -28,6 +29,7 @@ const Form_Auth: AdminConfigType = {
title: "Form Login",
subText: "Enable your organization to sign in with Appsmith Form.",
canSave: true,
isConnected: false,
settings: [
{
id: "APPSMITH_FORM_LOGIN_DISABLED",
@ -37,9 +39,9 @@ const Form_Auth: AdminConfigType = {
label: "Form Login Option",
toggleText: (value: boolean) => {
if (value) {
return "Enable form login/signup";
return "Disabled";
} else {
return " Disable form login/signup";
return " Enabled";
}
},
},
@ -51,12 +53,22 @@ const Form_Auth: AdminConfigType = {
label: "Signup",
toggleText: (value: boolean) => {
if (value) {
return "Allow invited users to signup";
return "Allow only invited users to signup";
} else {
return " Allow all users to signup";
}
},
},
{
id: "APPSMITH_FORM_CALLOUT_BANNER",
category: SettingCategories.FORM_AUTH,
subCategory: "form signup",
controlType: SettingTypes.LINK,
label:
"User emails are not verified. This can lead to a breach in your application.",
url: SIGNUP_RESTRICTION_DOC,
calloutType: "Warning",
},
],
};
@ -66,6 +78,7 @@ const Google_Auth: AdminConfigType = {
title: "Google Authentication",
subText: "Enable your organization to sign in with Google (OAuth).",
canSave: true,
isConnected: enableGoogleOAuth,
settings: [
{
id: "APPSMITH_OAUTH2_GOOGLE_READ_MORE",
@ -110,6 +123,7 @@ const Github_Auth: AdminConfigType = {
subText:
"Enable your organization to sign in with Github SAML single sign-on (SSO).",
canSave: true,
isConnected: enableGithubOAuth,
settings: [
{
id: "APPSMITH_OAUTH2_GITHUB_READ_MORE",

View File

@ -10,6 +10,9 @@ export enum SettingTypes {
GROUP = "GROUP",
TEXT = "TEXT",
PAGE = "PAGE",
UNEDITABLEFIELD = "UNEDITABLEFIELD",
ACCORDION = "ACCORDION",
TAGINPUT = "TAGINPUT",
}
export enum SettingSubtype {
@ -44,12 +47,15 @@ export interface Setting {
isVisible?: (values: Record<string, any>) => boolean;
isHidden?: boolean;
isDisabled?: (values: Record<string, any>) => boolean;
calloutType?: "Info" | "Warning";
advanced?: Setting[];
}
export interface Category {
title: string;
slug: string;
subText?: string;
isConnected?: boolean;
children?: Category[];
}
@ -74,4 +80,5 @@ export type AdminConfigType = {
component?: React.ElementType;
children?: AdminConfigType[];
canSave: boolean;
isConnected?: boolean;
};

View File

@ -0,0 +1,28 @@
import { getAppsmithConfigs } from "@appsmith/configs";
const {
disableLoginForm,
enableGithubOAuth,
enableGoogleOAuth,
} = getAppsmithConfigs();
export const connectedMethods = [
enableGoogleOAuth,
enableGithubOAuth,
!disableLoginForm,
].filter(Boolean);
export const saveAllowed = (settings: any) => {
if (
connectedMethods.length >= 2 ||
(connectedMethods.length === 1 &&
((!("APPSMITH_FORM_LOGIN_DISABLED" in settings) && !disableLoginForm) ||
(settings["APPSMITH_OAUTH2_GOOGLE_CLIENT_ID"] !== "" &&
enableGoogleOAuth) ||
(settings["APPSMITH_OAUTH2_GITHUB_CLIENT_ID"] !== "" &&
enableGithubOAuth)))
) {
return true;
} else {
return false;
}
};

View File

@ -8,6 +8,7 @@ import {
} from "@appsmith/constants/messages";
import { isEmail } from "utils/formhelpers";
import { Colors } from "constants/Colors";
const TagInputWrapper = styled.div<{ intent?: Intent }>`
margin-right: 8px;
@ -57,7 +58,7 @@ type TagInputProps = {
/** Intent of the tags, which defines their color */
intent?: Intent;
hasError?: boolean;
customError: (values: any) => void;
customError?: (values: any) => void;
};
/**
@ -89,9 +90,9 @@ function TagInputComponent(props: TagInputProps) {
error = createMessage(INVITE_USERS_VALIDATION_EMAIL_LIST);
}
});
props.customError(error);
props.customError?.(error);
} else {
props.customError("");
props.customError?.("");
}
};
@ -99,7 +100,7 @@ function TagInputComponent(props: TagInputProps) {
setValues(newValues);
props.input.onChange &&
props.input.onChange(newValues.filter(Boolean).join(","));
validateEmail(newValues);
props.type === "email" && validateEmail(newValues);
};
const onTagsChange = (values: React.ReactNode[]) => {

View File

@ -74,6 +74,7 @@ export type TextInputProps = CommonComponentProps & {
trimValue?: boolean;
$padding?: string;
useTextArea?: boolean;
isCopy?: boolean;
};
type boxReturnType = {

View File

@ -0,0 +1,107 @@
import React, { useEffect } from "react";
import { InjectedFormProps, reduxForm } from "redux-form";
import { HelpIcons } from "icons/HelpIcons";
import UneditableField from "components/ads/formFields/UneditableField";
import styled from "styled-components";
import copy from "copy-to-clipboard";
import { Toaster } from "components/ads/Toast";
import { Variant } from "components/ads/common";
import AnalyticsUtil from "utils/AnalyticsUtil";
import TooltipComponent from "../Tooltip";
import { Position } from "@blueprintjs/core";
import {
createMessage,
REDIRECT_URL_TOOLTIP,
} from "@appsmith/constants/messages";
const HelpIcon = HelpIcons.HELP_ICON;
const Wrapper = styled.div`
margin: 24px 0;
`;
export const BodyContainer = styled.div`
width: 100%;
padding: 0 0 16px;
`;
const HeaderWrapper = styled.div`
display: flex;
align-items: center;
margin-bottom: 8px;
.help-icon {
margin-left: 4px;
cursor: pointer;
svg {
border-radius: 50%;
border: 1px solid #858282;
padding: 1px;
}
}
`;
export const HeaderSecondary = styled.h3`
font-size: 20px;
font-style: normal;
font-weight: 500;
line-height: 24px;
letter-spacing: -0.23999999463558197px;
text-align: left;
`;
function RedirectUrlForm(
props: InjectedFormProps & { value: string; helpText?: string },
) {
useEffect(() => {
props.initialize({
"redirect-url-form": `${window.location.origin}${props.value}`,
});
}, []);
const handleCopy = (value: string) => {
copy(value);
Toaster.show({
text: "Redirect URL copied to clipboard",
variant: Variant.success,
});
AnalyticsUtil.logEvent("REDIRECT_URL_COPIED", { snippet: value });
};
return (
<Wrapper>
<HeaderWrapper>
<HeaderSecondary>Redirect URL</HeaderSecondary>
<TooltipComponent
autoFocus={false}
content={createMessage(REDIRECT_URL_TOOLTIP)}
hoverOpenDelay={1000}
minWidth={"180px"}
openOnTargetFocus={false}
position={Position.RIGHT}
>
<HelpIcon
className={"help-icon"}
color={"#858282"}
height={13}
width={13}
/>
</TooltipComponent>
</HeaderWrapper>
<BodyContainer>
<UneditableField
disabled
handleCopy={handleCopy}
helperText={props.helpText}
iscopy={"true"}
label={"URL"}
name={"redirect-url-form"}
/>
</BodyContainer>
</Wrapper>
);
}
export const RedirectUrlReduxForm = reduxForm<any, any>({
form: "Redirect URL",
touchOnBlur: true,
})(RedirectUrlForm);

View File

@ -0,0 +1,71 @@
import React from "react";
import {
Field,
WrappedFieldMetaProps,
WrappedFieldInputProps,
} from "redux-form";
import InputComponent, { InputType } from "../TextInput";
import { Intent } from "constants/DefaultTheme";
import { Colors } from "constants/Colors";
import styled from "styled-components";
import { ReactComponent as CopyIcon } from "assets/icons/menu/copy-snippet.svg";
const Label = styled.div`
font-size: 14px;
margin: 8px 0;
color: ${Colors.CHARCOAL};
`;
const InputCopyWrapper = styled.div`
display: flex;
align-items: center;
svg {
margin-left: 10px;
cursor: pointer;
}
`;
const renderComponent = (
componentProps: FormTextFieldProps & {
meta: Partial<WrappedFieldMetaProps>;
input: Partial<WrappedFieldInputProps>;
},
) => {
return (
<>
{componentProps.label && <Label>{componentProps.label}</Label>}
<InputCopyWrapper>
<InputComponent {...componentProps} {...componentProps.input} fill />
{componentProps.iscopy === "true" && (
<CopyIcon
height={16}
onClick={() =>
componentProps.handleCopy(componentProps.input.value)
}
width={16}
/>
)}
</InputCopyWrapper>
</>
);
};
export type FormTextFieldProps = {
name: string;
type?: InputType;
label?: string;
intent?: Intent;
disabled?: boolean;
autoFocus?: boolean;
value?: string;
helperText?: string;
iscopy?: string;
handleCopy: (value: string) => void;
};
function UneditableField(props: FormTextFieldProps) {
return <Field component={renderComponent} {...props} asyncControl />;
}
export default UneditableField;

View File

@ -15,3 +15,5 @@ export const GITHUB_SIGNUP_SETUP_DOC =
"https://docs.appsmith.com/setup/instance-configuration/github-login";
export const EMAIL_SETUP_DOC =
"https://docs.appsmith.com/setup/instance-configuration/email";
export const SIGNUP_RESTRICTION_DOC =
"https://docs.appsmith.com/setup/instance-configuration/disable-user-signup#disable-sign-up";

View File

@ -0,0 +1 @@
export * from "ce/utils/adminSettingsHelpers";

View File

@ -0,0 +1,86 @@
import React, { useState } from "react";
import styled from "styled-components";
import { Setting } from "@appsmith/pages/AdminSettings/config/types";
import { createMessage } from "@appsmith//constants/messages";
import { StyledLabel } from "./Common";
import Group from "./group";
import { Icon, IconSize } from "components/ads";
const AccordionWrapper = styled.div`
margin-top: 40px;
max-width: 634px;
`;
const AccordionHeader = styled(StyledLabel)`
text-transform: capitalize;
margin-bottom: ${(props) => props.theme.spaces[9]}px;
font-size: 20px;
font-weight: 500;
cursor: pointer;
display: flex;
justify-content: space-between;
align-items: center;
`;
const AccordionBody = styled.div`
& .hide {
display: none;
}
& .callout-link {
> div {
margin-top: 0px;
}
}
`;
const Line = styled.hr`
display: block;
height: 1px;
border: 0;
border-top: 1px solid #DFDFDF;
margin: 0 16px;
flex: 1 0 auto;
}
`;
type AccordionProps = {
label?: string;
settings?: Setting[];
isHidden?: boolean;
category?: string;
subCategory?: string;
};
export default function Accordion({
category,
label,
settings,
subCategory,
}: AccordionProps) {
const [isOpen, setIsOpen] = useState(false);
return (
<AccordionWrapper>
{label && (
<AccordionHeader onClick={() => setIsOpen(!isOpen)}>
<span>{createMessage(() => label)}</span>
<Line />
<Icon
name={isOpen ? "expand-less" : "expand-more"}
size={IconSize.XXL}
/>
</AccordionHeader>
)}
{isOpen && (
<AccordionBody>
<Group
category={category}
settings={settings}
subCategory={subCategory}
/>
</AccordionBody>
)}
</AccordionWrapper>
);
}

View File

@ -18,7 +18,7 @@ const StyledIcon = styled(Icon)`
`;
export const StyledFormGroup = styled.div`
width: 634px;
width: 40rem;
margin-bottom: ${(props) => props.theme.spaces[7]}px;
& span.bp3-popover-target {
display: inline-block;

View File

@ -0,0 +1,44 @@
import React from "react";
import {
Field,
WrappedFieldMetaProps,
WrappedFieldInputProps,
} from "redux-form";
import TagInputComponent from "components/ads/TagInputComponent";
import { FormGroup } from "./Common";
import { Intent } from "constants/DefaultTheme";
import { Setting } from "@appsmith/pages/AdminSettings/config/types";
const renderComponent = (
componentProps: TagListFieldProps & {
meta: Partial<WrappedFieldMetaProps>;
input: Partial<WrappedFieldInputProps>;
},
) => {
const setting = componentProps.setting;
return (
<FormGroup
className={`t--admin-settings-tag-input t--admin-settings-${setting.name ||
setting.id}`}
setting={setting}
>
<TagInputComponent {...componentProps} />
</FormGroup>
);
};
type TagListFieldProps = {
name: string;
placeholder: string;
type: string;
label?: string;
intent: Intent;
setting: Setting;
customError?: (err: string) => void;
};
function TagInputField(props: TagListFieldProps) {
return <Field component={renderComponent} {...props} />;
}
export default TagInputField;

View File

@ -10,7 +10,7 @@ export default function TextInput({ setting }: SettingComponentProps) {
setting={setting}
>
<FormTextField
name={setting.name || ""}
name={setting.name || setting.id || ""}
placeholder={createMessage(() => setting.placeholder || "")}
type={setting.controlSubType}
/>

View File

@ -14,6 +14,11 @@ import { SETTINGS_FORM_NAME } from "constants/forms";
import { useSelector } from "store";
import { createMessage } from "@appsmith/constants/messages";
import { Callout } from "components/ads/CalloutV2";
import { RedirectUrlReduxForm } from "components/ads/formFields/RedirectUrlForm";
import Accordion from "./Accordion";
import TagInputField from "./TagInputField";
import { Classes } from "@blueprintjs/core";
import { Colors } from "constants/Colors";
type GroupProps = {
name?: string;
@ -43,11 +48,33 @@ const GroupBody = styled.div`
display: none;
}
& .callout-link {
max-width: 634px;
> div {
margin-top: 0px;
}
}
& .tag-input {
.t--admin-settings-tag-input {
label {
+ div {
margin: 0;
}
}
.${Classes.TAG_INPUT}, .${Classes.TAG_INPUT}.${Classes.ACTIVE} {
border: 1.2px solid ${Colors.ALTO2};
box-shadow: none;
.bp3-tag {
background: #f8f8f8;
color: #000;
svg:hover {
cursor: pointer;
path {
fill: currentColor;
}
}
}
}
}
}
`;
const formValuesSelector = getFormValues(SETTINGS_FORM_NAME);
@ -79,7 +106,7 @@ export default function Group({
<div
className={setting.isHidden ? "hide" : ""}
data-testid="admin-settings-group-text-input"
key={setting.name}
key={setting.name || setting.id}
>
<TextInput setting={setting} />
</div>
@ -89,7 +116,7 @@ export default function Group({
<div
className={setting.isHidden ? "hide" : ""}
data-testid="admin-settings-group-toggle"
key={setting.name}
key={setting.name || setting.id}
>
<Toggle setting={setting} />
</div>
@ -101,13 +128,13 @@ export default function Group({
setting.isHidden ? "hide" : "callout-link"
} t--read-more-link`}
data-testid="admin-settings-group-link"
key={setting.name}
key={setting.name || setting.id}
>
<Callout
action={setting.action}
actionLabel="READ MORE"
title={createMessage(() => setting.label || "")}
type="Info"
type={setting.calloutType || "Info"}
url={setting.url}
/>
</div>
@ -117,7 +144,7 @@ export default function Group({
<div
className={setting.isHidden ? "hide" : ""}
data-testid="admin-settings-group-text"
key={setting.name}
key={setting.name || setting.id}
>
<Text setting={setting} />
</div>
@ -127,7 +154,7 @@ export default function Group({
<div
className={setting.isHidden ? "hide" : ""}
data-testid="admin-settings-group-button"
key={setting.name}
key={setting.name || setting.id}
>
<Button setting={setting} />
</div>
@ -137,7 +164,7 @@ export default function Group({
<div
className={setting.isHidden ? "hide" : ""}
data-testid="admin-settings-group"
key={setting.name}
key={setting.name || setting.id}
>
<Group
category={category}
@ -147,6 +174,52 @@ export default function Group({
/>
</div>
);
case SettingTypes.UNEDITABLEFIELD:
return (
<div
className={setting.isHidden ? "hide" : ""}
data-testid="admin-settings-redirect-url"
key={setting.name || setting.id}
>
<RedirectUrlReduxForm
helpText={setting.helpText}
value={setting.value}
/>
</div>
);
case SettingTypes.TAGINPUT:
return (
<div
className={setting.isHidden ? "hide" : "tag-input"}
data-testid="admin-settings-tag-input"
key={setting.name || setting.id}
>
<TagInputField
data-cy="t--tag-input"
intent="success"
label={setting.label}
name={setting.name || setting.id}
placeholder=""
setting={setting}
type="text"
/>
</div>
);
case SettingTypes.ACCORDION:
return (
<div
className={setting.isHidden ? "hide" : ""}
data-testid="admin-settings-accordion"
key={setting.name || setting.id}
>
<Accordion
category={category}
label={setting.label}
settings={setting.advanced}
subCategory={subCategory}
/>
</div>
);
}
})}
</GroupBody>

View File

@ -18,7 +18,21 @@ import Group from "./FormGroup/group";
import RestartBanner from "./RestartBanner";
import AdminConfig from "./config";
import SaveAdminSettings from "./SaveSettings";
import { SettingTypes } from "@appsmith/pages/AdminSettings/config/types";
import {
SettingTypes,
Setting,
} from "@appsmith/pages/AdminSettings/config/types";
import { DisconnectService } from "./DisconnectService";
import {
createMessage,
DISCONNECT_SERVICE_SUBHEADER,
DISCONNECT_SERVICE_WARNING,
} from "@appsmith/constants/messages";
import { Toaster, Variant } from "components/ads";
import {
connectedMethods,
saveAllowed,
} from "@appsmith/utils/adminSettingsHelpers";
const Wrapper = styled.div`
flex-basis: calc(100% - ${(props) => props.theme.homePage.leftPane.width}px);
@ -28,7 +42,9 @@ const Wrapper = styled.div`
overflow: auto;
`;
const SettingsFormWrapper = styled.div``;
const SettingsFormWrapper = styled.div`
max-width: 40rem;
`;
export const BottomSpace = styled.div`
height: ${(props) => props.theme.settings.footerHeight + 20}px;
@ -79,9 +95,16 @@ export function SettingsForm(
const isSavable = AdminConfig.savableCategories.includes(
subCategory ?? category,
);
const pageTitle = getSettingLabel(
details?.title || (subCategory ?? category),
);
const onSave = () => {
dispatch(saveSettings(props.settings));
if (saveAllowed(props.settings)) {
dispatch(saveSettings(props.settings));
} else {
saveBlocked();
}
};
const onClear = () => {
@ -90,13 +113,6 @@ export function SettingsForm(
if (setting && setting.controlType == SettingTypes.TOGGLE) {
props.settingsConfig[settingName] =
props.settingsConfig[settingName].toString() == "true";
if (
typeof props.settingsConfig["APPSMITH_SIGNUP_DISABLED"] ===
"undefined"
) {
props.settingsConfig["APPSMITH_SIGNUP_DISABLED"] = true;
}
}
});
props.initialize(props.settingsConfig);
@ -111,13 +127,32 @@ export function SettingsForm(
});
}, []);
const saveBlocked = () => {
Toaster.show({
text: "Cannot disconnect the only connected authentication method.",
variant: Variant.danger,
});
};
const disconnect = (currentSettings: AdminConfig) => {
const updatedSettings: any = {};
if (connectedMethods.length >= 2) {
_.forEach(currentSettings, (setting: Setting) => {
if (!setting.isHidden && setting.controlType !== SettingTypes.LINK) {
updatedSettings[setting.id] = "";
}
});
dispatch(saveSettings(updatedSettings));
} else {
saveBlocked();
}
};
return (
<Wrapper>
<SettingsFormWrapper>
<HeaderWrapper>
<SettingsHeader>
{getSettingLabel(details?.title || (subCategory ?? category))}
</SettingsHeader>
<SettingsHeader>{pageTitle}</SettingsHeader>
{details?.subText && (
<SettingsSubHeader>{details.subText}</SettingsSubHeader>
)}
@ -136,6 +171,15 @@ export function SettingsForm(
valid={props.valid}
/>
)}
{details?.isConnected && (
<DisconnectService
disconnect={() => disconnect(settings)}
subHeader={createMessage(DISCONNECT_SERVICE_SUBHEADER)}
warning={`${pageTitle} ${createMessage(
DISCONNECT_SERVICE_WARNING,
)}`}
/>
)}
<BottomSpace />
</SettingsFormWrapper>
{props.showReleaseNotes && (

View File

@ -20,6 +20,12 @@ export class ConfigFactory {
name: item.id,
...item,
});
item?.advanced?.forEach((subItem) => {
ConfigFactory.settingsMap[subItem.id] = {
...subItem,
};
});
});
config?.children?.forEach((child) => ConfigFactory.registerSettings(child));
}

View File

@ -155,6 +155,7 @@ export type EventName =
| "COMMENTS_ONBOARDING_MODAL_TRIGGERED"
| "REPLAY_UNDO"
| "REPLAY_REDO"
| "REDIRECT_URL_COPIED"
| "SNIPPET_CUSTOMIZE"
| "SNIPPET_EXECUTE"
| "SNIPPET_FILTER"

View File

@ -32,7 +32,7 @@ if ! test -f "$KEY_FILE" || ! test -f "$CERT_FILE"; then
exit
fi
ENV_FILE=../../.env
ENV_FILE=../../stacks/configuration/docker.env
if ! test -f "$ENV_FILE"; then
echo "
Please populate the .env at the root of the project and run again
@ -62,7 +62,7 @@ fi
docker rm -f wildcard-nginx || true
uname_out="$(uname -s)"
vars_to_substitute="$(printf '\$%s,' $(grep -o "^APPSMITH_[A-Z0-9_]\+" ../../.env | xargs))"
vars_to_substitute="$(printf '\$%s,' $(grep -o "^APPSMITH_[A-Z0-9_]\+" "$ENV_FILE" | xargs))"
client_proxy_pass="${default_client_proxy}"
network_mode="bridge"
case "${uname_out}" in

View File

@ -20,8 +20,11 @@ APPSMITH_CLOUD_SERVICES_BASE_URL="https://release-cs.appsmith.com"
#APPSMITH_OAUTH2_GITHUB_CLIENT_ID=""
#APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET=""
#APPSMITH_FORM_LOGIN_DISABLED=
#APPSMITH_SIGNUP_DISABLED=
#APPSMITH_SENTRY_DSN=
#APPSMITH_SENTRY_ENVIRONMENT=
#APPSMITH_RECAPTCHA_SITE_KEY=""
#APPSMITH_RECAPTCHA_SECRET_KEY=""
#APPSMITH_RECAPTCHA_SECRET_KEY=""

View File

@ -4,6 +4,8 @@
# APPSMITH_OAUTH2_GOOGLE_CLIENT_SECRET=""
# APPSMITH_OAUTH2_GITHUB_CLIENT_ID=""
# APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET=""
# APPSMITH_FORM_LOGIN_DISABLED=
# APPSMITH_SIGNUP_DISABLED=
# APPSMITH_MAIL_ENABLED=true
# APPSMITH_MAIL_HOST=localhost

View File

@ -20,6 +20,10 @@ APPSMITH_OAUTH2_GOOGLE_CLIENT_SECRET=
APPSMITH_OAUTH2_GITHUB_CLIENT_ID=
APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET=
# Form Login/Signup
APPSMITH_FORM_LOGIN_DISABLED=
APPSMITH_SIGNUP_DISABLED=
# Segment
APPSMITH_SEGMENT_KEY=

View File

@ -53,6 +53,8 @@ server {
sub_filter __APPSMITH_MAIL_ENABLED__ '\${APPSMITH_MAIL_ENABLED}';
sub_filter __APPSMITH_DISABLE_TELEMETRY__ '\${APPSMITH_DISABLE_TELEMETRY}';
sub_filter __APPSMITH_RECAPTCHA_SITE_KEY__ '\${APPSMITH_RECAPTCHA_SITE_KEY}';
sub_filter __APPSMITH_FORM_LOGIN_DISABLED__ '\${APPSMITH_FORM_LOGIN_DISABLED}';
sub_filter __APPSMITH_SIGNUP_DISABLED__ '\${APPSMITH_SIGNUP_DISABLED}';
}
location /api {

View File

@ -73,6 +73,8 @@ server {
sub_filter __APPSMITH_MAIL_ENABLED__ '\${APPSMITH_MAIL_ENABLED}';
sub_filter __APPSMITH_DISABLE_TELEMETRY__ '\${APPSMITH_DISABLE_TELEMETRY}';
sub_filter __APPSMITH_RECAPTCHA_SITE_KEY__ '\${APPSMITH_RECAPTCHA_SITE_KEY}';
sub_filter __APPSMITH_FORM_LOGIN_DISABLED__ '\${APPSMITH_FORM_LOGIN_DISABLED}';
sub_filter __APPSMITH_SIGNUP_DISABLED__ '\${APPSMITH_SIGNUP_DISABLED}';
}
location /api {

View File

@ -198,6 +198,8 @@ To change Appsmith configurations, you can use configuration UI in application o
| `applicationConfig.APPSMITH_ENCRYPTION_PASSWORD` | `""` |
| `applicationConfig.APPSMITH_ENCRYPTION_SALT` | `""` |
| `applicationConfig.APPSMITH_CUSTOM_DOMAIN` | `""` |
| `applicationConfig.APPSMITH_FORM_LOGIN_DISABLED` | `""` |
| `applicationConfig.APPSMITH_SIGNUP_DISABLED` | `""` |
For example, to change the encryption salt configuration, you can run the following command:
```

View File

@ -274,6 +274,8 @@ applicationConfig:
APPSMITH_OAUTH2_GOOGLE_CLIENT_SECRET: ""
APPSMITH_OAUTH2_GITHUB_CLIENT_ID: ""
APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET: ""
APPSMITH_FORM_LOGIN_DISABLED: ""
APPSMITH_SIGNUP_DISABLED: ""
APPSMITH_CLIENT_LOG_LEVEL: ""
APPSMITH_GOOGLE_MAPS_API_KEY: ""
APPSMITH_MAIL_ENABLED: ""

View File

@ -35,6 +35,8 @@ server {
sub_filter __APPSMITH_RECAPTCHA_SECRET_KEY__ '${APPSMITH_RECAPTCHA_SECRET_KEY}';
sub_filter __APPSMITH_RECAPTCHA_ENABLED__ '${APPSMITH_RECAPTCHA_ENABLED}';
sub_filter __APPSMITH_DISABLE_INTERCOM__ '${APPSMITH_DISABLE_INTERCOM}';
sub_filter __APPSMITH_FORM_LOGIN_DISABLED__ '${APPSMITH_FORM_LOGIN_DISABLED}';
sub_filter __APPSMITH_SIGNUP_DISABLED__ '${APPSMITH_SIGNUP_DISABLED}';
}

View File

@ -34,5 +34,7 @@ data:
APPSMITH_RECAPTCHA_SECRET_KEY: ""
APPSMITH_RECAPTCHA_ENABLED: "false"
APPSMITH_DISABLE_INTERCOM: "false"
APPSMITH_FORM_LOGIN_DISABLED: "false"
APPSMITH_SIGNUP_DISABLED: "true"
# APPSMITH_PLUGIN_MAX_RESPONSE_SIZE_MB=5
EOF

View File

@ -45,6 +45,8 @@ data:
sub_filter __APPSMITH_RECAPTCHA_SECRET_KEY__ '${APPSMITH_RECAPTCHA_SECRET_KEY}';
sub_filter __APPSMITH_RECAPTCHA_ENABLED__ '${APPSMITH_RECAPTCHA_ENABLED}';
sub_filter __APPSMITH_DISABLE_INTERCOM__ '${APPSMITH_DISABLE_INTERCOM}';
sub_filter __APPSMITH_FORM_LOGIN_DISABLED__ '${APPSMITH_FORM_LOGIN_DISABLED}';
sub_filter __APPSMITH_SIGNUP_DISABLED__ '${APPSMITH_SIGNUP_DISABLED}';
}
}"

View File

@ -35,6 +35,11 @@ APPSMITH_MAIL_ENABLED=false
# APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET=
# *********************************
# ******** Form Login/Signup ********
# APPSMITH_FORM_LOGIN_DISABLED=
# APPSMITH_SIGNUP_DISABLED=
# ***********************************
# ******** Google Maps ***********
# APPSMITH_GOOGLE_MAPS_API_KEY=
# ********************************

View File

@ -57,6 +57,8 @@ $NGINX_SSL_CMNT server_name $custom_domain ;
sub_filter __APPSMITH_RECAPTCHA_SECRET_KEY__ '\${APPSMITH_RECAPTCHA_SECRET_KEY}';
sub_filter __APPSMITH_RECAPTCHA_ENABLED__ '\${APPSMITH_RECAPTCHA_ENABLED}';
sub_filter __APPSMITH_DISABLE_INTERCOM__ '\${APPSMITH_DISABLE_INTERCOM}';
sub_filter __APPSMITH_FORM_LOGIN_DISABLED__ '\${APPSMITH_FORM_LOGIN_DISABLED}';
sub_filter __APPSMITH_SIGNUP_DISABLED__ '\${APPSMITH_SIGNUP_DISABLED}';
}
@ -114,6 +116,8 @@ $NGINX_SSL_CMNT sub_filter __APPSMITH_RECAPTCHA_SITE_KEY__ '\${APPSMITH_R
$NGINX_SSL_CMNT sub_filter __APPSMITH_RECAPTCHA_SECRET_KEY__ '\${APPSMITH_RECAPTCHA_SECRET_KEY}';
$NGINX_SSL_CMNT sub_filter __APPSMITH_RECAPTCHA_ENABLED__ '\${APPSMITH_RECAPTCHA_ENABLED}';
$NGINX_SSL_CMNT sub_filter __APPSMITH_DISABLE_INTERCOM__ '\${APPSMITH_DISABLE_INTERCOM}';
$NGINX_SSL_CMNT sub_filter __APPSMITH_FORM_LOGIN_DISABLED__ '${APPSMITH_FORM_LOGIN_DISABLED}';
$NGINX_SSL_CMNT sub_filter __APPSMITH_SIGNUP_DISABLED__ '${APPSMITH_SIGNUP_DISABLED}';
$NGINX_SSL_CMNT }
$NGINX_SSL_CMNT
$NGINX_SSL_CMNT location /api {