InviteMembers creates accounts for the supplied emails that do not yet exist and sends each an invite (magic-link or setup-password) email. Requires super-admin auth and a configured email service. Logic migrated from internal/graphql/invite_members.go.
(ctx context.Context, meta RequestMetadata, params *model.InviteMemberRequest)
| 111 | // super-admin auth and a configured email service. Logic migrated from |
| 112 | // internal/graphql/invite_members.go. |
| 113 | func (p *provider) InviteMembers(ctx context.Context, meta RequestMetadata, params *model.InviteMemberRequest) (*model.InviteMembersResponse, *ResponseSideEffects, error) { |
| 114 | log := p.Log.With().Str("func", "InviteMembers").Logger() |
| 115 | if err := p.requireSuperAdmin(ctx, meta); err != nil { |
| 116 | return nil, nil, err |
| 117 | } |
| 118 | |
| 119 | // this feature is only allowed if email server is configured |
| 120 | if !p.Config.IsEmailServiceEnabled { |
| 121 | log.Debug().Msg("Email sending is disabled") |
| 122 | return nil, nil, errors.New("email sending is disabled") |
| 123 | } |
| 124 | |
| 125 | isBasicAuthEnabled := p.Config.EnableBasicAuthentication |
| 126 | isMagicLinkLoginEnabled := p.Config.EnableMagicLinkLogin |
| 127 | if !isBasicAuthEnabled && !isMagicLinkLoginEnabled { |
| 128 | log.Debug().Msg("Either basic authentication or magic link login is required") |
| 129 | return nil, nil, errors.New("either basic authentication or magic link login is required") |
| 130 | } |
| 131 | |
| 132 | // filter valid emails |
| 133 | emails := []string{} |
| 134 | for _, email := range params.Emails { |
| 135 | if validators.IsValidEmail(email) { |
| 136 | emails = append(emails, email) |
| 137 | } |
| 138 | } |
| 139 | |
| 140 | if len(emails) == 0 { |
| 141 | log.Debug().Msg("No valid emails found") |
| 142 | return nil, nil, errors.New("no valid emails found") |
| 143 | } |
| 144 | |
| 145 | // TODO: optimise to use like query instead of looping through emails and getting user individually |
| 146 | // for each emails check if emails exists in db |
| 147 | newEmails := []string{} |
| 148 | for _, email := range emails { |
| 149 | _, err := p.StorageProvider.GetUserByEmail(ctx, email) |
| 150 | if err != nil { |
| 151 | log.Debug().Msgf("User with %s email does not exist", email) |
| 152 | newEmails = append(newEmails, email) |
| 153 | } else { |
| 154 | log.Debug().Msgf("User with %s email already exists", email) |
| 155 | } |
| 156 | } |
| 157 | |
| 158 | if len(newEmails) == 0 { |
| 159 | log.Debug().Msg("All emails already exist") |
| 160 | return nil, nil, errors.New("all emails already exist") |
| 161 | } |
| 162 | |
| 163 | // gin-shim: parsers.GetHost / GetAppURL still take a *gin.Context. |
| 164 | gc := &gin.Context{Request: meta.Request} |
| 165 | |
| 166 | // invite new emails |
| 167 | for _, email := range newEmails { |
| 168 | user := &schemas.User{ |
| 169 | Email: refs.NewStringRef(email), |
| 170 | Roles: strings.Join(p.Config.DefaultRoles, ","), |
nothing calls this directly
no test coverage detected