Files
goodie/pkg/server/login.go
Marc 0ed29fe2fd Odoo ERP ported to Go — complete backend + original OWL frontend
Full port of Odoo's ERP system from Python to Go, with the original
Odoo JavaScript frontend (OWL framework) running against the Go server.

Backend (10,691 LoC Go):
- Custom ORM: CRUD, domains→SQL with JOINs, computed fields, sequences
- 93 models across 14 modules (base, account, sale, stock, purchase, hr,
  project, crm, fleet, product, l10n_de, google_address/translate/calendar)
- Auth with bcrypt + session cookies
- Setup wizard (company, SKR03 chart, admin, demo data)
- Double-entry bookkeeping constraint
- Sale→Invoice workflow (confirm SO → generate invoice → post)
- SKR03 chart of accounts (110 accounts) + German taxes (USt/VSt)
- Record rules (multi-company filter)
- Google integrations as opt-in modules (Maps, Translate, Calendar)

Frontend:
- Odoo's original OWL webclient (503 JS modules, 378 XML templates)
- JS transpiled via Odoo's js_transpiler (ES modules → odoo.define)
- SCSS compiled to CSS (675KB) via dart-sass
- XML templates compiled to registerTemplate() JS calls
- Static file serving from Odoo source addons
- Login page, session management, menu navigation
- Contacts list view renders with real data from PostgreSQL

Infrastructure:
- 14MB single binary (CGO_ENABLED=0)
- Docker Compose (Go server + PostgreSQL 16)
- Zero phone-home (no outbound calls to odoo.com)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 01:45:09 +02:00

81 lines
3.3 KiB
Go

package server
import (
"net/http"
)
// handleLogin serves the login page.
func (s *Server) handleLogin(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.Write([]byte(`<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Odoo - Login</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
background: #f0eeee; display: flex; align-items: center; justify-content: center; min-height: 100vh; }
.login-box { background: white; padding: 40px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1);
width: 100%; max-width: 400px; }
.login-box h1 { text-align: center; color: #71639e; margin-bottom: 30px; font-size: 28px; }
.login-box label { display: block; margin-bottom: 6px; font-weight: 500; color: #333; }
.login-box input { width: 100%; padding: 10px 12px; border: 1px solid #ddd; border-radius: 4px;
font-size: 14px; margin-bottom: 16px; }
.login-box input:focus { outline: none; border-color: #71639e; box-shadow: 0 0 0 2px rgba(113,99,158,0.2); }
.login-box button { width: 100%; padding: 12px; background: #71639e; color: white; border: none;
border-radius: 4px; font-size: 16px; cursor: pointer; }
.login-box button:hover { background: #5f5387; }
.error { color: #dc3545; margin-bottom: 16px; display: none; text-align: center; }
</style>
</head>
<body>
<div class="login-box">
<h1>Odoo</h1>
<div id="error" class="error"></div>
<form id="loginForm">
<label for="login">Email</label>
<input type="text" id="login" name="login" value="admin" autofocus/>
<label for="password">Password</label>
<input type="password" id="password" name="password" value="admin"/>
<button type="submit">Log in</button>
</form>
</div>
<script>
document.getElementById('loginForm').addEventListener('submit', function(e) {
e.preventDefault();
var login = document.getElementById('login').value;
var password = document.getElementById('password').value;
var errorEl = document.getElementById('error');
errorEl.style.display = 'none';
fetch('/web/session/authenticate', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
jsonrpc: '2.0',
method: 'call',
id: 1,
params: {db: '` + s.config.DBName + `', login: login, password: password}
})
})
.then(function(r) { return r.json(); })
.then(function(data) {
if (data.error) {
errorEl.textContent = data.error.message;
errorEl.style.display = 'block';
} else if (data.result && data.result.uid) {
window.location.href = '/web';
}
})
.catch(function(err) {
errorEl.textContent = 'Connection error';
errorEl.style.display = 'block';
});
});
</script>
</body>
</html>`))
}