forked from rancher/rancher
-
Notifications
You must be signed in to change notification settings - Fork 0
/
user_actions.go
138 lines (113 loc) · 3.41 KB
/
user_actions.go
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package authn
import (
"net/http"
"strings"
"github.com/pkg/errors"
"github.com/rancher/norman/httperror"
"github.com/rancher/norman/parse"
"github.com/rancher/norman/types"
"github.com/rancher/rancher/pkg/settings"
"github.com/rancher/types/apis/management.cattle.io/v3"
"github.com/rancher/types/client/management/v3"
"golang.org/x/crypto/bcrypt"
"k8s.io/apimachinery/pkg/apis/meta/v1"
)
func UserFormatter(apiContext *types.APIContext, resource *types.RawResource) {
resource.AddAction(apiContext, "setpassword")
}
func CollectionFormatter(apiContext *types.APIContext, collection *types.GenericCollection) {
collection.AddAction(apiContext, "changepassword")
}
type Handler struct {
UserClient v3.UserInterface
}
func (h *Handler) Actions(actionName string, action *types.Action, apiContext *types.APIContext) error {
switch actionName {
case "changepassword":
if err := h.changePassword(actionName, action, apiContext); err != nil {
return err
}
case "setpassword":
if err := h.setPassword(actionName, action, apiContext); err != nil {
return err
}
default:
return errors.Errorf("bad action %v", actionName)
}
if !strings.EqualFold(settings.FirstLogin.Get(), "false") {
if err := settings.FirstLogin.Set("false"); err != nil {
return err
}
}
return nil
}
func (h *Handler) changePassword(actionName string, action *types.Action, request *types.APIContext) error {
actionInput, err := parse.ReadBody(request.Request)
if err != nil {
return err
}
store := request.Schema.Store
if store == nil {
return errors.New("no user store available")
}
userID := request.Request.Header.Get("Impersonate-User")
if userID == "" {
return errors.New("can't find user")
}
currentPass, ok := actionInput["currentPassword"].(string)
if !ok || len(currentPass) == 0 {
return httperror.NewAPIError(httperror.InvalidBodyContent, "must specify current password")
}
newPass, ok := actionInput["newPassword"].(string)
if !ok || len(newPass) == 0 {
return httperror.NewAPIError(httperror.InvalidBodyContent, "invalid new password")
}
user, err := h.UserClient.Get(userID, v1.GetOptions{})
if err != nil {
return err
}
if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(currentPass)); err != nil {
return httperror.NewAPIError(httperror.InvalidBodyContent, "invalid current password")
}
newPassHash, err := HashPasswordString(newPass)
if err != nil {
return err
}
user.Password = newPassHash
user.MustChangePassword = false
user, err = h.UserClient.Update(user)
if err != nil {
return err
}
return nil
}
func (h *Handler) setPassword(actionName string, action *types.Action, request *types.APIContext) error {
actionInput, err := parse.ReadBody(request.Request)
if err != nil {
return err
}
store := request.Schema.Store
if store == nil {
return errors.New("no user store available")
}
userData, err := store.ByID(request, request.Schema, request.ID)
if err != nil {
return err
}
newPass, ok := actionInput["newPassword"].(string)
if !ok || len(newPass) == 0 {
return errors.New("Invalid password")
}
userData[client.UserFieldPassword] = newPass
if err := hashPassword(userData); err != nil {
return err
}
userData[client.UserFieldMustChangePassword] = false
delete(userData, "me")
userData, err = store.Update(request, request.Schema, userData, request.ID)
if err != nil {
return err
}
request.WriteResponse(http.StatusOK, userData)
return nil
}