This commit is contained in:
Stavros
2025-01-23 19:16:35 +02:00
parent 143b13af2c
commit 80d25551e0
16 changed files with 491 additions and 115 deletions

View File

@@ -10,6 +10,7 @@ import (
"tinyauth/internal/assets"
"tinyauth/internal/auth"
"tinyauth/internal/hooks"
"tinyauth/internal/providers"
"tinyauth/internal/types"
"tinyauth/internal/utils"
@@ -20,25 +21,26 @@ import (
"github.com/rs/zerolog/log"
)
func NewAPI(config types.APIConfig, hooks *hooks.Hooks, auth *auth.Auth) (*API) {
func NewAPI(config types.APIConfig, hooks *hooks.Hooks, auth *auth.Auth, providers *providers.Providers) *API {
return &API{
Config: config,
Hooks: hooks,
Auth: auth,
Router: nil,
Config: config,
Hooks: hooks,
Auth: auth,
Providers: providers,
}
}
type API struct {
Config types.APIConfig
Router *gin.Engine
Hooks *hooks.Hooks
Auth *auth.Auth
Config types.APIConfig
Router *gin.Engine
Hooks *hooks.Hooks
Auth *auth.Auth
Providers *providers.Providers
}
func (api *API) Init() {
gin.SetMode(gin.ReleaseMode)
router := gin.New()
router.Use(zerolog())
dist, distErr := fs.Sub(assets.Assets, "dist")
@@ -67,17 +69,17 @@ func (api *API) Init() {
} else {
isSecure = false
}
store.Options(sessions.Options{
Domain: fmt.Sprintf(".%s", domain),
Path: "/",
HttpOnly: true,
Secure: isSecure,
})
router.Use(sessions.Sessions("tinyauth", store))
router.Use(func(c *gin.Context) {
store.Options(sessions.Options{
Domain: fmt.Sprintf(".%s", domain),
Path: "/",
HttpOnly: true,
Secure: isSecure,
})
router.Use(sessions.Sessions("tinyauth", store))
router.Use(func(c *gin.Context) {
if !strings.HasPrefix(c.Request.URL.Path, "/api") {
_, err := fs.Stat(dist, strings.TrimPrefix(c.Request.URL.Path, "/"))
if os.IsNotExist(err) {
@@ -92,12 +94,20 @@ func (api *API) Init() {
}
func (api *API) SetupRoutes() {
api.Router.GET("/api/auth", func (c *gin.Context) {
userContext := api.Hooks.UseUserContext(c)
api.Router.GET("/api/auth", func(c *gin.Context) {
userContext, userContextErr := api.Hooks.UseUserContext(c)
if userContextErr != nil {
c.JSON(500, gin.H{
"status": 500,
"message": "Internal Server Error",
})
return
}
if userContext.IsLoggedIn {
c.JSON(200, gin.H{
"status": 200,
"status": 200,
"message": "Authenticated",
})
return
@@ -112,7 +122,7 @@ func (api *API) SetupRoutes() {
if queryErr != nil {
c.JSON(501, gin.H{
"status": 501,
"status": 501,
"message": "Internal Server Error",
})
return
@@ -121,24 +131,24 @@ func (api *API) SetupRoutes() {
c.Redirect(http.StatusTemporaryRedirect, fmt.Sprintf("%s/?%s", api.Config.AppURL, queries.Encode()))
})
api.Router.POST("/api/login", func (c *gin.Context) {
api.Router.POST("/api/login", func(c *gin.Context) {
var login types.LoginRequest
err := c.BindJSON(&login)
if err != nil {
c.JSON(400, gin.H{
"status": 400,
"status": 400,
"message": "Bad Request",
})
return
}
user := api.Auth.GetUser(login.Username)
user := api.Auth.GetUser(login.Email)
if user == nil {
c.JSON(401, gin.H{
"status": 401,
"status": 401,
"message": "Unauthorized",
})
return
@@ -146,62 +156,149 @@ func (api *API) SetupRoutes() {
if !api.Auth.CheckPassword(*user, login.Password) {
c.JSON(401, gin.H{
"status": 401,
"status": 401,
"message": "Unauthorized",
})
return
}
session := sessions.Default(c)
session.Set("tinyauth", user.Username)
session.Set("tinyauth_sid", user.Email)
session.Set("tinyauth_oauth_provider", "")
session.Save()
c.JSON(200, gin.H{
"status": 200,
"status": 200,
"message": "Logged in",
})
})
api.Router.POST("/api/logout", func (c *gin.Context) {
api.Router.POST("/api/logout", func(c *gin.Context) {
session := sessions.Default(c)
session.Delete("tinyauth")
session.Delete("tinyauth_sid")
session.Delete("tinyauth_oauth_provider")
session.Save()
c.JSON(200, gin.H{
"status": 200,
"status": 200,
"message": "Logged out",
})
})
api.Router.GET("/api/status", func (c *gin.Context) {
userContext := api.Hooks.UseUserContext(c)
api.Router.GET("/api/status", func(c *gin.Context) {
userContext, userContextErr := api.Hooks.UseUserContext(c)
if userContextErr != nil {
c.JSON(500, gin.H{
"status": 500,
"message": "Internal Server Error",
})
return
}
if !userContext.IsLoggedIn {
c.JSON(200, gin.H{
"status": 200,
"message": "Unauthenticated",
"username": "",
"status": 200,
"message": "Unauthenticated",
"email": "",
"isLoggedIn": false,
"oauth": false,
"provider": "",
})
return
}
}
c.JSON(200, gin.H{
"status": 200,
"message": "Authenticated",
"username": userContext.Username,
"isLoggedIn": true,
"status": 200,
"message": "Authenticated",
"email": userContext.Email,
"isLoggedIn": userContext.IsLoggedIn,
"oauth": userContext.OAuth,
"provider": userContext.Provider,
})
})
api.Router.GET("/api/healthcheck", func (c *gin.Context) {
api.Router.GET("/api/healthcheck", func(c *gin.Context) {
c.JSON(200, gin.H{
"status": 200,
"status": 200,
"message": "OK",
})
})
}
api.Router.GET("/api/oauth/url/:provider", func(c *gin.Context) {
var provider types.OAuthBind
bindErr := c.BindUri(&provider)
if bindErr != nil {
c.JSON(400, gin.H{
"status": 400,
"message": "Bad Request",
})
return
}
authURL := api.Providers.GetAuthURL(provider.Provider)
if authURL == "" {
c.JSON(400, gin.H{
"status": 400,
"message": "Bad Request",
})
return
}
c.JSON(200, gin.H{
"status": 200,
"message": "Ok",
"url": authURL,
})
})
api.Router.GET("/api/oauth/callback/:provider", func(c *gin.Context) {
var provider types.OAuthBind
bindErr := c.BindUri(&provider)
if bindErr != nil {
c.JSON(400, gin.H{
"status": 400,
"message": "Bad Request",
})
return
}
code := c.Query("code")
if code == "" {
c.JSON(400, gin.H{
"status": 400,
"message": "Bad Request",
})
return
}
email, emailErr := api.Providers.Login(code, provider.Provider)
if emailErr != nil {
c.JSON(500, gin.H{
"status": 500,
"message": "Internal Server Error",
})
return
}
session := sessions.Default(c)
session.Set("tinyauth_sid", email)
session.Set("tinyauth_oauth_provider", provider.Provider)
session.Save()
c.JSON(200, gin.H{
"status": 200,
"message": "Logged in",
})
})
}
func (api *API) Run() {
log.Info().Str("address", api.Config.Address).Int("port", api.Config.Port).Msg("Starting server")
@@ -218,16 +315,16 @@ func zerolog() gin.HandlerFunc {
address := c.Request.RemoteAddr
method := c.Request.Method
path := c.Request.URL.Path
latency := time.Since(tStart).String()
switch {
case code >= 200 && code < 300:
log.Info().Str("method", method).Str("path", path).Str("address", address).Int("status", code).Str("latency", latency).Msg("Request")
case code >= 300 && code < 400:
log.Warn().Str("method", method).Str("path", path).Str("address", address).Int("status", code).Str("latency", latency).Msg("Request")
case code >= 400:
log.Error().Str("method", method).Str("path", path).Str("address", address).Int("status", code).Str("latency", latency).Msg("Request")
case code >= 200 && code < 300:
log.Info().Str("method", method).Str("path", path).Str("address", address).Int("status", code).Str("latency", latency).Msg("Request")
case code >= 300 && code < 400:
log.Warn().Str("method", method).Str("path", path).Str("address", address).Int("status", code).Str("latency", latency).Msg("Request")
case code >= 400:
log.Error().Str("method", method).Str("path", path).Str("address", address).Int("status", code).Str("latency", latency).Msg("Request")
}
}
}
}