mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-08-07 14:50:56 +00:00
Fix - non-logged-in needs a reply if auth needed
Refactor for testing - all janitors have sleep in a different function from the work, so tests can trigger them
This commit is contained in:
parent
4b2449aecf
commit
26747a1104
4 changed files with 104 additions and 79 deletions
|
@ -23,8 +23,8 @@ type CommandHandler func(*websocket.Conn, *ClientInfo, ClientMessage) (ClientMes
|
||||||
var commandHandlers = map[Command]CommandHandler{
|
var commandHandlers = map[Command]CommandHandler{
|
||||||
HelloCommand: C2SHello,
|
HelloCommand: C2SHello,
|
||||||
"ping": C2SPing,
|
"ping": C2SPing,
|
||||||
"setuser": C2SSetUser,
|
SetUserCommand: C2SSetUser,
|
||||||
"ready": C2SReady,
|
ReadyCommand: C2SReady,
|
||||||
|
|
||||||
"sub": C2SSubscribe,
|
"sub": C2SSubscribe,
|
||||||
"unsub": C2SUnsubscribe,
|
"unsub": C2SUnsubscribe,
|
||||||
|
@ -143,7 +143,6 @@ func C2SSetUser(conn *websocket.Conn, client *ClientInfo, msg ClientMessage) (rm
|
||||||
go client.StartAuthorization(func(_ *ClientInfo, _ bool) {
|
go client.StartAuthorization(func(_ *ClientInfo, _ bool) {
|
||||||
client.MsgChannelKeepalive.Done()
|
client.MsgChannelKeepalive.Done()
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResponseSuccess, nil
|
return ResponseSuccess, nil
|
||||||
|
@ -316,11 +315,11 @@ func C2SEmoticonUses(conn *websocket.Conn, client *ClientInfo, msg ClientMessage
|
||||||
func aggregateDataSender() {
|
func aggregateDataSender() {
|
||||||
for {
|
for {
|
||||||
time.Sleep(5 * time.Minute)
|
time.Sleep(5 * time.Minute)
|
||||||
doSendAggregateData()
|
aggregateDataSender_do()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func doSendAggregateData() {
|
func aggregateDataSender_do() {
|
||||||
followEventsLock.Lock()
|
followEventsLock.Lock()
|
||||||
follows := followEvents
|
follows := followEvents
|
||||||
followEvents = nil
|
followEvents = nil
|
||||||
|
@ -538,11 +537,18 @@ func C2SHandleRemoteCommand(conn *websocket.Conn, client *ClientInfo, msg Client
|
||||||
}
|
}
|
||||||
|
|
||||||
const AuthorizationFailedErrorString = "Failed to verify your Twitch username."
|
const AuthorizationFailedErrorString = "Failed to verify your Twitch username."
|
||||||
|
const AuthorizationNeededError = "You must be signed in to use that command."
|
||||||
|
|
||||||
func doRemoteCommand(conn *websocket.Conn, msg ClientMessage, client *ClientInfo) {
|
func doRemoteCommand(conn *websocket.Conn, msg ClientMessage, client *ClientInfo) {
|
||||||
resp, err := SendRemoteCommandCached(string(msg.Command), msg.origArguments, client.AuthInfo)
|
resp, err := SendRemoteCommandCached(string(msg.Command), msg.origArguments, client.AuthInfo)
|
||||||
|
|
||||||
if err == ErrAuthorizationNeeded {
|
if err == ErrAuthorizationNeeded {
|
||||||
|
if client.TwitchUsername == "" {
|
||||||
|
// Not logged in
|
||||||
|
client.MessageChannel <- ClientMessage{MessageID: msg.MessageID, Command: ErrorCommand, Arguments: AuthorizationNeededError}
|
||||||
|
client.MsgChannelKeepalive.Done()
|
||||||
|
return
|
||||||
|
}
|
||||||
client.StartAuthorization(func(_ *ClientInfo, success bool) {
|
client.StartAuthorization(func(_ *ClientInfo, success bool) {
|
||||||
if success {
|
if success {
|
||||||
doRemoteCommand(conn, msg, client)
|
doRemoteCommand(conn, msg, client)
|
||||||
|
|
|
@ -34,6 +34,12 @@ const ErrorCommand Command = "error"
|
||||||
// Sending any other command will result in a CloseFirstMessageNotHello.
|
// Sending any other command will result in a CloseFirstMessageNotHello.
|
||||||
const HelloCommand Command = "hello"
|
const HelloCommand Command = "hello"
|
||||||
|
|
||||||
|
// ReadyCommand is a C2S Command.
|
||||||
|
// It indicates that the client is finished sending the initial 'sub' commands and the server should send the backlog.
|
||||||
|
const ReadyCommand Command = "ready"
|
||||||
|
|
||||||
|
const SetUserCommand Command = "set_user"
|
||||||
|
|
||||||
// AuthorizeCommand is a S2C Command sent as part of Twitch username validation.
|
// AuthorizeCommand is a S2C Command sent as part of Twitch username validation.
|
||||||
const AuthorizeCommand Command = "do_authorize"
|
const AuthorizeCommand Command = "do_authorize"
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
"errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AuthCallback func(client *ClientInfo, successful bool)
|
type AuthCallback func(client *ClientInfo, successful bool)
|
||||||
|
@ -39,8 +40,11 @@ func AddPendingAuthorization(client *ClientInfo, challenge string, callback Auth
|
||||||
func authorizationJanitor() {
|
func authorizationJanitor() {
|
||||||
for {
|
for {
|
||||||
time.Sleep(5 * time.Minute)
|
time.Sleep(5 * time.Minute)
|
||||||
|
authorizationJanitor_do()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func() {
|
func authorizationJanitor_do() {
|
||||||
cullTime := time.Now().Add(-30 * time.Minute)
|
cullTime := time.Now().Add(-30 * time.Minute)
|
||||||
|
|
||||||
PendingAuthLock.Lock()
|
PendingAuthLock.Lock()
|
||||||
|
@ -51,16 +55,16 @@ func authorizationJanitor() {
|
||||||
for _, v := range PendingAuths {
|
for _, v := range PendingAuths {
|
||||||
if !cullTime.After(v.EnteredAt) {
|
if !cullTime.After(v.EnteredAt) {
|
||||||
newPendingAuths = append(newPendingAuths, v)
|
newPendingAuths = append(newPendingAuths, v)
|
||||||
|
} else {
|
||||||
|
v.Callback(v.Client, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PendingAuths = newPendingAuths
|
PendingAuths = newPendingAuths
|
||||||
}()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *ClientInfo) StartAuthorization(callback AuthCallback) {
|
func (client *ClientInfo) StartAuthorization(callback AuthCallback) {
|
||||||
fmt.Println(DEBUG, "startig auth for user", client.TwitchUsername, client.RemoteAddr)
|
fmt.Println(DEBUG, "starting auth for user", client.TwitchUsername, client.RemoteAddr)
|
||||||
var nonce [32]byte
|
var nonce [32]byte
|
||||||
_, err := rand.Read(nonce[:])
|
_, err := rand.Read(nonce[:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -88,6 +92,8 @@ const AuthCommand = "AUTH"
|
||||||
|
|
||||||
const DEBUG = "DEBUG"
|
const DEBUG = "DEBUG"
|
||||||
|
|
||||||
|
var errChallengeNotFound = errors.New("did not find a challenge solved by that message")
|
||||||
|
|
||||||
func ircConnection() {
|
func ircConnection() {
|
||||||
|
|
||||||
c := irc.SimpleClient("justinfan123")
|
c := irc.SimpleClient("justinfan123")
|
||||||
|
@ -113,12 +119,23 @@ func ircConnection() {
|
||||||
submittedUser := line.Nick
|
submittedUser := line.Nick
|
||||||
submittedChallenge := msgArray[1]
|
submittedChallenge := msgArray[1]
|
||||||
|
|
||||||
|
submitAuth(submittedUser, submittedChallenge)
|
||||||
|
})
|
||||||
|
|
||||||
|
err := c.ConnectTo("irc.twitch.tv")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("Cannot connect to IRC:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func submitAuth(user, challenge string) error {
|
||||||
var auth PendingAuthorization
|
var auth PendingAuthorization
|
||||||
var idx int = -1
|
var idx int = -1
|
||||||
|
|
||||||
PendingAuthLock.Lock()
|
PendingAuthLock.Lock()
|
||||||
for i, v := range PendingAuths {
|
for i, v := range PendingAuths {
|
||||||
if v.Client.TwitchUsername == submittedUser && v.Challenge == submittedChallenge {
|
if v.Client.TwitchUsername == user && v.Challenge == challenge {
|
||||||
auth = v
|
auth = v
|
||||||
idx = i
|
idx = i
|
||||||
break
|
break
|
||||||
|
@ -130,8 +147,7 @@ func ircConnection() {
|
||||||
PendingAuthLock.Unlock()
|
PendingAuthLock.Unlock()
|
||||||
|
|
||||||
if idx == -1 {
|
if idx == -1 {
|
||||||
fmt.Println(DEBUG, "discarded msg - challenge not found", line.Raw)
|
return errChallengeNotFound // perhaps it was for another socket server
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// auth is valid, and removed from pending list
|
// auth is valid, and removed from pending list
|
||||||
|
@ -139,7 +155,7 @@ func ircConnection() {
|
||||||
fmt.Println(DEBUG, "authorization success for user", auth.Client.TwitchUsername)
|
fmt.Println(DEBUG, "authorization success for user", auth.Client.TwitchUsername)
|
||||||
var usernameChanged bool
|
var usernameChanged bool
|
||||||
auth.Client.Mutex.Lock()
|
auth.Client.Mutex.Lock()
|
||||||
if auth.Client.TwitchUsername == submittedUser { // recheck condition
|
if auth.Client.TwitchUsername == user { // recheck condition
|
||||||
auth.Client.UsernameValidated = true
|
auth.Client.UsernameValidated = true
|
||||||
} else {
|
} else {
|
||||||
usernameChanged = true
|
usernameChanged = true
|
||||||
|
@ -153,11 +169,4 @@ func ircConnection() {
|
||||||
auth.Callback(auth.Client, false)
|
auth.Callback(auth.Client, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
|
||||||
err := c.ConnectTo("irc.twitch.tv")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalln("Cannot connect to IRC:", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -149,6 +149,11 @@ const ReapingDelay = 1 * time.Minute
|
||||||
func pubsubJanitor() {
|
func pubsubJanitor() {
|
||||||
for {
|
for {
|
||||||
time.Sleep(ReapingDelay)
|
time.Sleep(ReapingDelay)
|
||||||
|
pubsubJanitor_do()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func pubsubJanitor_do() {
|
||||||
var cleanedUp = make([]string, 0, 6)
|
var cleanedUp = make([]string, 0, 6)
|
||||||
ChatSubscriptionLock.Lock()
|
ChatSubscriptionLock.Lock()
|
||||||
for key, val := range ChatSubscriptionInfo {
|
for key, val := range ChatSubscriptionInfo {
|
||||||
|
@ -165,7 +170,6 @@ func pubsubJanitor() {
|
||||||
log.Println("error reporting cleaned subs:", err)
|
log.Println("error reporting cleaned subs:", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a channel to the subscriptions while holding a read-lock to the map.
|
// Add a channel to the subscriptions while holding a read-lock to the map.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue