Connect Meshkee backend, blog and shared account session
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
import { cookies } from 'next/headers';
|
||||
import { NextResponse } from 'next/server';
|
||||
import { api, ApiError, getTenant } from '../../../lib/meshkee/api';
|
||||
import { ACCESS_COOKIE,REFRESH_COOKIE,setSessionCookies } from '../../../lib/meshkee/session';
|
||||
type BusinessMembership={businessId?:number|string;id?:number|string;isOwner?:boolean;teamRole?:'admin'|'editor'|'viewer'|null};
|
||||
type User={firstName?:string;lastName?:string;businesses?:BusinessMembership[];isSuperAdmin?:boolean;roles?:string[]};
|
||||
const headers={'Cache-Control':'no-store'};
|
||||
function hasWebsiteAccess(user:User, businessId:number|string){
|
||||
if(user.isSuperAdmin||user.roles?.includes('super_admin'))return true;
|
||||
return user.businesses?.some(membership=>
|
||||
String(membership.businessId??membership.id)===String(businessId)
|
||||
&& (membership.isOwner===true||membership.teamRole==='admin'||membership.teamRole==='editor'||membership.teamRole==='viewer')
|
||||
)??false;
|
||||
}
|
||||
export async function GET(request:Request){
|
||||
const jar=await cookies();const token=jar.get(ACCESS_COOKIE)?.value;const refreshToken=jar.get(REFRESH_COOKIE)?.value;
|
||||
if(!token&&!refreshToken)return NextResponse.json({user:null},{headers});
|
||||
let refreshed:{accessToken:string;refreshToken:string}|undefined;
|
||||
try{
|
||||
let result:{user:User};
|
||||
try{
|
||||
if(!token)throw new ApiError(401);
|
||||
result=await api<{user:User}>('/auth/me',{headers:{Authorization:`Bearer ${token}`}});
|
||||
}catch(error){
|
||||
if(!(error instanceof ApiError)||error.status!==401||!refreshToken)throw error;
|
||||
refreshed=await api<{accessToken:string;refreshToken:string}>('/auth/refresh',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({refreshToken})});
|
||||
if(!refreshed.accessToken||!refreshed.refreshToken)throw new Error('Invalid refresh response');
|
||||
result=await api<{user:User}>('/auth/me',{headers:{Authorization:`Bearer ${refreshed.accessToken}`}});
|
||||
}
|
||||
const tenant=await getTenant();
|
||||
const response=NextResponse.json({user:{name:[result.user.firstName,result.user.lastName].filter(Boolean).join(' ')||'کاربر',isAdmin:hasWebsiteAccess(result.user,tenant.id)}},{headers});
|
||||
if(refreshed)setSessionCookies(response,request,refreshed);
|
||||
return response;
|
||||
}catch(error){return NextResponse.json({user:null},{status:error instanceof ApiError&&error.status===401?401:503,headers})}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import {sameOrigin} from '../../../lib/meshkee/session';
|
||||
import { tenantApi } from '../../../lib/meshkee/api';
|
||||
import { validateContact } from '../../../lib/meshkee/contact';
|
||||
export async function POST(request:Request) {
|
||||
if(!sameOrigin(request))return Response.json({message:'درخواست نامعتبر است.'},{status:403});
|
||||
if(!request.headers.get('content-type')?.includes('application/json'))return Response.json({message:'فرمت درخواست نامعتبر است.'},{status:415});
|
||||
const raw=await request.text();
|
||||
if(raw.length>20000)return Response.json({message:'متن پیام بیش از حد طولانی است.'},{status:413});
|
||||
let input;
|
||||
try{input=JSON.parse(raw)}catch{return Response.json({message:'درخواست نامعتبر است.'},{status:400})}
|
||||
if(!input||typeof input!=='object'||Array.isArray(input))return Response.json({message:'درخواست نامعتبر است.'},{status:400});
|
||||
const {data,errors}=validateContact(input);
|
||||
if(Object.keys(errors).length)return Response.json({message:'اطلاعات فرم را بررسی کنید.',errors},{status:400});
|
||||
try {
|
||||
await tenantApi('/contact-submissions',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(Object.fromEntries(Object.entries(data).filter(([,value])=>value)))});
|
||||
return Response.json({message:'پیام شما با موفقیت ثبت شد. از ارتباط شما سپاسگزاریم.'},{status:201});
|
||||
}catch{return Response.json({message:'پیام ارسال نشد. لطفاً دوباره تلاش کنید یا با ما تماس بگیرید.'},{status:502})}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import {NextResponse} from 'next/server';
|
||||
import { ACCESS_COOKIE,REFRESH_COOKIE,cookieOptions,sameOrigin } from '../../../lib/meshkee/session';
|
||||
export async function POST(request:Request){
|
||||
if(!sameOrigin(request))return NextResponse.json({message:'درخواست نامعتبر است.'},{status:403});
|
||||
const response=NextResponse.json({ok:true});
|
||||
for(const name of [ACCESS_COOKIE,REFRESH_COOKIE]){
|
||||
response.cookies.set(name,'',{...cookieOptions(request),maxAge:0});
|
||||
// Also expire a host-only cookie left by a local/older deployment.
|
||||
if(cookieOptions(request).domain)response.headers.append('Set-Cookie',`${name}=; Path=/; Max-Age=0; HttpOnly; Secure; SameSite=Lax`);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
Reference in New Issue
Block a user