File size: 3,445 Bytes
dcc4f27
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/**
 * GoldRate Engine — API Key Authentication Middleware
 * 
 * Validates API keys against Supabase api_keys table.
 * Keys have 30-day expiry and are tied to a price source (SLN or IBJA).
 * 
 * Pass your key as:
 *   Header: x-api-key: your_key
 *   OR Query: ?apikey=your_key
 * 
 * After auth, req.priceSource is set to 'SLN' or 'IBJA'
 */

const { getIsConnected, getClient } = require('./db');

// In-memory cache for validated keys (avoid DB hit every request)
const keyCache = new Map();
const KEY_CACHE_TTL = 5 * 60 * 1000; // 5 minutes

function authMiddleware(req, res, next) {
  const apiKey = req.headers['x-api-key'] || req.query.apikey;

  if (!apiKey) {
    return res.status(401).json({
      success: false,
      error: 'API key required. Pass it as header "x-api-key" or query "?apikey=YOUR_KEY"'
    });
  }

  // Master key from .env (never expires, for admin/frontend use)
  if (apiKey === process.env.API_KEY) {
    req.priceSource = 'SLN'; // Default to SLN for master key
    req.isMasterKey = true;
    return next();
  }

  // Check key cache first
  const cached = keyCache.get(apiKey);
  if (cached && (Date.now() - cached.cachedAt) < KEY_CACHE_TTL) {
    const now = new Date();
    if (!cached.is_active) {
      return res.status(403).json({
        success: false,
        error: 'API key has been deactivated. Contact us to get a new key.',
        contact: process.env.CONTACT_PHONE || '9360345770'
      });
    }
    if (new Date(cached.expires_at) < now) {
      return res.status(403).json({
        success: false,
        error: 'API key expired. Contact us to renew.',
        contact: process.env.CONTACT_PHONE || '9360345770'
      });
    }
    req.priceSource = cached.source;
    req.keyOwner = cached.owner_name;
    return next();
  }

  // Look up in Supabase
  if (!getIsConnected()) {
    // If DB not connected, reject non-master keys
    return res.status(403).json({
      success: false,
      error: 'Invalid API key'
    });
  }

  const supabase = getClient();
  supabase
    .from('api_keys')
    .select('*')
    .eq('api_key', apiKey)
    .single()
    .then(({ data, error }) => {
      if (error || !data) {
        return res.status(403).json({
          success: false,
          error: 'Invalid API key. Contact us to get one.',
          contact: process.env.CONTACT_PHONE || '9360345770'
        });
      }

      // Cache the key data
      keyCache.set(apiKey, { ...data, cachedAt: Date.now() });

      // Check if active
      if (!data.is_active) {
        return res.status(403).json({
          success: false,
          error: 'API key has been deactivated. Contact us to get a new key.',
          contact: process.env.CONTACT_PHONE || '9360345770'
        });
      }

      // Check expiry
      const now = new Date();
      if (new Date(data.expires_at) < now) {
        return res.status(403).json({
          success: false,
          error: 'API key expired. Contact us to renew.',
          expired_at: data.expires_at,
          contact: process.env.CONTACT_PHONE || '9360345770'
        });
      }

      // Valid key — set source
      req.priceSource = data.source; // 'SLN' or 'IBJA'
      req.keyOwner = data.owner_name;
      next();
    })
    .catch(() => {
      return res.status(500).json({
        success: false,
        error: 'Authentication service error. Please try again.'
      });
    });
}

module.exports = { authMiddleware };