93 lines
2.3 KiB
Go
93 lines
2.3 KiB
Go
package api
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"github.com/fatih/structs"
|
|
"github.com/supabase/auth/internal/api/provider"
|
|
"github.com/supabase/auth/internal/models"
|
|
"github.com/supabase/auth/internal/storage"
|
|
)
|
|
|
|
// InviteParams are the parameters the Signup endpoint accepts
|
|
type InviteParams struct {
|
|
Email string `json:"email"`
|
|
Data map[string]interface{} `json:"data"`
|
|
}
|
|
|
|
// Invite is the endpoint for inviting a new user
|
|
func (a *API) Invite(w http.ResponseWriter, r *http.Request) error {
|
|
ctx := r.Context()
|
|
db := a.db.WithContext(ctx)
|
|
adminUser := getAdminUser(ctx)
|
|
params := &InviteParams{}
|
|
if err := retrieveRequestParams(r, params); err != nil {
|
|
return err
|
|
}
|
|
|
|
var err error
|
|
params.Email, err = a.validateEmail(params.Email)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
aud := a.requestAud(ctx, r)
|
|
user, err := models.FindUserByEmailAndAudience(db, params.Email, aud)
|
|
if err != nil && !models.IsNotFoundError(err) {
|
|
return internalServerError("Database error finding user").WithInternalError(err)
|
|
}
|
|
|
|
err = db.Transaction(func(tx *storage.Connection) error {
|
|
if user != nil {
|
|
if user.IsConfirmed() {
|
|
return unprocessableEntityError(ErrorCodeEmailExists, DuplicateEmailMsg)
|
|
}
|
|
} else {
|
|
signupParams := SignupParams{
|
|
Email: params.Email,
|
|
Data: params.Data,
|
|
Aud: aud,
|
|
Provider: "email",
|
|
}
|
|
|
|
// because params above sets no password, this method
|
|
// is not computationally hard so it can be used within
|
|
// a database transaction
|
|
user, err = signupParams.ToUserModel(false /* <- isSSOUser */)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
user, err = a.signupNewUser(tx, user)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
identity, err := a.createNewIdentity(tx, user, "email", structs.Map(provider.Claims{
|
|
Subject: user.ID.String(),
|
|
Email: user.GetEmail(),
|
|
}))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
user.Identities = []models.Identity{*identity}
|
|
}
|
|
|
|
if terr := models.NewAuditLogEntry(r, tx, adminUser, models.UserInvitedAction, "", map[string]interface{}{
|
|
"user_id": user.ID,
|
|
"user_email": user.Email,
|
|
}); terr != nil {
|
|
return terr
|
|
}
|
|
|
|
if err := a.sendInvite(r, tx, user); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return sendJSON(w, http.StatusOK, user)
|
|
}
|