mirror of
https://github.com/lingble/twenty.git
synced 2025-10-29 20:02:29 +00:00
Add deploy buttons and clean environment variables (#974)
* add render.yaml * Clean environment variables --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
@@ -5,15 +5,11 @@ services:
|
||||
context: ..
|
||||
dockerfile: ./infra/prod/front/Dockerfile
|
||||
args:
|
||||
REACT_APP_API_URL: "http://localhost:3000/graphql"
|
||||
REACT_APP_AUTH_URL: "http://localhost:3000/auth"
|
||||
REACT_APP_FILES_URL: "http://localhost:3000/files"
|
||||
REACT_APP_SERVER_BASE_URL: "http://localhost:3000"
|
||||
ports:
|
||||
- "3001:3000"
|
||||
labels:
|
||||
dev.ergomake.env.replace-arg.REACT_APP_API_URL: "https://{{ services.server.url }}/graphql"
|
||||
dev.ergomake.env.replace-arg.REACT_APP_AUTH_URL: "https://{{ services.server.url }}/auth"
|
||||
dev.ergomake.env.replace-arg.REACT_APP_FILES_URL: "https://{{ services.server.url }}/files"
|
||||
dev.ergomake.env.replace-arg.REACT_APP_SERVER_BASE_URL: "https://{{ services.server.url }}"
|
||||
server:
|
||||
build:
|
||||
context: ..
|
||||
@@ -23,19 +19,14 @@ services:
|
||||
- "3000:3000"
|
||||
environment:
|
||||
DEBUG_MODE: false
|
||||
DEMO_MODE: true
|
||||
IS_SIGN_IN_PREFILLED: true
|
||||
ACCESS_TOKEN_SECRET: "secret_jwt"
|
||||
ACCESS_TOKEN_EXPIRES_IN: "30m"
|
||||
LOGIN_TOKEN_SECRET: "secret_login_token"
|
||||
LOGIN_TOKEN_EXPIRES_IN: "15m"
|
||||
REFRESH_TOKEN_SECRET: "secret_refresh_token"
|
||||
REFRESH_TOKEN_EXPIRES_IN: "90d"
|
||||
PG_DATABASE_URL: "postgres://postgres:postgrespassword@postgres:5432/default?connection_limit=1"
|
||||
FRONT_AUTH_CALLBACK_URL: "http://localhost:3000/verify"
|
||||
STORAGE_TYPE: "local"
|
||||
STORAGE_LOCAL_PATH: ".local-storage"
|
||||
FRONT_BASE_URL: "http://localhost:3000"
|
||||
labels:
|
||||
dev.ergomake.env.replace-env.FRONT_AUTH_CALLBACK_URL: "https://{{ services.server.url }}/verify"
|
||||
dev.ergomake.env.replace-env.FRONT_BASE_URL: "https://{{ services.server.url }}"
|
||||
postgres:
|
||||
build: ../infra/dev/postgres
|
||||
environment:
|
||||
|
||||
8
.github/workflows/ci-chromatic.yaml
vendored
8
.github/workflows/ci-chromatic.yaml
vendored
@@ -11,9 +11,7 @@ jobs:
|
||||
if: ${{ contains(github.event.*.labels.*.name, 'run-chromatic') }} || github.event_name == 'push' }}
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
REACT_APP_API_URL: http://127.0.0.1:3000/graphql
|
||||
REACT_APP_AUTH_URL: http://127.0.0.1:3000/auth
|
||||
REACT_APP_FILES_URL: http://127.0.0.1:3000/files
|
||||
REACT_APP_SERVER_BASE_URL: http://127.0.0.1:3000
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
if: github.event_name == 'push'
|
||||
@@ -33,9 +31,7 @@ jobs:
|
||||
run: |
|
||||
cd front
|
||||
touch .env
|
||||
echo "REACT_APP_API_URL: $REACT_APP_API_URL" >> .env
|
||||
echo "REACT_APP_AUTH_URL: $REACT_APP_AUTH_URL" >> .env
|
||||
echo "REACT_APP_FILES_URL: $REACT_APP_FILES_URL" >> .env
|
||||
echo "REACT_APP_SERVER_BASE_URL: $REACT_APP_SERVER_BASE_URL" >> .env
|
||||
- name: Front / Install Dependencies
|
||||
run: cd front && yarn
|
||||
- name: Publish to Chromatic
|
||||
|
||||
4
.github/workflows/ci-front.yaml
vendored
4
.github/workflows/ci-front.yaml
vendored
@@ -8,9 +8,7 @@ jobs:
|
||||
front-test:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
REACT_APP_API_URL: http://localhost:3000/graphql
|
||||
REACT_APP_AUTH_URL: http://localhost:3000/auth
|
||||
REACT_APP_FILES_URL: http://localhost:3000/files
|
||||
REACT_APP_SERVER_BASE_URL: http://localhost:3000
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
if: github.event_name == 'push'
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
sidebar_position: 0
|
||||
sidebar_custom_props:
|
||||
icon: TbArrowBigRight
|
||||
icon: TbDeviceDesktop
|
||||
---
|
||||
|
||||
# Local Setup
|
||||
|
||||
@@ -19,9 +19,7 @@ You will find these in the [infra/prod/front/Dockerfile](https://github.com/twen
|
||||
|
||||
```bash
|
||||
docker build \
|
||||
--build-arg REACT_APP_API_URL=REPLACE_ME \
|
||||
--build-arg REACT_APP_AUTH_URL=REPLACE_ME \
|
||||
--build-arg REACT_APP_FILES_URL=REPLACE_ME \
|
||||
--build-arg REACT_APP_SERVER_BASE_URL=REPLACE_ME \
|
||||
-t twenty-front:latest \
|
||||
-f ./infra/prod/front/Dockerfile .
|
||||
```
|
||||
@@ -36,10 +34,19 @@ docker build \
|
||||
-f ./infra/prod/server/Dockerfile .
|
||||
```
|
||||
|
||||
## Render
|
||||
|
||||
[](https://render.com/deploy?repo=https://github.com/twentyhq/twenty)
|
||||
|
||||
|
||||
## AWS Elastic Beanstalk (soon)
|
||||
|
||||
We are working on providing a joint Docker image - containing both the Twenty frontend and server - that you can deploy using [AWS Elastic Beanstalk](https://aws.amazon.com/elasticbeanstalk/).
|
||||
|
||||
## Railway (soon)
|
||||
|
||||
[Railway](https://railway.app) is an infrastructure platform that lets you deploy to the cloud in one click. We are currently working on making it available.
|
||||
<!--
|
||||
|
||||
## Railway
|
||||
[](https://railway.app/template/YWGqza?referralCode=3CLObs)
|
||||
|
||||
-->
|
||||
@@ -4,6 +4,6 @@ sidebar_custom_props:
|
||||
icon: TbTerminal2
|
||||
---
|
||||
|
||||
# CLI (soon)
|
||||
# CLI
|
||||
|
||||
Available soon!
|
||||
@@ -6,7 +6,7 @@ import Link from '@docusaurus/Link';
|
||||
import isInternalUrl from '@docusaurus/isInternalUrl';
|
||||
import IconExternalLink from '@theme/Icon/ExternalLink';
|
||||
import styles from './styles.module.css';
|
||||
import { TbFaceIdError, TbTerminal2, TbCloud, TbServer, TbBolt, TbApps, TbTopologyStar, TbChartDots, TbBug, TbVocabulary, TbArrowBigRight } from "react-icons/tb";
|
||||
import { TbFaceIdError, TbTerminal2, TbCloud, TbServer, TbBolt, TbApps, TbTopologyStar, TbChartDots, TbBug, TbVocabulary, TbArrowBigRight, TbDeviceDesktop } from "react-icons/tb";
|
||||
|
||||
|
||||
export default function DocSidebarItemLink({
|
||||
@@ -30,7 +30,8 @@ export default function DocSidebarItemLink({
|
||||
'TbTopologyStar': TbTopologyStar,
|
||||
'TbChartDots': TbChartDots,
|
||||
'TbBug': TbBug,
|
||||
'TbVocabulary': TbVocabulary
|
||||
'TbVocabulary': TbVocabulary,
|
||||
'TbDeviceDesktop': TbDeviceDesktop,
|
||||
};
|
||||
|
||||
let IconComponent = customProps && customProps.icon ? icons[customProps.icon] : TbFaceIdError;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
REACT_APP_API_URL=http://localhost:3000/graphql
|
||||
REACT_APP_AUTH_URL=http://localhost:3000/auth
|
||||
REACT_APP_FILES_URL=http://localhost:3000/files
|
||||
REACT_APP_SERVER_BASE_URL=http://localhost:3000
|
||||
|
||||
CHROMATIC_PROJECT_TOKEN=REPLACE_ME
|
||||
# ———————— Optional ————————
|
||||
# REACT_APP_SERVER_AUTH_URL=http://localhost:3000/auth
|
||||
# REACT_APP_SERVER_FILES_URL=http://localhost:3000/files
|
||||
# CHROMATIC_PROJECT_TOKEN=
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
module.exports = {
|
||||
schema: process.env.REACT_APP_API_URL,
|
||||
schema: process.env.REACT_APP_SERVER_BASE_URL + "/graphql",
|
||||
documents: ['./src/**/*.tsx', './src/**/*.ts'],
|
||||
overwrite: true,
|
||||
generates: {
|
||||
|
||||
@@ -547,7 +547,7 @@ export type ClientConfig = {
|
||||
__typename?: 'ClientConfig';
|
||||
authProviders: AuthProviders;
|
||||
debugMode: Scalars['Boolean'];
|
||||
demoMode: Scalars['Boolean'];
|
||||
signInPrefilled: Scalars['Boolean'];
|
||||
telemetry: Telemetry;
|
||||
};
|
||||
|
||||
@@ -2333,7 +2333,7 @@ export type RenewTokenMutation = { __typename?: 'Mutation', renewToken: { __type
|
||||
export type GetClientConfigQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type GetClientConfigQuery = { __typename?: 'Query', clientConfig: { __typename?: 'ClientConfig', demoMode: boolean, debugMode: boolean, authProviders: { __typename?: 'AuthProviders', google: boolean, password: boolean }, telemetry: { __typename?: 'Telemetry', enabled: boolean, anonymizationEnabled: boolean } } };
|
||||
export type GetClientConfigQuery = { __typename?: 'Query', clientConfig: { __typename?: 'ClientConfig', signInPrefilled: boolean, debugMode: boolean, authProviders: { __typename?: 'AuthProviders', google: boolean, password: boolean }, telemetry: { __typename?: 'Telemetry', enabled: boolean, anonymizationEnabled: boolean } } };
|
||||
|
||||
export type GetCompaniesQueryVariables = Exact<{
|
||||
orderBy?: InputMaybe<Array<CompanyOrderByWithRelationInput> | CompanyOrderByWithRelationInput>;
|
||||
@@ -3369,7 +3369,7 @@ export const GetClientConfigDocument = gql`
|
||||
google
|
||||
password
|
||||
}
|
||||
demoMode
|
||||
signInPrefilled
|
||||
debugMode
|
||||
telemetry {
|
||||
enabled
|
||||
|
||||
@@ -22,7 +22,7 @@ export function useApolloFactory() {
|
||||
|
||||
const apolloClient = useMemo(() => {
|
||||
apolloRef.current = new ApolloFactory({
|
||||
uri: `${process.env.REACT_APP_API_URL}`,
|
||||
uri: `${process.env.REACT_APP_SERVER_BASE_URL}/graphql`,
|
||||
cache: new InMemoryCache({
|
||||
typePolicies: {
|
||||
Activity: {
|
||||
|
||||
@@ -118,8 +118,11 @@ export function useAuth() {
|
||||
);
|
||||
|
||||
const handleGoogleLogin = useCallback((workspaceInviteHash?: string) => {
|
||||
const authServerUrl =
|
||||
process.env.REACT_APP_SERVER_AUTH_URL ??
|
||||
process.env.REACT_APP_SERVER_BASE_URL + '/auth';
|
||||
window.location.href =
|
||||
`${process.env.REACT_APP_AUTH_URL}/google/${
|
||||
`${authServerUrl}/google/${
|
||||
workspaceInviteHash ? '?inviteHash=' + workspaceInviteHash : ''
|
||||
}` || '';
|
||||
}, []);
|
||||
|
||||
@@ -6,7 +6,7 @@ import { useRecoilState, useRecoilValue } from 'recoil';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
import { authProvidersState } from '@/client-config/states/authProvidersState';
|
||||
import { isDemoModeState } from '@/client-config/states/isDemoModeState';
|
||||
import { isSignInPrefilledState } from '@/client-config/states/isSignInPrefilledState';
|
||||
import { AppPath } from '@/types/AppPath';
|
||||
import { PageHotkeyScope } from '@/types/PageHotkeyScope';
|
||||
import { useSnackBar } from '@/ui/snack-bar/hooks/useSnackBar';
|
||||
@@ -45,7 +45,7 @@ export function useSignInUp() {
|
||||
const { enqueueSnackBar } = useSnackBar();
|
||||
const isMatchingLocation = useIsMatchingLocation();
|
||||
const [authProviders] = useRecoilState(authProvidersState);
|
||||
const isDemoMode = useRecoilValue(isDemoModeState);
|
||||
const isSignInPrefilled = useRecoilValue(isSignInPrefilledState);
|
||||
const workspaceInviteHash = useParams().workspaceInviteHash;
|
||||
const [signInUpStep, setSignInUpStep] = useState<SignInUpStep>(
|
||||
SignInUpStep.Init,
|
||||
@@ -61,8 +61,8 @@ export function useSignInUp() {
|
||||
mode: 'onChange',
|
||||
defaultValues: {
|
||||
exist: false,
|
||||
email: isDemoMode ? 'tim@apple.dev' : '',
|
||||
password: isDemoMode ? 'Applecar2025' : '',
|
||||
email: isSignInPrefilled ? 'tim@apple.dev' : '',
|
||||
password: isSignInPrefilled ? 'Applecar2025' : '',
|
||||
},
|
||||
resolver: yupResolver(validationSchema),
|
||||
});
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useRecoilState } from 'recoil';
|
||||
|
||||
import { authProvidersState } from '@/client-config/states/authProvidersState';
|
||||
import { isDebugModeState } from '@/client-config/states/isDebugModeState';
|
||||
import { isDemoModeState } from '@/client-config/states/isDemoModeState';
|
||||
import { isSignInPrefilledState } from '@/client-config/states/isSignInPrefilledState';
|
||||
import { telemetryState } from '@/client-config/states/telemetryState';
|
||||
import { useGetClientConfigQuery } from '~/generated/graphql';
|
||||
|
||||
@@ -12,7 +12,7 @@ export const ClientConfigProvider: React.FC<React.PropsWithChildren> = ({
|
||||
}) => {
|
||||
const [, setAuthProviders] = useRecoilState(authProvidersState);
|
||||
const [, setDebugMode] = useRecoilState(isDebugModeState);
|
||||
const [, setDemoMode] = useRecoilState(isDemoModeState);
|
||||
const [, setSignInPrefilled] = useRecoilState(isSignInPrefilledState);
|
||||
const [, setTelemetry] = useRecoilState(telemetryState);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
@@ -29,14 +29,14 @@ export const ClientConfigProvider: React.FC<React.PropsWithChildren> = ({
|
||||
magicLink: false,
|
||||
});
|
||||
setDebugMode(data?.clientConfig.debugMode);
|
||||
setDemoMode(data?.clientConfig.demoMode);
|
||||
setSignInPrefilled(data?.clientConfig.signInPrefilled);
|
||||
setTelemetry(data?.clientConfig.telemetry);
|
||||
}
|
||||
}, [
|
||||
data,
|
||||
setAuthProviders,
|
||||
setDebugMode,
|
||||
setDemoMode,
|
||||
setSignInPrefilled,
|
||||
setTelemetry,
|
||||
setIsLoading,
|
||||
loading,
|
||||
|
||||
@@ -7,7 +7,7 @@ export const GET_CLIENT_CONFIG = gql`
|
||||
google
|
||||
password
|
||||
}
|
||||
demoMode
|
||||
signInPrefilled
|
||||
debugMode
|
||||
telemetry {
|
||||
enabled
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
import { atom } from 'recoil';
|
||||
|
||||
export const isDemoModeState = atom<boolean>({
|
||||
key: 'isDemoModeState',
|
||||
default: false,
|
||||
});
|
||||
@@ -0,0 +1,6 @@
|
||||
import { atom } from 'recoil';
|
||||
|
||||
export const isSignInPrefilledState = atom<boolean>({
|
||||
key: 'isSignInPrefilledState',
|
||||
default: false,
|
||||
});
|
||||
@@ -11,5 +11,9 @@ export function getImageAbsoluteURIOrBase64(imageUrl?: string | null) {
|
||||
return imageUrl;
|
||||
}
|
||||
|
||||
return `${process.env.REACT_APP_FILES_URL}/${imageUrl}`;
|
||||
const serverFilesUrl =
|
||||
process.env.REACT_APP_SERVER_FILES_URL ??
|
||||
process.env.REACT_APP_SERVER_BASE_URL + '/files';
|
||||
|
||||
return `${serverFilesUrl}/${imageUrl}`;
|
||||
}
|
||||
|
||||
@@ -198,7 +198,7 @@ export const graphqlMocks = [
|
||||
return res(
|
||||
ctx.data({
|
||||
clientConfig: {
|
||||
demoMode: true,
|
||||
signInPrefilled: true,
|
||||
debugMode: false,
|
||||
authProviders: { google: true, password: true, magicLink: false },
|
||||
telemetry: { enabled: false, anonymizationEnabled: true },
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ApolloClient, InMemoryCache } from '@apollo/client';
|
||||
|
||||
export const mockedClient = new ApolloClient({
|
||||
uri: process.env.REACT_APP_API_URL,
|
||||
uri: process.env.REACT_APP_SERVER_BASE_URL + '/graphql',
|
||||
cache: new InMemoryCache(),
|
||||
});
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
FROM node:18.16.0-alpine as build
|
||||
|
||||
ARG REACT_APP_API_URL
|
||||
ARG REACT_APP_AUTH_URL
|
||||
ARG REACT_APP_FILES_URL
|
||||
|
||||
ARG REACT_APP_SERVER_BASE_URL
|
||||
ARG REACT_APP_SERVER_AUTH_URL
|
||||
ARG REACT_APP_SERVER_FILES_URL
|
||||
|
||||
COPY ./packages/ /app/packages
|
||||
|
||||
|
||||
42
render.yaml
Normal file
42
render.yaml
Normal file
@@ -0,0 +1,42 @@
|
||||
services:
|
||||
- type: web
|
||||
name: front
|
||||
env: docker
|
||||
dockerfilePath: ./infra/prod/front/Dockerfile
|
||||
autoDeploy: false
|
||||
envVars:
|
||||
- key: REACT_APP_SERVER_BASE_URL
|
||||
fromService:
|
||||
name: server
|
||||
type: web
|
||||
envVarKey: RENDER_EXTERNAL_URL
|
||||
- type: web
|
||||
name: server
|
||||
env: docker
|
||||
dockerfilePath: ./infra/prod/server/Dockerfile
|
||||
dockerCommand: "sh -c yarn prisma:migrate && node dist/src/main"
|
||||
autoDeploy: false
|
||||
envVars:
|
||||
- key: ACCESS_TOKEN_SECRET
|
||||
generateValue: true
|
||||
- key: LOGIN_TOKEN_SECRET
|
||||
generateValue: true
|
||||
- key: REFRESH_TOKEN_SECRET
|
||||
generateValue: true
|
||||
- key: PG_DATABASE_URL
|
||||
fromDatabase:
|
||||
name: twenty-db
|
||||
property: connectionString
|
||||
- key: FRONT_BASE_URL
|
||||
fromService:
|
||||
name: front
|
||||
type: web
|
||||
envVarKey: RENDER_EXTERNAL_URL
|
||||
disk:
|
||||
name: twenty-disk
|
||||
mountPath: /.local-storage
|
||||
sizeGB: 5
|
||||
|
||||
databases:
|
||||
- name: twenty-db
|
||||
plan: starter
|
||||
@@ -1,13 +1,16 @@
|
||||
DEBUG_MODE=false
|
||||
DEMO_MODE=true
|
||||
ACCESS_TOKEN_SECRET=secret_jwt
|
||||
ACCESS_TOKEN_EXPIRES_IN=30m
|
||||
LOGIN_TOKEN_SECRET=secret_login_token
|
||||
LOGIN_TOKEN_EXPIRES_IN=15m
|
||||
REFRESH_TOKEN_SECRET=secret_refresh_token
|
||||
REFRESH_TOKEN_EXPIRES_IN=90d
|
||||
PG_DATABASE_URL=postgres://postgres:postgrespassword@localhost:5432/default?connection_limit=1
|
||||
FRONT_AUTH_CALLBACK_URL=http://localhost:3001/verify
|
||||
STORAGE_TYPE=local
|
||||
STORAGE_LOCAL_PATH=.local-storage
|
||||
FRONT_BASE_URL=http://localhost:3001
|
||||
ACCESS_TOKEN_SECRET=replace_me_with_a_random_string
|
||||
LOGIN_TOKEN_SECRET=replace_me_with_a_random_string
|
||||
REFRESH_TOKEN_SECRET=replace_me_with_a_random_string
|
||||
IS_SIGN_IN_PREFILLED=true
|
||||
|
||||
# ———————— Optional ————————
|
||||
# DEBUG_MODE=true
|
||||
# ACCESS_TOKEN_EXPIRES_IN=30m
|
||||
# LOGIN_TOKEN_EXPIRES_IN=15m
|
||||
# REFRESH_TOKEN_EXPIRES_IN=90d
|
||||
# FRONT_AUTH_CALLBACK_URL=http://localhost:3001/verify
|
||||
# AUTH_GOOGLE_ENABLED=false
|
||||
# STORAGE_TYPE=local
|
||||
# STORAGE_LOCAL_PATH=.local-storage
|
||||
@@ -1,12 +1,20 @@
|
||||
DEBUG_MODE=true
|
||||
AUTH_GOOGLE_ENABLED=false
|
||||
ACCESS_TOKEN_SECRET=secret_jwt
|
||||
ACCESS_TOKEN_EXPIRES_IN=1d
|
||||
REFRESH_TOKEN_SECRET=secret_refresh_token
|
||||
REFRESH_TOKEN_EXPIRES_IN=30d
|
||||
LOGIN_TOKEN_SECRET=secret_login_token
|
||||
LOGIN_TOKEN_EXPIRES_IN=15m
|
||||
FRONT_AUTH_CALLBACK_URL=http://localhost:3001/auth/callback
|
||||
PG_DATABASE_URL=postgres://postgres:postgrespassword@localhost:5432/test?connection_limit=1
|
||||
STORAGE_TYPE=local
|
||||
STORAGE_LOCAL_PATH=.local-storage
|
||||
# the URL of the front-end app
|
||||
FRONT_BASE_URL=http://localhost:3001
|
||||
# random keys used to generate JWT tokens
|
||||
ACCESS_TOKEN_SECRET=secret_jwt
|
||||
LOGIN_TOKEN_SECRET=secret_login_tokens
|
||||
REFRESH_TOKEN_SECRET=secret_refresh_token
|
||||
|
||||
|
||||
# ———————— Optional ————————
|
||||
# DEBUG_MODE=false
|
||||
# IS_SIGN_IN_PREFILLED=false
|
||||
# ACCESS_TOKEN_EXPIRES_IN=30m
|
||||
# LOGIN_TOKEN_EXPIRES_IN=15m
|
||||
# REFRESH_TOKEN_EXPIRES_IN=90d
|
||||
# FRONT_AUTH_CALLBACK_URL=http://localhost:3001/verify
|
||||
# AUTH_GOOGLE_ENABLED=false
|
||||
# STORAGE_TYPE=local
|
||||
# STORAGE_LOCAL_PATH=.local-storage
|
||||
@@ -11,7 +11,14 @@ ENV_PATH="${SCRIPT_DIR}/../.env.test"
|
||||
if [ -f "${ENV_PATH}" ]; then
|
||||
echo "🔵 - Loading environment variables from "${ENV_PATH}"..."
|
||||
# Export env vars
|
||||
export $(grep -v '^#' ${ENV_PATH} | xargs)
|
||||
while IFS= read -r line || [ -n "$line" ]; do
|
||||
if echo "$line" | grep -F = &>/dev/null
|
||||
then
|
||||
varname=$(echo "$line" | cut -d '=' -f 1)
|
||||
varvalue=$(echo "$line" | cut -d '=' -f 2- | cut -d '#' -f 1)
|
||||
export "$varname"="$varvalue"
|
||||
fi
|
||||
done < <(grep -v '^#' "${ENV_PATH}")
|
||||
else
|
||||
echo "Error: ${ENV_PATH} does not exist."
|
||||
exit 1
|
||||
|
||||
@@ -47,9 +47,10 @@ export class UpdateActivityTargetAbilityHandler implements IAbilityHandler {
|
||||
async handle(ability: AppAbility, context: ExecutionContext) {
|
||||
const gqlContext = GqlExecutionContext.create(context);
|
||||
const args = gqlContext.getArgs<ActivityTargetArgs>();
|
||||
const ActivityTarget = await this.prismaService.client.activityTarget.findFirst({
|
||||
where: args.where,
|
||||
});
|
||||
const ActivityTarget =
|
||||
await this.prismaService.client.activityTarget.findFirst({
|
||||
where: args.where,
|
||||
});
|
||||
assert(ActivityTarget, '', NotFoundException);
|
||||
|
||||
return ability.can(
|
||||
@@ -66,9 +67,10 @@ export class DeleteActivityTargetAbilityHandler implements IAbilityHandler {
|
||||
async handle(ability: AppAbility, context: ExecutionContext) {
|
||||
const gqlContext = GqlExecutionContext.create(context);
|
||||
const args = gqlContext.getArgs<ActivityTargetArgs>();
|
||||
const ActivityTarget = await this.prismaService.client.activityTarget.findFirst({
|
||||
where: args.where,
|
||||
});
|
||||
const ActivityTarget =
|
||||
await this.prismaService.client.activityTarget.findFirst({
|
||||
where: args.where,
|
||||
});
|
||||
assert(ActivityTarget, '', NotFoundException);
|
||||
|
||||
return ability.can(
|
||||
|
||||
@@ -30,7 +30,7 @@ export class ClientConfig {
|
||||
telemetry: Telemetry;
|
||||
|
||||
@Field(() => Boolean)
|
||||
demoMode: boolean;
|
||||
signInPrefilled: boolean;
|
||||
|
||||
@Field(() => Boolean)
|
||||
debugMode: boolean;
|
||||
|
||||
@@ -12,17 +12,17 @@ export class ClientConfigResolver {
|
||||
async clientConfig(): Promise<ClientConfig> {
|
||||
const clientConfig: ClientConfig = {
|
||||
authProviders: {
|
||||
google: this.environmentService.isAuthGoogleEnabled() ?? false,
|
||||
google: this.environmentService.isAuthGoogleEnabled(),
|
||||
magicLink: false,
|
||||
password: true,
|
||||
},
|
||||
telemetry: {
|
||||
enabled: this.environmentService.isTelemetryEnabled() ?? false,
|
||||
enabled: this.environmentService.isTelemetryEnabled(),
|
||||
anonymizationEnabled:
|
||||
this.environmentService.isTelemetryAnonymizationEnabled() ?? false,
|
||||
this.environmentService.isTelemetryAnonymizationEnabled(),
|
||||
},
|
||||
demoMode: this.environmentService.isDemoMode() ?? false,
|
||||
debugMode: this.environmentService.isDebugMode() ?? false,
|
||||
signInPrefilled: this.environmentService.isSignInPrefilled(),
|
||||
debugMode: this.environmentService.isDebugMode(),
|
||||
};
|
||||
|
||||
return Promise.resolve(clientConfig);
|
||||
|
||||
@@ -13,15 +13,15 @@ export class EnvironmentService {
|
||||
return this.configService.get<boolean>('DEBUG_MODE') ?? false;
|
||||
}
|
||||
|
||||
isDemoMode(): boolean {
|
||||
return this.configService.get<boolean>('DEMO_MODE') ?? false;
|
||||
isSignInPrefilled(): boolean {
|
||||
return this.configService.get<boolean>('IS_SIGN_IN_PREFILLED') ?? false;
|
||||
}
|
||||
|
||||
isTelemetryEnabled(): boolean {
|
||||
return this.configService.get<boolean>('TELEMETRY_ENABLED') ?? true;
|
||||
}
|
||||
|
||||
isTelemetryAnonymizationEnabled(): boolean | undefined {
|
||||
isTelemetryAnonymizationEnabled(): boolean {
|
||||
return (
|
||||
this.configService.get<boolean>('TELEMETRY_ANONYMIZATION_ENABLED') ?? true
|
||||
);
|
||||
@@ -31,12 +31,16 @@ export class EnvironmentService {
|
||||
return this.configService.get<string>('PG_DATABASE_URL')!;
|
||||
}
|
||||
|
||||
getFrontBaseUrl(): string {
|
||||
return this.configService.get<string>('FRONT_BASE_URL')!;
|
||||
}
|
||||
|
||||
getAccessTokenSecret(): string {
|
||||
return this.configService.get<string>('ACCESS_TOKEN_SECRET')!;
|
||||
}
|
||||
|
||||
getAccessTokenExpiresIn(): string {
|
||||
return this.configService.get<string>('ACCESS_TOKEN_EXPIRES_IN')!;
|
||||
return this.configService.get<string>('ACCESS_TOKEN_EXPIRES_IN') ?? '30m';
|
||||
}
|
||||
|
||||
getRefreshTokenSecret(): string {
|
||||
@@ -44,7 +48,7 @@ export class EnvironmentService {
|
||||
}
|
||||
|
||||
getRefreshTokenExpiresIn(): string {
|
||||
return this.configService.get<string>('REFRESH_TOKEN_EXPIRES_IN')!;
|
||||
return this.configService.get<string>('REFRESH_TOKEN_EXPIRES_IN') ?? '90d';
|
||||
}
|
||||
|
||||
getLoginTokenSecret(): string {
|
||||
@@ -52,15 +56,18 @@ export class EnvironmentService {
|
||||
}
|
||||
|
||||
getLoginTokenExpiresIn(): string {
|
||||
return this.configService.get<string>('LOGIN_TOKEN_EXPIRES_IN')!;
|
||||
return this.configService.get<string>('LOGIN_TOKEN_EXPIRES_IN') ?? '15m';
|
||||
}
|
||||
|
||||
getFrontAuthCallbackUrl(): string {
|
||||
return this.configService.get<string>('FRONT_AUTH_CALLBACK_URL')!;
|
||||
return (
|
||||
this.configService.get<string>('FRONT_AUTH_CALLBACK_URL') ??
|
||||
this.getFrontBaseUrl() + '/auth/callback'
|
||||
);
|
||||
}
|
||||
|
||||
isAuthGoogleEnabled(): boolean | undefined {
|
||||
return this.configService.get<boolean>('AUTH_GOOGLE_ENABLED');
|
||||
isAuthGoogleEnabled(): boolean {
|
||||
return this.configService.get<boolean>('AUTH_GOOGLE_ENABLED') ?? false;
|
||||
}
|
||||
|
||||
getAuthGoogleClientId(): string | undefined {
|
||||
@@ -75,8 +82,10 @@ export class EnvironmentService {
|
||||
return this.configService.get<string>('AUTH_GOOGLE_CALLBACK_URL');
|
||||
}
|
||||
|
||||
getStorageType(): StorageType | undefined {
|
||||
return this.configService.get<StorageType>('STORAGE_TYPE');
|
||||
getStorageType(): StorageType {
|
||||
return (
|
||||
this.configService.get<StorageType>('STORAGE_TYPE') ?? StorageType.Local
|
||||
);
|
||||
}
|
||||
|
||||
getStorageS3Region(): AwsRegion | undefined {
|
||||
@@ -87,7 +96,9 @@ export class EnvironmentService {
|
||||
return this.configService.get<AwsRegion>('STORAGE_S3_NAME');
|
||||
}
|
||||
|
||||
getStorageLocalPath(): string | undefined {
|
||||
return this.configService.get<string>('STORAGE_LOCAL_PATH')!;
|
||||
getStorageLocalPath(): string {
|
||||
return (
|
||||
this.configService.get<string>('STORAGE_LOCAL_PATH') ?? '.local-storage'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ export class EnvironmentVariables {
|
||||
@CastToBoolean()
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
DEMO_MODE?: boolean;
|
||||
IS_SIGN_IN_PREFILLED?: boolean;
|
||||
|
||||
@CastToBoolean()
|
||||
@IsOptional()
|
||||
@@ -43,24 +43,32 @@ export class EnvironmentVariables {
|
||||
@IsUrl({ protocols: ['postgres'], require_tld: false })
|
||||
PG_DATABASE_URL: string;
|
||||
|
||||
// Frontend URL
|
||||
@IsUrl({ require_tld: false })
|
||||
FRONT_BASE_URL: string;
|
||||
|
||||
// Json Web Token
|
||||
@IsString()
|
||||
ACCESS_TOKEN_SECRET: string;
|
||||
@IsDuration()
|
||||
@IsOptional()
|
||||
ACCESS_TOKEN_EXPIRES_IN: string;
|
||||
|
||||
@IsString()
|
||||
REFRESH_TOKEN_SECRET: string;
|
||||
@IsDuration()
|
||||
@IsOptional()
|
||||
REFRESH_TOKEN_EXPIRES_IN: string;
|
||||
|
||||
@IsString()
|
||||
LOGIN_TOKEN_SECRET: string;
|
||||
@IsDuration()
|
||||
@IsOptional()
|
||||
LOGIN_TOKEN_EXPIRES_IN: string;
|
||||
|
||||
// Auth
|
||||
@IsUrl({ require_tld: false })
|
||||
@IsOptional()
|
||||
FRONT_AUTH_CALLBACK_URL: string;
|
||||
|
||||
@CastToBoolean()
|
||||
|
||||
@@ -19,7 +19,6 @@ const fileStorageModuleFactory = async (
|
||||
const type = environmentService.getStorageType();
|
||||
|
||||
switch (type) {
|
||||
case undefined:
|
||||
case StorageType.Local: {
|
||||
const storagePath = environmentService.getStorageLocalPath();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user