Commit 62895778 authored by Andreas Düren's avatar Andreas Düren
Browse files

Implement Caddy for web app serving and fix OTP verification issues

parent 8df2a3a6
Loading
Loading
Loading
Loading
+183 −46
Original line number Diff line number Diff line
@@ -302,6 +302,9 @@ function generateNumericId() {
    return Math.floor(10000 + Math.random() * 90000);
}

// Store codes for verification (simple in-memory cache)
const verificationCodes = {};

// Create HTTP server
const server = http.createServer((req, res) => {
    const url = req.url;
@@ -311,7 +314,7 @@ const server = http.createServer((req, res) => {

    // Set CORS headers
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT');
    res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
    
    // Handle preflight requests
@@ -330,6 +333,34 @@ const server = http.createServer((req, res) => {
            time: new Date().toISOString() 
        }));
    } 
    else if (url.startsWith('/users/srp')) {
        // SRP endpoints - just return success for all SRP requests
        let body = '';
        
        req.on('data', chunk => {
            body += chunk.toString();
        });
        
        req.on('end', () => {
            log(`SRP request received: ${url} with body: ${body}`);
            
            // Return a standard response for any SRP request
            res.setHeader('Content-Type', 'application/json');
            res.end(JSON.stringify({ 
                status: "ok",
                id: 12345,
                token: "mock-token-12345",
                key: {
                    pubKey: "mockPubKey123456",
                    encPubKey: "mockEncPubKey123456",
                    kty: "RSA",
                    kid: "kid-123456",
                    alg: "RS256",
                    verifyKey: "mockVerifyKey123456"
                }
            }));
        });
    }
    else if (url === '/users/ott') {
        // OTT verification code endpoint
        let body = '';
@@ -363,6 +394,9 @@ const server = http.createServer((req, res) => {
            const code = generateCode();
            const userId = generateNumericId();
            
            // Store the code for this email
            verificationCodes[email] = code;
            
            // Log the code prominently
            const codeMessage = `⚠️ VERIFICATION CODE FOR ${email}: ${code}`;
            log(codeMessage);
@@ -407,17 +441,29 @@ const server = http.createServer((req, res) => {
            
            // Try to parse the request
            let email = 'user@example.com';
            let code = '123456';
            let code = '';
            let isValid = false;
            const userId = generateNumericId();
            
            try {
                const data = JSON.parse(body);
                if (data.email) email = data.email;
                
                // Try to get the verification code from different possible fields
                if (data.code) code = data.code;
                else if (data.ott) code = data.ott;
                
                // Check if code matches the stored code or is a test code
                if (code && (code === verificationCodes[email] || code === '123456' || code === '261419')) {
                    isValid = true;
                }
            } catch (e) {
                // Ignore parsing errors
                log(`Error parsing verification request: ${e.message}`);
                // For testing, treat as valid
                isValid = true;
            }
            
            if (isValid) {
                log(`⚠️ VERIFICATION SUCCESSFUL - code: ${code} for ${email}`);
                
                // Current timestamp
@@ -442,6 +488,35 @@ const server = http.createServer((req, res) => {
                    },
                    isEmailVerified: true
                }));
            } else {
                log(`⚠️ VERIFICATION FAILED - code: ${code} for ${email}`);
                
                // Send failure response
                res.statusCode = 400;
                res.setHeader('Content-Type', 'application/json');
                res.end(JSON.stringify({
                    status: "error",
                    message: "Invalid verification code"
                }));
            }
        });
    }
    else if (url === '/users/attributes' && method === 'PUT') {
        // Handle user attributes update
        let body = '';
        
        req.on('data', chunk => {
            body += chunk.toString();
        });
        
        req.on('end', () => {
            log(`User attributes update: ${body}`);
            
            // Send success response
            res.setHeader('Content-Type', 'application/json');
            res.end(JSON.stringify({
                status: "ok"
            }));
        });
    }
    else {
@@ -635,34 +710,96 @@ cat << EOF > /app/data/web/ente-patches.js
        }
    };
    
    // Patch the SRP implementation for browser compatibility
    if (window.process) {
        // Add any missing process methods
        window.process.nextTick = window.process.nextTick || function(fn) { 
            setTimeout(fn, 0); 
    // More robust Buffer implementation for SRP
    window.Buffer = window.Buffer || {
        from: function(data, encoding) {
            // Handle undefined data - critical fix
            if (data === undefined) {
                console.warn('Buffer.from called with undefined data, creating empty buffer');
                return {
                    data: '',
                    length: 0,
                    toString: function() { return ''; }
                };
            }
            
    // Add Buffer polyfill if needed
    if (!window.Buffer) {
        window.Buffer = {
            from: function(data, encoding) {
            // Handle string data
            if (typeof data === 'string') {
                    if (encoding === 'hex') {
                return {
                    data: data,
                            toString: function() { return data; }
                    length: data.length,
                    toString: function(enc) {
                        if (enc === 'hex' && encoding === 'hex') {
                            // Return the original hex string
                            return data;
                        }
                        return data;
                    }
                };
            }
            
            // Handle array/buffer data
            if (Array.isArray(data) || ArrayBuffer.isView(data)) {
                return {
                    data: data,
                        toString: function() { return data; }
                    length: data.length,
                    toString: function() {
                        return Array.from(data).map(b => String.fromCharCode(b)).join('');
                    }
                };
            }
                return { data: data };
            
            // Default fallback
            return {
                data: data || '',
                length: (data && data.length) || 0,
                toString: function() { return ''; }
            };
        },
            isBuffer: function() { return false; },
            alloc: function() { return {}; }
        isBuffer: function(obj) { return obj && obj.data !== undefined; },
        alloc: function(size) {
            const arr = new Array(size).fill(0);
            return {
                data: arr,
                length: size,
                toString: function() { return ''; }
            };
        },
        concat: function(list) {
            // Simple implementation that handles our use case
            return {
                data: list.map(b => b.data).join(''),
                length: list.reduce((acc, b) => acc + (b.length || 0), 0),
                toString: function() { 
                    return list.map(b => b.toString()).join('');
                }
            };
        }
    };
    
    // Add missing crypto methods that SRP might need
    if (window.crypto && !window.crypto.randomBytes) {
        window.crypto.randomBytes = function(size) {
            const array = new Uint8Array(size);
            window.crypto.getRandomValues(array);
            return {
                data: array,
                length: size,
                toString: function(encoding) {
                    if (encoding === 'hex') {
                        return Array.from(array).map(b => b.toString(16).padStart(2, '0')).join('');
                    }
                    return Array.from(array).map(b => String.fromCharCode(b)).join('');
                }
            };
        };
    }
    
    // Patch the SRP implementation for browser compatibility
    if (window.process) {
        // Add any missing process methods
        window.process.nextTick = window.process.nextTick || function(fn) { 
            setTimeout(fn, 0); 
        };
    }