blob: 03a4047a15c1b1829f698cdb5ca085854a46b47f [file] [log] [blame]
Giorgi Lekveishvili12850ee2023-06-22 13:11:17 +04001package welcome
2
3import (
4 "embed"
5 "encoding/json"
6 "fmt"
7 "log"
8 "net/http"
Giorgi Lekveishvili6b887be2023-06-22 14:38:19 +04009 "net/url"
Giorgi Lekveishvili12850ee2023-06-22 13:11:17 +040010
11 "github.com/labstack/echo/v4"
12
13 "github.com/giolekva/pcloud/core/installer"
14)
15
16//go:embed index.html
17var indexHtml string
18
19//go:embed static/*
20var staticAssets embed.FS
21
22type Server struct {
23 port int
24 repo installer.RepoIO
25}
26
27func NewServer(port int, repo installer.RepoIO) *Server {
28 return &Server{
29 port,
30 repo,
31 }
32}
33
34func (s *Server) Start() {
35 e := echo.New()
36 e.StaticFS("/static", echo.MustSubFS(staticAssets, "static"))
37 e.POST("/create-admin-account", s.createAdminAccount)
38 e.GET("/", s.createAdminAccountForm)
39 log.Fatal(e.Start(fmt.Sprintf(":%d", s.port)))
40}
41
42func (s *Server) createAdminAccountForm(c echo.Context) error {
43 return c.HTML(http.StatusOK, indexHtml)
44}
45
46type createAdminAccountReq struct {
47 Username string `json:"username,omitempty"`
48 Password string `json:"password,omitempty"` // TODO(giolekva): actually use this
49 GandiAPIToken string `json:"gandiAPIToken,omitempty"`
50 SecretToken string `json:"secretToken,omitempty"`
51}
52
Giorgi Lekveishvili6b887be2023-06-22 14:38:19 +040053func getFormValue(v url.Values, name string) (string, error) {
54 items, ok := v[name]
55 if !ok || len(items) != 1 {
56 return "", fmt.Errorf("%s not found", name)
57 }
58 return items[0], nil
59}
60
Giorgi Lekveishvili12850ee2023-06-22 13:11:17 +040061func (s *Server) createAdminAccount(c echo.Context) error {
62 var req createAdminAccountReq
Giorgi Lekveishvili6b887be2023-06-22 14:38:19 +040063 if err := func() error {
64 var err error
65 f, err := c.FormParams()
66 if err != nil {
67 return err
68 }
69 if req.Username, err = getFormValue(f, "username"); err != nil {
70 return err
71 }
72 if req.Password, err = getFormValue(f, "password"); err != nil {
73 return err
74 }
75 if req.GandiAPIToken, err = getFormValue(f, "gandi-api-token"); err != nil {
76 return err
77 }
78 if req.SecretToken, err = getFormValue(f, "secret-token"); err != nil {
79 return err
80 }
81 return nil
82 }(); err != nil {
83 if err := json.NewDecoder(c.Request().Body).Decode(&req); err != nil {
84 return err
85 }
Giorgi Lekveishvili12850ee2023-06-22 13:11:17 +040086 }
87 // TODO(giolekva): accounts-ui create user req
88 {
89 appManager, err := installer.NewAppManager(s.repo)
90 if err != nil {
91 return err
92 }
93 appsRepo := installer.NewInMemoryAppRepository(installer.CreateAllApps())
94 {
95 app, err := appsRepo.Find("certificate-issuer-private")
96 if err != nil {
97 return err
98 }
99 if err := appManager.Install(*app, map[string]any{
100 "GandiAPIToken": req.GandiAPIToken,
101 }); err != nil {
102 return err
103 }
104 }
105 {
106 app, err := appsRepo.Find("tailscale-proxy")
107 if err != nil {
108 return err
109 }
110 if err := appManager.Install(*app, map[string]any{
111 "Username": req.Username,
112 "IPSubnet": "10.1.0.0/24", // TODO(giolekva): this should be taken from the config generated during new env creation
113 }); err != nil {
114 return err
115 }
116 // TODO(giolekva): headscale accept routes
117 }
118 }
119 return c.String(http.StatusOK, "OK")
120}