mirror of
https://github.com/hrfee/jfa-go.git
synced 2024-12-22 09:00:10 +00:00
messages: assign tokens to jf users on userpage
pins generated on the user page are assigned to that user, no other jellyifn user can verify them.
This commit is contained in:
parent
3747eaa3a7
commit
e4a7172517
@ -301,10 +301,10 @@ func (app *appContext) GetMyPIN(gc *gin.Context) {
|
|||||||
resp := GetMyPINDTO{}
|
resp := GetMyPINDTO{}
|
||||||
switch service {
|
switch service {
|
||||||
case "discord":
|
case "discord":
|
||||||
resp.PIN = app.discord.NewAuthToken()
|
resp.PIN = app.discord.NewAssignedAuthToken(gc.GetString("jfId"))
|
||||||
break
|
break
|
||||||
case "telegram":
|
case "telegram":
|
||||||
resp.PIN = app.telegram.NewAuthToken()
|
resp.PIN = app.telegram.NewAssignedAuthToken(gc.GetString("jfId"))
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
respond(400, "invalid service", gc)
|
respond(400, "invalid service", gc)
|
||||||
@ -322,7 +322,7 @@ func (app *appContext) GetMyPIN(gc *gin.Context) {
|
|||||||
// @tags User Page
|
// @tags User Page
|
||||||
func (app *appContext) MyDiscordVerifiedInvite(gc *gin.Context) {
|
func (app *appContext) MyDiscordVerifiedInvite(gc *gin.Context) {
|
||||||
pin := gc.Param("pin")
|
pin := gc.Param("pin")
|
||||||
dcUser, ok := app.discord.UserVerified(pin)
|
dcUser, ok := app.discord.AssignedUserVerified(pin, gc.GetString("jfId"))
|
||||||
app.discord.DeleteVerifiedUser(pin)
|
app.discord.DeleteVerifiedUser(pin)
|
||||||
if !ok {
|
if !ok {
|
||||||
respondBool(200, false, gc)
|
respondBool(200, false, gc)
|
||||||
@ -350,7 +350,7 @@ func (app *appContext) MyDiscordVerifiedInvite(gc *gin.Context) {
|
|||||||
// @tags User Page
|
// @tags User Page
|
||||||
func (app *appContext) MyTelegramVerifiedInvite(gc *gin.Context) {
|
func (app *appContext) MyTelegramVerifiedInvite(gc *gin.Context) {
|
||||||
pin := gc.Param("pin")
|
pin := gc.Param("pin")
|
||||||
token, ok := app.telegram.TokenVerified(pin)
|
token, ok := app.telegram.AssignedTokenVerified(pin, gc.GetString("jfId"))
|
||||||
app.telegram.DeleteVerifiedToken(pin)
|
app.telegram.DeleteVerifiedToken(pin)
|
||||||
if !ok {
|
if !ok {
|
||||||
respondBool(200, false, gc)
|
respondBool(200, false, gc)
|
||||||
|
43
discord.go
43
discord.go
@ -13,8 +13,8 @@ type DiscordDaemon struct {
|
|||||||
ShutdownChannel chan string
|
ShutdownChannel chan string
|
||||||
bot *dg.Session
|
bot *dg.Session
|
||||||
username string
|
username string
|
||||||
tokens map[string]time.Time // Map of tokens to expiry times.
|
tokens map[string]VerifToken // Map of pins to tokens.
|
||||||
verifiedTokens map[string]DiscordUser // Map of tokens to discord users.
|
verifiedTokens map[string]DiscordUser // Map of token pins to discord users.
|
||||||
channelID, channelName, inviteChannelID, inviteChannelName string
|
channelID, channelName, inviteChannelID, inviteChannelName string
|
||||||
guildID string
|
guildID string
|
||||||
serverChannelName, serverName string
|
serverChannelName, serverName string
|
||||||
@ -38,7 +38,7 @@ func newDiscordDaemon(app *appContext) (*DiscordDaemon, error) {
|
|||||||
Stopped: false,
|
Stopped: false,
|
||||||
ShutdownChannel: make(chan string),
|
ShutdownChannel: make(chan string),
|
||||||
bot: bot,
|
bot: bot,
|
||||||
tokens: map[string]time.Time{},
|
tokens: map[string]VerifToken{},
|
||||||
verifiedTokens: map[string]DiscordUser{},
|
verifiedTokens: map[string]DiscordUser{},
|
||||||
users: map[string]DiscordUser{},
|
users: map[string]DiscordUser{},
|
||||||
app: app,
|
app: app,
|
||||||
@ -59,7 +59,15 @@ func newDiscordDaemon(app *appContext) (*DiscordDaemon, error) {
|
|||||||
// NewAuthToken generates an 8-character pin in the form "A1-2B-CD".
|
// NewAuthToken generates an 8-character pin in the form "A1-2B-CD".
|
||||||
func (d *DiscordDaemon) NewAuthToken() string {
|
func (d *DiscordDaemon) NewAuthToken() string {
|
||||||
pin := genAuthToken()
|
pin := genAuthToken()
|
||||||
d.tokens[pin] = time.Now().Add(VERIF_TOKEN_EXPIRY_SEC * time.Second)
|
d.tokens[pin] = VerifToken{Expiry: time.Now().Add(VERIF_TOKEN_EXPIRY_SEC * time.Second), JellyfinID: ""}
|
||||||
|
return pin
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewAssignedAuthToken generates an 8-character pin in the form "A1-2B-CD",
|
||||||
|
// and assigns it for access only with the given Jellyfin ID.
|
||||||
|
func (d *DiscordDaemon) NewAssignedAuthToken(id string) string {
|
||||||
|
pin := genAuthToken()
|
||||||
|
d.tokens[pin] = VerifToken{Expiry: time.Now().Add(VERIF_TOKEN_EXPIRY_SEC * time.Second), JellyfinID: id}
|
||||||
return pin
|
return pin
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -432,8 +440,8 @@ func (d *DiscordDaemon) cmdStart(s *dg.Session, i *dg.InteractionCreate, lang st
|
|||||||
|
|
||||||
func (d *DiscordDaemon) cmdPIN(s *dg.Session, i *dg.InteractionCreate, lang string) {
|
func (d *DiscordDaemon) cmdPIN(s *dg.Session, i *dg.InteractionCreate, lang string) {
|
||||||
pin := i.ApplicationCommandData().Options[0].StringValue()
|
pin := i.ApplicationCommandData().Options[0].StringValue()
|
||||||
expiry, ok := d.tokens[pin]
|
user, ok := d.tokens[pin]
|
||||||
if !ok || time.Now().After(expiry) {
|
if !ok || time.Now().After(user.Expiry) {
|
||||||
err := s.InteractionRespond(i.Interaction, &dg.InteractionResponse{
|
err := s.InteractionRespond(i.Interaction, &dg.InteractionResponse{
|
||||||
// Type: dg.InteractionResponseChannelMessageWithSource,
|
// Type: dg.InteractionResponseChannelMessageWithSource,
|
||||||
Type: dg.InteractionResponseChannelMessageWithSource,
|
Type: dg.InteractionResponseChannelMessageWithSource,
|
||||||
@ -459,7 +467,9 @@ func (d *DiscordDaemon) cmdPIN(s *dg.Session, i *dg.InteractionCreate, lang stri
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
d.app.err.Printf("Discord: Failed to send message to \"%s\": %v", i.Interaction.Member.User.Username, err)
|
d.app.err.Printf("Discord: Failed to send message to \"%s\": %v", i.Interaction.Member.User.Username, err)
|
||||||
}
|
}
|
||||||
d.verifiedTokens[pin] = d.users[i.Interaction.Member.User.ID]
|
dcUser := d.users[i.Interaction.Member.User.ID]
|
||||||
|
dcUser.JellyfinID = user.JellyfinID
|
||||||
|
d.verifiedTokens[pin] = dcUser
|
||||||
delete(d.tokens, pin)
|
delete(d.tokens, pin)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -601,8 +611,8 @@ func (d *DiscordDaemon) msgPIN(s *dg.Session, m *dg.MessageCreate, sects []strin
|
|||||||
d.app.debug.Println("Discord: Ignoring message as user was not found")
|
d.app.debug.Println("Discord: Ignoring message as user was not found")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
expiry, ok := d.tokens[sects[0]]
|
user, ok := d.tokens[sects[0]]
|
||||||
if !ok || time.Now().After(expiry) {
|
if !ok || time.Now().After(user.Expiry) {
|
||||||
_, err := s.ChannelMessageSend(
|
_, err := s.ChannelMessageSend(
|
||||||
m.ChannelID,
|
m.ChannelID,
|
||||||
d.app.storage.lang.Telegram[lang].Strings.get("invalidPIN"),
|
d.app.storage.lang.Telegram[lang].Strings.get("invalidPIN"),
|
||||||
@ -620,7 +630,9 @@ func (d *DiscordDaemon) msgPIN(s *dg.Session, m *dg.MessageCreate, sects []strin
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
d.app.err.Printf("Discord: Failed to send message to \"%s\": %v", m.Author.Username, err)
|
d.app.err.Printf("Discord: Failed to send message to \"%s\": %v", m.Author.Username, err)
|
||||||
}
|
}
|
||||||
d.verifiedTokens[sects[0]] = d.users[m.Author.ID]
|
dcUser := d.users[m.Author.ID]
|
||||||
|
dcUser.JellyfinID = user.JellyfinID
|
||||||
|
d.verifiedTokens[sects[0]] = dcUser
|
||||||
delete(d.tokens, sects[0])
|
delete(d.tokens, sects[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -683,6 +695,17 @@ func (d *DiscordDaemon) UserVerified(pin string) (user DiscordUser, ok bool) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AssignedUserVerified returns whether or not a user with the given PIN has been verified, and the token itself.
|
||||||
|
// Returns false if the given Jellyfin ID does not match the one in the user.
|
||||||
|
func (d *DiscordDaemon) AssignedUserVerified(pin string, jfID string) (user DiscordUser, ok bool) {
|
||||||
|
user, ok = d.verifiedTokens[pin]
|
||||||
|
if ok && user.JellyfinID != jfID {
|
||||||
|
ok = false
|
||||||
|
}
|
||||||
|
// delete(d.verifiedUsers, pin)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// UserExists returns whether or not a user with the given ID exists.
|
// UserExists returns whether or not a user with the given ID exists.
|
||||||
func (d *DiscordDaemon) UserExists(id string) (ok bool) {
|
func (d *DiscordDaemon) UserExists(id string) (ok bool) {
|
||||||
ok = false
|
ok = false
|
||||||
|
@ -181,6 +181,7 @@ type DiscordUser struct {
|
|||||||
Discriminator string
|
Discriminator string
|
||||||
Lang string
|
Lang string
|
||||||
Contact bool
|
Contact bool
|
||||||
|
JellyfinID string `json:"-"` // Used internally in discord.go
|
||||||
}
|
}
|
||||||
|
|
||||||
type EmailAddress struct {
|
type EmailAddress struct {
|
||||||
|
47
telegram.go
47
telegram.go
@ -14,8 +14,15 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type TelegramVerifiedToken struct {
|
type TelegramVerifiedToken struct {
|
||||||
ChatID int64
|
ChatID int64
|
||||||
Username string
|
Username string
|
||||||
|
JellyfinID string // optional, for ensuring a user-requested change is only accessed by them.
|
||||||
|
}
|
||||||
|
|
||||||
|
// VerifToken stores details about a pending user verification token.
|
||||||
|
type VerifToken struct {
|
||||||
|
Expiry time.Time
|
||||||
|
JellyfinID string // optional, for ensuring a user-requested change is only accessed by them.
|
||||||
}
|
}
|
||||||
|
|
||||||
type TelegramDaemon struct {
|
type TelegramDaemon struct {
|
||||||
@ -23,8 +30,8 @@ type TelegramDaemon struct {
|
|||||||
ShutdownChannel chan string
|
ShutdownChannel chan string
|
||||||
bot *tg.BotAPI
|
bot *tg.BotAPI
|
||||||
username string
|
username string
|
||||||
tokens map[string]time.Time // Map of tokens to their expiry time.
|
tokens map[string]VerifToken // Map of pins to tokens.
|
||||||
verifiedTokens map[string]TelegramVerifiedToken // Map of tokens to the responsible ChatID+Username.
|
verifiedTokens map[string]TelegramVerifiedToken // Map of token pins to the responsible ChatID+Username.
|
||||||
languages map[int64]string // Store of languages for chatIDs. Added to on first interaction, and loaded from app.storage.telegram on start.
|
languages map[int64]string // Store of languages for chatIDs. Added to on first interaction, and loaded from app.storage.telegram on start.
|
||||||
link string
|
link string
|
||||||
app *appContext
|
app *appContext
|
||||||
@ -43,7 +50,7 @@ func newTelegramDaemon(app *appContext) (*TelegramDaemon, error) {
|
|||||||
ShutdownChannel: make(chan string),
|
ShutdownChannel: make(chan string),
|
||||||
bot: bot,
|
bot: bot,
|
||||||
username: bot.Self.UserName,
|
username: bot.Self.UserName,
|
||||||
tokens: map[string]time.Time{},
|
tokens: map[string]VerifToken{},
|
||||||
verifiedTokens: map[string]TelegramVerifiedToken{},
|
verifiedTokens: map[string]TelegramVerifiedToken{},
|
||||||
languages: map[int64]string{},
|
languages: map[int64]string{},
|
||||||
link: "https://t.me/" + bot.Self.UserName,
|
link: "https://t.me/" + bot.Self.UserName,
|
||||||
@ -75,7 +82,15 @@ var runes = []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
|
|||||||
// NewAuthToken generates an 8-character pin in the form "A1-2B-CD".
|
// NewAuthToken generates an 8-character pin in the form "A1-2B-CD".
|
||||||
func (t *TelegramDaemon) NewAuthToken() string {
|
func (t *TelegramDaemon) NewAuthToken() string {
|
||||||
pin := genAuthToken()
|
pin := genAuthToken()
|
||||||
t.tokens[pin] = time.Now().Add(VERIF_TOKEN_EXPIRY_SEC * time.Second)
|
t.tokens[pin] = VerifToken{Expiry: time.Now().Add(VERIF_TOKEN_EXPIRY_SEC * time.Second), JellyfinID: ""}
|
||||||
|
return pin
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewAssignedAuthToken generates an 8-character pin in the form "A1-2B-CD",
|
||||||
|
// and assigns it for access only with the given Jellyfin ID.
|
||||||
|
func (t *TelegramDaemon) NewAssignedAuthToken(id string) string {
|
||||||
|
pin := genAuthToken()
|
||||||
|
t.tokens[pin] = VerifToken{Expiry: time.Now().Add(VERIF_TOKEN_EXPIRY_SEC * time.Second), JellyfinID: id}
|
||||||
return pin
|
return pin
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,8 +230,8 @@ func (t *TelegramDaemon) commandLang(upd *tg.Update, sects []string, lang string
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *TelegramDaemon) commandPIN(upd *tg.Update, sects []string, lang string) {
|
func (t *TelegramDaemon) commandPIN(upd *tg.Update, sects []string, lang string) {
|
||||||
expiry, ok := t.tokens[upd.Message.Text]
|
token, ok := t.tokens[upd.Message.Text]
|
||||||
if !ok || time.Now().After(expiry) {
|
if !ok || time.Now().After(token.Expiry) {
|
||||||
err := t.QuoteReply(upd, t.app.storage.lang.Telegram[lang].Strings.get("invalidPIN"))
|
err := t.QuoteReply(upd, t.app.storage.lang.Telegram[lang].Strings.get("invalidPIN"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.app.err.Printf("Telegram: Failed to send message to \"%s\": %v", upd.Message.From.UserName, err)
|
t.app.err.Printf("Telegram: Failed to send message to \"%s\": %v", upd.Message.From.UserName, err)
|
||||||
@ -229,8 +244,9 @@ func (t *TelegramDaemon) commandPIN(upd *tg.Update, sects []string, lang string)
|
|||||||
t.app.err.Printf("Telegram: Failed to send message to \"%s\": %v", upd.Message.From.UserName, err)
|
t.app.err.Printf("Telegram: Failed to send message to \"%s\": %v", upd.Message.From.UserName, err)
|
||||||
}
|
}
|
||||||
t.verifiedTokens[upd.Message.Text] = TelegramVerifiedToken{
|
t.verifiedTokens[upd.Message.Text] = TelegramVerifiedToken{
|
||||||
ChatID: upd.Message.Chat.ID,
|
ChatID: upd.Message.Chat.ID,
|
||||||
Username: upd.Message.Chat.UserName,
|
Username: upd.Message.Chat.UserName,
|
||||||
|
JellyfinID: token.JellyfinID,
|
||||||
}
|
}
|
||||||
delete(t.tokens, upd.Message.Text)
|
delete(t.tokens, upd.Message.Text)
|
||||||
}
|
}
|
||||||
@ -242,6 +258,17 @@ func (t *TelegramDaemon) TokenVerified(pin string) (token TelegramVerifiedToken,
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AssignedTokenVerified returns whether or not a token with the given PIN has been verified, and the token itself.
|
||||||
|
// Returns false if the given Jellyfin ID does not match the one in the token.
|
||||||
|
func (t *TelegramDaemon) AssignedTokenVerified(pin string, jfID string) (token TelegramVerifiedToken, ok bool) {
|
||||||
|
token, ok = t.verifiedTokens[pin]
|
||||||
|
if ok && token.JellyfinID != jfID {
|
||||||
|
ok = false
|
||||||
|
}
|
||||||
|
// delete(t.verifiedTokens, pin)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// UserExists returns whether or not a user with the given username exists.
|
// UserExists returns whether or not a user with the given username exists.
|
||||||
func (t *TelegramDaemon) UserExists(username string) (ok bool) {
|
func (t *TelegramDaemon) UserExists(username string) (ok bool) {
|
||||||
ok = false
|
ok = false
|
||||||
|
Loading…
Reference in New Issue
Block a user