feat(saas): full SquareMCP SaaS platform v1
- JWT auth with bcrypt password hashing, cookie sessions, forgot/reset password - Per-user encrypted credential storage (Redis + AES-256-GCM) for all 9 platforms - Usage tracking with monthly limits per plan (free/starter/growth/enterprise) - Invoice generation and retrieval (admin + user views) - Admin panel with customer listing (role-based access) - Web app UI at app.squaremcp.com — login, dashboard, connections, usage, invoices - Unified auth middleware: API key, OAuth Bearer, and JWT cookie support - Facebook Graph API fixes: published_posts endpoint, photo/video post support - TikTok sandbox compliance: SELF_ONLY privacy for unaudited apps - URL verification files for TikTok app review
This commit is contained in:
@@ -99,7 +99,7 @@ export async function getPosts(
|
||||
const { accessToken, pageId } = await resolveCreds(args, customer);
|
||||
const limit = args.limit ?? 10;
|
||||
const data = await fbRequest(
|
||||
`/${pageId}/feed?fields=id,message,story,created_time,permalink_url&limit=${limit}`,
|
||||
`/${pageId}/published_posts?fields=id,message,story,created_time,permalink_url&limit=${limit}`,
|
||||
accessToken
|
||||
);
|
||||
return (data.data ?? []).map((p: Record<string, unknown>) => ({
|
||||
|
||||
@@ -6,7 +6,7 @@ const TIKTOK_API_BASE = 'https://open.tiktokapis.com/v2';
|
||||
|
||||
function getEnvToken(account: string): string {
|
||||
const envKey = `TIKTOK_${account.toUpperCase()}_ACCESS_TOKEN`;
|
||||
return process.env[envKey] ?? '';
|
||||
return process.env[envKey] ?? process.env.TIKTOK_DEFAULT_ACCESS_TOKEN ?? '';
|
||||
}
|
||||
|
||||
async function resolveToken(args: { account?: string }, customer?: Customer): Promise<string> {
|
||||
@@ -122,9 +122,13 @@ export async function createVideo(
|
||||
|
||||
// Step 1: query creator info to get valid privacy levels (sandbox may not support PUBLIC_TO_EVERYONE)
|
||||
const creatorInfo = await getCreatorInfo(args, customer);
|
||||
const privacyLevel = creatorInfo.privacy_level_options.includes('PUBLIC_TO_EVERYONE')
|
||||
const options = creatorInfo.privacy_level_options;
|
||||
// Unaudited apps MUST post SELF_ONLY; prefer that when public isn't available
|
||||
const privacyLevel = options.includes('PUBLIC_TO_EVERYONE')
|
||||
? 'PUBLIC_TO_EVERYONE'
|
||||
: creatorInfo.privacy_level_options[0] ?? 'SELF_ONLY';
|
||||
: options.includes('SELF_ONLY')
|
||||
? 'SELF_ONLY'
|
||||
: options[0] ?? 'SELF_ONLY';
|
||||
|
||||
// Step 2: initialise upload
|
||||
const init = await tiktokRequest('/post/publish/video/init/', accessToken, 'POST', {
|
||||
|
||||
Reference in New Issue
Block a user