• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

codenotary / immudb / 6493880191

12 Oct 2023 09:32AM UTC coverage: 89.622% (+0.01%) from 89.609%
6493880191

push

gh-ci

jeroiraz
Update README.md

33507 of 37387 relevant lines covered (89.62%)

143481.42 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.53
/pkg/server/user.go
1
/*
2
Copyright 2022 Codenotary Inc. All rights reserved.
3

4
Licensed under the Apache License, Version 2.0 (the "License");
5
you may not use this file except in compliance with the License.
6
You may obtain a copy of the License at
7

8
        http://www.apache.org/licenses/LICENSE-2.0
9

10
Unless required by applicable law or agreed to in writing, software
11
distributed under the License is distributed on an "AS IS" BASIS,
12
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
See the License for the specific language governing permissions and
14
limitations under the License.
15
*/
16

17
package server
18

19
import (
20
        "context"
21
        "encoding/json"
22
        "fmt"
23
        "time"
24

25
        "github.com/codenotary/immudb/pkg/database"
26
        "github.com/codenotary/immudb/pkg/server/sessions"
27

28
        "github.com/codenotary/immudb/pkg/api/schema"
29
        "github.com/codenotary/immudb/pkg/auth"
30
        "github.com/codenotary/immudb/pkg/errors"
31
        "github.com/golang/protobuf/ptypes/empty"
32
        "google.golang.org/grpc/codes"
33
        "google.golang.org/grpc/status"
34
)
35

36
// Login ...
37
func (s *ImmuServer) Login(ctx context.Context, r *schema.LoginRequest) (*schema.LoginResponse, error) {
77✔
38
        if !s.Options.auth {
78✔
39
                return nil, errors.New(ErrAuthDisabled).WithCode(errors.CodProtocolViolation)
1✔
40
        }
1✔
41

42
        u, err := s.getValidatedUser(ctx, r.User, r.Password)
76✔
43
        if err != nil {
79✔
44
                return nil, errors.Wrap(err, ErrInvalidUsernameOrPassword)
3✔
45
        }
3✔
46

47
        if !u.Active {
74✔
48
                return nil, errors.New(ErrUserNotActive)
1✔
49
        }
1✔
50

51
        var token string
72✔
52

72✔
53
        if s.multidbmode {
79✔
54
                //-1 no database yet, must exec the "use" (UseDatabase) command first
7✔
55
                token, err = auth.GenerateToken(*u, -1, s.Options.TokenExpiryTimeMin)
7✔
56
        } else {
72✔
57
                token, err = auth.GenerateToken(*u, defaultDbIndex, s.Options.TokenExpiryTimeMin)
65✔
58
        }
65✔
59
        if err != nil {
72✔
60
                return nil, err
×
61
        }
×
62

63
        loginResponse := &schema.LoginResponse{Token: token}
72✔
64
        if u.Username == auth.SysAdminUsername && string(r.GetPassword()) == auth.SysAdminPassword {
135✔
65
                loginResponse.Warning = []byte(auth.WarnDefaultAdminPassword)
63✔
66
        }
63✔
67

68
        if u.Username == auth.SysAdminUsername {
135✔
69
                u.IsSysAdmin = true
63✔
70
        }
63✔
71

72
        //add user to loggedin list
73
        s.addUserToLoginList(u)
72✔
74

72✔
75
        return loginResponse, nil
72✔
76
}
77

78
// Logout ...
79
func (s *ImmuServer) Logout(ctx context.Context, r *empty.Empty) (*empty.Empty, error) {
33✔
80
        if !s.Options.auth {
34✔
81
                return nil, errors.New(ErrAuthDisabled).WithCode(errors.CodProtocolViolation)
1✔
82
        }
1✔
83

84
        _, user, err := s.getLoggedInUserdataFromCtx(ctx)
32✔
85
        if err != nil {
60✔
86
                return nil, err
28✔
87
        }
28✔
88

89
        // remove user from loggedin users
90
        s.removeUserFromLoginList(user.Username)
4✔
91

4✔
92
        // invalidate the token for this user
4✔
93
        _, err = auth.DropTokenKeysForCtx(ctx)
4✔
94

4✔
95
        return new(empty.Empty), err
4✔
96
}
97

98
// CreateUser Creates a new user
99
func (s *ImmuServer) CreateUser(ctx context.Context, r *schema.CreateUserRequest) (*empty.Empty, error) {
31✔
100
        s.Logger.Debugf("CreateUser")
31✔
101

31✔
102
        if s.Options.GetMaintenance() {
32✔
103
                return nil, ErrNotAllowedInMaintenanceMode
1✔
104
        }
1✔
105

106
        if !s.Options.GetAuth() {
31✔
107
                return nil, fmt.Errorf("this command is available only with authentication on")
1✔
108
        }
1✔
109

110
        _, loggedInuser, err := s.getLoggedInUserdataFromCtx(ctx)
29✔
111
        if err != nil {
30✔
112
                return nil, err
1✔
113
        }
1✔
114

115
        if len(r.User) == 0 {
29✔
116
                return nil, fmt.Errorf("username can not be empty")
1✔
117
        }
1✔
118

119
        if (len(r.Database) == 0) && s.multidbmode {
28✔
120
                return nil, fmt.Errorf("database name can not be empty when there are multiple databases")
1✔
121
        }
1✔
122

123
        if (len(r.Database) == 0) && !s.multidbmode {
26✔
124
                r.Database = DefaultDBName
×
125
        }
×
126

127
        //check if database exists
128
        if s.dbList.GetId(r.Database) < 0 {
27✔
129
                return nil, fmt.Errorf("database %s does not exist", r.Database)
1✔
130
        }
1✔
131

132
        //check permission is a known value
133
        if (r.Permission == auth.PermissionNone) ||
25✔
134
                (r.Permission > auth.PermissionRW && r.Permission < auth.PermissionAdmin) {
26✔
135
                return nil, fmt.Errorf("unrecognized permission")
1✔
136
        }
1✔
137

138
        //if the requesting user has admin permission on this database
139
        if (!loggedInuser.IsSysAdmin) &&
24✔
140
                (!loggedInuser.HasPermission(r.Database, auth.PermissionAdmin)) {
25✔
141
                return nil, fmt.Errorf("you do not have permission on this database")
1✔
142
        }
1✔
143

144
        //do not allow to create another system admin
145
        if r.Permission == auth.PermissionSysAdmin {
24✔
146
                return nil, fmt.Errorf("can not create another system admin")
1✔
147
        }
1✔
148

149
        _, err = s.getUser(ctx, r.User)
22✔
150
        if err == nil {
23✔
151
                return nil, fmt.Errorf("user already exists")
1✔
152
        }
1✔
153

154
        _, _, err = s.insertNewUser(ctx, r.User, r.Password, r.GetPermission(), r.Database, true, loggedInuser.Username)
21✔
155
        if err != nil {
21✔
156
                return nil, err
×
157
        }
×
158

159
        s.Logger.Infof("user %s was created by user %s", r.User, loggedInuser.Username)
21✔
160

21✔
161
        return &empty.Empty{}, nil
21✔
162
}
163

164
// ListUsers returns a list of users based on the requesting user permissions
165
func (s *ImmuServer) ListUsers(ctx context.Context, req *empty.Empty) (*schema.UserList, error) {
8✔
166
        s.Logger.Debugf("ListUsers")
8✔
167

8✔
168
        loggedInuser := &auth.User{}
8✔
169
        var db database.DB
8✔
170
        var err error
8✔
171
        userlist := &schema.UserList{}
8✔
172

8✔
173
        if !s.Options.GetMaintenance() {
16✔
174
                if !s.Options.GetAuth() {
9✔
175
                        return nil, fmt.Errorf("this command is available only with authentication on")
1✔
176
                }
1✔
177

178
                var dbInd int
7✔
179

7✔
180
                dbInd, loggedInuser, err = s.getLoggedInUserdataFromCtx(ctx)
7✔
181
                if err != nil {
8✔
182
                        return nil, err
1✔
183
                }
1✔
184

185
                if dbInd >= 0 {
11✔
186
                        db, err = s.dbList.GetByIndex(dbInd)
5✔
187
                        if err != nil {
5✔
188
                                return nil, err
×
189
                        }
×
190
                }
191
        }
192

193
        itemList, err := s.sysDB.Scan(ctx, &schema.ScanRequest{
6✔
194
                Prefix: []byte{KeyPrefixUser},
6✔
195
                NoWait: true,
6✔
196
        })
6✔
197
        if err != nil {
6✔
198
                s.Logger.Errorf("error getting users: %v", err)
×
199
                return nil, err
×
200
        }
×
201

202
        if loggedInuser.IsSysAdmin || s.Options.GetMaintenance() {
10✔
203
                // return all users, including the deactivated ones
4✔
204
                for i := 0; i < len(itemList.Entries); i++ {
11✔
205
                        itemList.Entries[i].Key = itemList.Entries[i].Key[1:]
7✔
206

7✔
207
                        var user auth.User
7✔
208

7✔
209
                        err = json.Unmarshal(itemList.Entries[i].Value, &user)
7✔
210
                        if err != nil {
7✔
211
                                return nil, err
×
212
                        }
×
213

214
                        permissions := []*schema.Permission{}
7✔
215

7✔
216
                        for _, val := range user.Permissions {
13✔
217
                                permissions = append(permissions, &schema.Permission{
6✔
218
                                        Database:   val.Database,
6✔
219
                                        Permission: val.Permission,
6✔
220
                                })
6✔
221
                        }
6✔
222

223
                        u := schema.User{
7✔
224
                                User:        []byte(user.Username),
7✔
225
                                Createdat:   user.CreatedAt.String(),
7✔
226
                                Createdby:   user.CreatedBy,
7✔
227
                                Permissions: permissions,
7✔
228
                                Active:      user.Active,
7✔
229
                        }
7✔
230

7✔
231
                        userlist.Users = append(userlist.Users, &u)
7✔
232
                }
233

234
                return userlist, nil
4✔
235

236
        } else if db != nil && loggedInuser.WhichPermission(db.GetName()) == auth.PermissionAdmin {
3✔
237
                // for admin users return only users for the database that is has selected
1✔
238
                selectedDbname := db.GetName()
1✔
239
                userlist := &schema.UserList{}
1✔
240

1✔
241
                for i := 0; i < len(itemList.Entries); i++ {
3✔
242
                        include := false
2✔
243
                        itemList.Entries[i].Key = itemList.Entries[i].Key[1:]
2✔
244

2✔
245
                        var user auth.User
2✔
246

2✔
247
                        err = json.Unmarshal(itemList.Entries[i].Value, &user)
2✔
248
                        if err != nil {
2✔
249
                                return nil, err
×
250
                        }
×
251

252
                        permissions := []*schema.Permission{}
2✔
253

2✔
254
                        for _, val := range user.Permissions {
4✔
255
                                //check if this user has any permission for this database
2✔
256
                                //include in the reply only if it has any permission for the currently selected database
2✔
257
                                if val.Database == selectedDbname {
3✔
258
                                        include = true
1✔
259
                                }
1✔
260

261
                                permissions = append(permissions, &schema.Permission{
2✔
262
                                        Database:   val.Database,
2✔
263
                                        Permission: val.Permission,
2✔
264
                                })
2✔
265
                        }
266

267
                        if include {
3✔
268
                                u := schema.User{
1✔
269
                                        User:        []byte(user.Username),
1✔
270
                                        Createdat:   user.CreatedAt.String(),
1✔
271
                                        Createdby:   user.CreatedBy,
1✔
272
                                        Permissions: permissions,
1✔
273
                                        Active:      user.Active,
1✔
274
                                }
1✔
275

1✔
276
                                userlist.Users = append(userlist.Users, &u)
1✔
277
                        }
1✔
278
                }
279

280
                return userlist, nil
1✔
281

282
        } else {
1✔
283
                // any other permission return only its data
1✔
284
                userlist := &schema.UserList{}
1✔
285
                permissions := []*schema.Permission{}
1✔
286

1✔
287
                for _, val := range loggedInuser.Permissions {
2✔
288
                        permissions = append(permissions, &schema.Permission{
1✔
289
                                Database:   val.Database,
1✔
290
                                Permission: val.Permission,
1✔
291
                        })
1✔
292
                }
1✔
293

294
                u := schema.User{
1✔
295
                        User:        []byte(loggedInuser.Username),
1✔
296
                        Createdat:   loggedInuser.CreatedAt.String(),
1✔
297
                        Createdby:   loggedInuser.CreatedBy,
1✔
298
                        Permissions: permissions,
1✔
299
                        Active:      loggedInuser.Active,
1✔
300
                }
1✔
301

1✔
302
                userlist.Users = append(userlist.Users, &u)
1✔
303

1✔
304
                return userlist, nil
1✔
305
        }
306
}
307

308
// ChangePassword ...
309
func (s *ImmuServer) ChangePassword(ctx context.Context, r *schema.ChangePasswordRequest) (*empty.Empty, error) {
11✔
310
        s.Logger.Debugf("ChangePassword")
11✔
311

11✔
312
        if s.Options.GetMaintenance() {
12✔
313
                return nil, ErrNotAllowedInMaintenanceMode
1✔
314
        }
1✔
315

316
        if !s.Options.GetAuth() {
11✔
317
                return nil, fmt.Errorf("this command is available only with authentication on")
1✔
318
        }
1✔
319

320
        _, user, err := s.getLoggedInUserdataFromCtx(ctx)
9✔
321
        if err != nil {
10✔
322
                return nil, err
1✔
323
        }
1✔
324

325
        if string(r.User) == auth.SysAdminUsername {
9✔
326
                if err = auth.ComparePasswords(user.HashedPassword, r.OldPassword); err != nil {
2✔
327
                        return new(empty.Empty), status.Errorf(codes.PermissionDenied, "old password is incorrect")
1✔
328
                }
1✔
329
        }
330

331
        if !user.IsSysAdmin {
9✔
332
                if !user.HasAtLeastOnePermission(auth.PermissionAdmin) {
3✔
333
                        return nil, fmt.Errorf("user is not system admin nor admin in any of the databases")
1✔
334
                }
1✔
335
        }
336

337
        if len(r.User) == 0 {
7✔
338
                return nil, fmt.Errorf("username can not be empty")
1✔
339
        }
1✔
340

341
        targetUser, err := s.getUser(ctx, r.User)
5✔
342
        if err != nil {
6✔
343
                return nil, fmt.Errorf("user %s was not found or it was not created by you", string(r.User))
1✔
344
        }
1✔
345

346
        //if the user is not sys admin then let's make sure the target was created from this admin
347
        if !user.IsSysAdmin {
5✔
348
                if user.Username != targetUser.CreatedBy {
2✔
349
                        return nil, fmt.Errorf("user %s was not found or it was not created by you", string(r.User))
1✔
350
                }
1✔
351
        }
352

353
        _, err = targetUser.SetPassword(r.NewPassword)
3✔
354
        if err != nil {
3✔
355
                return nil, err
×
356
        }
×
357

358
        targetUser.CreatedBy = user.Username
3✔
359
        targetUser.CreatedAt = time.Now()
3✔
360
        if err := s.saveUser(ctx, targetUser); err != nil {
3✔
361
                return nil, err
×
362
        }
×
363

364
        s.Logger.Infof("password for user %s was changed by user %s", targetUser.Username, user.Username)
3✔
365

3✔
366
        // remove user from logged in users
3✔
367
        s.removeUserFromLoginList(targetUser.Username)
3✔
368

3✔
369
        // invalidate the token for this user
3✔
370
        auth.DropTokenKeys(targetUser.Username)
3✔
371

3✔
372
        return new(empty.Empty), nil
3✔
373
}
374

375
// ChangePermission grant or revoke user permissions on databases
376
func (s *ImmuServer) ChangePermission(ctx context.Context, r *schema.ChangePermissionRequest) (*empty.Empty, error) {
17✔
377
        s.Logger.Debugf("ChangePermission %+v", r)
17✔
378

17✔
379
        if s.Options.GetMaintenance() {
18✔
380
                return nil, ErrNotAllowedInMaintenanceMode
1✔
381
        }
1✔
382

383
        //sanitize input
384
        {
16✔
385
                if len(r.Username) == 0 {
17✔
386
                        return nil, status.Errorf(codes.InvalidArgument, "username can not be empty")
1✔
387
                }
1✔
388
                if len(r.Database) == 0 {
16✔
389
                        return nil, status.Errorf(codes.InvalidArgument, "database can not be empty")
1✔
390
                }
1✔
391
                if (r.Action != schema.PermissionAction_GRANT) &&
14✔
392
                        (r.Action != schema.PermissionAction_REVOKE) {
15✔
393
                        return nil, status.Errorf(codes.InvalidArgument, "action not recognized")
1✔
394
                }
1✔
395
                if (r.Permission == auth.PermissionNone) ||
13✔
396
                        ((r.Permission > auth.PermissionRW) &&
13✔
397
                                (r.Permission < auth.PermissionAdmin)) {
14✔
398
                        return nil, status.Errorf(codes.InvalidArgument, "unrecognized permission")
1✔
399
                }
1✔
400
        }
401

402
        _, user, err := s.getLoggedInUserdataFromCtx(ctx)
12✔
403
        if err != nil {
14✔
404
                return nil, err
2✔
405
        }
2✔
406

407
        //do not allow to change own permissions, user can lock itsself out
408
        if r.Username == user.Username {
11✔
409
                return nil, status.Errorf(codes.InvalidArgument, "changing your own permissions is not allowed")
1✔
410
        }
1✔
411

412
        if r.Username == auth.SysAdminUsername {
10✔
413
                return nil, status.Errorf(codes.InvalidArgument, "changing sysadmin permisions is not allowed")
1✔
414
        }
1✔
415

416
        if r.Database == SystemDBName && r.Permission == auth.PermissionRW {
9✔
417
                return nil, ErrPermissionDenied
1✔
418
        }
1✔
419

420
        //check if user exists
421
        targetUser, err := s.getUser(ctx, []byte(r.Username))
7✔
422
        if err != nil {
8✔
423
                return nil, status.Errorf(codes.NotFound, "user %s not found", string(r.Username))
1✔
424
        }
1✔
425

426
        //target user should be active
427
        if !targetUser.Active {
7✔
428
                return nil, status.Errorf(codes.FailedPrecondition, "user %s is not active", string(r.Username))
1✔
429
        }
1✔
430

431
        //check if requesting user has permission on this database
432
        if !user.IsSysAdmin {
5✔
433
                if !user.HasPermission(r.Database, auth.PermissionAdmin) {
×
434
                        return nil, status.Errorf(codes.PermissionDenied, "you do not have permission on this database")
×
435
                }
×
436
        }
437

438
        if r.Action == schema.PermissionAction_REVOKE {
7✔
439
                targetUser.RevokePermission(r.Database)
2✔
440
        } else {
5✔
441
                targetUser.GrantPermission(r.Database, r.Permission)
3✔
442
        }
3✔
443

444
        targetUser.CreatedBy = user.Username
5✔
445
        targetUser.CreatedAt = time.Now()
5✔
446

5✔
447
        if err := s.saveUser(ctx, targetUser); err != nil {
5✔
448
                return nil, err
×
449
        }
×
450

451
        s.Logger.Infof("permissions of user %s for database %s was changed by user %s", targetUser.Username, r.Database, user.Username)
5✔
452

5✔
453
        //remove user from loggedin users
5✔
454
        s.removeUserFromLoginList(targetUser.Username)
5✔
455

5✔
456
        return new(empty.Empty), nil
5✔
457
}
458

459
// SetActiveUser activate or deactivate a user
460
func (s *ImmuServer) SetActiveUser(ctx context.Context, r *schema.SetActiveUserRequest) (*empty.Empty, error) {
26✔
461
        s.Logger.Debugf("SetActiveUser")
26✔
462

26✔
463
        if s.Options.GetMaintenance() {
27✔
464
                return nil, ErrNotAllowedInMaintenanceMode
1✔
465
        }
1✔
466

467
        if !s.Options.GetAuth() {
26✔
468
                return nil, fmt.Errorf("this command is available only with authentication on")
1✔
469
        }
1✔
470

471
        if len(r.Username) == 0 {
25✔
472
                return nil, fmt.Errorf("username can not be empty")
1✔
473
        }
1✔
474

475
        _, user, err := s.getLoggedInUserdataFromCtx(ctx)
23✔
476
        if err != nil {
24✔
477
                return nil, err
1✔
478
        }
1✔
479

480
        if !user.IsSysAdmin {
23✔
481
                if !user.HasAtLeastOnePermission(auth.PermissionAdmin) {
2✔
482
                        return nil, fmt.Errorf("user is not system admin nor admin in any of the databases")
1✔
483
                }
1✔
484
        }
485

486
        if r.Username == user.Username {
22✔
487
                return nil, fmt.Errorf("changing your own status is not allowed")
1✔
488
        }
1✔
489

490
        targetUser, err := s.getUser(ctx, []byte(r.Username))
20✔
491
        if err != nil {
21✔
492
                return nil, fmt.Errorf("user %s not found", r.Username)
1✔
493
        }
1✔
494

495
        //if the user is not sys admin then let's make sure the target was created from this admin
496
        if !user.IsSysAdmin && user.Username != targetUser.CreatedBy {
19✔
497
                return nil, fmt.Errorf("%s was not created by you", r.Username)
×
498
        }
×
499

500
        targetUser.Active = r.Active
19✔
501
        targetUser.CreatedBy = user.Username
19✔
502
        targetUser.CreatedAt = time.Now()
19✔
503

19✔
504
        if err := s.saveUser(ctx, targetUser); err != nil {
19✔
505
                return nil, err
×
506
        }
×
507

508
        s.Logger.Infof("user %s was %s by user %s", targetUser.Username, map[bool]string{
19✔
509
                true:  "activated",
19✔
510
                false: "deactivated",
19✔
511
        }[r.Active], user.Username)
19✔
512

19✔
513
        //remove user from loggedin users
19✔
514
        s.removeUserFromLoginList(targetUser.Username)
19✔
515

19✔
516
        return new(empty.Empty), nil
19✔
517
}
518

519
// insertNewUser inserts a new user to the system database and returns username and plain text password
520
// A new password is generated automatically if passed parameter is empty
521
// If enforceStrongAuth is true it checks if username and password meet security criteria
522
func (s *ImmuServer) insertNewUser(ctx context.Context, username []byte, plainPassword []byte, permission uint32, database string, enforceStrongAuth bool, createdBy string) ([]byte, []byte, error) {
232✔
523
        if enforceStrongAuth {
255✔
524
                if !auth.IsValidUsername(string(username)) {
24✔
525
                        return nil, nil, status.Errorf(
1✔
526
                                codes.InvalidArgument,
1✔
527
                                "username can only contain letters, digits and underscores")
1✔
528
                }
1✔
529
        }
530

531
        if enforceStrongAuth {
253✔
532
                if err := auth.IsStrongPassword(string(plainPassword)); err != nil {
23✔
533
                        return nil, nil, status.Errorf(codes.InvalidArgument, "%v", err)
1✔
534
                }
1✔
535
        }
536

537
        userdata := new(auth.User)
230✔
538
        plainpassword, err := userdata.SetPassword(plainPassword)
230✔
539
        if err != nil {
230✔
540
                return nil, nil, err
×
541
        }
×
542

543
        userdata.Active = true
230✔
544
        userdata.Username = string(username)
230✔
545
        userdata.Permissions = append(userdata.Permissions, auth.Permission{Permission: permission, Database: database})
230✔
546
        userdata.CreatedBy = createdBy
230✔
547
        userdata.CreatedAt = time.Now()
230✔
548

230✔
549
        if permission == auth.PermissionSysAdmin {
438✔
550
                userdata.IsSysAdmin = true
208✔
551
        }
208✔
552

553
        if (permission > auth.PermissionRW) && (permission < auth.PermissionAdmin) {
231✔
554
                return nil, nil, fmt.Errorf("unknown permission")
1✔
555
        }
1✔
556

557
        err = s.saveUser(ctx, userdata)
229✔
558

229✔
559
        return username, plainpassword, err
229✔
560
}
561

562
func (s *ImmuServer) getValidatedUser(ctx context.Context, username []byte, password []byte) (*auth.User, error) {
490✔
563
        userdata, err := s.getUser(ctx, username)
490✔
564
        if err != nil {
492✔
565
                return nil, err
2✔
566
        }
2✔
567

568
        err = userdata.ComparePasswords(password)
488✔
569
        if err != nil {
499✔
570
                return nil, err
11✔
571
        }
11✔
572

573
        return userdata, nil
477✔
574
}
575

576
// getUser returns userdata (username,hashed password, permission, active) from username
577
func (s *ImmuServer) getUser(ctx context.Context, username []byte) (*auth.User, error) {
552✔
578
        key := make([]byte, 1+len(username))
552✔
579
        key[0] = KeyPrefixUser
552✔
580
        copy(key[1:], username)
552✔
581

552✔
582
        item, err := s.sysDB.Get(ctx, &schema.KeyRequest{Key: key})
552✔
583
        if err != nil {
580✔
584
                return nil, err
28✔
585
        }
28✔
586

587
        var usr auth.User
524✔
588

524✔
589
        err = json.Unmarshal(item.Value, &usr)
524✔
590
        if err != nil {
524✔
591
                return nil, err
×
592
        }
×
593

594
        return &usr, nil
524✔
595
}
596

597
func (s *ImmuServer) saveUser(ctx context.Context, user *auth.User) error {
258✔
598
        userData, err := json.Marshal(user)
258✔
599
        if err != nil {
258✔
600
                return logErr(s.Logger, "error saving user: %v", err)
×
601
        }
×
602

603
        userKey := make([]byte, 1+len(user.Username))
258✔
604
        userKey[0] = KeyPrefixUser
258✔
605
        copy(userKey[1:], []byte(user.Username))
258✔
606

258✔
607
        userKV := &schema.KeyValue{Key: userKey, Value: userData}
258✔
608
        _, err = s.sysDB.Set(ctx, &schema.SetRequest{KVs: []*schema.KeyValue{userKV}})
258✔
609

258✔
610
        time.Sleep(time.Duration(10) * time.Millisecond)
258✔
611

258✔
612
        return logErr(s.Logger, "error saving user: %v", err)
258✔
613
}
614

615
func (s *ImmuServer) removeUserFromLoginList(username string) {
31✔
616
        s.userdata.Lock()
31✔
617
        defer s.userdata.Unlock()
31✔
618

31✔
619
        delete(s.userdata.Userdata, username)
31✔
620
}
31✔
621

622
func (s *ImmuServer) addUserToLoginList(u *auth.User) {
72✔
623
        s.userdata.Lock()
72✔
624
        defer s.userdata.Unlock()
72✔
625

72✔
626
        s.userdata.Userdata[u.Username] = u
72✔
627
}
72✔
628

629
func (s *ImmuServer) getLoggedInUserdataFromCtx(ctx context.Context) (int, *auth.User, error) {
15,411✔
630
        if sessionID, err := sessions.GetSessionIDFromContext(ctx); err == nil {
30,271✔
631
                sess, e := s.SessManager.GetSession(sessionID)
14,860✔
632
                if e != nil {
14,860✔
633
                        return 0, nil, e
×
634
                }
×
635

636
                if sess.GetDatabase().GetName() == SystemDBName {
14,862✔
637
                        return sysDBIndex, sess.GetUser(), nil
2✔
638
                }
2✔
639

640
                return s.dbList.GetId(sess.GetDatabase().GetName()), sess.GetUser(), nil
14,858✔
641
        }
642
        jsUser, err := auth.GetLoggedInUser(ctx)
551✔
643
        if err != nil {
635✔
644
                return -1, nil, err
84✔
645
        }
84✔
646

647
        u, err := s.getLoggedInUserDataFromUsername(jsUser.Username)
467✔
648
        return int(jsUser.DatabaseIndex), u, err
467✔
649
}
650

651
func (s *ImmuServer) getLoggedInUserDataFromUsername(username string) (*auth.User, error) {
468✔
652
        s.userdata.Lock()
468✔
653
        defer s.userdata.Unlock()
468✔
654

468✔
655
        userdata, ok := s.userdata.Userdata[username]
468✔
656
        if !ok {
472✔
657
                return nil, ErrNotLoggedIn
4✔
658
        }
4✔
659

660
        return userdata, nil
464✔
661
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2024 Coveralls, Inc