2022-07-05 11:10:18 +01:00
|
|
|
package invite
|
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/rand"
|
|
|
|
"database/sql"
|
|
|
|
"errors"
|
|
|
|
"math/big"
|
2022-07-23 12:57:55 +01:00
|
|
|
"whitelistmanager/internal/store"
|
2022-07-05 11:10:18 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
const NotOwnerofServer = "user is not owner of server"
|
|
|
|
|
|
|
|
type Manager struct {
|
|
|
|
store store.Storer
|
|
|
|
}
|
|
|
|
|
|
|
|
type InviteManager interface {
|
|
|
|
Create(in store.Invite, user store.User) (string, error)
|
|
|
|
RemainingUses(in store.Invite) (int, error)
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewManager(db store.Storer) *Manager {
|
|
|
|
return &Manager{store: db}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (i *Manager) Create(in store.Invite, user store.User) (string, error) {
|
|
|
|
server, err := i.store.GetServer(in.Server.Id)
|
|
|
|
if server.Owner.Id != user.Id {
|
|
|
|
return "", errors.New(NotOwnerofServer)
|
|
|
|
}
|
|
|
|
|
|
|
|
token, err := i.createToken()
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we have an unlikely collision, generate a new token.
|
|
|
|
_, err = i.store.GetInvite(token)
|
|
|
|
if err != nil {
|
|
|
|
if !errors.Is(err, sql.ErrNoRows) {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
token, err = i.createToken()
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
in.Token = token
|
|
|
|
in.Creator = user
|
|
|
|
return token, i.store.SaveInvite(in)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (i *Manager) createToken() (string, error) {
|
2022-07-15 17:38:53 +01:00
|
|
|
const letters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
2022-07-05 11:10:18 +01:00
|
|
|
ret := make([]byte, 8)
|
|
|
|
for i := 0; i < 8; i++ {
|
|
|
|
num, err := rand.Int(rand.Reader, big.NewInt(int64(len(letters))))
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
ret[i] = letters[num.Int64()]
|
|
|
|
}
|
|
|
|
|
|
|
|
return string(ret), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (i *Manager) RemainingUses(in store.Invite) (int, error) {
|
|
|
|
if in.Unlimited {
|
|
|
|
return 1, nil
|
|
|
|
}
|
|
|
|
logs, err := i.store.InviteLog(in)
|
|
|
|
if err != nil {
|
|
|
|
return 0, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return in.Uses - len(logs), nil
|
|
|
|
}
|