func TestUnsetSocialChannelFromWorkspace(t *testing.T) { db := modeltesthelper.NewMongoDB(t) defer db.Close() rand.Seed(time.Now().UnixNano()) w, err := createWorkspace() if err != nil { t.Fatalf(err.Error()) } // first fetch it w2, err := modelhelper.GetWorkspaceByChannelId(w.ChannelId) if err != nil { t.Errorf(err.Error()) } if w2 == nil { t.Errorf("couldnt fetch workspace by channel id got nil, expected: %+v", w) } if w2.ObjectId.Hex() != w.ObjectId.Hex() { t.Errorf("workspaces are not same: expected: %+v, got: ", w) } err = modelhelper.UnsetSocialChannelFromWorkspace(w.ObjectId) if err != nil { t.Errorf("we should be able to unset social channel id") } _, err = modelhelper.GetWorkspaceByChannelId(w.ChannelId) if err == nil { t.Errorf("we should not be able to find the WS") } }
func TestGetWorkspaceByChannelId(t *testing.T) { db := modeltesthelper.NewMongoDB(t) defer db.Close() rand.Seed(time.Now().UnixNano()) w, err := createWorkspace() if err != nil { t.Fatalf(err.Error()) } w2, err := modelhelper.GetWorkspaceByChannelId(w.ChannelId) if err != nil { t.Errorf(err.Error()) } if w2 == nil { t.Errorf("couldnt fetch workspace by channel id got nil, expected: %+v", w) } if w2.ObjectId.Hex() != w.ObjectId.Hex() { t.Errorf("workspaces are not same: expected: %+v, got: ", w) } _, err = modelhelper.GetWorkspaceByChannelId(strconv.FormatInt(rand.Int63(), 10)) if err == nil { t.Errorf("we should not be able to find the WS") } }
// UnshareVM removes the users from JMachine document func (c *Controller) UnshareVM(ping *models.Ping, toBeRemovedUsers []bson.ObjectId) error { // if channel id is nil, there is nothing to do if ping.ChannelId == 0 { return nil } ws, err := modelhelper.GetWorkspaceByChannelId( strconv.FormatInt(ping.ChannelId, 10), ) if err != nil { return filterErr(err) } if len(toBeRemovedUsers) == 0 { return nil // no one to remove } return modelhelper.RemoveUsersFromMachineByIds(ws.MachineUID, toBeRemovedUsers) }
// EndPrivateMessage stops the collaboration session and deletes the all // messages from db func (c *Controller) EndPrivateMessage(ping *models.Ping) error { // if channel id is nil, there is nothing to do if ping.ChannelId == 0 { return nil } // fetch the channel channel := socialapimodels.NewChannel() if err := channel.ById(ping.ChannelId); err != nil { // if channel is not there, do not do anyting if err == bongo.RecordNotFound { return nil } return err } canOpen, err := channel.CanOpen(ping.AccountId) if err != nil { return err } if !canOpen { return nil // if the requester can not open the channel do not process } // delete the channel err = channel.Delete() if err != nil { return err } ws, err := modelhelper.GetWorkspaceByChannelId( strconv.FormatInt(ping.ChannelId, 10), ) if err != nil { return filterErr(err) } return modelhelper.UnsetSocialChannelFromWorkspace(ws.ObjectId) }
func TestCollaborationOperationsEndPrivateMessage(t *testing.T) { r := runner.New("collaboration-EndPrivateMessage-tests") err := r.Init() if err != nil { panic(err) } defer r.Close() appConfig := config.MustRead(r.Conf.Path) modelhelper.Initialize(appConfig.Mongo) defer modelhelper.Close() // init with defaults mongoCache := cache.NewMongoCacheWithTTL(modelhelper.Mongo.Session) defer mongoCache.StopGC() handler := New(r.Log, mongoCache, appConfig, r.Kite) Convey("while testing EndPrivateMessage", t, func() { req := &models.Ping{ AccountId: 1, FileId: fmt.Sprintf("%d", rand.Int63()), } Convey("should be able to create the channel first", func() { creator := socialapimodels.CreateAccountWithTest() // init account c := socialapimodels.NewChannel() // init channel c.CreatorId = creator.Id // set Creator id c.TypeConstant = socialapimodels.Channel_TYPE_COLLABORATION So(c.Create(), ShouldBeNil) cp, err := c.AddParticipant(creator.Id) So(err, ShouldBeNil) So(cp, ShouldNotBeNil) req.AccountId = c.CreatorId // set real account id req.ChannelId = c.Id // set real channel id ws := &mongomodels.Workspace{ ObjectId: bson.NewObjectId(), OriginId: bson.NewObjectId(), Name: "My Workspace", Slug: "my-workspace", ChannelId: strconv.FormatInt(req.ChannelId, 10), MachineUID: bson.NewObjectId().Hex(), MachineLabel: "koding-vm-0", Owner: "cihangir", RootPath: "/home/cihangir", IsDefault: true, } So(modelhelper.CreateWorkspace(ws), ShouldBeNil) Convey("should be able to delete channel", func() { err = handler.EndPrivateMessage(req) So(err, ShouldBeNil) Convey("deleted channel should not be exist", func() { channel := socialapimodels.NewChannel() err := channel.ById(req.ChannelId) So(err, ShouldEqual, bongo.RecordNotFound) }) Convey("channel id in workspace should not be exist", func() { ws2, err := modelhelper.GetWorkspaceByChannelId( strconv.FormatInt(req.ChannelId, 10), ) So(err, ShouldEqual, mgo.ErrNotFound) So(ws2, ShouldEqual, nil) }) }) Convey("if not a participant, should not be able to delete channel", func() { req.AccountId = 1 err = handler.EndPrivateMessage(req) So(err, ShouldBeNil) Convey("channel should exist", func() { channel := socialapimodels.NewChannel() err := channel.ById(req.ChannelId) So(err, ShouldBeNil) }) }) Convey("if channel doesnt exists, should success", func() { req.ChannelId = 1 err = handler.EndPrivateMessage(req) So(err, ShouldBeNil) Convey("channel should not exist", func() { channel := socialapimodels.NewChannel() err := channel.ById(req.ChannelId) So(err, ShouldEqual, bongo.RecordNotFound) }) }) }) }) }
func (c *Controller) findToBeRemovedUsers(ping *models.Ping) ([]bson.ObjectId, error) { ws, err := modelhelper.GetWorkspaceByChannelId( strconv.FormatInt(ping.ChannelId, 10), ) if err != nil { return nil, filterErr(err) } machine, err := modelhelper.GetMachineByUid(ws.MachineUID) if err != nil { return nil, filterErr(err) } ownerMachineUser := machine.Owner() if ownerMachineUser == nil { c.log.Critical("owner couldnt found %+v", ping) return nil, nil // if we cant find the owner, we cant process the users } ownerAccount, err := modelhelper.GetAccountByUserId(ownerMachineUser.Id) if err != nil { return nil, filterErr(err) } // get workspaces of the owner ownersWorkspaces, err := modelhelper.GetWorkspaces(ownerAccount.Id) if err != nil { return nil, filterErr(err) } users := partitionUsers(ownerAccount, ownersWorkspaces, ws) var toBeRemovedUsers []bson.ObjectId for accountID, count := range users { // if we count the user more than once, that means user is in another // workspace too if count > 1 { continue } u, err := modelhelper.GetUserByAccountId(accountID) if err != nil { return nil, err } toBeRemovedUsers = append(toBeRemovedUsers, u.ObjectId) } var filteredUsers []bson.ObjectId permanentUsers := make(map[string]struct{}) for _, user := range machine.Users { if user.Permanent { permanentUsers[user.Id.Hex()] = struct{}{} } } for _, toBeRemovedUser := range toBeRemovedUsers { if _, ok := permanentUsers[toBeRemovedUser.Hex()]; !ok { filteredUsers = append(filteredUsers, toBeRemovedUser) } } return filteredUsers, nil }
// RemoveUsersFromMachine removes the collaboraters from the host machine func (c *Controller) RemoveUsersFromMachine(ping *models.Ping, toBeRemovedUsers []bson.ObjectId) error { // if channel id is nil, there is nothing to do if ping.ChannelId == 0 { return nil } ws, err := modelhelper.GetWorkspaceByChannelId(strconv.FormatInt(ping.ChannelId, 10)) if err != nil { return filterErr(err) } m, err := modelhelper.GetMachineByUid(ws.MachineUID) if err != nil { return filterErr(err) } // Get the klient. klientRef, err := klient.ConnectTimeout(c.kite, m.QueryString, time.Second*10) if err != nil { if err == klient.ErrDialingFailed || err == kite.ErrNoKitesAvailable { c.log.Error( "[%s] Klient is not registered to Kontrol. Err: %s", m.QueryString, err, ) return nil // if the machine is not open, we cant do anything } return err } defer klientRef.Close() type args struct { Username string // we are not gonna use this propery here, just for reference // Permanent bool } var iterErr error for _, toBeDeletedUser := range toBeRemovedUsers { // fetch user for its username u, err := modelhelper.GetUserById(toBeDeletedUser.Hex()) if err != nil { c.log.Error("couldnt get user", err.Error()) // if we cant find the regarding user, do not do anything if err == mgo.ErrNotFound { continue } iterErr = err continue // do not stop iterating, unshare from others } param := args{ Username: u.Name, } _, err = klientRef.Client.Tell("klient.unshare", param) if err != nil { c.log.Error("couldnt unshare %+v", err.Error()) // those are so error prone, force klient side not to change the API // or make them exported to some other package? if strings.Contains(err.Error(), "user is permanent") { continue } if strings.Contains(err.Error(), "user is not in the shared list") { continue } if strings.Contains(err.Error(), "User not found") { continue } iterErr = err continue // do not stop iterating, unshare from others } } res, err := klientRef.Client.Tell("klient.shared", nil) if err == nil { c.log.Info("other users in the machine: %+v", res.MustString()) } // iterErr will be nil if we dont encounter to any error in iter return iterErr }