signaller/internal/backends/memory/user.go

225 lines
5.3 KiB
Go

package memory
import (
"sync"
"time"
"github.com/nxshock/signaller/internal"
"github.com/nxshock/signaller/internal/models"
"github.com/nxshock/signaller/internal/models/createroom"
"github.com/nxshock/signaller/internal/models/devices"
"github.com/nxshock/signaller/internal/models/rooms"
)
type User struct {
name string
password string
Tokens map[string]Token
backend *Backend
mutex sync.RWMutex
}
func (user *User) ID() string {
return "@" + user.name + ":" + user.backend.hostname
}
func (user *User) Name() string {
return user.name
}
func (user *User) Password() string {
return user.password
}
func (user *User) CreateRoom(request createroom.Request) (internal.Room, *models.ApiError) {
for _, existingRoom := range user.backend.rooms {
if existingRoom.AliasName() == request.RoomAliasName { // TODO: strip and check request room alias name before use
return nil, internal.NewError(models.M_ROOM_IN_USE, "")
}
}
t := time.Now()
events := make([]RoomEvent, 0)
// Create room event
events = append(events, RoomEvent{
Content: nil,
Type: rooms.Create,
EventID: newToken(eventIDSize),
Sender: user,
OriginServerTS: t})
// TODO: Add join room event
// Set join rules event
events = append(events, RoomEvent{
Content: []byte(request.Visibility), // TODO: check visibility vs join rules
Type: rooms.JoinRules,
EventID: newToken(eventIDSize),
Sender: user,
OriginServerTS: t})
// Set room name event
if request.Name != "" {
events = append(events, RoomEvent{
Content: nil, // TODO: add
Type: rooms.Name,
EventID: newToken(eventIDSize),
Sender: user,
OriginServerTS: t})
}
// Set room alias event
if request.RoomAliasName != "" {
events = append(events, RoomEvent{
Content: nil, // TODO: add
Type: rooms.CanonicalAlias,
EventID: newToken(eventIDSize),
Sender: user,
OriginServerTS: t})
}
room := &Room{
id: newToken(groupIDSize),
aliasName: request.RoomAliasName,
name: request.Name,
topic: request.Topic,
events: events,
creator: user,
joined: []internal.User{user},
visibility: request.Visibility,
server: user.backend,
state: request.Preset}
for i, _ := range room.events {
room.events[i].Room = room
//v.Room = room
}
user.backend.rooms[room.ID()] = room
return room, nil
}
func (user *User) SetTopic(room internal.Room, topic string) *models.ApiError {
room.(*Room).mutex.Lock()
defer room.(*Room).mutex.Unlock()
if room.(*Room).creator.ID() != user.ID() { // TODO: currently only creator can change topic
return internal.NewError(models.M_FORBIDDEN, "")
}
room.(*Room).topic = topic
room.(*Room).events = append(room.(*Room).events, RoomEvent{
Type: rooms.Topic,
Sender: user,
OriginServerTS: time.Now(),
Room: room})
return nil
}
func (user *User) LeaveRoom(room internal.Room) *models.ApiError {
room.(*Room).mutex.Lock()
defer room.(*Room).mutex.Unlock()
for i, roomMember := range room.(*Room).joined {
if roomMember.ID() == user.ID() {
room.(*Room).joined = append(room.(*Room).joined[:i], room.(*Room).joined[i+1:]...) // TODO: add event
return nil
}
}
return internal.NewError(models.M_BAD_STATE, "you are not a member of group") // TODO: check error code
}
func (user *User) SendMessage(room internal.Room, text string) *models.ApiError {
room.(*Room).mutex.Lock()
defer room.(*Room).mutex.Unlock()
userInRoom := false
for _, roomMember := range room.(*Room).joined {
if roomMember.ID() == user.ID() {
userInRoom = true
}
}
if !userInRoom {
return internal.NewError(models.M_FORBIDDEN, "")
}
room.(*Room).events = append(room.(*Room).events, RoomEvent{
Content: nil,
Type: rooms.Message,
EventID: newToken(defaultTokenSize),
Sender: user,
OriginServerTS: time.Now(),
Room: room})
return nil
}
func (user *User) JoinedRooms() []internal.Room {
user.backend.mutex.Lock()
defer user.backend.mutex.Unlock()
var result []internal.Room
for _, room := range user.backend.rooms {
for _, user := range room.(*Room).joined {
if user.ID() == user.ID() {
result = append(result, room)
}
}
}
return result
}
func (user *User) Devices() []devices.Device {
user.backend.mutex.Lock()
defer user.backend.mutex.Unlock()
var result []devices.Device
for _, token := range user.Tokens {
device := devices.Device{
DeviceID: token.Device}
result = append(result, device)
}
return result
}
func (user *User) SetRoomVisibility(room internal.Room, visibilityType createroom.VisibilityType) *models.ApiError {
if user.ID() != room.Creator().ID() {
return internal.NewError(models.M_FORBIDDEN, "only room owner can change visibility") // TODO: room administrators can use this method too
}
room.(*Room).mutex.Lock()
defer room.(*Room).mutex.Unlock()
room.(*Room).visibility = visibilityType
return nil
}
func (user *User) ChangePassword(newPassword string) {
user.mutex.Lock()
defer user.mutex.Unlock()
user.password = newPassword
}
func (user *User) Logout(token string) {
delete(user.Tokens, token)
}
func (user *User) LogoutAll() {
user.Tokens = make(map[string]Token)
}