All files / postcardotp-backend/src/services apiKeyService.js

23.4% Statements 11/47
0% Branches 0/25
0% Functions 0/13
24.44% Lines 11/45

Press n or j to go to the next uncovered block, b, p or k for the previous block.

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 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 1531x   1x     1x         1x               1x                 1x                 1x         1x                   1x                 1x         1x                                                                                                                                                                              
const { models } = require("../config/sequelize");
 
const { ApiError } = require("../utils/errorHandler");
 
// Save a new API key
exports.saveApiKey = async (userId, key, type = "live") => {
  return models.ApiKey.create({ user_id: userId, key, type });
};
 
// Get all API keys for a user
exports.getUserApiKeys = async (userId) => {
  return models.ApiKey.findAll({
    where: { user_id: userId },
    order: [["created_at", "DESC"]],
  });
};
 
// Soft delete / revoke API key
exports.revokeApiKey = async (userId, id) => {
  const key = await models.ApiKey.findOne({ where: { id } });
  if (!key) throw new ApiError("API key not found or unauthorized", 404);
  key.status = "revoked";
  await key.save();
  return key;
};
 
// Restore a revoked API key (if needed)
exports.restoreApiKey = async (userId, id) => {
  const key = await models.ApiKey.findOne({ where: { id, user_id: userId } });
  if (!key) throw new ApiError("API key not found or unauthorized", 404);
  key.status = "active";
  await key.save();
  return key;
};
 
// Get a specific key
exports.getApiKeyById = async (id) => {
  return models.ApiKey.findByPk(id);
};
 
// Validate if an API key is legit and active
exports.validateApiKey = async (keyValue) => {
  return models.ApiKey.findOne({
    where: {
      key: keyValue,
      status: "active",
    },
  });
};
 
// Log key usage
exports.logApiKeyUsage = async (apiKeyId, endpoint, ipAddress) => {
  return models.ApiKeyUsage.create({
    api_key_id: apiKeyId,
    endpoint,
    ip_address: ipAddress,
  });
};
 
// Admin-only: get all keys (optional)
exports.getAllApiKeys = async () => {
  return models.ApiKey.findAll({
    include: [{ model: User, as: "user" }],
  });
};
exports.getApiKeyUsageLogs = async (apiKeyId, userId) => {
  // Verify the API key belongs to the user
  const key = await models.ApiKey.findOne({
    where: {
      id: apiKeyId,
      user_id: userId,
    },
    include: [
      {
        model: models.User,
        as: "user",
        attributes: ["id", "first_name", "last_name", "email"], // Fixed attribute name (last_name instead of lastname)
      },
    ],
  });
 
  if (!key) {
    throw new ApiError("API key not found or unauthorized", 404);
  }
 
  // Get all usage logs for this API key
  const logs = await models.ApiKeyUsage.findAll({
    where: { api_key_id: apiKeyId },
    order: [["request_time", "DESC"]],
    raw: true,
  });
 
  // Calculate statistics
  const totalCalls = logs.length;
  const endpoints = {};
  const ipAddresses = {};
  const dailyUsage = {};
 
  logs.forEach((log) => {
    // Count endpoint usage
    endpoints[log.endpoint] = (endpoints[log.endpoint] || 0) + 1;
 
    // Count IP addresses
    ipAddresses[log.ip_address] = (ipAddresses[log.ip_address] || 0) + 1;
 
    // Count daily usage
    const date = new Date(log.request_time).toISOString().split("T")[0];
    dailyUsage[date] = (dailyUsage[date] || 0) + 1;
  });
 
  // Combine first and last name
  const userName = key.user
    ? `${key.user.first_name || ""} ${key.user.last_name || ""}`.trim()
    : "Unknown User";
 
  return {
    metadata: {
      apiKeyId,
      user_name: userName, // Fixed user name concatenation
      user_email: key.user?.email || null,
      status: key.status,
      createdAt: key.created_at, // Changed from request_time to created_at for key creation time
      totalCalls,
      firstUsed: logs.length > 0 ? logs[logs.length - 1].request_time : null,
      lastUsed: logs.length > 0 ? logs[0].request_time : null,
    },
    statistics: {
      endpoints,
      ipAddresses,
      dailyUsage,
    },
    recentLogs: logs.slice(0, 100),
    timeStats: {
      last24Hours: logs.filter(
        (log) =>
          new Date(log.request_time) >
          new Date(Date.now() - 24 * 60 * 60 * 1000),
      ).length,
      last7Days: logs.filter(
        (log) =>
          new Date(log.request_time) >
          new Date(Date.now() - 7 * 24 * 60 * 60 * 1000),
      ).length,
      // Added monthly count
      last30Days: logs.filter(
        (log) =>
          new Date(log.request_time) >
          new Date(Date.now() - 30 * 24 * 60 * 60 * 1000),
      ).length,
    },
  };
};