package server import ( "context" "encoding/json" "fmt" "log" "net/http" "regexp" "strings" "time" "odoo-go/pkg/service" "odoo-go/pkg/tools" ) var dbnamePattern = regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9_.-]+$`) // isSetupNeeded checks if the current database has been initialized. func (s *Server) isSetupNeeded() bool { var count int err := s.pool.QueryRow(context.Background(), `SELECT COUNT(*) FROM res_company`).Scan(&count) return err != nil || count == 0 } // handleDatabaseManager serves the database manager page. // Mirrors: odoo/addons/web/controllers/database.py Database.manager() func (s *Server) handleDatabaseManager(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html; charset=utf-8") w.Write([]byte(databaseManagerHTML)) } // handleDatabaseCreate processes the database creation form. // Mirrors: odoo/addons/web/controllers/database.py Database.create() // Fields match Python Odoo: name, login, password, phone, lang, country_code, demo func (s *Server) handleDatabaseCreate(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) return } var params struct { MasterPwd string `json:"master_pwd"` Name string `json:"name"` Login string `json:"login"` Password string `json:"password"` Phone string `json:"phone"` Lang string `json:"lang"` CountryCode string `json:"country_code"` Demo bool `json:"demo"` } if err := json.NewDecoder(r.Body).Decode(¶ms); err != nil { writeJSON(w, map[string]string{"error": "Invalid request"}) return } // Validate if params.Login == "" || params.Password == "" { writeJSON(w, map[string]string{"error": "Email and password are required"}) return } if len(params.Password) < 4 { writeJSON(w, map[string]string{"error": "Password must be at least 4 characters"}) return } // Default values if params.Lang == "" { params.Lang = "en_US" } if params.CountryCode == "" { params.CountryCode = "DE" } // Map country code countryName := "Germany" phoneCode := "49" switch strings.ToUpper(params.CountryCode) { case "AT": countryName = "Austria" phoneCode = "43" case "CH": countryName = "Switzerland" phoneCode = "41" case "US": countryName = "United States" phoneCode = "1" case "GB": countryName = "United Kingdom" phoneCode = "44" case "FR": countryName = "France" phoneCode = "33" } // Determine chart of accounts from country chart := "skr03" switch strings.ToUpper(params.CountryCode) { case "AT", "CH": chart = "skr03" // Use SKR03 for DACH region default: chart = "skr03" } // Extract company name from email domain, or use default companyName := "My Company" if strings.Contains(params.Login, "@") { parts := strings.Split(params.Login, "@") if len(parts) == 2 { domain := parts[1] domainParts := strings.Split(domain, ".") if len(domainParts) > 0 { companyName = strings.Title(domainParts[0]) } } } log.Printf("setup: creating database for %q (login: %s, country: %s)", companyName, params.Login, params.CountryCode) // Hash password hashedPw, err := tools.HashPassword(params.Password) if err != nil { writeJSON(w, map[string]string{"error": fmt.Sprintf("Password error: %v", err)}) return } // Seed the database setupCfg := service.SetupConfig{ CompanyName: companyName, CountryCode: strings.ToUpper(params.CountryCode), CountryName: countryName, PhoneCode: phoneCode, Phone: params.Phone, Email: params.Login, Chart: chart, AdminLogin: params.Login, AdminPassword: hashedPw, DemoData: params.Demo, } if err := service.SeedWithSetup(context.Background(), s.pool, setupCfg); err != nil { log.Printf("setup: error: %v", err) writeJSON(w, map[string]string{"error": fmt.Sprintf("Database error: %v", err)}) return } // Auto-login: create session and return session cookie // Mirrors: odoo/addons/web/controllers/database.py line 82-88 sess := s.sessions.New(1, 1, params.Login) http.SetCookie(w, &http.Cookie{ Name: "session_id", Value: sess.ID, Path: "/", HttpOnly: true, SameSite: http.SameSiteLaxMode, }) log.Printf("setup: database initialized, auto-login as %q", params.Login) writeJSON(w, map[string]interface{}{ "status": "ok", "session_id": sess.ID, "redirect": "/odoo", }) } // handleDatabaseList returns the list of databases. // Mirrors: odoo/addons/web/controllers/database.py Database.list() func (s *Server) handleDatabaseListJSON(w http.ResponseWriter, r *http.Request) { writeJSON(w, []string{s.config.DBName}) } func writeJSON(w http.ResponseWriter, v interface{}) { w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(v) } // --- Database Manager HTML --- // Mirrors: odoo/addons/web/static/src/public/database_manager.create_form.qweb.html var databaseManagerHTML = ` Odoo — Database Manager

Create Database

Set up your Odoo database

Default: admin

Creating database...

` + fmt.Sprintf("", time.Now().Format(time.RFC3339))