func PatchUser(c *gin.Context) { me := session.User(c) in := &model.User{} err := c.Bind(in) if err != nil { c.AbortWithStatus(http.StatusBadRequest) return } user, err := store.GetUserLogin(c, c.Param("login")) if err != nil { c.AbortWithStatus(http.StatusNotFound) return } user.Admin = in.Admin user.Active = in.Active // cannot update self if me.ID == user.ID { c.AbortWithStatus(http.StatusForbidden) return } err = store.UpdateUser(c, user) if err != nil { c.AbortWithStatus(http.StatusConflict) return } c.IndentedJSON(http.StatusOK, user) }
func GetLoginToken(c *gin.Context) { remote := remote.FromContext(c) in := &tokenPayload{} err := c.Bind(in) if err != nil { c.AbortWithError(http.StatusBadRequest, err) return } login, err := remote.Auth(in.Access, in.Refresh) if err != nil { c.AbortWithError(http.StatusUnauthorized, err) return } user, err := store.GetUserLogin(c, login) if err != nil { c.AbortWithError(http.StatusNotFound, err) return } exp := time.Now().Add(time.Hour * 72).Unix() token := token.New(token.SessToken, user.Login) tokenstr, err := token.SignExpires(user.Hash, exp) if err != nil { c.AbortWithError(http.StatusInternalServerError, err) return } c.IndentedJSON(http.StatusOK, &tokenPayload{ Access: tokenstr, Expires: exp - time.Now().Unix(), }) }
func SetUser() gin.HandlerFunc { return func(c *gin.Context) { var user *model.User t, err := token.ParseRequest(c.Request, func(t *token.Token) (string, error) { var err error user, err = store.GetUserLogin(c, t.Text) return user.Hash, err }) if err == nil { c.Set("user", user) // if this is a session token (ie not the API token) // this means the user is accessing with a web browser, // so we should implement CSRF protection measures. if t.Kind == token.SessToken { err = token.CheckCsrf(c.Request, func(t *token.Token) (string, error) { return user.Hash, nil }) // if csrf token validation fails, exit immediately // with a not authorized error. if err != nil { c.AbortWithStatus(http.StatusUnauthorized) return } } } c.Next() } }
func GetUser(c *gin.Context) { user, err := store.GetUserLogin(c, c.Param("login")) if err != nil { c.AbortWithStatus(http.StatusNotFound) return } token := token.New(token.UserToken, user.Login) tokenstr, err := token.Sign(user.Hash) if err != nil { tokenstr = "" } userWithToken := struct { *model.User Token string `json:"token,omitempty"` }{user, tokenstr} c.IndentedJSON(http.StatusOK, userWithToken) }
func DeleteUser(c *gin.Context) { me := session.User(c) user, err := store.GetUserLogin(c, c.Param("login")) if err != nil { c.AbortWithStatus(http.StatusNotFound) return } // cannot delete self if me.ID == user.ID { c.AbortWithStatus(http.StatusForbidden) return } err = store.DeleteUser(c, user) if err != nil { c.AbortWithStatus(http.StatusInternalServerError) return } c.Writer.WriteHeader(http.StatusNoContent) }
func GetLogin(c *gin.Context) { remote := remote.FromContext(c) // when dealing with redirects we may need // to adjust the content type. I cannot, however, // rememver why, so need to revisit this line. c.Writer.Header().Del("Content-Type") tmpuser, open, err := remote.Login(c.Writer, c.Request) if err != nil { log.Errorf("cannot authenticate user. %s", err) c.Redirect(303, "/login?error=oauth_error") return } // this will happen when the user is redirected by // the remote provide as part of the oauth dance. if tmpuser == nil { return } // get the user from the database u, err := store.GetUserLogin(c, tmpuser.Login) if err != nil { count, err := store.CountUsers(c) if err != nil { log.Errorf("cannot register %s. %s", tmpuser.Login, err) c.Redirect(303, "/login?error=internal_error") return } // if self-registration is disabled we should // return a notAuthorized error. the only exception // is if no users exist yet in the system we'll proceed. if !open && count != 0 { log.Errorf("cannot register %s. registration closed", tmpuser.Login) c.Redirect(303, "/login?error=access_denied") return } // create the user account u = &model.User{} u.Login = tmpuser.Login u.Token = tmpuser.Token u.Secret = tmpuser.Secret u.Email = tmpuser.Email u.Avatar = tmpuser.Avatar u.Hash = crypto.Rand() // insert the user into the database if err := store.CreateUser(c, u); err != nil { log.Errorf("cannot insert %s. %s", u.Login, err) c.Redirect(303, "/login?error=internal_error") return } // if this is the first user, they // should be an admin. if count == 0 { u.Admin = true } } // update the user meta data and authorization // data and cache in the datastore. u.Token = tmpuser.Token u.Secret = tmpuser.Secret u.Email = tmpuser.Email u.Avatar = tmpuser.Avatar if err := store.UpdateUser(c, u); err != nil { log.Errorf("cannot update %s. %s", u.Login, err) c.Redirect(303, "/login?error=internal_error") return } exp := time.Now().Add(time.Hour * 72).Unix() token := token.New(token.SessToken, u.Login) tokenstr, err := token.SignExpires(u.Hash, exp) if err != nil { log.Errorf("cannot create token for %s. %s", u.Login, err) c.Redirect(303, "/login?error=internal_error") return } httputil.SetCookie(c.Writer, c.Request, "user_sess", tokenstr) redirect := httputil.GetCookie(c.Request, "user_last") if len(redirect) == 0 { redirect = "/" } c.Redirect(303, redirect) }