Skip to content

Commit

Permalink
some updates for more flexibile routing and server shutdown for cloud
Browse files Browse the repository at this point in the history
  • Loading branch information
danenania committed Sep 27, 2024
1 parent 0e791cd commit 2012dfe
Show file tree
Hide file tree
Showing 8 changed files with 181 additions and 94 deletions.
5 changes: 5 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
dist-server/
cli/
node_modules/
plandex-server
plandex-cloud
2 changes: 2 additions & 0 deletions app/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
cli/
plandex-server
38 changes: 35 additions & 3 deletions app/server/handlers/auth_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"plandex-server/hooks"
"plandex-server/types"
"strings"
"time"

"github.com/plandex/plandex/shared"
)
Expand Down Expand Up @@ -90,6 +91,11 @@ func ClearAuthCookieIfBrowser(w http.ResponseWriter, r *http.Request) error {
return fmt.Errorf("error retrieving auth cookie: %v", err)
}

var domain string
if os.Getenv("GOENV") == "production" {
domain = os.Getenv("APP_SUBDOMAIN") + ".plandex.ai"
}

// Clear the authToken cookie
http.SetCookie(w, &http.Cookie{
Name: "authToken",
Expand All @@ -99,8 +105,11 @@ func ClearAuthCookieIfBrowser(w http.ResponseWriter, r *http.Request) error {
Secure: os.Getenv("GOENV") != "development",
HttpOnly: true,
SameSite: http.SameSiteLaxMode,
Domain: domain,
})

log.Println("cleared auth cookie")

return nil
}

Expand Down Expand Up @@ -129,13 +138,18 @@ func ClearAccountFromCookies(w http.ResponseWriter, r *http.Request, userId stri
encodedAccounts := base64.URLEncoding.EncodeToString(updatedAccountsBytes)

// Set the updated accounts cookie
var domain string
if os.Getenv("GOENV") == "production" {
domain = os.Getenv("APP_SUBDOMAIN") + ".plandex.ai"
}
http.SetCookie(w, &http.Cookie{
Name: "accounts",
Path: "/",
Value: encodedAccounts,
Secure: os.Getenv("GOENV") != "development",
HttpOnly: true,
SameSite: http.SameSiteLaxMode,
Domain: domain,
})

return nil
Expand Down Expand Up @@ -180,14 +194,25 @@ func SetAuthCookieIfBrowser(w http.ResponseWriter, r *http.Request, user *db.Use
// base64 encode
token = base64.URLEncoding.EncodeToString(bytes)

http.SetCookie(w, &http.Cookie{
var domain string
if os.Getenv("GOENV") == "production" {
domain = os.Getenv("APP_SUBDOMAIN") + ".plandex.ai"
}

cookie := &http.Cookie{
Name: "authToken",
Path: "/",
Value: "Bearer " + token,
Secure: os.Getenv("GOENV") != "development",
HttpOnly: true,
SameSite: http.SameSiteLaxMode,
})
Domain: domain,
Expires: time.Now().Add(time.Hour * 24 * 90),
}

log.Println("setting auth cookie", cookie)

http.SetCookie(w, cookie)

storedAccounts, err := GetAccountsFromCookie(r)

Expand Down Expand Up @@ -232,6 +257,8 @@ func SetAuthCookieIfBrowser(w http.ResponseWriter, r *http.Request, user *db.Use
Secure: os.Getenv("GOENV") != "development",
HttpOnly: true,
SameSite: http.SameSiteLaxMode,
Domain: domain,
Expires: time.Now().Add(time.Hour * 24 * 90),
})

return nil
Expand Down Expand Up @@ -309,6 +336,8 @@ func ValidateAndSignIn(w http.ResponseWriter, r *http.Request, req shared.SignIn
log.Printf("Error validating email verification: %v\n", err)
return nil, fmt.Errorf("error validating email verification: %v", err)
}

log.Println("Email verification successful")
}

// start a transaction
Expand Down Expand Up @@ -347,12 +376,14 @@ func ValidateAndSignIn(w http.ResponseWriter, r *http.Request, req shared.SignIn
}
} else {
// update email verification with user and auth token ids
_, err = tx.Exec("UPDATE email verifications SET user_id = $1, auth_token_id = $2 WHERE id = $3", user.Id, authTokenId, emailVerificationId)
_, err = tx.Exec("UPDATE email_verifications SET user_id = $1, auth_token_id = $2 WHERE id = $3", user.Id, authTokenId, emailVerificationId)

if err != nil {
log.Printf("Error updating email verification: %v\n", err)
return nil, fmt.Errorf("error updating email verification: %v", err)
}

log.Println("Email verification updated")
}

// commit transaction
Expand Down Expand Up @@ -387,6 +418,7 @@ func ValidateAndSignIn(w http.ResponseWriter, r *http.Request, req shared.SignIn
orgId = orgs[0].Id
}

log.Println("Setting auth cookie if browser")
err = SetAuthCookieIfBrowser(w, r, user, token, orgId)
if err != nil {
log.Printf("Error setting auth cookie: %v\n", err)
Expand Down
1 change: 1 addition & 0 deletions app/server/handlers/sessions.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ func SignInHandler(w http.ResponseWriter, r *http.Request) {
return
}

log.Println("Validating and signing in")
resp, err := ValidateAndSignIn(w, r, req)

if err != nil {
Expand Down
3 changes: 3 additions & 0 deletions app/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"log"
"plandex-server/routes"
"plandex-server/setup"

"github.com/gorilla/mux"
Expand All @@ -12,6 +13,8 @@ func main() {
log.SetFlags(log.LstdFlags | log.Lmicroseconds)

r := mux.NewRouter()
routes.AddHealthRoutes(r)
routes.AddApiRoutes(r)

setup.MustLoadIp()
setup.MustInitDb()
Expand Down
156 changes: 87 additions & 69 deletions app/server/routes/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,37 @@ import (
"log"
"net/http"
"os"
"path/filepath"
"plandex-server/handlers"
"plandex-server/hooks"

"github.com/gorilla/mux"
)

func AddApiRoutes(r *mux.Router) {
func AddHealthRoutes(r *mux.Router) {
r.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {

_, apiErr := hooks.ExecHook(hooks.HealthCheck, hooks.HookParams{})

if apiErr != nil {
log.Printf("Error in health check hook: %v\n", apiErr)
http.Error(w, apiErr.Msg, apiErr.Status)
return
}

fmt.Fprint(w, "OK")
})

r.HandleFunc("/version", func(w http.ResponseWriter, r *http.Request) {
// Log the host
host := r.Host
log.Printf("Host header: %s", host)

execPath, err := os.Executable()
if err != nil {
log.Fatal("Error getting current directory: ", err)
}
currentDir := filepath.Dir(execPath)

// get version from version.txt
bytes, err := os.ReadFile("version.txt")
bytes, err := os.ReadFile(filepath.Join(currentDir, "..", "version.txt"))

if err != nil {
http.Error(w, "Error getting version", http.StatusInternalServerError)
Expand All @@ -36,91 +44,101 @@ func AddApiRoutes(r *mux.Router) {

fmt.Fprint(w, string(bytes))
})
}

func AddApiRoutes(r *mux.Router) {
addApiRoutes(r, "")
}

func AddApiRoutesWithPrefix(r *mux.Router, prefix string) {
addApiRoutes(r, prefix)
}

r.HandleFunc("/accounts/email_verifications", handlers.CreateEmailVerificationHandler).Methods("POST")
r.HandleFunc("/accounts/email_verifications/check_pin", handlers.CheckEmailPinHandler).Methods("POST")
r.HandleFunc("/accounts/sign_in_codes", handlers.CreateSignInCodeHandler).Methods("POST")
r.HandleFunc("/accounts/sign_in", handlers.SignInHandler).Methods("POST")
r.HandleFunc("/accounts/sign_out", handlers.SignOutHandler).Methods("POST")
r.HandleFunc("/accounts", handlers.CreateAccountHandler).Methods("POST")
func addApiRoutes(r *mux.Router, prefix string) {
r.HandleFunc(prefix+"/accounts/email_verifications", handlers.CreateEmailVerificationHandler).Methods("POST")
r.HandleFunc(prefix+"/accounts/email_verifications/check_pin", handlers.CheckEmailPinHandler).Methods("POST")
r.HandleFunc(prefix+"/accounts/sign_in_codes", handlers.CreateSignInCodeHandler).Methods("POST")
r.HandleFunc(prefix+"/accounts/sign_in", handlers.SignInHandler).Methods("POST")
r.HandleFunc(prefix+"/accounts/sign_out", handlers.SignOutHandler).Methods("POST")
r.HandleFunc(prefix+"/accounts", handlers.CreateAccountHandler).Methods("POST")

r.HandleFunc("/orgs/session", handlers.GetOrgSessionHandler).Methods("GET")
r.HandleFunc("/orgs", handlers.ListOrgsHandler).Methods("GET")
r.HandleFunc("/orgs", handlers.CreateOrgHandler).Methods("POST")
r.HandleFunc(prefix+"/orgs/session", handlers.GetOrgSessionHandler).Methods("GET")
r.HandleFunc(prefix+"/orgs", handlers.ListOrgsHandler).Methods("GET")
r.HandleFunc(prefix+"/orgs", handlers.CreateOrgHandler).Methods("POST")

r.HandleFunc("/users", handlers.ListUsersHandler).Methods("GET")
r.HandleFunc("/orgs/users/{userId}", handlers.DeleteOrgUserHandler).Methods("DELETE")
r.HandleFunc("/orgs/roles", handlers.ListOrgRolesHandler).Methods("GET")
r.HandleFunc(prefix+"/users", handlers.ListUsersHandler).Methods("GET")
r.HandleFunc(prefix+"/orgs/users/{userId}", handlers.DeleteOrgUserHandler).Methods("DELETE")
r.HandleFunc(prefix+"/orgs/roles", handlers.ListOrgRolesHandler).Methods("GET")

r.HandleFunc("/invites", handlers.InviteUserHandler).Methods("POST")
r.HandleFunc("/invites/pending", handlers.ListPendingInvitesHandler).Methods("GET")
r.HandleFunc("/invites/accepted", handlers.ListAcceptedInvitesHandler).Methods("GET")
r.HandleFunc("/invites/all", handlers.ListAllInvitesHandler).Methods("GET")
r.HandleFunc("/invites/{inviteId}", handlers.DeleteInviteHandler).Methods("DELETE")
r.HandleFunc(prefix+"/invites", handlers.InviteUserHandler).Methods("POST")
r.HandleFunc(prefix+"/invites/pending", handlers.ListPendingInvitesHandler).Methods("GET")
r.HandleFunc(prefix+"/invites/accepted", handlers.ListAcceptedInvitesHandler).Methods("GET")
r.HandleFunc(prefix+"/invites/all", handlers.ListAllInvitesHandler).Methods("GET")
r.HandleFunc(prefix+"/invites/{inviteId}", handlers.DeleteInviteHandler).Methods("DELETE")

r.HandleFunc("/projects", handlers.CreateProjectHandler).Methods("POST")
r.HandleFunc("/projects", handlers.ListProjectsHandler).Methods("GET")
r.HandleFunc("/projects/{projectId}/set_plan", handlers.ProjectSetPlanHandler).Methods("PUT")
r.HandleFunc("/projects/{projectId}/rename", handlers.RenameProjectHandler).Methods("PUT")
r.HandleFunc(prefix+"/projects", handlers.CreateProjectHandler).Methods("POST")
r.HandleFunc(prefix+"/projects", handlers.ListProjectsHandler).Methods("GET")
r.HandleFunc(prefix+"/projects/{projectId}/set_plan", handlers.ProjectSetPlanHandler).Methods("PUT")
r.HandleFunc(prefix+"/projects/{projectId}/rename", handlers.RenameProjectHandler).Methods("PUT")

r.HandleFunc("/projects/{projectId}/plans/current_branches", handlers.GetCurrentBranchByPlanIdHandler).Methods("POST")
r.HandleFunc(prefix+"/projects/{projectId}/plans/current_branches", handlers.GetCurrentBranchByPlanIdHandler).Methods("POST")

r.HandleFunc("/plans", handlers.ListPlansHandler).Methods("GET")
r.HandleFunc("/plans/archive", handlers.ListArchivedPlansHandler).Methods("GET")
r.HandleFunc("/plans/ps", handlers.ListPlansRunningHandler).Methods("GET")
r.HandleFunc(prefix+"/plans", handlers.ListPlansHandler).Methods("GET")
r.HandleFunc(prefix+"/plans/archive", handlers.ListArchivedPlansHandler).Methods("GET")
r.HandleFunc(prefix+"/plans/ps", handlers.ListPlansRunningHandler).Methods("GET")

r.HandleFunc("/projects/{projectId}/plans", handlers.CreatePlanHandler).Methods("POST")
r.HandleFunc(prefix+"/projects/{projectId}/plans", handlers.CreatePlanHandler).Methods("POST")

r.HandleFunc("/projects/{projectId}/plans", handlers.CreatePlanHandler).Methods("DELETE")
r.HandleFunc(prefix+"/projects/{projectId}/plans", handlers.CreatePlanHandler).Methods("DELETE")

r.HandleFunc("/plans/{planId}", handlers.GetPlanHandler).Methods("GET")
r.HandleFunc("/plans/{planId}", handlers.DeletePlanHandler).Methods("DELETE")
r.HandleFunc(prefix+"/plans/{planId}", handlers.GetPlanHandler).Methods("GET")
r.HandleFunc(prefix+"/plans/{planId}", handlers.DeletePlanHandler).Methods("DELETE")

r.HandleFunc("/plans/{planId}/{branch}/tell", handlers.TellPlanHandler).Methods("POST")
r.HandleFunc(prefix+"/plans/{planId}/{branch}/tell", handlers.TellPlanHandler).Methods("POST")

r.HandleFunc("/plans/{planId}/{branch}/respond_missing_file", handlers.RespondMissingFileHandler).Methods("POST")
r.HandleFunc(prefix+"/plans/{planId}/{branch}/respond_missing_file", handlers.RespondMissingFileHandler).Methods("POST")

r.HandleFunc("/plans/{planId}/{branch}/build", handlers.BuildPlanHandler).Methods("PATCH")
r.HandleFunc("/plans/{planId}/{branch}/connect", handlers.ConnectPlanHandler).Methods("PATCH")
r.HandleFunc("/plans/{planId}/{branch}/stop", handlers.StopPlanHandler).Methods("DELETE")
r.HandleFunc(prefix+"/plans/{planId}/{branch}/build", handlers.BuildPlanHandler).Methods("PATCH")
r.HandleFunc(prefix+"/plans/{planId}/{branch}/connect", handlers.ConnectPlanHandler).Methods("PATCH")
r.HandleFunc(prefix+"/plans/{planId}/{branch}/stop", handlers.StopPlanHandler).Methods("DELETE")

r.HandleFunc("/plans/{planId}/{branch}/current_plan", handlers.CurrentPlanHandler).Methods("GET")
r.HandleFunc("/plans/{planId}/{branch}/apply", handlers.ApplyPlanHandler).Methods("PATCH")
r.HandleFunc("/plans/{planId}/archive", handlers.ArchivePlanHandler).Methods("PATCH")
r.HandleFunc("/plans/{planId}/unarchive", handlers.UnarchivePlanHandler).Methods("PATCH")
r.HandleFunc(prefix+"/plans/{planId}/{branch}/current_plan", handlers.CurrentPlanHandler).Methods("GET")
r.HandleFunc(prefix+"/plans/{planId}/{branch}/apply", handlers.ApplyPlanHandler).Methods("PATCH")
r.HandleFunc(prefix+"/plans/{planId}/archive", handlers.ArchivePlanHandler).Methods("PATCH")
r.HandleFunc(prefix+"/plans/{planId}/unarchive", handlers.UnarchivePlanHandler).Methods("PATCH")

r.HandleFunc("/plans/{planId}/rename", handlers.RenamePlanHandler).Methods("PATCH")
r.HandleFunc("/plans/{planId}/{branch}/reject_all", handlers.RejectAllChangesHandler).Methods("PATCH")
r.HandleFunc("/plans/{planId}/{branch}/reject_file", handlers.RejectFileHandler).Methods("PATCH")
r.HandleFunc("/plans/{planId}/{branch}/reject_files", handlers.RejectFilesHandler).Methods("PATCH")
r.HandleFunc("/plans/{planId}/{branch}/diffs", handlers.GetPlanDiffsHandler).Methods("GET")
r.HandleFunc(prefix+"/plans/{planId}/rename", handlers.RenamePlanHandler).Methods("PATCH")
r.HandleFunc(prefix+"/plans/{planId}/{branch}/reject_all", handlers.RejectAllChangesHandler).Methods("PATCH")
r.HandleFunc(prefix+"/plans/{planId}/{branch}/reject_file", handlers.RejectFileHandler).Methods("PATCH")
r.HandleFunc(prefix+"/plans/{planId}/{branch}/reject_files", handlers.RejectFilesHandler).Methods("PATCH")
r.HandleFunc(prefix+"/plans/{planId}/{branch}/diffs", handlers.GetPlanDiffsHandler).Methods("GET")

r.HandleFunc("/plans/{planId}/{branch}/context", handlers.ListContextHandler).Methods("GET")
r.HandleFunc("/plans/{planId}/{branch}/context", handlers.LoadContextHandler).Methods("POST")
r.HandleFunc("/plans/{planId}/{branch}/context", handlers.UpdateContextHandler).Methods("PUT")
r.HandleFunc("/plans/{planId}/{branch}/context", handlers.DeleteContextHandler).Methods("DELETE")
r.HandleFunc(prefix+"/plans/{planId}/{branch}/context", handlers.ListContextHandler).Methods("GET")
r.HandleFunc(prefix+"/plans/{planId}/{branch}/context", handlers.LoadContextHandler).Methods("POST")
r.HandleFunc(prefix+"/plans/{planId}/{branch}/context", handlers.UpdateContextHandler).Methods("PUT")
r.HandleFunc(prefix+"/plans/{planId}/{branch}/context", handlers.DeleteContextHandler).Methods("DELETE")

r.HandleFunc("/plans/{planId}/{branch}/convo", handlers.ListConvoHandler).Methods("GET")
r.HandleFunc("/plans/{planId}/{branch}/rewind", handlers.RewindPlanHandler).Methods("PATCH")
r.HandleFunc("/plans/{planId}/{branch}/logs", handlers.ListLogsHandler).Methods("GET")
r.HandleFunc(prefix+"/plans/{planId}/{branch}/convo", handlers.ListConvoHandler).Methods("GET")
r.HandleFunc(prefix+"/plans/{planId}/{branch}/rewind", handlers.RewindPlanHandler).Methods("PATCH")
r.HandleFunc(prefix+"/plans/{planId}/{branch}/logs", handlers.ListLogsHandler).Methods("GET")

r.HandleFunc("/plans/{planId}/branches", handlers.ListBranchesHandler).Methods("GET")
r.HandleFunc("/plans/{planId}/branches/{branch}", handlers.DeleteBranchHandler).Methods("DELETE")
r.HandleFunc("/plans/{planId}/{branch}/branches", handlers.CreateBranchHandler).Methods("POST")
r.HandleFunc(prefix+"/plans/{planId}/branches", handlers.ListBranchesHandler).Methods("GET")
r.HandleFunc(prefix+"/plans/{planId}/branches/{branch}", handlers.DeleteBranchHandler).Methods("DELETE")
r.HandleFunc(prefix+"/plans/{planId}/{branch}/branches", handlers.CreateBranchHandler).Methods("POST")

r.HandleFunc("/plans/{planId}/{branch}/settings", handlers.GetSettingsHandler).Methods("GET")
r.HandleFunc("/plans/{planId}/{branch}/settings", handlers.UpdateSettingsHandler).Methods("PUT")
r.HandleFunc(prefix+"/plans/{planId}/{branch}/settings", handlers.GetSettingsHandler).Methods("GET")
r.HandleFunc(prefix+"/plans/{planId}/{branch}/settings", handlers.UpdateSettingsHandler).Methods("PUT")

r.HandleFunc("/plans/{planId}/{branch}/status", handlers.GetPlanStatusHandler).Methods("GET")
r.HandleFunc(prefix+"/plans/{planId}/{branch}/status", handlers.GetPlanStatusHandler).Methods("GET")

r.HandleFunc("/custom_models", handlers.ListCustomModelsHandler).Methods("GET")
r.HandleFunc("/custom_models", handlers.CreateCustomModelHandler).Methods("POST")
r.HandleFunc("/custom_models/{modelId}", handlers.DeleteAvailableModelHandler).Methods("DELETE")
r.HandleFunc(prefix+"/custom_models", handlers.ListCustomModelsHandler).Methods("GET")
r.HandleFunc(prefix+"/custom_models", handlers.CreateCustomModelHandler).Methods("POST")
r.HandleFunc(prefix+"/custom_models/{modelId}", handlers.DeleteAvailableModelHandler).Methods("DELETE")

r.HandleFunc("/model_sets", handlers.ListModelPacksHandler).Methods("GET")
r.HandleFunc("/model_sets", handlers.CreateModelPackHandler).Methods("POST")
r.HandleFunc("/model_sets/{setId}", handlers.DeleteModelPackHandler).Methods("DELETE")
r.HandleFunc(prefix+"/model_sets", handlers.ListModelPacksHandler).Methods("GET")
r.HandleFunc(prefix+"/model_sets", handlers.CreateModelPackHandler).Methods("POST")
r.HandleFunc(prefix+"/model_sets/{setId}", handlers.DeleteModelPackHandler).Methods("DELETE")

r.HandleFunc("/default_settings", handlers.GetDefaultSettingsHandler).Methods("GET")
r.HandleFunc("/default_settings", handlers.UpdateDefaultSettingsHandler).Methods("PUT")
r.HandleFunc(prefix+"/default_settings", handlers.GetDefaultSettingsHandler).Methods("GET")
r.HandleFunc(prefix+"/default_settings", handlers.UpdateDefaultSettingsHandler).Methods("PUT")
}
Loading

0 comments on commit 2012dfe

Please sign in to comment.