This commit is contained in:
Alex 2020-02-26 21:36:35 +01:00
parent f675ba57e4
commit 775fc7b217
4 changed files with 101 additions and 92 deletions

View File

@ -2,6 +2,7 @@ package main
import (
"fmt"
"reflect"
"strings"
"sync"
@ -15,22 +16,63 @@ type Account struct {
AccountName string
Protocol string
Config map[string]string
Conn Connector
Conn Connector
JoinedRooms map[RoomID]bool
}
var accountsLock sync.Mutex
var registeredAccounts = map[string]map[string]*Account{}
func AddAccount(a *Account) {
func SetAccount(mxid string, name string, protocol string, config map[string]string) error {
accountsLock.Lock()
defer accountsLock.Unlock()
if _, ok := registeredAccounts[a.MatrixUser]; !ok {
registeredAccounts[a.MatrixUser] = make(map[string]*Account)
if _, ok := registeredAccounts[mxid]; !ok {
registeredAccounts[mxid] = make(map[string]*Account)
}
registeredAccounts[a.MatrixUser][a.AccountName] = a
accounts := registeredAccounts[mxid]
if prev_acct, ok := accounts[name]; ok {
if protocol != prev_acct.Protocol {
return fmt.Errorf("Wrong protocol")
}
if !reflect.DeepEqual(config, prev_acct.Config) {
prev_acct.Config = config
go prev_acct.connect()
}
} else {
conn := createConnector(protocol)
if conn == nil {
return fmt.Errorf("Could not create connector for protocol %s", protocol)
}
account := &Account{
MatrixUser: mxid,
AccountName: name,
Protocol: protocol,
Config: config,
Conn: conn,
JoinedRooms: map[RoomID]bool{},
}
conn.SetHandler(account)
accounts[name] = account
go account.connect()
}
return nil
}
func ListAccounts(mxUser string) []*Account {
accountsLock.Lock()
defer accountsLock.Unlock()
ret := []*Account{}
if accts, ok := registeredAccounts[mxUser]; ok {
for _, acct := range accts {
ret = append(ret, acct)
}
}
return ret
}
func FindAccount(mxUser string, name string) *Account {
@ -70,6 +112,24 @@ func RemoveAccount(mxUser string, name string) {
}
}
func SaveDbAccounts(mxid string, key *[32]byte) {
accountsLock.Lock()
defer accountsLock.Unlock()
if accounts, ok := registeredAccounts[mxid]; ok {
for name, acct := range accounts {
var entry DbAccountConfig
db.Where(&DbAccountConfig{
MxUserID: mxid,
Name: name,
}).Assign(&DbAccountConfig{
Protocol: acct.Protocol,
Config: encryptAccountConfig(acct.Config, key),
}).FirstOrCreate(&entry)
}
}
}
// ----
func (a *Account) ezbrMessagef(format string, args ...interface{}) {
@ -78,10 +138,10 @@ func (a *Account) ezbrMessagef(format string, args ...interface{}) {
ezbrSystemSend(a.MatrixUser, msg)
}
func (a *Account) connect(config map[string]string) {
func (a *Account) connect() {
ezbrSystemSendf(a.MatrixUser, "Connecting to account %s (%s)", a.AccountName, a.Protocol)
err := a.Conn.Configure(config)
err := a.Conn.Configure(a.Config)
if err != nil {
ezbrSystemSendf(a.MatrixUser, "%s (%s) cannot connect: %s", a.AccountName, a.Protocol, err.Error())
return

34
main.go
View File

@ -15,10 +15,6 @@ import (
log "github.com/sirupsen/logrus"
"gopkg.in/yaml.v2"
"git.deuxfleurs.fr/Deuxfleurs/easybridge/connector"
"git.deuxfleurs.fr/Deuxfleurs/easybridge/connector/irc"
"git.deuxfleurs.fr/Deuxfleurs/easybridge/connector/mattermost"
"git.deuxfleurs.fr/Deuxfleurs/easybridge/connector/xmpp"
"git.deuxfleurs.fr/Deuxfleurs/easybridge/mxlib"
)
@ -174,22 +170,9 @@ func main() {
StartWeb()
for user, accounts := range config.Accounts {
mxid := fmt.Sprintf("@%s:%s", user, config.MatrixDomain)
for name, params := range accounts {
conn := createConnector(params.Protocol)
if conn == nil {
log.Fatalf("Could not create connector for protocol %s", params.Protocol)
}
account := &Account{
MatrixUser: fmt.Sprintf("@%s:%s", user, config.MatrixDomain),
AccountName: name,
Protocol: params.Protocol,
Config: params.Config,
Conn: conn,
JoinedRooms: map[connector.RoomID]bool{},
}
conn.SetHandler(account)
AddAccount(account)
go account.connect(params.Config)
SetAccount(mxid, name, params.Protocol, params.Config)
}
}
@ -198,16 +181,3 @@ func main() {
log.Fatal(err)
}
}
func createConnector(protocol string) connector.Connector {
switch protocol {
case "irc":
return &irc.IRC{}
case "xmpp":
return &xmpp.XMPP{}
case "mattermost":
return &mattermost.Mattermost{}
default:
return nil
}
}

18
util.go
View File

@ -11,6 +11,9 @@ import (
"golang.org/x/crypto/nacl/secretbox"
. "git.deuxfleurs.fr/Deuxfleurs/easybridge/connector"
"git.deuxfleurs.fr/Deuxfleurs/easybridge/connector/irc"
"git.deuxfleurs.fr/Deuxfleurs/easybridge/connector/mattermost"
"git.deuxfleurs.fr/Deuxfleurs/easybridge/connector/xmpp"
)
const EASYBRIDGE_SYSTEM_PROTOCOL string = "✯◡✯"
@ -98,3 +101,18 @@ func decryptAccountConfig(data string, key *[32]byte) (map[string]string, error)
err = json.Unmarshal(decoded, &config)
return config, err
}
// ----
func createConnector(protocol string) Connector {
switch protocol {
case "irc":
return &irc.IRC{}
case "xmpp":
return &xmpp.XMPP{}
case "mattermost":
return &mattermost.Mattermost{}
default:
return nil
}
}

67
web.go
View File

@ -11,7 +11,6 @@ import (
"github.com/gorilla/sessions"
"golang.org/x/crypto/argon2"
"git.deuxfleurs.fr/Deuxfleurs/easybridge/connector"
"git.deuxfleurs.fr/Deuxfleurs/easybridge/mxlib"
)
@ -81,7 +80,7 @@ func checkLogin(w http.ResponseWriter, r *http.Request) *LoginInfo {
type HomeData struct {
Login *LoginInfo
Accounts map[string]*Account
Accounts []*Account
}
func handleHome(w http.ResponseWriter, r *http.Request) {
@ -92,11 +91,9 @@ func handleHome(w http.ResponseWriter, r *http.Request) {
return
}
accountsLock.Lock()
defer accountsLock.Unlock()
templateHome.Execute(w, &HomeData{
Login: login,
Accounts: registeredAccounts[login.MxId],
Accounts: ListAccounts(login.MxId),
})
}
@ -154,7 +151,9 @@ func handleLogin(w http.ResponseWriter, r *http.Request) *LoginInfo {
key_slice := argon2.IDKey([]byte(password), []byte("EZBRIDGE account store"), 3, 64*1024, 4, 32)
copy(key[:], key_slice[:])
userKeys[mxid] = key
syncDbAccounts(mxid, key)
SaveDbAccounts(mxid, key)
LoadDbAccounts(mxid, key)
// Successfully logged in, save it to session
session, err := sessionsStore.Get(r, SESSION_NAME)
@ -179,57 +178,19 @@ func handleLogin(w http.ResponseWriter, r *http.Request) *LoginInfo {
}
}
func syncDbAccounts(mxid string, key *[32]byte) {
accountsLock.Lock()
defer accountsLock.Unlock()
// 1. Save all accounts that we have
var accounts map[string]*Account
if accts, ok := registeredAccounts[mxid]; ok {
accounts = accts
for name, acct := range accts {
var entry DbAccountConfig
db.Where(&DbAccountConfig{
MxUserID: mxid,
Name: name,
}).Assign(&DbAccountConfig{
Protocol: acct.Protocol,
Config: encryptAccountConfig(acct.Config, key),
}).FirstOrCreate(&entry)
}
} else {
accounts = make(map[string]*Account)
registeredAccounts[mxid] = accounts
}
// 2. Load and start missing accounts
func LoadDbAccounts(mxid string, key *[32]byte) {
var allAccounts []DbAccountConfig
db.Where(&DbAccountConfig{MxUserID: mxid}).Find(&allAccounts)
for _, acct := range allAccounts {
if _, ok := accounts[acct.Name]; !ok {
config, err := decryptAccountConfig(acct.Config, key)
if err != nil {
ezbrSystemSendf("Could not decrypt stored configuration for account %s", acct.Name)
continue
}
conn := createConnector(acct.Protocol)
if conn == nil {
ezbrSystemSendf("Could not create connector for protocol %s", acct.Protocol)
continue
}
account := &Account{
MatrixUser: mxid,
AccountName: acct.Name,
Protocol: acct.Protocol,
Config: config,
Conn: conn,
JoinedRooms: map[connector.RoomID]bool{},
}
conn.SetHandler(account)
config, err := decryptAccountConfig(acct.Config, key)
if err != nil {
ezbrSystemSendf("Could not decrypt stored configuration for account %s", acct.Name)
continue
}
accounts[acct.Name] = account
go account.connect(config)
err = SetAccount(mxid, acct.Name, acct.Protocol, config)
if err != nil {
ezbrSystemSendf("Could not setup account %s: %s", acct.Name, err.Error())
}
}
}