diff options
Diffstat (limited to 'web/handler')
| -rw-r--r-- | web/handler/auth.go | 149 | ||||
| -rw-r--r-- | web/handler/deploy.go | 2 | ||||
| -rw-r--r-- | web/handler/index.go | 4 | ||||
| -rw-r--r-- | web/handler/instance.go | 6 |
4 files changed, 123 insertions, 38 deletions
diff --git a/web/handler/auth.go b/web/handler/auth.go index 38b87b6..29bd47c 100644 --- a/web/handler/auth.go +++ b/web/handler/auth.go @@ -1,81 +1,164 @@ package handler import ( + "errors" "html/template" "log/slog" "net/http" - "strconv" "time" + "git.leonardobishop.net/instancer/pkg/auth" "git.leonardobishop.net/instancer/pkg/session" ) -func GetAuth(tmpl *template.Template) http.HandlerFunc { +func GetAuth(tmpl *template.Template, authProvider *auth.OIDCAuthProvider) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - tmpl.ExecuteTemplate(w, "auth.html", nil) + w.Header().Add("HX-Redirect", "/auth") + tmpl.ExecuteTemplate(w, "auth.html", struct { + Error string + OidcIdPName string + }{ + Error: "", + OidcIdPName: authProvider.Name, + }) } } -func PostAuth(tmpl *template.Template, session *session.MemoryStore) http.HandlerFunc { +func PostAuth(tmpl *template.Template, session *session.MemoryStore, authProvider *auth.OIDCAuthProvider) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - if err := r.ParseForm(); err != nil { - tmpl.ExecuteTemplate(w, "f_auth_error.html", struct { - Message string + url, err := authProvider.StartJourney(r.RemoteAddr, r.UserAgent()) + if err != nil { + slog.Error("oidc start journey failed", "cause", err) + tmpl.ExecuteTemplate(w, "auth.html", struct { + Error string + OidcIdPName string }{ - Message: "Invalid form data", + Error: "Failed to start OIDC journey", + OidcIdPName: authProvider.Name, }) return } - team := r.FormValue("team") - if team == "" { - tmpl.ExecuteTemplate(w, "f_auth_error.html", struct { - Message string - }{ - Message: "No team entered", - }) - return + http.Redirect(w, r, url, http.StatusFound) + } +} + +func GetAuthCallback(tmpl *template.Template, session *session.MemoryStore, authProvider *auth.OIDCAuthProvider) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + type pageParams struct { + Error string + OidcIdPName string } + params := pageParams{OidcIdPName: authProvider.Name} + query := r.URL.Query() - if _, err := strconv.Atoi(team); err != nil { - tmpl.ExecuteTemplate(w, "f_auth_error.html", struct { - Message string - }{ - Message: "Team ID must be number", - }) + s, err := session.Create() + if err != nil { + params.Error = "Failed to create session" + slog.Error("session creation failed", "cause", err) + w.Header().Add("HX-Push-Url", "/auth") + tmpl.ExecuteTemplate(w, "auth.html", params) return } - session, err := session.Create(team) + err = authProvider.CompleteJourney(r.Context(), query.Get("code"), query.Get("state"), r.RemoteAddr, r.UserAgent(), s) + if err != nil { - slog.Error("could not create session", "cause", err) - tmpl.ExecuteTemplate(w, "f_auth_error.html", struct { - Message string - }{ - Message: "Could not create session", - }) + if errors.Is(err, auth.ErrNotAuthorised) { + params.Error = "You are not authorised to use this service" + goto done + } else if errors.Is(err, auth.ErrInvalidState) { + params.Error = "Invalid state" + goto done + } else if errors.Is(err, auth.ErrStateVerificationFailed) { + params.Error = "State verification failed" + goto done + } else if errors.Is(err, auth.ErrInvalidIDToken) { + params.Error = "Invalid ID token" + goto done + } + params.Error = "Failed to complete OIDC journey" + slog.Error("oidc complete journey failed", "cause", err) + done: + w.Header().Add("HX-Push-Url", "/auth") + tmpl.ExecuteTemplate(w, "auth.html", params) + session.Destroy(s.Token) return } http.SetCookie(w, &http.Cookie{ - Name: "session", - Value: session.Token, + Name: "instancer-session", + Value: s.Token, Path: "/", Secure: true, SameSite: http.SameSiteStrictMode, HttpOnly: true, }) - w.Header().Add("HX-Redirect", "/") + http.Redirect(w, r, "/", http.StatusFound) } } +//func PostAuth(tmpl *template.Template, session *session.MemoryStore) http.HandlerFunc { +// return func(w http.ResponseWriter, r *http.Request) { +// if err := r.ParseForm(); err != nil { +// tmpl.ExecuteTemplate(w, "f_auth_error.html", struct { +// Message string +// }{ +// Message: "Invalid form data", +// }) +// return +// } +// +// team := r.FormValue("team") +// if team == "" { +// tmpl.ExecuteTemplate(w, "f_auth_error.html", struct { +// Message string +// }{ +// Message: "No team entered", +// }) +// return +// } +// +// if _, err := strconv.Atoi(team); err != nil { +// tmpl.ExecuteTemplate(w, "f_auth_error.html", struct { +// Message string +// }{ +// Message: "Team ID must be number", +// }) +// return +// } +// +// session, err := session.Create(team) +// if err != nil { +// slog.Error("could not create session", "cause", err) +// tmpl.ExecuteTemplate(w, "f_auth_error.html", struct { +// Message string +// }{ +// Message: "Could not create session", +// }) +// return +// } +// +// http.SetCookie(w, &http.Cookie{ +// Name: "session", +// Value: session.Token, +// +// Path: "/", +// Secure: true, +// SameSite: http.SameSiteStrictMode, +// HttpOnly: true, +// }) +// w.Header().Add("HX-Redirect", "/") +// } +//} + func GetLogout(session *session.MemoryStore) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { //TODO expire session here http.SetCookie(w, &http.Cookie{ - Name: "session", + Name: "instancer-session", Value: "", Expires: time.Unix(0, 0), diff --git a/web/handler/deploy.go b/web/handler/deploy.go index 24e0f95..f0c40fc 100644 --- a/web/handler/deploy.go +++ b/web/handler/deploy.go @@ -24,7 +24,7 @@ func PostDeploy(tmpl *template.Template, dockerDeployer *deployer.DockerDeployer } session := r.Context().Value("session").(*session.UserSession) - deployKey := dockerDeployer.StartDeploy(challenge, session.Team) + deployKey := dockerDeployer.StartDeploy(challenge, session.TeamID) tmpl.ExecuteTemplate(w, "f_deploy.html", struct { DeployKey string diff --git a/web/handler/index.go b/web/handler/index.go index 5cf44cf..9279151 100644 --- a/web/handler/index.go +++ b/web/handler/index.go @@ -22,10 +22,12 @@ func GetIndex(tmpl *template.Template, registryClient *registry.RegistryClient) if err := tmpl.ExecuteTemplate(w, "index.html", struct { Challenges []string + Name string Team string }{ Challenges: challenges, - Team: session.Team, + Name: session.Name, + Team: session.TeamName, }); err != nil { http.Error(w, "Internal server error", http.StatusInternalServerError) return diff --git a/web/handler/instance.go b/web/handler/instance.go index 0222a42..e5e4c53 100644 --- a/web/handler/instance.go +++ b/web/handler/instance.go @@ -15,9 +15,9 @@ func GetInstances(tmpl *template.Template, dockerDeployer *deployer.DockerDeploy return func(w http.ResponseWriter, r *http.Request) { session := r.Context().Value("session").(*session.UserSession) - instances, err := dockerDeployer.GetTeamInstances(r.Context(), session.Team) + instances, err := dockerDeployer.GetTeamInstances(r.Context(), session.TeamID) if err != nil { - slog.Error("could not get team instances", "team", session.Team, "error", err) + slog.Error("could not get team instances", "team", session.TeamID, "error", err) http.Error(w, "Internal server error", http.StatusInternalServerError) return } @@ -70,7 +70,7 @@ func PostStopInstance(tmpl *template.Template, dockerDeployer *deployer.DockerDe session := r.Context().Value("session").(*session.UserSession) deployKey := r.PathValue("deployKey") - err := dockerDeployer.StopInstance(r.Context(), deployKey, session.Team) + err := dockerDeployer.StopInstance(r.Context(), deployKey, session.TeamID) if err != nil { tmpl.ExecuteTemplate(w, "f_instance_result.html", struct { State string |
