(ctx context.Context, orgID, projectID, reportName, ownerID string, emails []string, resources []*adminv1.ResourceName)
| 669 | } |
| 670 | |
| 671 | func (s *Server) createMagicTokens(ctx context.Context, orgID, projectID, reportName, ownerID string, emails []string, resources []*adminv1.ResourceName) (map[string]string, error) { |
| 672 | var createdByUserID *string |
| 673 | if ownerID != "" { |
| 674 | createdByUserID = &ownerID |
| 675 | } |
| 676 | ttl := 3 * 30 * 24 * time.Hour // approx 3 months |
| 677 | mgcOpts := &admin.IssueMagicAuthTokenOptions{ |
| 678 | ProjectID: projectID, |
| 679 | CreatedByUserID: createdByUserID, |
| 680 | Internal: true, |
| 681 | TTL: &ttl, |
| 682 | } |
| 683 | |
| 684 | var res []database.ResourceName |
| 685 | for _, r := range resources { |
| 686 | res = append(res, database.ResourceName{ |
| 687 | Type: r.Type, |
| 688 | Name: r.Name, |
| 689 | }) |
| 690 | } |
| 691 | |
| 692 | mgcOpts.Resources = res |
| 693 | |
| 694 | if ownerID != "" { |
| 695 | // Get the project-level permissions for the creating user. |
| 696 | orgPerms, err := s.admin.OrganizationPermissionsForUser(ctx, orgID, ownerID) |
| 697 | if err != nil { |
| 698 | return nil, err |
| 699 | } |
| 700 | projectPermissions, err := s.admin.ProjectPermissionsForUser(ctx, projectID, ownerID, orgPerms) |
| 701 | if err != nil { |
| 702 | return nil, err |
| 703 | } |
| 704 | |
| 705 | // Generate JWT attributes based on the creating user's, but with limited project-level permissions. |
| 706 | // We store these attributes with the magic token, so it can simulate the creating user (even if the creating user is later deleted or their permissions change). |
| 707 | // |
| 708 | // NOTE: A problem with this approach is that if we change the built-in format of JWT attributes, these will remain as they were when captured. |
| 709 | // NOTE: Another problem is that if the creator is an admin, attrs["admin"] will be true. It shouldn't be a problem today, but could end up leaking some privileges in the future if we're not careful. |
| 710 | attrs, err := s.jwtAttributesForUser(ctx, ownerID, orgID, projectPermissions) |
| 711 | if err != nil { |
| 712 | return nil, err |
| 713 | } |
| 714 | mgcOpts.Attributes = attrs |
| 715 | } |
| 716 | |
| 717 | // issue magic tokens |
| 718 | cctx, tx, err := s.admin.DB.NewTx(ctx, false) |
| 719 | if err != nil { |
| 720 | return nil, fmt.Errorf("failed to start transaction: %w", err) |
| 721 | } |
| 722 | defer func() { _ = tx.Rollback() }() |
| 723 | |
| 724 | emailTokens := make(map[string]string) |
| 725 | for _, email := range emails { |
| 726 | if ownerID == "" { |
| 727 | // set user attrs as per the email |
| 728 | mgcOpts.Attributes = map[string]interface{}{ |
no test coverage detected