diff --git a/actions.go b/actions.go index bb2dc5e9e619d71bac4158fecf154ee26b2b8ad7..61f0abfbf40f3a3d5e68424e57b2dd3ff207b546 100644 --- a/actions.go +++ b/actions.go @@ -407,7 +407,7 @@ func (s *AccountService) DeleteApplicationSpecificPassword(ctx context.Context, // password (we're going to find it via its ID). keys, err := tx.GetUserEncryptionKeys(ctx, user) if err != nil { - return err + return newBackendError(err) } if len(keys) == 0 { return nil @@ -510,7 +510,7 @@ func (s *AccountService) MoveResource(ctx context.Context, tx TX, req *MoveResou // Collect all related resources, as they should all be moved at once. r, err := tx.GetResource(ctx, req.ResourceID) if err != nil { - return err + return newBackendError(err) } var resources []*Resource if r.Group != "" { @@ -522,7 +522,7 @@ func (s *AccountService) MoveResource(ctx context.Context, tx TX, req *MoveResou for _, r := range resources { r.Shard = req.Shard if err := tx.UpdateResource(ctx, r); err != nil { - return err + return newBackendError(err) } resp.MovedIDs = append(resp.MovedIDs, r.ID.String()) } @@ -572,6 +572,7 @@ func (s *AccountService) EnableOTP(ctx context.Context, tx TX, req *EnableOTPReq } resp.TOTPSecret = req.TOTPSecret + s.audit.Log(ctx, ResourceID{}, "totp enabled") return nil }) return &resp, err @@ -589,6 +590,7 @@ func (s *AccountService) DisableOTP(ctx context.Context, tx TX, req *DisableOTPR if err := tx.DeleteUserTOTPSecret(ctx, user); err != nil { return newBackendError(err) } + s.audit.Log(ctx, ResourceID{}, "totp disabled") return nil }) } @@ -652,7 +654,7 @@ func (s *AccountService) DeleteEmailAlias(ctx context.Context, tx TX, req *Delet } r.Email.Aliases = aliases if err := tx.UpdateResource(ctx, r); err != nil { - return err + return newBackendError(err) } s.audit.Log(ctx, r.ID, fmt.Sprintf("removed alias %s", req.Addr)) @@ -729,8 +731,9 @@ func (s *AccountService) CreateResources(ctx context.Context, tx TX, req *Create err := s.handleAdminRequest(ctx, tx, req, req.SSO, func(ctx context.Context) error { for _, r := range req.Resources { if err := tx.CreateResource(ctx, r); err != nil { - return err + return newBackendError(err) } + s.audit.Log(ctx, r.ID, "resource created") resp.Resources = append(resp.Resources, r) } return nil @@ -786,7 +789,7 @@ func (req *CreateUserRequest) Validate(ctx context.Context, s *AccountService, _ return nil } -// CreateUserResponse is the request type for AccountService.CreateUser(). +// CreateUserResponse is the response type for AccountService.CreateUser(). type CreateUserResponse struct { User *User `json:"user,omitempty"` Password string `json:"password"` @@ -812,7 +815,7 @@ func (s *AccountService) CreateUser(ctx context.Context, tx TX, req *CreateUserR err := s.handleAdminRequest(ctx, tx, req, req.SSO, func(ctx context.Context) (err error) { // Create the user first, along with all the resources. if err := tx.CreateUser(ctx, req.User); err != nil { - return err + return newBackendError(err) } resp.User = req.User @@ -826,7 +829,9 @@ func (s *AccountService) CreateUser(ctx context.Context, tx TX, req *CreateUserR } resp.Password = newPassword + s.audit.Log(ctx, ResourceID{}, "user created") for _, r := range req.User.Resources { + s.audit.Log(ctx, r.ID, "resource created") if resourceHasPassword(r) { if _, err := s.doResetResourcePassword(ctx, tx, r); err != nil { // Just log, don't fail. diff --git a/actions_test.go b/actions_test.go index ed87188ad328f816d7ca33701ff8ef7ad1ddd6dc..c0423b31e5dcc0b2e9a14dd0799c1591da80b102 100644 --- a/actions_test.go +++ b/actions_test.go @@ -116,12 +116,16 @@ func (b *fakeBackend) HasAnyResource(_ context.Context, rsrcs []FindResourceRequ const testAdminGroupName = "admins" +// Fake SSO validator: the sso ticket username is just the ticket +// itself. The only invalid value is the empty string. type fakeValidator struct { adminUser string } func (v *fakeValidator) Validate(tkt, nonce, service string, _ []string) (*sso.Ticket, error) { - // The sso ticket username is just the ticket itself. + if tkt == "" { + return nil, errors.New("empty sso ticket") + } var groups []string if tkt == v.adminUser { groups = []string{testAdminGroupName} @@ -422,17 +426,18 @@ func TestService_CreateResource_List(t *testing.T) { func TestService_CreateUser(t *testing.T) { svc, tx := testService("admin") + emailResourceID := NewResourceID(ResourceTypeEmail, "testuser2@example.com", "testuser2@example.com") req := &CreateUserRequest{ SSO: "admin", User: &User{ Name: "testuser2@example.com", Resources: []*Resource{ &Resource{ - ID: NewResourceID(ResourceTypeEmail, "testuser2@example.com", "testuser2@example.com"), - Name: "testuser2@example.com", - Status: ResourceStatusActive, - Shard: "host2", - OriginalShard: "host2", + ID: emailResourceID, + Name: "testuser2@example.com", + //Status: ResourceStatusActive, + //Shard: "host2", + //OriginalShard: "host2", Email: &Email{ Maildir: "example.com/testuser2", }, @@ -449,18 +454,33 @@ func TestService_CreateUser(t *testing.T) { if resp.User.Name != "testuser2@example.com" { t.Fatalf("unexpected user in response: got %s, expected testuser2", resp.User.Name) } + + user, _ := tx.GetUser(context.Background(), "testuser2@example.com") + if user == nil { + t.Fatal("GetUser returned nil") + } + + // Verify that the new resource has default fields set. + resource := user.GetResourceByID(emailResourceID) + if resource == nil { + t.Fatalf("user.GetResourceByID(%s) failed", emailResourceID) + } + if resource.Shard == "" { + t.Fatalf("resource shard is unset: %+v", resource) + } } func TestService_CreateUser_FailIfNotAdmin(t *testing.T) { svc, tx := testService("admin") + emailResourceID := NewResourceID(ResourceTypeEmail, "testuser2@example.com", "testuser2@example.com") req := &CreateUserRequest{ SSO: "testuser", User: &User{ Name: "testuser2@example.com", Resources: []*Resource{ &Resource{ - ID: NewResourceID(ResourceTypeEmail, "testuser2@example.com", "testuser2@example.com"), + ID: emailResourceID, Name: "testuser2@example.com", Status: ResourceStatusActive, Shard: "host2", diff --git a/service.go b/service.go index 8b46fcb1d24b11fc3be02b0e76f4cd2c5574ff55..3c82d693b3164f8ecb3a9bda09edfa7e6dfd8170 100644 --- a/service.go +++ b/service.go @@ -160,7 +160,7 @@ type authUserCtxKeyType int var authUserCtxKey authUserCtxKeyType func authUserFromContext(ctx context.Context) string { - s, ok := ctx.Value(userCtxKey).(string) + s, ok := ctx.Value(authUserCtxKey).(string) if ok { return s }