init from gitlab
This commit is contained in:
47
internal/server/api/auth/auth.go
Normal file
47
internal/server/api/auth/auth.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/rs/zerolog/log"
|
||||
"gitlab.com/texm/shokku/internal/env"
|
||||
"gitlab.com/texm/shokku/internal/server/auth"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func HandleLogout(e *env.Env, c echo.Context) error {
|
||||
e.Auth.ClearTokenCookies(c)
|
||||
return c.NoContent(http.StatusOK)
|
||||
}
|
||||
|
||||
func HandleRefreshAuth(e *env.Env, c echo.Context) error {
|
||||
user, err := e.Auth.GetUserFromContext(c)
|
||||
if err != nil {
|
||||
log.Error().Msg("failed to parse user from context")
|
||||
return echo.ErrInternalServerError
|
||||
}
|
||||
|
||||
claims := auth.UserClaims{
|
||||
Name: user.Name,
|
||||
}
|
||||
token, err := e.Auth.NewToken(claims)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("failed to create jwt")
|
||||
return echo.ErrInternalServerError
|
||||
}
|
||||
|
||||
e.Auth.SetTokenCookies(c, token)
|
||||
|
||||
return c.NoContent(http.StatusOK)
|
||||
}
|
||||
|
||||
func HandleGetDetails(e *env.Env, c echo.Context) error {
|
||||
user, err := e.Auth.GetUserFromContext(c)
|
||||
if err != nil {
|
||||
log.Error().Msg("failed to parse user from context")
|
||||
return echo.ErrInternalServerError
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, echo.Map{
|
||||
"username": user.Name,
|
||||
})
|
||||
}
|
||||
76
internal/server/api/auth/github.go
Normal file
76
internal/server/api/auth/github.go
Normal file
@@ -0,0 +1,76 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/rs/zerolog/log"
|
||||
"gitlab.com/texm/shokku/internal/env"
|
||||
"gitlab.com/texm/shokku/internal/models"
|
||||
"gitlab.com/texm/shokku/internal/server/auth"
|
||||
"gitlab.com/texm/shokku/internal/server/dto"
|
||||
"gitlab.com/texm/shokku/internal/server/github"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func GetGithubAuthInfo(e *env.Env, c echo.Context) error {
|
||||
var ghApp models.GithubApp
|
||||
if err := e.DB.First(&ghApp).Error; err != nil {
|
||||
log.Error().Err(err).Msg("no github app in db")
|
||||
return echo.ErrBadRequest
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, dto.GetGithubAuthInfoResponse{
|
||||
ClientID: ghApp.ClientId,
|
||||
})
|
||||
}
|
||||
|
||||
func CompleteGithubAuth(e *env.Env, c echo.Context) error {
|
||||
var req dto.GithubAuthRequest
|
||||
if err := c.Bind(&req); err != nil {
|
||||
return echo.ErrBadRequest
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
params := github.CodeExchangeParams{
|
||||
Code: req.Code,
|
||||
Scopes: []string{},
|
||||
RedirectURL: req.RedirectURL,
|
||||
}
|
||||
client, err := github.ExchangeCode(ctx, e, params)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("failed to exchange code for client")
|
||||
return echo.ErrBadRequest
|
||||
}
|
||||
|
||||
user, err := client.GetUser(ctx)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("failed to get user")
|
||||
return echo.ErrBadRequest
|
||||
}
|
||||
|
||||
var count int64
|
||||
dbUser := models.User{Name: user.GetLogin()}
|
||||
r := e.DB.Model(&dbUser).Where(&dbUser).Count(&count)
|
||||
if r.Error != nil {
|
||||
log.Error().
|
||||
Err(r.Error).
|
||||
Str("name", user.GetLogin()).
|
||||
Msg("user lookup error")
|
||||
return echo.ErrInternalServerError
|
||||
}
|
||||
if count == 0 {
|
||||
return echo.ErrForbidden
|
||||
}
|
||||
|
||||
claims := auth.UserClaims{
|
||||
Name: user.GetLogin(),
|
||||
}
|
||||
token, err := e.Auth.NewToken(claims)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("failed to create jwt")
|
||||
return echo.ErrInternalServerError
|
||||
}
|
||||
e.Auth.SetTokenCookies(c, token)
|
||||
|
||||
return c.NoContent(http.StatusOK)
|
||||
}
|
||||
58
internal/server/api/auth/password.go
Normal file
58
internal/server/api/auth/password.go
Normal file
@@ -0,0 +1,58 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"github.com/pquerna/otp/totp"
|
||||
"github.com/rs/zerolog/log"
|
||||
"gitlab.com/texm/shokku/internal/env"
|
||||
auth "gitlab.com/texm/shokku/internal/server/auth"
|
||||
"gitlab.com/texm/shokku/internal/server/dto"
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"gitlab.com/texm/shokku/internal/models"
|
||||
)
|
||||
|
||||
func HandlePasswordLogin(e *env.Env, c echo.Context) error {
|
||||
var req dto.PasswordLoginRequest
|
||||
if err := c.Bind(&req); err != nil {
|
||||
return echo.ErrBadRequest
|
||||
}
|
||||
|
||||
var dbUser models.User
|
||||
res := e.DB.Where("name = ?", req.Username).Take(&dbUser)
|
||||
if res.Error != nil {
|
||||
return echo.ErrForbidden
|
||||
}
|
||||
|
||||
pwAuth, ok := e.Auth.(*auth.PasswordAuthenticator)
|
||||
if !ok {
|
||||
log.Error().Msg("failed to cast authenticator to pw auth")
|
||||
return echo.ErrInternalServerError
|
||||
}
|
||||
if !pwAuth.VerifyHash([]byte(req.Password), dbUser.PasswordHash) {
|
||||
return echo.ErrForbidden
|
||||
}
|
||||
|
||||
if dbUser.TotpEnabled {
|
||||
if !totp.Validate(req.TotpCode, dbUser.TotpSecret) {
|
||||
return c.JSON(http.StatusOK, dto.PasswordLoginResponse{
|
||||
Success: true,
|
||||
NeedsTotp: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
claims := auth.UserClaims{
|
||||
Name: req.Username,
|
||||
}
|
||||
token, err := e.Auth.NewToken(claims)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("failed to create jwt")
|
||||
return echo.ErrInternalServerError
|
||||
}
|
||||
e.Auth.SetTokenCookies(c, token)
|
||||
|
||||
return c.JSON(http.StatusOK, dto.PasswordLoginResponse{
|
||||
Success: true,
|
||||
})
|
||||
}
|
||||
16
internal/server/api/auth/routes.go
Normal file
16
internal/server/api/auth/routes.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
"gitlab.com/texm/shokku/internal/env"
|
||||
)
|
||||
|
||||
func RegisterRoutes(e *env.Env, g *echo.Group, authG *echo.Group) {
|
||||
g.POST("/login", e.H(HandlePasswordLogin))
|
||||
g.GET("/github", e.H(GetGithubAuthInfo))
|
||||
g.POST("/github/auth", e.H(CompleteGithubAuth))
|
||||
g.POST("/logout", e.H(HandleLogout))
|
||||
|
||||
authG.GET("/details", e.H(HandleGetDetails))
|
||||
authG.POST("/refresh", e.H(HandleRefreshAuth))
|
||||
}
|
||||
Reference in New Issue
Block a user