package server import ( "encoding/json" "fmt" "net/http" ) // handleSessionCheck verifies the session is valid and returns session info. func (s *Server) handleSessionCheck(w http.ResponseWriter, r *http.Request) { sess := GetSession(r) if sess == nil { if cookie, err := r.Cookie("session_id"); err == nil && cookie.Value != "" { sess = s.sessions.Get(cookie.Value) } } if sess == nil { s.writeJSONRPC(w, nil, nil, &RPCError{ Code: 100, Message: "Session expired", }) return } s.writeJSONRPC(w, nil, s.buildSessionInfo(sess), nil) } // handleSessionModules returns installed module names. func (s *Server) handleSessionModules(w http.ResponseWriter, r *http.Request) { s.writeJSONRPC(w, nil, []string{ "base", "web", "contacts", "sale", "account", "stock", "purchase", "crm", "hr", "project", "fleet", "product", "l10n_de", }, nil) } // handleManifest returns a minimal PWA manifest. func (s *Server) handleManifest(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/manifest+json") json.NewEncoder(w).Encode(map[string]interface{}{ "name": "Odoo", "short_name": "Odoo", "start_url": "/web", "display": "standalone", "background_color": "#71639e", "theme_color": "#71639e", "icons": []map[string]string{ {"src": "/web/static/img/odoo-icon-192x192.png", "sizes": "192x192", "type": "image/png"}, }, }) } // handleBootstrapTranslations returns translations for initial boot (login page etc.). // Mirrors: odoo/addons/web/controllers/webclient.py bootstrap_translations() func (s *Server) handleBootstrapTranslations(w http.ResponseWriter, r *http.Request) { lang := "en_US" // Try to detect language from request if r.Method == http.MethodPost { var req JSONRPCRequest if err := json.NewDecoder(r.Body).Decode(&req); err == nil { var params struct { Mods []string `json:"mods"` Lang string `json:"lang"` } if err := json.Unmarshal(req.Params, ¶ms); err == nil && params.Lang != "" { lang = params.Lang } } } langParams := map[string]interface{}{ "direction": "ltr", "date_format": "%%m/%%d/%%Y", "time_format": "%%H:%%M:%%S", "grouping": "[3,0]", "decimal_point": ".", "thousands_sep": ",", "week_start": 1, } // Try to load language parameters from res_lang var dateFormat, timeFormat, decimalPoint, thousandsSep, direction string err := s.pool.QueryRow(r.Context(), `SELECT date_format, time_format, decimal_point, thousands_sep, direction FROM res_lang WHERE code = $1 AND active = true`, lang, ).Scan(&dateFormat, &timeFormat, &decimalPoint, &thousandsSep, &direction) if err == nil { langParams["date_format"] = dateFormat langParams["time_format"] = timeFormat langParams["decimal_point"] = decimalPoint langParams["thousands_sep"] = thousandsSep langParams["direction"] = direction } // Check if multiple languages are active multiLang := false var langCount int if err := s.pool.QueryRow(r.Context(), `SELECT COUNT(*) FROM res_lang WHERE active = true`).Scan(&langCount); err == nil { if langCount > 1 { multiLang = true } } s.writeJSONRPC(w, nil, map[string]interface{}{ "lang": lang, "hash": fmt.Sprintf("odoo-go-boot-%s", lang), "lang_parameters": langParams, "modules": map[string]interface{}{}, "multi_lang": multiLang, }, nil) }