code.gitea.io/gitea@v1.22.3/models/organization/team_invite.go (about)

     1  // Copyright 2022 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package organization
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  
    10  	"code.gitea.io/gitea/models/db"
    11  	user_model "code.gitea.io/gitea/models/user"
    12  	"code.gitea.io/gitea/modules/timeutil"
    13  	"code.gitea.io/gitea/modules/util"
    14  
    15  	"xorm.io/builder"
    16  )
    17  
    18  type ErrTeamInviteAlreadyExist struct {
    19  	TeamID int64
    20  	Email  string
    21  }
    22  
    23  func IsErrTeamInviteAlreadyExist(err error) bool {
    24  	_, ok := err.(ErrTeamInviteAlreadyExist)
    25  	return ok
    26  }
    27  
    28  func (err ErrTeamInviteAlreadyExist) Error() string {
    29  	return fmt.Sprintf("team invite already exists [team_id: %d, email: %s]", err.TeamID, err.Email)
    30  }
    31  
    32  func (err ErrTeamInviteAlreadyExist) Unwrap() error {
    33  	return util.ErrAlreadyExist
    34  }
    35  
    36  type ErrTeamInviteNotFound struct {
    37  	Token string
    38  }
    39  
    40  func IsErrTeamInviteNotFound(err error) bool {
    41  	_, ok := err.(ErrTeamInviteNotFound)
    42  	return ok
    43  }
    44  
    45  func (err ErrTeamInviteNotFound) Error() string {
    46  	return fmt.Sprintf("team invite was not found [token: %s]", err.Token)
    47  }
    48  
    49  func (err ErrTeamInviteNotFound) Unwrap() error {
    50  	return util.ErrNotExist
    51  }
    52  
    53  // ErrUserEmailAlreadyAdded represents a "user by email already added to team" error.
    54  type ErrUserEmailAlreadyAdded struct {
    55  	Email string
    56  }
    57  
    58  // IsErrUserEmailAlreadyAdded checks if an error is a ErrUserEmailAlreadyAdded.
    59  func IsErrUserEmailAlreadyAdded(err error) bool {
    60  	_, ok := err.(ErrUserEmailAlreadyAdded)
    61  	return ok
    62  }
    63  
    64  func (err ErrUserEmailAlreadyAdded) Error() string {
    65  	return fmt.Sprintf("user with email already added [email: %s]", err.Email)
    66  }
    67  
    68  func (err ErrUserEmailAlreadyAdded) Unwrap() error {
    69  	return util.ErrAlreadyExist
    70  }
    71  
    72  // TeamInvite represents an invite to a team
    73  type TeamInvite struct {
    74  	ID          int64              `xorm:"pk autoincr"`
    75  	Token       string             `xorm:"UNIQUE(token) INDEX NOT NULL DEFAULT ''"`
    76  	InviterID   int64              `xorm:"NOT NULL DEFAULT 0"`
    77  	OrgID       int64              `xorm:"INDEX NOT NULL DEFAULT 0"`
    78  	TeamID      int64              `xorm:"UNIQUE(team_mail) INDEX NOT NULL DEFAULT 0"`
    79  	Email       string             `xorm:"UNIQUE(team_mail) NOT NULL DEFAULT ''"`
    80  	CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
    81  	UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
    82  }
    83  
    84  func CreateTeamInvite(ctx context.Context, doer *user_model.User, team *Team, email string) (*TeamInvite, error) {
    85  	has, err := db.GetEngine(ctx).Exist(&TeamInvite{
    86  		TeamID: team.ID,
    87  		Email:  email,
    88  	})
    89  	if err != nil {
    90  		return nil, err
    91  	}
    92  	if has {
    93  		return nil, ErrTeamInviteAlreadyExist{
    94  			TeamID: team.ID,
    95  			Email:  email,
    96  		}
    97  	}
    98  
    99  	// check if the user is already a team member by email
   100  	exist, err := db.GetEngine(ctx).
   101  		Where(builder.Eq{
   102  			"team_user.org_id":  team.OrgID,
   103  			"team_user.team_id": team.ID,
   104  			"`user`.email":      email,
   105  		}).
   106  		Join("INNER", "`user`", "`user`.id = team_user.uid").
   107  		Table("team_user").
   108  		Exist()
   109  	if err != nil {
   110  		return nil, err
   111  	}
   112  
   113  	if exist {
   114  		return nil, ErrUserEmailAlreadyAdded{
   115  			Email: email,
   116  		}
   117  	}
   118  
   119  	token, err := util.CryptoRandomString(25)
   120  	if err != nil {
   121  		return nil, err
   122  	}
   123  
   124  	invite := &TeamInvite{
   125  		Token:     token,
   126  		InviterID: doer.ID,
   127  		OrgID:     team.OrgID,
   128  		TeamID:    team.ID,
   129  		Email:     email,
   130  	}
   131  
   132  	return invite, db.Insert(ctx, invite)
   133  }
   134  
   135  func RemoveInviteByID(ctx context.Context, inviteID, teamID int64) error {
   136  	_, err := db.DeleteByBean(ctx, &TeamInvite{
   137  		ID:     inviteID,
   138  		TeamID: teamID,
   139  	})
   140  	return err
   141  }
   142  
   143  func GetInvitesByTeamID(ctx context.Context, teamID int64) ([]*TeamInvite, error) {
   144  	invites := make([]*TeamInvite, 0, 10)
   145  	return invites, db.GetEngine(ctx).
   146  		Where("team_id=?", teamID).
   147  		Find(&invites)
   148  }
   149  
   150  func GetInviteByToken(ctx context.Context, token string) (*TeamInvite, error) {
   151  	invite := &TeamInvite{}
   152  
   153  	has, err := db.GetEngine(ctx).Where("token=?", token).Get(invite)
   154  	if err != nil {
   155  		return nil, err
   156  	}
   157  	if !has {
   158  		return nil, ErrTeamInviteNotFound{Token: token}
   159  	}
   160  	return invite, nil
   161  }