File size: 4,214 Bytes
3253ef3
 
a1011f7
3253ef3
 
 
 
be24b13
3253ef3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
be24b13
 
 
 
 
 
 
 
 
 
 
3253ef3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a1011f7
 
 
 
 
 
 
 
 
3253ef3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
const express = require('express');
const bodyParser = require('body-parser');
const rateLimit = require('express-rate-limit');
const fs = require('fs');
const path = require('path');

const app = express();
const PORT = process.env.PORT || 3000; // User preferred default
const DATA_FILE = path.join(__dirname, '../data/ressentis.json');
const APP_PASSWORD = process.env.APP_PASSWORD || 'parox'; // Default password

app.use(bodyParser.json());
app.use(express.static(path.join(__dirname, 'public')));

// Middleware to check authentication
const checkAuth = (req, res, next) => {
    // For simplicity, we'll check a custom header 'x-auth-token' or query param
    const token = req.headers['x-auth-token'];
    if (token === APP_PASSWORD) {
        next();
    } else {
        res.status(401).json({ error: 'Unauthorized' });
    }
};

// GCS Setup
const { Storage } = require('@google-cloud/storage');
const GCS_BUCKET_NAME = process.env.GCS_BUCKET_NAME;

// HF Spaces / General Secret support: Write key from ENV to file if available
if (process.env.GCS_KEY_JSON && !fs.existsSync('/app/gcs-key.json')) {
    try {
        console.log("> Writing GCS Key from ENV (GCS_KEY_JSON) to file...");
        fs.writeFileSync('/app/gcs-key.json', process.env.GCS_KEY_JSON);
        process.env.GOOGLE_APPLICATION_CREDENTIALS = '/app/gcs-key.json';
    } catch (e) {
        console.error("! Failed to write GCS Key from ENV:", e);
    }
}

let gcsBucket = null;
if (GCS_BUCKET_NAME) {
    try {
        const storage = new Storage();
        gcsBucket = storage.bucket(GCS_BUCKET_NAME);
        console.log(`> GCS Enabled: Using bucket '${GCS_BUCKET_NAME}'`);
    } catch (e) {
        console.error("! GCS config found but failed to init:", e);
    }
} else {
    console.log("> GCS Disabled: Using local filesystem");
    // Ensure data file exists locally
    if (!fs.existsSync(DATA_FILE)) {
        try {
            fs.mkdirSync(path.dirname(DATA_FILE), { recursive: true });
            fs.writeFileSync(DATA_FILE, JSON.stringify([], null, 2));
        } catch (e) { console.error("FS Init Error:", e); }
    }
}

// Data Handling Functions
async function readData() {
    if (gcsBucket) {
        try {
            const [contents] = await gcsBucket.file('ressentis.json').download();
            return JSON.parse(contents.toString());
        } catch (e) {
            if (e.code === 404) return []; // Auto-create on first write
            throw e;
        }
    } else {
        if (fs.existsSync(DATA_FILE)) {
            return JSON.parse(fs.readFileSync(DATA_FILE, 'utf8'));
        }
        return [];
    }
}

async function writeData(data) {
    const jsonStr = JSON.stringify(data, null, 2);
    if (gcsBucket) {
        await gcsBucket.file('ressentis.json').save(jsonStr, {
            contentType: 'application/json',
            resumable: false
        });
    } else {
        fs.writeFileSync(DATA_FILE, jsonStr);
    }
}

// API Routes

// Login check
const loginLimiter = rateLimit({
    windowMs: 15 * 60 * 1000, // 15 minutes
    max: 5, // Limit each IP to 5 requests per windowMs
    messsage: { error: 'Too many login attempts, please try again after 15 minutes' },
    standardHeaders: true,
    legacyHeaders: false,
});

app.post('/api/login', loginLimiter, (req, res) => {
    const { password } = req.body;
    if (password === APP_PASSWORD) {
        res.json({ success: true, token: password });
    } else {
        res.status(401).json({ success: false, error: 'Invalid Password' });
    }
});

// Get Data
app.get('/api/data', checkAuth, async (req, res) => {
    try {
        const data = await readData();
        res.json(data);
    } catch (e) {
        console.error("Read Error:", e);
        res.status(500).json({ error: 'Failed to read data' });
    }
});

// Save Data
app.post('/api/data', checkAuth, async (req, res) => {
    const newData = req.body;
    try {
        await writeData(newData);
        res.json({ success: true });
    } catch (e) {
        console.error("Save Error:", e);
        res.status(500).json({ error: 'Failed to save data' });
    }
});

app.listen(PORT, () => {
    console.log(`Server running on http://localhost:${PORT}`);
});