feat(supabase): add pezkiwi.app CORS and multi-bot-token auth support

- Add telegram.pezkiwi.app to CORS allowed origins in all edge functions
- Support multiple bot tokens (TELEGRAM_BOT_TOKEN, TELEGRAM_BOT_TOKEN_KRD) in auth
- Dynamic origin matching for proper CORS headers
This commit is contained in:
2026-02-14 11:09:14 +03:00
parent f6125a127d
commit 44a4b9395b
13 changed files with 101 additions and 42 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "pezkuwi-telegram-miniapp",
"version": "1.0.187",
"version": "1.0.188",
"type": "module",
"description": "Pezkuwichain Telegram Mini App - Forum, Announcements, Rewards",
"author": "Pezkuwichain Team",
+3 -3
View File
@@ -1,5 +1,5 @@
{
"version": "1.0.187",
"buildTime": "2026-02-14T08:08:25.403Z",
"buildNumber": 1771056505404
"version": "1.0.188",
"buildTime": "2026-02-14T08:09:14.764Z",
"buildNumber": 1771056554765
}
@@ -2,11 +2,13 @@ import { serve } from 'https://deno.land/std@0.177.0/http/server.ts';
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2';
import { createHmac } from 'https://deno.land/std@0.177.0/node/crypto.ts';
const ALLOWED_ORIGIN = 'https://telegram.pezkuwichain.io';
const ALLOWED_ORIGINS = ['https://telegram.pezkuwichain.io', 'https://telegram.pezkiwi.app'];
function getCorsHeaders(): Record<string, string> {
function getCorsHeaders(origin?: string | null): Record<string, string> {
const allowedOrigin =
origin && ALLOWED_ORIGINS.some((o) => origin.startsWith(o)) ? origin : ALLOWED_ORIGINS[0];
return {
'Access-Control-Allow-Origin': ALLOWED_ORIGIN,
'Access-Control-Allow-Origin': allowedOrigin,
'Access-Control-Allow-Headers':
'authorization, x-client-info, apikey, content-type, x-supabase-client-platform',
'Access-Control-Allow-Methods': 'POST, OPTIONS',
@@ -52,7 +54,8 @@ function validateInitData(initData: string, botToken: string): TelegramUser | nu
}
serve(async (req) => {
const corsHeaders = getCorsHeaders();
const origin = req.headers.get('origin');
const corsHeaders = getCorsHeaders(origin);
if (req.method === 'OPTIONS') {
return new Response('ok', { headers: corsHeaders });
+7 -4
View File
@@ -13,7 +13,7 @@ import { sha256 } from 'https://esm.sh/@noble/hashes@1.3.2/sha256';
import { bytesToHex } from 'https://esm.sh/@noble/hashes@1.3.2/utils';
import { secp256k1 } from 'https://esm.sh/@noble/curves@1.2.0/secp256k1';
const ALLOWED_ORIGIN = 'https://telegram.pezkuwichain.io';
const ALLOWED_ORIGINS = ['https://telegram.pezkuwichain.io', 'https://telegram.pezkiwi.app'];
const MIN_DEPOSIT = 10; // Minimum 10 USDT
// Platform fees per network
@@ -32,9 +32,11 @@ const TRON_USDT_CONTRACT = 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t'; // TRC20 USDT
const BASE58_ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
function getCorsHeaders(): Record<string, string> {
function getCorsHeaders(origin?: string | null): Record<string, string> {
const allowedOrigin =
origin && ALLOWED_ORIGINS.some((o) => origin.startsWith(o)) ? origin : ALLOWED_ORIGINS[0];
return {
'Access-Control-Allow-Origin': ALLOWED_ORIGIN,
'Access-Control-Allow-Origin': allowedOrigin,
'Access-Control-Allow-Headers':
'authorization, x-client-info, apikey, content-type, x-supabase-client-platform',
'Access-Control-Allow-Methods': 'POST, OPTIONS',
@@ -313,7 +315,8 @@ async function checkTrc20Deposits(
}
serve(async (req) => {
const corsHeaders = getCorsHeaders();
const origin = req.headers.get('origin');
const corsHeaders = getCorsHeaders(origin);
if (req.method === 'OPTIONS') {
return new Response('ok', { headers: corsHeaders });
@@ -3,7 +3,11 @@ import { createClient } from 'https://esm.sh/@supabase/supabase-js@2';
import { createHmac } from 'https://deno.land/std@0.177.0/node/crypto.ts';
// CORS - Production domain only
const ALLOWED_ORIGINS = ['https://telegram.pezkuwichain.io', 'https://t.me'];
const ALLOWED_ORIGINS = [
'https://telegram.pezkuwichain.io',
'https://telegram.pezkiwi.app',
'https://t.me',
];
function getCorsHeaders(origin: string | null): Record<string, string> {
const allowedOrigin =
+7 -4
View File
@@ -2,11 +2,13 @@ import { serve } from 'https://deno.land/std@0.177.0/http/server.ts';
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2';
import { createHmac } from 'https://deno.land/std@0.177.0/node/crypto.ts';
const ALLOWED_ORIGIN = 'https://telegram.pezkuwichain.io';
const ALLOWED_ORIGINS = ['https://telegram.pezkuwichain.io', 'https://telegram.pezkiwi.app'];
function getCorsHeaders(): Record<string, string> {
function getCorsHeaders(origin?: string | null): Record<string, string> {
const allowedOrigin =
origin && ALLOWED_ORIGINS.some((o) => origin.startsWith(o)) ? origin : ALLOWED_ORIGINS[0];
return {
'Access-Control-Allow-Origin': ALLOWED_ORIGIN,
'Access-Control-Allow-Origin': allowedOrigin,
'Access-Control-Allow-Headers':
'authorization, x-client-info, apikey, content-type, x-supabase-client-platform',
'Access-Control-Allow-Methods': 'POST, OPTIONS',
@@ -61,7 +63,8 @@ function generateDepositCode(): string {
}
serve(async (req) => {
const corsHeaders = getCorsHeaders();
const origin = req.headers.get('origin');
const corsHeaders = getCorsHeaders(origin);
if (req.method === 'OPTIONS') {
return new Response('ok', { headers: corsHeaders });
+7 -4
View File
@@ -13,12 +13,14 @@ import { sha256 } from 'https://esm.sh/@noble/hashes@1.3.2/sha256';
import { bytesToHex, hexToBytes } from 'https://esm.sh/@noble/hashes@1.3.2/utils';
import { secp256k1 } from 'https://esm.sh/@noble/curves@1.2.0/secp256k1';
const ALLOWED_ORIGIN = 'https://telegram.pezkuwichain.io';
const ALLOWED_ORIGINS = ['https://telegram.pezkuwichain.io', 'https://telegram.pezkiwi.app'];
const BASE58_ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
function getCorsHeaders(): Record<string, string> {
function getCorsHeaders(origin?: string | null): Record<string, string> {
const allowedOrigin =
origin && ALLOWED_ORIGINS.some((o) => origin.startsWith(o)) ? origin : ALLOWED_ORIGINS[0];
return {
'Access-Control-Allow-Origin': ALLOWED_ORIGIN,
'Access-Control-Allow-Origin': allowedOrigin,
'Access-Control-Allow-Headers':
'authorization, x-client-info, apikey, content-type, x-supabase-client-platform',
'Access-Control-Allow-Methods': 'POST, OPTIONS',
@@ -143,7 +145,8 @@ function deriveTronAddress(mnemonic: string, index: number): string {
}
serve(async (req) => {
const corsHeaders = getCorsHeaders();
const origin = req.headers.get('origin');
const corsHeaders = getCorsHeaders(origin);
if (req.method === 'OPTIONS') {
return new Response('ok', { headers: corsHeaders });
+7 -4
View File
@@ -2,11 +2,13 @@ import { serve } from 'https://deno.land/std@0.177.0/http/server.ts';
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2';
import { createHmac } from 'https://deno.land/std@0.177.0/node/crypto.ts';
const ALLOWED_ORIGIN = 'https://telegram.pezkuwichain.io';
const ALLOWED_ORIGINS = ['https://telegram.pezkuwichain.io', 'https://telegram.pezkiwi.app'];
function getCorsHeaders(): Record<string, string> {
function getCorsHeaders(origin?: string | null): Record<string, string> {
const allowedOrigin =
origin && ALLOWED_ORIGINS.some((o) => origin.startsWith(o)) ? origin : ALLOWED_ORIGINS[0];
return {
'Access-Control-Allow-Origin': ALLOWED_ORIGIN,
'Access-Control-Allow-Origin': allowedOrigin,
'Access-Control-Allow-Headers':
'authorization, x-client-info, apikey, content-type, x-supabase-client-platform',
'Access-Control-Allow-Methods': 'POST, OPTIONS',
@@ -52,7 +54,8 @@ function validateInitData(initData: string, botToken: string): TelegramUser | nu
}
serve(async (req) => {
const corsHeaders = getCorsHeaders();
const origin = req.headers.get('origin');
const corsHeaders = getCorsHeaders(origin);
if (req.method === 'OPTIONS') {
return new Response('ok', { headers: corsHeaders });
+5 -1
View File
@@ -3,7 +3,11 @@ import { createClient } from 'https://esm.sh/@supabase/supabase-js@2';
import { createHmac } from 'https://deno.land/std@0.177.0/node/crypto.ts';
// CORS - Production domain only
const ALLOWED_ORIGINS = ['https://telegram.pezkuwichain.io', 'https://t.me'];
const ALLOWED_ORIGINS = [
'https://telegram.pezkuwichain.io',
'https://telegram.pezkiwi.app',
'https://t.me',
];
function getCorsHeaders(origin: string | null): Record<string, string> {
const allowedOrigin =
+5 -1
View File
@@ -9,7 +9,11 @@ import { ApiPromise, WsProvider, Keyring } from 'npm:@pezkuwi/api@16.5.36';
import { cryptoWaitReady } from 'npm:@pezkuwi/util-crypto@14.0.25';
// CORS - Restricted for security (cron/admin only)
const ALLOWED_ORIGINS = ['https://telegram.pezkuwichain.io', 'https://supabase.com'];
const ALLOWED_ORIGINS = [
'https://telegram.pezkuwichain.io',
'https://telegram.pezkiwi.app',
'https://supabase.com',
];
function getCorsHeaders(origin: string | null): Record<string, string> {
const allowedOrigin =
@@ -6,11 +6,13 @@ import { serve } from 'https://deno.land/std@0.177.0/http/server.ts';
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2';
import { createHmac } from 'https://deno.land/std@0.177.0/node/crypto.ts';
const ALLOWED_ORIGIN = 'https://telegram.pezkuwichain.io';
const ALLOWED_ORIGINS = ['https://telegram.pezkuwichain.io', 'https://telegram.pezkiwi.app'];
function getCorsHeaders(): Record<string, string> {
function getCorsHeaders(origin?: string | null): Record<string, string> {
const allowedOrigin =
origin && ALLOWED_ORIGINS.some((o) => origin.startsWith(o)) ? origin : ALLOWED_ORIGINS[0];
return {
'Access-Control-Allow-Origin': ALLOWED_ORIGIN,
'Access-Control-Allow-Origin': allowedOrigin,
'Access-Control-Allow-Headers':
'authorization, x-client-info, apikey, content-type, x-supabase-client-platform',
'Access-Control-Allow-Methods': 'POST, OPTIONS',
@@ -65,7 +67,8 @@ function isValidSubstrateAddress(address: string): boolean {
}
serve(async (req) => {
const corsHeaders = getCorsHeaders();
const origin = req.headers.get('origin');
const corsHeaders = getCorsHeaders(origin);
if (req.method === 'OPTIONS') {
return new Response('ok', { headers: corsHeaders });
+35 -10
View File
@@ -2,11 +2,13 @@ import { serve } from 'https://deno.land/std@0.177.0/http/server.ts';
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2';
import { createHmac } from 'https://deno.land/std@0.177.0/node/crypto.ts';
const ALLOWED_ORIGIN = 'https://telegram.pezkuwichain.io';
const ALLOWED_ORIGINS = ['https://telegram.pezkuwichain.io', 'https://telegram.pezkiwi.app'];
function getCorsHeaders(): Record<string, string> {
function getCorsHeaders(origin?: string | null): Record<string, string> {
const allowedOrigin =
origin && ALLOWED_ORIGINS.some((o) => origin.startsWith(o)) ? origin : ALLOWED_ORIGINS[0];
return {
'Access-Control-Allow-Origin': ALLOWED_ORIGIN,
'Access-Control-Allow-Origin': allowedOrigin,
'Access-Control-Allow-Headers':
'authorization, x-client-info, apikey, content-type, x-supabase-client-platform',
'Access-Control-Allow-Methods': 'POST, OPTIONS',
@@ -93,7 +95,8 @@ function verifySessionToken(token: string, botToken: string): number | null {
}
serve(async (req) => {
const corsHeaders = getCorsHeaders();
const origin = req.headers.get('origin');
const corsHeaders = getCorsHeaders(origin);
if (req.method === 'OPTIONS') {
return new Response('ok', { headers: corsHeaders });
@@ -105,9 +108,15 @@ serve(async (req) => {
const supabaseUrl = Deno.env.get('SUPABASE_URL')!;
const supabaseServiceKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!;
const botToken = Deno.env.get('TELEGRAM_BOT_TOKEN');
if (!botToken) {
// Collect all available bot tokens
const botTokens: string[] = [];
const mainToken = Deno.env.get('TELEGRAM_BOT_TOKEN');
const krdToken = Deno.env.get('TELEGRAM_BOT_TOKEN_KRD');
if (mainToken) botTokens.push(mainToken);
if (krdToken) botTokens.push(krdToken);
if (botTokens.length === 0) {
return new Response(JSON.stringify({ error: 'Server configuration error' }), {
status: 500,
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
@@ -118,7 +127,15 @@ serve(async (req) => {
// Method 1: Session token verification
if (sessionToken) {
const tgId = verifySessionToken(sessionToken, botToken);
let tgId: number | null = null;
let matchedToken: string = botTokens[0];
for (const token of botTokens) {
tgId = verifySessionToken(sessionToken, token);
if (tgId) {
matchedToken = token;
break;
}
}
if (!tgId) {
return new Response(JSON.stringify({ error: 'Invalid or expired session' }), {
status: 401,
@@ -142,7 +159,7 @@ serve(async (req) => {
return new Response(
JSON.stringify({
user: userData,
session_token: generateSessionToken(tgId, botToken),
session_token: generateSessionToken(tgId, matchedToken),
}),
{ headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
);
@@ -156,7 +173,15 @@ serve(async (req) => {
});
}
const telegramUser = validateInitData(initData, botToken);
let telegramUser: TelegramUser | null = null;
let matchedBotToken: string = botTokens[0];
for (const token of botTokens) {
telegramUser = validateInitData(initData, token);
if (telegramUser) {
matchedBotToken = token;
break;
}
}
if (!telegramUser) {
return new Response(JSON.stringify({ error: 'Invalid Telegram data' }), {
status: 401,
@@ -216,7 +241,7 @@ serve(async (req) => {
JSON.stringify({
user: userData,
telegram_user: telegramUser,
session_token: generateSessionToken(telegramUser.id, botToken),
session_token: generateSessionToken(telegramUser.id, matchedBotToken),
}),
{ headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
);
@@ -8,7 +8,11 @@ import { ApiPromise, WsProvider } from 'npm:@pezkuwi/api@16.5.36';
import { createHmac } from 'https://deno.land/std@0.177.0/node/crypto.ts';
// CORS - Production domain only
const ALLOWED_ORIGINS = ['https://telegram.pezkuwichain.io', 'https://t.me'];
const ALLOWED_ORIGINS = [
'https://telegram.pezkuwichain.io',
'https://telegram.pezkiwi.app',
'https://t.me',
];
function getCorsHeaders(origin: string | null): Record<string, string> {
const allowedOrigin =