diff --git a/.gitignore b/.gitignore index 5bed118..d1a6e8a 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ node_modules/ .vscode/ .DS_Store .pgpass -.log \ No newline at end of file +.log +.sh \ No newline at end of file diff --git a/public/css/login.css b/public/css/login.css index c7da188..27f349b 100644 --- a/public/css/login.css +++ b/public/css/login.css @@ -307,3 +307,68 @@ body { font-size: 0.8rem; } } + +/* OAuth Container */ +.oauth-container { + margin-bottom: 20px; +} + +.btn-google { + width: 100%; + background: white; + color: #333; + border: 1px solid #dadce0; + padding: 12px 16px; + border-radius: 8px; + font-weight: 500; + cursor: pointer; + transition: all 0.3s ease; + display: flex; + align-items: center; + justify-content: center; + gap: 12px; + font-size: 0.95rem; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} + +.btn-google:hover { + background: #f8f9fa; + border-color: #c1c7cd; + transform: translateY(-1px); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); +} + +.btn-google:active { + transform: translateY(0); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} + +.btn-google svg { + flex-shrink: 0; +} + +/* Divider */ +.divider { + position: relative; + text-align: center; + margin: 20px 0; + color: #64748b; + font-size: 0.9rem; +} + +.divider::before { + content: ''; + position: absolute; + top: 50%; + left: 0; + right: 0; + height: 1px; + background: linear-gradient(to right, transparent, #334155, transparent); +} + +.divider span { + background: #0a0a0f; + padding: 0 16px; + position: relative; + z-index: 1; +} diff --git a/public/js/login.js b/public/js/login.js index 8ae7c71..2642cf8 100644 --- a/public/js/login.js +++ b/public/js/login.js @@ -13,6 +13,32 @@ async function checkAuth() { } } +// Google OAuth Sign In +async function signInWithGoogle() { + try { + setLoading(true); + clearMessage(); + + const { data, error } = await supabase.auth.signInWithOAuth({ + provider: 'google', + options: { + redirectTo: `${window.location.origin}/auth/callback` + } + }); + + if (error) { + console.error('Google OAuth error:', error); + showMessage('Fehler bei der Google-Anmeldung: ' + error.message, 'error'); + } + // Note: OAuth redirects the page, so we don't need to handle success here + } catch (error) { + console.error('Google OAuth error:', error); + showMessage('Fehler bei der Google-Anmeldung: ' + error.message, 'error'); + } finally { + setLoading(false); + } +} + // Toggle between login and register forms function toggleForm() { const loginForm = document.getElementById('loginForm'); @@ -65,6 +91,9 @@ function setLoading(show) { // Event Listeners Setup function setupEventListeners() { + // Handle Google OAuth + document.getElementById('googleSignInBtn').addEventListener('click', signInWithGoogle); + // Handle login document.getElementById('loginFormElement').addEventListener('submit', async (e) => { e.preventDefault(); diff --git a/public/login.html b/public/login.html index 7aff8cf..198e01b 100644 --- a/public/login.html +++ b/public/login.html @@ -27,6 +27,23 @@

Welcome Back

+ +
+ +
+ +
+ or +
+
diff --git a/server.js b/server.js index fbfb22c..f652392 100644 --- a/server.js +++ b/server.js @@ -165,6 +165,16 @@ app.get('/adminlogin.html', (req, res) => { res.sendFile(path.join(__dirname, 'public', 'adminlogin.html')); }); +/** + * OAuth Callback Route + * Handles OAuth redirects from Supabase (Google, etc.) + */ +app.get('/auth/callback', (req, res) => { + // Redirect to the main page after OAuth callback + // Supabase handles the OAuth flow and redirects here + res.redirect('/'); +}); + // ============================================================================ // STATIC FILE SERVING // ============================================================================ diff --git a/server.log b/server.log index c39d578..65a1dd3 100644 --- a/server.log +++ b/server.log @@ -1,18 +1,8 @@ nohup: ignoring input -Uncaught Exception: Error: listen EADDRINUSE: address already in use :::3000 - at Server.setupListenHandle [as _listen2] (node:net:1940:16) - at listenInCluster (node:net:1997:12) - at Server.listen (node:net:2102:7) - at Object. (/root/ninjaserver/server.js:229:8) - at Module._compile (node:internal/modules/cjs/loader:1688:14) - at Object..js (node:internal/modules/cjs/loader:1820:10) - at Module.load (node:internal/modules/cjs/loader:1423:32) - at Function._load (node:internal/modules/cjs/loader:1246:12) - at TracingChannel.traceSync (node:diagnostics_channel:322:14) - at wrapModuleLoad (node:internal/modules/cjs/loader:235:24) { - code: 'EADDRINUSE', - errno: -98, - syscall: 'listen', - address: '::', - port: 3000 -} +๐Ÿš€ Server lรคuft auf http://ninja.reptilfpv.de:3000 +๐Ÿ“Š Datenbank: localhost:5432/ninjacross +๐Ÿ” API-Key Authentifizierung aktiviert +๐Ÿ”Œ WebSocket-Server aktiviert +๐Ÿ“ Static files: /public +๐ŸŒ Public API: /public-api +๐Ÿ”‘ Private API: /api