(ctx context.Context, req *adminv1.AddOrganizationMemberUserRequest)
| 405 | } |
| 406 | |
| 407 | func (s *Server) AddOrganizationMemberUser(ctx context.Context, req *adminv1.AddOrganizationMemberUserRequest) (*adminv1.AddOrganizationMemberUserResponse, error) { |
| 408 | observability.AddRequestAttributes(ctx, |
| 409 | attribute.String("args.org", req.Org), |
| 410 | attribute.String("args.email", req.Email), |
| 411 | attribute.String("args.role", req.Role), |
| 412 | ) |
| 413 | |
| 414 | org, err := s.admin.DB.FindOrganizationByName(ctx, req.Org) |
| 415 | if err != nil { |
| 416 | return nil, err |
| 417 | } |
| 418 | |
| 419 | claims := auth.GetClaims(ctx) |
| 420 | forceAccess := claims.Superuser(ctx) && req.SuperuserForceAccess |
| 421 | if !claims.OrganizationPermissions(ctx, org.ID).ManageOrgMembers && !forceAccess { |
| 422 | return nil, status.Error(codes.PermissionDenied, "not allowed to add org members") |
| 423 | } |
| 424 | |
| 425 | count, err := s.admin.DB.CountInvitesForOrganization(ctx, org.ID) |
| 426 | if err != nil { |
| 427 | return nil, err |
| 428 | } |
| 429 | if org.QuotaOutstandingInvites >= 0 && count >= org.QuotaOutstandingInvites { |
| 430 | return nil, status.Errorf(codes.FailedPrecondition, "quota exceeded: org can at most have %d outstanding invitations", org.QuotaOutstandingInvites) |
| 431 | } |
| 432 | |
| 433 | role, err := s.admin.DB.FindOrganizationRole(ctx, req.Role) |
| 434 | if err != nil { |
| 435 | return nil, err |
| 436 | } |
| 437 | if role.Admin && !claims.OrganizationPermissions(ctx, org.ID).ManageOrgAdmins && !forceAccess { |
| 438 | return nil, status.Error(codes.PermissionDenied, "as a non-admin you are not allowed to assign an admin role") |
| 439 | } |
| 440 | |
| 441 | var invitedByUserID, invitedByName string |
| 442 | if claims.OwnerType() == auth.OwnerTypeUser { |
| 443 | user, err := s.admin.DB.FindUser(ctx, claims.OwnerID()) |
| 444 | if err != nil && !errors.Is(err, database.ErrNotFound) { |
| 445 | return nil, err |
| 446 | } |
| 447 | if user != nil { |
| 448 | invitedByUserID = user.ID |
| 449 | invitedByName = user.DisplayName |
| 450 | } |
| 451 | } |
| 452 | |
| 453 | user, err := s.admin.DB.FindUserByEmail(ctx, req.Email) |
| 454 | if err != nil { |
| 455 | if !errors.Is(err, database.ErrNotFound) { |
| 456 | return nil, err |
| 457 | } |
| 458 | |
| 459 | // Invite user to join org |
| 460 | err := s.admin.DB.InsertOrganizationInvite(ctx, &database.InsertOrganizationInviteOptions{ |
| 461 | Email: req.Email, |
| 462 | InviterID: invitedByUserID, |
| 463 | OrgID: org.ID, |
| 464 | RoleID: role.ID, |
nothing calls this directly
no test coverage detected