mirror of
https://codeberg.org/shroff/phylum.git
synced 2026-01-07 04:00:17 -06:00
[server][api][auth] Split out functions into various files
This commit is contained in:
49
server/internal/api/v1/auth/oauth.go
Normal file
49
server/internal/api/v1/auth/oauth.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"codeberg.org/shroff/phylum/server/internal/auth"
|
||||
"codeberg.org/shroff/phylum/server/internal/db"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func handleOAuthStart(c *gin.Context) {
|
||||
provider := c.Query("provider")
|
||||
clientType := auth.OpenIDClientWeb
|
||||
if c.Query("client_type") == "native" {
|
||||
clientType = auth.OpenIDClientNative
|
||||
}
|
||||
db := db.Get(c.Request.Context())
|
||||
if authURL, err := auth.OpenIDStart(db, provider, getInstanceURL(c.Request, "/api/v1/auth/oauth/redirect"), clientType); err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
c.Redirect(http.StatusFound, authURL)
|
||||
}
|
||||
}
|
||||
|
||||
func handleOAuthRedirect(c *gin.Context) {
|
||||
db := db.Get(c.Request.Context())
|
||||
|
||||
authCode := c.Query("code")
|
||||
state := c.Query("state")
|
||||
|
||||
if clientType, err := auth.OpenIDValidateAuthCode(db, state, authCode, getInstanceURL(c.Request, "/api/v1/auth/oauth/redirect")); err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
var clientURI url.URL
|
||||
if clientType == auth.OpenIDClientWeb {
|
||||
clientURI = *c.Request.URL
|
||||
clientURI.RawQuery = ""
|
||||
} else {
|
||||
clientURI = url.URL{Scheme: "cloud.phylum.drive"}
|
||||
}
|
||||
clientURI.Path = "/login/token"
|
||||
q := url.Values{}
|
||||
q.Add("token", state)
|
||||
q.Add("instance", getInstanceURL(c.Request, ""))
|
||||
clientURI.RawQuery = q.Encode()
|
||||
c.Redirect(http.StatusFound, clientURI.String())
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"codeberg.org/shroff/phylum/server/internal/auth"
|
||||
"codeberg.org/shroff/phylum/server/internal/core"
|
||||
"codeberg.org/shroff/phylum/server/internal/db"
|
||||
"codeberg.org/shroff/phylum/server/internal/mail"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
@@ -16,7 +17,19 @@ type passwordUpdateParams struct {
|
||||
NewPassword string `json:"new_password" form:"new_password"`
|
||||
}
|
||||
|
||||
func handlePasswordChangeRoute(c *gin.Context) {
|
||||
func handlePasswordLogin(c *gin.Context) {
|
||||
var params passwordParams
|
||||
err := c.ShouldBind(¶ms)
|
||||
if err != nil {
|
||||
panic(core.NewError(http.StatusBadRequest, "missing_params", "Email or password not specified"))
|
||||
}
|
||||
|
||||
loginAndSendResponse(c, func(db db.TxHandler) (auth.Auth, string, error) {
|
||||
return auth.PerformPasswordLogin(db, params.Email, params.Password)
|
||||
})
|
||||
}
|
||||
|
||||
func handlePasswordChange(c *gin.Context) {
|
||||
var params passwordUpdateParams
|
||||
err := c.Bind(¶ms)
|
||||
if err != nil {
|
||||
@@ -35,3 +48,42 @@ func handlePasswordChangeRoute(c *gin.Context) {
|
||||
|
||||
c.JSON(200, gin.H{})
|
||||
}
|
||||
|
||||
func handlePasswordRequestReset(c *gin.Context) {
|
||||
var params emailParams
|
||||
err := c.ShouldBind(¶ms)
|
||||
if err != nil {
|
||||
panic(core.NewError(http.StatusBadRequest, "missing_params", "Missing Parameters"))
|
||||
}
|
||||
|
||||
if err := db.RunInTx(c.Request.Context(), func(db db.TxHandler) error {
|
||||
if user, token, err := auth.CreateResetToken(db, params.Email); err != nil {
|
||||
// Do not indicate that there was an error if no user was found
|
||||
if !errors.Is(err, core.ErrUserNotFound) {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// TODO: #jobs #mail #error
|
||||
go func() {
|
||||
mail.SendPasswordResetEmail(user, token)
|
||||
}()
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
c.JSON(http.StatusOK, gin.H{})
|
||||
}
|
||||
}
|
||||
|
||||
func handlePasswordReset(c *gin.Context) {
|
||||
var params resetPasswordParams
|
||||
err := c.ShouldBind(¶ms)
|
||||
if err != nil {
|
||||
panic(core.NewError(http.StatusBadRequest, "missing_params", "Missing Parameters"))
|
||||
}
|
||||
|
||||
loginAndSendResponse(c, func(db db.TxHandler) (auth.Auth, string, error) {
|
||||
return auth.ResetUserPassword(db, params.Email, params.Token, params.Password)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -51,14 +51,14 @@ func SetupRoutes(r *gin.RouterGroup, logger *zerolog.Logger) {
|
||||
|
||||
if auth.PasswordAuthEnabled() {
|
||||
passwordConfigResponse.Password = true
|
||||
group.POST("/password/login", handlePasswordAuth)
|
||||
group.POST("/password/change", handlePasswordChangeRoute)
|
||||
group.POST("/password/login", handlePasswordLogin)
|
||||
group.POST("/password/change", handlePasswordChange)
|
||||
}
|
||||
if auth.PasswordResetEnabled() {
|
||||
if mail.Configured() {
|
||||
passwordConfigResponse.PasswordReset = true
|
||||
group.POST("/password/request-reset", handleRequestPasswordReset)
|
||||
group.POST("/password/reset", handleResetPassword)
|
||||
group.POST("/password/request-reset", handlePasswordRequestReset)
|
||||
group.POST("/password/reset", handlePasswordReset)
|
||||
} else {
|
||||
logger.Warn().Msg("Password reset enabled but mail not configured")
|
||||
}
|
||||
@@ -85,44 +85,6 @@ func handleConfig(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, passwordConfigResponse)
|
||||
}
|
||||
|
||||
func handleOAuthStart(c *gin.Context) {
|
||||
provider := c.Query("provider")
|
||||
clientType := auth.OpenIDClientWeb
|
||||
if c.Query("client_type") == "native" {
|
||||
clientType = auth.OpenIDClientNative
|
||||
}
|
||||
db := db.Get(c.Request.Context())
|
||||
if authURL, err := auth.OpenIDStart(db, provider, getInstanceURL(c.Request, "/api/v1/auth/oauth/redirect"), clientType); err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
c.Redirect(http.StatusFound, authURL)
|
||||
}
|
||||
}
|
||||
|
||||
func handleOAuthRedirect(c *gin.Context) {
|
||||
db := db.Get(c.Request.Context())
|
||||
|
||||
authCode := c.Query("code")
|
||||
state := c.Query("state")
|
||||
|
||||
if clientType, err := auth.OpenIDValidateAuthCode(db, state, authCode, getInstanceURL(c.Request, "/api/v1/auth/oauth/redirect")); err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
var clientURI url.URL
|
||||
if clientType == auth.OpenIDClientWeb {
|
||||
clientURI = *c.Request.URL
|
||||
clientURI.RawQuery = ""
|
||||
} else {
|
||||
clientURI = url.URL{Scheme: "cloud.phylum.drive"}
|
||||
}
|
||||
clientURI.Path = "/login/token"
|
||||
q := url.Values{}
|
||||
q.Add("token", state)
|
||||
q.Add("instance", getInstanceURL(c.Request, ""))
|
||||
clientURI.RawQuery = q.Encode()
|
||||
c.Redirect(http.StatusFound, clientURI.String())
|
||||
}
|
||||
}
|
||||
func getInstanceURL(req *http.Request, path string) string {
|
||||
uri := url.URL{
|
||||
Scheme: "https",
|
||||
@@ -138,96 +100,6 @@ func getInstanceURL(req *http.Request, path string) string {
|
||||
return uri.String()
|
||||
}
|
||||
|
||||
func handleTokenLogin(c *gin.Context) {
|
||||
var params tokenLoginParams
|
||||
err := c.ShouldBind(¶ms)
|
||||
if err != nil {
|
||||
panic(core.NewError(http.StatusBadRequest, "missing_params", "login token not specified"))
|
||||
}
|
||||
|
||||
loginAndSendResponse(c, func(db db.TxHandler) (auth.Auth, string, error) {
|
||||
return auth.PerformTokenLogin(db, params.Token)
|
||||
})
|
||||
}
|
||||
|
||||
func handleTokenRequest(c *gin.Context) {
|
||||
var params emailParams
|
||||
err := c.ShouldBind(¶ms)
|
||||
if err != nil {
|
||||
panic(core.NewError(http.StatusBadRequest, "missing_params", "Missing Parameters"))
|
||||
}
|
||||
|
||||
if err := db.RunInTx(c.Request.Context(), func(db db.TxHandler) error {
|
||||
if user, token, err := auth.CreateLoginToken(db, params.Email); err != nil {
|
||||
// Do not indicate that there was an error if no user was found
|
||||
if !errors.Is(err, core.ErrUserNotFound) {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// TODO: #jobs #mail #error
|
||||
go func() {
|
||||
mail.SendTokenLoginEmail(user, token)
|
||||
}()
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
c.JSON(http.StatusOK, gin.H{})
|
||||
}
|
||||
}
|
||||
|
||||
func handlePasswordAuth(c *gin.Context) {
|
||||
var params passwordParams
|
||||
err := c.ShouldBind(¶ms)
|
||||
if err != nil {
|
||||
panic(core.NewError(http.StatusBadRequest, "missing_params", "Email or password not specified"))
|
||||
}
|
||||
|
||||
loginAndSendResponse(c, func(db db.TxHandler) (auth.Auth, string, error) {
|
||||
return auth.PerformPasswordLogin(db, params.Email, params.Password)
|
||||
})
|
||||
}
|
||||
|
||||
func handleRequestPasswordReset(c *gin.Context) {
|
||||
var params emailParams
|
||||
err := c.ShouldBind(¶ms)
|
||||
if err != nil {
|
||||
panic(core.NewError(http.StatusBadRequest, "missing_params", "Missing Parameters"))
|
||||
}
|
||||
|
||||
if err := db.RunInTx(c.Request.Context(), func(db db.TxHandler) error {
|
||||
if user, token, err := auth.CreateResetToken(db, params.Email); err != nil {
|
||||
// Do not indicate that there was an error if no user was found
|
||||
if !errors.Is(err, core.ErrUserNotFound) {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// TODO: #jobs #mail #error
|
||||
go func() {
|
||||
mail.SendPasswordResetEmail(user, token)
|
||||
}()
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
c.JSON(http.StatusOK, gin.H{})
|
||||
}
|
||||
}
|
||||
|
||||
func handleResetPassword(c *gin.Context) {
|
||||
var params resetPasswordParams
|
||||
err := c.ShouldBind(¶ms)
|
||||
if err != nil {
|
||||
panic(core.NewError(http.StatusBadRequest, "missing_params", "Missing Parameters"))
|
||||
}
|
||||
|
||||
loginAndSendResponse(c, func(db db.TxHandler) (auth.Auth, string, error) {
|
||||
return auth.ResetUserPassword(db, params.Email, params.Token, params.Password)
|
||||
})
|
||||
}
|
||||
|
||||
func loginAndSendResponse(c *gin.Context, loginFn func(db.TxHandler) (auth.Auth, string, error)) {
|
||||
var err error
|
||||
var key string
|
||||
|
||||
51
server/internal/api/v1/auth/token.go
Normal file
51
server/internal/api/v1/auth/token.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"codeberg.org/shroff/phylum/server/internal/auth"
|
||||
"codeberg.org/shroff/phylum/server/internal/core"
|
||||
"codeberg.org/shroff/phylum/server/internal/db"
|
||||
"codeberg.org/shroff/phylum/server/internal/mail"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func handleTokenLogin(c *gin.Context) {
|
||||
var params tokenLoginParams
|
||||
err := c.ShouldBind(¶ms)
|
||||
if err != nil {
|
||||
panic(core.NewError(http.StatusBadRequest, "missing_params", "login token not specified"))
|
||||
}
|
||||
|
||||
loginAndSendResponse(c, func(db db.TxHandler) (auth.Auth, string, error) {
|
||||
return auth.PerformTokenLogin(db, params.Token)
|
||||
})
|
||||
}
|
||||
|
||||
func handleTokenRequest(c *gin.Context) {
|
||||
var params emailParams
|
||||
err := c.ShouldBind(¶ms)
|
||||
if err != nil {
|
||||
panic(core.NewError(http.StatusBadRequest, "missing_params", "Missing Parameters"))
|
||||
}
|
||||
|
||||
if err := db.RunInTx(c.Request.Context(), func(db db.TxHandler) error {
|
||||
if user, token, err := auth.CreateLoginToken(db, params.Email); err != nil {
|
||||
// Do not indicate that there was an error if no user was found
|
||||
if !errors.Is(err, core.ErrUserNotFound) {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// TODO: #jobs #mail #error
|
||||
go func() {
|
||||
mail.SendTokenLoginEmail(user, token)
|
||||
}()
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
c.JSON(http.StatusOK, gin.H{})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user