Go-Back-Skeleton/auth/api.go
2017-09-25 20:19:57 +02:00

91 lines
2.1 KiB
Go

package auth
import (
"net/http"
"time"
"github.com/dhax/go-base/email"
"github.com/dhax/go-base/logging"
"github.com/dhax/go-base/models"
"github.com/go-chi/chi"
"github.com/go-chi/render"
"github.com/sirupsen/logrus"
)
// Store defines database operations on account and token data.
type Store interface {
GetByID(id int) (*models.Account, error)
GetByEmail(email string) (*models.Account, error)
GetByRefreshToken(token string) (*models.Account, *models.Token, error)
UpdateAccount(a *models.Account) error
SaveRefreshToken(u *models.Token) error
DeleteRefreshToken(t *models.Token) error
PurgeExpiredToken() error
}
// EmailService defines methods to send account emails.
type EmailService interface {
LoginToken(name, email string, c email.LoginTokenContent) error
}
// Resource implements passwordless token authentication against a database.
type Resource struct {
Login *LoginTokenAuth
Token *TokenAuth
store Store
mailer EmailService
}
// NewResource returns a configured authentication resource.
func NewResource(store Store, mailer EmailService) (*Resource, error) {
loginAuth, err := NewLoginTokenAuth()
if err != nil {
return nil, err
}
tokenAuth, err := NewTokenAuth()
if err != nil {
return nil, err
}
resource := &Resource{
Login: loginAuth,
Token: tokenAuth,
store: store,
mailer: mailer,
}
resource.Cleanup()
return resource, nil
}
// Router provides neccessary routes for passwordless authentication flow.
func (rs *Resource) Router() *chi.Mux {
r := chi.NewRouter()
r.Use(render.SetContentType(render.ContentTypeJSON))
r.Post("/login", rs.login)
r.Post("/token", rs.token)
r.Group(func(r chi.Router) {
r.Use(rs.Token.Verifier())
r.Use(AuthenticateRefreshJWT)
r.Post("/refresh", rs.refresh)
r.Post("/logout", rs.logout)
})
return r
}
func (rs *Resource) Cleanup() {
ticker := time.NewTicker(time.Hour * 1)
go func() {
for range ticker.C {
if err := rs.store.PurgeExpiredToken(); err != nil {
logging.Logger.WithField("auth", "cleanup").Error(err)
}
}
}()
}
func log(r *http.Request) logrus.FieldLogger {
return logging.GetLogEntry(r)
}