"use server"; import { redirect } from "next/navigation"; import pb from "@/lib/pocketbase"; import { cookies } from "next/headers"; import CryptoJS from 'crypto-js'; import { CheckoutSession, SignUpForm, SourceModal, Subscription, SubscriptionSession, User } from "@/types"; import { apiPrices } from "./(public)/pricing/actions"; export async function mailchimp(formData: { email: string; first_name: string; last_name: string; phone_number?: string; company_size: string; source?: SourceModal; }) { const email = formData.email; const mailchimpBaseUrl = process.env.NEXT_PUBLIC_MAILCHIMP_BASE_URL; const mailchimpApiKey = process.env.NEXT_PUBLIC_MAILCHIMP_BASE64_API_KEY; const mailchimpList = process.env.NEXT_PUBLIC_MAILCHIMP_LIST_ID; if (!mailchimpApiKey) return; try { const subscriberHash = CryptoJS.MD5(email.toLocaleLowerCase()); const mailchimpResponse = await fetch(`${mailchimpBaseUrl}/3.0/lists/${mailchimpList}/members/${subscriberHash}`, { method: 'PUT', headers: { "Content-Type": "application/json", Authorization: mailchimpApiKey, }, body: JSON.stringify( { "email_address": email, status: "subscribed", merge_fields: { EMAIL: formData.email, FNAME: formData.first_name, LNAME: formData.last_name, PHONE: !formData.phone_number ? '' : formData.phone_number, CSIZE: formData.company_size, SOURCE: formData.source } } ) }) if (mailchimpResponse.status !== 200) { throw new Error("couldn't complete the request"); } return mailchimpResponse.json(); } catch (err) { throw new Error("couldn't complete the request"); } } export async function signup(formData: SignUpForm) { const email = formData.email; const password = formData.password; const organisation = formData.organisation; console.log('app/(authenticated)/actions', 'organisation', organisation) const pocketbaseUrl = process.env.NEXT_PUBLIC_POCKETBASE_URL as string; const adminToken = process.env.NEXT_PUBLIC_POCKETBASE_ADMIN_TOKEN as string; try { const orgRes = await fetch( `${pocketbaseUrl}/api/collections/organisation/records`, { method: "POST", headers: { "Content-Type": "application/json", Authorization: adminToken, }, body: JSON.stringify({ name: organisation, }), } ); console.log("orgRes.status: ", orgRes.status); if (orgRes.status !== 200) { throw new Error("Failed to create organisation"); } const orgData = await orgRes.json(); console.log(orgData); const userRes = await fetch( `${pocketbaseUrl}/api/collections/user/records`, { method: "POST", headers: { "Content-Type": "application/json", Authorization: adminToken, }, body: JSON.stringify({ firstName: formData.first_name, lastName: formData.last_name, displayName: formData.first_name + ' ' + formData.last_name, email: email, password: password, passwordConfirm: password, organisation: orgData?.id, role: "Admin", lastSeen: new Date(), }), } ); console.log("userRes.status: ", userRes.status); if (userRes.status !== 200) { console.log(userRes); throw new Error("Failed to create user"); } } catch (err) { if (err instanceof Error) { throw new Error(err.message); } } } export async function login(formData: { email: string; password: string }) { console.log('login') const email = formData.email as string; const password = formData.password as string; try { const { token, record: data } = await pb .collection("user") .authWithPassword(email, password); if (pb.authStore.isValid) { const cookie = pb.authStore.exportToCookie(); cookies().set("pb_auth", cookie, { secure: true, path: "/", sameSite: "strict", httpOnly: true, }); } return { success: true, error: "Failed to log in", token: token, data: data }; } catch (error) { console.log(error) if ((error as any).status == 403) { await pb.collection('user').requestVerification(email); } return JSON.parse(JSON.stringify(error)) } } export async function getAuthCookie() { try { const cookie = cookies().get('pb_auth'); pb.authStore.loadFromCookie(cookie?.value || ''); return pb.authStore.token; } catch (error) { return undefined; } } export async function isAuthenticated() { try { const cookie = cookies().get('pb_auth'); if(!cookie) return false; pb.authStore.loadFromCookie(cookie?.value || ''); return pb.authStore.isValid || false; } catch (error) { return undefined; } } export async function getUser() { try { const cookie = cookies().get('pb_auth'); if(!cookie) return false; pb.authStore.loadFromCookie(cookie?.value || ''); return pb.authStore.model; } catch (error) { return undefined; } } export async function logout() { cookies().delete("pb_auth"); redirect('/'); } export async function createCheckoutSession(price_id: string, type: string) { const pocketbaseUrl = process.env.NEXT_PUBLIC_POCKETBASE_URL; if (!pocketbaseUrl) { throw Error('Connection Timeout'); } if (!price_id) { throw Error('There was an error during the payment processing'); } const token = await getAuthCookie(); if (!token) { throw Error('Could not authenticate'); } console.log('token', token); console.log('url ', `${pocketbaseUrl}/create-checkout-session`); const body = JSON.stringify({ price: { id: price_id, type: type }, quantity: 1 }); console.log('body',body); try{ const createCheckoutSessionResponse = await fetch( `${pocketbaseUrl}/create-checkout-session`, { method: "POST", headers: { "Content-Type": "application/json", Authorization: token, }, body: body, } ); if (createCheckoutSessionResponse.status !== 200) { throw new Error("Failed to process Request"); } const createCheckoutSessionData: CheckoutSession = await createCheckoutSessionResponse.json(); if (createCheckoutSessionData.url === "") { throw new Error("Failed to process request an invalid URL was served"); } return createCheckoutSessionData; } catch (error) { throw error; } } export async function getSubscriptions() { const cookie = cookies().get('pb_auth'); pb.authStore.loadFromCookie(cookie?.value || ''); const userId = (pb.authStore.model as User).id const subscriptions = await pb.collection("subscription").getFullList({filter: `user_id="${userId}" && status="active"`}); console.log('app/(authenticated)/actions', 'subscriptions', subscriptions) if (subscriptions.length === 0){ return []; } const products = await apiPrices(); const subscriptionWithProducts = subscriptions.map(subscription => {return {...subscription, product: products.find(product => product?.yearlyPrice?.price_id === subscription.price_id || product?.monthlyPrice?.price_id === subscription.price_id)}}) as Subscription[] return subscriptionWithProducts; } export async function createManagementSubscriptionSession() { const pocketbaseUrl = process.env.NEXT_PUBLIC_POCKETBASE_URL; if (!pocketbaseUrl) { throw Error('Connection Timeout'); } const token = await getAuthCookie(); if (!token) { throw Error('Could not authenticate'); } console.log('token', token); console.log('url ', `${pocketbaseUrl}/create-checkout-session`); try{ const createManagementSessionResponse = await fetch( `${pocketbaseUrl}/create-portal-link`, { method: "POST", headers: { "Content-Type": "application/json", Authorization: token, }, body: JSON.stringify({}), } ); if (createManagementSessionResponse.status !== 200) { console.log(createManagementSessionResponse.status) throw new Error(JSON.stringify( await createManagementSessionResponse.json())); } const createManagementSessionData: SubscriptionSession = await createManagementSessionResponse.json(); return createManagementSessionData; } catch (error) { throw error; } }