Skip to content

Commit

Permalink
Merge pull request #1985 from ever-co/improve-recaptcha
Browse files Browse the repository at this point in the history
Improve Env Variable Retrieval
  • Loading branch information
evereq authored Dec 12, 2023
2 parents bf63081 + 3e1a9ff commit cd4adbe
Show file tree
Hide file tree
Showing 25 changed files with 241 additions and 94 deletions.
68 changes: 57 additions & 11 deletions apps/web/app/constants.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { JitsuOptions } from '@jitsu/jitsu-react/dist/useJitsu';
import { I_SMTPRequest } from './interfaces/ISmtp';
import { getNextPublicEnv } from './env';

export const API_BASE_URL = '/api';
export const DEFAULT_APP_PATH = '/auth/passcode';
Expand Down Expand Up @@ -28,24 +29,47 @@ export const NO_TEAM_POPUP_SHOW_COOKIE_NAME = 'no-team-popup-show';
export const ACTIVE_PROJECT_COOKIE_NAME = 'auth-active-project';

// Recaptcha
export const RECAPTCHA_SITE_KEY = process.env.NEXT_PUBLIC_CAPTCHA_SITE_KEY;
export const RECAPTCHA_SITE_KEY = getNextPublicEnv(
'NEXT_PUBLIC_CAPTCHA_SITE_KEY',
process.env.NEXT_PUBLIC_CAPTCHA_SITE_KEY
);
export const RECAPTCHA_SECRET_KEY = process.env.CAPTCHA_SECRET_KEY;

// Gauzy Server URL
export const GAUZY_API_SERVER_URL = process.env.GAUZY_API_SERVER_URL || 'https://api.gauzy.co/api';
export const GAUZY_API_BASE_SERVER_URL = getNextPublicEnv(
'NEXT_PUBLIC_GAUZY_API_SERVER_URL',
process.env.NEXT_PUBLIC_GAUZY_API_SERVER_URL
);

// Invite
export const INVITE_CALLBACK_URL = process.env.INVITE_CALLBACK_URL || 'https://app.ever.team/auth/passcode';
export const INVITE_CALLBACK_PATH = '/auth/passcode';
export const VERIFY_EMAIL_CALLBACK_URL = process.env.VERIFY_EMAIL_CALLBACK_URL || 'https://app.ever.team/verify-email';
export const VERIFY_EMAIL_CALLBACK_PATH = '/verify-email';
export const GA_MEASUREMENT_ID = process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID;
export const GA_MEASUREMENT_ID = getNextPublicEnv(
'NEXT_PUBLIC_GA_MEASUREMENT_ID',
process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID
);

// Chatwoot
export const CHATWOOT_API_KEY = getNextPublicEnv(
'NEXT_PUBLIC_CHATWOOT_API_KEY',
process.env.NEXT_PUBLIC_CHATWOOT_API_KEY
);

export const SMTP_FROM_ADDRESS = process.env.SMTP_FROM_ADDRESS || '[email protected]';
export const SMTP_HOST = process.env.SMTP_HOST || '';
export const SMTP_PORT = process.env.SMTP_PORT || '';
export const SMTP_SECURE = process.env.SMTP_SECURE || '';
export const SMTP_USERNAME = process.env.SMTP_USERNAME || '';
export const SMTP_PASSWORD = process.env.SMTP_PASSWORD || '';
export const DISABLE_AUTO_REFRESH = process.env.NEXT_PUBLIC_DISABLE_AUTO_REFRESH === 'true';
export const DISABLE_AUTO_REFRESH = getNextPublicEnv('NEXT_PUBLIC_DISABLE_AUTO_REFRESH', {
default: process.env.NEXT_PUBLIC_DISABLE_AUTO_REFRESH,
map(value) {
return value === 'true';
}
});

export const APP_NAME = process.env.APP_NAME || 'Ever Teams';
export const APP_SIGNATURE = process.env.APP_SIGNATURE || 'Ever Teams';
Expand All @@ -64,31 +88,53 @@ export const smtpConfiguration: () => I_SMTPRequest = () => ({
});

// Cookies
export const COOKIE_DOMAINS = (process.env.NEXT_PUBLIC_COOKIE_DOMAINS || 'ever.team').split(',').map((d) => d.trim());
export const COOKIE_DOMAINS = getNextPublicEnv('NEXT_PUBLIC_COOKIE_DOMAINS', {
default: process.env.NEXT_PUBLIC_COOKIE_DOMAINS || 'ever.team',
map(value) {
return value?.split(',').map((d) => d.trim()) || [];
}
});

// MEET Constants
export const MEET_DOMAIN = process.env.NEXT_PUBLIC_MEET_DOMAIN || 'meet.ever.team';
export const MEET_DOMAIN = getNextPublicEnv(
'NEXT_PUBLIC_MEET_DOMAIN',
process.env.NEXT_PUBLIC_MEET_DOMAIN || 'meet.ever.team'
);
export const MEET_JWT_APP_ID = process.env.MEET_JWT_APP_ID || 'ever_teams';
export const MEET_JWT_APP_SECRET = process.env.MEET_JWT_APP_SECRET;
export const MEET_JWT_TOKEN_COOKIE_NAME = 'meet-jwt-session';

// BOARD board
export const BOARD_APP_DOMAIN = process.env.NEXT_PUBLIC_BOARD_APP_DOMAIN || 'https://board.ever.team';
export const BOARD_BACKEND_POST_URL = process.env.NEXT_PUBLIC_BOARD_BACKEND_POST_URL || 'https://jsonboard.ever.team/api/v2/post/';
export const BOARD_FIREBASE_CONFIG = process.env.NEXT_PUBLIC_BOARD_FIREBASE_CONFIG;
export const BOARD_APP_DOMAIN = getNextPublicEnv(
'NEXT_PUBLIC_BOARD_APP_DOMAIN',
process.env.NEXT_PUBLIC_BOARD_APP_DOMAIN || 'https://board.ever.team'
);

export const BOARD_BACKEND_POST_URL = getNextPublicEnv(
'NEXT_PUBLIC_BOARD_BACKEND_POST_URL',
process.env.NEXT_PUBLIC_BOARD_BACKEND_POST_URL || 'https://jsonboard.ever.team/api/v2/post/'
);
export const BOARD_FIREBASE_CONFIG = getNextPublicEnv(
'NEXT_PUBLIC_BOARD_FIREBASE_CONFIG',
process.env.NEXT_PUBLIC_BOARD_FIREBASE_CONFIG
);

// Jitsu
export const jitsuConfiguration: () => JitsuOptions = () => ({
host: process.env.NEXT_PUBLIC_JITSU_BROWSER_URL || '',
writeKey: process.env.NEXT_PUBLIC_JITSU_BROWSER_WRITE_KEY || '',
host: getNextPublicEnv('NEXT_PUBLIC_JITSU_BROWSER_URL', process.env.NEXT_PUBLIC_JITSU_BROWSER_URL).value,
writeKey: getNextPublicEnv('NEXT_PUBLIC_JITSU_BROWSER_WRITE_KEY', process.env.NEXT_PUBLIC_JITSU_BROWSER_WRITE_KEY)
.value,
// if enabled - events will be sent to the console but no data sent to Jitsu.
// Strange this is not mentioned in the documentation https://github.com/jitsucom/jitsu/blob/35c4ecaff54d61a87853381cb17262b7bfbd4a6e/libs/jitsu-js/src/jitsu.ts#L40
echoEvents: false,
debug: false
});

// Github Integration
export const GITHUB_APP_NAME = process.env.NEXT_PUBLIC_GITHUB_APP_NAME || 'ever-github';
export const GITHUB_APP_NAME = getNextPublicEnv(
'NEXT_PUBLIC_GITHUB_APP_NAME',
process.env.NEXT_PUBLIC_GITHUB_APP_NAME || 'ever-github'
);

// Application Languages
export const APPLICATION_LANGUAGES = [
Expand Down
65 changes: 65 additions & 0 deletions apps/web/app/env.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
const NEXT_PUBLIC_ENVS: { value: Env } = { value: {} };

type Env = Record<string, string | undefined>;

type OptionObject<T> = {
default?: string;
map?: (value: string | undefined) => T;
};
type Options<T> = string | OptionObject<T>;

type InferValue<T> = T extends { map: (value: any) => infer U } ? U : string | undefined;

type ReturnedType<T> = {
readonly value: T extends string ? string : InferValue<T>;
};

/**
* This function only loads environment variables starting with NEXT_PUBLIC_*
*
* Useful for getting the latest value of the variable at runtime rather than at build time
*
* @param name
* @param options
* @returns
*/
export function getNextPublicEnv<O extends Options<unknown>>(name: string, options?: O): ReturnedType<O> {
return {
get value() {
const defaultValue = typeof options === 'string' ? options : options?.default;

let value = NEXT_PUBLIC_ENVS.value[name] || defaultValue;
if (typeof options === 'object' && options.map) {
value = options.map(value) as any;
}

return value as any;
}
};
}

export function setNextPublicEnv(envs: Env) {
if (envs) {
NEXT_PUBLIC_ENVS.value = {
...NEXT_PUBLIC_ENVS.value,
...envs
};
}
}

export function loadNextPublicEnvs() {
return Object.keys(process.env)
.filter((key) => key.startsWith('NEXT_PUBLIC'))
.reduce(
(acc, value) => {
if (process.env[value]) {
acc[value] = process.env[value] as string;
}
return acc;
},
{} as Record<string, string>
);
}

// Preload Some variables
setNextPublicEnv(loadNextPublicEnvs());
4 changes: 2 additions & 2 deletions apps/web/app/helpers/cookies/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { deleteCookie as _deleteCookie, getCookie as _getCookie, setCookie as _s
export const deleteCookie: typeof _deleteCookie = (key, options) => {
_deleteCookie(key, options);

COOKIE_DOMAINS.forEach((domain) => {
COOKIE_DOMAINS.value.forEach((domain) => {
_deleteCookie(key, {
domain,
...options
Expand All @@ -22,7 +22,7 @@ export const setCookie: SetCookie = (key, data, options, crossSite) => {
_setCookie(key, data, options);

crossSite &&
COOKIE_DOMAINS.forEach((domain) => {
COOKIE_DOMAINS.value.forEach((domain) => {
_setCookie(key, data, {
domain,
...options
Expand Down
3 changes: 2 additions & 1 deletion apps/web/app/hooks/features/useImageAssets.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { getAccessTokenCookie } from '@app/helpers';
import { useCallback, useState } from 'react';
import axios, { AxiosResponse } from 'axios';
import { GAUZY_API_BASE_SERVER_URL } from '@app/constants';

export function useImageAssets() {
const [loading, setLoading] = useState(false);
Expand All @@ -15,7 +16,7 @@ export function useImageAssets() {
setLoading(true);

return axios
.post(process.env.NEXT_PUBLIC_GAUZY_API_SERVER_URL + `/api/image-assets/upload/${folder}`, formData, {
.post(GAUZY_API_BASE_SERVER_URL.value + `/api/image-assets/upload/${folder}`, formData, {
headers: {
'tenant-id': tenantId,
authorization: `Bearer ${bearer_token}`
Expand Down
4 changes: 2 additions & 2 deletions apps/web/app/hooks/useCollaborative.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ export function useCollaborative(user?: IUser) {
const onBoardClick = useCallback(() => {
const members = collaborativeMembers.map((m) => m.id).join(',');

if (collaborativeMembers.length > 0 && BOARD_APP_DOMAIN) {
const url = new URL(BOARD_APP_DOMAIN);
if (collaborativeMembers.length > 0 && BOARD_APP_DOMAIN.value) {
const url = new URL(BOARD_APP_DOMAIN.value);
url.searchParams.set('live', 'true');
url.searchParams.set('members', btoa(members));

Expand Down
3 changes: 2 additions & 1 deletion apps/web/app/services/client/api/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { getRefreshTokenCookie } from '@app/helpers/cookies';
import { ISuccessResponse } from '@app/interfaces';
import { ILoginResponse, IRegisterDataAPI, ISigninEmailConfirmResponse } from '@app/interfaces/IAuthentication';
import api, { get } from '../axios';
import { GAUZY_API_BASE_SERVER_URL } from '@app/constants';

export const signInWithEmailAndCodeAPI = (email: string, code: string) => {
return api.post<ILoginResponse>(`/auth/login`, {
Expand Down Expand Up @@ -44,7 +45,7 @@ export const getAuthenticatedUserDataAPI = async () => {
const endpoint = `/user/me?${query.toString()}`;
const data = await get(endpoint, true);

return process.env.NEXT_PUBLIC_GAUZY_API_SERVER_URL ? data.data : data;
return GAUZY_API_BASE_SERVER_URL.value ? data.data : data;
};

export const verifyUserEmailByCodeAPI = (code: string) => {
Expand Down
9 changes: 4 additions & 5 deletions apps/web/app/services/client/api/employee.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { GAUZY_API_BASE_SERVER_URL } from '@app/constants';
import { get } from '../axios';

export async function getWorkingEmployeesAPI(tenantId: string, organizationId: string) {
Expand All @@ -6,12 +7,10 @@ export async function getWorkingEmployeesAPI(tenantId: string, organizationId: s
'where[organizationId]': organizationId,
'relations[0]': 'user'
};
const query = new URLSearchParams(params);
const query = new URLSearchParams(params);

const endpoint = process.env.NEXT_PUBLIC_GAUZY_API_SERVER_URL
? `/employee/pagination?${query.toString()}`
: '/employee/working';
const endpoint = GAUZY_API_BASE_SERVER_URL.value ? `/employee/pagination?${query.toString()}` : '/employee/working';
const data = await get(endpoint, true, { tenantId });

return process.env.NEXT_PUBLIC_GAUZY_API_SERVER_URL ? data.data : data;
return GAUZY_API_BASE_SERVER_URL.value ? data.data : data;
}
8 changes: 4 additions & 4 deletions apps/web/app/services/client/api/invite.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { PaginationResponse } from '@app/interfaces/IDataResponse';
import { IInvitation, MyInvitationActionEnum, CreateResponse, IInviteCreate, IRole } from '@app/interfaces';
import { INVITE_CALLBACK_URL } from '@app/constants';
import { GAUZY_API_BASE_SERVER_URL, INVITE_CALLBACK_URL } from '@app/constants';
import api, { get, post } from '../axios';
import { AxiosResponse } from 'axios';

Expand Down Expand Up @@ -41,7 +41,7 @@ export async function inviteByEmailsAPI(data: IIInviteRequest, tenantId: string)
// for not direct call we need to adjust data to include name and email only
const fetchData = await post(endpoint, dataToInviteUser, true, { tenantId });

return process.env.NEXT_PUBLIC_GAUZY_API_SERVER_URL ? fetchData.data : fetchData;
return GAUZY_API_BASE_SERVER_URL.value ? fetchData.data : fetchData;
}

export async function getTeamInvitationsAPI(tenantId: string, organizationId: string, role: string, teamId: string) {
Expand All @@ -56,7 +56,7 @@ export async function getTeamInvitationsAPI(tenantId: string, organizationId: st
const endpoint = `/invite?${query.toString()}`;
const data = await get(endpoint, true, { tenantId });

return process.env.NEXT_PUBLIC_GAUZY_API_SERVER_URL ? data.data : data;
return GAUZY_API_BASE_SERVER_URL.value ? data.data : data;
}

export function removeTeamInvitationsAPI(invitationId: string) {
Expand All @@ -73,7 +73,7 @@ export async function getMyInvitationsAPI(tenantId: string) {
const endpoint = '/invite/me';
const data = await get(endpoint, true, { tenantId });

return process.env.NEXT_PUBLIC_GAUZY_API_SERVER_URL ? data.data : data;
return GAUZY_API_BASE_SERVER_URL.value ? data.data : data;
}

export function acceptRejectMyInvitationsAPI(invitationId: string, action: MyInvitationActionEnum) {
Expand Down
3 changes: 2 additions & 1 deletion apps/web/app/services/client/api/languages.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { GAUZY_API_BASE_SERVER_URL } from '@app/constants';
import { get } from '../axios';

export async function getLanguageListAPI(is_system: boolean) {
const endpoint = `/languages?is_system=${is_system}`;
const data = await get(endpoint, true);

return process.env.NEXT_PUBLIC_GAUZY_API_SERVER_URL ? data.data : data;
return GAUZY_API_BASE_SERVER_URL.value ? data.data : data;
}
5 changes: 3 additions & 2 deletions apps/web/app/services/client/api/organization-team.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
} from '@app/interfaces';
import moment from 'moment';
import api, { get } from '../axios';
import { GAUZY_API_BASE_SERVER_URL } from '@app/constants';

export async function getOrganizationTeamsAPI(organizationId: string, tenantId: string) {
const relations = [
Expand Down Expand Up @@ -36,7 +37,7 @@ export async function getOrganizationTeamsAPI(organizationId: string, tenantId:
const endpoint = `/organization-team?${query.toString()}`;

const data = await get(endpoint, true, { tenantId });
return process.env.NEXT_PUBLIC_GAUZY_API_SERVER_URL ? data.data : data;
return GAUZY_API_BASE_SERVER_URL.value ? data.data : data;
}

export function createOrganizationTeamAPI(name: string) {
Expand Down Expand Up @@ -74,7 +75,7 @@ export async function getOrganizationTeamAPI(teamId: string, organizationId: str
const endpoint = `/organization-team/${teamId}?${queries.toString()}`;
const data = await get(endpoint, true);

return process.env.NEXT_PUBLIC_GAUZY_API_SERVER_URL ? data.data : data;
return GAUZY_API_BASE_SERVER_URL.value ? data.data : data;
}

export function editOrganizationTeamAPI(data: IOrganizationTeamUpdate) {
Expand Down
7 changes: 4 additions & 3 deletions apps/web/app/services/client/api/tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { CreateResponse, DeleteResponse, PaginationResponse } from '@app/interfa
import { ICreateTask, ITeamTask } from '@app/interfaces/ITask';
import { ITasksTimesheet } from '@app/interfaces/ITimer';
import api, { get } from '../axios';
import { GAUZY_API_BASE_SERVER_URL } from '@app/constants';

export function getTasksByIdAPI(taskId: string) {
return api.get<CreateResponse<ITeamTask>>(`/tasks/${taskId}`);
Expand Down Expand Up @@ -40,7 +41,7 @@ export async function getTeamTasksAPI(organizationId: string, tenantId: string,
const endpoint = `/tasks/team?${query.toString()}`;
const data = await get(endpoint, true, { tenantId });

return process.env.NEXT_PUBLIC_GAUZY_API_SERVER_URL ? data.data : data;
return GAUZY_API_BASE_SERVER_URL.value ? data.data : data;
}

export function deleteTaskAPI(taskId: string) {
Expand All @@ -61,7 +62,7 @@ export async function tasksTimesheetStatisticsAPI(
organizationId: string,
employeeId?: string
) {
if (process.env.NEXT_PUBLIC_GAUZY_API_SERVER_URL) {
if (GAUZY_API_BASE_SERVER_URL.value) {
const employeesParams = employeeId
? [employeeId].reduce((acc: any, v, i) => {
acc[`employeeIds[${i}]`] = v;
Expand Down Expand Up @@ -109,7 +110,7 @@ export async function activeTaskTimesheetStatisticsAPI(
organizationId: string,
employeeId?: string
) {
if (process.env.NEXT_PUBLIC_GAUZY_API_SERVER_URL) {
if (GAUZY_API_BASE_SERVER_URL.value) {
const employeesParams = employeeId
? [employeeId].reduce((acc: any, v, i) => {
acc[`employeeIds[${i}]`] = v;
Expand Down
7 changes: 3 additions & 4 deletions apps/web/app/services/client/api/timer.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import { ITimerStatus, IToggleTimerParams, TimerSource } from '@app/interfaces/ITimer';
import api, { get } from '../axios';
import { GAUZY_API_BASE_SERVER_URL } from '@app/constants';

export async function getTimerStatusAPI(tenantId: string, organizationId: string) {
const params = new URLSearchParams({ tenantId, organizationId });
const endpoint = process.env.NEXT_PUBLIC_GAUZY_API_SERVER_URL
? `/timesheet/timer/status?${params.toString()}`
: '/timer/status';
const endpoint = GAUZY_API_BASE_SERVER_URL.value ? `/timesheet/timer/status?${params.toString()}` : '/timer/status';
const data = await get(endpoint, true);

return process.env.NEXT_PUBLIC_GAUZY_API_SERVER_URL ? data.data : data;
return GAUZY_API_BASE_SERVER_URL.value ? data.data : data;
}

export function toggleTimerAPI(body: Pick<IToggleTimerParams, 'taskId'>) {
Expand Down
Loading

0 comments on commit cd4adbe

Please sign in to comment.