Merge branch 'release' of https://github.com/appsmithorg/appsmith into release
This commit is contained in:
commit
c47e66cf0c
|
|
@ -3,7 +3,12 @@ import styled from "styled-components";
|
|||
import HighlightedCode, {
|
||||
SYNTAX_HIGHLIGHTING_SUPPORTED_LANGUAGES,
|
||||
} from "components/editorComponents/HighlightedCode";
|
||||
import { Popover, PopoverInteractionKind, Classes } from "@blueprintjs/core";
|
||||
import {
|
||||
Popover,
|
||||
PopoverInteractionKind,
|
||||
Classes,
|
||||
Icon,
|
||||
} from "@blueprintjs/core";
|
||||
import { CurrentValueViewer } from "components/editorComponents/CodeEditor/EvaluatedValuePopup";
|
||||
import { EditorTheme } from "components/editorComponents/CodeEditor/EditorConfig";
|
||||
import useClipboard from "utils/hooks/useClipboard";
|
||||
|
|
@ -61,9 +66,15 @@ const Wrapper = styled.div<{ step: number }>`
|
|||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
cursor: pointer;
|
||||
& ~ span.${Classes.ICON} {
|
||||
position: absolute;
|
||||
right: 4px;
|
||||
top: 10px;
|
||||
opacity: 0;
|
||||
}
|
||||
&:hover {
|
||||
&:before {
|
||||
content: "Copy";
|
||||
content: "";
|
||||
background: ${Colors.TUNDORA};
|
||||
opacity: 0.5;
|
||||
position: absolute;
|
||||
|
|
@ -71,14 +82,11 @@ const Wrapper = styled.div<{ step: number }>`
|
|||
height: 100%;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
font-size: 12px;
|
||||
color: white;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
text-align: right;
|
||||
z-index: 1;
|
||||
}
|
||||
& ~ span.${Classes.ICON} {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -92,6 +100,7 @@ const Wrapper = styled.div<{ step: number }>`
|
|||
text-shadow: none;
|
||||
padding-left: ${props =>
|
||||
props.step * props.theme.spaces[2] + props.theme.spaces[3]}px;
|
||||
padding-right: 20px;
|
||||
& span.token.property {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
|
|
@ -214,6 +223,7 @@ export const EntityProperty = memo((props: EntityPropertyProps) => {
|
|||
codeText={codeText}
|
||||
language={SYNTAX_HIGHLIGHTING_SUPPORTED_LANGUAGES.APPSMITH}
|
||||
/>
|
||||
<Icon icon="duplicate" iconSize={14} color={Colors.ALTO} />
|
||||
{propertyValue}
|
||||
</Wrapper>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ export const ExplorerPageEntity = memo((props: ExplorerPageEntityProps) => {
|
|||
if (!!params.applicationId) {
|
||||
history.push(BUILDER_PAGE_URL(params.applicationId, props.page.pageId));
|
||||
}
|
||||
}, [props.isCurrentPage, props.page.pageId, params.applicationId]);
|
||||
}, [props.page.pageId, params.applicationId]);
|
||||
|
||||
const contextMenu = (
|
||||
<PageContextMenu
|
||||
|
|
|
|||
|
|
@ -1,216 +0,0 @@
|
|||
import React, { useLayoutEffect } from "react";
|
||||
import { AppState } from "reducers";
|
||||
import { withRouter, RouteComponentProps } from "react-router-dom";
|
||||
import { connect } from "react-redux";
|
||||
import { InjectedFormProps, reduxForm, Field } from "redux-form";
|
||||
import { CREATE_PASSWORD_FORM_NAME } from "constants/forms";
|
||||
import { ReduxActionTypes } from "constants/ReduxActionConstants";
|
||||
import { getIsTokenValid, getIsValidatingToken } from "selectors/authSelectors";
|
||||
import FormTextField from "components/editorComponents/form/FormTextField";
|
||||
import FormMessage, {
|
||||
FormMessageProps,
|
||||
MessageAction,
|
||||
} from "components/editorComponents/form/FormMessage";
|
||||
import Spinner from "components/editorComponents/Spinner";
|
||||
import Button from "components/editorComponents/Button";
|
||||
import FormGroup from "components/editorComponents/form/FormGroup";
|
||||
import StyledForm from "components/editorComponents/Form";
|
||||
import { isEmptyString, isStrongPassword } from "utils/formhelpers";
|
||||
|
||||
import {
|
||||
CreatePasswordFormValues,
|
||||
createPasswordSubmitHandler,
|
||||
} from "./helpers";
|
||||
import {
|
||||
AuthCardHeader,
|
||||
AuthCardFooter,
|
||||
AuthCardContainer,
|
||||
AuthCardBody,
|
||||
AuthCardNavLink,
|
||||
FormActions,
|
||||
} from "./StyledComponents";
|
||||
import { AUTH_LOGIN_URL } from "constants/routes";
|
||||
|
||||
import {
|
||||
CREATE_PASSWORD_PAGE_PASSWORD_INPUT_LABEL,
|
||||
CREATE_PASSWORD_PAGE_PASSWORD_INPUT_PLACEHOLDER,
|
||||
CREATE_PASSWORD_LOGIN_LINK_TEXT,
|
||||
CREATE_PASSWORD_SUBMIT_BUTTON_TEXT,
|
||||
CREATE_PASSWORD_PAGE_SUBTITLE,
|
||||
CREATE_PASSWORD_PAGE_TITLE,
|
||||
FORM_VALIDATION_INVALID_PASSWORD,
|
||||
FORM_VALIDATION_EMPTY_PASSWORD,
|
||||
CREATE_PASSWORD_EXPIRED_TOKEN,
|
||||
CREATE_PASSWORD_INVALID_TOKEN,
|
||||
CREATE_PASSWORD_RESET_SUCCESS,
|
||||
CREATE_PASSWORD_RESET_SUCCESS_LOGIN_LINK,
|
||||
} from "constants/messages";
|
||||
import { TncPPLinks } from "./SignUp";
|
||||
|
||||
const validate = (values: CreatePasswordFormValues) => {
|
||||
const errors: CreatePasswordFormValues = {};
|
||||
if (!values.password || isEmptyString(values.password)) {
|
||||
errors.password = FORM_VALIDATION_EMPTY_PASSWORD;
|
||||
} else if (!isStrongPassword(values.password)) {
|
||||
errors.password = FORM_VALIDATION_INVALID_PASSWORD;
|
||||
}
|
||||
return errors;
|
||||
};
|
||||
|
||||
type CreatePasswordProps = InjectedFormProps<
|
||||
CreatePasswordFormValues,
|
||||
{
|
||||
verifyToken: (token: string, email: string) => void;
|
||||
isTokenValid: boolean;
|
||||
validatingToken: boolean;
|
||||
}
|
||||
> & {
|
||||
verifyToken: (token: string, email: string) => void;
|
||||
isTokenValid: boolean;
|
||||
validatingToken: boolean;
|
||||
} & RouteComponentProps<{ email: string; token: string }>;
|
||||
|
||||
export const CreatePassword = (props: CreatePasswordProps) => {
|
||||
const {
|
||||
error,
|
||||
handleSubmit,
|
||||
pristine,
|
||||
submitting,
|
||||
submitSucceeded,
|
||||
submitFailed,
|
||||
initialValues,
|
||||
isTokenValid,
|
||||
validatingToken,
|
||||
verifyToken,
|
||||
valid,
|
||||
} = props;
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (initialValues.token && initialValues.email)
|
||||
verifyToken(initialValues.token, initialValues.email);
|
||||
}, [initialValues.token, initialValues.email, verifyToken]);
|
||||
|
||||
const showInvalidMessage = !initialValues.token || !initialValues.email;
|
||||
const showExpiredMessage = !isTokenValid && !validatingToken;
|
||||
const showSuccessMessage = submitSucceeded && !pristine;
|
||||
const showFailureMessage = submitFailed && !!error;
|
||||
|
||||
let message = "";
|
||||
let messageActions: MessageAction[] | undefined = undefined;
|
||||
|
||||
if (showExpiredMessage) {
|
||||
message = CREATE_PASSWORD_EXPIRED_TOKEN;
|
||||
}
|
||||
if (showInvalidMessage) {
|
||||
message = CREATE_PASSWORD_INVALID_TOKEN;
|
||||
}
|
||||
|
||||
if (showSuccessMessage) {
|
||||
message = CREATE_PASSWORD_RESET_SUCCESS;
|
||||
messageActions = [
|
||||
{
|
||||
url: AUTH_LOGIN_URL,
|
||||
text: CREATE_PASSWORD_RESET_SUCCESS_LOGIN_LINK,
|
||||
intent: "primary",
|
||||
},
|
||||
];
|
||||
}
|
||||
if (showFailureMessage) {
|
||||
message = error;
|
||||
}
|
||||
|
||||
const messageTagProps: FormMessageProps = {
|
||||
intent:
|
||||
showInvalidMessage || showExpiredMessage || showFailureMessage
|
||||
? "danger"
|
||||
: "primary",
|
||||
message,
|
||||
actions: messageActions,
|
||||
};
|
||||
|
||||
if (showInvalidMessage || showExpiredMessage) {
|
||||
return <FormMessage {...messageTagProps} />;
|
||||
}
|
||||
|
||||
if (!isTokenValid && validatingToken) {
|
||||
return <Spinner />;
|
||||
}
|
||||
return (
|
||||
<AuthCardContainer>
|
||||
{(showSuccessMessage || showFailureMessage) && (
|
||||
<FormMessage {...messageTagProps} />
|
||||
)}
|
||||
<AuthCardHeader>
|
||||
<h1>{CREATE_PASSWORD_PAGE_TITLE}</h1>
|
||||
<h5>{CREATE_PASSWORD_PAGE_SUBTITLE}</h5>
|
||||
</AuthCardHeader>
|
||||
<AuthCardBody>
|
||||
<StyledForm onSubmit={handleSubmit(createPasswordSubmitHandler)}>
|
||||
<FormGroup
|
||||
intent={error ? "danger" : "none"}
|
||||
label={CREATE_PASSWORD_PAGE_PASSWORD_INPUT_LABEL}
|
||||
>
|
||||
<FormTextField
|
||||
name="password"
|
||||
type="password"
|
||||
placeholder={CREATE_PASSWORD_PAGE_PASSWORD_INPUT_PLACEHOLDER}
|
||||
/>
|
||||
</FormGroup>
|
||||
<Field type="hidden" name="email" component="input" />
|
||||
<Field type="hidden" name="token" component="input" />
|
||||
<FormActions>
|
||||
<Button
|
||||
filled
|
||||
size="large"
|
||||
type="submit"
|
||||
text={CREATE_PASSWORD_SUBMIT_BUTTON_TEXT}
|
||||
intent="primary"
|
||||
disabled={pristine || !valid}
|
||||
loading={submitting}
|
||||
/>
|
||||
</FormActions>
|
||||
</StyledForm>
|
||||
</AuthCardBody>
|
||||
<AuthCardNavLink to={AUTH_LOGIN_URL}>
|
||||
{CREATE_PASSWORD_LOGIN_LINK_TEXT}
|
||||
</AuthCardNavLink>
|
||||
<AuthCardFooter>
|
||||
<TncPPLinks></TncPPLinks>
|
||||
</AuthCardFooter>
|
||||
</AuthCardContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default connect(
|
||||
(state: AppState, props: CreatePasswordProps) => {
|
||||
const queryParams = new URLSearchParams(props.location.search);
|
||||
return {
|
||||
initialValues: {
|
||||
email: queryParams.get("email") || undefined,
|
||||
token: queryParams.get("token") || undefined,
|
||||
},
|
||||
isTokenValid: getIsTokenValid(state),
|
||||
validatingToken: getIsValidatingToken(state),
|
||||
};
|
||||
},
|
||||
(dispatch: any) => ({
|
||||
verifyToken: (token: string, email: string) =>
|
||||
dispatch({
|
||||
type: ReduxActionTypes.VERIFY_INVITE_INIT,
|
||||
payload: { token, email },
|
||||
}),
|
||||
}),
|
||||
)(
|
||||
reduxForm<
|
||||
CreatePasswordFormValues,
|
||||
{
|
||||
verifyToken: (token: string, email: string) => void;
|
||||
validatingToken: boolean;
|
||||
isTokenValid: boolean;
|
||||
}
|
||||
>({
|
||||
validate,
|
||||
form: CREATE_PASSWORD_FORM_NAME,
|
||||
touchOnBlur: true,
|
||||
})(withRouter(CreatePassword)),
|
||||
);
|
||||
|
|
@ -2,7 +2,7 @@ import React from "react";
|
|||
import { reduxForm, InjectedFormProps } from "redux-form";
|
||||
import { AUTH_LOGIN_URL } from "constants/routes";
|
||||
import { SIGNUP_FORM_NAME } from "constants/forms";
|
||||
import { Link, useLocation } from "react-router-dom";
|
||||
import { Link, RouteComponentProps, useLocation, withRouter } from "react-router-dom";
|
||||
import Divider from "components/editorComponents/Divider";
|
||||
import {
|
||||
AuthCardHeader,
|
||||
|
|
@ -43,6 +43,8 @@ import AnalyticsUtil from "utils/AnalyticsUtil";
|
|||
|
||||
import { getAppsmithConfigs } from "configs";
|
||||
import { SIGNUP_SUBMIT_PATH } from "constants/ApiConstants";
|
||||
import { connect } from "react-redux";
|
||||
import { AppState } from "@appsmith/reducers";
|
||||
const {
|
||||
enableGithubOAuth,
|
||||
enableGoogleOAuth,
|
||||
|
|
@ -81,7 +83,9 @@ const validate = (values: SignupFormValues) => {
|
|||
return errors;
|
||||
};
|
||||
|
||||
export const SignUp = (props: InjectedFormProps<SignupFormValues>) => {
|
||||
type SignUpFormProps = InjectedFormProps<SignupFormValues> & RouteComponentProps<{ email: string }>;
|
||||
|
||||
export const SignUp = (props: SignUpFormProps) => {
|
||||
const { error, submitting, pristine, valid } = props;
|
||||
const location = useLocation();
|
||||
|
||||
|
|
@ -160,8 +164,20 @@ export const SignUp = (props: InjectedFormProps<SignupFormValues>) => {
|
|||
);
|
||||
};
|
||||
|
||||
export default reduxForm<SignupFormValues>({
|
||||
validate,
|
||||
form: SIGNUP_FORM_NAME,
|
||||
touchOnBlur: true,
|
||||
})(SignUp);
|
||||
export default connect(
|
||||
(state: AppState, props: SignUpFormProps) => {
|
||||
const queryParams = new URLSearchParams(props.location.search);
|
||||
return {
|
||||
initialValues: {
|
||||
email: queryParams.get("email"),
|
||||
},
|
||||
};
|
||||
},
|
||||
null,
|
||||
)(
|
||||
reduxForm<SignupFormValues>({
|
||||
validate,
|
||||
form: SIGNUP_FORM_NAME,
|
||||
touchOnBlur: true,
|
||||
})(withRouter(SignUp)),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ import { AuthContainer, AuthCard } from "./StyledComponents";
|
|||
import SignUp from "./SignUp";
|
||||
import ForgotPassword from "./ForgotPassword";
|
||||
import ResetPassword from "./ResetPassword";
|
||||
import CreatePassword from "./CreatePassword";
|
||||
import AppRoute from "pages/common/AppRoute";
|
||||
import PageNotFound from "pages/common/PageNotFound";
|
||||
const AnimatedAuthCard = animated(AuthContainer);
|
||||
export const UserAuth = () => {
|
||||
const { path } = useRouteMatch();
|
||||
|
|
@ -50,10 +50,8 @@ export const UserAuth = () => {
|
|||
name={"ForgotPassword"}
|
||||
/>
|
||||
<AppRoute
|
||||
exact
|
||||
path={`${path}/createPassword`}
|
||||
component={CreatePassword}
|
||||
name={"CreatePassword"}
|
||||
component={PageNotFound}
|
||||
name={"PageNotFound"}
|
||||
/>
|
||||
</Switch>
|
||||
</AuthCard>
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ public interface Url {
|
|||
String TEAM_URL = BASE_URL + VERSION + "/teams";
|
||||
String GROUP_URL = BASE_URL + VERSION + "/groups";
|
||||
String PERMISSION_URL = BASE_URL + VERSION + "/permissions";
|
||||
String SIGNUP_URL = BASE_URL + VERSION + "/signup";
|
||||
String COLLECTION_URL = BASE_URL + VERSION + "/collections";
|
||||
String IMPORT_URL = BASE_URL + VERSION + "/import";
|
||||
String PROVIDER_URL = BASE_URL + VERSION + "/providers";
|
||||
|
|
|
|||
|
|
@ -103,7 +103,9 @@ public class User extends BaseDomain implements UserDetails, OidcUser {
|
|||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return this.isEnabled;
|
||||
// The `isEnabled` field is `Boolean` whereas we are returning `boolean` here. If `isEnabled` field value is
|
||||
// `null`, this would throw a `NullPointerException`. Hence, checking equality with `Boolean.TRUE` instead.
|
||||
return Boolean.TRUE.equals(this.isEnabled);
|
||||
}
|
||||
|
||||
// TODO: Check the return value for the functions below to ensure that correct values are being returned
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ public class UserServiceImpl extends BaseService<UserRepository, User, String> i
|
|||
private static final String WELCOME_USER_EMAIL_TEMPLATE = "email/welcomeUserTemplate.html";
|
||||
private static final String FORGOT_PASSWORD_EMAIL_TEMPLATE = "email/forgotPasswordTemplate.html";
|
||||
private static final String FORGOT_PASSWORD_CLIENT_URL_FORMAT = "%s/user/resetPassword?token=%s&email=%s";
|
||||
private static final String INVITE_USER_CLIENT_URL_FORMAT = "%s/user/createPassword?token=%s&email=%s";
|
||||
private static final String INVITE_USER_CLIENT_URL_FORMAT = "%s/user/signup?token=%s&email=%s";
|
||||
private static final String INVITE_USER_EMAIL_TEMPLATE = "email/inviteUserCreatorTemplate.html";
|
||||
private static final String USER_ADDED_TO_ORGANIZATION_EMAIL_TEMPLATE = "email/inviteExistingUserToOrganizationTemplate.html";
|
||||
// We default the origin header to the production deployment of the client's URL
|
||||
|
|
@ -229,7 +229,7 @@ public class UserServiceImpl extends BaseService<UserRepository, User, String> i
|
|||
*
|
||||
* @param email The email of the user whose password is being reset
|
||||
* @param token The one-time token provided to the user for resetting the password
|
||||
* @return
|
||||
* @return Publishes a boolean indicating whether the given token is valid for the given email address
|
||||
*/
|
||||
@Override
|
||||
public Mono<Boolean> verifyPasswordResetToken(String email, String token) {
|
||||
|
|
@ -425,7 +425,7 @@ public class UserServiceImpl extends BaseService<UserRepository, User, String> i
|
|||
public Mono<User> userCreate(User user) {
|
||||
|
||||
// Only encode the password if it's a form signup. For OAuth signups, we don't need password
|
||||
if (user.getIsEnabled() && LoginSource.FORM.equals(user.getSource())) {
|
||||
if (user.isEnabled() && LoginSource.FORM.equals(user.getSource())) {
|
||||
if (user.getPassword() == null || user.getPassword().isBlank()) {
|
||||
return Mono.error(new AppsmithException(AppsmithError.INVALID_CREDENTIALS));
|
||||
}
|
||||
|
|
@ -465,8 +465,8 @@ public class UserServiceImpl extends BaseService<UserRepository, User, String> i
|
|||
* <p>
|
||||
* For new user invite flow, please {@link UserService#inviteUser(InviteUsersDTO, String)}
|
||||
*
|
||||
* @param user
|
||||
* @return
|
||||
* @param user User object representing the user to be created/enabled.
|
||||
* @return Publishes the user object, after having been saved.
|
||||
*/
|
||||
@Override
|
||||
public Mono<User> createUserAndSendEmail(User user, String originHeader) {
|
||||
|
|
@ -481,7 +481,7 @@ public class UserServiceImpl extends BaseService<UserRepository, User, String> i
|
|||
// If the user doesn't exist, create the user. If the user exists, return a duplicate key exception
|
||||
return repository.findByEmail(user.getUsername())
|
||||
.flatMap(savedUser -> {
|
||||
if (!savedUser.getIsEnabled()) {
|
||||
if (!savedUser.isEnabled()) {
|
||||
// First enable the user
|
||||
savedUser.setIsEnabled(true);
|
||||
|
||||
|
|
@ -553,7 +553,7 @@ public class UserServiceImpl extends BaseService<UserRepository, User, String> i
|
|||
* 2. User exists :
|
||||
* a. Add user to the organization
|
||||
* b. Add organization to the user
|
||||
* @return
|
||||
* @return Publishes the invited users, after being saved with the new organization ID.
|
||||
*/
|
||||
@Override
|
||||
public Flux<User> inviteUser(InviteUsersDTO inviteUsersDTO, String originHeader) {
|
||||
|
|
|
|||
|
|
@ -104,6 +104,54 @@ overwrite_file() {
|
|||
fi
|
||||
}
|
||||
|
||||
# This function prompts the user for an input for a non-empty Mongo root password.
|
||||
read_mongo_password() {
|
||||
read -sp 'Set the mongo password: ' mongo_root_password
|
||||
while [[ -z $mongo_root_password ]]
|
||||
do
|
||||
echo ""
|
||||
echo ""
|
||||
echo "+++++++++++ ERROR ++++++++++++++++++++++"
|
||||
echo "The mongo password cannot be empty. Please input a valid password string."
|
||||
echo "++++++++++++++++++++++++++++++++++++++++"
|
||||
echo ""
|
||||
read -sp 'Set the mongo password: ' mongo_root_password
|
||||
done
|
||||
}
|
||||
|
||||
# This function prompts the user for an input for a non-empty Mongo username.
|
||||
read_mongo_username() {
|
||||
read -p 'Set the mongo root user: ' mongo_root_user
|
||||
while [[ -z $mongo_root_user ]]
|
||||
do
|
||||
echo ""
|
||||
echo "+++++++++++ ERROR ++++++++++++++++++++++"
|
||||
echo "The mongo username cannot be empty. Please input a valid username string."
|
||||
echo "++++++++++++++++++++++++++++++++++++++++"
|
||||
echo ""
|
||||
read -p 'Set the mongo root user: ' mongo_root_user
|
||||
done
|
||||
}
|
||||
|
||||
wait_for_containers_start() {
|
||||
timeout=$1
|
||||
i=1
|
||||
echo -ne "Waiting for all containers to start. This check will timeout in $timeout seconds ...\r\c"
|
||||
# The do-while loop is important because for-loops don't work for dynamic values
|
||||
while [[ $i -le $timeout ]]
|
||||
do
|
||||
status_code=$(curl -s -o /dev/null -w "%{http_code}" http://localhost/api/v1)
|
||||
# echo $status_code
|
||||
if [[ status_code -eq 401 ]]; then
|
||||
break
|
||||
else
|
||||
echo -ne "Waiting for all containers to start. This check will timeout in $timeout seconds ...\r\c"
|
||||
fi
|
||||
((i = i + 1))
|
||||
sleep 1
|
||||
done
|
||||
}
|
||||
|
||||
echo -e "\U1F44B Thank you for trying out Appsmith! "
|
||||
echo ""
|
||||
|
||||
|
|
@ -132,6 +180,25 @@ if [[ $ports_occupied -ne 0 ]]; then
|
|||
exit
|
||||
fi
|
||||
|
||||
# Check is Docker daemon is installed and available. If not, the install & start Docker for Linux machines. We cannot automatically install Docker Desktop on Mac OS
|
||||
if ! is_command_present docker ;then
|
||||
if [ $package_manager == "apt-get" -o $package_manager == "yum" ];then
|
||||
install_docker
|
||||
else
|
||||
echo ""
|
||||
echo "+++++++++++ IMPORTANT READ ++++++++++++++++++++++"
|
||||
echo "Docker Desktop must be installed manually on Mac OS to proceed. Docker can only be installed automatically on Ubuntu / Redhat / Cent OS"
|
||||
echo "https://docs.docker.com/docker-for-mac/install/"
|
||||
echo "++++++++++++++++++++++++++++++++++++++++++++++++"
|
||||
exit
|
||||
fi
|
||||
fi
|
||||
|
||||
# Starting docker service
|
||||
if [ $package_manager == "yum" -o $package_manager == "apt-get" ];then
|
||||
start_docker
|
||||
fi
|
||||
|
||||
read -p 'Installation Directory [appsmith]: ' install_dir
|
||||
install_dir=${install_dir:-appsmith}
|
||||
mkdir -p $PWD/$install_dir
|
||||
|
|
@ -159,8 +226,11 @@ elif [ $fresh_install == "Y" -o $fresh_install == "y" -o $fresh_install == "yes"
|
|||
echo "Appsmith needs to create a mongo db"
|
||||
mongo_host="mongo"
|
||||
mongo_database="appsmith"
|
||||
read -p 'Set the mongo root user: ' mongo_root_user
|
||||
read -sp 'Set the mongo password: ' mongo_root_password
|
||||
|
||||
# We invoke functions to read the mongo credentials from the user because they MUST be non-empty
|
||||
read_mongo_username
|
||||
read_mongo_password
|
||||
|
||||
# Since the mongo was automatically setup, this must be the first time installation. Generate encryption credentials for this scenario
|
||||
auto_generate_encryption="true"
|
||||
fi
|
||||
|
|
@ -228,6 +298,8 @@ if [[ -z $custom_domain ]]; then
|
|||
NGINX_SSL_CMNT="#"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Downloading the configuration templates ..."
|
||||
mkdir -p template
|
||||
( cd template
|
||||
curl -O --silent https://raw.githubusercontent.com/appsmithorg/appsmith/release/deploy/template/docker-compose.yml.sh
|
||||
|
|
@ -238,31 +310,13 @@ curl -O --silent https://raw.githubusercontent.com/appsmithorg/appsmith/release/
|
|||
curl -O --silent https://raw.githubusercontent.com/appsmithorg/appsmith/release/deploy/template/encryption.env.sh
|
||||
)
|
||||
|
||||
# Role - Docker
|
||||
if ! is_command_present docker ;then
|
||||
if [ $package_manager == "apt-get" -o $package_manager == "yum" ];then
|
||||
install_docker
|
||||
else
|
||||
echo ""
|
||||
echo "+++++++++++ IMPORTANT READ ++++++++++++++++++++++"
|
||||
echo "Docker Desktop must be installed manually on Mac OS to proceed. Docker will be installed automatically on Ubuntu / Redhat / Cent OS"
|
||||
echo "https://docs.docker.com/docker-for-mac/install/"
|
||||
echo "++++++++++++++++++++++++++++++++++++++++++++++++"
|
||||
exit
|
||||
fi
|
||||
fi
|
||||
|
||||
# Starting docker service
|
||||
if [ $package_manager == "yum" -o $package_manager == "apt-get" ];then
|
||||
start_docker
|
||||
fi
|
||||
|
||||
# Role - Folder
|
||||
for directory_name in nginx certbot/conf certbot/www mongo/db
|
||||
do
|
||||
mkdir -p "$install_dir/data/$directory_name"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "Generating the configuration files from the templates"
|
||||
. ./template/nginx_app.conf.sh
|
||||
. ./template/docker-compose.yml.sh
|
||||
|
|
@ -295,15 +349,33 @@ echo "Pulling the latest container images"
|
|||
sudo docker-compose pull
|
||||
echo "Starting the Appsmith containers"
|
||||
sudo docker-compose -f docker-compose.yml up -d --remove-orphans
|
||||
|
||||
# These echo statements are important for some reason. The script doesn't run successfully without them.
|
||||
echo ""
|
||||
echo "+++++++++++ SUCCESS ++++++++++++++++++++++"
|
||||
echo "Your installation is complete. Please run the following command to ensure that all the containers are running without errors:"
|
||||
echo -ne "Waiting for all containers to start. This check will timeout in $timeout seconds ...\r\c"
|
||||
wait_for_containers_start 60
|
||||
echo ""
|
||||
echo "cd $install_dir && sudo docker-compose ps -a"
|
||||
echo "+++++++++++++++++++++++++++++++++++++++++++++++++"
|
||||
echo ""
|
||||
echo "Need help troubleshooting?"
|
||||
echo "Join our discord server https://discord.com/invite/rBTTVJp"
|
||||
echo ""
|
||||
echo "Your application is running on http://localhost"
|
||||
|
||||
if [[ $status_code -ne 401 ]]; then
|
||||
echo "+++++++++++ ERROR ++++++++++++++++++++++"
|
||||
echo "The containers didn't seem to start correctly. Please run the following command to check containers that may have errored out:"
|
||||
echo ""
|
||||
echo "cd $install_dir && sudo docker-compose ps -a"
|
||||
echo "For troubleshooting help, please reach out to us via our Discord server: https://discord.com/invite/rBTTVJp"
|
||||
echo "++++++++++++++++++++++++++++++++++++++++"
|
||||
echo ""
|
||||
else
|
||||
echo ""
|
||||
echo "+++++++++++ SUCCESS ++++++++++++++++++++++"
|
||||
echo "Your installation is complete. Please run the following command to ensure that all the containers are running without errors:"
|
||||
echo ""
|
||||
echo "cd $install_dir && sudo docker-compose ps -a"
|
||||
echo "+++++++++++++++++++++++++++++++++++++++++++++++++"
|
||||
echo ""
|
||||
echo "Need help troubleshooting?"
|
||||
echo "Join our Discord server https://discord.com/invite/rBTTVJp"
|
||||
echo ""
|
||||
echo "Your application is running on http://localhost"
|
||||
fi
|
||||
|
||||
echo -e "Peace out \U1F596"
|
||||
Loading…
Reference in New Issue
Block a user