UNPKG

studiocms

Version:

Astro Native CMS for AstroDB. Built from the ground up by the Astro community.

144 lines (133 loc) 4.91 kB
import { eq } from 'astro:db'; import { Effect, genLogger } from '../../../effect.js'; import { AstroDB, SDKCore_Generators, SDKCore_Users } from '../effect/index.js'; import { SDKCoreError, StudioCMS_SDK_Error } from '../errors.js'; import { tsUserResetTokens } from '../tables.js'; import type { tsUserResetTokensSelect } from '../types/index.js'; import { SDKCore_UPDATE } from './update.js'; /** * Provides an effectful service for managing user reset tokens in the StudioCMS SDK. * * This service includes methods to create, delete, and validate reset tokens for users. * It interacts with the database and token generator services, handling errors gracefully. * * @remarks * - Depends on AstroDB, SDKCore_Generators, SDKCore_Users, and SDKCore_UPDATE services. * - Handles database errors by wrapping them in `SDKCoreError`. * * @example * ```typescript * const resetTokenBucket = yield* SDKCore_ResetTokenBucket; * const token = yield* resetTokenBucket.new(userId); * const isValid = yield* resetTokenBucket.check(token); * yield* resetTokenBucket.delete(userId); * ``` * * @method new * Creates a new reset token for the specified user and stores it in the database. * @param userId - The ID of the user for whom to create the reset token. * @returns An effect yielding the created reset token record. * * @method delete * Deletes all reset tokens associated with the specified user. * @param userId - The ID of the user whose reset tokens should be deleted. * @returns An effect yielding void. * * @method check * Validates whether a given token is valid and exists for a user. * @param token - The reset token to validate. * @returns An effect yielding a boolean indicating token validity. */ export class SDKCore_ResetTokenBucket extends Effect.Service<SDKCore_ResetTokenBucket>()( 'studiocms/sdk/SDKCore/modules/resetTokenBucket', { dependencies: [ AstroDB.Default, SDKCore_Generators.Default, SDKCore_Users.Default, SDKCore_UPDATE.Default, ], effect: genLogger('studiocms/sdk/SDKCore/modules/resetTokenBucket/effect')(function* () { const [dbService, { generateToken, testToken }] = yield* Effect.all([ AstroDB, SDKCore_Generators, ]); const resetTokenBucket = { /** * Creates a new reset token for the specified user and stores it in the database. * @param userId - The ID of the user for whom to create the reset token. * @returns An effect yielding the created reset token record. */ new: (userId: string): Effect.Effect<tsUserResetTokensSelect, SDKCoreError, never> => Effect.gen(function* () { const token = yield* generateToken(userId); return yield* dbService.execute((db) => db .insert(tsUserResetTokens) .values({ id: crypto.randomUUID(), userId, token }) .returning() .get() ); }).pipe( Effect.catchTags({ LibSQLClientError: (cause) => Effect.fail( new SDKCoreError({ type: 'LibSQLDatabaseError', cause: new StudioCMS_SDK_Error(`resetTokenBucket New Error: ${cause}`), }) ), }) ), /** * Deletes all reset tokens associated with the specified user. * @param userId - The ID of the user whose reset tokens should be deleted. * @returns An effect yielding void. */ delete: (userId: string): Effect.Effect<void, SDKCoreError, never> => dbService .execute((db) => db.delete(tsUserResetTokens).where(eq(tsUserResetTokens.userId, userId)) ) .pipe( Effect.catchTags({ LibSQLClientError: (cause) => Effect.fail( new SDKCoreError({ type: 'LibSQLDatabaseError', cause: new StudioCMS_SDK_Error(`resetTokenBucket Delete Error: ${cause}`), }) ), }) ), /** * Validates whether a given token is valid and exists for a user. * @param token - The reset token to validate. * @returns An effect yielding a boolean indicating token validity. */ check: (token: string): Effect.Effect<boolean, SDKCoreError, never> => Effect.gen(function* () { const { isValid, userId } = yield* testToken(token); if (!isValid) return false; if (!userId) return false; const resetToken = yield* dbService.execute((db) => db.select().from(tsUserResetTokens).where(eq(tsUserResetTokens.userId, userId)) ); if (!resetToken || resetToken.length === 0) return false; return !!resetToken.find((t) => t.token === token); }).pipe( Effect.catchTags({ LibSQLClientError: (cause) => Effect.fail( new SDKCoreError({ type: 'LibSQLDatabaseError', cause: new StudioCMS_SDK_Error(`resetTokenBucket Check Error: ${cause}`), }) ), }) ), }; return resetTokenBucket; }), } ) {}