This commit is contained in:
hoernschen 2020-10-11 23:11:30 +02:00
parent 7db9c374cc
commit 9eac960763
26 changed files with 3119 additions and 266 deletions

View file

@ -1,13 +1,114 @@
package room
import (
"nutfactory.org/Matrix/entities/event"
)
import "nutfactory.org/Matrix/entities/event"
type Room struct {
Id string `json:"id,omitempty"`
Messages map[string]*event.Event `json:"messages,omitempty"`
//State map[string]event.Event `json:"state,omitempty"`
Members []string `json:"members,omitempty"`
Version string `json:"version,omitempty"`
Id string `json:"id,omitempty"`
Version string `json:"version,omitempty"`
Name string `json:"name,omitempty"`
Topic string `json:"topic,omitempty"`
Members []string `json:"members,omitempty"`
Servers []string
Events map[string]*event.Event `json:"events,omitempty"`
Visibility string `json:"visibility,omitempty"`
IsDirect bool `json:"is_direct,omitempty"`
Federated bool `json:"federated,omitempty"`
}
type createRoomRequest struct {
Visibility string `json:"visibility,omitempty"`
RoomAliasName string `json:"room_alias_name,omitempty"`
Name string `json:"name,omitempty"`
Topic string `json:"topic,omitempty"`
Invite string `json:"invite,omitempty"`
Invite3pid invite3pid `json:"invite_3pid,omitempty"`
RoomVersion string `json:"room_version,omitempty"`
CreationContent creationContent `json:"creation_content,omitempty"`
InitialState []event.StateEvent `json:"initial_state,omitempty"`
Preset string `json:"preset,omitempty"`
IsDirect bool `json:"is_direct,omitempty"`
PowerLevelContentOverride string `json:"power_level_content_override,omitempty"`
}
type createRoomResponse struct {
RoomId string `json:"room_id,omitempty"`
}
type getRoomMemberRequest struct{}
type getRoomMemberResponse struct {
Chunk []*event.Event `json:"chunk,omitempty"`
}
type joinRoomUserRequest struct {
ThirdPartySigned thirdPartySigned `json:"third_party_signed,omitempty"`
}
type joinRoomUserResponse struct {
RoomId string `json:"room_id,omitempty"`
}
type leaveRoomUserRequest struct{}
type leaveRoomUserResponse struct{}
type makeJoinRequest struct{}
type makeJoinResponse struct {
RoomVersion string `json:"room_version,omitempty"`
Event event.Event `json:"event,omitempty"`
}
type joinRoomServerRequest struct {
Sender string `json:"sender,omitempty"`
Origin string `json:"origin,omitempty"`
Timestamp int64 `json:"origin_server_ts,omitempty"`
EventType string `json:"type,omitempty"`
StateKey string `json:"state_key,omitempty"`
Content event.MemberEventContent `json:"content,omitempty"`
}
type joinRoomServerResponse struct {
Origin string `json:"origin,omitempty"`
AuthChain []*event.Event `json:"auth_chain,omitempty"`
State []*event.Event `json:"state,omitempty"`
}
type makeLeaveRequest struct{}
type makeLeaveResponse struct{}
type leaveRoomServerRequest struct{}
type leaveRoomServerResponse struct{}
type invite3pid struct {
IdServer string `json:"id_server,omitempty"`
IdAccessToken string `json:"id_access_token,omitempty"`
Medium string `json:"medium,omitempty"`
Address string `json:"address,omitempty"`
}
type creationContent struct {
Federated bool `json:"m.federate,omitempty"`
}
type unsignedData struct {
Age int `json:"age,omitempty"`
RedactedBecause *event.Event `json:"redacted_because,omitempty"`
TransactionId string `json:"transaction_id,omitempty"`
}
type invite struct {
DisplayName string `json:"display_name,omitempty"`
Signed thirdPartySigned `json:"signed,omitempty"`
}
type thirdPartySigned struct {
Sender string `json:"sender,omitempty"`
MXID string `json:"mxid,omitempty"`
Signatures signatures `json:"signatures,omitempty"`
Token string `json:"token,omitempty"`
}
type signatures struct{}

View file

@ -1,5 +1,770 @@
package room
func New() (room *Room) {
import (
"bytes"
"encoding/json"
"fmt"
"log"
"net/http"
"strings"
"time"
"github.com/cenkalti/backoff/v4"
"github.com/gorilla/mux"
"nutfactory.org/Matrix/config"
"nutfactory.org/Matrix/entities/event"
"nutfactory.org/Matrix/entities/user"
"nutfactory.org/Matrix/utils"
)
func New(
version string,
name string,
topic string,
visibility string,
isDirect bool,
federated bool,
creatorId string,
) (err error, newRoom *Room) {
err, roomId := utils.CreateUUID()
if err != nil {
return
}
id := generateRoomId(roomId)
newRoom = &Room{
Id: id,
Version: version,
Name: name,
Topic: topic,
Members: []string{creatorId},
Events: make(map[string]*event.Event),
Visibility: visibility,
IsDirect: isDirect,
Federated: federated,
}
return
}
func CreateRoomHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
request := createRoomRequest{}
errResponse := utils.CheckRequest(r)
if errResponse != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(errResponse); err != nil {
panic(err)
}
return
}
token, errResponse := utils.GetAccessToken(r)
if errResponse != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(errResponse); err != nil {
panic(err)
}
return
}
foundUser, err := user.ReadUserFromAccessToken(token)
if err != nil || foundUser == nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorCode: "M_UNKNOWN_TOKEN", ErrorMessage: fmt.Sprintf("%s", err)}); err != nil {
panic(err)
}
return
}
decoder := json.NewDecoder(r.Body)
err = decoder.Decode(&request)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Could not parse JSON: %s", err)}); err != nil {
panic(err)
}
return
}
err, newRoom := New(
request.RoomVersion,
request.Name,
request.Topic,
request.Visibility,
request.IsDirect,
request.CreationContent.Federated,
foundUser.Id,
)
err = CreateRoom(newRoom)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Database Error: %s", err)}); err != nil {
panic(err)
}
return
}
createEventContent := event.CreateEventContent{
Creator: foundUser.Id,
Federated: request.CreationContent.Federated,
RoomVersion: newRoom.Version,
}
createEventContentBytes, _ := json.Marshal(createEventContent)
err, createEvent := event.New(
newRoom.Id,
foundUser.Id,
config.Homeserver,
time.Now().Unix(),
"m.room.create",
"",
string(createEventContentBytes),
"",
)
if err == nil {
err = event.CreateEvent(createEvent, "")
}
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Error Event-Creation: %s", err)}); err != nil {
panic(err)
}
return
}
memberEventContent := event.MemberEventContent{
DisplayName: foundUser.Name,
IsDirect: request.IsDirect,
Membership: "join",
}
memberEventContentBytes, _ := json.Marshal(memberEventContent)
err, memberEvent := event.New(
newRoom.Id,
foundUser.Id,
config.Homeserver,
time.Now().Unix(),
"m.room.member",
foundUser.Id,
string(memberEventContentBytes),
"",
)
if err == nil {
err = event.CreateEvent(memberEvent, "")
}
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Error Event-Creation: %s", err)}); err != nil {
panic(err)
}
return
}
userPowerLevel := make(map[string]int)
userPowerLevel[foundUser.Id] = 100
powerLevelEventContent := event.PowerLevelsEventContent{
Ban: 50,
EventsDefault: 0,
Invite: 50,
Kick: 50,
Redact: 50,
StateDefault: 50,
Users: userPowerLevel,
UsersDefault: 0,
Notifications: event.Notifications{
Room: 50,
},
}
powerLevelEventContentBytes, _ := json.Marshal(powerLevelEventContent)
err, powerLevelEvent := event.New(
newRoom.Id,
foundUser.Id,
config.Homeserver,
time.Now().Unix(),
"m.room.power_levels",
"",
string(powerLevelEventContentBytes),
"",
)
if err == nil {
err = event.CreateEvent(powerLevelEvent, "")
}
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Error Event-Creation: %s", err)}); err != nil {
panic(err)
}
return
}
joinRule := "invite"
historyVisibilty := "shared"
guestAccess := "can_join"
if request.Preset == "public_chat" {
joinRule = "public"
guestAccess = "forbidden"
}
joinRuleEventContent := event.JoinRuleEventContent{
JoinRule: joinRule,
}
joinRuleEventContentBytes, _ := json.Marshal(joinRuleEventContent)
err, joinRulesEvent := event.New(
newRoom.Id,
foundUser.Id,
config.Homeserver,
time.Now().Unix(),
"m.room.join_rules",
"",
string(joinRuleEventContentBytes),
"",
)
if err == nil {
err = event.CreateEvent(joinRulesEvent, "")
}
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Error Event-Creation: %s", err)}); err != nil {
panic(err)
}
return
}
historyVisiblilityEventContent := event.HistoryVisibilityEventContent{
HistoryVisibility: historyVisibilty,
}
historyVisiblilityContentBytes, _ := json.Marshal(historyVisiblilityEventContent)
err, historyVisibilityEvent := event.New(
newRoom.Id,
foundUser.Id,
config.Homeserver,
time.Now().Unix(),
"m.room.history_visibility",
"",
string(historyVisiblilityContentBytes),
"",
)
if err == nil {
err = event.CreateEvent(historyVisibilityEvent, "")
}
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Error Event-Creation: %s", err)}); err != nil {
panic(err)
}
return
}
guestAccessEventContent := event.GuestAccessEventContent{
GuestAccess: guestAccess,
}
guestAccessContentBytes, _ := json.Marshal(guestAccessEventContent)
err, guestAccessEvent := event.New(
newRoom.Id,
foundUser.Id,
config.Homeserver,
time.Now().Unix(),
"m.room.guest_access",
"",
string(guestAccessContentBytes),
"",
)
if err == nil {
err = event.CreateEvent(guestAccessEvent, "")
}
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Error Event-Creation: %s", err)}); err != nil {
panic(err)
}
return
}
nameEventContent := event.NameEventContent{
Name: newRoom.Name,
}
nameContentBytes, _ := json.Marshal(nameEventContent)
err, nameEvent := event.New(
newRoom.Id,
foundUser.Id,
config.Homeserver,
time.Now().Unix(),
"m.room.name",
"",
string(nameContentBytes),
"",
)
if err == nil {
err = event.CreateEvent(nameEvent, "")
}
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Error Event-Creation: %s", err)}); err != nil {
panic(err)
}
return
}
topicEventContent := event.TopicEventContent{
Topic: newRoom.Topic,
}
topicContentBytes, _ := json.Marshal(topicEventContent)
err, topicEvent := event.New(
newRoom.Id,
foundUser.Id,
config.Homeserver,
time.Now().Unix(),
"m.room.topic",
"",
string(topicContentBytes),
"",
)
if err == nil {
err = event.CreateEvent(topicEvent, "")
}
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Error Event-Creation: %s", err)}); err != nil {
panic(err)
}
return
}
response := createRoomResponse{RoomId: newRoom.Id}
w.WriteHeader(http.StatusOK)
if err := json.NewEncoder(w).Encode(response); err != nil {
panic(err)
}
}
func GetRoomMemberHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
request := getRoomMemberRequest{}
errResponse := utils.CheckRequest(r)
if errResponse != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(errResponse); err != nil {
panic(err)
}
return
}
token, errResponse := utils.GetAccessToken(r)
if errResponse != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(errResponse); err != nil {
panic(err)
}
return
}
foundUser, err := user.ReadUserFromAccessToken(token)
if err != nil || foundUser == nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorCode: "M_UNKNOWN_TOKEN", ErrorMessage: fmt.Sprintf("%s", err)}); err != nil {
panic(err)
}
return
}
decoder := json.NewDecoder(r.Body)
err = decoder.Decode(&request)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Could not parse JSON: %s", err)}); err != nil {
panic(err)
}
return
}
vars := mux.Vars(r)
roomId := vars["roomId"]
if roomId == "" {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: "Missing Params"}); err != nil {
panic(err)
}
return
}
event.ReadStateEvents(roomId, "m.room.member")
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode("Not Implemented"); err != nil {
panic(err)
}
}
func JoinRoomUserHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
request := joinRoomUserRequest{}
errResponse := utils.CheckRequest(r)
if errResponse != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(errResponse); err != nil {
panic(err)
}
return
}
token, errResponse := utils.GetAccessToken(r)
if errResponse != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(errResponse); err != nil {
panic(err)
}
return
}
foundUser, err := user.ReadUserFromAccessToken(token)
if err != nil || foundUser == nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorCode: "M_UNKNOWN_TOKEN", ErrorMessage: fmt.Sprintf("%s", err)}); err != nil {
panic(err)
}
return
}
decoder := json.NewDecoder(r.Body)
err = decoder.Decode(&request)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Could not parse JSON: %s", err)}); err != nil {
panic(err)
}
return
}
vars := mux.Vars(r)
roomId := vars["roomId"]
if roomId == "" {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: "Missing Parameter"}); err != nil {
panic(err)
}
return
}
foundRoom, err := ReadRoom(roomId)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Database Error: %s", err)}); err != nil {
panic(err)
}
return
}
var joinEvent *event.Event
if foundRoom == nil {
memberEventContent := event.MemberEventContent{
DisplayName: foundUser.Name,
IsDirect: true,
Membership: "join",
}
memberEventContentBytes, _ := json.Marshal(memberEventContent)
err, memberEvent := event.New(
roomId,
foundUser.Id,
config.Homeserver,
time.Now().Unix(),
"m.room.member",
foundUser.Id,
string(memberEventContentBytes),
"",
)
if err == nil {
err = event.CreateEvent(memberEvent, "")
}
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Error Event-Creation: %s", err)}); err != nil {
panic(err)
}
return
}
httpString := "https"
server := strings.Split(roomId, ":")[1]
requestUrl := fmt.Sprintf("%s://%s/_matrix/federation/v1/make_join/%s/%s", httpString, server, roomId, foundUser.Id)
res, err := http.Get(requestUrl)
makeJoinRes := makeJoinResponse{}
decoder = json.NewDecoder(res.Body)
err = decoder.Decode(&makeJoinRes)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Could not parse JSON: %s", err)}); err != nil {
panic(err)
}
return
}
err = CreateRoom(&Room{Id: roomId, Version: makeJoinRes.RoomVersion})
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Database Error: %s", err)}); err != nil {
panic(err)
}
return
}
err, joinEvent = event.New(
roomId,
makeJoinRes.Event.Sender,
makeJoinRes.Event.Origin,
makeJoinRes.Event.Timestamp,
makeJoinRes.Event.EventType,
makeJoinRes.Event.StateKey,
makeJoinRes.Event.Content,
"",
)
requestUrl = fmt.Sprintf("%s://%s/_matrix/federation/v2/send_join/%s/%s", httpString, server, roomId, joinEvent.Id)
reqBody, err := json.Marshal(joinEvent)
if err != nil {
return
}
client := &http.Client{}
req, err := http.NewRequest(http.MethodPut, requestUrl, bytes.NewBuffer(reqBody))
if err != nil {
return
}
res, err = client.Do(req)
joinRes := joinRoomServerResponse{}
decoder = json.NewDecoder(res.Body)
err = decoder.Decode(&joinRes)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Could not parse JSON: %s", err)}); err != nil {
panic(err)
}
return
}
err = event.HandleEvents(joinRes.State)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Error Handling Events: %s", err)}); err != nil {
panic(err)
}
return
}
} else {
memberEventContent := event.MemberEventContent{
DisplayName: foundUser.Name,
IsDirect: true,
Membership: "join",
}
memberEventContentBytes, _ := json.Marshal(memberEventContent)
err, joinEvent = event.New(
roomId,
foundUser.Id,
config.Homeserver,
time.Now().Unix(),
"m.room.member",
foundUser.Id,
string(memberEventContentBytes),
"",
)
}
err, txnId := utils.CreateUUID()
err = event.CreateEvent(joinEvent, txnId)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Database Error: %s", err)}); err != nil {
panic(err)
}
return
}
transaction := &event.Transaction{
Id: txnId,
Origin: config.Homeserver,
Timestamp: time.Now().Unix(),
PDUS: []*event.Event{joinEvent},
}
servers, err := event.ReadServers(roomId)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Database Error: %s", err)}); err != nil {
panic(err)
}
return
}
for _, server := range servers {
//if server != config.Homeserver {
operation := func() error {
return event.SendTransaction(transaction, server)
}
notify := func(err error, duration time.Duration) {
log.Printf("Error Sending Transaction, retrying in %ss: %s", duration/1000000000, err)
}
go backoff.RetryNotify(operation, backoff.NewExponentialBackOff(), notify)
//}
}
err = CreateRoomMember(roomId, foundUser.Id)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Database Error: %s", err)}); err != nil {
panic(err)
}
return
}
response := joinRoomUserResponse{RoomId: roomId}
w.WriteHeader(http.StatusOK)
if err := json.NewEncoder(w).Encode(response); err != nil {
panic(err)
}
}
func GetPrepInfoToJoinHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
request := makeJoinRequest{}
errResponse := utils.CheckRequest(r)
if errResponse != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(errResponse); err != nil {
panic(err)
}
return
}
decoder := json.NewDecoder(r.Body)
err := decoder.Decode(&request)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Could not parse JSON: %s", err)}); err != nil {
panic(err)
}
return
}
vars := mux.Vars(r)
roomId := vars["roomId"]
userId := vars["userId"]
if roomId == "" || userId == "" {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: "Missing Parameter"}); err != nil {
panic(err)
}
return
}
homeserver := strings.Split(userId, ":")
if len(homeserver) <= 1 {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: "Missing Homeserver in UserId"}); err != nil {
panic(err)
}
return
}
foundRoom, err := ReadRoom(roomId)
if err != nil || foundRoom == nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorCode: "MISSING_ROOM", ErrorMessage: fmt.Sprintf("%s", err)}); err != nil {
panic(err)
}
return
}
memberEventContent := event.MemberEventContent{
Membership: "join",
}
memberEventContentBytes, err := json.Marshal(memberEventContent)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Could not parse JSON: %s", err)}); err != nil {
panic(err)
}
return
}
response := makeJoinResponse{
RoomVersion: foundRoom.Version,
Event: event.Event{
Sender: userId,
Origin: homeserver[1],
Timestamp: time.Now().Unix(),
EventType: "m.room.member",
StateKey: userId,
Content: string(memberEventContentBytes),
},
}
w.WriteHeader(http.StatusOK)
if err := json.NewEncoder(w).Encode(response); err != nil {
panic(err)
}
}
// TODO: TEST
func JoinRoomServerHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
request := event.Event{}
errResponse := utils.CheckRequest(r)
if errResponse != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(errResponse); err != nil {
panic(err)
}
return
}
decoder := json.NewDecoder(r.Body)
err := decoder.Decode(&request)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Could not parse JSON: %s", err)}); err != nil {
panic(err)
}
return
}
vars := mux.Vars(r)
roomId := vars["roomId"]
eventId := vars["eventId"]
if roomId == "" || eventId == "" {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: "Missing Parameter"}); err != nil {
panic(err)
}
return
}
foundRoom, err := ReadRoom(roomId)
if err != nil || foundRoom == nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorCode: "MISSING_ROOM", ErrorMessage: fmt.Sprintf("%s", err)}); err != nil {
panic(err)
}
return
}
request.RoomId = roomId
request.Id = eventId
memberEventContent := event.MemberEventContent{}
err = json.Unmarshal([]byte(request.Content), &memberEventContent)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Could not parse JSON: %s", err)}); err != nil {
panic(err)
}
return
}
if memberEventContent.Membership != "join" {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: "Wrong Membership"}); err != nil {
panic(err)
}
return
}
if err == nil {
err = event.CreateEvent(&request, "")
}
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Error Event-Creation: %s", err)}); err != nil {
panic(err)
}
return
}
CreateRoomMember(roomId, request.StateKey)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Database Error: %s", err)}); err != nil {
panic(err)
}
return
}
authChain, err := event.GetAuthChain(&request)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Error Creating Auth Chain: %s", err)}); err != nil {
panic(err)
}
return
}
stateEvents, err := event.ReadStateEventsFromRoom(roomId)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Database Error: %s", err)}); err != nil {
panic(err)
}
return
}
response := joinRoomServerResponse{
Origin: config.Homeserver,
AuthChain: authChain,
State: stateEvents,
}
w.WriteHeader(http.StatusOK)
if err := json.NewEncoder(w).Encode(response); err != nil {
panic(err)
}
}
func generateRoomId(id string) string {
return fmt.Sprintf("!%s:%s", id, config.Homeserver)
}

View file

@ -7,11 +7,11 @@ import (
"nutfactory.org/Matrix/utils/database"
)
func CreateRoom(room *Room, userId string) (err error) {
func CreateRoom(room *Room) (err error) {
sqlStmt := fmt.Sprintf(`INSERT INTO room
(id, version)
(id, version, visibility, name, topic, isDirect, federated)
VALUES
(?, ?)`)
(?, ?, ?, ?, ?, ?, ?)`)
tx, err := database.DB.Begin()
if err != nil {
@ -24,42 +24,31 @@ func CreateRoom(room *Room, userId string) (err error) {
}
defer stmt.Close()
_, err = stmt.Exec(room.Id, room.Version)
_, err = stmt.Exec(
room.Id,
room.Version,
room.Visibility,
room.Name,
room.Topic,
room.IsDirect,
room.Federated,
)
if err != nil {
return
}
tx.Commit()
err = CreateRoomMember(room.Id, userId)
for _, userId := range room.Members {
err = CreateRoomMember(room.Id, userId)
}
return
}
func CreateRoomMember(roomId string, userId string) (err error) {
sqlStmt := fmt.Sprintf(`INSERT INTO roomMember
(roomId, userId)
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)
if err != nil {
return
}
tx.Commit()
return
return event.CreateRoomMember(roomId, userId)
}
func ReadRoom(id string) (foundRoom *Room, err error) {
queryStmt := fmt.Sprintf(`SELECT id, version
queryStmt := fmt.Sprintf(`SELECT id, version, visibility, name, topic, isDirect, federated
FROM room
WHERE id = '%s'`, id)
@ -72,11 +61,19 @@ func ReadRoom(id string) (foundRoom *Room, err error) {
if rows.Next() {
foundRoom = &Room{}
err = rows.Scan(&foundRoom.Id, &foundRoom.Version)
err = rows.Scan(
&foundRoom.Id,
&foundRoom.Version,
&foundRoom.Visibility,
&foundRoom.Name,
&foundRoom.Topic,
&foundRoom.IsDirect,
&foundRoom.Federated,
)
if err != nil {
return
}
foundRoom.Messages, err = event.ReadEventsFromRoom(foundRoom.Id)
foundRoom.Events, err = event.ReadEventsFromRoom(foundRoom.Id)
if err != nil {
return
}
@ -90,34 +87,17 @@ func ReadRoom(id string) (foundRoom *Room, err error) {
}
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
return event.ReadRoomMembers(roomId)
}
func UpdateRoom(room *Room) (err error) {
sqlStmt := fmt.Sprintf(`UPDATE room SET
version = ?
version = ?,
visibility = ?,
name = ?,
topic = ?,
isDirect = ?,
federated = ?
WHERE id = ?`)
tx, err := database.DB.Begin()
@ -131,7 +111,15 @@ func UpdateRoom(room *Room) (err error) {
}
defer stmt.Close()
_, err = stmt.Exec(room.Version, room.Id)
_, err = stmt.Exec(
room.Version,
room.Visibility,
room.Name,
room.Topic,
room.IsDirect,
room.Federated,
room.Id,
)
if err != nil {
return
}