studiocms
Version:
Astro Native CMS for AstroDB. Built from the ground up by the Astro community.
87 lines (72 loc) • 2.67 kB
text/typescript
import { Password, Session, VerifyEmail } from 'studiocms:auth/lib';
import { SDKCore } from 'studiocms:sdk';
import {
AllResponse,
createEffectAPIRoutes,
createJsonResponse,
Effect,
genLogger,
Layer,
OptionsResponse,
pipeLogger,
} from '../../../effect.js';
import { AuthAPIUtils } from './shared.js';
const deps = Layer.mergeAll(AuthAPIUtils.Default, VerifyEmail.Default);
export const { POST, OPTIONS, ALL } = createEffectAPIRoutes(
{
POST: (ctx) =>
genLogger('studiocms/routes/api/auth/login/POST')(function* () {
const [
sdk,
{ badFormDataEntry, parseFormDataEntryToString, readFormData },
{ verifyPasswordHash },
{ createUserSession },
{ isEmailVerified },
] = yield* Effect.all([SDKCore, AuthAPIUtils, Password, Session, VerifyEmail]);
const formData = yield* readFormData(ctx);
const [username, password] = yield* pipeLogger(
'studiocms/routes/api/auth/login/POST.parseFormData'
)(
Effect.all([
parseFormDataEntryToString(formData, 'username'),
parseFormDataEntryToString(formData, 'password'),
])
);
if (!username) return yield* badFormDataEntry('Invalid credentials', 'Invalid credentials');
if (!password) return yield* badFormDataEntry('Invalid credentials', 'Invalid credentials');
const existingUser = yield* sdk.GET.users.byUsername(username);
// If the user does not exist, return an ambiguous error
if (!existingUser)
return yield* badFormDataEntry('Invalid credentials', 'Invalid credentials');
// Check if the user has a password or is using a oAuth login
if (!existingUser.password)
return yield* badFormDataEntry('Invalid credentials', 'Invalid credentials');
const validPassword = yield* verifyPasswordHash(existingUser.password, password);
if (!validPassword)
return yield* badFormDataEntry('Invalid credentials', 'Invalid credentials');
const isEmailAccountVerified = yield* isEmailVerified(existingUser);
// If the email is not verified, return an error
if (!isEmailAccountVerified)
return yield* badFormDataEntry(
'Email not verified',
'Please verify your email before logging in'
);
yield* createUserSession(existingUser.id, ctx);
return new Response();
}).pipe(Effect.provide(deps)),
OPTIONS: () => Effect.try(() => OptionsResponse({ allowedMethods: ['POST'] })),
ALL: () => Effect.try(() => AllResponse()),
},
{
cors: { methods: ['POST', 'OPTIONS'] },
onError: (error) => {
console.error('API Error:', error);
return createJsonResponse(
{ error: 'Internal Server Error' },
{
status: 500,
}
);
},
}
);