refactor(model): rename from models (#2968)
parent
7e59df6f7f
commit
6d937cf6cc
|
@ -41,7 +41,7 @@ for, and the structure it must have.
|
||||||
│ │ └─⫸ Summary in present tense. Not capitalized. No period at the end.
|
│ │ └─⫸ Summary in present tense. Not capitalized. No period at the end.
|
||||||
│ │
|
│ │
|
||||||
│ └─⫸ Commit Scope: api|authentication|authorization|cmd|commands|configuration|duo|
|
│ └─⫸ Commit Scope: api|authentication|authorization|cmd|commands|configuration|duo|
|
||||||
│ handlers|logging|middlewares|mocks|models|notification|oidc|
|
│ handlers|logging|middlewares|mocks|model|notification|ntp|oidc|
|
||||||
│ regulation|server|session|storage|suites|templates|utils|web
|
│ regulation|server|session|storage|suites|templates|utils|web
|
||||||
│
|
│
|
||||||
└─⫸ Commit Type: build|ci|docs|feat|fix|perf|refactor|release|test
|
└─⫸ Commit Type: build|ci|docs|feat|fix|perf|refactor|release|test
|
||||||
|
@ -77,7 +77,7 @@ The scope should be the name of the package affected
|
||||||
* logging
|
* logging
|
||||||
* middlewares
|
* middlewares
|
||||||
* mocks
|
* mocks
|
||||||
* models
|
* model
|
||||||
* notification
|
* notification
|
||||||
* ntp
|
* ntp
|
||||||
* oidc
|
* oidc
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
package authentication
|
package authentication
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/authelia/authelia/v4/internal/models"
|
"github.com/authelia/authelia/v4/internal/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
// UserProvider is the interface for checking user password and
|
// UserProvider is the interface for checking user password and
|
||||||
// gathering user details.
|
// gathering user details.
|
||||||
type UserProvider interface {
|
type UserProvider interface {
|
||||||
models.StartupCheck
|
model.StartupCheck
|
||||||
|
|
||||||
CheckUserPassword(username string, password string) (valid bool, err error)
|
CheckUserPassword(username string, password string) (valid bool, err error)
|
||||||
GetDetails(username string) (details *UserDetails, err error)
|
GetDetails(username string) (details *UserDetails, err error)
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
"github.com/authelia/authelia/v4/internal/configuration/schema"
|
"github.com/authelia/authelia/v4/internal/configuration/schema"
|
||||||
"github.com/authelia/authelia/v4/internal/logging"
|
"github.com/authelia/authelia/v4/internal/logging"
|
||||||
"github.com/authelia/authelia/v4/internal/middlewares"
|
"github.com/authelia/authelia/v4/internal/middlewares"
|
||||||
"github.com/authelia/authelia/v4/internal/models"
|
"github.com/authelia/authelia/v4/internal/model"
|
||||||
"github.com/authelia/authelia/v4/internal/server"
|
"github.com/authelia/authelia/v4/internal/server"
|
||||||
"github.com/authelia/authelia/v4/internal/utils"
|
"github.com/authelia/authelia/v4/internal/utils"
|
||||||
)
|
)
|
||||||
|
@ -121,7 +121,7 @@ func doStartupChecks(config *schema.Configuration, providers *middlewares.Provid
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func doStartupCheck(logger *logrus.Logger, name string, provider models.StartupCheck, disabled bool) error {
|
func doStartupCheck(logger *logrus.Logger, name string, provider model.StartupCheck, disabled bool) error {
|
||||||
if disabled {
|
if disabled {
|
||||||
logger.Debugf("%s provider: startup check skipped as it is disabled", name)
|
logger.Debugf("%s provider: startup check skipped as it is disabled", name)
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -15,7 +15,7 @@ import (
|
||||||
"github.com/authelia/authelia/v4/internal/configuration"
|
"github.com/authelia/authelia/v4/internal/configuration"
|
||||||
"github.com/authelia/authelia/v4/internal/configuration/schema"
|
"github.com/authelia/authelia/v4/internal/configuration/schema"
|
||||||
"github.com/authelia/authelia/v4/internal/configuration/validator"
|
"github.com/authelia/authelia/v4/internal/configuration/validator"
|
||||||
"github.com/authelia/authelia/v4/internal/models"
|
"github.com/authelia/authelia/v4/internal/model"
|
||||||
"github.com/authelia/authelia/v4/internal/storage"
|
"github.com/authelia/authelia/v4/internal/storage"
|
||||||
"github.com/authelia/authelia/v4/internal/totp"
|
"github.com/authelia/authelia/v4/internal/totp"
|
||||||
"github.com/authelia/authelia/v4/internal/utils"
|
"github.com/authelia/authelia/v4/internal/utils"
|
||||||
|
@ -203,7 +203,7 @@ func storageTOTPGenerateRunE(cmd *cobra.Command, args []string) (err error) {
|
||||||
var (
|
var (
|
||||||
provider storage.Provider
|
provider storage.Provider
|
||||||
ctx = context.Background()
|
ctx = context.Background()
|
||||||
c *models.TOTPConfiguration
|
c *model.TOTPConfiguration
|
||||||
force bool
|
force bool
|
||||||
filename string
|
filename string
|
||||||
file *os.File
|
file *os.File
|
||||||
|
@ -302,7 +302,7 @@ func storageTOTPExportRunE(cmd *cobra.Command, args []string) (err error) {
|
||||||
var (
|
var (
|
||||||
provider storage.Provider
|
provider storage.Provider
|
||||||
format, dir string
|
format, dir string
|
||||||
configurations []models.TOTPConfiguration
|
configurations []model.TOTPConfiguration
|
||||||
img image.Image
|
img image.Image
|
||||||
|
|
||||||
ctx = context.Background()
|
ctx = context.Background()
|
||||||
|
@ -400,7 +400,7 @@ func storageMigrateHistoryRunE(_ *cobra.Command, _ []string) (err error) {
|
||||||
var (
|
var (
|
||||||
provider storage.Provider
|
provider storage.Provider
|
||||||
version int
|
version int
|
||||||
migrations []models.Migration
|
migrations []model.Migration
|
||||||
|
|
||||||
ctx = context.Background()
|
ctx = context.Background()
|
||||||
)
|
)
|
||||||
|
@ -445,7 +445,7 @@ func newStorageMigrateListRunE(up bool) func(cmd *cobra.Command, args []string)
|
||||||
var (
|
var (
|
||||||
provider storage.Provider
|
provider storage.Provider
|
||||||
ctx = context.Background()
|
ctx = context.Background()
|
||||||
migrations []models.SchemaMigration
|
migrations []model.SchemaMigration
|
||||||
directionStr string
|
directionStr string
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
"github.com/authelia/authelia/v4/internal/authorization"
|
"github.com/authelia/authelia/v4/internal/authorization"
|
||||||
"github.com/authelia/authelia/v4/internal/configuration/schema"
|
"github.com/authelia/authelia/v4/internal/configuration/schema"
|
||||||
"github.com/authelia/authelia/v4/internal/mocks"
|
"github.com/authelia/authelia/v4/internal/mocks"
|
||||||
"github.com/authelia/authelia/v4/internal/models"
|
"github.com/authelia/authelia/v4/internal/model"
|
||||||
"github.com/authelia/authelia/v4/internal/regulation"
|
"github.com/authelia/authelia/v4/internal/regulation"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -57,13 +57,13 @@ func (s *FirstFactorSuite) TestShouldFailIfUserProviderCheckPasswordFail() {
|
||||||
|
|
||||||
s.mock.StorageMock.
|
s.mock.StorageMock.
|
||||||
EXPECT().
|
EXPECT().
|
||||||
AppendAuthenticationLog(s.mock.Ctx, gomock.Eq(models.AuthenticationAttempt{
|
AppendAuthenticationLog(s.mock.Ctx, gomock.Eq(model.AuthenticationAttempt{
|
||||||
Username: "test",
|
Username: "test",
|
||||||
Successful: false,
|
Successful: false,
|
||||||
Banned: false,
|
Banned: false,
|
||||||
Time: s.mock.Clock.Now(),
|
Time: s.mock.Clock.Now(),
|
||||||
Type: regulation.AuthType1FA,
|
Type: regulation.AuthType1FA,
|
||||||
RemoteIP: models.NewNullIPFromString("0.0.0.0"),
|
RemoteIP: model.NewNullIPFromString("0.0.0.0"),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
s.mock.Ctx.Request.SetBodyString(`{
|
s.mock.Ctx.Request.SetBodyString(`{
|
||||||
|
@ -85,13 +85,13 @@ func (s *FirstFactorSuite) TestShouldCheckAuthenticationIsNotMarkedWhenProviderC
|
||||||
|
|
||||||
s.mock.StorageMock.
|
s.mock.StorageMock.
|
||||||
EXPECT().
|
EXPECT().
|
||||||
AppendAuthenticationLog(s.mock.Ctx, gomock.Eq(models.AuthenticationAttempt{
|
AppendAuthenticationLog(s.mock.Ctx, gomock.Eq(model.AuthenticationAttempt{
|
||||||
Username: "test",
|
Username: "test",
|
||||||
Successful: false,
|
Successful: false,
|
||||||
Banned: false,
|
Banned: false,
|
||||||
Time: s.mock.Clock.Now(),
|
Time: s.mock.Clock.Now(),
|
||||||
Type: regulation.AuthType1FA,
|
Type: regulation.AuthType1FA,
|
||||||
RemoteIP: models.NewNullIPFromString("0.0.0.0"),
|
RemoteIP: model.NewNullIPFromString("0.0.0.0"),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
s.mock.Ctx.Request.SetBodyString(`{
|
s.mock.Ctx.Request.SetBodyString(`{
|
||||||
|
@ -111,13 +111,13 @@ func (s *FirstFactorSuite) TestShouldCheckAuthenticationIsMarkedWhenInvalidCrede
|
||||||
|
|
||||||
s.mock.StorageMock.
|
s.mock.StorageMock.
|
||||||
EXPECT().
|
EXPECT().
|
||||||
AppendAuthenticationLog(s.mock.Ctx, gomock.Eq(models.AuthenticationAttempt{
|
AppendAuthenticationLog(s.mock.Ctx, gomock.Eq(model.AuthenticationAttempt{
|
||||||
Username: "test",
|
Username: "test",
|
||||||
Successful: false,
|
Successful: false,
|
||||||
Banned: false,
|
Banned: false,
|
||||||
Time: s.mock.Clock.Now(),
|
Time: s.mock.Clock.Now(),
|
||||||
Type: regulation.AuthType1FA,
|
Type: regulation.AuthType1FA,
|
||||||
RemoteIP: models.NewNullIPFromString("0.0.0.0"),
|
RemoteIP: model.NewNullIPFromString("0.0.0.0"),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
s.mock.Ctx.Request.SetBodyString(`{
|
s.mock.Ctx.Request.SetBodyString(`{
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
|
|
||||||
"github.com/authelia/authelia/v4/internal/duo"
|
"github.com/authelia/authelia/v4/internal/duo"
|
||||||
"github.com/authelia/authelia/v4/internal/middlewares"
|
"github.com/authelia/authelia/v4/internal/middlewares"
|
||||||
"github.com/authelia/authelia/v4/internal/models"
|
"github.com/authelia/authelia/v4/internal/model"
|
||||||
"github.com/authelia/authelia/v4/internal/utils"
|
"github.com/authelia/authelia/v4/internal/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ func SecondFactorDuoDevicePost(ctx *middlewares.AutheliaCtx) {
|
||||||
|
|
||||||
userSession := ctx.GetSession()
|
userSession := ctx.GetSession()
|
||||||
ctx.Logger.Debugf("Save new preferred Duo device and method of user %s to %s using %s", userSession.Username, device.Device, device.Method)
|
ctx.Logger.Debugf("Save new preferred Duo device and method of user %s to %s using %s", userSession.Username, device.Device, device.Method)
|
||||||
err = ctx.Providers.StorageProvider.SavePreferredDuoDevice(ctx, models.DuoDevice{Username: userSession.Username, Device: device.Device, Method: device.Method})
|
err = ctx.Providers.StorageProvider.SavePreferredDuoDevice(ctx, model.DuoDevice{Username: userSession.Username, Device: device.Device, Method: device.Method})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(fmt.Errorf("unable to save new preferred Duo device and method: %s", err), messageMFAValidationFailed)
|
ctx.Error(fmt.Errorf("unable to save new preferred Duo device and method: %s", err), messageMFAValidationFailed)
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
|
|
||||||
"github.com/authelia/authelia/v4/internal/duo"
|
"github.com/authelia/authelia/v4/internal/duo"
|
||||||
"github.com/authelia/authelia/v4/internal/mocks"
|
"github.com/authelia/authelia/v4/internal/mocks"
|
||||||
"github.com/authelia/authelia/v4/internal/models"
|
"github.com/authelia/authelia/v4/internal/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RegisterDuoDeviceSuite struct {
|
type RegisterDuoDeviceSuite struct {
|
||||||
|
@ -129,7 +129,7 @@ func (s *RegisterDuoDeviceSuite) TestShouldRespondWithDeny() {
|
||||||
func (s *RegisterDuoDeviceSuite) TestShouldRespondOK() {
|
func (s *RegisterDuoDeviceSuite) TestShouldRespondOK() {
|
||||||
s.mock.Ctx.Request.SetBodyString("{\"device\":\"1234567890123456\", \"method\":\"push\"}")
|
s.mock.Ctx.Request.SetBodyString("{\"device\":\"1234567890123456\", \"method\":\"push\"}")
|
||||||
s.mock.StorageMock.EXPECT().
|
s.mock.StorageMock.EXPECT().
|
||||||
SavePreferredDuoDevice(gomock.Eq(s.mock.Ctx), gomock.Eq(models.DuoDevice{Username: "john", Device: "1234567890123456", Method: "push"})).
|
SavePreferredDuoDevice(gomock.Eq(s.mock.Ctx), gomock.Eq(model.DuoDevice{Username: "john", Device: "1234567890123456", Method: "push"})).
|
||||||
Return(nil)
|
Return(nil)
|
||||||
|
|
||||||
SecondFactorDuoDevicePost(s.mock.Ctx)
|
SecondFactorDuoDevicePost(s.mock.Ctx)
|
||||||
|
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/authelia/authelia/v4/internal/middlewares"
|
"github.com/authelia/authelia/v4/internal/middlewares"
|
||||||
"github.com/authelia/authelia/v4/internal/models"
|
"github.com/authelia/authelia/v4/internal/model"
|
||||||
"github.com/authelia/authelia/v4/internal/session"
|
"github.com/authelia/authelia/v4/internal/session"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ var SecondFactorTOTPIdentityStart = middlewares.IdentityVerificationStart(middle
|
||||||
|
|
||||||
func secondFactorTOTPIdentityFinish(ctx *middlewares.AutheliaCtx, username string) {
|
func secondFactorTOTPIdentityFinish(ctx *middlewares.AutheliaCtx, username string) {
|
||||||
var (
|
var (
|
||||||
config *models.TOTPConfiguration
|
config *model.TOTPConfiguration
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"github.com/valyala/fasthttp"
|
"github.com/valyala/fasthttp"
|
||||||
|
|
||||||
"github.com/authelia/authelia/v4/internal/middlewares"
|
"github.com/authelia/authelia/v4/internal/middlewares"
|
||||||
"github.com/authelia/authelia/v4/internal/models"
|
"github.com/authelia/authelia/v4/internal/model"
|
||||||
"github.com/authelia/authelia/v4/internal/regulation"
|
"github.com/authelia/authelia/v4/internal/regulation"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ var SecondFactorWebauthnIdentityFinish = middlewares.IdentityVerificationFinish(
|
||||||
func SecondFactorWebauthnAttestationGET(ctx *middlewares.AutheliaCtx, _ string) {
|
func SecondFactorWebauthnAttestationGET(ctx *middlewares.AutheliaCtx, _ string) {
|
||||||
var (
|
var (
|
||||||
w *webauthn.WebAuthn
|
w *webauthn.WebAuthn
|
||||||
user *models.WebauthnUser
|
user *model.WebauthnUser
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ func SecondFactorWebauthnAttestationPOST(ctx *middlewares.AutheliaCtx) {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
w *webauthn.WebAuthn
|
w *webauthn.WebAuthn
|
||||||
user *models.WebauthnUser
|
user *model.WebauthnUser
|
||||||
|
|
||||||
attestationResponse *protocol.ParsedCredentialCreationData
|
attestationResponse *protocol.ParsedCredentialCreationData
|
||||||
credential *webauthn.Credential
|
credential *webauthn.Credential
|
||||||
|
@ -134,7 +134,7 @@ func SecondFactorWebauthnAttestationPOST(ctx *middlewares.AutheliaCtx) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
device := models.NewWebauthnDeviceFromCredential(w.Config.RPID, userSession.Username, "Primary", credential)
|
device := model.NewWebauthnDeviceFromCredential(w.Config.RPID, userSession.Username, "Primary", credential)
|
||||||
|
|
||||||
if err = ctx.Providers.StorageProvider.SaveWebauthnDevice(ctx, device); err != nil {
|
if err = ctx.Providers.StorageProvider.SaveWebauthnDevice(ctx, device); err != nil {
|
||||||
ctx.Logger.Errorf("Unable to load %s devices for assertion challenge for user '%s': %+v", regulation.AuthTypeWebauthn, userSession.Username, err)
|
ctx.Logger.Errorf("Unable to load %s devices for assertion challenge for user '%s': %+v", regulation.AuthTypeWebauthn, userSession.Username, err)
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
|
|
||||||
"github.com/authelia/authelia/v4/internal/duo"
|
"github.com/authelia/authelia/v4/internal/duo"
|
||||||
"github.com/authelia/authelia/v4/internal/middlewares"
|
"github.com/authelia/authelia/v4/internal/middlewares"
|
||||||
"github.com/authelia/authelia/v4/internal/models"
|
"github.com/authelia/authelia/v4/internal/model"
|
||||||
"github.com/authelia/authelia/v4/internal/regulation"
|
"github.com/authelia/authelia/v4/internal/regulation"
|
||||||
"github.com/authelia/authelia/v4/internal/session"
|
"github.com/authelia/authelia/v4/internal/session"
|
||||||
"github.com/authelia/authelia/v4/internal/utils"
|
"github.com/authelia/authelia/v4/internal/utils"
|
||||||
|
@ -235,7 +235,7 @@ func HandleAutoSelection(ctx *middlewares.AutheliaCtx, devices []DuoDevice, user
|
||||||
method := devices[0].Capabilities[0]
|
method := devices[0].Capabilities[0]
|
||||||
ctx.Logger.Debugf("Exactly one device: '%s' and method: '%s' found, saving as new preferred Duo device and method for user: %s", device, method, username)
|
ctx.Logger.Debugf("Exactly one device: '%s' and method: '%s' found, saving as new preferred Duo device and method for user: %s", device, method, username)
|
||||||
|
|
||||||
if err := ctx.Providers.StorageProvider.SavePreferredDuoDevice(ctx, models.DuoDevice{Username: username, Method: method, Device: device}); err != nil {
|
if err := ctx.Providers.StorageProvider.SavePreferredDuoDevice(ctx, model.DuoDevice{Username: username, Method: method, Device: device}); err != nil {
|
||||||
return "", "", fmt.Errorf("unable to save new preferred Duo device and method for user %s: %s", username, err)
|
return "", "", fmt.Errorf("unable to save new preferred Duo device and method for user %s: %s", username, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ import (
|
||||||
|
|
||||||
"github.com/authelia/authelia/v4/internal/duo"
|
"github.com/authelia/authelia/v4/internal/duo"
|
||||||
"github.com/authelia/authelia/v4/internal/mocks"
|
"github.com/authelia/authelia/v4/internal/mocks"
|
||||||
"github.com/authelia/authelia/v4/internal/models"
|
"github.com/authelia/authelia/v4/internal/model"
|
||||||
"github.com/authelia/authelia/v4/internal/regulation"
|
"github.com/authelia/authelia/v4/internal/regulation"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -86,18 +86,18 @@ func (s *SecondFactorDuoPostSuite) TestShouldAutoSelect() {
|
||||||
duoMock.EXPECT().PreAuthCall(s.mock.Ctx, gomock.Eq(values)).Return(&preAuthResponse, nil)
|
duoMock.EXPECT().PreAuthCall(s.mock.Ctx, gomock.Eq(values)).Return(&preAuthResponse, nil)
|
||||||
|
|
||||||
s.mock.StorageMock.EXPECT().
|
s.mock.StorageMock.EXPECT().
|
||||||
SavePreferredDuoDevice(s.mock.Ctx, models.DuoDevice{Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "push"}).
|
SavePreferredDuoDevice(s.mock.Ctx, model.DuoDevice{Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "push"}).
|
||||||
Return(nil)
|
Return(nil)
|
||||||
|
|
||||||
s.mock.StorageMock.
|
s.mock.StorageMock.
|
||||||
EXPECT().
|
EXPECT().
|
||||||
AppendAuthenticationLog(s.mock.Ctx, gomock.Eq(models.AuthenticationAttempt{
|
AppendAuthenticationLog(s.mock.Ctx, gomock.Eq(model.AuthenticationAttempt{
|
||||||
Username: "john",
|
Username: "john",
|
||||||
Successful: true,
|
Successful: true,
|
||||||
Banned: false,
|
Banned: false,
|
||||||
Time: s.mock.Clock.Now(),
|
Time: s.mock.Clock.Now(),
|
||||||
Type: regulation.AuthTypeDuo,
|
Type: regulation.AuthTypeDuo,
|
||||||
RemoteIP: models.NewNullIPFromString("0.0.0.0"),
|
RemoteIP: model.NewNullIPFromString("0.0.0.0"),
|
||||||
})).
|
})).
|
||||||
Return(nil)
|
Return(nil)
|
||||||
|
|
||||||
|
@ -176,7 +176,7 @@ func (s *SecondFactorDuoPostSuite) TestShouldDeleteOldDeviceAndEnroll() {
|
||||||
|
|
||||||
s.mock.StorageMock.EXPECT().
|
s.mock.StorageMock.EXPECT().
|
||||||
LoadPreferredDuoDevice(s.mock.Ctx, "john").
|
LoadPreferredDuoDevice(s.mock.Ctx, "john").
|
||||||
Return(&models.DuoDevice{ID: 1, Username: "john", Device: "NOTEXISTENT", Method: "push"}, nil)
|
Return(&model.DuoDevice{ID: 1, Username: "john", Device: "NOTEXISTENT", Method: "push"}, nil)
|
||||||
|
|
||||||
var enrollURL = "https://api-example.duosecurity.com/portal?code=1234567890ABCDEF&akey=12345ABCDEFGHIJ67890"
|
var enrollURL = "https://api-example.duosecurity.com/portal?code=1234567890ABCDEF&akey=12345ABCDEFGHIJ67890"
|
||||||
|
|
||||||
|
@ -208,7 +208,7 @@ func (s *SecondFactorDuoPostSuite) TestShouldDeleteOldDeviceAndCallPreauthAPIWit
|
||||||
|
|
||||||
s.mock.StorageMock.EXPECT().
|
s.mock.StorageMock.EXPECT().
|
||||||
LoadPreferredDuoDevice(s.mock.Ctx, "john").
|
LoadPreferredDuoDevice(s.mock.Ctx, "john").
|
||||||
Return(&models.DuoDevice{ID: 1, Username: "john", Device: "NOTEXISTENT", Method: "push"}, nil)
|
Return(&model.DuoDevice{ID: 1, Username: "john", Device: "NOTEXISTENT", Method: "push"}, nil)
|
||||||
|
|
||||||
var duoDevices = []duo.Device{
|
var duoDevices = []duo.Device{
|
||||||
{Capabilities: []string{"sms"}, Number: " ", Device: "12345ABCDEFGHIJ67890", DisplayName: "Test Device 1"},
|
{Capabilities: []string{"sms"}, Number: " ", Device: "12345ABCDEFGHIJ67890", DisplayName: "Test Device 1"},
|
||||||
|
@ -241,7 +241,7 @@ func (s *SecondFactorDuoPostSuite) TestShouldUseOldDeviceAndSelect() {
|
||||||
|
|
||||||
s.mock.StorageMock.EXPECT().
|
s.mock.StorageMock.EXPECT().
|
||||||
LoadPreferredDuoDevice(s.mock.Ctx, "john").
|
LoadPreferredDuoDevice(s.mock.Ctx, "john").
|
||||||
Return(&models.DuoDevice{ID: 1, Username: "john", Device: "NOTEXISTENT", Method: "push"}, nil)
|
Return(&model.DuoDevice{ID: 1, Username: "john", Device: "NOTEXISTENT", Method: "push"}, nil)
|
||||||
|
|
||||||
var duoDevices = []duo.Device{
|
var duoDevices = []duo.Device{
|
||||||
{Capabilities: []string{"auto", "push", "sms", "mobile_otp"}, Number: " ", Device: "12345ABCDEFGHIJ67890", DisplayName: "Test Device 1"},
|
{Capabilities: []string{"auto", "push", "sms", "mobile_otp"}, Number: " ", Device: "12345ABCDEFGHIJ67890", DisplayName: "Test Device 1"},
|
||||||
|
@ -276,17 +276,17 @@ func (s *SecondFactorDuoPostSuite) TestShouldUseInvalidMethodAndAutoSelect() {
|
||||||
|
|
||||||
s.mock.StorageMock.EXPECT().
|
s.mock.StorageMock.EXPECT().
|
||||||
LoadPreferredDuoDevice(s.mock.Ctx, "john").
|
LoadPreferredDuoDevice(s.mock.Ctx, "john").
|
||||||
Return(&models.DuoDevice{ID: 1, Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "invalidmethod"}, nil)
|
Return(&model.DuoDevice{ID: 1, Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "invalidmethod"}, nil)
|
||||||
|
|
||||||
s.mock.StorageMock.
|
s.mock.StorageMock.
|
||||||
EXPECT().
|
EXPECT().
|
||||||
AppendAuthenticationLog(s.mock.Ctx, gomock.Eq(models.AuthenticationAttempt{
|
AppendAuthenticationLog(s.mock.Ctx, gomock.Eq(model.AuthenticationAttempt{
|
||||||
Username: "john",
|
Username: "john",
|
||||||
Successful: true,
|
Successful: true,
|
||||||
Banned: false,
|
Banned: false,
|
||||||
Time: s.mock.Clock.Now(),
|
Time: s.mock.Clock.Now(),
|
||||||
Type: regulation.AuthTypeDuo,
|
Type: regulation.AuthTypeDuo,
|
||||||
RemoteIP: models.NewNullIPFromString("0.0.0.0"),
|
RemoteIP: model.NewNullIPFromString("0.0.0.0"),
|
||||||
})).
|
})).
|
||||||
Return(nil)
|
Return(nil)
|
||||||
|
|
||||||
|
@ -304,7 +304,7 @@ func (s *SecondFactorDuoPostSuite) TestShouldUseInvalidMethodAndAutoSelect() {
|
||||||
duoMock.EXPECT().PreAuthCall(s.mock.Ctx, gomock.Eq(values)).Return(&preAuthResponse, nil)
|
duoMock.EXPECT().PreAuthCall(s.mock.Ctx, gomock.Eq(values)).Return(&preAuthResponse, nil)
|
||||||
|
|
||||||
s.mock.StorageMock.EXPECT().
|
s.mock.StorageMock.EXPECT().
|
||||||
SavePreferredDuoDevice(s.mock.Ctx, models.DuoDevice{Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "push"}).
|
SavePreferredDuoDevice(s.mock.Ctx, model.DuoDevice{Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "push"}).
|
||||||
Return(nil)
|
Return(nil)
|
||||||
|
|
||||||
values = url.Values{}
|
values = url.Values{}
|
||||||
|
@ -332,7 +332,7 @@ func (s *SecondFactorDuoPostSuite) TestShouldCallDuoPreauthAPIAndAllowAccess() {
|
||||||
|
|
||||||
s.mock.StorageMock.EXPECT().
|
s.mock.StorageMock.EXPECT().
|
||||||
LoadPreferredDuoDevice(s.mock.Ctx, "john").
|
LoadPreferredDuoDevice(s.mock.Ctx, "john").
|
||||||
Return(&models.DuoDevice{ID: 1, Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "push"}, nil)
|
Return(&model.DuoDevice{ID: 1, Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "push"}, nil)
|
||||||
|
|
||||||
values := url.Values{}
|
values := url.Values{}
|
||||||
values.Set("username", "john")
|
values.Set("username", "john")
|
||||||
|
@ -356,7 +356,7 @@ func (s *SecondFactorDuoPostSuite) TestShouldCallDuoPreauthAPIAndDenyAccess() {
|
||||||
|
|
||||||
s.mock.StorageMock.EXPECT().
|
s.mock.StorageMock.EXPECT().
|
||||||
LoadPreferredDuoDevice(s.mock.Ctx, "john").
|
LoadPreferredDuoDevice(s.mock.Ctx, "john").
|
||||||
Return(&models.DuoDevice{ID: 1, Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "push"}, nil)
|
Return(&model.DuoDevice{ID: 1, Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "push"}, nil)
|
||||||
|
|
||||||
values := url.Values{}
|
values := url.Values{}
|
||||||
values.Set("username", "john")
|
values.Set("username", "john")
|
||||||
|
@ -386,7 +386,7 @@ func (s *SecondFactorDuoPostSuite) TestShouldCallDuoPreauthAPIAndFail() {
|
||||||
|
|
||||||
s.mock.StorageMock.EXPECT().
|
s.mock.StorageMock.EXPECT().
|
||||||
LoadPreferredDuoDevice(s.mock.Ctx, "john").
|
LoadPreferredDuoDevice(s.mock.Ctx, "john").
|
||||||
Return(&models.DuoDevice{ID: 1, Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "push"}, nil)
|
Return(&model.DuoDevice{ID: 1, Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "push"}, nil)
|
||||||
|
|
||||||
duoMock.EXPECT().PreAuthCall(s.mock.Ctx, gomock.Any()).Return(nil, fmt.Errorf("Connnection error"))
|
duoMock.EXPECT().PreAuthCall(s.mock.Ctx, gomock.Any()).Return(nil, fmt.Errorf("Connnection error"))
|
||||||
|
|
||||||
|
@ -404,17 +404,17 @@ func (s *SecondFactorDuoPostSuite) TestShouldCallDuoAPIAndDenyAccess() {
|
||||||
|
|
||||||
s.mock.StorageMock.EXPECT().
|
s.mock.StorageMock.EXPECT().
|
||||||
LoadPreferredDuoDevice(s.mock.Ctx, "john").
|
LoadPreferredDuoDevice(s.mock.Ctx, "john").
|
||||||
Return(&models.DuoDevice{ID: 1, Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "push"}, nil)
|
Return(&model.DuoDevice{ID: 1, Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "push"}, nil)
|
||||||
|
|
||||||
s.mock.StorageMock.
|
s.mock.StorageMock.
|
||||||
EXPECT().
|
EXPECT().
|
||||||
AppendAuthenticationLog(s.mock.Ctx, gomock.Eq(models.AuthenticationAttempt{
|
AppendAuthenticationLog(s.mock.Ctx, gomock.Eq(model.AuthenticationAttempt{
|
||||||
Username: "john",
|
Username: "john",
|
||||||
Successful: false,
|
Successful: false,
|
||||||
Banned: false,
|
Banned: false,
|
||||||
Time: s.mock.Clock.Now(),
|
Time: s.mock.Clock.Now(),
|
||||||
Type: regulation.AuthTypeDuo,
|
Type: regulation.AuthTypeDuo,
|
||||||
RemoteIP: models.NewNullIPFromString("0.0.0.0"),
|
RemoteIP: model.NewNullIPFromString("0.0.0.0"),
|
||||||
})).
|
})).
|
||||||
Return(nil)
|
Return(nil)
|
||||||
|
|
||||||
|
@ -456,7 +456,7 @@ func (s *SecondFactorDuoPostSuite) TestShouldCallDuoAPIAndFail() {
|
||||||
|
|
||||||
s.mock.StorageMock.EXPECT().
|
s.mock.StorageMock.EXPECT().
|
||||||
LoadPreferredDuoDevice(s.mock.Ctx, "john").
|
LoadPreferredDuoDevice(s.mock.Ctx, "john").
|
||||||
Return(&models.DuoDevice{ID: 1, Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "push"}, nil)
|
Return(&model.DuoDevice{ID: 1, Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "push"}, nil)
|
||||||
|
|
||||||
var duoDevices = []duo.Device{
|
var duoDevices = []duo.Device{
|
||||||
{Capabilities: []string{"auto", "push", "sms", "mobile_otp"}, Number: " ", Device: "12345ABCDEFGHIJ67890", DisplayName: "Test Device 1"},
|
{Capabilities: []string{"auto", "push", "sms", "mobile_otp"}, Number: " ", Device: "12345ABCDEFGHIJ67890", DisplayName: "Test Device 1"},
|
||||||
|
@ -487,17 +487,17 @@ func (s *SecondFactorDuoPostSuite) TestShouldRedirectUserToDefaultURL() {
|
||||||
|
|
||||||
s.mock.StorageMock.EXPECT().
|
s.mock.StorageMock.EXPECT().
|
||||||
LoadPreferredDuoDevice(s.mock.Ctx, "john").
|
LoadPreferredDuoDevice(s.mock.Ctx, "john").
|
||||||
Return(&models.DuoDevice{ID: 1, Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "push"}, nil)
|
Return(&model.DuoDevice{ID: 1, Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "push"}, nil)
|
||||||
|
|
||||||
s.mock.StorageMock.
|
s.mock.StorageMock.
|
||||||
EXPECT().
|
EXPECT().
|
||||||
AppendAuthenticationLog(s.mock.Ctx, gomock.Eq(models.AuthenticationAttempt{
|
AppendAuthenticationLog(s.mock.Ctx, gomock.Eq(model.AuthenticationAttempt{
|
||||||
Username: "john",
|
Username: "john",
|
||||||
Successful: true,
|
Successful: true,
|
||||||
Banned: false,
|
Banned: false,
|
||||||
Time: s.mock.Clock.Now(),
|
Time: s.mock.Clock.Now(),
|
||||||
Type: regulation.AuthTypeDuo,
|
Type: regulation.AuthTypeDuo,
|
||||||
RemoteIP: models.NewNullIPFromString("0.0.0.0"),
|
RemoteIP: model.NewNullIPFromString("0.0.0.0"),
|
||||||
})).
|
})).
|
||||||
Return(nil)
|
Return(nil)
|
||||||
|
|
||||||
|
@ -536,17 +536,17 @@ func (s *SecondFactorDuoPostSuite) TestShouldNotReturnRedirectURL() {
|
||||||
|
|
||||||
s.mock.StorageMock.EXPECT().
|
s.mock.StorageMock.EXPECT().
|
||||||
LoadPreferredDuoDevice(s.mock.Ctx, "john").
|
LoadPreferredDuoDevice(s.mock.Ctx, "john").
|
||||||
Return(&models.DuoDevice{ID: 1, Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "push"}, nil)
|
Return(&model.DuoDevice{ID: 1, Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "push"}, nil)
|
||||||
|
|
||||||
s.mock.StorageMock.
|
s.mock.StorageMock.
|
||||||
EXPECT().
|
EXPECT().
|
||||||
AppendAuthenticationLog(s.mock.Ctx, gomock.Eq(models.AuthenticationAttempt{
|
AppendAuthenticationLog(s.mock.Ctx, gomock.Eq(model.AuthenticationAttempt{
|
||||||
Username: "john",
|
Username: "john",
|
||||||
Successful: true,
|
Successful: true,
|
||||||
Banned: false,
|
Banned: false,
|
||||||
Time: s.mock.Clock.Now(),
|
Time: s.mock.Clock.Now(),
|
||||||
Type: regulation.AuthTypeDuo,
|
Type: regulation.AuthTypeDuo,
|
||||||
RemoteIP: models.NewNullIPFromString("0.0.0.0"),
|
RemoteIP: model.NewNullIPFromString("0.0.0.0"),
|
||||||
})).
|
})).
|
||||||
Return(nil)
|
Return(nil)
|
||||||
|
|
||||||
|
@ -581,17 +581,17 @@ func (s *SecondFactorDuoPostSuite) TestShouldRedirectUserToSafeTargetURL() {
|
||||||
|
|
||||||
s.mock.StorageMock.EXPECT().
|
s.mock.StorageMock.EXPECT().
|
||||||
LoadPreferredDuoDevice(s.mock.Ctx, "john").
|
LoadPreferredDuoDevice(s.mock.Ctx, "john").
|
||||||
Return(&models.DuoDevice{ID: 1, Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "push"}, nil)
|
Return(&model.DuoDevice{ID: 1, Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "push"}, nil)
|
||||||
|
|
||||||
s.mock.StorageMock.
|
s.mock.StorageMock.
|
||||||
EXPECT().
|
EXPECT().
|
||||||
AppendAuthenticationLog(s.mock.Ctx, gomock.Eq(models.AuthenticationAttempt{
|
AppendAuthenticationLog(s.mock.Ctx, gomock.Eq(model.AuthenticationAttempt{
|
||||||
Username: "john",
|
Username: "john",
|
||||||
Successful: true,
|
Successful: true,
|
||||||
Banned: false,
|
Banned: false,
|
||||||
Time: s.mock.Clock.Now(),
|
Time: s.mock.Clock.Now(),
|
||||||
Type: regulation.AuthTypeDuo,
|
Type: regulation.AuthTypeDuo,
|
||||||
RemoteIP: models.NewNullIPFromString("0.0.0.0"),
|
RemoteIP: model.NewNullIPFromString("0.0.0.0"),
|
||||||
})).
|
})).
|
||||||
Return(nil)
|
Return(nil)
|
||||||
|
|
||||||
|
@ -630,17 +630,17 @@ func (s *SecondFactorDuoPostSuite) TestShouldNotRedirectToUnsafeURL() {
|
||||||
|
|
||||||
s.mock.StorageMock.EXPECT().
|
s.mock.StorageMock.EXPECT().
|
||||||
LoadPreferredDuoDevice(s.mock.Ctx, "john").
|
LoadPreferredDuoDevice(s.mock.Ctx, "john").
|
||||||
Return(&models.DuoDevice{ID: 1, Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "push"}, nil)
|
Return(&model.DuoDevice{ID: 1, Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "push"}, nil)
|
||||||
|
|
||||||
s.mock.StorageMock.
|
s.mock.StorageMock.
|
||||||
EXPECT().
|
EXPECT().
|
||||||
AppendAuthenticationLog(s.mock.Ctx, gomock.Eq(models.AuthenticationAttempt{
|
AppendAuthenticationLog(s.mock.Ctx, gomock.Eq(model.AuthenticationAttempt{
|
||||||
Username: "john",
|
Username: "john",
|
||||||
Successful: true,
|
Successful: true,
|
||||||
Banned: false,
|
Banned: false,
|
||||||
Time: s.mock.Clock.Now(),
|
Time: s.mock.Clock.Now(),
|
||||||
Type: regulation.AuthTypeDuo,
|
Type: regulation.AuthTypeDuo,
|
||||||
RemoteIP: models.NewNullIPFromString("0.0.0.0"),
|
RemoteIP: model.NewNullIPFromString("0.0.0.0"),
|
||||||
})).
|
})).
|
||||||
Return(nil)
|
Return(nil)
|
||||||
|
|
||||||
|
@ -677,17 +677,17 @@ func (s *SecondFactorDuoPostSuite) TestShouldRegenerateSessionForPreventingSessi
|
||||||
|
|
||||||
s.mock.StorageMock.EXPECT().
|
s.mock.StorageMock.EXPECT().
|
||||||
LoadPreferredDuoDevice(s.mock.Ctx, "john").
|
LoadPreferredDuoDevice(s.mock.Ctx, "john").
|
||||||
Return(&models.DuoDevice{ID: 1, Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "push"}, nil)
|
Return(&model.DuoDevice{ID: 1, Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "push"}, nil)
|
||||||
|
|
||||||
s.mock.StorageMock.
|
s.mock.StorageMock.
|
||||||
EXPECT().
|
EXPECT().
|
||||||
AppendAuthenticationLog(s.mock.Ctx, gomock.Eq(models.AuthenticationAttempt{
|
AppendAuthenticationLog(s.mock.Ctx, gomock.Eq(model.AuthenticationAttempt{
|
||||||
Username: "john",
|
Username: "john",
|
||||||
Successful: true,
|
Successful: true,
|
||||||
Banned: false,
|
Banned: false,
|
||||||
Time: s.mock.Clock.Now(),
|
Time: s.mock.Clock.Now(),
|
||||||
Type: regulation.AuthTypeDuo,
|
Type: regulation.AuthTypeDuo,
|
||||||
RemoteIP: models.NewNullIPFromString("0.0.0.0"),
|
RemoteIP: model.NewNullIPFromString("0.0.0.0"),
|
||||||
})).
|
})).
|
||||||
Return(nil)
|
Return(nil)
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
|
|
||||||
"github.com/authelia/authelia/v4/internal/mocks"
|
"github.com/authelia/authelia/v4/internal/mocks"
|
||||||
"github.com/authelia/authelia/v4/internal/models"
|
"github.com/authelia/authelia/v4/internal/model"
|
||||||
"github.com/authelia/authelia/v4/internal/regulation"
|
"github.com/authelia/authelia/v4/internal/regulation"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ func (s *HandlerSignTOTPSuite) TearDownTest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HandlerSignTOTPSuite) TestShouldRedirectUserToDefaultURL() {
|
func (s *HandlerSignTOTPSuite) TestShouldRedirectUserToDefaultURL() {
|
||||||
config := models.TOTPConfiguration{ID: 1, Username: "john", Digits: 6, Secret: []byte("secret"), Period: 30, Algorithm: "SHA1"}
|
config := model.TOTPConfiguration{ID: 1, Username: "john", Digits: 6, Secret: []byte("secret"), Period: 30, Algorithm: "SHA1"}
|
||||||
|
|
||||||
s.mock.StorageMock.EXPECT().
|
s.mock.StorageMock.EXPECT().
|
||||||
LoadTOTPConfiguration(s.mock.Ctx, gomock.Any()).
|
LoadTOTPConfiguration(s.mock.Ctx, gomock.Any()).
|
||||||
|
@ -42,13 +42,13 @@ func (s *HandlerSignTOTPSuite) TestShouldRedirectUserToDefaultURL() {
|
||||||
|
|
||||||
s.mock.StorageMock.
|
s.mock.StorageMock.
|
||||||
EXPECT().
|
EXPECT().
|
||||||
AppendAuthenticationLog(s.mock.Ctx, gomock.Eq(models.AuthenticationAttempt{
|
AppendAuthenticationLog(s.mock.Ctx, gomock.Eq(model.AuthenticationAttempt{
|
||||||
Username: "john",
|
Username: "john",
|
||||||
Successful: true,
|
Successful: true,
|
||||||
Banned: false,
|
Banned: false,
|
||||||
Time: s.mock.Clock.Now(),
|
Time: s.mock.Clock.Now(),
|
||||||
Type: regulation.AuthTypeTOTP,
|
Type: regulation.AuthTypeTOTP,
|
||||||
RemoteIP: models.NewNullIPFromString("0.0.0.0"),
|
RemoteIP: model.NewNullIPFromString("0.0.0.0"),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
s.mock.TOTPMock.EXPECT().Validate(gomock.Eq("abc"), gomock.Eq(&config)).Return(true, nil)
|
s.mock.TOTPMock.EXPECT().Validate(gomock.Eq("abc"), gomock.Eq(&config)).Return(true, nil)
|
||||||
|
@ -72,7 +72,7 @@ func (s *HandlerSignTOTPSuite) TestShouldRedirectUserToDefaultURL() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HandlerSignTOTPSuite) TestShouldFailWhenTOTPSignInInfoFailsToUpdate() {
|
func (s *HandlerSignTOTPSuite) TestShouldFailWhenTOTPSignInInfoFailsToUpdate() {
|
||||||
config := models.TOTPConfiguration{ID: 1, Username: "john", Digits: 6, Secret: []byte("secret"), Period: 30, Algorithm: "SHA1"}
|
config := model.TOTPConfiguration{ID: 1, Username: "john", Digits: 6, Secret: []byte("secret"), Period: 30, Algorithm: "SHA1"}
|
||||||
|
|
||||||
s.mock.StorageMock.EXPECT().
|
s.mock.StorageMock.EXPECT().
|
||||||
LoadTOTPConfiguration(s.mock.Ctx, gomock.Any()).
|
LoadTOTPConfiguration(s.mock.Ctx, gomock.Any()).
|
||||||
|
@ -80,13 +80,13 @@ func (s *HandlerSignTOTPSuite) TestShouldFailWhenTOTPSignInInfoFailsToUpdate() {
|
||||||
|
|
||||||
s.mock.StorageMock.
|
s.mock.StorageMock.
|
||||||
EXPECT().
|
EXPECT().
|
||||||
AppendAuthenticationLog(s.mock.Ctx, gomock.Eq(models.AuthenticationAttempt{
|
AppendAuthenticationLog(s.mock.Ctx, gomock.Eq(model.AuthenticationAttempt{
|
||||||
Username: "john",
|
Username: "john",
|
||||||
Successful: true,
|
Successful: true,
|
||||||
Banned: false,
|
Banned: false,
|
||||||
Time: s.mock.Clock.Now(),
|
Time: s.mock.Clock.Now(),
|
||||||
Type: regulation.AuthTypeTOTP,
|
Type: regulation.AuthTypeTOTP,
|
||||||
RemoteIP: models.NewNullIPFromString("0.0.0.0"),
|
RemoteIP: model.NewNullIPFromString("0.0.0.0"),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
s.mock.TOTPMock.EXPECT().Validate(gomock.Eq("abc"), gomock.Eq(&config)).Return(true, nil)
|
s.mock.TOTPMock.EXPECT().Validate(gomock.Eq("abc"), gomock.Eq(&config)).Return(true, nil)
|
||||||
|
@ -108,7 +108,7 @@ func (s *HandlerSignTOTPSuite) TestShouldFailWhenTOTPSignInInfoFailsToUpdate() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HandlerSignTOTPSuite) TestShouldNotReturnRedirectURL() {
|
func (s *HandlerSignTOTPSuite) TestShouldNotReturnRedirectURL() {
|
||||||
config := models.TOTPConfiguration{ID: 1, Username: "john", Digits: 6, Secret: []byte("secret"), Period: 30, Algorithm: "SHA1"}
|
config := model.TOTPConfiguration{ID: 1, Username: "john", Digits: 6, Secret: []byte("secret"), Period: 30, Algorithm: "SHA1"}
|
||||||
|
|
||||||
s.mock.StorageMock.EXPECT().
|
s.mock.StorageMock.EXPECT().
|
||||||
LoadTOTPConfiguration(s.mock.Ctx, gomock.Any()).
|
LoadTOTPConfiguration(s.mock.Ctx, gomock.Any()).
|
||||||
|
@ -116,13 +116,13 @@ func (s *HandlerSignTOTPSuite) TestShouldNotReturnRedirectURL() {
|
||||||
|
|
||||||
s.mock.StorageMock.
|
s.mock.StorageMock.
|
||||||
EXPECT().
|
EXPECT().
|
||||||
AppendAuthenticationLog(s.mock.Ctx, gomock.Eq(models.AuthenticationAttempt{
|
AppendAuthenticationLog(s.mock.Ctx, gomock.Eq(model.AuthenticationAttempt{
|
||||||
Username: "john",
|
Username: "john",
|
||||||
Successful: true,
|
Successful: true,
|
||||||
Banned: false,
|
Banned: false,
|
||||||
Time: s.mock.Clock.Now(),
|
Time: s.mock.Clock.Now(),
|
||||||
Type: regulation.AuthTypeTOTP,
|
Type: regulation.AuthTypeTOTP,
|
||||||
RemoteIP: models.NewNullIPFromString("0.0.0.0"),
|
RemoteIP: model.NewNullIPFromString("0.0.0.0"),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
s.mock.TOTPMock.EXPECT().Validate(gomock.Eq("abc"), gomock.Eq(&config)).Return(true, nil)
|
s.mock.TOTPMock.EXPECT().Validate(gomock.Eq("abc"), gomock.Eq(&config)).Return(true, nil)
|
||||||
|
@ -142,7 +142,7 @@ func (s *HandlerSignTOTPSuite) TestShouldNotReturnRedirectURL() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HandlerSignTOTPSuite) TestShouldRedirectUserToSafeTargetURL() {
|
func (s *HandlerSignTOTPSuite) TestShouldRedirectUserToSafeTargetURL() {
|
||||||
config := models.TOTPConfiguration{ID: 1, Username: "john", Digits: 6, Secret: []byte("secret"), Period: 30, Algorithm: "SHA1"}
|
config := model.TOTPConfiguration{ID: 1, Username: "john", Digits: 6, Secret: []byte("secret"), Period: 30, Algorithm: "SHA1"}
|
||||||
|
|
||||||
s.mock.StorageMock.EXPECT().
|
s.mock.StorageMock.EXPECT().
|
||||||
LoadTOTPConfiguration(s.mock.Ctx, gomock.Any()).
|
LoadTOTPConfiguration(s.mock.Ctx, gomock.Any()).
|
||||||
|
@ -150,13 +150,13 @@ func (s *HandlerSignTOTPSuite) TestShouldRedirectUserToSafeTargetURL() {
|
||||||
|
|
||||||
s.mock.StorageMock.
|
s.mock.StorageMock.
|
||||||
EXPECT().
|
EXPECT().
|
||||||
AppendAuthenticationLog(s.mock.Ctx, gomock.Eq(models.AuthenticationAttempt{
|
AppendAuthenticationLog(s.mock.Ctx, gomock.Eq(model.AuthenticationAttempt{
|
||||||
Username: "john",
|
Username: "john",
|
||||||
Successful: true,
|
Successful: true,
|
||||||
Banned: false,
|
Banned: false,
|
||||||
Time: s.mock.Clock.Now(),
|
Time: s.mock.Clock.Now(),
|
||||||
Type: regulation.AuthTypeTOTP,
|
Type: regulation.AuthTypeTOTP,
|
||||||
RemoteIP: models.NewNullIPFromString("0.0.0.0"),
|
RemoteIP: model.NewNullIPFromString("0.0.0.0"),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
s.mock.TOTPMock.EXPECT().Validate(gomock.Eq("abc"), gomock.Eq(&config)).Return(true, nil)
|
s.mock.TOTPMock.EXPECT().Validate(gomock.Eq("abc"), gomock.Eq(&config)).Return(true, nil)
|
||||||
|
@ -182,17 +182,17 @@ func (s *HandlerSignTOTPSuite) TestShouldRedirectUserToSafeTargetURL() {
|
||||||
func (s *HandlerSignTOTPSuite) TestShouldNotRedirectToUnsafeURL() {
|
func (s *HandlerSignTOTPSuite) TestShouldNotRedirectToUnsafeURL() {
|
||||||
s.mock.StorageMock.EXPECT().
|
s.mock.StorageMock.EXPECT().
|
||||||
LoadTOTPConfiguration(s.mock.Ctx, "john").
|
LoadTOTPConfiguration(s.mock.Ctx, "john").
|
||||||
Return(&models.TOTPConfiguration{Secret: []byte("secret")}, nil)
|
Return(&model.TOTPConfiguration{Secret: []byte("secret")}, nil)
|
||||||
|
|
||||||
s.mock.StorageMock.
|
s.mock.StorageMock.
|
||||||
EXPECT().
|
EXPECT().
|
||||||
AppendAuthenticationLog(s.mock.Ctx, gomock.Eq(models.AuthenticationAttempt{
|
AppendAuthenticationLog(s.mock.Ctx, gomock.Eq(model.AuthenticationAttempt{
|
||||||
Username: "john",
|
Username: "john",
|
||||||
Successful: true,
|
Successful: true,
|
||||||
Banned: false,
|
Banned: false,
|
||||||
Time: s.mock.Clock.Now(),
|
Time: s.mock.Clock.Now(),
|
||||||
Type: regulation.AuthTypeTOTP,
|
Type: regulation.AuthTypeTOTP,
|
||||||
RemoteIP: models.NewNullIPFromString("0.0.0.0"),
|
RemoteIP: model.NewNullIPFromString("0.0.0.0"),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
s.mock.StorageMock.
|
s.mock.StorageMock.
|
||||||
|
@ -200,7 +200,7 @@ func (s *HandlerSignTOTPSuite) TestShouldNotRedirectToUnsafeURL() {
|
||||||
UpdateTOTPConfigurationSignIn(s.mock.Ctx, gomock.Any(), gomock.Any())
|
UpdateTOTPConfigurationSignIn(s.mock.Ctx, gomock.Any(), gomock.Any())
|
||||||
|
|
||||||
s.mock.TOTPMock.EXPECT().
|
s.mock.TOTPMock.EXPECT().
|
||||||
Validate(gomock.Eq("abc"), gomock.Eq(&models.TOTPConfiguration{Secret: []byte("secret")})).
|
Validate(gomock.Eq("abc"), gomock.Eq(&model.TOTPConfiguration{Secret: []byte("secret")})).
|
||||||
Return(true, nil)
|
Return(true, nil)
|
||||||
|
|
||||||
bodyBytes, err := json.Marshal(signTOTPRequestBody{
|
bodyBytes, err := json.Marshal(signTOTPRequestBody{
|
||||||
|
@ -216,7 +216,7 @@ func (s *HandlerSignTOTPSuite) TestShouldNotRedirectToUnsafeURL() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HandlerSignTOTPSuite) TestShouldRegenerateSessionForPreventingSessionFixation() {
|
func (s *HandlerSignTOTPSuite) TestShouldRegenerateSessionForPreventingSessionFixation() {
|
||||||
config := models.TOTPConfiguration{ID: 1, Username: "john", Digits: 6, Secret: []byte("secret"), Period: 30, Algorithm: "SHA1"}
|
config := model.TOTPConfiguration{ID: 1, Username: "john", Digits: 6, Secret: []byte("secret"), Period: 30, Algorithm: "SHA1"}
|
||||||
|
|
||||||
s.mock.StorageMock.EXPECT().
|
s.mock.StorageMock.EXPECT().
|
||||||
LoadTOTPConfiguration(s.mock.Ctx, gomock.Any()).
|
LoadTOTPConfiguration(s.mock.Ctx, gomock.Any()).
|
||||||
|
@ -224,13 +224,13 @@ func (s *HandlerSignTOTPSuite) TestShouldRegenerateSessionForPreventingSessionFi
|
||||||
|
|
||||||
s.mock.StorageMock.
|
s.mock.StorageMock.
|
||||||
EXPECT().
|
EXPECT().
|
||||||
AppendAuthenticationLog(s.mock.Ctx, gomock.Eq(models.AuthenticationAttempt{
|
AppendAuthenticationLog(s.mock.Ctx, gomock.Eq(model.AuthenticationAttempt{
|
||||||
Username: "john",
|
Username: "john",
|
||||||
Successful: true,
|
Successful: true,
|
||||||
Banned: false,
|
Banned: false,
|
||||||
Time: s.mock.Clock.Now(),
|
Time: s.mock.Clock.Now(),
|
||||||
Type: regulation.AuthTypeTOTP,
|
Type: regulation.AuthTypeTOTP,
|
||||||
RemoteIP: models.NewNullIPFromString("0.0.0.0"),
|
RemoteIP: model.NewNullIPFromString("0.0.0.0"),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
s.mock.TOTPMock.EXPECT().
|
s.mock.TOTPMock.EXPECT().
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"github.com/go-webauthn/webauthn/webauthn"
|
"github.com/go-webauthn/webauthn/webauthn"
|
||||||
|
|
||||||
"github.com/authelia/authelia/v4/internal/middlewares"
|
"github.com/authelia/authelia/v4/internal/middlewares"
|
||||||
"github.com/authelia/authelia/v4/internal/models"
|
"github.com/authelia/authelia/v4/internal/model"
|
||||||
"github.com/authelia/authelia/v4/internal/regulation"
|
"github.com/authelia/authelia/v4/internal/regulation"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ import (
|
||||||
func SecondFactorWebauthnAssertionGET(ctx *middlewares.AutheliaCtx) {
|
func SecondFactorWebauthnAssertionGET(ctx *middlewares.AutheliaCtx) {
|
||||||
var (
|
var (
|
||||||
w *webauthn.WebAuthn
|
w *webauthn.WebAuthn
|
||||||
user *models.WebauthnUser
|
user *model.WebauthnUser
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ func SecondFactorWebauthnAssertionPOST(ctx *middlewares.AutheliaCtx) {
|
||||||
var (
|
var (
|
||||||
assertionResponse *protocol.ParsedCredentialAssertionData
|
assertionResponse *protocol.ParsedCredentialAssertionData
|
||||||
credential *webauthn.Credential
|
credential *webauthn.Credential
|
||||||
user *models.WebauthnUser
|
user *model.WebauthnUser
|
||||||
)
|
)
|
||||||
|
|
||||||
if assertionResponse, err = protocol.ParseCredentialRequestResponseBody(bytes.NewReader(ctx.PostBody())); err != nil {
|
if assertionResponse, err = protocol.ParseCredentialRequestResponseBody(bytes.NewReader(ctx.PostBody())); err != nil {
|
||||||
|
|
|
@ -13,7 +13,7 @@ import (
|
||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
|
|
||||||
"github.com/authelia/authelia/v4/internal/mocks"
|
"github.com/authelia/authelia/v4/internal/mocks"
|
||||||
"github.com/authelia/authelia/v4/internal/models"
|
"github.com/authelia/authelia/v4/internal/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FetchSuite struct {
|
type FetchSuite struct {
|
||||||
|
@ -36,21 +36,21 @@ func (s *FetchSuite) TearDownTest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
type expectedResponse struct {
|
type expectedResponse struct {
|
||||||
db models.UserInfo
|
db model.UserInfo
|
||||||
api *models.UserInfo
|
api *model.UserInfo
|
||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMethodSetToU2F(t *testing.T) {
|
func TestMethodSetToU2F(t *testing.T) {
|
||||||
expectedResponses := []expectedResponse{
|
expectedResponses := []expectedResponse{
|
||||||
{
|
{
|
||||||
db: models.UserInfo{
|
db: model.UserInfo{
|
||||||
Method: "totp",
|
Method: "totp",
|
||||||
},
|
},
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
db: models.UserInfo{
|
db: model.UserInfo{
|
||||||
Method: "webauthn",
|
Method: "webauthn",
|
||||||
HasWebauthn: true,
|
HasWebauthn: true,
|
||||||
HasTOTP: true,
|
HasTOTP: true,
|
||||||
|
@ -58,7 +58,7 @@ func TestMethodSetToU2F(t *testing.T) {
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
db: models.UserInfo{
|
db: model.UserInfo{
|
||||||
Method: "webauthn",
|
Method: "webauthn",
|
||||||
HasWebauthn: true,
|
HasWebauthn: true,
|
||||||
HasTOTP: false,
|
HasTOTP: false,
|
||||||
|
@ -66,7 +66,7 @@ func TestMethodSetToU2F(t *testing.T) {
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
db: models.UserInfo{
|
db: model.UserInfo{
|
||||||
Method: "mobile_push",
|
Method: "mobile_push",
|
||||||
HasWebauthn: false,
|
HasWebauthn: false,
|
||||||
HasTOTP: false,
|
HasTOTP: false,
|
||||||
|
@ -74,11 +74,11 @@ func TestMethodSetToU2F(t *testing.T) {
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
db: models.UserInfo{},
|
db: model.UserInfo{},
|
||||||
err: sql.ErrNoRows,
|
err: sql.ErrNoRows,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
db: models.UserInfo{},
|
db: model.UserInfo{},
|
||||||
err: errors.New("invalid thing"),
|
err: errors.New("invalid thing"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -108,7 +108,7 @@ func TestMethodSetToU2F(t *testing.T) {
|
||||||
assert.Equal(t, 200, mock.Ctx.Response.StatusCode())
|
assert.Equal(t, 200, mock.Ctx.Response.StatusCode())
|
||||||
})
|
})
|
||||||
|
|
||||||
actualPreferences := models.UserInfo{}
|
actualPreferences := model.UserInfo{}
|
||||||
|
|
||||||
mock.GetResponseData(t, &actualPreferences)
|
mock.GetResponseData(t, &actualPreferences)
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ func TestMethodSetToU2F(t *testing.T) {
|
||||||
func (s *FetchSuite) TestShouldReturnError500WhenStorageFailsToLoad() {
|
func (s *FetchSuite) TestShouldReturnError500WhenStorageFailsToLoad() {
|
||||||
s.mock.StorageMock.EXPECT().
|
s.mock.StorageMock.EXPECT().
|
||||||
LoadUserInfo(s.mock.Ctx, gomock.Eq("john")).
|
LoadUserInfo(s.mock.Ctx, gomock.Eq("john")).
|
||||||
Return(models.UserInfo{}, fmt.Errorf("failure"))
|
Return(model.UserInfo{}, fmt.Errorf("failure"))
|
||||||
|
|
||||||
UserInfoGet(s.mock.Ctx)
|
UserInfoGet(s.mock.Ctx)
|
||||||
|
|
||||||
|
|
|
@ -8,12 +8,12 @@ import (
|
||||||
"github.com/go-webauthn/webauthn/webauthn"
|
"github.com/go-webauthn/webauthn/webauthn"
|
||||||
|
|
||||||
"github.com/authelia/authelia/v4/internal/middlewares"
|
"github.com/authelia/authelia/v4/internal/middlewares"
|
||||||
"github.com/authelia/authelia/v4/internal/models"
|
"github.com/authelia/authelia/v4/internal/model"
|
||||||
"github.com/authelia/authelia/v4/internal/session"
|
"github.com/authelia/authelia/v4/internal/session"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getWebAuthnUser(ctx *middlewares.AutheliaCtx, userSession session.UserSession) (user *models.WebauthnUser, err error) {
|
func getWebAuthnUser(ctx *middlewares.AutheliaCtx, userSession session.UserSession) (user *model.WebauthnUser, err error) {
|
||||||
user = &models.WebauthnUser{
|
user = &model.WebauthnUser{
|
||||||
Username: userSession.Username,
|
Username: userSession.Username,
|
||||||
DisplayName: userSession.DisplayName,
|
DisplayName: userSession.DisplayName,
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/authelia/authelia/v4/internal/mocks"
|
"github.com/authelia/authelia/v4/internal/mocks"
|
||||||
"github.com/authelia/authelia/v4/internal/models"
|
"github.com/authelia/authelia/v4/internal/model"
|
||||||
"github.com/authelia/authelia/v4/internal/session"
|
"github.com/authelia/authelia/v4/internal/session"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -21,13 +21,13 @@ func TestWebauthnGetUser(t *testing.T) {
|
||||||
DisplayName: "John Smith",
|
DisplayName: "John Smith",
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.StorageMock.EXPECT().LoadWebauthnDevicesByUsername(ctx.Ctx, "john").Return([]models.WebauthnDevice{
|
ctx.StorageMock.EXPECT().LoadWebauthnDevicesByUsername(ctx.Ctx, "john").Return([]model.WebauthnDevice{
|
||||||
{
|
{
|
||||||
ID: 1,
|
ID: 1,
|
||||||
RPID: "https://example.com",
|
RPID: "https://example.com",
|
||||||
Username: "john",
|
Username: "john",
|
||||||
Description: "Primary",
|
Description: "Primary",
|
||||||
KID: models.NewBase64([]byte("abc123")),
|
KID: model.NewBase64([]byte("abc123")),
|
||||||
AttestationType: "fido-u2f",
|
AttestationType: "fido-u2f",
|
||||||
PublicKey: []byte("data"),
|
PublicKey: []byte("data"),
|
||||||
SignCount: 0,
|
SignCount: 0,
|
||||||
|
@ -38,7 +38,7 @@ func TestWebauthnGetUser(t *testing.T) {
|
||||||
RPID: "example.com",
|
RPID: "example.com",
|
||||||
Username: "john",
|
Username: "john",
|
||||||
Description: "Secondary",
|
Description: "Secondary",
|
||||||
KID: models.NewBase64([]byte("123abc")),
|
KID: model.NewBase64([]byte("123abc")),
|
||||||
AttestationType: "packed",
|
AttestationType: "packed",
|
||||||
Transport: "usb,nfc",
|
Transport: "usb,nfc",
|
||||||
PublicKey: []byte("data"),
|
PublicKey: []byte("data"),
|
||||||
|
@ -106,13 +106,13 @@ func TestWebauthnGetUserWithoutDisplayName(t *testing.T) {
|
||||||
Username: "john",
|
Username: "john",
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.StorageMock.EXPECT().LoadWebauthnDevicesByUsername(ctx.Ctx, "john").Return([]models.WebauthnDevice{
|
ctx.StorageMock.EXPECT().LoadWebauthnDevicesByUsername(ctx.Ctx, "john").Return([]model.WebauthnDevice{
|
||||||
{
|
{
|
||||||
ID: 1,
|
ID: 1,
|
||||||
RPID: "https://example.com",
|
RPID: "https://example.com",
|
||||||
Username: "john",
|
Username: "john",
|
||||||
Description: "Primary",
|
Description: "Primary",
|
||||||
KID: models.NewBase64([]byte("abc123")),
|
KID: model.NewBase64([]byte("abc123")),
|
||||||
AttestationType: "fido-u2f",
|
AttestationType: "fido-u2f",
|
||||||
PublicKey: []byte("data"),
|
PublicKey: []byte("data"),
|
||||||
SignCount: 0,
|
SignCount: 0,
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
"github.com/golang-jwt/jwt/v4"
|
"github.com/golang-jwt/jwt/v4"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
|
||||||
"github.com/authelia/authelia/v4/internal/models"
|
"github.com/authelia/authelia/v4/internal/model"
|
||||||
"github.com/authelia/authelia/v4/internal/templates"
|
"github.com/authelia/authelia/v4/internal/templates"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ func IdentityVerificationStart(args IdentityVerificationStartArgs, delayFunc Tim
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
verification := models.NewIdentityVerification(jti, identity.Username, args.ActionClaim, ctx.RemoteIP())
|
verification := model.NewIdentityVerification(jti, identity.Username, args.ActionClaim, ctx.RemoteIP())
|
||||||
|
|
||||||
// Create the claim with the action to sign it.
|
// Create the claim with the action to sign it.
|
||||||
claims := verification.ToIdentityVerificationClaim()
|
claims := verification.ToIdentityVerificationClaim()
|
||||||
|
@ -139,7 +139,7 @@ func IdentityVerificationFinish(args IdentityVerificationFinishArgs, next func(c
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
token, err := jwt.ParseWithClaims(finishBody.Token, &models.IdentityVerificationClaim{},
|
token, err := jwt.ParseWithClaims(finishBody.Token, &model.IdentityVerificationClaim{},
|
||||||
func(token *jwt.Token) (interface{}, error) {
|
func(token *jwt.Token) (interface{}, error) {
|
||||||
return []byte(ctx.Configuration.JWTSecret), nil
|
return []byte(ctx.Configuration.JWTSecret), nil
|
||||||
})
|
})
|
||||||
|
@ -165,7 +165,7 @@ func IdentityVerificationFinish(args IdentityVerificationFinishArgs, next func(c
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
claims, ok := token.Claims.(*models.IdentityVerificationClaim)
|
claims, ok := token.Claims.(*model.IdentityVerificationClaim)
|
||||||
if !ok {
|
if !ok {
|
||||||
ctx.Error(fmt.Errorf("Wrong type of claims (%T != *middlewares.IdentityVerificationClaim)", claims), messageOperationFailed)
|
ctx.Error(fmt.Errorf("Wrong type of claims (%T != *middlewares.IdentityVerificationClaim)", claims), messageOperationFailed)
|
||||||
return
|
return
|
||||||
|
@ -201,7 +201,7 @@ func IdentityVerificationFinish(args IdentityVerificationFinishArgs, next func(c
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ctx.Providers.StorageProvider.ConsumeIdentityVerification(ctx, claims.ID, models.NewNullIP(ctx.RemoteIP()))
|
err = ctx.Providers.StorageProvider.ConsumeIdentityVerification(ctx, claims.ID, model.NewNullIP(ctx.RemoteIP()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(err, messageOperationFailed)
|
ctx.Error(err, messageOperationFailed)
|
||||||
return
|
return
|
||||||
|
|
|
@ -13,7 +13,7 @@ import (
|
||||||
|
|
||||||
"github.com/authelia/authelia/v4/internal/middlewares"
|
"github.com/authelia/authelia/v4/internal/middlewares"
|
||||||
"github.com/authelia/authelia/v4/internal/mocks"
|
"github.com/authelia/authelia/v4/internal/mocks"
|
||||||
"github.com/authelia/authelia/v4/internal/models"
|
"github.com/authelia/authelia/v4/internal/model"
|
||||||
"github.com/authelia/authelia/v4/internal/session"
|
"github.com/authelia/authelia/v4/internal/session"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -148,8 +148,8 @@ func (s *IdentityVerificationFinishProcess) TearDownTest() {
|
||||||
s.mock.Close()
|
s.mock.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func createToken(ctx *mocks.MockAutheliaCtx, username, action string, expiresAt time.Time) (data string, verification models.IdentityVerification) {
|
func createToken(ctx *mocks.MockAutheliaCtx, username, action string, expiresAt time.Time) (data string, verification model.IdentityVerification) {
|
||||||
verification = models.NewIdentityVerification(uuid.New(), username, action, ctx.Ctx.RemoteIP())
|
verification = model.NewIdentityVerification(uuid.New(), username, action, ctx.Ctx.RemoteIP())
|
||||||
|
|
||||||
verification.ExpiresAt = expiresAt
|
verification.ExpiresAt = expiresAt
|
||||||
|
|
||||||
|
@ -264,7 +264,7 @@ func (s *IdentityVerificationFinishProcess) TestShouldFailIfTokenCannotBeRemoved
|
||||||
Return(true, nil)
|
Return(true, nil)
|
||||||
|
|
||||||
s.mock.StorageMock.EXPECT().
|
s.mock.StorageMock.EXPECT().
|
||||||
ConsumeIdentityVerification(s.mock.Ctx, gomock.Eq(verification.JTI.String()), gomock.Eq(models.NewNullIP(s.mock.Ctx.RemoteIP()))).
|
ConsumeIdentityVerification(s.mock.Ctx, gomock.Eq(verification.JTI.String()), gomock.Eq(model.NewNullIP(s.mock.Ctx.RemoteIP()))).
|
||||||
Return(fmt.Errorf("cannot remove"))
|
Return(fmt.Errorf("cannot remove"))
|
||||||
|
|
||||||
middlewares.IdentityVerificationFinish(newFinishArgs(), next)(s.mock.Ctx)
|
middlewares.IdentityVerificationFinish(newFinishArgs(), next)(s.mock.Ctx)
|
||||||
|
@ -283,7 +283,7 @@ func (s *IdentityVerificationFinishProcess) TestShouldReturn200OnFinishComplete(
|
||||||
Return(true, nil)
|
Return(true, nil)
|
||||||
|
|
||||||
s.mock.StorageMock.EXPECT().
|
s.mock.StorageMock.EXPECT().
|
||||||
ConsumeIdentityVerification(s.mock.Ctx, gomock.Eq(verification.JTI.String()), gomock.Eq(models.NewNullIP(s.mock.Ctx.RemoteIP()))).
|
ConsumeIdentityVerification(s.mock.Ctx, gomock.Eq(verification.JTI.String()), gomock.Eq(model.NewNullIP(s.mock.Ctx.RemoteIP()))).
|
||||||
Return(nil)
|
Return(nil)
|
||||||
|
|
||||||
middlewares.IdentityVerificationFinish(newFinishArgs(), next)(s.mock.Ctx)
|
middlewares.IdentityVerificationFinish(newFinishArgs(), next)(s.mock.Ctx)
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
|
|
||||||
gomock "github.com/golang/mock/gomock"
|
gomock "github.com/golang/mock/gomock"
|
||||||
|
|
||||||
models "github.com/authelia/authelia/v4/internal/models"
|
models "github.com/authelia/authelia/v4/internal/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MockStorage is a mock of Provider interface.
|
// MockStorage is a mock of Provider interface.
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
|
|
||||||
gomock "github.com/golang/mock/gomock"
|
gomock "github.com/golang/mock/gomock"
|
||||||
|
|
||||||
models "github.com/authelia/authelia/v4/internal/models"
|
models "github.com/authelia/authelia/v4/internal/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MockTOTP is a mock of Provider interface.
|
// MockTOTP is a mock of Provider interface.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package models
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
|
@ -1,4 +1,4 @@
|
||||||
package models
|
package model
|
||||||
|
|
||||||
const (
|
const (
|
||||||
errFmtValueNil = "cannot value model type '%T' with value nil to driver.Value"
|
errFmtValueNil = "cannot value model type '%T' with value nil to driver.Value"
|
|
@ -1,4 +1,4 @@
|
||||||
package models
|
package model
|
||||||
|
|
||||||
// DuoDevice represents a DUO Device.
|
// DuoDevice represents a DUO Device.
|
||||||
type DuoDevice struct {
|
type DuoDevice struct {
|
|
@ -1,4 +1,4 @@
|
||||||
package models
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
|
@ -1,4 +1,4 @@
|
||||||
package models
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
|
@ -1,4 +1,4 @@
|
||||||
package models
|
package model
|
||||||
|
|
||||||
// SchemaMigration represents an intended migration.
|
// SchemaMigration represents an intended migration.
|
||||||
type SchemaMigration struct {
|
type SchemaMigration struct {
|
|
@ -1,4 +1,4 @@
|
||||||
package models
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"image"
|
"image"
|
|
@ -1,4 +1,4 @@
|
||||||
package models
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
|
@ -1,4 +1,4 @@
|
||||||
package models
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql/driver"
|
"database/sql/driver"
|
|
@ -1,4 +1,4 @@
|
||||||
package models
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -11,7 +11,7 @@ func TestDatabaseModelTypeIP(t *testing.T) {
|
||||||
|
|
||||||
value, err := ip.Value()
|
value, err := ip.Value()
|
||||||
assert.Nil(t, value)
|
assert.Nil(t, value)
|
||||||
assert.EqualError(t, err, "cannot value model type 'models.IP' with value nil to driver.Value")
|
assert.EqualError(t, err, "cannot value model type 'model.IP' with value nil to driver.Value")
|
||||||
|
|
||||||
err = ip.Scan("192.168.2.0")
|
err = ip.Scan("192.168.2.0")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
@ -33,10 +33,10 @@ func TestDatabaseModelTypeIP(t *testing.T) {
|
||||||
|
|
||||||
err = ip.Scan(1)
|
err = ip.Scan(1)
|
||||||
|
|
||||||
assert.EqualError(t, err, "cannot scan model type '*models.IP' from type 'int' with value '1'")
|
assert.EqualError(t, err, "cannot scan model type '*model.IP' from type 'int' with value '1'")
|
||||||
|
|
||||||
err = ip.Scan(nil)
|
err = ip.Scan(nil)
|
||||||
assert.EqualError(t, err, "cannot scan model type '*models.IP' from value nil: type doesn't support nil values")
|
assert.EqualError(t, err, "cannot scan model type '*model.IP' from value nil: type doesn't support nil values")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDatabaseModelTypeNullIP(t *testing.T) {
|
func TestDatabaseModelTypeNullIP(t *testing.T) {
|
||||||
|
@ -66,7 +66,7 @@ func TestDatabaseModelTypeNullIP(t *testing.T) {
|
||||||
|
|
||||||
err = ip.Scan(1)
|
err = ip.Scan(1)
|
||||||
|
|
||||||
assert.EqualError(t, err, "cannot scan model type '*models.NullIP' from type 'int' with value '1'")
|
assert.EqualError(t, err, "cannot scan model type '*model.NullIP' from type 'int' with value '1'")
|
||||||
|
|
||||||
err = ip.Scan(nil)
|
err = ip.Scan(nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
@ -81,13 +81,13 @@ func TestDatabaseModelTypeBase64(t *testing.T) {
|
||||||
assert.Nil(t, b64.Bytes())
|
assert.Nil(t, b64.Bytes())
|
||||||
|
|
||||||
err = b64.Scan(nil)
|
err = b64.Scan(nil)
|
||||||
assert.EqualError(t, err, "cannot scan model type '*models.Base64' from value nil: type doesn't support nil values")
|
assert.EqualError(t, err, "cannot scan model type '*model.Base64' from value nil: type doesn't support nil values")
|
||||||
|
|
||||||
err = b64.Scan("###")
|
err = b64.Scan("###")
|
||||||
assert.EqualError(t, err, "cannot scan model type '*models.Base64' from type 'string' with value '###': illegal base64 data at input byte 0")
|
assert.EqualError(t, err, "cannot scan model type '*model.Base64' from type 'string' with value '###': illegal base64 data at input byte 0")
|
||||||
|
|
||||||
err = b64.Scan(1)
|
err = b64.Scan(1)
|
||||||
assert.EqualError(t, err, "cannot scan model type '*models.Base64' from type 'int' with value '1'")
|
assert.EqualError(t, err, "cannot scan model type '*model.Base64' from type 'int' with value '1'")
|
||||||
|
|
||||||
err = b64.Scan("YXV0aGVsaWE=")
|
err = b64.Scan("YXV0aGVsaWE=")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
|
@ -1,4 +1,4 @@
|
||||||
package models
|
package model
|
||||||
|
|
||||||
// U2FDevice represents a users U2F device row in the database.
|
// U2FDevice represents a users U2F device row in the database.
|
||||||
type U2FDevice struct {
|
type U2FDevice struct {
|
|
@ -1,4 +1,4 @@
|
||||||
package models
|
package model
|
||||||
|
|
||||||
// UserInfo represents the user information required by the web UI.
|
// UserInfo represents the user information required by the web UI.
|
||||||
type UserInfo struct {
|
type UserInfo struct {
|
|
@ -1,4 +1,4 @@
|
||||||
package models
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
|
@ -1,12 +1,12 @@
|
||||||
package notification
|
package notification
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/authelia/authelia/v4/internal/models"
|
"github.com/authelia/authelia/v4/internal/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Notifier interface for sending the identity verification link.
|
// Notifier interface for sending the identity verification link.
|
||||||
type Notifier interface {
|
type Notifier interface {
|
||||||
models.StartupCheck
|
model.StartupCheck
|
||||||
|
|
||||||
Send(recipient, subject, body, htmlBody string) (err error)
|
Send(recipient, subject, body, htmlBody string) (err error)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/authelia/authelia/v4/internal/configuration/schema"
|
"github.com/authelia/authelia/v4/internal/configuration/schema"
|
||||||
"github.com/authelia/authelia/v4/internal/models"
|
"github.com/authelia/authelia/v4/internal/model"
|
||||||
"github.com/authelia/authelia/v4/internal/storage"
|
"github.com/authelia/authelia/v4/internal/storage"
|
||||||
"github.com/authelia/authelia/v4/internal/utils"
|
"github.com/authelia/authelia/v4/internal/utils"
|
||||||
)
|
)
|
||||||
|
@ -24,13 +24,13 @@ func NewRegulator(config schema.RegulationConfiguration, provider storage.Regula
|
||||||
// Mark an authentication attempt.
|
// Mark an authentication attempt.
|
||||||
// We split Mark and Regulate in order to avoid timing attacks.
|
// We split Mark and Regulate in order to avoid timing attacks.
|
||||||
func (r *Regulator) Mark(ctx context.Context, successful, banned bool, username, requestURI, requestMethod, authType string, remoteIP net.IP) error {
|
func (r *Regulator) Mark(ctx context.Context, successful, banned bool, username, requestURI, requestMethod, authType string, remoteIP net.IP) error {
|
||||||
return r.storageProvider.AppendAuthenticationLog(ctx, models.AuthenticationAttempt{
|
return r.storageProvider.AppendAuthenticationLog(ctx, model.AuthenticationAttempt{
|
||||||
Time: r.clock.Now(),
|
Time: r.clock.Now(),
|
||||||
Successful: successful,
|
Successful: successful,
|
||||||
Banned: banned,
|
Banned: banned,
|
||||||
Username: username,
|
Username: username,
|
||||||
Type: authType,
|
Type: authType,
|
||||||
RemoteIP: models.NewNullIP(remoteIP),
|
RemoteIP: model.NewNullIP(remoteIP),
|
||||||
RequestURI: requestURI,
|
RequestURI: requestURI,
|
||||||
RequestMethod: requestMethod,
|
RequestMethod: requestMethod,
|
||||||
})
|
})
|
||||||
|
@ -49,7 +49,7 @@ func (r *Regulator) Regulate(ctx context.Context, username string) (time.Time, e
|
||||||
return time.Time{}, nil
|
return time.Time{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
latestFailedAttempts := make([]models.AuthenticationAttempt, 0, r.config.MaxRetries)
|
latestFailedAttempts := make([]model.AuthenticationAttempt, 0, r.config.MaxRetries)
|
||||||
|
|
||||||
for _, attempt := range attempts {
|
for _, attempt := range attempts {
|
||||||
if attempt.Successful || len(latestFailedAttempts) >= r.config.MaxRetries {
|
if attempt.Successful || len(latestFailedAttempts) >= r.config.MaxRetries {
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
|
|
||||||
"github.com/authelia/authelia/v4/internal/configuration/schema"
|
"github.com/authelia/authelia/v4/internal/configuration/schema"
|
||||||
"github.com/authelia/authelia/v4/internal/mocks"
|
"github.com/authelia/authelia/v4/internal/mocks"
|
||||||
"github.com/authelia/authelia/v4/internal/models"
|
"github.com/authelia/authelia/v4/internal/model"
|
||||||
"github.com/authelia/authelia/v4/internal/regulation"
|
"github.com/authelia/authelia/v4/internal/regulation"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ func (s *RegulatorSuite) TearDownTest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *RegulatorSuite) TestShouldNotThrowWhenUserIsLegitimate() {
|
func (s *RegulatorSuite) TestShouldNotThrowWhenUserIsLegitimate() {
|
||||||
attemptsInDB := []models.AuthenticationAttempt{
|
attemptsInDB := []model.AuthenticationAttempt{
|
||||||
{
|
{
|
||||||
Username: "john",
|
Username: "john",
|
||||||
Successful: true,
|
Successful: true,
|
||||||
|
@ -64,7 +64,7 @@ func (s *RegulatorSuite) TestShouldNotThrowWhenUserIsLegitimate() {
|
||||||
// This test checks the case in which a user failed to authenticate many times but always
|
// This test checks the case in which a user failed to authenticate many times but always
|
||||||
// with a certain amount of time larger than FindTime. Meaning the user should not be banned.
|
// with a certain amount of time larger than FindTime. Meaning the user should not be banned.
|
||||||
func (s *RegulatorSuite) TestShouldNotThrowWhenFailedAuthenticationNotInFindTime() {
|
func (s *RegulatorSuite) TestShouldNotThrowWhenFailedAuthenticationNotInFindTime() {
|
||||||
attemptsInDB := []models.AuthenticationAttempt{
|
attemptsInDB := []model.AuthenticationAttempt{
|
||||||
{
|
{
|
||||||
Username: "john",
|
Username: "john",
|
||||||
Successful: false,
|
Successful: false,
|
||||||
|
@ -95,7 +95,7 @@ func (s *RegulatorSuite) TestShouldNotThrowWhenFailedAuthenticationNotInFindTime
|
||||||
// This test checks the case in which a user failed to authenticate many times only a few
|
// This test checks the case in which a user failed to authenticate many times only a few
|
||||||
// seconds ago (meaning we are checking from now back to now-FindTime).
|
// seconds ago (meaning we are checking from now back to now-FindTime).
|
||||||
func (s *RegulatorSuite) TestShouldBanUserIfLatestAttemptsAreWithinFinTime() {
|
func (s *RegulatorSuite) TestShouldBanUserIfLatestAttemptsAreWithinFinTime() {
|
||||||
attemptsInDB := []models.AuthenticationAttempt{
|
attemptsInDB := []model.AuthenticationAttempt{
|
||||||
{
|
{
|
||||||
Username: "john",
|
Username: "john",
|
||||||
Successful: false,
|
Successful: false,
|
||||||
|
@ -133,7 +133,7 @@ func (s *RegulatorSuite) TestShouldBanUserIfLatestAttemptsAreWithinFinTime() {
|
||||||
// we are within now and now-BanTime). It means the user has been banned some time ago and is still
|
// we are within now and now-BanTime). It means the user has been banned some time ago and is still
|
||||||
// banned right now.
|
// banned right now.
|
||||||
func (s *RegulatorSuite) TestShouldCheckUserIsStillBanned() {
|
func (s *RegulatorSuite) TestShouldCheckUserIsStillBanned() {
|
||||||
attemptsInDB := []models.AuthenticationAttempt{
|
attemptsInDB := []model.AuthenticationAttempt{
|
||||||
{
|
{
|
||||||
Username: "john",
|
Username: "john",
|
||||||
Successful: false,
|
Successful: false,
|
||||||
|
@ -162,7 +162,7 @@ func (s *RegulatorSuite) TestShouldCheckUserIsStillBanned() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *RegulatorSuite) TestShouldCheckUserIsNotYetBanned() {
|
func (s *RegulatorSuite) TestShouldCheckUserIsNotYetBanned() {
|
||||||
attemptsInDB := []models.AuthenticationAttempt{
|
attemptsInDB := []model.AuthenticationAttempt{
|
||||||
{
|
{
|
||||||
Username: "john",
|
Username: "john",
|
||||||
Successful: false,
|
Successful: false,
|
||||||
|
@ -186,7 +186,7 @@ func (s *RegulatorSuite) TestShouldCheckUserIsNotYetBanned() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *RegulatorSuite) TestShouldCheckUserWasAboutToBeBanned() {
|
func (s *RegulatorSuite) TestShouldCheckUserWasAboutToBeBanned() {
|
||||||
attemptsInDB := []models.AuthenticationAttempt{
|
attemptsInDB := []model.AuthenticationAttempt{
|
||||||
{
|
{
|
||||||
Username: "john",
|
Username: "john",
|
||||||
Successful: false,
|
Successful: false,
|
||||||
|
@ -218,7 +218,7 @@ func (s *RegulatorSuite) TestShouldCheckUserWasAboutToBeBanned() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *RegulatorSuite) TestShouldCheckRegulationHasBeenResetOnSuccessfulAttempt() {
|
func (s *RegulatorSuite) TestShouldCheckRegulationHasBeenResetOnSuccessfulAttempt() {
|
||||||
attemptsInDB := []models.AuthenticationAttempt{
|
attemptsInDB := []model.AuthenticationAttempt{
|
||||||
{
|
{
|
||||||
Username: "john",
|
Username: "john",
|
||||||
Successful: false,
|
Successful: false,
|
||||||
|
@ -260,7 +260,7 @@ func TestRunRegulatorSuite(t *testing.T) {
|
||||||
|
|
||||||
// This test checks that the regulator is disabled when configuration is set to 0.
|
// This test checks that the regulator is disabled when configuration is set to 0.
|
||||||
func (s *RegulatorSuite) TestShouldHaveRegulatorDisabled() {
|
func (s *RegulatorSuite) TestShouldHaveRegulatorDisabled() {
|
||||||
attemptsInDB := []models.AuthenticationAttempt{
|
attemptsInDB := []model.AuthenticationAttempt{
|
||||||
{
|
{
|
||||||
Username: "john",
|
Username: "john",
|
||||||
Successful: false,
|
Successful: false,
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/authelia/authelia/v4/internal/models"
|
"github.com/authelia/authelia/v4/internal/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed migrations/*
|
//go:embed migrations/*
|
||||||
|
@ -46,7 +46,7 @@ func latestMigrationVersion(providerName string) (version int, err error) {
|
||||||
return version, nil
|
return version, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadMigration(providerName string, version int, up bool) (migration *models.SchemaMigration, err error) {
|
func loadMigration(providerName string, version int, up bool) (migration *model.SchemaMigration, err error) {
|
||||||
entries, err := migrationsFS.ReadDir("migrations")
|
entries, err := migrationsFS.ReadDir("migrations")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -85,7 +85,7 @@ func loadMigration(providerName string, version int, up bool) (migration *models
|
||||||
// loadMigrations scans the migrations fs and loads the appropriate migrations for a given providerName, prior and
|
// loadMigrations scans the migrations fs and loads the appropriate migrations for a given providerName, prior and
|
||||||
// target versions. If the target version is -1 this indicates the latest version. If the target version is 0
|
// target versions. If the target version is -1 this indicates the latest version. If the target version is 0
|
||||||
// this indicates the database zero state.
|
// this indicates the database zero state.
|
||||||
func loadMigrations(providerName string, prior, target int) (migrations []models.SchemaMigration, err error) {
|
func loadMigrations(providerName string, prior, target int) (migrations []model.SchemaMigration, err error) {
|
||||||
if prior == target && (prior != -1 || target != -1) {
|
if prior == target && (prior != -1 || target != -1) {
|
||||||
return nil, ErrMigrateCurrentVersionSameAsTarget
|
return nil, ErrMigrateCurrentVersionSameAsTarget
|
||||||
}
|
}
|
||||||
|
@ -127,7 +127,7 @@ func loadMigrations(providerName string, prior, target int) (migrations []models
|
||||||
return migrations, nil
|
return migrations, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func skipMigration(providerName string, up bool, target, prior int, migration *models.SchemaMigration) (skip bool) {
|
func skipMigration(providerName string, up bool, target, prior int, migration *model.SchemaMigration) (skip bool) {
|
||||||
if migration.Provider != providerAll && migration.Provider != providerName {
|
if migration.Provider != providerAll && migration.Provider != providerName {
|
||||||
// Skip if migration.Provider is not a match.
|
// Skip if migration.Provider is not a match.
|
||||||
return true
|
return true
|
||||||
|
@ -165,21 +165,21 @@ func skipMigration(providerName string, up bool, target, prior int, migration *m
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func scanMigration(m string) (migration models.SchemaMigration, err error) {
|
func scanMigration(m string) (migration model.SchemaMigration, err error) {
|
||||||
result := reMigration.FindStringSubmatch(m)
|
result := reMigration.FindStringSubmatch(m)
|
||||||
|
|
||||||
if result == nil || len(result) != 5 {
|
if result == nil || len(result) != 5 {
|
||||||
return models.SchemaMigration{}, errors.New("invalid migration: could not parse the format")
|
return model.SchemaMigration{}, errors.New("invalid migration: could not parse the format")
|
||||||
}
|
}
|
||||||
|
|
||||||
migration = models.SchemaMigration{
|
migration = model.SchemaMigration{
|
||||||
Name: strings.ReplaceAll(result[2], "_", " "),
|
Name: strings.ReplaceAll(result[2], "_", " "),
|
||||||
Provider: result[3],
|
Provider: result[3],
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := migrationsFS.ReadFile(fmt.Sprintf("migrations/%s", m))
|
data, err := migrationsFS.ReadFile(fmt.Sprintf("migrations/%s", m))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return models.SchemaMigration{}, err
|
return model.SchemaMigration{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
migration.Query = string(data)
|
migration.Query = string(data)
|
||||||
|
@ -190,7 +190,7 @@ func scanMigration(m string) (migration models.SchemaMigration, err error) {
|
||||||
case "down":
|
case "down":
|
||||||
migration.Up = false
|
migration.Up = false
|
||||||
default:
|
default:
|
||||||
return models.SchemaMigration{}, fmt.Errorf("invalid migration: value in position 4 '%s' must be up or down", result[4])
|
return model.SchemaMigration{}, fmt.Errorf("invalid migration: value in position 4 '%s' must be up or down", result[4])
|
||||||
}
|
}
|
||||||
|
|
||||||
migration.Version, _ = strconv.Atoi(result[1])
|
migration.Version, _ = strconv.Atoi(result[1])
|
||||||
|
@ -199,7 +199,7 @@ func scanMigration(m string) (migration models.SchemaMigration, err error) {
|
||||||
case providerAll, providerSQLite, providerMySQL, providerPostgres:
|
case providerAll, providerSQLite, providerMySQL, providerPostgres:
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
return models.SchemaMigration{}, fmt.Errorf("invalid migration: value in position 3 '%s' must be all, sqlite, postgres, or mysql", result[3])
|
return model.SchemaMigration{}, fmt.Errorf("invalid migration: value in position 3 '%s' must be all, sqlite, postgres, or mysql", result[3])
|
||||||
}
|
}
|
||||||
|
|
||||||
return migration, nil
|
return migration, nil
|
||||||
|
|
|
@ -4,46 +4,46 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/authelia/authelia/v4/internal/models"
|
"github.com/authelia/authelia/v4/internal/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Provider is an interface providing storage capabilities for persisting any kind of data related to Authelia.
|
// Provider is an interface providing storage capabilities for persisting any kind of data related to Authelia.
|
||||||
type Provider interface {
|
type Provider interface {
|
||||||
models.StartupCheck
|
model.StartupCheck
|
||||||
|
|
||||||
RegulatorProvider
|
RegulatorProvider
|
||||||
|
|
||||||
SavePreferred2FAMethod(ctx context.Context, username string, method string) (err error)
|
SavePreferred2FAMethod(ctx context.Context, username string, method string) (err error)
|
||||||
LoadPreferred2FAMethod(ctx context.Context, username string) (method string, err error)
|
LoadPreferred2FAMethod(ctx context.Context, username string) (method string, err error)
|
||||||
LoadUserInfo(ctx context.Context, username string) (info models.UserInfo, err error)
|
LoadUserInfo(ctx context.Context, username string) (info model.UserInfo, err error)
|
||||||
|
|
||||||
SaveIdentityVerification(ctx context.Context, verification models.IdentityVerification) (err error)
|
SaveIdentityVerification(ctx context.Context, verification model.IdentityVerification) (err error)
|
||||||
ConsumeIdentityVerification(ctx context.Context, jti string, ip models.NullIP) (err error)
|
ConsumeIdentityVerification(ctx context.Context, jti string, ip model.NullIP) (err error)
|
||||||
FindIdentityVerification(ctx context.Context, jti string) (found bool, err error)
|
FindIdentityVerification(ctx context.Context, jti string) (found bool, err error)
|
||||||
|
|
||||||
SaveTOTPConfiguration(ctx context.Context, config models.TOTPConfiguration) (err error)
|
SaveTOTPConfiguration(ctx context.Context, config model.TOTPConfiguration) (err error)
|
||||||
UpdateTOTPConfigurationSignIn(ctx context.Context, id int, lastUsedAt *time.Time) (err error)
|
UpdateTOTPConfigurationSignIn(ctx context.Context, id int, lastUsedAt *time.Time) (err error)
|
||||||
DeleteTOTPConfiguration(ctx context.Context, username string) (err error)
|
DeleteTOTPConfiguration(ctx context.Context, username string) (err error)
|
||||||
LoadTOTPConfiguration(ctx context.Context, username string) (config *models.TOTPConfiguration, err error)
|
LoadTOTPConfiguration(ctx context.Context, username string) (config *model.TOTPConfiguration, err error)
|
||||||
LoadTOTPConfigurations(ctx context.Context, limit, page int) (configs []models.TOTPConfiguration, err error)
|
LoadTOTPConfigurations(ctx context.Context, limit, page int) (configs []model.TOTPConfiguration, err error)
|
||||||
|
|
||||||
SaveWebauthnDevice(ctx context.Context, device models.WebauthnDevice) (err error)
|
SaveWebauthnDevice(ctx context.Context, device model.WebauthnDevice) (err error)
|
||||||
UpdateWebauthnDeviceSignIn(ctx context.Context, id int, rpid string, lastUsedAt *time.Time, signCount uint32, cloneWarning bool) (err error)
|
UpdateWebauthnDeviceSignIn(ctx context.Context, id int, rpid string, lastUsedAt *time.Time, signCount uint32, cloneWarning bool) (err error)
|
||||||
LoadWebauthnDevices(ctx context.Context, limit, page int) (devices []models.WebauthnDevice, err error)
|
LoadWebauthnDevices(ctx context.Context, limit, page int) (devices []model.WebauthnDevice, err error)
|
||||||
LoadWebauthnDevicesByUsername(ctx context.Context, username string) (devices []models.WebauthnDevice, err error)
|
LoadWebauthnDevicesByUsername(ctx context.Context, username string) (devices []model.WebauthnDevice, err error)
|
||||||
|
|
||||||
SavePreferredDuoDevice(ctx context.Context, device models.DuoDevice) (err error)
|
SavePreferredDuoDevice(ctx context.Context, device model.DuoDevice) (err error)
|
||||||
DeletePreferredDuoDevice(ctx context.Context, username string) (err error)
|
DeletePreferredDuoDevice(ctx context.Context, username string) (err error)
|
||||||
LoadPreferredDuoDevice(ctx context.Context, username string) (device *models.DuoDevice, err error)
|
LoadPreferredDuoDevice(ctx context.Context, username string) (device *model.DuoDevice, err error)
|
||||||
|
|
||||||
SchemaTables(ctx context.Context) (tables []string, err error)
|
SchemaTables(ctx context.Context) (tables []string, err error)
|
||||||
SchemaVersion(ctx context.Context) (version int, err error)
|
SchemaVersion(ctx context.Context) (version int, err error)
|
||||||
SchemaLatestVersion() (version int, err error)
|
SchemaLatestVersion() (version int, err error)
|
||||||
|
|
||||||
SchemaMigrate(ctx context.Context, up bool, version int) (err error)
|
SchemaMigrate(ctx context.Context, up bool, version int) (err error)
|
||||||
SchemaMigrationHistory(ctx context.Context) (migrations []models.Migration, err error)
|
SchemaMigrationHistory(ctx context.Context) (migrations []model.Migration, err error)
|
||||||
SchemaMigrationsUp(ctx context.Context, version int) (migrations []models.SchemaMigration, err error)
|
SchemaMigrationsUp(ctx context.Context, version int) (migrations []model.SchemaMigration, err error)
|
||||||
SchemaMigrationsDown(ctx context.Context, version int) (migrations []models.SchemaMigration, err error)
|
SchemaMigrationsDown(ctx context.Context, version int) (migrations []model.SchemaMigration, err error)
|
||||||
|
|
||||||
SchemaEncryptionChangeKey(ctx context.Context, encryptionKey string) (err error)
|
SchemaEncryptionChangeKey(ctx context.Context, encryptionKey string) (err error)
|
||||||
SchemaEncryptionCheckKey(ctx context.Context, verbose bool) (err error)
|
SchemaEncryptionCheckKey(ctx context.Context, verbose bool) (err error)
|
||||||
|
@ -53,6 +53,6 @@ type Provider interface {
|
||||||
|
|
||||||
// RegulatorProvider is an interface providing storage capabilities for persisting any kind of data related to the regulator.
|
// RegulatorProvider is an interface providing storage capabilities for persisting any kind of data related to the regulator.
|
||||||
type RegulatorProvider interface {
|
type RegulatorProvider interface {
|
||||||
AppendAuthenticationLog(ctx context.Context, attempt models.AuthenticationAttempt) (err error)
|
AppendAuthenticationLog(ctx context.Context, attempt model.AuthenticationAttempt) (err error)
|
||||||
LoadAuthenticationLogs(ctx context.Context, username string, fromDate time.Time, limit, page int) (attempts []models.AuthenticationAttempt, err error)
|
LoadAuthenticationLogs(ctx context.Context, username string, fromDate time.Time, limit, page int) (attempts []model.AuthenticationAttempt, err error)
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ import (
|
||||||
"github.com/authelia/authelia/v4/internal/authentication"
|
"github.com/authelia/authelia/v4/internal/authentication"
|
||||||
"github.com/authelia/authelia/v4/internal/configuration/schema"
|
"github.com/authelia/authelia/v4/internal/configuration/schema"
|
||||||
"github.com/authelia/authelia/v4/internal/logging"
|
"github.com/authelia/authelia/v4/internal/logging"
|
||||||
"github.com/authelia/authelia/v4/internal/models"
|
"github.com/authelia/authelia/v4/internal/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewSQLProvider generates a generic SQLProvider to be used with other SQL provider NewUp's.
|
// NewSQLProvider generates a generic SQLProvider to be used with other SQL provider NewUp's.
|
||||||
|
@ -211,8 +211,8 @@ func (p *SQLProvider) LoadPreferred2FAMethod(ctx context.Context, username strin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadUserInfo loads the models.UserInfo from the database.
|
// LoadUserInfo loads the model.UserInfo from the database.
|
||||||
func (p *SQLProvider) LoadUserInfo(ctx context.Context, username string) (info models.UserInfo, err error) {
|
func (p *SQLProvider) LoadUserInfo(ctx context.Context, username string) (info model.UserInfo, err error) {
|
||||||
err = p.db.GetContext(ctx, &info, p.sqlSelectUserInfo, username, username, username, username)
|
err = p.db.GetContext(ctx, &info, p.sqlSelectUserInfo, username, username, username, username)
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
|
@ -220,21 +220,21 @@ func (p *SQLProvider) LoadUserInfo(ctx context.Context, username string) (info m
|
||||||
return info, nil
|
return info, nil
|
||||||
case errors.Is(err, sql.ErrNoRows):
|
case errors.Is(err, sql.ErrNoRows):
|
||||||
if _, err = p.db.ExecContext(ctx, p.sqlUpsertPreferred2FAMethod, username, authentication.PossibleMethods[0]); err != nil {
|
if _, err = p.db.ExecContext(ctx, p.sqlUpsertPreferred2FAMethod, username, authentication.PossibleMethods[0]); err != nil {
|
||||||
return models.UserInfo{}, fmt.Errorf("error upserting preferred two factor method while selecting user info for user '%s': %w", username, err)
|
return model.UserInfo{}, fmt.Errorf("error upserting preferred two factor method while selecting user info for user '%s': %w", username, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = p.db.GetContext(ctx, &info, p.sqlSelectUserInfo, username, username, username, username); err != nil {
|
if err = p.db.GetContext(ctx, &info, p.sqlSelectUserInfo, username, username, username, username); err != nil {
|
||||||
return models.UserInfo{}, fmt.Errorf("error selecting user info for user '%s': %w", username, err)
|
return model.UserInfo{}, fmt.Errorf("error selecting user info for user '%s': %w", username, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return info, nil
|
return info, nil
|
||||||
default:
|
default:
|
||||||
return models.UserInfo{}, fmt.Errorf("error selecting user info for user '%s': %w", username, err)
|
return model.UserInfo{}, fmt.Errorf("error selecting user info for user '%s': %w", username, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SaveIdentityVerification save an identity verification record to the database.
|
// SaveIdentityVerification save an identity verification record to the database.
|
||||||
func (p *SQLProvider) SaveIdentityVerification(ctx context.Context, verification models.IdentityVerification) (err error) {
|
func (p *SQLProvider) SaveIdentityVerification(ctx context.Context, verification model.IdentityVerification) (err error) {
|
||||||
if _, err = p.db.ExecContext(ctx, p.sqlInsertIdentityVerification,
|
if _, err = p.db.ExecContext(ctx, p.sqlInsertIdentityVerification,
|
||||||
verification.JTI, verification.IssuedAt, verification.IssuedIP, verification.ExpiresAt,
|
verification.JTI, verification.IssuedAt, verification.IssuedIP, verification.ExpiresAt,
|
||||||
verification.Username, verification.Action); err != nil {
|
verification.Username, verification.Action); err != nil {
|
||||||
|
@ -245,7 +245,7 @@ func (p *SQLProvider) SaveIdentityVerification(ctx context.Context, verification
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConsumeIdentityVerification marks an identity verification record in the database as consumed.
|
// ConsumeIdentityVerification marks an identity verification record in the database as consumed.
|
||||||
func (p *SQLProvider) ConsumeIdentityVerification(ctx context.Context, jti string, ip models.NullIP) (err error) {
|
func (p *SQLProvider) ConsumeIdentityVerification(ctx context.Context, jti string, ip model.NullIP) (err error) {
|
||||||
if _, err = p.db.ExecContext(ctx, p.sqlConsumeIdentityVerification, ip, jti); err != nil {
|
if _, err = p.db.ExecContext(ctx, p.sqlConsumeIdentityVerification, ip, jti); err != nil {
|
||||||
return fmt.Errorf("error updating identity verification: %w", err)
|
return fmt.Errorf("error updating identity verification: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -255,7 +255,7 @@ func (p *SQLProvider) ConsumeIdentityVerification(ctx context.Context, jti strin
|
||||||
|
|
||||||
// FindIdentityVerification checks if an identity verification record is in the database and active.
|
// FindIdentityVerification checks if an identity verification record is in the database and active.
|
||||||
func (p *SQLProvider) FindIdentityVerification(ctx context.Context, jti string) (found bool, err error) {
|
func (p *SQLProvider) FindIdentityVerification(ctx context.Context, jti string) (found bool, err error) {
|
||||||
verification := models.IdentityVerification{}
|
verification := model.IdentityVerification{}
|
||||||
if err = p.db.GetContext(ctx, &verification, p.sqlSelectIdentityVerification, jti); err != nil {
|
if err = p.db.GetContext(ctx, &verification, p.sqlSelectIdentityVerification, jti); err != nil {
|
||||||
if errors.Is(err, sql.ErrNoRows) {
|
if errors.Is(err, sql.ErrNoRows) {
|
||||||
return false, nil
|
return false, nil
|
||||||
|
@ -275,7 +275,7 @@ func (p *SQLProvider) FindIdentityVerification(ctx context.Context, jti string)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SaveTOTPConfiguration save a TOTP configuration of a given user in the database.
|
// SaveTOTPConfiguration save a TOTP configuration of a given user in the database.
|
||||||
func (p *SQLProvider) SaveTOTPConfiguration(ctx context.Context, config models.TOTPConfiguration) (err error) {
|
func (p *SQLProvider) SaveTOTPConfiguration(ctx context.Context, config model.TOTPConfiguration) (err error) {
|
||||||
if config.Secret, err = p.encrypt(config.Secret); err != nil {
|
if config.Secret, err = p.encrypt(config.Secret); err != nil {
|
||||||
return fmt.Errorf("error encrypting the TOTP configuration secret for user '%s': %w", config.Username, err)
|
return fmt.Errorf("error encrypting the TOTP configuration secret for user '%s': %w", config.Username, err)
|
||||||
}
|
}
|
||||||
|
@ -309,8 +309,8 @@ func (p *SQLProvider) DeleteTOTPConfiguration(ctx context.Context, username stri
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadTOTPConfiguration load a TOTP configuration given a username from the database.
|
// LoadTOTPConfiguration load a TOTP configuration given a username from the database.
|
||||||
func (p *SQLProvider) LoadTOTPConfiguration(ctx context.Context, username string) (config *models.TOTPConfiguration, err error) {
|
func (p *SQLProvider) LoadTOTPConfiguration(ctx context.Context, username string) (config *model.TOTPConfiguration, err error) {
|
||||||
config = &models.TOTPConfiguration{}
|
config = &model.TOTPConfiguration{}
|
||||||
|
|
||||||
if err = p.db.QueryRowxContext(ctx, p.sqlSelectTOTPConfig, username).StructScan(config); err != nil {
|
if err = p.db.QueryRowxContext(ctx, p.sqlSelectTOTPConfig, username).StructScan(config); err != nil {
|
||||||
if errors.Is(err, sql.ErrNoRows) {
|
if errors.Is(err, sql.ErrNoRows) {
|
||||||
|
@ -328,8 +328,8 @@ func (p *SQLProvider) LoadTOTPConfiguration(ctx context.Context, username string
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadTOTPConfigurations load a set of TOTP configurations.
|
// LoadTOTPConfigurations load a set of TOTP configurations.
|
||||||
func (p *SQLProvider) LoadTOTPConfigurations(ctx context.Context, limit, page int) (configs []models.TOTPConfiguration, err error) {
|
func (p *SQLProvider) LoadTOTPConfigurations(ctx context.Context, limit, page int) (configs []model.TOTPConfiguration, err error) {
|
||||||
configs = make([]models.TOTPConfiguration, 0, limit)
|
configs = make([]model.TOTPConfiguration, 0, limit)
|
||||||
|
|
||||||
if err = p.db.SelectContext(ctx, &configs, p.sqlSelectTOTPConfigs, limit, limit*page); err != nil {
|
if err = p.db.SelectContext(ctx, &configs, p.sqlSelectTOTPConfigs, limit, limit*page); err != nil {
|
||||||
if errors.Is(err, sql.ErrNoRows) {
|
if errors.Is(err, sql.ErrNoRows) {
|
||||||
|
@ -348,7 +348,7 @@ func (p *SQLProvider) LoadTOTPConfigurations(ctx context.Context, limit, page in
|
||||||
return configs, nil
|
return configs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *SQLProvider) updateTOTPConfigurationSecret(ctx context.Context, config models.TOTPConfiguration) (err error) {
|
func (p *SQLProvider) updateTOTPConfigurationSecret(ctx context.Context, config model.TOTPConfiguration) (err error) {
|
||||||
switch config.ID {
|
switch config.ID {
|
||||||
case 0:
|
case 0:
|
||||||
_, err = p.db.ExecContext(ctx, p.sqlUpdateTOTPConfigSecretByUsername, config.Secret, config.Username)
|
_, err = p.db.ExecContext(ctx, p.sqlUpdateTOTPConfigSecretByUsername, config.Secret, config.Username)
|
||||||
|
@ -364,7 +364,7 @@ func (p *SQLProvider) updateTOTPConfigurationSecret(ctx context.Context, config
|
||||||
}
|
}
|
||||||
|
|
||||||
// SaveWebauthnDevice saves a registered Webauthn device.
|
// SaveWebauthnDevice saves a registered Webauthn device.
|
||||||
func (p *SQLProvider) SaveWebauthnDevice(ctx context.Context, device models.WebauthnDevice) (err error) {
|
func (p *SQLProvider) SaveWebauthnDevice(ctx context.Context, device model.WebauthnDevice) (err error) {
|
||||||
if device.PublicKey, err = p.encrypt(device.PublicKey); err != nil {
|
if device.PublicKey, err = p.encrypt(device.PublicKey); err != nil {
|
||||||
return fmt.Errorf("error encrypting the Webauthn device public key for user '%s' kid '%x': %w", device.Username, device.KID, err)
|
return fmt.Errorf("error encrypting the Webauthn device public key for user '%s' kid '%x': %w", device.Username, device.KID, err)
|
||||||
}
|
}
|
||||||
|
@ -391,8 +391,8 @@ func (p *SQLProvider) UpdateWebauthnDeviceSignIn(ctx context.Context, id int, rp
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadWebauthnDevices loads Webauthn device registrations.
|
// LoadWebauthnDevices loads Webauthn device registrations.
|
||||||
func (p *SQLProvider) LoadWebauthnDevices(ctx context.Context, limit, page int) (devices []models.WebauthnDevice, err error) {
|
func (p *SQLProvider) LoadWebauthnDevices(ctx context.Context, limit, page int) (devices []model.WebauthnDevice, err error) {
|
||||||
devices = make([]models.WebauthnDevice, 0, limit)
|
devices = make([]model.WebauthnDevice, 0, limit)
|
||||||
|
|
||||||
if err = p.db.SelectContext(ctx, &devices, p.sqlSelectWebauthnDevices, limit, limit*page); err != nil {
|
if err = p.db.SelectContext(ctx, &devices, p.sqlSelectWebauthnDevices, limit, limit*page); err != nil {
|
||||||
if errors.Is(err, sql.ErrNoRows) {
|
if errors.Is(err, sql.ErrNoRows) {
|
||||||
|
@ -412,7 +412,7 @@ func (p *SQLProvider) LoadWebauthnDevices(ctx context.Context, limit, page int)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadWebauthnDevicesByUsername loads all webauthn devices registration for a given username.
|
// LoadWebauthnDevicesByUsername loads all webauthn devices registration for a given username.
|
||||||
func (p *SQLProvider) LoadWebauthnDevicesByUsername(ctx context.Context, username string) (devices []models.WebauthnDevice, err error) {
|
func (p *SQLProvider) LoadWebauthnDevicesByUsername(ctx context.Context, username string) (devices []model.WebauthnDevice, err error) {
|
||||||
if err = p.db.SelectContext(ctx, &devices, p.sqlSelectWebauthnDevicesByUsername, username); err != nil {
|
if err = p.db.SelectContext(ctx, &devices, p.sqlSelectWebauthnDevicesByUsername, username); err != nil {
|
||||||
if errors.Is(err, sql.ErrNoRows) {
|
if errors.Is(err, sql.ErrNoRows) {
|
||||||
return nil, ErrNoWebauthnDevice
|
return nil, ErrNoWebauthnDevice
|
||||||
|
@ -430,7 +430,7 @@ func (p *SQLProvider) LoadWebauthnDevicesByUsername(ctx context.Context, usernam
|
||||||
return devices, nil
|
return devices, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *SQLProvider) updateWebauthnDevicePublicKey(ctx context.Context, device models.WebauthnDevice) (err error) {
|
func (p *SQLProvider) updateWebauthnDevicePublicKey(ctx context.Context, device model.WebauthnDevice) (err error) {
|
||||||
switch device.ID {
|
switch device.ID {
|
||||||
case 0:
|
case 0:
|
||||||
_, err = p.db.ExecContext(ctx, p.sqlUpdateWebauthnDevicePublicKeyByUsername, device.PublicKey, device.Username, device.KID)
|
_, err = p.db.ExecContext(ctx, p.sqlUpdateWebauthnDevicePublicKeyByUsername, device.PublicKey, device.Username, device.KID)
|
||||||
|
@ -446,7 +446,7 @@ func (p *SQLProvider) updateWebauthnDevicePublicKey(ctx context.Context, device
|
||||||
}
|
}
|
||||||
|
|
||||||
// SavePreferredDuoDevice saves a Duo device.
|
// SavePreferredDuoDevice saves a Duo device.
|
||||||
func (p *SQLProvider) SavePreferredDuoDevice(ctx context.Context, device models.DuoDevice) (err error) {
|
func (p *SQLProvider) SavePreferredDuoDevice(ctx context.Context, device model.DuoDevice) (err error) {
|
||||||
if _, err = p.db.ExecContext(ctx, p.sqlUpsertDuoDevice, device.Username, device.Device, device.Method); err != nil {
|
if _, err = p.db.ExecContext(ctx, p.sqlUpsertDuoDevice, device.Username, device.Device, device.Method); err != nil {
|
||||||
return fmt.Errorf("error upserting preferred duo device for user '%s': %w", device.Username, err)
|
return fmt.Errorf("error upserting preferred duo device for user '%s': %w", device.Username, err)
|
||||||
}
|
}
|
||||||
|
@ -464,8 +464,8 @@ func (p *SQLProvider) DeletePreferredDuoDevice(ctx context.Context, username str
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadPreferredDuoDevice loads a Duo device of a given user.
|
// LoadPreferredDuoDevice loads a Duo device of a given user.
|
||||||
func (p *SQLProvider) LoadPreferredDuoDevice(ctx context.Context, username string) (device *models.DuoDevice, err error) {
|
func (p *SQLProvider) LoadPreferredDuoDevice(ctx context.Context, username string) (device *model.DuoDevice, err error) {
|
||||||
device = &models.DuoDevice{}
|
device = &model.DuoDevice{}
|
||||||
|
|
||||||
if err = p.db.QueryRowxContext(ctx, p.sqlSelectDuoDevice, username).StructScan(device); err != nil {
|
if err = p.db.QueryRowxContext(ctx, p.sqlSelectDuoDevice, username).StructScan(device); err != nil {
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
|
@ -479,7 +479,7 @@ func (p *SQLProvider) LoadPreferredDuoDevice(ctx context.Context, username strin
|
||||||
}
|
}
|
||||||
|
|
||||||
// AppendAuthenticationLog append a mark to the authentication log.
|
// AppendAuthenticationLog append a mark to the authentication log.
|
||||||
func (p *SQLProvider) AppendAuthenticationLog(ctx context.Context, attempt models.AuthenticationAttempt) (err error) {
|
func (p *SQLProvider) AppendAuthenticationLog(ctx context.Context, attempt model.AuthenticationAttempt) (err error) {
|
||||||
if _, err = p.db.ExecContext(ctx, p.sqlInsertAuthenticationAttempt,
|
if _, err = p.db.ExecContext(ctx, p.sqlInsertAuthenticationAttempt,
|
||||||
attempt.Time, attempt.Successful, attempt.Banned, attempt.Username,
|
attempt.Time, attempt.Successful, attempt.Banned, attempt.Username,
|
||||||
attempt.Type, attempt.RemoteIP, attempt.RequestURI, attempt.RequestMethod); err != nil {
|
attempt.Type, attempt.RemoteIP, attempt.RequestURI, attempt.RequestMethod); err != nil {
|
||||||
|
@ -490,8 +490,8 @@ func (p *SQLProvider) AppendAuthenticationLog(ctx context.Context, attempt model
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadAuthenticationLogs retrieve the latest failed authentications from the authentication log.
|
// LoadAuthenticationLogs retrieve the latest failed authentications from the authentication log.
|
||||||
func (p *SQLProvider) LoadAuthenticationLogs(ctx context.Context, username string, fromDate time.Time, limit, page int) (attempts []models.AuthenticationAttempt, err error) {
|
func (p *SQLProvider) LoadAuthenticationLogs(ctx context.Context, username string, fromDate time.Time, limit, page int) (attempts []model.AuthenticationAttempt, err error) {
|
||||||
attempts = make([]models.AuthenticationAttempt, 0, limit)
|
attempts = make([]model.AuthenticationAttempt, 0, limit)
|
||||||
|
|
||||||
if err = p.db.SelectContext(ctx, &attempts, p.sqlSelectAuthenticationAttemptsByUsername, fromDate, username, limit, limit*page); err != nil {
|
if err = p.db.SelectContext(ctx, &attempts, p.sqlSelectAuthenticationAttemptsByUsername, fromDate, username, limit, limit*page); err != nil {
|
||||||
if errors.Is(err, sql.ErrNoRows) {
|
if errors.Is(err, sql.ErrNoRows) {
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
|
|
||||||
"github.com/authelia/authelia/v4/internal/models"
|
"github.com/authelia/authelia/v4/internal/model"
|
||||||
"github.com/authelia/authelia/v4/internal/utils"
|
"github.com/authelia/authelia/v4/internal/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ func (p *SQLProvider) SchemaEncryptionChangeKey(ctx context.Context, encryptionK
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *SQLProvider) schemaEncryptionChangeKeyTOTP(ctx context.Context, tx *sqlx.Tx, key [32]byte) (err error) {
|
func (p *SQLProvider) schemaEncryptionChangeKeyTOTP(ctx context.Context, tx *sqlx.Tx, key [32]byte) (err error) {
|
||||||
var configs []models.TOTPConfiguration
|
var configs []model.TOTPConfiguration
|
||||||
|
|
||||||
for page := 0; true; page++ {
|
for page := 0; true; page++ {
|
||||||
if configs, err = p.LoadTOTPConfigurations(ctx, 10, page); err != nil {
|
if configs, err = p.LoadTOTPConfigurations(ctx, 10, page); err != nil {
|
||||||
|
@ -80,7 +80,7 @@ func (p *SQLProvider) schemaEncryptionChangeKeyTOTP(ctx context.Context, tx *sql
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *SQLProvider) schemaEncryptionChangeKeyWebauthn(ctx context.Context, tx *sqlx.Tx, key [32]byte) (err error) {
|
func (p *SQLProvider) schemaEncryptionChangeKeyWebauthn(ctx context.Context, tx *sqlx.Tx, key [32]byte) (err error) {
|
||||||
var devices []models.WebauthnDevice
|
var devices []model.WebauthnDevice
|
||||||
|
|
||||||
for page := 0; true; page++ {
|
for page := 0; true; page++ {
|
||||||
if devices, err = p.LoadWebauthnDevices(ctx, 10, page); err != nil {
|
if devices, err = p.LoadWebauthnDevices(ctx, 10, page); err != nil {
|
||||||
|
@ -163,7 +163,7 @@ func (p *SQLProvider) SchemaEncryptionCheckKey(ctx context.Context, verbose bool
|
||||||
|
|
||||||
func (p *SQLProvider) schemaEncryptionCheckTOTP(ctx context.Context) (err error) {
|
func (p *SQLProvider) schemaEncryptionCheckTOTP(ctx context.Context) (err error) {
|
||||||
var (
|
var (
|
||||||
config models.TOTPConfiguration
|
config model.TOTPConfiguration
|
||||||
row int
|
row int
|
||||||
invalid int
|
invalid int
|
||||||
total int
|
total int
|
||||||
|
@ -212,7 +212,7 @@ func (p *SQLProvider) schemaEncryptionCheckTOTP(ctx context.Context) (err error)
|
||||||
|
|
||||||
func (p *SQLProvider) schemaEncryptionCheckU2F(ctx context.Context) (err error) {
|
func (p *SQLProvider) schemaEncryptionCheckU2F(ctx context.Context) (err error) {
|
||||||
var (
|
var (
|
||||||
device models.U2FDevice
|
device model.U2FDevice
|
||||||
row int
|
row int
|
||||||
invalid int
|
invalid int
|
||||||
total int
|
total int
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
|
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
|
|
||||||
"github.com/authelia/authelia/v4/internal/models"
|
"github.com/authelia/authelia/v4/internal/model"
|
||||||
"github.com/authelia/authelia/v4/internal/utils"
|
"github.com/authelia/authelia/v4/internal/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -81,8 +81,8 @@ func (p *SQLProvider) SchemaVersion(ctx context.Context) (version int, err error
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *SQLProvider) schemaLatestMigration(ctx context.Context) (migration *models.Migration, err error) {
|
func (p *SQLProvider) schemaLatestMigration(ctx context.Context) (migration *model.Migration, err error) {
|
||||||
migration = &models.Migration{}
|
migration = &model.Migration{}
|
||||||
|
|
||||||
err = p.db.QueryRowxContext(ctx, p.sqlSelectLatestMigration).StructScan(migration)
|
err = p.db.QueryRowxContext(ctx, p.sqlSelectLatestMigration).StructScan(migration)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -93,7 +93,7 @@ func (p *SQLProvider) schemaLatestMigration(ctx context.Context) (migration *mod
|
||||||
}
|
}
|
||||||
|
|
||||||
// SchemaMigrationHistory returns migration history rows.
|
// SchemaMigrationHistory returns migration history rows.
|
||||||
func (p *SQLProvider) SchemaMigrationHistory(ctx context.Context) (migrations []models.Migration, err error) {
|
func (p *SQLProvider) SchemaMigrationHistory(ctx context.Context) (migrations []model.Migration, err error) {
|
||||||
rows, err := p.db.QueryxContext(ctx, p.sqlSelectMigrations)
|
rows, err := p.db.QueryxContext(ctx, p.sqlSelectMigrations)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -105,7 +105,7 @@ func (p *SQLProvider) SchemaMigrationHistory(ctx context.Context) (migrations []
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
var migration models.Migration
|
var migration model.Migration
|
||||||
|
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
err = rows.StructScan(&migration)
|
err = rows.StructScan(&migration)
|
||||||
|
@ -221,7 +221,7 @@ func (p *SQLProvider) schemaMigrateRollback(ctx context.Context, prior, after in
|
||||||
return fmt.Errorf("migration rollback complete. rollback caused by: %+v", migrateErr)
|
return fmt.Errorf("migration rollback complete. rollback caused by: %+v", migrateErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *SQLProvider) schemaMigrateApply(ctx context.Context, migration models.SchemaMigration) (err error) {
|
func (p *SQLProvider) schemaMigrateApply(ctx context.Context, migration model.SchemaMigration) (err error) {
|
||||||
_, err = p.db.ExecContext(ctx, migration.Query)
|
_, err = p.db.ExecContext(ctx, migration.Query)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf(errFmtFailedMigration, migration.Version, migration.Name, err)
|
return fmt.Errorf(errFmtFailedMigration, migration.Version, migration.Name, err)
|
||||||
|
@ -246,7 +246,7 @@ func (p *SQLProvider) schemaMigrateApply(ctx context.Context, migration models.S
|
||||||
return p.schemaMigrateFinalize(ctx, migration)
|
return p.schemaMigrateFinalize(ctx, migration)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p SQLProvider) schemaMigrateFinalize(ctx context.Context, migration models.SchemaMigration) (err error) {
|
func (p SQLProvider) schemaMigrateFinalize(ctx context.Context, migration model.SchemaMigration) (err error) {
|
||||||
return p.schemaMigrateFinalizeAdvanced(ctx, migration.Before(), migration.After())
|
return p.schemaMigrateFinalizeAdvanced(ctx, migration.Before(), migration.After())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,7 +262,7 @@ func (p *SQLProvider) schemaMigrateFinalizeAdvanced(ctx context.Context, before,
|
||||||
}
|
}
|
||||||
|
|
||||||
// SchemaMigrationsUp returns a list of migrations up available between the current version and the provided version.
|
// SchemaMigrationsUp returns a list of migrations up available between the current version and the provided version.
|
||||||
func (p *SQLProvider) SchemaMigrationsUp(ctx context.Context, version int) (migrations []models.SchemaMigration, err error) {
|
func (p *SQLProvider) SchemaMigrationsUp(ctx context.Context, version int) (migrations []model.SchemaMigration, err error) {
|
||||||
current, err := p.SchemaVersion(ctx)
|
current, err := p.SchemaVersion(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return migrations, err
|
return migrations, err
|
||||||
|
@ -280,7 +280,7 @@ func (p *SQLProvider) SchemaMigrationsUp(ctx context.Context, version int) (migr
|
||||||
}
|
}
|
||||||
|
|
||||||
// SchemaMigrationsDown returns a list of migrations down available between the current version and the provided version.
|
// SchemaMigrationsDown returns a list of migrations down available between the current version and the provided version.
|
||||||
func (p *SQLProvider) SchemaMigrationsDown(ctx context.Context, version int) (migrations []models.SchemaMigration, err error) {
|
func (p *SQLProvider) SchemaMigrationsDown(ctx context.Context, version int) (migrations []model.SchemaMigration, err error) {
|
||||||
current, err := p.SchemaVersion(ctx)
|
current, err := p.SchemaVersion(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return migrations, err
|
return migrations, err
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/authelia/authelia/v4/internal/models"
|
"github.com/authelia/authelia/v4/internal/model"
|
||||||
"github.com/authelia/authelia/v4/internal/utils"
|
"github.com/authelia/authelia/v4/internal/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -169,13 +169,13 @@ func (p *SQLProvider) schemaMigratePre1To1AuthenticationLogs(ctx context.Context
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *SQLProvider) schemaMigratePre1To1AuthenticationLogsGetRows(ctx context.Context, page int) (attempts []models.AuthenticationAttempt, err error) {
|
func (p *SQLProvider) schemaMigratePre1To1AuthenticationLogsGetRows(ctx context.Context, page int) (attempts []model.AuthenticationAttempt, err error) {
|
||||||
rows, err := p.db.QueryxContext(ctx, fmt.Sprintf(p.db.Rebind(queryFmtPre1To1SelectAuthenticationLogs), tablePrefixBackup+tableAuthenticationLogs), page*100)
|
rows, err := p.db.QueryxContext(ctx, fmt.Sprintf(p.db.Rebind(queryFmtPre1To1SelectAuthenticationLogs), tablePrefixBackup+tableAuthenticationLogs), page*100)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
attempts = make([]models.AuthenticationAttempt, 0, 100)
|
attempts = make([]model.AuthenticationAttempt, 0, 100)
|
||||||
|
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var (
|
var (
|
||||||
|
@ -189,7 +189,7 @@ func (p *SQLProvider) schemaMigratePre1To1AuthenticationLogsGetRows(ctx context.
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
attempts = append(attempts, models.AuthenticationAttempt{Username: username, Successful: successful, Time: time.Unix(timestamp, 0)})
|
attempts = append(attempts, model.AuthenticationAttempt{Username: username, Successful: successful, Time: time.Unix(timestamp, 0)})
|
||||||
}
|
}
|
||||||
|
|
||||||
return attempts, nil
|
return attempts, nil
|
||||||
|
@ -201,7 +201,7 @@ func (p *SQLProvider) schemaMigratePre1To1TOTP(ctx context.Context) (err error)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var totpConfigs []models.TOTPConfiguration
|
var totpConfigs []model.TOTPConfiguration
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := rows.Close(); err != nil {
|
if err := rows.Close(); err != nil {
|
||||||
|
@ -222,7 +222,7 @@ func (p *SQLProvider) schemaMigratePre1To1TOTP(ctx context.Context) (err error)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
totpConfigs = append(totpConfigs, models.TOTPConfiguration{Username: username, Secret: encryptedSecret})
|
totpConfigs = append(totpConfigs, model.TOTPConfiguration{Username: username, Secret: encryptedSecret})
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, config := range totpConfigs {
|
for _, config := range totpConfigs {
|
||||||
|
@ -247,7 +247,7 @@ func (p *SQLProvider) schemaMigratePre1To1U2F(ctx context.Context) (err error) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
var devices []models.U2FDevice
|
var devices []model.U2FDevice
|
||||||
|
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var username, keyHandleBase64, publicKeyBase64 string
|
var username, keyHandleBase64, publicKeyBase64 string
|
||||||
|
@ -272,7 +272,7 @@ func (p *SQLProvider) schemaMigratePre1To1U2F(ctx context.Context) (err error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
devices = append(devices, models.U2FDevice{Username: username, KeyHandle: keyHandle, PublicKey: encryptedPublicKey})
|
devices = append(devices, model.U2FDevice{Username: username, KeyHandle: keyHandle, PublicKey: encryptedPublicKey})
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, device := range devices {
|
for _, device := range devices {
|
||||||
|
@ -364,15 +364,15 @@ func (p *SQLProvider) schemaMigrate1ToPre1AuthenticationLogs(ctx context.Context
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *SQLProvider) schemaMigrate1ToPre1AuthenticationLogsGetRows(ctx context.Context, page int) (attempts []models.AuthenticationAttempt, err error) {
|
func (p *SQLProvider) schemaMigrate1ToPre1AuthenticationLogsGetRows(ctx context.Context, page int) (attempts []model.AuthenticationAttempt, err error) {
|
||||||
rows, err := p.db.QueryxContext(ctx, fmt.Sprintf(p.db.Rebind(queryFmt1ToPre1SelectAuthenticationLogs), tablePrefixBackup+tableAuthenticationLogs), page*100)
|
rows, err := p.db.QueryxContext(ctx, fmt.Sprintf(p.db.Rebind(queryFmt1ToPre1SelectAuthenticationLogs), tablePrefixBackup+tableAuthenticationLogs), page*100)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
attempts = make([]models.AuthenticationAttempt, 0, 100)
|
attempts = make([]model.AuthenticationAttempt, 0, 100)
|
||||||
|
|
||||||
var attempt models.AuthenticationAttempt
|
var attempt model.AuthenticationAttempt
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
err = rows.StructScan(&attempt)
|
err = rows.StructScan(&attempt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -391,7 +391,7 @@ func (p *SQLProvider) schemaMigrate1ToPre1TOTP(ctx context.Context) (err error)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var totpConfigs []models.TOTPConfiguration
|
var totpConfigs []model.TOTPConfiguration
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := rows.Close(); err != nil {
|
if err := rows.Close(); err != nil {
|
||||||
|
@ -415,7 +415,7 @@ func (p *SQLProvider) schemaMigrate1ToPre1TOTP(ctx context.Context) (err error)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
totpConfigs = append(totpConfigs, models.TOTPConfiguration{Username: username, Secret: secretClearText})
|
totpConfigs = append(totpConfigs, model.TOTPConfiguration{Username: username, Secret: secretClearText})
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, config := range totpConfigs {
|
for _, config := range totpConfigs {
|
||||||
|
@ -441,8 +441,8 @@ func (p *SQLProvider) schemaMigrate1ToPre1U2F(ctx context.Context) (err error) {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
var (
|
var (
|
||||||
devices []models.U2FDevice
|
devices []model.U2FDevice
|
||||||
device models.U2FDevice
|
device model.U2FDevice
|
||||||
)
|
)
|
||||||
|
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
|
|
||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
|
|
||||||
"github.com/authelia/authelia/v4/internal/models"
|
"github.com/authelia/authelia/v4/internal/model"
|
||||||
"github.com/authelia/authelia/v4/internal/storage"
|
"github.com/authelia/authelia/v4/internal/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -293,11 +293,11 @@ func (s *CLISuite) TestStorage03ShouldExportTOTP() {
|
||||||
expectedLinesCSV = append(expectedLinesCSV, "issuer,username,algorithm,digits,period,secret")
|
expectedLinesCSV = append(expectedLinesCSV, "issuer,username,algorithm,digits,period,secret")
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
config models.TOTPConfiguration
|
config model.TOTPConfiguration
|
||||||
png bool
|
png bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
config: models.TOTPConfiguration{
|
config: model.TOTPConfiguration{
|
||||||
Username: "john",
|
Username: "john",
|
||||||
Period: 30,
|
Period: 30,
|
||||||
Digits: 6,
|
Digits: 6,
|
||||||
|
@ -305,7 +305,7 @@ func (s *CLISuite) TestStorage03ShouldExportTOTP() {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
config: models.TOTPConfiguration{
|
config: model.TOTPConfiguration{
|
||||||
Username: "mary",
|
Username: "mary",
|
||||||
Period: 45,
|
Period: 45,
|
||||||
Digits: 6,
|
Digits: 6,
|
||||||
|
@ -313,7 +313,7 @@ func (s *CLISuite) TestStorage03ShouldExportTOTP() {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
config: models.TOTPConfiguration{
|
config: model.TOTPConfiguration{
|
||||||
Username: "fred",
|
Username: "fred",
|
||||||
Period: 30,
|
Period: 30,
|
||||||
Digits: 8,
|
Digits: 8,
|
||||||
|
@ -321,7 +321,7 @@ func (s *CLISuite) TestStorage03ShouldExportTOTP() {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
config: models.TOTPConfiguration{
|
config: model.TOTPConfiguration{
|
||||||
Username: "jone",
|
Username: "jone",
|
||||||
Period: 30,
|
Period: 30,
|
||||||
Digits: 6,
|
Digits: 6,
|
||||||
|
@ -332,7 +332,7 @@ func (s *CLISuite) TestStorage03ShouldExportTOTP() {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
config *models.TOTPConfiguration
|
config *model.TOTPConfiguration
|
||||||
fileInfo os.FileInfo
|
fileInfo os.FileInfo
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
|
|
||||||
"github.com/authelia/authelia/v4/internal/duo"
|
"github.com/authelia/authelia/v4/internal/duo"
|
||||||
"github.com/authelia/authelia/v4/internal/models"
|
"github.com/authelia/authelia/v4/internal/model"
|
||||||
"github.com/authelia/authelia/v4/internal/storage"
|
"github.com/authelia/authelia/v4/internal/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -153,7 +153,7 @@ func (s *DuoPushWebDriverSuite) TestShouldSelectDevice() {
|
||||||
|
|
||||||
// Set default 2FA preference to enable Select Device link in frontend.
|
// Set default 2FA preference to enable Select Device link in frontend.
|
||||||
provider := storage.NewSQLiteProvider(&storageLocalTmpConfig)
|
provider := storage.NewSQLiteProvider(&storageLocalTmpConfig)
|
||||||
require.NoError(s.T(), provider.SavePreferredDuoDevice(ctx, models.DuoDevice{Username: "john", Device: "ABCDEFGHIJ1234567890", Method: "push"}))
|
require.NoError(s.T(), provider.SavePreferredDuoDevice(ctx, model.DuoDevice{Username: "john", Device: "ABCDEFGHIJ1234567890", Method: "push"}))
|
||||||
|
|
||||||
var PreAuthAPIResponse = duo.PreAuthResponse{
|
var PreAuthAPIResponse = duo.PreAuthResponse{
|
||||||
Result: "auth",
|
Result: "auth",
|
||||||
|
@ -232,7 +232,7 @@ func (s *DuoPushWebDriverSuite) TestShouldSelectNewDeviceAfterSavedDeviceMethodI
|
||||||
|
|
||||||
// Setup unsupported Duo device in DB.
|
// Setup unsupported Duo device in DB.
|
||||||
provider := storage.NewSQLiteProvider(&storageLocalTmpConfig)
|
provider := storage.NewSQLiteProvider(&storageLocalTmpConfig)
|
||||||
require.NoError(s.T(), provider.SavePreferredDuoDevice(ctx, models.DuoDevice{Username: "john", Device: "ABCDEFGHIJ1234567890", Method: "sms"}))
|
require.NoError(s.T(), provider.SavePreferredDuoDevice(ctx, model.DuoDevice{Username: "john", Device: "ABCDEFGHIJ1234567890", Method: "sms"}))
|
||||||
ConfigureDuoPreAuth(s.T(), PreAuthAPIResponse)
|
ConfigureDuoPreAuth(s.T(), PreAuthAPIResponse)
|
||||||
ConfigureDuo(s.T(), Allow)
|
ConfigureDuo(s.T(), Allow)
|
||||||
|
|
||||||
|
@ -258,7 +258,7 @@ func (s *DuoPushWebDriverSuite) TestShouldAutoSelectNewDeviceAfterSavedDeviceIsN
|
||||||
|
|
||||||
// Setup unsupported Duo device in DB.
|
// Setup unsupported Duo device in DB.
|
||||||
provider := storage.NewSQLiteProvider(&storageLocalTmpConfig)
|
provider := storage.NewSQLiteProvider(&storageLocalTmpConfig)
|
||||||
require.NoError(s.T(), provider.SavePreferredDuoDevice(ctx, models.DuoDevice{Username: "john", Device: "ABCDEFGHIJ1234567890", Method: "push"}))
|
require.NoError(s.T(), provider.SavePreferredDuoDevice(ctx, model.DuoDevice{Username: "john", Device: "ABCDEFGHIJ1234567890", Method: "push"}))
|
||||||
ConfigureDuoPreAuth(s.T(), PreAuthAPIResponse)
|
ConfigureDuoPreAuth(s.T(), PreAuthAPIResponse)
|
||||||
ConfigureDuo(s.T(), Allow)
|
ConfigureDuo(s.T(), Allow)
|
||||||
|
|
||||||
|
@ -277,7 +277,7 @@ func (s *DuoPushWebDriverSuite) TestShouldFailSelectionBecauseOfSelectionBypasse
|
||||||
}
|
}
|
||||||
|
|
||||||
provider := storage.NewSQLiteProvider(&storageLocalTmpConfig)
|
provider := storage.NewSQLiteProvider(&storageLocalTmpConfig)
|
||||||
require.NoError(s.T(), provider.SavePreferredDuoDevice(ctx, models.DuoDevice{Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "push"}))
|
require.NoError(s.T(), provider.SavePreferredDuoDevice(ctx, model.DuoDevice{Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "push"}))
|
||||||
ConfigureDuoPreAuth(s.T(), PreAuthAPIResponse)
|
ConfigureDuoPreAuth(s.T(), PreAuthAPIResponse)
|
||||||
ConfigureDuo(s.T(), Deny)
|
ConfigureDuo(s.T(), Deny)
|
||||||
|
|
||||||
|
@ -297,7 +297,7 @@ func (s *DuoPushWebDriverSuite) TestShouldFailSelectionBecauseOfSelectionDenied(
|
||||||
}
|
}
|
||||||
|
|
||||||
provider := storage.NewSQLiteProvider(&storageLocalTmpConfig)
|
provider := storage.NewSQLiteProvider(&storageLocalTmpConfig)
|
||||||
require.NoError(s.T(), provider.SavePreferredDuoDevice(ctx, models.DuoDevice{Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "push"}))
|
require.NoError(s.T(), provider.SavePreferredDuoDevice(ctx, model.DuoDevice{Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "push"}))
|
||||||
ConfigureDuoPreAuth(s.T(), PreAuthAPIResponse)
|
ConfigureDuoPreAuth(s.T(), PreAuthAPIResponse)
|
||||||
ConfigureDuo(s.T(), Deny)
|
ConfigureDuo(s.T(), Deny)
|
||||||
|
|
||||||
|
@ -318,7 +318,7 @@ func (s *DuoPushWebDriverSuite) TestShouldFailAuthenticationBecausePreauthDenied
|
||||||
}
|
}
|
||||||
|
|
||||||
provider := storage.NewSQLiteProvider(&storageLocalTmpConfig)
|
provider := storage.NewSQLiteProvider(&storageLocalTmpConfig)
|
||||||
require.NoError(s.T(), provider.SavePreferredDuoDevice(ctx, models.DuoDevice{Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "push"}))
|
require.NoError(s.T(), provider.SavePreferredDuoDevice(ctx, model.DuoDevice{Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "push"}))
|
||||||
ConfigureDuoPreAuth(s.T(), PreAuthAPIResponse)
|
ConfigureDuoPreAuth(s.T(), PreAuthAPIResponse)
|
||||||
|
|
||||||
s.doLoginOneFactor(s.T(), s.Context(ctx), "john", "password", false, "")
|
s.doLoginOneFactor(s.T(), s.Context(ctx), "john", "password", false, "")
|
||||||
|
@ -345,7 +345,7 @@ func (s *DuoPushWebDriverSuite) TestShouldSucceedAuthentication() {
|
||||||
|
|
||||||
// Setup Duo device in DB.
|
// Setup Duo device in DB.
|
||||||
provider := storage.NewSQLiteProvider(&storageLocalTmpConfig)
|
provider := storage.NewSQLiteProvider(&storageLocalTmpConfig)
|
||||||
require.NoError(s.T(), provider.SavePreferredDuoDevice(ctx, models.DuoDevice{Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "push"}))
|
require.NoError(s.T(), provider.SavePreferredDuoDevice(ctx, model.DuoDevice{Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "push"}))
|
||||||
ConfigureDuoPreAuth(s.T(), PreAuthAPIResponse)
|
ConfigureDuoPreAuth(s.T(), PreAuthAPIResponse)
|
||||||
ConfigureDuo(s.T(), Allow)
|
ConfigureDuo(s.T(), Allow)
|
||||||
|
|
||||||
|
@ -372,7 +372,7 @@ func (s *DuoPushWebDriverSuite) TestShouldFailAuthentication() {
|
||||||
|
|
||||||
// Setup Duo device in DB.
|
// Setup Duo device in DB.
|
||||||
provider := storage.NewSQLiteProvider(&storageLocalTmpConfig)
|
provider := storage.NewSQLiteProvider(&storageLocalTmpConfig)
|
||||||
require.NoError(s.T(), provider.SavePreferredDuoDevice(ctx, models.DuoDevice{Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "push"}))
|
require.NoError(s.T(), provider.SavePreferredDuoDevice(ctx, model.DuoDevice{Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "push"}))
|
||||||
ConfigureDuoPreAuth(s.T(), PreAuthAPIResponse)
|
ConfigureDuoPreAuth(s.T(), PreAuthAPIResponse)
|
||||||
ConfigureDuo(s.T(), Deny)
|
ConfigureDuo(s.T(), Deny)
|
||||||
|
|
||||||
|
@ -431,7 +431,7 @@ func (s *DuoPushDefaultRedirectionSuite) TestUserIsRedirectedToDefaultURL() {
|
||||||
|
|
||||||
// Setup Duo device in DB.
|
// Setup Duo device in DB.
|
||||||
provider := storage.NewSQLiteProvider(&storageLocalTmpConfig)
|
provider := storage.NewSQLiteProvider(&storageLocalTmpConfig)
|
||||||
require.NoError(s.T(), provider.SavePreferredDuoDevice(ctx, models.DuoDevice{Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "push"}))
|
require.NoError(s.T(), provider.SavePreferredDuoDevice(ctx, model.DuoDevice{Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "push"}))
|
||||||
ConfigureDuoPreAuth(s.T(), PreAuthAPIResponse)
|
ConfigureDuoPreAuth(s.T(), PreAuthAPIResponse)
|
||||||
ConfigureDuo(s.T(), Allow)
|
ConfigureDuo(s.T(), Allow)
|
||||||
|
|
||||||
|
@ -477,7 +477,7 @@ func (s *DuoPushSuite) TestUserPreferencesScenario() {
|
||||||
|
|
||||||
// Setup Duo device in DB.
|
// Setup Duo device in DB.
|
||||||
provider := storage.NewSQLiteProvider(&storageLocalTmpConfig)
|
provider := storage.NewSQLiteProvider(&storageLocalTmpConfig)
|
||||||
require.NoError(s.T(), provider.SavePreferredDuoDevice(ctx, models.DuoDevice{Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "push"}))
|
require.NoError(s.T(), provider.SavePreferredDuoDevice(ctx, model.DuoDevice{Username: "john", Device: "12345ABCDEFGHIJ67890", Method: "push"}))
|
||||||
ConfigureDuoPreAuth(s.T(), PreAuthAPIResponse)
|
ConfigureDuoPreAuth(s.T(), PreAuthAPIResponse)
|
||||||
ConfigureDuo(s.T(), Allow)
|
ConfigureDuo(s.T(), Allow)
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
package totp
|
package totp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/authelia/authelia/v4/internal/models"
|
"github.com/authelia/authelia/v4/internal/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Provider for TOTP functionality.
|
// Provider for TOTP functionality.
|
||||||
type Provider interface {
|
type Provider interface {
|
||||||
Generate(username string) (config *models.TOTPConfiguration, err error)
|
Generate(username string) (config *model.TOTPConfiguration, err error)
|
||||||
GenerateCustom(username string, algorithm string, digits, period, secretSize uint) (config *models.TOTPConfiguration, err error)
|
GenerateCustom(username string, algorithm string, digits, period, secretSize uint) (config *model.TOTPConfiguration, err error)
|
||||||
Validate(token string, config *models.TOTPConfiguration) (valid bool, err error)
|
Validate(token string, config *model.TOTPConfiguration) (valid bool, err error)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"github.com/pquerna/otp/totp"
|
"github.com/pquerna/otp/totp"
|
||||||
|
|
||||||
"github.com/authelia/authelia/v4/internal/configuration/schema"
|
"github.com/authelia/authelia/v4/internal/configuration/schema"
|
||||||
"github.com/authelia/authelia/v4/internal/models"
|
"github.com/authelia/authelia/v4/internal/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewTimeBasedProvider creates a new totp.TimeBased which implements the totp.Provider.
|
// NewTimeBasedProvider creates a new totp.TimeBased which implements the totp.Provider.
|
||||||
|
@ -32,7 +32,7 @@ type TimeBased struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenerateCustom generates a TOTP with custom options.
|
// GenerateCustom generates a TOTP with custom options.
|
||||||
func (p TimeBased) GenerateCustom(username, algorithm string, digits, period, secretSize uint) (config *models.TOTPConfiguration, err error) {
|
func (p TimeBased) GenerateCustom(username, algorithm string, digits, period, secretSize uint) (config *model.TOTPConfiguration, err error) {
|
||||||
var key *otp.Key
|
var key *otp.Key
|
||||||
|
|
||||||
opts := totp.GenerateOpts{
|
opts := totp.GenerateOpts{
|
||||||
|
@ -48,7 +48,7 @@ func (p TimeBased) GenerateCustom(username, algorithm string, digits, period, se
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
config = &models.TOTPConfiguration{
|
config = &model.TOTPConfiguration{
|
||||||
CreatedAt: time.Now(),
|
CreatedAt: time.Now(),
|
||||||
Username: username,
|
Username: username,
|
||||||
Issuer: p.config.Issuer,
|
Issuer: p.config.Issuer,
|
||||||
|
@ -62,12 +62,12 @@ func (p TimeBased) GenerateCustom(username, algorithm string, digits, period, se
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate generates a TOTP with default options.
|
// Generate generates a TOTP with default options.
|
||||||
func (p TimeBased) Generate(username string) (config *models.TOTPConfiguration, err error) {
|
func (p TimeBased) Generate(username string) (config *model.TOTPConfiguration, err error) {
|
||||||
return p.GenerateCustom(username, p.config.Algorithm, p.config.Digits, p.config.Period, 32)
|
return p.GenerateCustom(username, p.config.Algorithm, p.config.Digits, p.config.Period, 32)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate the token against the given configuration.
|
// Validate the token against the given configuration.
|
||||||
func (p TimeBased) Validate(token string, config *models.TOTPConfiguration) (valid bool, err error) {
|
func (p TimeBased) Validate(token string, config *model.TOTPConfiguration) (valid bool, err error) {
|
||||||
opts := totp.ValidateOpts{
|
opts := totp.ValidateOpts{
|
||||||
Period: config.Period,
|
Period: config.Period,
|
||||||
Skew: p.skew,
|
Skew: p.skew,
|
||||||
|
|
|
@ -33,7 +33,7 @@ module.exports = {
|
||||||
"logging",
|
"logging",
|
||||||
"middlewares",
|
"middlewares",
|
||||||
"mocks",
|
"mocks",
|
||||||
"models",
|
"model",
|
||||||
"notification",
|
"notification",
|
||||||
"npm",
|
"npm",
|
||||||
"ntp",
|
"ntp",
|
||||||
|
|
Loading…
Reference in New Issue