103 lines
3.0 KiB
Go
103 lines
3.0 KiB
Go
package refreshtokens
|
|
|
|
import (
|
|
"strings"
|
|
|
|
sessionmodel "git.sendico.io/tech/sxchnge/product/sessions/model"
|
|
"git.sendico.io/tech/sxchnge/shared/database/repository"
|
|
ri "git.sendico.io/tech/sxchnge/shared/database/repository/index"
|
|
"git.sendico.io/tech/sxchnge/shared/database/source"
|
|
"git.sendico.io/tech/sxchnge/shared/database/template"
|
|
"git.sendico.io/tech/sxchnge/shared/logging"
|
|
"git.sendico.io/tech/sxchnge/shared/service"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
type Collections struct {
|
|
RefreshTokens string
|
|
Clients string
|
|
}
|
|
|
|
type RefreshTokenDB struct {
|
|
template.DBImp[*sessionmodel.RefreshToken]
|
|
clients repository.Repository
|
|
collection Collections
|
|
}
|
|
|
|
func Create(logger mlogger.Logger, db source.Source) (*RefreshTokenDB, error) {
|
|
return CreateWithCollections(logger, db, Collections{})
|
|
}
|
|
|
|
func (c Collections) WithDefaults() Collections {
|
|
if strings.TrimSpace(c.RefreshTokens) == "" {
|
|
c.RefreshTokens = mservice.RefreshTokens
|
|
}
|
|
if strings.TrimSpace(c.Clients) == "" {
|
|
c.Clients = mservice.Clients
|
|
}
|
|
return c
|
|
}
|
|
|
|
func CreateWithCollections(logger mlogger.Logger, db source.Source, collections Collections) (*RefreshTokenDB, error) {
|
|
collections = collections.WithDefaults()
|
|
p := &RefreshTokenDB{
|
|
DBImp: *template.Create[*sessionmodel.RefreshToken](logger, mservice.Type(collections.RefreshTokens), db),
|
|
clients: repository.CreateRepository(db, collections.Clients),
|
|
collection: collections,
|
|
}
|
|
|
|
if err := p.Repository.CreateIndex(&ri.Definition{
|
|
Keys: []ri.Key{{Field: "token", Sort: ri.Asc}},
|
|
Unique: true,
|
|
}); err != nil {
|
|
p.Logger.Error("Failed to create unique token index", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
|
|
ttl := int32(0)
|
|
if err := p.Repository.CreateIndex(&ri.Definition{
|
|
Keys: []ri.Key{{Field: ExpiresAtField, Sort: ri.Asc}},
|
|
Name: "expire_sessions",
|
|
TTL: &ttl,
|
|
}); err != nil {
|
|
p.Logger.Error("Failed to create refresh session expiration index", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
|
|
// Add unique constraint on account/client/device combination
|
|
if err := p.Repository.CreateIndex(&ri.Definition{
|
|
Keys: []ri.Key{
|
|
{Field: "accountRef", Sort: ri.Asc},
|
|
{Field: "clientId", Sort: ri.Asc},
|
|
{Field: "deviceId", Sort: ri.Asc},
|
|
},
|
|
Unique: true,
|
|
Name: "unique_active_session",
|
|
PartialFilter: repository.Filter(IsRevokedField, false),
|
|
}); err != nil {
|
|
p.Logger.Error("Failed to create unique account/client/device index", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
|
|
if err := p.Repository.CreateIndex(&ri.Definition{
|
|
Keys: []ri.Key{{Field: IsRevokedField, Sort: ri.Asc}},
|
|
}); err != nil {
|
|
p.Logger.Error("Failed to create unique token revokation status index", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
|
|
if err := p.clients.CreateIndex(&ri.Definition{
|
|
Keys: []ri.Key{{Field: "clientId", Sort: ri.Asc}},
|
|
Unique: true,
|
|
}); err != nil {
|
|
p.Logger.Error("Failed to create unique client identifier index", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
|
|
return p, nil
|
|
}
|
|
|
|
func (db *RefreshTokenDB) Collections() Collections {
|
|
return db.collection
|
|
}
|