1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
  | 
package handlers
import (
	"fmt"
	"strings"
	"sync"
	"github.com/clems4ever/authelia/internal/authentication"
	"github.com/clems4ever/authelia/internal/middlewares"
	"github.com/clems4ever/authelia/internal/storage"
	"github.com/clems4ever/authelia/internal/utils"
	"github.com/sirupsen/logrus"
)
func loadInfo(username string, storageProvier storage.Provider, preferences *UserPreferences, logger *logrus.Entry) []error {
	var wg sync.WaitGroup
	wg.Add(3)
	errors := make([]error, 0)
	go func() {
		defer wg.Done()
		method, err := storageProvier.LoadPrefered2FAMethod(username)
		if err != nil {
			errors = append(errors, err)
			logger.Error(err)
			return
		}
		if method == "" {
			preferences.Method = authentication.PossibleMethods[0]
		} else {
			preferences.Method = method
		}
	}()
	go func() {
		defer wg.Done()
		_, _, err := storageProvier.LoadU2FDeviceHandle(username)
		if err != nil {
			if err == storage.ErrNoU2FDeviceHandle {
				return
			}
			errors = append(errors, err)
			logger.Error(err)
			return
		}
		preferences.HasU2F = true
	}()
	go func() {
		defer wg.Done()
		_, err := storageProvier.LoadTOTPSecret(username)
		if err != nil {
			if err == storage.ErrNoTOTPSecret {
				return
			}
			errors = append(errors, err)
			logger.Error(err)
			return
		}
		preferences.HasTOTP = true
	}()
	wg.Wait()
	return errors
}
// UserInfoGet get the info related to the user identitified by the session.
func UserInfoGet(ctx *middlewares.AutheliaCtx) {
	userSession := ctx.GetSession()
	preferences := UserPreferences{}
	errors := loadInfo(userSession.Username, ctx.Providers.StorageProvider, &preferences, ctx.Logger)
	if len(errors) > 0 {
		ctx.Error(fmt.Errorf("Unable to load user information"), operationFailedMessage)
		return
	}
	ctx.SetJSONBody(preferences)
}
type MethodBody struct {
	Method string `json:"method" valid:"required"`
}
// MethodPreferencePost update the user preferences regarding 2FA method.
func MethodPreferencePost(ctx *middlewares.AutheliaCtx) {
	bodyJSON := MethodBody{}
	err := ctx.ParseBody(&bodyJSON)
	if err != nil {
		ctx.Error(err, operationFailedMessage)
		return
	}
	if !utils.IsStringInSlice(bodyJSON.Method, authentication.PossibleMethods) {
		ctx.Error(fmt.Errorf("Unknown method '%s', it should be one of %s", bodyJSON.Method, strings.Join(authentication.PossibleMethods, ", ")), operationFailedMessage)
		return
	}
	userSession := ctx.GetSession()
	ctx.Logger.Debugf("Save new prefered 2FA method of user %s to %s", userSession.Username, bodyJSON.Method)
	err = ctx.Providers.StorageProvider.SavePrefered2FAMethod(userSession.Username, bodyJSON.Method)
	if err != nil {
		ctx.Error(fmt.Errorf("Unable to save new prefered 2FA method: %s", err), operationFailedMessage)
		return
	}
	ctx.ReplyOK()
}
  |