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 | 2x 2x 2x 2x 2x 2x 2x 2x 2x | // Centralized configuration for the queuing / storage feature.
//
// Authentication to Google Cloud (Pub/Sub + Storage) is handled automatically
// by the client libraries through the GOOGLE_APPLICATION_CREDENTIALS
// environment variable, which must point to the absolute path of a service
// account JSON key file. That key file must NEVER be committed to the repo.
//
// See .env.example for the full list of variables.
require('dotenv').config();
// The number "i" attributed to you. The Pub/Sub topic and subscription are
// both named "ecni2-<i>". Set PUBSUB_INDEX in your .env file.
const pubsubIndex = process.env.PUBSUB_INDEX || '';
const resourceName = `ecni2-${pubsubIndex}`;
const isTest = process.env.NODE_ENV === 'test';
// --- Rate limiting (token bucket) -----------------------------------------
// Redis connection used to share the rate-limiter state across horizontally
// scaled instances (Part III of the TP). The password MUST come from an
// environment variable and never be committed (see .env / .env.example).
const redisUrl = process.env.REDIS_URL || '';
const redisHost = process.env.REDIS_HOST || '';
// Only turn the Redis-backed limiter on when we actually have connection
// details; otherwise the limiter degrades to a per-process in-memory map.
const redisConfigured = Boolean(redisUrl || redisHost);
// Firebase Realtime Database is used to persist the completed zips so they
// survive a restart of the instance. The Admin SDK authenticates with the exact
// same service account key as Pub/Sub / Storage (GOOGLE_APPLICATION_CREDENTIALS),
// so no extra credentials are needed.
const firebaseDatabaseUrl =
process.env.FIREBASE_DATABASE_URL ||
'https://ecni2-2026-default-rtdb.firebaseio.com';
module.exports = {
// Google Cloud project that hosts the Pub/Sub topic and the bucket.
projectId: process.env.GOOGLE_CLOUD_PROJECT || 'ecni2-2026',
// Topic and subscription share the same "ecni2-<i>" name.
topicName: process.env.PUBSUB_TOPIC || resourceName,
subscriptionName: process.env.PUBSUB_SUBSCRIPTION || resourceName,
// Google Cloud Storage bucket where the generated zips are stored.
storageBucket: process.env.STORAGE_BUCKET || 'ecni22026bucket',
// Whether to start the background worker on boot. Explicitly controllable via
// WORKER_ENABLED; otherwise on everywhere except the test environment.
workerEnabled: process.env.WORKER_ENABLED
? process.env.WORKER_ENABLED !== 'false'
: !isTest,
pubsubIndex,
// --- Firebase (Realtime Database + Auth) ---------------------------------
// Realtime Database URL (Part I & II). From the TP guide.
firebaseDatabaseUrl,
// Root path segment ("votreprenom") under which completed zips are stored:
// /<firebaseDbRoot>/<heureduzippage>/<filename>
firebaseDbRoot: process.env.FIREBASE_DB_ROOT || 'theo',
// Turn the whole Firebase integration on/off. Off in the test environment so
// the suite never needs a live database; otherwise on. Can be forced with
// FIREBASE_ENABLED=true/false.
firebaseEnabled: process.env.FIREBASE_ENABLED
? process.env.FIREBASE_ENABLED !== 'false'
: !isTest,
// Require a verified Firebase ID token on the mutating zip endpoints (Part
// III). Defaults to on wherever Firebase is enabled; force with
// AUTH_REQUIRED=true/false.
authRequired: process.env.AUTH_REQUIRED
? process.env.AUTH_REQUIRED !== 'false'
: !isTest,
// --- Rate limiting (token bucket algorithm) ------------------------------
// The zip generation endpoint is the most sensitive to abuse (a malicious
// actor spamming the "generate zip" button), so we throttle it per client IP
// with a token bucket. The three numbers below are the algorithm constants
// from the TP:
// r -> tokens refilled per second
// b -> bucket size (also the starting/burst allowance)
// cost -> tokens consumed by a single request
rateLimitRefillPerSecond: Number(process.env.RATE_LIMIT_REFILL_PER_SECOND) || 1, // r
rateLimitBucketSize: Number(process.env.RATE_LIMIT_BUCKET_SIZE) || 15, // b
rateLimitRequestCost: Number(process.env.RATE_LIMIT_REQUEST_COST) || 3, // cost
// Turn rate limiting on/off. Off in the test environment (so the suite never
// needs a Redis server and isn't throttled); on everywhere else. Force with
// RATE_LIMIT_ENABLED=true/false.
rateLimitEnabled: process.env.RATE_LIMIT_ENABLED
? process.env.RATE_LIMIT_ENABLED !== 'false'
: !isTest,
// Back the limiter with Redis so several instances share one bucket per IP
// (Part III). Enabled automatically when REDIS_URL / REDIS_HOST are set and
// we're not in tests; otherwise the limiter falls back to an in-memory map
// (Part II). Force with RATE_LIMIT_REDIS_ENABLED=true/false.
rateLimitRedisEnabled: process.env.RATE_LIMIT_REDIS_ENABLED
? process.env.RATE_LIMIT_REDIS_ENABLED !== 'false'
: redisConfigured && !isTest,
// Redis connection details (Part III). Prefer a full REDIS_URL; otherwise
// assemble the connection from the individual pieces the TP provides.
redisUrl,
redisUsername: process.env.REDIS_USERNAME || 'default',
redisPassword: process.env.REDIS_PASSWORD || '',
redisHost,
redisPort: Number(process.env.REDIS_PORT) || 6379
};
|