diff --git a/main.go b/main.go index 201703c..c8f29f9 100644 --- a/main.go +++ b/main.go @@ -56,6 +56,7 @@ type Settings struct { Name string `yaml:"name"` Subtitle string `yaml:"subtitle"` Logo string `yaml:"logo"` + TopUser string `yaml:"top_user"` Language string `yaml:"language"` Timezone string `yaml:"timezone"` } `yaml:"company"` @@ -81,6 +82,13 @@ type UserSettings struct { EmailPassword string `json:"email_password,omitempty"` Language string `json:"language,omitempty"` Timezone string `json:"timezone,omitempty"` + Phone string `json:"phone,omitempty"` + Address string `json:"address,omitempty"` + Messenger string `json:"messenger,omitempty"` + Bio string `json:"bio,omitempty"` + Manager string `json:"manager,omitempty"` + JobTitle string `json:"job_title,omitempty"` + Dept string `json:"dept,omitempty"` } func loadUserSettings(username string) *UserSettings { @@ -445,6 +453,13 @@ func userSettingsSaveHandler(w http.ResponseWriter, r *http.Request) { EmailPassword: r.FormValue("email_password"), Language: r.FormValue("language"), Timezone: r.FormValue("timezone"), + Phone: r.FormValue("phone"), + Address: r.FormValue("address"), + Messenger: r.FormValue("messenger"), + Bio: r.FormValue("bio"), + Manager: r.FormValue("manager"), + JobTitle: r.FormValue("job_title"), + Dept: r.FormValue("dept"), } if err := saveUserSettings(user, us); err != nil { http.Error(w, "Failed to save", http.StatusInternalServerError) @@ -453,6 +468,109 @@ func userSettingsSaveHandler(w http.ResponseWriter, r *http.Request) { w.Write([]byte(`{"status":"ok"}`)) } +// --- People directory --- + +type apiUser struct { + Username string `json:"username"` + DisplayName string `json:"display_name"` +} + +func fetchAllUsers() ([]apiUser, error) { + apiToken := os.Getenv("AUTHELIA_SECRET") + req, _ := http.NewRequest("GET", "http://127.0.0.1:8080/api/users", nil) + req.Header.Set("Authorization", "Bearer "+apiToken) + resp, err := http.DefaultClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + var users []apiUser + json.NewDecoder(resp.Body).Decode(&users) + return users, nil +} + +func peopleDirectoryHandler(w http.ResponseWriter, r *http.Request) { + // If path is /people/{username}, show profile + username := strings.TrimPrefix(r.URL.Path, "/people/") + if username != "" && username != "/" && !strings.Contains(username, "/") { + peopleProfileHandler(w, r, username) + return + } + + users, err := fetchAllUsers() + if err != nil { + http.Error(w, "Failed to fetch users", http.StatusBadGateway) + return + } + + type Person struct { + Username string + DisplayName string + JobTitle string + Dept string + ProfilePic string + } + var people []Person + for _, u := range users { + us := loadUserSettings(u.Username) + displayName := u.DisplayName + if us.FirstName != "" { + displayName = us.FirstName + " " + us.LastName + } + people = append(people, Person{ + Username: u.Username, + DisplayName: displayName, + JobTitle: us.JobTitle, + Dept: us.Dept, + ProfilePic: us.ProfilePicture, + }) + } + + tmpl := template.Must(template.New("people").Funcs(template.FuncMap{"t": t, "initial": initials}).Parse(peopleHTML)) + w.Header().Set("Content-Type", "text/html; charset=utf-8") + tmpl.Execute(w, map[string]interface{}{"People": people, "Lang": "en"}) +} + +func peopleProfileHandler(w http.ResponseWriter, r *http.Request, username string) { + us := loadUserSettings(username) + + var managerName string + if us.Manager != "" { + mgr := loadUserSettings(us.Manager) + if mgr.FirstName != "" { + managerName = mgr.FirstName + " " + mgr.LastName + } else { + managerName = us.Manager + } + } + + tmpl := template.Must(template.New("profile").Funcs(template.FuncMap{"t": t, "initial": initials}).Parse(profileHTML)) + w.Header().Set("Content-Type", "text/html; charset=utf-8") + tmpl.Execute(w, map[string]interface{}{ + "Username": username, + "Profile": us, + "ManagerName": managerName, + "Lang": "en", + }) +} + +func initials(s string) string { + parts := strings.Fields(s) + if len(parts) == 0 { + return "?" + } + var result string + for _, p := range parts { + if len(p) > 0 { + result += strings.ToUpper(string(p[0])) + } + } + if len(result) > 2 { + result = result[:2] + } + return result +} + // --- API proxy for authelia-api --- func apiProxyHandler(w http.ResponseWriter, r *http.Request) { @@ -522,6 +640,7 @@ func globalSettingsSaveHandler(w http.ResponseWriter, r *http.Request) { settings.Company.Name = r.FormValue("company_name") settings.Company.Subtitle = r.FormValue("company_subtitle") settings.Company.Logo = r.FormValue("company_logo") + settings.Company.TopUser = r.FormValue("top_user") settings.Company.Language = r.FormValue("language") settings.Company.Timezone = r.FormValue("timezone") settings.SMTP.Host = r.FormValue("smtp_host") @@ -731,6 +850,7 @@ const launcherHTML = `
@@ -794,6 +914,17 @@ const settingsHTML = ` +Server: {{.Settings.IMAP.Host}}:{{.Settings.IMAP.Port}}
@@ -852,6 +983,105 @@ const settingsHTML = `