mirror of
https://github.com/pushbits/server.git
synced 2025-06-08 13:42:05 +02:00
Initialize repository
This commit is contained in:
commit
1d758fcfd0
28 changed files with 1107 additions and 0 deletions
106
authentication/authentication.go
Normal file
106
authentication/authentication.go
Normal file
|
@ -0,0 +1,106 @@
|
|||
package authentication
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"github.com/eikendev/pushbits/authentication/credentials"
|
||||
"github.com/eikendev/pushbits/model"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
const (
|
||||
headerName = "X-Gotify-Key"
|
||||
)
|
||||
|
||||
// The Database interface for encapsulating database access.
|
||||
type Database interface {
|
||||
GetApplicationByToken(token string) (*model.Application, error)
|
||||
GetUserByName(name string) (*model.User, error)
|
||||
}
|
||||
|
||||
// Authenticator is the provider for authentication middleware.
|
||||
type Authenticator struct {
|
||||
DB Database
|
||||
}
|
||||
|
||||
type hasUserProperty func(user *model.User) bool
|
||||
|
||||
func (a *Authenticator) userFromBasicAuth(ctx *gin.Context) (*model.User, error) {
|
||||
if name, password, ok := ctx.Request.BasicAuth(); ok {
|
||||
if user, err := a.DB.GetUserByName(name); err != nil {
|
||||
return nil, err
|
||||
} else if user != nil && credentials.ComparePassword(user.PasswordHash, []byte(password)) {
|
||||
return user, nil
|
||||
} else {
|
||||
return nil, errors.New("credentials were invalid")
|
||||
}
|
||||
}
|
||||
|
||||
return nil, errors.New("no credentials were supplied")
|
||||
}
|
||||
|
||||
func (a *Authenticator) requireUserProperty(has hasUserProperty) gin.HandlerFunc {
|
||||
return func(ctx *gin.Context) {
|
||||
user, err := a.userFromBasicAuth(ctx)
|
||||
if err != nil {
|
||||
ctx.AbortWithError(http.StatusForbidden, err)
|
||||
return
|
||||
}
|
||||
|
||||
if !has(user) {
|
||||
ctx.AbortWithError(http.StatusForbidden, errors.New("authentication failed"))
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Set("user", user)
|
||||
}
|
||||
}
|
||||
|
||||
// RequireUser returns a Gin middleware which requires valid user credentials to be supplied with the request.
|
||||
func (a *Authenticator) RequireUser() gin.HandlerFunc {
|
||||
return a.requireUserProperty(func(user *model.User) bool {
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
// RequireAdmin returns a Gin middleware which requires valid admin credentials to be supplied with the request.
|
||||
func (a *Authenticator) RequireAdmin() gin.HandlerFunc {
|
||||
return a.requireUserProperty(func(user *model.User) bool {
|
||||
return user.IsAdmin
|
||||
})
|
||||
}
|
||||
|
||||
func (a *Authenticator) tokenFromQueryOrHeader(ctx *gin.Context) string {
|
||||
if token := a.tokenFromQuery(ctx); token != "" {
|
||||
return token
|
||||
} else if token := a.tokenFromHeader(ctx); token != "" {
|
||||
return token
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func (a *Authenticator) tokenFromQuery(ctx *gin.Context) string {
|
||||
return ctx.Request.URL.Query().Get("token")
|
||||
}
|
||||
|
||||
func (a *Authenticator) tokenFromHeader(ctx *gin.Context) string {
|
||||
return ctx.Request.Header.Get(headerName)
|
||||
}
|
||||
|
||||
// RequireApplicationToken returns a Gin middleware which requires an application token to be supplied with the request.
|
||||
func (a *Authenticator) RequireApplicationToken() gin.HandlerFunc {
|
||||
return func(ctx *gin.Context) {
|
||||
token := a.tokenFromQueryOrHeader(ctx)
|
||||
|
||||
app, err := a.DB.GetApplicationByToken(token)
|
||||
if err != nil {
|
||||
ctx.AbortWithError(http.StatusForbidden, err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Set("app", app)
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue