Skip to content

Commit

Permalink
Merge pull request #2567 from ever-co/develop
Browse files Browse the repository at this point in the history
Release
  • Loading branch information
evereq authored Jun 1, 2024
2 parents 0d4af6b + e592806 commit 12a256a
Show file tree
Hide file tree
Showing 14 changed files with 235 additions and 127 deletions.
9 changes: 3 additions & 6 deletions apps/mobile/app/services/client/requests/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,7 @@ type IUEmployeeParam = {
* @param {IUEmployeeParam} The employee parameters, including bearer token and optional relations.
* @returns A Promise resolving to the IUser object with the desired relations and employee details.
*/
export const currentAuthenticatedUserRequest = ({
bearer_token,
relations = ['role', 'tenant']
}: IUEmployeeParam) => {
export const currentAuthenticatedUserRequest = ({ bearer_token, relations = ['role', 'tenant'] }: IUEmployeeParam) => {
// Create a new instance of URLSearchParams for query string construction
const query = new URLSearchParams();

Expand Down Expand Up @@ -104,9 +101,9 @@ export function sendAuthCodeRequest(email: string) {
// auth/signin.email/confirm Gives response with tenantId's
export function verifyAuthCodeRequest(email: string, code: string) {
return serverFetch<IEmailAndCodeConfirmResponse>({
path: '/auth/signin.email/confirm?includeTeams=true',
path: '/auth/signin.email/confirm',
method: 'POST',
body: { email, code }
body: { email, code, includeTeams: true }
});
}

Expand Down
41 changes: 27 additions & 14 deletions apps/web/app/[locale]/auth/error/page.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
'use client';

import { useSearchParams } from 'next/navigation';
import SadCry from '@components/ui/svgs/sad-cry';
import { Text } from 'lib/components';
import { useTranslations } from 'next-intl';
import Link from 'next/link';
/**
* Error page
*
* @description the page that will be shown if any social login failed. This is not related to Next.js error file
* @returns a custom component that shows error
*/
export default function Page() {
const t = useTranslations();
return (
import UnauthorizedPage from '@components/pages/unauthorized';

enum Error {
Configuration = 'Configuration',
AccessDenied = 'AccessDenied'
}

const errorMap = {
[Error.Configuration]: (
<div className="mt-28 flex flex-col gap-7 items-center">
<div className="m-auto relative flex justify-center items-center gap-4 text-center ">
<SadCry width={97} height={97} />
<Text className="text-[78px] font-semibold text-chetwodeBlue">{t('pages.error.TITLE')}</Text>
<Text className="text-[78px] font-semibold text-chetwodeBlue">Error !</Text>
</div>

<Text className="text-[40px] font-bold text-center text-[#282048] dark:text-light--theme">
{t('pages.error.HEADING_TITLE')}
Something went wrong !
</Text>
<div className="flex flex-col gap-4">
<Text className="text-[20px] font-normal text-center text-gray-400">
{t('pages.error.HEADING_DESCRIPTION')}
If the problem persists, send a distress signal to our support team.
</Text>
<Link href="/auth/passcode">Try again</Link>
</div>
Expand All @@ -33,5 +33,18 @@ export default function Page() {
<h4 className="text-2xl text-red-400 font-medium text-center">Error on signing</h4>
</div>
</div>
);
),
[Error.AccessDenied]: <UnauthorizedPage />
};

/**
* Error page
*
* @description the page that will be shown if any social login failed. This is not related to Next.js error file
* @returns a custom component that shows error
*/
export default function Page() {
const search = useSearchParams();
const error = search?.get('error') as Error;
return <>{errorMap[error]}</>;
}
4 changes: 3 additions & 1 deletion apps/web/app/[locale]/auth/social-logins-buttons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export default function SocialLogins() {
{ name: 'twitter', icon: <FaTwitter key="twitter-icon" /> }
].filter((provider) => providerNames[provider.name] !== undefined);

return (
return mappedProviders.length > 0 ? (
<div className="flex flex-col gap-4">
<div className="flex flex-row justify-center items-center gap-2">
<Divider className="w-56" />
Expand All @@ -38,5 +38,7 @@ export default function SocialLogins() {
))}
</div>
</div>
) : (
<></>
);
}
12 changes: 3 additions & 9 deletions apps/web/app/api/auth/signin-email-social-login/route.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
import { validateForm } from '@app/helpers/validations';
import { signWithSocialLoginsRequest } from '@app/services/server/requests';
import { ProviderEnum } from '@app/services/server/requests/OAuth';

import { NextResponse } from 'next/server';

export async function POST(req: Request) {
const body = (await req.json()) as { email: string; password: string };
const body = (await req.json()) as { provider: ProviderEnum; access_token: string };

const { errors, isValid } = validateForm(['email'], body);

if (!isValid) {
return NextResponse.json({ errors }, { status: 400 });
}

const { data } = await signWithSocialLoginsRequest(body.email);
const { data } = await signWithSocialLoginsRequest(body.provider, body.access_token);

return NextResponse.json(data);
}
16 changes: 6 additions & 10 deletions apps/web/app/services/client/api/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
} from '@app/constants';
import qs from 'qs';
import { signInEmailConfirmGauzy, signInWorkspaceGauzy } from './auth/invite-accept';
import { ProviderEnum } from '@app/services/server/requests/OAuth';

/**
* Fetches data of the authenticated user with specified relations and the option to include employee details.
Expand Down Expand Up @@ -106,19 +107,14 @@ export const signInEmailAPI = (email: string) => {
};

export function signInEmailPasswordAPI(email: string, password: string) {
const endpoint = GAUZY_API_BASE_SERVER_URL.value
? '/auth/signin.email.password?includeTeams=true'
: `/auth/signin-email-password`;

return post<ISigninEmailConfirmResponse>(endpoint, { email, password });
const endpoint = GAUZY_API_BASE_SERVER_URL.value ? '/auth/signin.email.password' : `/auth/signin-email-password`;
return post<ISigninEmailConfirmResponse>(endpoint, { email, password, includeTeams: true });
}

export function signInEmailSocialLoginAPI(email: string) {
const endpoint = GAUZY_API_BASE_SERVER_URL.value
? '/auth/signin.email.social?includeTeams=true'
: `/auth/signin-email-social`;
export function signInEmailSocialLoginAPI(provider: ProviderEnum, access_token: string) {
const endpoint = GAUZY_API_BASE_SERVER_URL.value ? '/auth/signin.provider.social' : `/auth/signin-email-social`;

return post<ISigninEmailConfirmResponse>(endpoint, { email });
return post<ISigninEmailConfirmResponse>(endpoint, { provider, access_token, includeTeams: true });
}

export const verifyUserEmailByTokenAPI = (email: string, token: string) => {
Expand Down
2 changes: 1 addition & 1 deletion apps/web/app/services/client/api/auth/invite-accept.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export function getAllOrganizationTeamAPI(params: ITeamRequestParams, bearer_tok

export const signInEmailConfirmAPI = (data: { code: string; email: string }) => {
const { code, email } = data;
return post<ISigninEmailConfirmResponse>('/auth/signin.email/confirm?includeTeams=true', { code, email });
return post<ISigninEmailConfirmResponse>('/auth/signin.email/confirm', { code, email, includeTeams: true });
};

export async function signInEmailCodeConfirmGauzy(email: string, code: string) {
Expand Down
83 changes: 83 additions & 0 deletions apps/web/app/services/server/requests/OAuth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { type Adapter } from '@auth/core/adapters';
import { signWithSocialLoginsRequest } from '@app/services/server/requests';
import { getUserOrganizationsRequest, signInWorkspaceAPI } from '@app/services/client/api/auth/invite-accept';

export enum ProviderEnum {
GITHUB = 'github',
GOOGLE = 'google',
FACEBOOK = 'facebook',
TWITTER = 'twitter'
}

export const GauzyAdapter: Adapter = {
// Provide createUser and other related functions that will call Gauzy APIs when implementing social signup
};

async function signIn(provider: ProviderEnum, access_token: string) {
try {
const gauzyUser = await signWithSocialLoginsRequest(provider, access_token);

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

const data = await signInWorkspaceAPI(gauzyUser?.data.confirmed_email, gauzyUser?.data.workspaces[0].token);
const tenantId = data.user?.tenantId || '';
const token = data.token;
const userId = data.user?.id;

const { data: organizations } = await getUserOrganizationsRequest({
tenantId,
userId,
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'
}
});
}
return { data, gauzyUser, organization, tenantId, userId };
} catch (error) {
throw new Error('Signin error', { cause: error });
}
}

export async function signInCallback(provider: ProviderEnum, access_token: string): Promise<boolean> {
try {
const { gauzyUser, organization } = await signIn(provider, access_token);
return !!gauzyUser && !!organization;
} catch (error) {
return false;
}
}

export async function jwtCallback(provider: ProviderEnum, access_token: string) {
try {
const { data, gauzyUser, organization, tenantId, userId } = await signIn(provider, access_token);
return {
access_token,
refresh_token: {
token: data.refresh_token
},
teamId: gauzyUser?.data.workspaces[0].current_teams[0].team_id,
tenantId,
organizationId: organization?.organizationId,
languageId: 'en',
noTeamPopup: true,
userId,
workspaces: gauzyUser?.data.workspaces,
confirmed_mail: gauzyUser?.data.confirmed_email
};
} catch (error) {
throw new Error('Signin error', { cause: error });
}
}
15 changes: 8 additions & 7 deletions apps/web/app/services/server/requests/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { ILoginResponse, IRegisterDataRequest, ISigninEmailConfirmResponse } fro
import { IUser } from '@app/interfaces/IUserData';
import { serverFetch } from '../fetch';
import qs from 'qs';
import { ProviderEnum } from './OAuth';

const registerDefaultValue = {
appName: APP_NAME,
Expand Down Expand Up @@ -43,27 +44,27 @@ export function signInEmailRequest(email: string, callbackUrl: string) {

export function signInEmailPasswordRequest(email: string, password: string) {
return serverFetch<ISigninEmailConfirmResponse>({
path: '/auth/signin.email.password?includeTeams=true',
path: '/auth/signin.email.password',
method: 'POST',
body: { email, password }
body: { email, password, includeTeams: true }
});
}

export function signWithSocialLoginsRequest(email: string) {
export function signWithSocialLoginsRequest(provider: ProviderEnum, token: string) {
return serverFetch<ISigninEmailConfirmResponse>({
path: '/auth/signin.email.social?includeTeams=true',
path: '/auth/signin.email.social',
method: 'POST',
body: { email }
body: { provider, token, includeTeams: true }
});
}

export const signInEmailConfirmRequest = (data: { code: string; email: string }) => {
const { code, email } = data;

return serverFetch<ISigninEmailConfirmResponse>({
path: '/auth/signin.email/confirm?includeTeams=true',
path: '/auth/signin.email/confirm',
method: 'POST',
body: { code, email }
body: { code, email, includeTeams: true }
});
};

Expand Down
83 changes: 14 additions & 69 deletions apps/web/auth.ts
Original file line number Diff line number Diff line change
@@ -1,84 +1,29 @@
import NextAuth from 'next-auth';

import { signWithSocialLoginsRequest } from '@app/services/server/requests';
import { getUserOrganizationsRequest, signInWorkspaceAPI } from '@app/services/client/api/auth/invite-accept';
import { filteredProviders } from '@app/utils/check-provider-env-vars';
import { GauzyAdapter, jwtCallback, ProviderEnum, signInCallback } from '@app/services/server/requests/OAuth';

export const { handlers, signIn, signOut, auth } = NextAuth({
providers: filteredProviders,
adapter: GauzyAdapter,
callbacks: {
async signIn({ user }) {
try {
const { email } = user;
const gauzyLoginUser = await signWithSocialLoginsRequest(email ?? '');
const data = await signInWorkspaceAPI(
gauzyLoginUser?.data.confirmed_email,
gauzyLoginUser?.data.workspaces[0].token
);
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 false;
async signIn({ account }) {
if (account) {
const { provider, access_token } = account;
if (access_token) {
return await signInCallback(provider as ProviderEnum, access_token);
}

return !!gauzyLoginUser && !!organization;
} catch (error) {
return false;
}
return true;
},

async jwt({ token, user, trigger, session }) {
async jwt({ token, user, trigger, session, account }) {
if (user) {
const { email } = user;
const gauzyLoginUser = await signWithSocialLoginsRequest(email ?? '');
const data = await signInWorkspaceAPI(
gauzyLoginUser?.data.confirmed_email,
gauzyLoginUser?.data.workspaces[0].token
);
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'
}
});
if (account) {
const { access_token, provider } = account;
if (access_token) {
token.authCookie = await jwtCallback(provider as ProviderEnum, access_token);
}
}

token.authCookie = {
access_token,
refresh_token: {
token: data.refresh_token
},
teamId: gauzyLoginUser?.data.workspaces[0].current_teams[0].team_id,
tenantId,
organizationId: organization?.organizationId,
languageId: 'en',
noTeamPopup: true,
userId,
workspaces: gauzyLoginUser?.data.workspaces,
confirmed_mail: gauzyLoginUser?.data.confirmed_email
};
}

if (trigger === 'update' && session) {
Expand Down
Loading

0 comments on commit 12a256a

Please sign in to comment.