| package welcome |
| |
| import ( |
| "embed" |
| "encoding/json" |
| "fmt" |
| "log" |
| "net/http" |
| "net/url" |
| |
| "github.com/labstack/echo/v4" |
| |
| "github.com/giolekva/pcloud/core/installer" |
| ) |
| |
| //go:embed create-admin-account.html |
| var indexHtml string |
| |
| //go:embed static/* |
| var staticAssets embed.FS |
| |
| type Server struct { |
| port int |
| repo installer.RepoIO |
| nsCreator installer.NamespaceCreator |
| } |
| |
| func NewServer(port int, repo installer.RepoIO, nsCreator installer.NamespaceCreator) *Server { |
| return &Server{ |
| port, |
| repo, |
| nsCreator, |
| } |
| } |
| |
| func (s *Server) Start() { |
| e := echo.New() |
| e.StaticFS("/static", echo.MustSubFS(staticAssets, "static")) |
| e.POST("/create-admin-account", s.createAdminAccount) |
| e.GET("/", s.createAdminAccountForm) |
| log.Fatal(e.Start(fmt.Sprintf(":%d", s.port))) |
| } |
| |
| func (s *Server) createAdminAccountForm(c echo.Context) error { |
| return c.HTML(http.StatusOK, indexHtml) |
| } |
| |
| type createAdminAccountReq struct { |
| Username string `json:"username,omitempty"` |
| Password string `json:"password,omitempty"` // TODO(giolekva): actually use this |
| GandiAPIToken string `json:"gandiAPIToken,omitempty"` |
| SecretToken string `json:"secretToken,omitempty"` |
| } |
| |
| func getFormValue(v url.Values, name string) (string, error) { |
| items, ok := v[name] |
| if !ok || len(items) != 1 { |
| return "", fmt.Errorf("%s not found", name) |
| } |
| return items[0], nil |
| } |
| |
| func (s *Server) createAdminAccount(c echo.Context) error { |
| var req createAdminAccountReq |
| if err := func() error { |
| var err error |
| f, err := c.FormParams() |
| if err != nil { |
| return err |
| } |
| if req.Username, err = getFormValue(f, "username"); err != nil { |
| return err |
| } |
| if req.Password, err = getFormValue(f, "password"); err != nil { |
| return err |
| } |
| if req.GandiAPIToken, err = getFormValue(f, "gandi-api-token"); err != nil { |
| return err |
| } |
| if req.SecretToken, err = getFormValue(f, "secret-token"); err != nil { |
| return err |
| } |
| return nil |
| }(); err != nil { |
| if err := json.NewDecoder(c.Request().Body).Decode(&req); err != nil { |
| return err |
| } |
| } |
| // TODO(giolekva): accounts-ui create user req |
| { |
| config, err := s.repo.ReadConfig() |
| if err != nil { |
| return err |
| } |
| if err != nil { |
| return err |
| } |
| nsGen := installer.NewPrefixGenerator(config.Values.NamespacePrefix) |
| suffixGen := installer.NewEmptySuffixGenerator() |
| appManager, err := installer.NewAppManager(s.repo, s.nsCreator) |
| if err != nil { |
| return err |
| } |
| appsRepo := installer.NewInMemoryAppRepository(installer.CreateAllApps()) |
| { |
| app, err := appsRepo.Find("certificate-issuer-private") |
| if err != nil { |
| return err |
| } |
| if err := appManager.Install(*app, nsGen, suffixGen, map[string]any{ |
| "GandiAPIToken": req.GandiAPIToken, |
| }); err != nil { |
| return err |
| } |
| } |
| { |
| app, err := appsRepo.Find("tailscale-proxy") |
| if err != nil { |
| return err |
| } |
| if err := appManager.Install(*app, nsGen, suffixGen, map[string]any{ |
| "Username": req.Username, |
| "IPSubnet": "10.1.0.0/24", // TODO(giolekva): this should be taken from the config generated during new env creation |
| }); err != nil { |
| return err |
| } |
| // TODO(giolekva): headscale accept routes |
| } |
| } |
| return c.String(http.StatusOK, "OK") |
| } |