-
Gabriel Zachmann authoredGabriel Zachmann authored
authcodeInfo.go 4.15 KiB
package authcodeinforepo
import (
"github.com/jmoiron/sqlx"
log "github.com/sirupsen/logrus"
"github.com/oidc-mytoken/api/v0"
"github.com/oidc-mytoken/server/internal/config"
"github.com/oidc-mytoken/server/internal/db"
"github.com/oidc-mytoken/server/internal/db/dbrepo/authcodeinforepo/state"
"github.com/oidc-mytoken/server/internal/db/dbrepo/mytokenrepo/transfercoderepo"
"github.com/oidc-mytoken/server/shared/mytoken/restrictions"
)
// AuthFlowInfo holds database information about a started authorization flow
type AuthFlowInfo struct {
AuthFlowInfoOut
PollingCode *transfercoderepo.TransferCode
}
// AuthFlowInfoOut holds database information about a started authorization flow
type AuthFlowInfoOut struct {
State *state.State
Issuer string
Restrictions restrictions.Restrictions
Capabilities api.Capabilities
SubtokenCapabilities api.Capabilities
Name string
PollingCode bool
Rotation *api.Rotation
}
type authFlowInfo struct {
State *state.State `db:"state_h"`
Issuer string `db:"iss"`
Restrictions restrictions.Restrictions
Capabilities api.Capabilities
SubtokenCapabilities api.Capabilities `db:"subtoken_capabilities"`
Name db.NullString
PollingCode db.BitBool `db:"polling_code"`
ExpiresIn int64 `db:"expires_in"`
Rotation *api.Rotation
}
func (i *AuthFlowInfo) toAuthFlowInfo() *authFlowInfo {
return &authFlowInfo{
State: i.State,
Issuer: i.Issuer,
Restrictions: i.Restrictions,
Capabilities: i.Capabilities,
SubtokenCapabilities: i.SubtokenCapabilities,
Name: db.NewNullString(i.Name),
ExpiresIn: config.Get().Features.Polling.PollingCodeExpiresAfter,
PollingCode: i.PollingCode != nil,
Rotation: i.Rotation,
}
}
func (i *authFlowInfo) toAuthFlowInfo() *AuthFlowInfoOut {
return &AuthFlowInfoOut{
State: i.State,
Issuer: i.Issuer,
Restrictions: i.Restrictions,
Capabilities: i.Capabilities,
SubtokenCapabilities: i.SubtokenCapabilities,
Name: i.Name.String,
PollingCode: bool(i.PollingCode),
Rotation: i.Rotation,
}
}
// Store stores the AuthFlowInfoIn in the database as well as the linked polling code if it exists
func (i *AuthFlowInfo) Store(tx *sqlx.Tx) error {
log.Debug("Storing auth flow info")
store := i.toAuthFlowInfo()
return db.RunWithinTransaction(tx, func(tx *sqlx.Tx) error {
if i.PollingCode != nil {
if err := i.PollingCode.Store(tx); err != nil {
return err
}
}
_, err := tx.NamedExec(`INSERT INTO AuthInfo (state_h, iss, restrictions, capabilities, subtoken_capabilities, name, expires_in, polling_code, rotation) VALUES(:state_h, :iss, :restrictions, :capabilities, :subtoken_capabilities, :name, :expires_in, :polling_code, :rotation)`, store)
return err
})
}
// GetAuthFlowInfoByState returns AuthFlowInfoIn by state
func GetAuthFlowInfoByState(state *state.State) (*AuthFlowInfoOut, error) {
info := authFlowInfo{}
if err := db.Transact(func(tx *sqlx.Tx) error {
return tx.Get(&info, `SELECT state_h, iss, restrictions, capabilities, subtoken_capabilities, name, polling_code, rotation FROM AuthInfo WHERE state_h=? AND expires_at >= CURRENT_TIMESTAMP()`, state)
}); err != nil {
return nil, err
}
return info.toAuthFlowInfo(), nil
}
// DeleteAuthFlowInfoByState deletes the AuthFlowInfoIn for a given state
func DeleteAuthFlowInfoByState(tx *sqlx.Tx, state *state.State) error {
return db.RunWithinTransaction(tx, func(tx *sqlx.Tx) error {
_, err := tx.Exec(`DELETE FROM AuthInfo WHERE state_h = ?`, state)
return err
})
}
// UpdateTokenInfoByState updates the stored AuthFlowInfo for the given state
func UpdateTokenInfoByState(tx *sqlx.Tx, state *state.State, r restrictions.Restrictions, c, sc api.Capabilities) error {
return db.RunWithinTransaction(tx, func(tx *sqlx.Tx) error {
_, err := tx.Exec(`UPDATE AuthInfo SET restrictions=?, capabilities=?, subtoken_capabilities=? WHERE state_h=?`, r, c, sc, state)
return err
})
}