func ContextualizeRecordChangesGET(ctx context.Context, db data.DB, logger services.Logger) websocket.Handler { return func(ws *websocket.Conn) { defer ws.Close() l := logger.WithPrefix("ContextualizeRecordChangesGET: ") if err := ws.Request().ParseForm(); err != nil { l.Printf("error parsing form: %s", err) return } public := ws.Request().Form.Get(publicParam) private := ws.Request().Form.Get(privateParam) if public == "" || private == "" { l.Print("failed to retrieve credentials") return } cred, err := access.Authenticate(db, public, private) if err != nil { l.Print("failed to authenticate") return } if u, err := cred.Owner(db); err != nil { l.Print("error retrieving user: %s", err) } else { RecordChangesGET(user.NewContext(ctx, u), ws, db, logger) } } }
func ContextualizeCommandWebGET(ctx context.Context, db data.DB, logger services.Logger) websocket.Handler { return func(c *websocket.Conn) { if err := c.Request().ParseForm(); err != nil { logger.Print("Failure parsing form") return } public := c.Request().Form.Get("public") private := c.Request().Form.Get("private") if public == "" || private == "" { logger.Print("failed to retrieve credentials") return } cred, err := access.Authenticate(db, public, private) if err != nil { logger.Print("failed to auth") return } u, _ := cred.Owner(db) CommandWebGET(user.NewContext(ctx, u), c, logger, db) } }
// Authenticate checks a request's basic authentication, and associates a *models.User with the context // if so. Otherwise it handles responding to and closing the request. // // contextWithUser, authWasSuccessful := routes.Authenticate(ctx, w, r, logger, db) // // Use for any requests which expect to act on behalf of a user (which is most) func Authenticate(ctx context.Context, w http.ResponseWriter, r *http.Request, l services.Logger, db services.DB) (context.Context, bool) { l = l.WithPrefix("routes.Authenticate: ") var ( c *models.Credential u *models.User err error ) public, private, ok := r.BasicAuth() if !ok { l.Printf("authentication reverting from basic auth to session") // assume std lib didn't make a mistake, and the BasicAuth simply wasn't given // fall back to cookie if sesh, err := session(r, db); err != nil { switch err { case http.ErrNoCookie: l.Printf("no session cookie") case data.ErrNotFound: l.Printf("session token not found") default: l.Printf("session(r, db) error: %s", err) } l.Printf("authentication reverting from cookie to form values") public, private = r.FormValue(publicParam), r.FormValue(privateParam) } else if sesh.Valid() { if u, err := sesh.Owner(db); err != nil { l.Printf("sesh.Owner(db) error: %s", err) public, private = r.FormValue(publicParam), r.FormValue(privateParam) } else { return user.NewContext(ctx, u), true } } else { l.Printf("session no longer valid") public, private = r.FormValue(publicParam), r.FormValue(privateParam) } } if c, err = access.Authenticate(db, public, private); err != nil { l.Printf("authentication of (%s, %s) failed: couldn't find credential: %s", public, private, err) goto unauthorized // this error is on us, but it manifests as a failure to authenticate } if u, err = c.Owner(db); err != nil { l.Printf("authentication failed: couldn't load user's owner: %s", err) goto unauthorized // this error is also on us, but also manifests as a failure to authenticate } // successful authentications return user.NewContext(ctx, u), true // rejection unauthorized: http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) return nil, false }