func DeleteUser(userId bson.ObjectId) error { user, err := modelhelper.GetUserById(userId.Hex()) if err != nil { return err } userQuery := func(c *mgo.Collection) error { return c.Remove(bson.M{"_id": userId}) } err = modelhelper.Mongo.Run(modelhelper.UserColl, userQuery) if err != nil { return err } accQuery := func(c *mgo.Collection) error { return c.Remove(bson.M{"profile.nickname": user.Name}) } return modelhelper.Mongo.Run(modelhelper.AccountsColl, accQuery) }
// BuildMachine ensures the user and group of the spec are // inserted into db. func (spec *MachineSpec) BuildMachine(createUser bool) error { // If MachineID is not nil, ensure it exists and reuse it if it does. if spec.HasMachine() { m, err := modelhelper.GetMachine(spec.Machine.ObjectId.Hex()) if err != nil { return err } spec.Machine = *m return nil } // If no existing group is provided, create or use 'hackathon' one, // which will make VMs invisible to users until they're assigned // to proper group before the hackathon. if !spec.HasGroup() { group, err := modelhelper.GetGroup("koding") if err != nil { return err } spec.Machine.Groups = []models.MachineGroup{{Id: group.Id}} } // If no existing user is provided, create one. if !spec.HasUser() { // Try to lookup user by username first. user, err := modelhelper.GetUser(spec.Username()) if err != nil { if !createUser { return fmt.Errorf("user %q does not exist", spec.Username()) } spec.User.ObjectId = bson.NewObjectId() if spec.User.RegisteredAt.IsZero() { spec.User.RegisteredAt = time.Now() } if spec.User.LastLoginDate.IsZero() { spec.User.LastLoginDate = spec.User.RegisteredAt } if err = modelhelper.CreateUser(&spec.User); err != nil { return err } user = &spec.User } spec.User.ObjectId = user.ObjectId spec.User.Name = spec.Username() } // Ensure the user is assigned to the machine. if len(spec.Machine.Users) == 0 { spec.Machine.Users = []models.MachineUser{{ Sudo: true, Owner: true, }} } if spec.Machine.Users[0].Id == "" { spec.Machine.Users[0].Id = spec.User.ObjectId } if spec.Machine.Users[0].Username == "" { spec.Machine.Users[0].Username = spec.User.Name } // Lookup username for existing user. if spec.Machine.Users[0].Username == "" { user, err := modelhelper.GetUserById(spec.Machine.Users[0].Id.Hex()) if err != nil { return err } spec.Machine.Users[0].Username = user.Name } // Lookup group and init Uid. group, err := modelhelper.GetGroupById(spec.Machine.Groups[0].Id.Hex()) if err != nil { return err } spec.Machine.Uid = fmt.Sprintf("u%c%c%c", spec.Machine.Users[0].Username[0], group.Slug[0], spec.Machine.Provider[0], ) m, err := modelhelper.GetMachineBySlug(spec.Machine.Users[0].Id, spec.Machine.Slug) if err == mgo.ErrNotFound { return nil } if err != nil { return err } switch m.State() { case machinestate.Building, machinestate.Starting: return ErrAlreadyBuilding case machinestate.Running: return ErrAlreadyRunning case machinestate.NotInitialized: spec.Machine.ObjectId = m.ObjectId return ErrRebuild default: return fmt.Errorf("machine state is %q; needs to be deleted and build "+ "again (jMachine.ObjectId = %q)", m.State(), m.ObjectId.Hex()) } }
// 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 }