199 lines
5.2 KiB
Go
199 lines
5.2 KiB
Go
package helpers
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log/slog"
|
|
"slices"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"git.maximotejeda.com/maximo/telegram-base-bot/config"
|
|
"git.maximotejeda.com/maximo/telegram-base-bot/internal/ports"
|
|
"github.com/go-telegram/bot"
|
|
"github.com/go-telegram/bot/models"
|
|
)
|
|
|
|
func IsUserRegistered() {}
|
|
func IsUserAuthorized() {}
|
|
func GetPendingAuthRequest() {}
|
|
func CreatePendingAuthRequest() {}
|
|
func DeletePendingAuthRequest() {}
|
|
func BanUSer() {}
|
|
func UnBanUser() {}
|
|
|
|
func Authenticate(ctx context.Context, log *slog.Logger, b *bot.Bot, update *models.Update, uSVC ports.UserService) bool {
|
|
var (
|
|
user models.User
|
|
|
|
)
|
|
// select user
|
|
if update.CallbackQuery != nil {
|
|
user = update.CallbackQuery.From
|
|
} else {
|
|
if update.MessageReaction != nil {
|
|
return true
|
|
}
|
|
user = *update.Message.From
|
|
}
|
|
// bot name
|
|
bn, _ := b.GetMe(ctx)
|
|
switch IsUserAdmin(user.ID) {
|
|
case true:
|
|
// theres an user env admin
|
|
// check if user exist on db
|
|
_, err := uSVC.Get(user.ID)
|
|
if err != nil {
|
|
log.Error("geting user", "error", err)
|
|
log.Debug("user seems to not exists")
|
|
if strings.Contains(err.Error(), "sql: no rows in result set") {
|
|
// if user does not exist create it
|
|
_, err := uSVC.Create(&user)
|
|
log.Debug("creating user")
|
|
if err != nil {
|
|
log.Error("creating new user for admnin", "err", err)
|
|
}
|
|
// add bot to user list
|
|
_, err = uSVC.AddBot(user.ID, bn.Username)
|
|
if err != nil {
|
|
log.Error("Adding bot to admin user list", "err", err)
|
|
}
|
|
}
|
|
}
|
|
return true
|
|
case false:
|
|
// user is not admin and need to be authorized
|
|
// check if user is on db
|
|
_, err := uSVC.Get(user.ID)
|
|
if err != nil {
|
|
// user need auth
|
|
log.Error("user not in db, authorization from an admin is required", "error", err)
|
|
// add user to manage it
|
|
|
|
if strings.Contains(err.Error(), "sql: no rows in result set") {
|
|
// check if theres an access request from the same user and bot
|
|
_, err := uSVC.Create(&user)
|
|
if err != nil {
|
|
log.Error("creating new user", "user", user.ID, "error", err)
|
|
}
|
|
|
|
// create access request
|
|
_, err = uSVC.CreateAccessRequest(user.ID, bn.Username)
|
|
if err != nil {
|
|
log.Error("creating access request for ", "user", user.ID, "error", err)
|
|
}
|
|
}
|
|
} else {
|
|
bots, err := uSVC.GetBots(user.ID)
|
|
if err != nil {
|
|
log.Error("checking bots on user access")
|
|
}
|
|
switch HasUserAccess(bots, bn.Username) {
|
|
case true:
|
|
return true
|
|
case false:
|
|
// check for banned user
|
|
buser, err := uSVC.GetAllBannedUsers(bn.Username)
|
|
if err != nil {
|
|
log.Error("error querying banned user")
|
|
}
|
|
for _, u := range buser.GetBans() {
|
|
if u.TgbId == user.ID {
|
|
b.SendMessage(ctx, &bot.SendMessageParams{
|
|
ChatID: u.TgbId,
|
|
Text: "user access is restricted, please ask for permission",
|
|
},)
|
|
return false
|
|
}
|
|
}
|
|
ac, err := uSVC.GetAccessRequest(user.ID)
|
|
acl := []string{}
|
|
for _, val := range ac.Access {
|
|
acl = append(acl, val.BotName)
|
|
}
|
|
if slices.Contains(acl, bn.Username) {
|
|
// create access request
|
|
log.Info("Access Request found returning early", "user", user.ID, "error", err)
|
|
return false
|
|
} else {
|
|
|
|
// create one
|
|
_, err = uSVC.CreateAccessRequest(user.ID, bn.Username)
|
|
if err != nil {
|
|
log.Error("creating access request", "err", err)
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// get all admins
|
|
userL, _ := GetAdminFromEnv()
|
|
// send a mesage to all admins
|
|
for _, adm := range userL {
|
|
|
|
param := GenerateAccessRequestMessage(user, adm, b, update)
|
|
b.SendMessage(ctx, param)
|
|
}
|
|
return false
|
|
}
|
|
|
|
// GetAdminFromEnv
|
|
// will get an env variable that is a list of tgbID comma separated
|
|
// if the user trying to enter is admin auth the user
|
|
func GetAdminFromEnv() (adminList []int64, errList []error) {
|
|
adminsStrList := config.GetAdminsList()
|
|
list := strings.Split(adminsStrList, ",")
|
|
adminList = []int64{}
|
|
errList = []error{}
|
|
for _, item := range list {
|
|
adm, err := strconv.ParseInt(item, 10, 64)
|
|
if err != nil {
|
|
err = fmt.Errorf("parsing tgb admin id: %s\n err: %w", item, err)
|
|
fmt.Println(err)
|
|
errList = append(errList, err)
|
|
continue
|
|
}
|
|
adminList = append(adminList, adm)
|
|
}
|
|
return
|
|
}
|
|
|
|
// IsUserAdmin
|
|
// check if userID is admin on bot
|
|
func IsUserAdmin(userID int64) bool {
|
|
userL, errl := GetAdminFromEnv()
|
|
if len(errl) > 0 {
|
|
fmt.Printf("error no admin in var %v", errl)
|
|
}
|
|
return slices.Contains(userL, userID)
|
|
}
|
|
|
|
func HasUserAccess(bots []string, botName string) bool {
|
|
return slices.Contains(bots, botName)
|
|
}
|
|
|
|
func GenerateAccessRequestMessage(up models.User, adm int64, b *bot.Bot, update *models.Update) *bot.SendMessageParams {
|
|
txt := fmt.Sprintf(`User %s is requesting access
|
|
ID: %d
|
|
FirstName: %s
|
|
LastName: %s
|
|
ChatID: %d
|
|
`, up.Username, up.ID, up.FirstName, up.LastName, up.ID)
|
|
msg := &bot.SendMessageParams{
|
|
ChatID: adm,
|
|
Text: txt,
|
|
}
|
|
|
|
bn, _ := b.GetMe(context.Background())
|
|
options := [][]string{
|
|
{"Grant", fmt.Sprintf("operation=grant&userID=%d&bot=%s", up.ID, bn.Username)},
|
|
{"Deny", fmt.Sprintf("operation=deny&userID=%d&bot=%s", up.ID, bn.Username)},
|
|
// {"Deny", fmt.Sprintf("operation=ignore&userID=%d&bot=%s", up.ID, bn.Username)},
|
|
}
|
|
kbd := KeyboardWithCancel(options, 2, false)
|
|
|
|
msg.ReplyMarkup = kbd
|
|
return msg
|
|
}
|