Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release #2213

Merged
merged 11 commits into from
Feb 15, 2024
11 changes: 10 additions & 1 deletion .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,16 @@
"xlcard",
"xlight",
"yellowbox",
"Desabled"
"Desabled",
"keyrings",
"dearmor",
"dpkg",
"containerd",
"nodistro",
"nodesource",
"Koyeb",
"Northflank",
"prebuild"
],
"useGitignore": true,
"ignorePaths": [
Expand Down
2 changes: 1 addition & 1 deletion Layerfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ RUN apt-get update && \
RUN REPEATABLE docker pull everco/ever-teams-webapp

RUN REPEATABLE (docker rm ever-teams --force || true) &&\
docker run --name ever-teams -d -p 3030:3030 everco/ever-teams-webapp && sleep 5
docker run --name ever-teams -d -p 3030:3030 everco/ever-teams-webapp && sleep 10

EXPOSE WEBSITE localhost:3030
14 changes: 9 additions & 5 deletions apps/web/app/services/client/api/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
VERIFY_EMAIL_CALLBACK_URL
} from '@app/constants';
import qs from 'qs';
import { signInEmailConfirmGauzy } from './auth/invite-accept';
import { signInEmailConfirmGauzy, signInWorkspaceGauzy } from './auth/invite-accept';

export const getAuthenticatedUserDataAPI = () => {
const params = {} as { [x: string]: string };
Expand Down Expand Up @@ -114,14 +114,18 @@ export async function signInEmailConfirmAPI(email: string, code: string) {
});
}

export const registerUserTeamAPI = (data: IRegisterDataAPI) => {
return api.post<ILoginResponse>('/auth/register', data);
};

export const signInWorkspaceAPI = (email: string, token: string, selectedTeam: string) => {
if (GAUZY_API_BASE_SERVER_URL.value) {
return signInWorkspaceGauzy({ email, token, teamId: selectedTeam, code: 'sign-in-workspace' });
}

return api.post<ILoginResponse>(`/auth/signin-workspace`, {
email,
token,
teamId: selectedTeam
});
};

export const registerUserTeamAPI = (data: IRegisterDataAPI) => {
return api.post<ILoginResponse>('/auth/register', data);
};
89 changes: 81 additions & 8 deletions apps/web/app/services/client/api/auth/invite-accept.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,22 +80,17 @@ export const signInEmailConfirmAPI = (data: { code: string; email: string }) =>
return post<ISigninEmailConfirmResponse>('/auth/signin.email/confirm?includeTeams=true', { code, email });
};

/**
*
* @param email
* @param code
* @returns
*/
export async function signInEmailConfirmGauzy(email: string, code: string) {
export async function signInEmailCodeConfirmGauzy(email: string, code: string) {
let loginResponse: ILoginResponse | null = null;
const inviteReq = await verifyInviteCodeAPI({ email, code });

const { errors, valid: formValid } = authFormValidate(['email', 'code'], { email, code } as any);

if (!formValid) {
return Promise.reject({ errors });
}

const inviteReq = await verifyInviteCodeAPI({ email, code });

if (inviteReq && inviteReq.fullName) {
const password = generateToken(8);
const names = inviteReq.fullName.split(' ');
Expand Down Expand Up @@ -175,5 +170,83 @@ export async function signInEmailConfirmGauzy(email: string, code: string) {
return Promise.resolve(response);
}

return loginResponse;
}

export function signInWorkspaceAPI(email: string, token: string) {
return post<ILoginResponse>('/auth/signin.workspace', {
email,
token
}).then((res) => res.data);
}

/**
*
* @param email
* @param code
* @returns
*/
export async function signInEmailConfirmGauzy(email: string, code: string) {
const loginResponse = await signInEmailCodeConfirmGauzy(email, code);

if (loginResponse) {
return loginResponse;
}

return signInEmailConfirmAPI({ email, code });
}

/**
* @param params
*/
export async function signInWorkspaceGauzy(params: { email: string; token: string; teamId: string; code: string }) {
const loginResponse = await signInEmailCodeConfirmGauzy(params.email, params.code);

if (loginResponse) {
return loginResponse;
}

const data = await signInWorkspaceAPI(params.email, params.token);

/**
* Get the first team from first organization
*/
const tenantId = data.user?.tenantId || '';
const access_token = data.token;
const userId = data.user?.id;

const { data: organizations } = await getUserOrganizationsRequest({ tenantId, userId, token: access_token });

const organization = organizations?.items[0];

if (!organization) {
return Promise.reject({
errors: {
email: 'Your account is not yet ready to be used on the Ever Teams Platform'
}
});
}

setAuthCookies({
access_token: data.token,
refresh_token: {
token: data.refresh_token
},
teamId: params.teamId,
tenantId,
organizationId: organization?.organizationId,
languageId: 'en', // TODO: not sure what should be here
noTeamPopup: true,
userId
});

const response: AxiosResponse<{ loginResponse: ILoginResponse }> = {
data: { loginResponse: data },
status: 200,
statusText: '',
headers: {},
config: {} as any
};

return Promise.resolve(response);
}
186 changes: 186 additions & 0 deletions apps/web/app/services/client/api/auth/register.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
import {
APP_LOGO_URL,
APP_NAME,
APP_SIGNATURE,
VERIFY_EMAIL_CALLBACK_PATH,
VERIFY_EMAIL_CALLBACK_URL,
smtpConfiguration
} from '@app/constants';
import { authFormValidate, generateToken, setAuthCookies } from '@app/helpers';
import {
ICreateEmployee,
IEmployee,
ILoginResponse,
IOrganization,
IOrganizationCreate,
IOrganizationTeam,
IRegisterDataAPI,
IRegisterDataRequest,
ITenant,
IUser,
I_SMTP
} from '@app/interfaces';
import { post } from '../../axios';
import { createOrganizationTeamGauzy } from '../organization-team';
import { AxiosResponse } from 'axios';

const registerDefaultValue = {
appName: APP_NAME,
appSignature: APP_SIGNATURE,
appLogo: APP_LOGO_URL
};

export function registerUserAPI(data: IRegisterDataRequest) {
const body = {
...data,
...registerDefaultValue,
appEmailConfirmationUrl: VERIFY_EMAIL_CALLBACK_URL || data.appEmailConfirmationUrl
};

return post<IUser>('/auth/register', body).then(({ data }) => data);
}

export function loginUserAPI(email: string, password: string) {
return post<ILoginResponse>('/auth/login', { email, password }).then(({ data }) => data);
}

export function createTenantAPI(name: string, bearer_token: string) {
return post<ITenant>(
'/tenant',
{ name },
{
headers: { Authorization: `Bearer ${bearer_token}` }
}
).then(({ data }) => data);
}

export function createTenantSmtpAPI({ tenantId, access_token }: { tenantId: string; access_token: string }) {
const config = smtpConfiguration();

console.log(`SMTP Config: ${JSON.stringify(config)}`);

return post<I_SMTP>('/smtp', config, {
tenantId,
headers: { Authorization: `Bearer ${access_token}` }
});
}

export function createOrganizationAPI(datas: IOrganizationCreate, bearer_token: string) {
return post<IOrganization>('/organization', datas, {
headers: { Authorization: `Bearer ${bearer_token}` }
}).then(({ data }) => data);
}

export function createEmployeeFromUserAPI(data: ICreateEmployee, bearer_token: string) {
return post<IEmployee>('/employee', data, {
tenantId: data.tenantId,
headers: { Authorization: `Bearer ${bearer_token}` }
}).then(({ data }) => data);
}

export const refreshTokenAPI = (refresh_token: string) => {
return post<{ token: string }>('/auth/refresh-token', {
refresh_token
}).then(({ data }) => data);
};

export async function registerGauzy(body: IRegisterDataAPI) {
const appEmailConfirmationUrl = `${location.origin}${VERIFY_EMAIL_CALLBACK_PATH}`;

const noRecaptchaArray = ['email', 'name', 'team'];

const validationFields = noRecaptchaArray;

const { errors, valid: formValid } = authFormValidate(validationFields, body);

if (!formValid) {
return Promise.reject({ errors });
}

const password = generateToken(8);
const names = body.name.split(' ');

const user = await registerUserAPI({
password: password,
confirmPassword: password,
user: {
firstName: names[0],
lastName: names[1] || '',
email: body.email,
timeZone: body.timezone as string
},
appEmailConfirmationUrl
});

// User Login, get the access token
const loginRes = await loginUserAPI(body.email, password);
let auth_token = loginRes.token;

const tenant = await createTenantAPI(body.email, auth_token);

// TODO: This function should be implemented from Gauzy
// Create tenant SMTP
// await createTenantSmtpRequest({
// access_token: auth_token,
// tenantId: tenant.id
// });

// Create user organization
const organization = await createOrganizationAPI(
{
currency: 'USD',
name: body.team,
tenantId: tenant.id,
invitesAllowed: true
},
auth_token
);

// Create employee
const employee = await createEmployeeFromUserAPI(
{
organizationId: organization.id,
startedWorkOn: new Date().toISOString(),
tenantId: tenant.id,
userId: user.id
},
auth_token
);

const { data: team } = await createOrganizationTeamGauzy(
{
name: body.team,
tenantId: tenant.id,
organizationId: organization.id,
managerIds: [employee.id],
public: true // By default team should be public,
},
auth_token
);

const refreshTokenRes = await refreshTokenAPI(loginRes.refresh_token);
auth_token = refreshTokenRes.token;

setAuthCookies({
access_token: auth_token,
refresh_token: {
token: loginRes.refresh_token
},
timezone: body['timezone'],
teamId: team.id,
tenantId: tenant.id,
organizationId: organization.id,
languageId: 'en', // TODO: not sure what should be here
userId: user.id
});

const response: AxiosResponse<{ loginRes: ILoginResponse; team: IOrganizationTeam; employee: IEmployee }> = {
data: { loginRes, team, employee },
status: 200,
statusText: '',
headers: {},
config: {} as any
};

return Promise.resolve(response);
}
Loading
Loading