535 lines
14 KiB
Go
535 lines
14 KiB
Go
package localserver
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
)
|
|
|
|
const (
|
|
LIST_ZONE_MEMBERS = "list_zone_members"
|
|
LIST_ZONE_MEMBERS_RESPONSE = "list_zone_members_response"
|
|
GET_USER = "get_user"
|
|
MODIFY_USER_CHAT_RIGHTS = "modify_user_chat_rights"
|
|
ADD_KNOWN_CHAT = "add_known_chat"
|
|
REMOVE_KNOWN_CHAT = "remove_known_chat"
|
|
ADD_KNOWN_AUDIO_CHANNEL = "add_known_audio_channel"
|
|
REMOVE_KNOWN_AUDIO_CHANNEL = "remove_known_audio_channel"
|
|
ADD_KNOWN_VIDEO_CHANNEL = "add_known_video_channel"
|
|
REMOVE_KNOWN_VIDEO_CHANNEL = "remove_known_video_channel"
|
|
ADD_USER = "add_user"
|
|
REMOVE_USER = "remove_user"
|
|
)
|
|
|
|
const (
|
|
NEW_ZONE_USER = "new_zone_user"
|
|
REMOVED_ZONE_USER = "removed_zone_user"
|
|
)
|
|
|
|
type ZoneUsersHandler struct {
|
|
ZoneId string
|
|
ZoneMembersId []string
|
|
DataChannels map[string]*DataChannel
|
|
Flag *uint32
|
|
Publishers []<-chan *ZoneRequest
|
|
DB *ZoneUsersDBHandler
|
|
reqChans []chan<- *ZoneRequest
|
|
}
|
|
|
|
type ZoneUserConfig struct {
|
|
DefaultChatsRights string `json:"defaultChatsRights"`
|
|
DefaultAudioChannelsRights string `json:"defaultAudioChannelsRights"`
|
|
DefaultVideoChannelsRights string `json:"defaultVideoChannelsRights"`
|
|
DefaultMediaRights string `json:"defaultMediaRights"`
|
|
DefaultFileRights string `json:"defaultFileRights"`
|
|
AdminRights string `json:"adminRights"`
|
|
}
|
|
|
|
func NewZoneUsersHandler(zoneId string, owner string, authorizedMembers []string, dataChannels map[string]*DataChannel, flag *uint32) (zoneUsersHandler *ZoneUsersHandler, err error) {
|
|
_, err = os.ReadDir(filepath.Join("data", "zones", zoneId, "users"))
|
|
var zoneUsersDBHandler *ZoneUsersDBHandler
|
|
if err != nil {
|
|
if os.IsNotExist(err) {
|
|
logger.Printf("creating chat directory for zone %s...\n", zoneId)
|
|
mkdirErr := os.MkdirAll(filepath.Join("data", "zones", zoneId, "users"), 0700)
|
|
if mkdirErr != nil {
|
|
return nil, mkdirErr
|
|
}
|
|
zoneUsersDBHandler, err = NewZoneUsersDBHandler(zoneId, owner, authorizedMembers, true)
|
|
if err != nil {
|
|
return
|
|
}
|
|
file, ferr := os.Create(filepath.Join("data", "zones", zoneId, "users", "usersConfig.json"))
|
|
if ferr != nil {
|
|
return nil, ferr
|
|
}
|
|
baseConfig := ZoneUserConfig{
|
|
DefaultChatsRights: "",
|
|
DefaultAudioChannelsRights: "",
|
|
DefaultVideoChannelsRights: "",
|
|
DefaultMediaRights: "",
|
|
DefaultFileRights: "",
|
|
AdminRights: "",
|
|
}
|
|
bs, jsonErr := json.Marshal(baseConfig)
|
|
if jsonErr != nil {
|
|
return nil, jsonErr
|
|
}
|
|
if _, writeErr := file.WriteString(string(bs)); writeErr != nil {
|
|
return nil, writeErr
|
|
}
|
|
_ = file.Close()
|
|
if err != nil {
|
|
return
|
|
}
|
|
} else {
|
|
return
|
|
}
|
|
} else {
|
|
zoneUsersDBHandler, err = NewZoneUsersDBHandler(zoneId, owner, authorizedMembers, false)
|
|
}
|
|
if err != nil {
|
|
return
|
|
}
|
|
zoneUsersHandler = &ZoneUsersHandler{
|
|
ZoneId: zoneId,
|
|
DataChannels: dataChannels,
|
|
ZoneMembersId: authorizedMembers,
|
|
Flag: flag,
|
|
DB: zoneUsersDBHandler,
|
|
}
|
|
return
|
|
}
|
|
|
|
func (zuh *ZoneUsersHandler) Init(ctx context.Context, authorizedMembers []string) (err error) {
|
|
users, err := zuh.DB.ListUsers(0, 1000)
|
|
if err != nil {
|
|
return
|
|
}
|
|
logger.Println(authorizedMembers)
|
|
for _, user := range users {
|
|
var contain bool
|
|
for _, member := range authorizedMembers {
|
|
if user.ID == member {
|
|
contain = true
|
|
break
|
|
}
|
|
}
|
|
if !contain {
|
|
logger.Println("userId", user.ID)
|
|
if rerr := zuh.RemoveUser(user.ID); rerr != nil {
|
|
logger.Println(rerr)
|
|
}
|
|
go func(userId string) {
|
|
for _, rc := range zuh.reqChans {
|
|
logger.Println("------------------------ sending to req chan ------------------------")
|
|
rc <- &ZoneRequest{
|
|
ReqType: string(REMOVED_ZONE_AUTHORIZED_MEMBER),
|
|
From: "node",
|
|
Payload: map[string]interface{}{
|
|
"userId": userId,
|
|
},
|
|
}
|
|
}
|
|
}(user.ID)
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (zuh *ZoneUsersHandler) Subscribe(ctx context.Context, publisher <-chan *ZoneRequest) (reqChan chan *ZoneRequest, done chan struct{}, errCh chan error) {
|
|
reqChan, done, errCh = make(chan *ZoneRequest), make(chan struct{}), make(chan error)
|
|
zuh.reqChans = append(zuh.reqChans, reqChan)
|
|
go func() {
|
|
for {
|
|
select {
|
|
case <-ctx.Done():
|
|
done <- struct{}{}
|
|
return
|
|
case req := <-publisher:
|
|
if err := zuh.handleZoneRequest(ctx, req); err != nil {
|
|
errCh <- err
|
|
}
|
|
}
|
|
}
|
|
}()
|
|
return
|
|
}
|
|
|
|
func (zuh *ZoneUsersHandler) AddUser(userId string) (err error) {
|
|
newUser := &User{
|
|
ID: userId,
|
|
Name: userId,
|
|
ChatRights: "",
|
|
AudioChannelRights: "",
|
|
VideoChannelRights: "",
|
|
MediaRights: "",
|
|
FileRights: "",
|
|
KnownChatsId: []string{},
|
|
KnownAudioChannelsId: []string{},
|
|
KnownVideoChannelsId: make([]string, 0),
|
|
KnownMediaFolderId: make([]string, 0),
|
|
KnownFileFolderId: make([]string, 0),
|
|
}
|
|
if err = zuh.DB.AddNewUser(newUser); err != nil {
|
|
return
|
|
}
|
|
err = atomicallyExecute(zuh.Flag, func() (err error) {
|
|
users, err := zuh.DB.ListUsers(0, 10000)
|
|
if err != nil {
|
|
return
|
|
}
|
|
bs, jsonErr := json.Marshal(&ZoneResponse{
|
|
Type: NEW_ZONE_USER,
|
|
From: "node",
|
|
To: "user",
|
|
Payload: map[string]interface{}{
|
|
"user": newUser,
|
|
},
|
|
})
|
|
if jsonErr != nil {
|
|
return jsonErr
|
|
}
|
|
for _, user := range users {
|
|
if _, ok := zuh.DataChannels[user.ID]; ok {
|
|
_ = zuh.DataChannels[user.ID].DataChannel.SendText(string(bs))
|
|
}
|
|
}
|
|
return
|
|
})
|
|
return
|
|
}
|
|
|
|
func (zuh *ZoneUsersHandler) RemoveUser(userId string) (err error) {
|
|
if err = zuh.DB.DeleteUser(userId); err != nil {
|
|
return
|
|
}
|
|
err = atomicallyExecute(zuh.Flag, func() (err error) {
|
|
users, err := zuh.DB.ListUsers(0, 10000)
|
|
if err != nil {
|
|
return
|
|
}
|
|
bs, jsonErr := json.Marshal(&ZoneResponse{
|
|
Type: REMOVED_ZONE_USER,
|
|
From: "node",
|
|
To: "user",
|
|
Payload: map[string]interface{}{
|
|
"userId": userId,
|
|
},
|
|
})
|
|
if jsonErr != nil {
|
|
return jsonErr
|
|
}
|
|
if _, ok := zuh.DataChannels[userId]; ok {
|
|
_ = zuh.DataChannels[userId].DataChannel.SendText(string(bs))
|
|
}
|
|
for _, user := range users {
|
|
if _, ok := zuh.DataChannels[user.ID]; ok {
|
|
_ = zuh.DataChannels[user.ID].DataChannel.SendText(string(bs))
|
|
}
|
|
}
|
|
return
|
|
})
|
|
return
|
|
}
|
|
|
|
func (zuh *ZoneUsersHandler) AddKnownChat(chatId string, userId string) (err error) {
|
|
user, err := zuh.DB.GetUser(userId)
|
|
if err != nil {
|
|
return
|
|
}
|
|
for _, id := range user.KnownChatsId {
|
|
if id == chatId {
|
|
err = fmt.Errorf("user already know channel %s", chatId)
|
|
return
|
|
}
|
|
}
|
|
user.KnownChatsId = append(user.KnownChatsId, chatId)
|
|
if err = zuh.DB.ModifyUser(userId, user); err != nil {
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
func (zuh *ZoneUsersHandler) RemoveKnownChat(chatId string, userId string) (err error) {
|
|
user, err := zuh.DB.GetUser(userId)
|
|
if err != nil {
|
|
return
|
|
}
|
|
var index int
|
|
var contain bool
|
|
for i, id := range user.KnownChatsId {
|
|
if id == chatId {
|
|
index = i
|
|
contain = true
|
|
break
|
|
}
|
|
}
|
|
if !contain {
|
|
err = fmt.Errorf("does not know this chat")
|
|
return
|
|
}
|
|
if len(user.KnownChatsId) < 2 {
|
|
user.KnownChatsId = make([]string, 0)
|
|
} else {
|
|
user.KnownChatsId = append(user.KnownChatsId[:index], user.KnownChatsId[index+1:]...)
|
|
}
|
|
err = zuh.DB.ModifyUser(userId, user)
|
|
return
|
|
}
|
|
|
|
func (zuh *ZoneUsersHandler) AddKnownAudioChannel(channelId string, userId string) (err error) {
|
|
logger.Println("added new audio channel", channelId, userId)
|
|
user, err := zuh.DB.GetUser(userId)
|
|
if err != nil {
|
|
return
|
|
}
|
|
for _, id := range user.KnownAudioChannelsId {
|
|
if id == channelId {
|
|
err = fmt.Errorf("user already know channel %s", channelId)
|
|
return
|
|
}
|
|
}
|
|
user.KnownAudioChannelsId = append(user.KnownAudioChannelsId, channelId)
|
|
if err = zuh.DB.ModifyUser(userId, user); err != nil {
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
func (zuh *ZoneUsersHandler) RemoveKnownAudioChannel(channelId string, userId string) (err error) {
|
|
user, err := zuh.DB.GetUser(userId)
|
|
if err != nil {
|
|
return
|
|
}
|
|
var index int
|
|
var contain bool
|
|
for i, id := range user.KnownAudioChannelsId {
|
|
if id == channelId {
|
|
index = i
|
|
contain = true
|
|
break
|
|
}
|
|
}
|
|
if !contain {
|
|
err = fmt.Errorf("does not know this chat")
|
|
return
|
|
}
|
|
if len(user.KnownAudioChannelsId) < 2 {
|
|
user.KnownAudioChannelsId = make([]string, 0)
|
|
} else {
|
|
user.KnownAudioChannelsId = append(user.KnownAudioChannelsId[:index], user.KnownAudioChannelsId[index+1:]...)
|
|
}
|
|
err = zuh.DB.ModifyUser(userId, user)
|
|
return
|
|
}
|
|
|
|
func (zuh *ZoneUsersHandler) AddKnownVideoChannel(channelId string, userId string) (err error) {
|
|
logger.Println("added new audio channel", channelId, userId)
|
|
user, err := zuh.DB.GetUser(userId)
|
|
if err != nil {
|
|
return
|
|
}
|
|
for _, id := range user.KnownVideoChannelsId {
|
|
if id == channelId {
|
|
err = fmt.Errorf("user already know channel %s", channelId)
|
|
return
|
|
}
|
|
}
|
|
user.KnownVideoChannelsId = append(user.KnownVideoChannelsId, channelId)
|
|
if err = zuh.DB.ModifyUser(userId, user); err != nil {
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
func (zuh *ZoneUsersHandler) RemoveKnownVideoChannel(channelId string, userId string) (err error) {
|
|
user, err := zuh.DB.GetUser(userId)
|
|
if err != nil {
|
|
return
|
|
}
|
|
var index int
|
|
var contain bool
|
|
for i, id := range user.KnownVideoChannelsId {
|
|
if id == channelId {
|
|
index = i
|
|
contain = true
|
|
break
|
|
}
|
|
}
|
|
if !contain {
|
|
err = fmt.Errorf("does not know this chat")
|
|
return
|
|
}
|
|
if len(user.KnownVideoChannelsId) < 2 {
|
|
user.KnownVideoChannelsId = make([]string, 0)
|
|
} else {
|
|
user.KnownVideoChannelsId = append(user.KnownVideoChannelsId[:index], user.KnownVideoChannelsId[index+1:]...)
|
|
}
|
|
err = zuh.DB.ModifyUser(userId, user)
|
|
return
|
|
}
|
|
|
|
func (zuh *ZoneUsersHandler) AddKnownFolder(folderId string, userId string) (err error) {
|
|
logger.Println("added new known folder", folderId, userId)
|
|
user, err := zuh.DB.GetUser(userId)
|
|
if err != nil {
|
|
return
|
|
}
|
|
for _, id := range user.KnownFileFolderId {
|
|
if id == folderId {
|
|
err = fmt.Errorf("user already know channel %s", folderId)
|
|
return
|
|
}
|
|
}
|
|
user.KnownVideoChannelsId = append(user.KnownVideoChannelsId, folderId)
|
|
if err = zuh.DB.ModifyUser(userId, user); err != nil {
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
func (zuh *ZoneUsersHandler) RemoveKnownFolder(folderId string, userId string) (err error) {
|
|
user, err := zuh.DB.GetUser(userId)
|
|
if err != nil {
|
|
return
|
|
}
|
|
var index int
|
|
var contain bool
|
|
for i, id := range user.KnownFileFolderId {
|
|
if id == folderId {
|
|
index = i
|
|
contain = true
|
|
break
|
|
}
|
|
}
|
|
if !contain {
|
|
err = fmt.Errorf("does not know this chat")
|
|
return
|
|
}
|
|
if len(user.KnownFileFolderId) < 2 {
|
|
user.KnownFileFolderId = make([]string, 0)
|
|
} else {
|
|
user.KnownFileFolderId = append(user.KnownFileFolderId[:index], user.KnownFileFolderId[index+1:]...)
|
|
}
|
|
err = zuh.DB.ModifyUser(userId, user)
|
|
return
|
|
}
|
|
|
|
func (zuh *ZoneUsersHandler) handleZoneRequest(ctx context.Context, req *ZoneRequest) (err error) {
|
|
logger.Println("got request in zone users handler", req)
|
|
switch req.ReqType {
|
|
case REMOVE_USER:
|
|
if err = verifyFieldsString(req.Payload, "userId"); err != nil {
|
|
return
|
|
}
|
|
err = zuh.RemoveUser(req.Payload["userId"].(string))
|
|
case ADD_USER:
|
|
if err = verifyFieldsString(req.Payload, "userId"); err != nil {
|
|
return
|
|
}
|
|
err = zuh.AddUser(req.Payload["userId"].(string))
|
|
case REMOVE_KNOWN_CHAT:
|
|
if err = verifyFieldsString(req.Payload, "chatId", "userId"); err != nil {
|
|
return
|
|
}
|
|
err = zuh.RemoveKnownChat(req.Payload["chatId"].(string), req.Payload["userId"].(string))
|
|
case ADD_KNOWN_CHAT:
|
|
if err = verifyFieldsString(req.Payload, "chatId", "userId"); err != nil {
|
|
return
|
|
}
|
|
err = zuh.AddKnownChat(req.Payload["chatId"].(string), req.Payload["userId"].(string))
|
|
case REMOVE_KNOWN_AUDIO_CHANNEL:
|
|
if err = verifyFieldsString(req.Payload, "channelId", "userId"); err != nil {
|
|
return
|
|
}
|
|
err = zuh.RemoveKnownAudioChannel(req.Payload["channelId"].(string), req.Payload["userId"].(string))
|
|
case ADD_KNOWN_AUDIO_CHANNEL:
|
|
if err = verifyFieldsString(req.Payload, "channelId", "userId"); err != nil {
|
|
return
|
|
}
|
|
err = zuh.AddKnownAudioChannel(req.Payload["channelId"].(string), req.Payload["userId"].(string))
|
|
case REMOVE_KNOWN_VIDEO_CHANNEL:
|
|
if err = verifyFieldsString(req.Payload, "channelId", "userId"); err != nil {
|
|
return
|
|
}
|
|
err = zuh.RemoveKnownVideoChannel(req.Payload["channelId"].(string), req.Payload["userId"].(string))
|
|
case ADD_KNOWN_VIDEO_CHANNEL:
|
|
if err = verifyFieldsString(req.Payload, "channelId", "userId"); err != nil {
|
|
return
|
|
}
|
|
err = zuh.AddKnownVideoChannel(req.Payload["channelId"].(string), req.Payload["userId"].(string))
|
|
case GET_USER:
|
|
if err = verifyFieldsString(req.Payload, "userId"); err != nil {
|
|
return
|
|
}
|
|
if _, ok := req.Payload["init"]; !ok {
|
|
err = fmt.Errorf("no field init in req payload for get user")
|
|
return
|
|
}
|
|
if _, ok := req.Payload["init"].(bool); !ok {
|
|
err = fmt.Errorf("field init is of wrong type")
|
|
return
|
|
}
|
|
user, err := zuh.DB.GetUser(req.Payload["userId"].(string))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
var answer *ZoneResponse
|
|
if req.Payload["init"].(bool) {
|
|
answer = &ZoneResponse{
|
|
Type: "get_current_user_response",
|
|
To: "",
|
|
From: "",
|
|
Payload: map[string]interface{}{
|
|
"user": user,
|
|
},
|
|
}
|
|
} else {
|
|
answer = &ZoneResponse{
|
|
Type: "get_user_response",
|
|
To: "",
|
|
From: "",
|
|
Payload: map[string]interface{}{
|
|
"user": user,
|
|
},
|
|
}
|
|
}
|
|
bs, err := json.Marshal(answer)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
logger.Println(string(bs))
|
|
if _, ok := zuh.DataChannels[req.From]; ok {
|
|
if err = zuh.DataChannels[req.From].DataChannel.SendText(string(bs)); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
case LIST_ZONE_MEMBERS:
|
|
users, err := zuh.DB.ListUsers(0, 0)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
bs, err := json.Marshal(&ZoneResponse{
|
|
Type: LIST_ZONE_MEMBERS_RESPONSE,
|
|
To: "",
|
|
From: "",
|
|
Payload: map[string]interface{}{
|
|
"users": users,
|
|
},
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if _, ok := zuh.DataChannels[req.From]; ok {
|
|
if err = zuh.DataChannels[req.From].DataChannel.SendText(string(bs)); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
case MODIFY_USER_CHAT_RIGHTS:
|
|
}
|
|
return
|
|
}
|