blob: 51313eb382b4adcaff706efe1a5b390a0ab5501b [file] [log] [blame]
Davit Tabidze207ce082024-04-09 19:15:25 +04001package welcome
2
3import (
4 "embed"
5 "fmt"
6 "html/template"
7 "log"
8 "net/http"
9 "strings"
Davit Tabidze56f86a42024-04-09 19:15:25 +040010
11 "github.com/giolekva/pcloud/core/installer"
gioc23530e2024-05-01 11:06:09 +040012
giobe7b7242024-05-20 18:13:55 +040013 "github.com/Masterminds/sprig/v3"
gioc23530e2024-05-01 11:06:09 +040014 "github.com/gomarkdown/markdown"
Davit Tabidze207ce082024-04-09 19:15:25 +040015)
16
17//go:embed launcher-tmpl/launcher.html
18var indexHTML embed.FS
19
20//go:embed static/*
21var files embed.FS
22
23type AppLauncherInfo struct {
Davit Tabidze56f86a42024-04-09 19:15:25 +040024 Name string
25 Icon template.HTML
gioc23530e2024-05-01 11:06:09 +040026 Help []HelpDocumentRendered
Davit Tabidze56f86a42024-04-09 19:15:25 +040027 Url string
Davit Tabidze207ce082024-04-09 19:15:25 +040028}
29
gioc23530e2024-05-01 11:06:09 +040030type HelpDocumentRendered struct {
31 Title string
32 Contents template.HTML
33 Children []HelpDocumentRendered
34}
35
Davit Tabidze207ce082024-04-09 19:15:25 +040036type AppDirectory interface {
37 GetAllApps() ([]AppLauncherInfo, error)
38}
39
Davit Tabidze56f86a42024-04-09 19:15:25 +040040type AppManagerDirectory struct {
41 AppManager *installer.AppManager
42}
43
gio09a3e5b2024-04-26 14:11:06 +040044func (d *AppManagerDirectory) GetAllApps() ([]AppLauncherInfo, error) {
45 all, err := d.AppManager.FindAllInstances()
46 if err != nil {
47 return nil, err
48 }
49 ret := []AppLauncherInfo{}
50 for _, a := range all {
51 if a.URL == "" && len(a.Help) == 0 {
52 continue
53 }
54 ret = append(ret, AppLauncherInfo{
55 Name: a.AppId,
56 Icon: template.HTML(a.Icon),
gioc23530e2024-05-01 11:06:09 +040057 Help: toMarkdown(a.Help),
gio09a3e5b2024-04-26 14:11:06 +040058 Url: a.URL,
59 })
60 }
61 return ret, nil
62}
63
Davit Tabidze207ce082024-04-09 19:15:25 +040064type LauncherServer struct {
65 port int
66 logoutUrl string
67 appDirectory AppDirectory
68 homeTmpl *template.Template
69}
70
71func NewLauncherServer(
72 port int,
73 logoutUrl string,
74 appDirectory AppDirectory,
75) (*LauncherServer, error) {
76 tmpl, err := indexHTML.ReadFile("launcher-tmpl/launcher.html")
77 if err != nil {
78 return nil, fmt.Errorf("failed to parse template: %v", err)
79 }
giobe7b7242024-05-20 18:13:55 +040080 t := template.New("index").Funcs(template.FuncMap(sprig.FuncMap())).Funcs(template.FuncMap{
Davit Tabidze207ce082024-04-09 19:15:25 +040081 "GetUserInitials": getUserInitials,
82 "CleanAppName": cleanAppName,
83 })
84 t, err = t.Parse(string(tmpl))
85 if err != nil {
86 return nil, fmt.Errorf("failed to parse template: %v", err)
87 }
88 return &LauncherServer{
89 port,
90 logoutUrl,
91 appDirectory,
92 t,
93 }, nil
94}
95
96func getUserInitials(username string) string {
97 if username == "" {
98 return ""
99 }
100 return strings.ToUpper(username[:1])
101}
102
103func cleanAppName(name string) string {
104 cleanName := strings.ToLower(name)
105 cleanName = strings.ReplaceAll(cleanName, " ", "-")
106 return cleanName
107}
108
Davit Tabidze56f86a42024-04-09 19:15:25 +0400109func getLoggedInUser(r *http.Request) (string, error) {
110 if user := r.Header.Get("X-User"); user != "" {
111 return user, nil
112 } else {
113 return "", fmt.Errorf("unauthenticated")
114 }
115 // return "Username", nil
116}
117
Davit Tabidze207ce082024-04-09 19:15:25 +0400118func (s *LauncherServer) Start() {
119 http.Handle("/static/", http.FileServer(http.FS(files)))
120 http.HandleFunc("/", s.homeHandler)
121 log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", s.port), nil))
122}
123
124type homeHandlerData struct {
125 LoggedInUsername string
126 AllAppsInfo []AppLauncherInfo
127}
128
129func (s *LauncherServer) homeHandler(w http.ResponseWriter, r *http.Request) {
Davit Tabidze56f86a42024-04-09 19:15:25 +0400130 loggedInUsername, err := getLoggedInUser(r)
131 if err != nil {
132 http.Error(w, "User Not Logged In", http.StatusUnauthorized)
133 return
134 }
Davit Tabidze207ce082024-04-09 19:15:25 +0400135 allAppsInfo, err := s.appDirectory.GetAllApps()
136 if err != nil {
Davit Tabidze56f86a42024-04-09 19:15:25 +0400137 http.Error(w, err.Error(), http.StatusInternalServerError)
Davit Tabidze207ce082024-04-09 19:15:25 +0400138 }
139 data := homeHandlerData{
140 LoggedInUsername: loggedInUsername,
141 AllAppsInfo: allAppsInfo,
142 }
143 if err := s.homeTmpl.Execute(w, data); err != nil {
144 http.Error(w, err.Error(), http.StatusInternalServerError)
145 return
146 }
147}
gioc23530e2024-05-01 11:06:09 +0400148
149func toMarkdown(help []installer.HelpDocument) []HelpDocumentRendered {
150 if help == nil {
151 return nil
152 }
153 var ret []HelpDocumentRendered
154 for _, h := range help {
155 ret = append(ret, HelpDocumentRendered{
156 Title: h.Title,
157 Contents: template.HTML(markdown.ToHTML([]byte(h.Contents), nil, nil)),
158 Children: toMarkdown(h.Children),
159 })
160 }
161 return ret
162}