refactor: adjust settings components
parent
4239db6171
commit
dd781ffc51
|
@ -3,11 +3,13 @@ package handlers
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"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/model"
|
||||||
"github.com/authelia/authelia/v4/internal/regulation"
|
"github.com/authelia/authelia/v4/internal/regulation"
|
||||||
"github.com/authelia/authelia/v4/internal/storage"
|
"github.com/authelia/authelia/v4/internal/storage"
|
||||||
)
|
)
|
||||||
|
@ -30,11 +32,11 @@ func getWebauthnDeviceIDFromContext(ctx *middlewares.AutheliaCtx) (int, error) {
|
||||||
return deviceID, nil
|
return deviceID, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// WebauthnDevicesGet returns all devices registered for the current user.
|
// WebauthnDevicesGET returns all devices registered for the current user.
|
||||||
func WebauthnDevicesGet(ctx *middlewares.AutheliaCtx) {
|
func WebauthnDevicesGET(ctx *middlewares.AutheliaCtx) {
|
||||||
userSession := ctx.GetSession()
|
s := ctx.GetSession()
|
||||||
|
|
||||||
devices, err := ctx.Providers.StorageProvider.LoadWebauthnDevicesByUsername(ctx, userSession.Username)
|
devices, err := ctx.Providers.StorageProvider.LoadWebauthnDevicesByUsername(ctx, s.Username)
|
||||||
|
|
||||||
if err != nil && err != storage.ErrNoWebauthnDevice {
|
if err != nil && err != storage.ErrNoWebauthnDevice {
|
||||||
ctx.Error(err, messageOperationFailed)
|
ctx.Error(err, messageOperationFailed)
|
||||||
|
@ -47,19 +49,20 @@ func WebauthnDevicesGet(ctx *middlewares.AutheliaCtx) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WebauthnDeviceUpdate updates the description for a specific device for the current user.
|
// WebauthnDevicePUT updates the description for a specific device for the current user.
|
||||||
func WebauthnDeviceUpdate(ctx *middlewares.AutheliaCtx) {
|
func WebauthnDevicePUT(ctx *middlewares.AutheliaCtx) {
|
||||||
type requestPostData struct {
|
var (
|
||||||
Description string `json:"description"`
|
bodyJSON bodyEditWebauthnDeviceRequest
|
||||||
}
|
|
||||||
|
|
||||||
var postData *requestPostData
|
id int
|
||||||
|
device *model.WebauthnDevice
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
userSession := ctx.GetSession()
|
s := ctx.GetSession()
|
||||||
|
|
||||||
err := json.Unmarshal(ctx.PostBody(), &postData)
|
if err = json.Unmarshal(ctx.PostBody(), &bodyJSON); err != nil {
|
||||||
if err != nil {
|
ctx.Logger.Errorf("Unable to parse %s update request data for user '%s': %+v", regulation.AuthTypeWebauthn, s.Username, err)
|
||||||
ctx.Logger.Errorf("Unable to parse %s update request data for user '%s': %+v", regulation.AuthTypeWebauthn, userSession.Username, err)
|
|
||||||
|
|
||||||
ctx.SetStatusCode(fasthttp.StatusBadRequest)
|
ctx.SetStatusCode(fasthttp.StatusBadRequest)
|
||||||
ctx.Error(err, messageOperationFailed)
|
ctx.Error(err, messageOperationFailed)
|
||||||
|
@ -67,28 +70,54 @@ func WebauthnDeviceUpdate(ctx *middlewares.AutheliaCtx) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
deviceID, err := getWebauthnDeviceIDFromContext(ctx)
|
if id, err = getWebauthnDeviceIDFromContext(ctx); err != nil {
|
||||||
if err != nil {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ctx.Providers.StorageProvider.UpdateWebauthnDeviceDescription(ctx, userSession.Username, deviceID, postData.Description); err != nil {
|
if device, err = ctx.Providers.StorageProvider.LoadWebauthnDeviceByID(ctx, id); err != nil {
|
||||||
|
ctx.Error(err, messageOperationFailed)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if device.Username != s.Username {
|
||||||
|
ctx.Error(fmt.Errorf("user '%s' tried to delete device with id '%d' which belongs to '%s", s.Username, device.ID, device.Username), messageOperationFailed)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = ctx.Providers.StorageProvider.UpdateWebauthnDeviceDescription(ctx, s.Username, id, bodyJSON.Description); err != nil {
|
||||||
ctx.Error(err, messageOperationFailed)
|
ctx.Error(err, messageOperationFailed)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WebauthnDeviceDelete deletes a specific device for the current user.
|
// WebauthnDeviceDELETE deletes a specific device for the current user.
|
||||||
func WebauthnDeviceDelete(ctx *middlewares.AutheliaCtx) {
|
func WebauthnDeviceDELETE(ctx *middlewares.AutheliaCtx) {
|
||||||
userSession := ctx.GetSession()
|
var (
|
||||||
|
id int
|
||||||
|
device *model.WebauthnDevice
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
deviceID, err := getWebauthnDeviceIDFromContext(ctx)
|
if id, err = getWebauthnDeviceIDFromContext(ctx); err != nil {
|
||||||
if err != nil {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ctx.Providers.StorageProvider.DeleteWebauthnDeviceByUsernameAndID(ctx, userSession.Username, deviceID); err != nil {
|
if device, err = ctx.Providers.StorageProvider.LoadWebauthnDeviceByID(ctx, id); err != nil {
|
||||||
ctx.Error(err, messageOperationFailed)
|
ctx.Error(err, messageOperationFailed)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s := ctx.GetSession()
|
||||||
|
|
||||||
|
if device.Username != s.Username {
|
||||||
|
ctx.Error(fmt.Errorf("user '%s' tried to delete device with id '%d' which belongs to '%s", s.Username, device.ID, device.Username), messageOperationFailed)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = ctx.Providers.StorageProvider.DeleteWebauthnDevice(ctx, device.KID.String()); err != nil {
|
||||||
|
ctx.Error(err, messageOperationFailed)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.ReplyOK()
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,10 @@ type bodySignWebauthnRequest struct {
|
||||||
WorkflowID string `json:"workflowID"`
|
WorkflowID string `json:"workflowID"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type bodyEditWebauthnDeviceRequest struct {
|
||||||
|
Description string `json:"description"`
|
||||||
|
}
|
||||||
|
|
||||||
// bodySignDuoRequest is the model of the request body of Duo 2FA authentication endpoint.
|
// bodySignDuoRequest is the model of the request body of Duo 2FA authentication endpoint.
|
||||||
type bodySignDuoRequest struct {
|
type bodySignDuoRequest struct {
|
||||||
TargetURL string `json:"targetURL"`
|
TargetURL string `json:"targetURL"`
|
||||||
|
|
|
@ -194,20 +194,6 @@ func (mr *MockStorageMockRecorder) DeleteWebauthnDeviceByUsername(arg0, arg1, ar
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteWebauthnDeviceByUsername", reflect.TypeOf((*MockStorage)(nil).DeleteWebauthnDeviceByUsername), arg0, arg1, arg2)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteWebauthnDeviceByUsername", reflect.TypeOf((*MockStorage)(nil).DeleteWebauthnDeviceByUsername), arg0, arg1, arg2)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteWebauthnDeviceByUsernameAndID mocks base method.
|
|
||||||
func (m *MockStorage) DeleteWebauthnDeviceByUsernameAndID(arg0 context.Context, arg1 string, arg2 int) error {
|
|
||||||
m.ctrl.T.Helper()
|
|
||||||
ret := m.ctrl.Call(m, "DeleteWebauthnDeviceByUsernameAndID", arg0, arg1, arg2)
|
|
||||||
ret0, _ := ret[0].(error)
|
|
||||||
return ret0
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteWebauthnDeviceByUsernameAndID indicates an expected call of DeleteWebauthnDeviceByUsernameAndID.
|
|
||||||
func (mr *MockStorageMockRecorder) DeleteWebauthnDeviceByUsernameAndID(arg0, arg1, arg2 interface{}) *gomock.Call {
|
|
||||||
mr.mock.ctrl.T.Helper()
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteWebauthnDeviceByUsernameAndID", reflect.TypeOf((*MockStorage)(nil).DeleteWebauthnDeviceByUsernameAndID), arg0, arg1, arg2)
|
|
||||||
}
|
|
||||||
|
|
||||||
// FindIdentityVerification mocks base method.
|
// FindIdentityVerification mocks base method.
|
||||||
func (m *MockStorage) FindIdentityVerification(arg0 context.Context, arg1 string) (bool, error) {
|
func (m *MockStorage) FindIdentityVerification(arg0 context.Context, arg1 string) (bool, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
|
@ -418,6 +404,21 @@ func (mr *MockStorageMockRecorder) LoadUserOpaqueIdentifiers(arg0 interface{}) *
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadUserOpaqueIdentifiers", reflect.TypeOf((*MockStorage)(nil).LoadUserOpaqueIdentifiers), arg0)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadUserOpaqueIdentifiers", reflect.TypeOf((*MockStorage)(nil).LoadUserOpaqueIdentifiers), arg0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LoadWebauthnDeviceByID mocks base method.
|
||||||
|
func (m *MockStorage) LoadWebauthnDeviceByID(arg0 context.Context, arg1 int) (*model.WebauthnDevice, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "LoadWebauthnDeviceByID", arg0, arg1)
|
||||||
|
ret0, _ := ret[0].(*model.WebauthnDevice)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadWebauthnDeviceByID indicates an expected call of LoadWebauthnDeviceByID.
|
||||||
|
func (mr *MockStorageMockRecorder) LoadWebauthnDeviceByID(arg0, arg1 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadWebauthnDeviceByID", reflect.TypeOf((*MockStorage)(nil).LoadWebauthnDeviceByID), arg0, arg1)
|
||||||
|
}
|
||||||
|
|
||||||
// LoadWebauthnDevices mocks base method.
|
// LoadWebauthnDevices mocks base method.
|
||||||
func (m *MockStorage) LoadWebauthnDevices(arg0 context.Context, arg1, arg2 int) ([]model.WebauthnDevice, error) {
|
func (m *MockStorage) LoadWebauthnDevices(arg0 context.Context, arg1, arg2 int) ([]model.WebauthnDevice, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
|
|
|
@ -200,9 +200,9 @@ func handleRouter(config schema.Configuration, providers middlewares.Providers)
|
||||||
r.POST("/api/secondfactor/webauthn/assertion", middleware1FA(handlers.WebauthnAssertionPOST))
|
r.POST("/api/secondfactor/webauthn/assertion", middleware1FA(handlers.WebauthnAssertionPOST))
|
||||||
|
|
||||||
// Management of the webauthn devices.
|
// Management of the webauthn devices.
|
||||||
r.GET("/api/secondfactor/webauthn/devices", middleware1FA(handlers.WebauthnDevicesGet))
|
r.GET("/api/secondfactor/webauthn/devices", middleware1FA(handlers.WebauthnDevicesGET))
|
||||||
r.PUT("/api/secondfactor/webauthn/devices/{deviceID}", middleware2FA(handlers.WebauthnDeviceUpdate))
|
r.PUT("/api/secondfactor/webauthn/device/{deviceID}", middleware2FA(handlers.WebauthnDevicePUT))
|
||||||
r.DELETE("/api/secondfactor/webauthn/devices/{deviceID}", middleware2FA(handlers.WebauthnDeviceDelete))
|
r.DELETE("/api/secondfactor/webauthn/device/{deviceID}", middleware2FA(handlers.WebauthnDeviceDELETE))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure DUO api endpoint only if configuration exists.
|
// Configure DUO api endpoint only if configuration exists.
|
||||||
|
|
|
@ -43,9 +43,9 @@ type Provider interface {
|
||||||
UpdateWebauthnDeviceSignIn(ctx context.Context, id int, rpid string, lastUsedAt sql.NullTime, signCount uint32, cloneWarning bool) (err error)
|
UpdateWebauthnDeviceSignIn(ctx context.Context, id int, rpid string, lastUsedAt sql.NullTime, signCount uint32, cloneWarning bool) (err error)
|
||||||
DeleteWebauthnDevice(ctx context.Context, kid string) (err error)
|
DeleteWebauthnDevice(ctx context.Context, kid string) (err error)
|
||||||
DeleteWebauthnDeviceByUsername(ctx context.Context, username, description string) (err error)
|
DeleteWebauthnDeviceByUsername(ctx context.Context, username, description string) (err error)
|
||||||
DeleteWebauthnDeviceByUsernameAndID(ctx context.Context, username string, deviceID int) (err error)
|
|
||||||
LoadWebauthnDevices(ctx context.Context, limit, page int) (devices []model.WebauthnDevice, err error)
|
LoadWebauthnDevices(ctx context.Context, limit, page int) (devices []model.WebauthnDevice, err error)
|
||||||
LoadWebauthnDevicesByUsername(ctx context.Context, username string) (devices []model.WebauthnDevice, err error)
|
LoadWebauthnDevicesByUsername(ctx context.Context, username string) (devices []model.WebauthnDevice, err error)
|
||||||
|
LoadWebauthnDeviceByID(ctx context.Context, id int) (device *model.WebauthnDevice, err error)
|
||||||
|
|
||||||
SavePreferredDuoDevice(ctx context.Context, device model.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)
|
||||||
|
|
|
@ -49,6 +49,7 @@ func NewSQLProvider(config *schema.Configuration, name, driverName, dataSourceNa
|
||||||
sqlUpsertWebauthnDevice: fmt.Sprintf(queryFmtUpsertWebauthnDevice, tableWebauthnDevices),
|
sqlUpsertWebauthnDevice: fmt.Sprintf(queryFmtUpsertWebauthnDevice, tableWebauthnDevices),
|
||||||
sqlSelectWebauthnDevices: fmt.Sprintf(queryFmtSelectWebauthnDevices, tableWebauthnDevices),
|
sqlSelectWebauthnDevices: fmt.Sprintf(queryFmtSelectWebauthnDevices, tableWebauthnDevices),
|
||||||
sqlSelectWebauthnDevicesByUsername: fmt.Sprintf(queryFmtSelectWebauthnDevicesByUsername, tableWebauthnDevices),
|
sqlSelectWebauthnDevicesByUsername: fmt.Sprintf(queryFmtSelectWebauthnDevicesByUsername, tableWebauthnDevices),
|
||||||
|
sqlSelectWebauthnDeviceByID: fmt.Sprintf(queryFmtSelectWebauthnDeviceByID, tableWebauthnDevices),
|
||||||
sqlUpdateWebauthnDeviceDescriptionByUsernameAndID: fmt.Sprintf(queryFmtUpdateUpdateWebauthnDeviceDescriptionByUsernameAndID, tableWebauthnDevices),
|
sqlUpdateWebauthnDeviceDescriptionByUsernameAndID: fmt.Sprintf(queryFmtUpdateUpdateWebauthnDeviceDescriptionByUsernameAndID, tableWebauthnDevices),
|
||||||
sqlUpdateWebauthnDevicePublicKey: fmt.Sprintf(queryFmtUpdateWebauthnDevicePublicKey, tableWebauthnDevices),
|
sqlUpdateWebauthnDevicePublicKey: fmt.Sprintf(queryFmtUpdateWebauthnDevicePublicKey, tableWebauthnDevices),
|
||||||
sqlUpdateWebauthnDevicePublicKeyByUsername: fmt.Sprintf(queryFmtUpdateUpdateWebauthnDevicePublicKeyByUsername, tableWebauthnDevices),
|
sqlUpdateWebauthnDevicePublicKeyByUsername: fmt.Sprintf(queryFmtUpdateUpdateWebauthnDevicePublicKeyByUsername, tableWebauthnDevices),
|
||||||
|
@ -56,7 +57,6 @@ func NewSQLProvider(config *schema.Configuration, name, driverName, dataSourceNa
|
||||||
sqlUpdateWebauthnDeviceRecordSignInByUsername: fmt.Sprintf(queryFmtUpdateWebauthnDeviceRecordSignInByUsername, tableWebauthnDevices),
|
sqlUpdateWebauthnDeviceRecordSignInByUsername: fmt.Sprintf(queryFmtUpdateWebauthnDeviceRecordSignInByUsername, tableWebauthnDevices),
|
||||||
sqlDeleteWebauthnDevice: fmt.Sprintf(queryFmtDeleteWebauthnDevice, tableWebauthnDevices),
|
sqlDeleteWebauthnDevice: fmt.Sprintf(queryFmtDeleteWebauthnDevice, tableWebauthnDevices),
|
||||||
sqlDeleteWebauthnDeviceByUsername: fmt.Sprintf(queryFmtDeleteWebauthnDeviceByUsername, tableWebauthnDevices),
|
sqlDeleteWebauthnDeviceByUsername: fmt.Sprintf(queryFmtDeleteWebauthnDeviceByUsername, tableWebauthnDevices),
|
||||||
sqlDeleteWebauthnDeviceByUsernameAndID: fmt.Sprintf(queryFmtDeleteWebauthnDeviceByUsernameAndID, tableWebauthnDevices),
|
|
||||||
sqlDeleteWebauthnDeviceByUsernameAndDescription: fmt.Sprintf(queryFmtDeleteWebauthnDeviceByUsernameAndDescription, tableWebauthnDevices),
|
sqlDeleteWebauthnDeviceByUsernameAndDescription: fmt.Sprintf(queryFmtDeleteWebauthnDeviceByUsernameAndDescription, tableWebauthnDevices),
|
||||||
|
|
||||||
sqlUpsertDuoDevice: fmt.Sprintf(queryFmtUpsertDuoDevice, tableDuoDevices),
|
sqlUpsertDuoDevice: fmt.Sprintf(queryFmtUpsertDuoDevice, tableDuoDevices),
|
||||||
|
@ -166,6 +166,7 @@ type SQLProvider struct {
|
||||||
sqlUpsertWebauthnDevice string
|
sqlUpsertWebauthnDevice string
|
||||||
sqlSelectWebauthnDevices string
|
sqlSelectWebauthnDevices string
|
||||||
sqlSelectWebauthnDevicesByUsername string
|
sqlSelectWebauthnDevicesByUsername string
|
||||||
|
sqlSelectWebauthnDeviceByID string
|
||||||
|
|
||||||
sqlUpdateWebauthnDeviceDescriptionByUsernameAndID string
|
sqlUpdateWebauthnDeviceDescriptionByUsernameAndID string
|
||||||
sqlUpdateWebauthnDevicePublicKey string
|
sqlUpdateWebauthnDevicePublicKey string
|
||||||
|
@ -175,7 +176,6 @@ type SQLProvider struct {
|
||||||
|
|
||||||
sqlDeleteWebauthnDevice string
|
sqlDeleteWebauthnDevice string
|
||||||
sqlDeleteWebauthnDeviceByUsername string
|
sqlDeleteWebauthnDeviceByUsername string
|
||||||
sqlDeleteWebauthnDeviceByUsernameAndID string
|
|
||||||
sqlDeleteWebauthnDeviceByUsernameAndDescription string
|
sqlDeleteWebauthnDeviceByUsernameAndDescription string
|
||||||
|
|
||||||
// Table: duo_devices.
|
// Table: duo_devices.
|
||||||
|
@ -803,7 +803,7 @@ func (p *SQLProvider) DeleteTOTPConfiguration(ctx context.Context, username stri
|
||||||
func (p *SQLProvider) LoadTOTPConfiguration(ctx context.Context, username string) (config *model.TOTPConfiguration, err error) {
|
func (p *SQLProvider) LoadTOTPConfiguration(ctx context.Context, username string) (config *model.TOTPConfiguration, err error) {
|
||||||
config = &model.TOTPConfiguration{}
|
config = &model.TOTPConfiguration{}
|
||||||
|
|
||||||
if err = p.db.QueryRowxContext(ctx, p.sqlSelectTOTPConfig, username).StructScan(config); err != nil {
|
if err = p.db.GetContext(ctx, config, p.sqlSelectTOTPConfig, username); err != nil {
|
||||||
if errors.Is(err, sql.ErrNoRows) {
|
if errors.Is(err, sql.ErrNoRows) {
|
||||||
return nil, ErrNoTOTPConfiguration
|
return nil, ErrNoTOTPConfiguration
|
||||||
}
|
}
|
||||||
|
@ -903,19 +903,6 @@ func (p *SQLProvider) DeleteWebauthnDeviceByUsername(ctx context.Context, userna
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteWebauthnDeviceByUsernameAndID deletes a registered Webauthn device by username and ID.
|
|
||||||
func (p *SQLProvider) DeleteWebauthnDeviceByUsernameAndID(ctx context.Context, username string, deviceID int) (err error) {
|
|
||||||
if len(username) == 0 {
|
|
||||||
return fmt.Errorf("error deleting webauthn device with username '%s' and id '%d': username must not be empty", username, deviceID)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err = p.db.ExecContext(ctx, p.sqlDeleteWebauthnDeviceByUsernameAndID, username, deviceID); err != nil {
|
|
||||||
return fmt.Errorf("error deleting webauthn device with username '%s' and id '%d': %w", username, deviceID, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadWebauthnDevices loads Webauthn device registrations.
|
// LoadWebauthnDevices loads Webauthn device registrations.
|
||||||
func (p *SQLProvider) LoadWebauthnDevices(ctx context.Context, limit, page int) (devices []model.WebauthnDevice, err error) {
|
func (p *SQLProvider) LoadWebauthnDevices(ctx context.Context, limit, page int) (devices []model.WebauthnDevice, err error) {
|
||||||
devices = make([]model.WebauthnDevice, 0, limit)
|
devices = make([]model.WebauthnDevice, 0, limit)
|
||||||
|
@ -937,6 +924,21 @@ func (p *SQLProvider) LoadWebauthnDevices(ctx context.Context, limit, page int)
|
||||||
return devices, nil
|
return devices, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LoadWebauthnDeviceByID loads a webauthn device registration for a given id.
|
||||||
|
func (p *SQLProvider) LoadWebauthnDeviceByID(ctx context.Context, id int) (device *model.WebauthnDevice, err error) {
|
||||||
|
device = &model.WebauthnDevice{}
|
||||||
|
|
||||||
|
if err = p.db.GetContext(ctx, device, p.sqlSelectWebauthnDeviceByID, id); err != nil {
|
||||||
|
if errors.Is(err, sql.ErrNoRows) {
|
||||||
|
return nil, sql.ErrNoRows
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("error selecting Webauthn device with id '%d': %w", id, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return device, nil
|
||||||
|
}
|
||||||
|
|
||||||
// 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 []model.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 {
|
||||||
|
|
|
@ -61,6 +61,7 @@ func NewPostgreSQLProvider(config *schema.Configuration, caCertPool *x509.CertPo
|
||||||
|
|
||||||
provider.sqlSelectWebauthnDevices = provider.db.Rebind(provider.sqlSelectWebauthnDevices)
|
provider.sqlSelectWebauthnDevices = provider.db.Rebind(provider.sqlSelectWebauthnDevices)
|
||||||
provider.sqlSelectWebauthnDevicesByUsername = provider.db.Rebind(provider.sqlSelectWebauthnDevicesByUsername)
|
provider.sqlSelectWebauthnDevicesByUsername = provider.db.Rebind(provider.sqlSelectWebauthnDevicesByUsername)
|
||||||
|
provider.sqlSelectWebauthnDeviceByID = provider.db.Rebind(provider.sqlSelectWebauthnDeviceByID)
|
||||||
provider.sqlUpdateWebauthnDeviceDescriptionByUsernameAndID = provider.db.Rebind(provider.sqlUpdateWebauthnDeviceDescriptionByUsernameAndID)
|
provider.sqlUpdateWebauthnDeviceDescriptionByUsernameAndID = provider.db.Rebind(provider.sqlUpdateWebauthnDeviceDescriptionByUsernameAndID)
|
||||||
provider.sqlUpdateWebauthnDevicePublicKey = provider.db.Rebind(provider.sqlUpdateWebauthnDevicePublicKey)
|
provider.sqlUpdateWebauthnDevicePublicKey = provider.db.Rebind(provider.sqlUpdateWebauthnDevicePublicKey)
|
||||||
provider.sqlUpdateWebauthnDevicePublicKeyByUsername = provider.db.Rebind(provider.sqlUpdateWebauthnDevicePublicKeyByUsername)
|
provider.sqlUpdateWebauthnDevicePublicKeyByUsername = provider.db.Rebind(provider.sqlUpdateWebauthnDevicePublicKeyByUsername)
|
||||||
|
@ -68,7 +69,6 @@ func NewPostgreSQLProvider(config *schema.Configuration, caCertPool *x509.CertPo
|
||||||
provider.sqlUpdateWebauthnDeviceRecordSignInByUsername = provider.db.Rebind(provider.sqlUpdateWebauthnDeviceRecordSignInByUsername)
|
provider.sqlUpdateWebauthnDeviceRecordSignInByUsername = provider.db.Rebind(provider.sqlUpdateWebauthnDeviceRecordSignInByUsername)
|
||||||
provider.sqlDeleteWebauthnDevice = provider.db.Rebind(provider.sqlDeleteWebauthnDevice)
|
provider.sqlDeleteWebauthnDevice = provider.db.Rebind(provider.sqlDeleteWebauthnDevice)
|
||||||
provider.sqlDeleteWebauthnDeviceByUsername = provider.db.Rebind(provider.sqlDeleteWebauthnDeviceByUsername)
|
provider.sqlDeleteWebauthnDeviceByUsername = provider.db.Rebind(provider.sqlDeleteWebauthnDeviceByUsername)
|
||||||
provider.sqlDeleteWebauthnDeviceByUsernameAndID = provider.db.Rebind(provider.sqlDeleteWebauthnDeviceByUsernameAndID)
|
|
||||||
provider.sqlDeleteWebauthnDeviceByUsernameAndDescription = provider.db.Rebind(provider.sqlDeleteWebauthnDeviceByUsernameAndDescription)
|
provider.sqlDeleteWebauthnDeviceByUsernameAndDescription = provider.db.Rebind(provider.sqlDeleteWebauthnDeviceByUsernameAndDescription)
|
||||||
|
|
||||||
provider.sqlSelectDuoDevice = provider.db.Rebind(provider.sqlSelectDuoDevice)
|
provider.sqlSelectDuoDevice = provider.db.Rebind(provider.sqlSelectDuoDevice)
|
||||||
|
|
|
@ -134,6 +134,11 @@ const (
|
||||||
FROM %s
|
FROM %s
|
||||||
WHERE username = ?;`
|
WHERE username = ?;`
|
||||||
|
|
||||||
|
queryFmtSelectWebauthnDeviceByID = `
|
||||||
|
SELECT id, created_at, last_used_at, rpid, username, description, kid, public_key, attestation_type, transport, aaguid, sign_count, clone_warning
|
||||||
|
FROM %s
|
||||||
|
WHERE id = ?;`
|
||||||
|
|
||||||
queryFmtUpdateWebauthnDevicePublicKey = `
|
queryFmtUpdateWebauthnDevicePublicKey = `
|
||||||
UPDATE %s
|
UPDATE %s
|
||||||
SET public_key = ?
|
SET public_key = ?
|
||||||
|
@ -181,10 +186,6 @@ const (
|
||||||
DELETE FROM %s
|
DELETE FROM %s
|
||||||
WHERE username = ?;`
|
WHERE username = ?;`
|
||||||
|
|
||||||
queryFmtDeleteWebauthnDeviceByUsernameAndID = `
|
|
||||||
DELETE FROM %s
|
|
||||||
WHERE username = ? AND id = ?;`
|
|
||||||
|
|
||||||
queryFmtDeleteWebauthnDeviceByUsernameAndDescription = `
|
queryFmtDeleteWebauthnDeviceByUsernameAndDescription = `
|
||||||
DELETE FROM %s
|
DELETE FROM %s
|
||||||
WHERE username = ? AND description = ?;`
|
WHERE username = ? AND description = ?;`
|
||||||
|
|
|
@ -18,6 +18,7 @@ export const WebauthnAttestationPath = basePath + "/api/secondfactor/webauthn/at
|
||||||
export const WebauthnAssertionPath = basePath + "/api/secondfactor/webauthn/assertion";
|
export const WebauthnAssertionPath = basePath + "/api/secondfactor/webauthn/assertion";
|
||||||
|
|
||||||
export const WebauthnDevicesPath = basePath + "/api/secondfactor/webauthn/devices";
|
export const WebauthnDevicesPath = basePath + "/api/secondfactor/webauthn/devices";
|
||||||
|
export const WebauthnDevicePath = basePath + "/api/secondfactor/webauthn/device";
|
||||||
|
|
||||||
export const InitiateDuoDeviceSelectionPath = basePath + "/api/secondfactor/duo_devices";
|
export const InitiateDuoDeviceSelectionPath = basePath + "/api/secondfactor/duo_devices";
|
||||||
export const CompleteDuoDeviceSelectionPath = basePath + "/api/secondfactor/duo_device";
|
export const CompleteDuoDeviceSelectionPath = basePath + "/api/secondfactor/duo_device";
|
||||||
|
|
|
@ -24,7 +24,7 @@ import {
|
||||||
ServiceResponse,
|
ServiceResponse,
|
||||||
WebauthnAssertionPath,
|
WebauthnAssertionPath,
|
||||||
WebauthnAttestationPath,
|
WebauthnAttestationPath,
|
||||||
WebauthnDevicesPath,
|
WebauthnDevicePath,
|
||||||
WebauthnIdentityFinishPath,
|
WebauthnIdentityFinishPath,
|
||||||
} from "@services/Api";
|
} from "@services/Api";
|
||||||
import { SignInResponse } from "@services/SignIn";
|
import { SignInResponse } from "@services/SignIn";
|
||||||
|
@ -399,12 +399,12 @@ export async function performAssertionCeremony(
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function deleteDevice(deviceID: string): Promise<number> {
|
export async function deleteDevice(deviceID: string): Promise<number> {
|
||||||
let response = await axios.delete(`${WebauthnDevicesPath}/${deviceID}`);
|
let response = await axios.delete(`${WebauthnDevicePath}/${deviceID}`);
|
||||||
return response.status;
|
return response.status;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateDevice(deviceID: string, description: string): Promise<number> {
|
export async function updateDevice(deviceID: string, description: string): Promise<number> {
|
||||||
let response = await axios.put<ServiceResponse<WebauthnDeviceUpdateRequest>>(`${WebauthnDevicesPath}/${deviceID}`, {
|
let response = await axios.put<ServiceResponse<WebauthnDeviceUpdateRequest>>(`${WebauthnDevicePath}/${deviceID}`, {
|
||||||
description: description,
|
description: description,
|
||||||
});
|
});
|
||||||
return response.status;
|
return response.status;
|
||||||
|
|
|
@ -44,6 +44,8 @@ export default function WebauthnDeviceItem(props: Props) {
|
||||||
|
|
||||||
const status = await updateDevice(props.device.id, name);
|
const status = await updateDevice(props.device.id, name);
|
||||||
|
|
||||||
|
console.log("Status was: ", status);
|
||||||
|
|
||||||
setLoadingEdit(false);
|
setLoadingEdit(false);
|
||||||
|
|
||||||
if (status !== 200) {
|
if (status !== 200) {
|
||||||
|
@ -65,6 +67,8 @@ export default function WebauthnDeviceItem(props: Props) {
|
||||||
|
|
||||||
const status = await deleteDevice(props.device.id);
|
const status = await deleteDevice(props.device.id);
|
||||||
|
|
||||||
|
console.log("Status was: ", status);
|
||||||
|
|
||||||
setLoadingDelete(false);
|
setLoadingDelete(false);
|
||||||
|
|
||||||
if (status !== 200) {
|
if (status !== 200) {
|
||||||
|
|
Loading…
Reference in New Issue