Matrix/entities/event/eventDatabaseConnector.go
2020-10-17 12:07:39 +02:00

813 lines
15 KiB
Go

package event
import (
"fmt"
"git.nutfactory.org/hoernschen/Matrix/utils/database"
)
func CreateRoomMember(roomId string, userId string, server string) (err error) {
sqlStmt := fmt.Sprintf(`INSERT INTO roomMember
(roomId, userId, server)
VALUES
(?, ?, ?)`)
tx, err := database.DB.Begin()
if err != nil {
return
}
stmt, err := tx.Prepare(sqlStmt)
if err != nil {
return
}
defer stmt.Close()
_, err = stmt.Exec(roomId, userId, server)
if err != nil {
tx.Rollback()
return
}
tx.Commit()
return
}
func CreateParents(eventId string, parentIds map[string]EventHash) (err error) {
sqlStmt := fmt.Sprintf(`INSERT INTO parent
(eventId, parentId)
VALUES
(?, ?)`)
tx, err := database.DB.Begin()
if err != nil {
return
}
stmt, err := tx.Prepare(sqlStmt)
if err != nil {
return
}
defer stmt.Close()
for parentId, _ := range parentIds {
_, err = stmt.Exec(
eventId,
parentId,
)
if err != nil {
tx.Rollback()
return
}
}
tx.Commit()
return
}
func CreateAuthEvents(eventId string, authEventIds map[string]EventHash) (err error) {
sqlStmt := fmt.Sprintf(`INSERT INTO authEvent
(eventId, authEventId)
VALUES
(?, ?)`)
tx, err := database.DB.Begin()
if err != nil {
return
}
stmt, err := tx.Prepare(sqlStmt)
if err != nil {
return
}
defer stmt.Close()
for authEventId, _ := range authEventIds {
_, err = stmt.Exec(
eventId,
authEventId,
)
if err != nil {
tx.Rollback()
return
}
}
tx.Commit()
return
}
func CreateEvent(event *Event, txnId string) (err error) {
sqlStmt := fmt.Sprintf(`INSERT INTO event
(id, roomId, txnId, sender, origin, timestamp, eventType, stateKey, content, depth, hash, signature)
VALUES
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
tx, err := database.DB.Begin()
if err != nil {
return
}
stmt, err := tx.Prepare(sqlStmt)
if err != nil {
return
}
defer stmt.Close()
signatures := ""
for _, signature := range event.Signatures[event.Origin] {
signatures = signature
}
_, err = stmt.Exec(
event.Id,
event.RoomId,
txnId,
event.Sender,
event.Origin,
event.Timestamp,
event.EventType,
event.StateKey,
event.Content,
event.Depth,
event.Hashes.SHA256,
signatures,
)
if err != nil {
tx.Rollback()
return
}
tx.Commit()
err = CreateParents(event.Id, event.PrevEventHashes)
if err != nil {
return
}
err = CreateAuthEvents(event.Id, event.AuthEventHashes)
if err != nil {
return
}
return
}
func CreateEventsFromTransaction(txnId string, pdus map[string]*Event) (err error) {
sqlStmt := fmt.Sprintf(`INSERT INTO event
(id, roomId, txnId, sender, origin, timestamp, eventType, stateKey, content, depth, hash, signature)
VALUES
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
tx, err := database.DB.Begin()
if err != nil {
return
}
stmt, err := tx.Prepare(sqlStmt)
if err != nil {
return
}
defer stmt.Close()
for _, pdu := range pdus {
signatures := ""
for _, signature := range pdu.Signatures[pdu.Origin] {
signatures = signature
}
_, err = stmt.Exec(
pdu.Id,
pdu.RoomId,
txnId,
pdu.Sender,
pdu.Origin,
pdu.Timestamp,
pdu.EventType,
pdu.StateKey,
pdu.Content,
pdu.Depth,
pdu.Hashes.SHA256,
signatures,
)
if err != nil {
tx.Rollback()
return
}
err = CreateParents(pdu.Id, pdu.PrevEventHashes)
if err != nil {
return
}
err = CreateAuthEvents(pdu.Id, pdu.AuthEventHashes)
if err != nil {
return
}
}
tx.Commit()
return
}
func ReadEventHash(id string) (hash string, err error) {
queryStmt := fmt.Sprintf(`SELECT hash
FROM event
WHERE id = '%s'`, id)
rows, err := database.DB.Query(queryStmt)
if err != nil {
return
}
defer rows.Close()
if rows.Next() {
err = rows.Scan(hash)
if err != nil {
return
}
}
return
}
func ReadRoomMembers(roomId string) (roomMembers []string, err error) {
queryStmt := fmt.Sprintf(`SELECT userId
FROM roomMember
WHERE roomId = '%s'`, roomId)
rows, err := database.DB.Query(queryStmt)
if err != nil {
return
}
defer rows.Close()
roomMembers = []string{}
for rows.Next() {
var foundUser string
err = rows.Scan(&foundUser)
if err != nil {
return
}
roomMembers = append(roomMembers, foundUser)
}
return
}
func ReadServers(roomId string) (servers []string, err error) {
queryStmt := fmt.Sprintf(`SELECT DISTINCT server
FROM roomMember
WHERE roomId = '%s'`, roomId)
rows, err := database.DB.Query(queryStmt)
if err != nil {
return
}
defer rows.Close()
servers = []string{}
for rows.Next() {
var foundUser string
err = rows.Scan(&foundUser)
if err != nil {
return
}
servers = append(servers, foundUser)
}
return
}
func ReadParents(eventId string) (parents map[string]EventHash, err error) {
queryStmt := fmt.Sprintf(`SELECT e.id, e.hash
FROM event as e
join parent as p on e.id = p.parentId
WHERE p.eventId = '%s'`, eventId)
rows, err := database.DB.Query(queryStmt)
if err != nil {
return
}
defer rows.Close()
parents = make(map[string]EventHash)
for rows.Next() {
var eventId string
var foundEvent EventHash
err = rows.Scan(&eventId,
&foundEvent.SHA256,
)
if err != nil {
return
}
parents[eventId] = foundEvent
}
return
}
func ReadEventsWithoutChild(roomId string) (events map[string]EventHash, depth int, err error) {
queryStmt := fmt.Sprintf(`SELECT e.id, e.hash, e.depth
FROM event as e
LEFT JOIN parent as p on e.id = p.parentId
WHERE p.eventId IS NULL AND e.roomId = '%s'`, roomId)
rows, err := database.DB.Query(queryStmt)
if err != nil {
return
}
defer rows.Close()
events = make(map[string]EventHash)
for rows.Next() {
var eventId string
var foundEvent EventHash
var foundDepth int
err = rows.Scan(&eventId,
&foundEvent.SHA256,
&foundDepth,
)
if foundDepth > depth {
depth = foundDepth
}
if err != nil {
return
}
events[eventId] = foundEvent
}
return
}
func ReadAuthEvents(eventId string) (authEvents map[string]EventHash, err error) {
queryStmt := fmt.Sprintf(`SELECT e.id, e.hash
FROM event as e
join authEvent as a on e.id = a.authEventId
WHERE a.eventId = '%s'`, eventId)
rows, err := database.DB.Query(queryStmt)
if err != nil {
return
}
defer rows.Close()
authEvents = make(map[string]EventHash)
for rows.Next() {
var eventId string
var foundEvent EventHash
err = rows.Scan(&eventId,
&foundEvent.SHA256,
)
if err != nil {
return
}
authEvents[eventId] = foundEvent
}
return
}
func ReadEvent(id string) (foundEvent *Event, err error) {
queryStmt := fmt.Sprintf(`SELECT id, roomId, txnId, sender, origin, timestamp, eventType, stateKey, content, depth, hash, signature
FROM event
WHERE id = '%s'`, id)
rows, err := database.DB.Query(queryStmt)
if err != nil {
return
}
defer rows.Close()
if rows.Next() {
foundEvent = &Event{}
var signature string
err = rows.Scan(&foundEvent.Id,
&foundEvent.RoomId,
&foundEvent.Unsigned.TransactionId,
&foundEvent.Sender,
&foundEvent.Origin,
&foundEvent.Timestamp,
&foundEvent.EventType,
&foundEvent.StateKey,
&foundEvent.Content,
&foundEvent.Depth,
&foundEvent.Hashes.SHA256,
&signature,
)
foundEvent.Signatures = make(map[string]map[string]string)
foundEvent.Signatures[foundEvent.Origin] = make(map[string]string)
foundEvent.Signatures[foundEvent.Origin]["ed25519:1"] = signature
if err != nil {
return
}
foundEvent.PrevEventHashes, err = ReadParents(foundEvent.Id)
if err != nil {
return
}
foundEvent.AuthEventHashes, err = ReadAuthEvents(foundEvent.Id)
if err != nil {
return
}
}
return
}
func ReadStateEvent(roomId string, eventType string, stateKey string) (foundEvent *Event, err error) {
queryStmt := fmt.Sprintf(`SELECT id, roomId, txnId, sender, origin, timestamp, eventType, stateKey, content, depth, hash, signature
FROM event
WHERE roomId = '%s'
AND eventType = '%s'
AND stateKey = '%s'`, roomId, eventType, stateKey)
if stateKey == "" {
queryStmt = fmt.Sprintf(`SELECT id, roomId, txnId, sender, origin, timestamp, eventType, stateKey, content, depth, hash, signature
FROM event
WHERE roomId = '%s'
AND eventType = '%s'`, roomId, eventType)
}
rows, err := database.DB.Query(queryStmt)
if err != nil {
return
}
defer rows.Close()
if rows.Next() {
foundEvent = &Event{}
var signature string
err = rows.Scan(&foundEvent.Id,
&foundEvent.RoomId,
&foundEvent.Unsigned.TransactionId,
&foundEvent.Sender,
&foundEvent.Origin,
&foundEvent.Timestamp,
&foundEvent.EventType,
&foundEvent.StateKey,
&foundEvent.Content,
&foundEvent.Depth,
&foundEvent.Hashes.SHA256,
&signature,
)
foundEvent.Signatures = make(map[string]map[string]string)
foundEvent.Signatures[foundEvent.Origin] = make(map[string]string)
foundEvent.Signatures[foundEvent.Origin]["ed25519:1"] = signature
if err != nil {
return
}
foundEvent.PrevEventHashes, err = ReadParents(foundEvent.Id)
if err != nil {
return
}
foundEvent.AuthEventHashes, err = ReadAuthEvents(foundEvent.Id)
if err != nil {
return
}
}
return
}
func ReadStateEvents(roomId string, eventType string) (foundEvents []*Event, err error) {
queryStmt := fmt.Sprintf(`SELECT id, roomId, txnId, sender, origin, timestamp, eventType, stateKey, content, depth, hash, signature
FROM event
WHERE roomId = '%s'
AND eventType = '%s'`, roomId, eventType)
rows, err := database.DB.Query(queryStmt)
if err != nil {
return
}
defer rows.Close()
for rows.Next() {
foundEvent := &Event{}
var signature string
err = rows.Scan(&foundEvent.Id,
&foundEvent.RoomId,
&foundEvent.Unsigned.TransactionId,
&foundEvent.Sender,
&foundEvent.Origin,
&foundEvent.Timestamp,
&foundEvent.EventType,
&foundEvent.StateKey,
&foundEvent.Content,
&foundEvent.Depth,
&foundEvent.Hashes.SHA256,
&signature,
)
foundEvent.Signatures = make(map[string]map[string]string)
foundEvent.Signatures[foundEvent.Origin] = make(map[string]string)
foundEvent.Signatures[foundEvent.Origin]["ed25519:1"] = signature
if err != nil {
return
}
foundEvent.PrevEventHashes, err = ReadParents(foundEvent.Id)
if err != nil {
return
}
foundEvent.AuthEventHashes, err = ReadAuthEvents(foundEvent.Id)
if err != nil {
return
}
foundEvents = append(foundEvents, foundEvent)
}
return
}
func ReadEventsFromRoom(roomId string) (events map[string]*Event, err error) {
queryStmt := fmt.Sprintf(`SELECT id, roomId, txnId, sender, origin, timestamp, eventType, stateKey, content, depth, hash, signature
FROM event
WHERE roomId = '%s'`, roomId)
rows, err := database.DB.Query(queryStmt)
if err != nil {
return
}
defer rows.Close()
events = make(map[string]*Event)
for rows.Next() {
foundEvent := &Event{}
var signature string
err = rows.Scan(&foundEvent.Id,
&foundEvent.RoomId,
&foundEvent.Unsigned.TransactionId,
&foundEvent.Sender,
&foundEvent.Origin,
&foundEvent.Timestamp,
&foundEvent.EventType,
&foundEvent.StateKey,
&foundEvent.Content,
&foundEvent.Depth,
&foundEvent.Hashes.SHA256,
&signature,
)
foundEvent.Signatures = make(map[string]map[string]string)
foundEvent.Signatures[foundEvent.Origin] = make(map[string]string)
foundEvent.Signatures[foundEvent.Origin]["ed25519:1"] = signature
if err != nil {
return
}
foundEvent.PrevEventHashes, err = ReadParents(foundEvent.Id)
if err != nil {
return
}
foundEvent.AuthEventHashes, err = ReadAuthEvents(foundEvent.Id)
if err != nil {
return
}
events[foundEvent.Id] = foundEvent
}
return
}
func ReadStateEventsFromRoom(roomId string) (events []*Event, err error) {
queryStmt := fmt.Sprintf(`SELECT id, roomId, txnId, sender, origin, timestamp, eventType, stateKey, content, depth, hash, signature
FROM event
WHERE eventType <> 'm.room.message' AND roomId = '%s'`, roomId)
rows, err := database.DB.Query(queryStmt)
if err != nil {
return
}
defer rows.Close()
for rows.Next() {
foundEvent := &Event{}
var signature string
err = rows.Scan(&foundEvent.Id,
&foundEvent.RoomId,
&foundEvent.Unsigned.TransactionId,
&foundEvent.Sender,
&foundEvent.Origin,
&foundEvent.Timestamp,
&foundEvent.EventType,
&foundEvent.StateKey,
&foundEvent.Content,
&foundEvent.Depth,
&foundEvent.Hashes.SHA256,
&signature,
)
foundEvent.Signatures = make(map[string]map[string]string)
foundEvent.Signatures[foundEvent.Origin] = make(map[string]string)
foundEvent.Signatures[foundEvent.Origin]["ed25519:1"] = signature
if err != nil {
return
}
foundEvent.PrevEventHashes, err = ReadParents(foundEvent.Id)
if err != nil {
return
}
foundEvent.AuthEventHashes, err = ReadAuthEvents(foundEvent.Id)
if err != nil {
return
}
events = append(events, foundEvent)
}
return
}
func ReadEventsFromTransaction(txnId string) (events []*Event, err error) {
queryStmt := fmt.Sprintf(`SELECT id, roomId, txnId, sender, origin, timestamp, eventType, stateKey, content, depth, hash, signature
FROM event
WHERE txnId = '%s'`, txnId)
rows, err := database.DB.Query(queryStmt)
if err != nil {
return
}
defer rows.Close()
for rows.Next() {
foundEvent := &Event{}
var signature string
err = rows.Scan(&foundEvent.Id,
&foundEvent.RoomId,
&foundEvent.Unsigned.TransactionId,
&foundEvent.Sender,
&foundEvent.Origin,
&foundEvent.Timestamp,
&foundEvent.EventType,
&foundEvent.StateKey,
&foundEvent.Content,
&foundEvent.Depth,
&foundEvent.Hashes.SHA256,
&signature,
)
foundEvent.Signatures = make(map[string]map[string]string)
foundEvent.Signatures[foundEvent.Origin] = make(map[string]string)
foundEvent.Signatures[foundEvent.Origin]["ed25519:1"] = signature
if err != nil {
return
}
foundEvent.PrevEventHashes, err = ReadParents(foundEvent.Id)
if err != nil {
return
}
foundEvent.AuthEventHashes, err = ReadAuthEvents(foundEvent.Id)
if err != nil {
return
}
events = append(events, foundEvent)
}
return
}
func UpdateEvent(event *Event) (err error) {
sqlStmt := fmt.Sprintf(`UPDATE event SET
eventType = ?,
content = ?,
WHERE id = ?`)
tx, err := database.DB.Begin()
if err != nil {
return
}
stmt, err := tx.Prepare(sqlStmt)
if err != nil {
return
}
defer stmt.Close()
_, err = stmt.Exec(
event.EventType,
event.Content,
event.Id,
)
if err != nil {
tx.Rollback()
return
}
tx.Commit()
return
}
func DeleteEvent(id string) (err error) {
queryStmt := fmt.Sprintf(`DELETE FROM event
WHERE id = '%s'`, id)
tx, err := database.DB.Begin()
if err != nil {
return
}
_, err = tx.Exec(queryStmt)
if err != nil {
tx.Rollback()
return
}
err = DeleteParents(id)
if err != nil {
return
}
err = DeleteAuthEvents(id)
if err != nil {
return
}
tx.Commit()
return
}
func DeleteParents(eventId string) (err error) {
queryStmt := fmt.Sprintf(`DELETE FROM parent
WHERE eventId = '%s'`, eventId)
tx, err := database.DB.Begin()
if err != nil {
return
}
_, err = tx.Exec(queryStmt)
if err != nil {
tx.Rollback()
return
}
tx.Commit()
return
}
func DeleteAuthEvents(eventId string) (err error) {
queryStmt := fmt.Sprintf(`DELETE FROM authEvent
WHERE eventId = '%s'`, eventId)
tx, err := database.DB.Begin()
if err != nil {
return
}
_, err = tx.Exec(queryStmt)
if err != nil {
tx.Rollback()
return
}
tx.Commit()
return
}