func TestGetMachinesByUsernameAndProvider(t *testing.T) { db := modeltesthelper.NewMongoDB(t) defer db.Close() user := &models.User{Name: "testuser", ObjectId: bson.NewObjectId()} defer modelhelper.RemoveUser(user.Name) if err := modelhelper.CreateUser(user); err != nil { t.Error(err) } // koding provider machine m1 := &models.Machine{ ObjectId: bson.NewObjectId(), Uid: bson.NewObjectId().Hex(), Provider: "koding", Users: []models.MachineUser{ {Id: user.ObjectId, Owner: true}, }, } if err := modelhelper.CreateMachine(m1); err != nil { t.Errorf(err.Error()) } defer modelhelper.DeleteMachine(m1.ObjectId) // non koding provider machine m2 := &models.Machine{ ObjectId: bson.NewObjectId(), Uid: bson.NewObjectId().Hex(), Provider: "amazon", Users: []models.MachineUser{ {Id: user.ObjectId, Owner: true}, }, } if err := modelhelper.CreateMachine(m2); err != nil { t.Errorf(err.Error()) } defer modelhelper.DeleteMachine(m2.ObjectId) // should only get koding provider machine machines, err := modelhelper.GetMachinesByUsernameAndProvider(user.Name, m1.Provider) if err != nil { t.Error(err.Error()) } if len(machines) != 1 { t.Errorf("machine count should be 2, got: %d", len(machines)) } }
func TestBlockUser(t *testing.T) { db := modeltesthelper.NewMongoDB(t) defer db.Close() username, blockedReason := "testuser", "testing" user := &models.User{ Name: username, ObjectId: bson.NewObjectId(), Status: models.UserBlocked, } defer func() { modelhelper.RemoveUser(username) }() err := modelhelper.CreateUser(user) if err != nil { t.Error(err) } err = modelhelper.BlockUser(username, blockedReason, 1*time.Hour) if err != nil { t.Error(err) } user, err = modelhelper.GetUser(username) if err != nil { t.Error(err) } if user.Status != models.UserBlocked { t.Errorf("User status is not blocked") } if user.BlockedReason != blockedReason { t.Errorf("User blocked reason is not: %s", blockedReason) } if user.BlockedUntil.IsZero() { t.Errorf("User blocked until date is not set") } id, err := modelhelper.GetUserID(user.Name) if err != nil { t.Fatalf("GetUserID()=%s", err) } if id != user.ObjectId { t.Fatalf("got %q, want %q", id.Hex(), user.ObjectId.Hex()) } }
func TestRemoveUser(t *testing.T) { db := modeltesthelper.NewMongoDB(t) defer db.Close() username := "******" user := &models.User{ Name: username, ObjectId: bson.NewObjectId(), } err := modelhelper.CreateUser(user) if err != nil { t.Error(err) } err = modelhelper.RemoveUser(username) if err != nil { t.Error(err) } user, err = modelhelper.GetUser(username) if err == nil { t.Errorf("User should've been deleted, but wasn't") } }
func CreateAccountInBothDbsWithNick(nick string) (*Account, error) { accId := bson.NewObjectId() accHex := nick oldAcc, err := modelhelper.GetAccount(nick) if err == mgo.ErrNotFound { oldAcc = &kodingmodels.Account{ Id: accId, Profile: struct { Nickname string `bson:"nickname" json:"nickname"` FirstName string `bson:"firstName" json:"firstName"` LastName string `bson:"lastName" json:"lastName"` Hash string `bson:"hash" json:"hash"` }{ Nickname: nick, }, } err := modelhelper.CreateAccount(oldAcc) if err != nil { return nil, err } } oldUser, err := modelhelper.GetUser(nick) if err == mgo.ErrNotFound { oldUser = &kodingmodels.User{ ObjectId: bson.NewObjectId(), Password: accHex, Salt: accHex, Name: nick, Email: accHex + "@koding.com", Status: "confirmed", EmailFrequency: &kodingmodels.EmailFrequency{}, } err = modelhelper.CreateUser(oldUser) if err != nil { return nil, err } } a := NewAccount() a.Nick = nick a.OldId = accId.Hex() if err := a.ByNick(nick); err == bongo.RecordNotFound { if err := a.Create(); err != nil { return nil, err } } if oldAcc.SocialApiId != strconv.FormatInt(a.Id, 10) { s := modelhelper.Selector{"_id": oldAcc.Id} o := modelhelper.Selector{"$set": modelhelper.Selector{ "socialApiId": strconv.FormatInt(a.Id, 10), }} if err := modelhelper.UpdateAccount(s, o); err != nil { return nil, err } } return a, nil }
func testFixture(t *testing.T) (*models.User, *models.Group, *models.Machine, *models.Account, func()) { var c cleaner user := &models.User{ ObjectId: bson.NewObjectId(), Name: "testuser", } if err := modelhelper.CreateUser(user); err != nil { c.clean() t.Fatalf("error creating user: %s", err) } c.add(user) account := &models.Account{ Id: bson.NewObjectId(), Profile: models.AccountProfile{ Nickname: user.Name, FirstName: bson.NewObjectId().Hex(), LastName: bson.NewObjectId().Hex(), }, Type: "registered", } if err := modelhelper.CreateAccount(account); err != nil { c.clean() t.Fatalf("error creating account: %s", err) } c.add(account) group, err := createGroup() if err != nil { c.clean() t.Fatalf("error creating group: %s", err) } c.add(group) machine := &models.Machine{ ObjectId: bson.NewObjectId(), Uid: bson.NewObjectId().Hex(), Provider: "koding", Users: []models.MachineUser{ { Id: user.ObjectId, Owner: true, }, }, } if err := modelhelper.CreateMachine(machine); err != nil { c.clean() t.Fatalf("error creating machine: %s", err) } c.add(machine) return user, group, machine, account, c.clean }
func TestLookupGroup(t *testing.T) { const N = 10 db := modeltesthelper.NewMongoDB(t) defer db.Close() user := &models.User{ ObjectId: bson.NewObjectId(), Name: bson.NewObjectId().Hex(), Email: bson.NewObjectId().Hex(), } if err := modelhelper.CreateUser(user); err != nil { t.Fatalf("CreateUser()=%s", err) } groups, err := createGroups(N + 1) if err != nil { t.Fatalf("createGroups()=%s", err) } machines, err := createMachines(N, t) if err != nil { t.Fatalf("createMachines()=%s", err) } for i := range machines { machines[i].Groups = []models.MachineGroup{{Id: groups[i].Id}} update := bson.M{ "$set": bson.M{ "groups": machines[i].Groups, "users": []*models.MachineUser{{ Id: user.ObjectId, Username: user.Name, }}, }, } if i&2 == 0 { // force to lookup by registerUrl for machines with even index update["$set"].(bson.M)["ipAddress"] = "" } err := modelhelper.UpdateMachine(machines[i].ObjectId, update) if err != nil { t.Fatalf("UpdateMachine()=%s", err) } } session := &models.Session{ Id: bson.NewObjectId(), GroupName: groups[N].Slug, Username: user.Name, } if err := modelhelper.CreateSession(session); err != nil { t.Fatalf("CreateSession()=%s") } cases := map[string]struct { opts *modelhelper.LookupGroupOptions id bson.ObjectId }{ "lookup by queryString": { &modelhelper.LookupGroupOptions{ Username: user.Name, KiteID: mustKiteID(machines[0].QueryString), }, groups[0].Id, }, "lookup by ipAddress": { &modelhelper.LookupGroupOptions{ Username: user.Name, ClientURL: machines[1].RegisterURL, }, groups[1].Id, }, "lookup by registerUrl": { &modelhelper.LookupGroupOptions{ Username: user.Name, ClientURL: machines[4].RegisterURL, }, groups[4].Id, }, "lookup by most recent session for KD": { &modelhelper.LookupGroupOptions{ Username: user.Name, Environment: "managed", }, groups[N].Id, }, } for name, cas := range cases { t.Run(name, func(t *testing.T) { team, err := modelhelper.LookupGroup(cas.opts) if err != nil { t.Fatalf("LookupGroup()=%s", err) } if team.Id != cas.id { t.Fatalf("got %q, want %q", team.Id.Hex(), cas.id.Hex()) } }) } }
func TestGetAnyUserTokenFromGroup(t *testing.T) { db := modeltesthelper.NewMongoDB(t) defer db.Close() id := bson.NewObjectId() username := id.Hex() user := &models.User{ ObjectId: id, Name: username, Email: username + "@" + username + ".com", } err := modelhelper.CreateUser(user) if err != nil { t.Error(err) } groupName := bson.NewObjectId().Hex() key := fmt.Sprintf("foreignAuth.slack.%s.token", groupName) token := "token-123qwe" selector := bson.M{"username": username} update := bson.M{key: token} if err := modelhelper.UpdateUser(selector, update); err != nil { t.Error("Error while updating user") } id2 := bson.NewObjectId() username2 := id2.Hex() user2 := &models.User{ ObjectId: id2, Name: username2, Email: username2 + "@" + username2 + ".com", } err = modelhelper.CreateUser(user2) if err != nil { t.Error(err) } groupName2 := bson.NewObjectId().Hex() key2 := fmt.Sprintf("foreignAuth.slack.%s.token", groupName2) token2 := "token-123qwe11" selector2 := bson.M{"username": username2} update2 := bson.M{key2: token2} if err := modelhelper.UpdateUser(selector2, update2); err != nil { t.Error("Error while updating user") } users, err := modelhelper.GetAnySlackTokenWithGroup(groupName) if err != nil { t.Error("Error while getting user token") } if len(users) != 1 { t.Error("Length of user should be 1") } err = modelhelper.RemoveUser(username) if err != nil { t.Error(err) } }
// 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()) } }
func CreateUser(opts *UserOptions) (*User, error) { username := opts.Username groupname := opts.Groupname provider := opts.Provider template := opts.Template privateKey, publicKey, err := sshutil.TemporaryKey() if err != nil { return nil, err } labels, err := machineLabels([]byte(template)) if err != nil { return nil, err } relationExists := true // jAccounts account, err := modelhelper.GetAccount(username) if err == mgo.ErrNotFound { relationExists = false account = &models.Account{ Id: bson.NewObjectId(), Profile: models.AccountProfile{ Nickname: username, }, } err = modelhelper.CreateAccount(account) } if err != nil { return nil, errors.New("failure looking up jAccounts: " + err.Error()) } // jGroups group, err := modelhelper.GetGroup(groupname) if err == mgo.ErrNotFound { relationExists = false group = &models.Group{ Id: bson.NewObjectId(), Title: groupname, Slug: groupname, } err = modelhelper.CreateGroup(group) } if err != nil { return nil, errors.New("failure looking up jGroups: " + err.Error()) } if !relationExists { // add relation between use and group relationship := &models.Relationship{ Id: bson.NewObjectId(), TargetId: account.Id, TargetName: "JAccount", SourceId: group.Id, SourceName: "JGroup", As: "member", } err := modelhelper.AddRelationship(relationship) if err != nil { return nil, errors.New("failure insering relationship: " + err.Error()) } } // jUsers user, err := modelhelper.GetUser(username) if err == nil && len(user.SshKeys) != 0 { publicKey = user.SshKeys[0].Key } if err == mgo.ErrNotFound { user = &models.User{ ObjectId: bson.NewObjectId(), Email: username + "@" + username + ".com", LastLoginDate: time.Now().UTC(), RegisteredAt: time.Now().UTC(), Name: username, // bson equivelant is username Password: "******", Status: "confirmed", SshKeys: []struct { Title string `bson:"title"` Key string `bson:"key"` }{ {Key: publicKey}, }, } err = modelhelper.CreateUser(user) } if err != nil { return nil, errors.New("failure looking up jUsers: " + err.Error()) } queryString := protocol.Kite{ID: opts.KlientID}.String() cred := &models.Credential{ Id: bson.NewObjectId(), Provider: opts.Provider, Identifier: bson.NewObjectId().Hex(), OriginId: account.Id, } credData := &models.CredentialData{ Id: bson.NewObjectId(), Identifier: cred.Identifier, OriginId: account.Id, Meta: bson.M{ "queryString": queryString, "memory": 0, "cpu": 0, "box": "", }, } if err := modelhelper.InsertCredential(cred, credData); err != nil { return nil, err } relationship := &models.Relationship{ Id: bson.NewObjectId(), TargetId: cred.Id, TargetName: "JCredential", SourceId: account.Id, SourceName: "JAccount", As: "owner", } if err := modelhelper.AddRelationship(relationship); err != nil { return nil, err } // jComputeStack and jStackTemplates stackTemplateId := bson.NewObjectId() stackTemplate := &models.StackTemplate{ Id: stackTemplateId, Credentials: map[string][]string{ "vagrant": {cred.Identifier}, }, } stackTemplate.Template.Content = template if err := modelhelper.CreateStackTemplate(stackTemplate); err != nil { return nil, err } // later we can add more users with "Owner:false" to test sharing capabilities users := []models.MachineUser{ {Id: user.ObjectId, Sudo: true, Owner: true}, } machineIds := make([]bson.ObjectId, len(labels)) for i, label := range labels { machineId := bson.NewObjectId() machine := &models.Machine{ ObjectId: machineId, Label: label, Domain: username + ".dev.koding.io", Provider: provider, CreatedAt: time.Now().UTC(), Users: users, Meta: make(bson.M, 0), Groups: make([]models.MachineGroup, 0), Credential: username, } machine.Assignee.InProgress = false machine.Assignee.AssignedAt = time.Now().UTC() machine.Status.State = machinestate.NotInitialized.String() machine.Status.ModifiedAt = time.Now().UTC() machineIds[i] = machine.ObjectId if err := modelhelper.CreateMachine(machine); err != nil { return nil, err } } computeStackID := bson.NewObjectId() computeStack := &models.ComputeStack{ Id: computeStackID, BaseStackId: stackTemplateId, Machines: machineIds, } if err := modelhelper.CreateComputeStack(computeStack); err != nil { return nil, err } return &User{ MachineIDs: machineIds, MachineLabels: labels, StackID: computeStackID.Hex(), StackTemplateID: stackTemplate.Id.Hex(), AccountID: account.Id, CredID: cred.Id.Hex(), CredDataID: credData.Id.Hex(), PrivateKey: privateKey, PublicKey: publicKey, Identifiers: []string{cred.Identifier}, }, nil }
func TestChannelUpdatedCalculateUnreadItemCount(t *testing.T) { r := runner.New("test") if err := r.Init(); err != nil { t.Fatalf("couldnt start bongo %s", err.Error()) } defer r.Close() appConfig := config.MustRead(r.Conf.Path) modelhelper.Initialize(appConfig.Mongo) defer modelhelper.Close() groupName := models.RandomGroupName() Convey("while testing get account", t, func() { Convey("if cookie is not set, should return nil", func() { a := getAccount(&http.Request{}, models.Channel_KODING_NAME) So(a, ShouldNotBeNil) So(a.Id, ShouldBeZeroValue) }) Convey("if cookie value is not set, should return nil", func() { req, _ := http.NewRequest("GET", "/", nil) expire := time.Now().AddDate(0, 0, 1) cookie := http.Cookie{ Name: "clientId", Value: "", Path: "/", Domain: "localhost", Expires: expire, } req.AddCookie(&cookie) a := getAccount(req, models.Channel_KODING_NAME) So(a, ShouldNotBeNil) So(a.Id, ShouldBeZeroValue) }) Convey("if session doesnt have username, should return nil", func() { ses, err := modelhelper.CreateSessionForAccount("", groupName) So(err, ShouldBeNil) So(ses, ShouldNotBeNil) req, _ := http.NewRequest("GET", "/", nil) expire := time.Now().AddDate(0, 0, 1) cookie := http.Cookie{ Name: "clientId", Value: ses.ClientId, Path: "/", Domain: "localhost", Expires: expire, } req.AddCookie(&cookie) a := getAccount(req, models.Channel_KODING_NAME) So(a, ShouldNotBeNil) So(a.Id, ShouldBeZeroValue) }) Convey("if session is valid, should return account", func() { acc, err := models.CreateAccountInBothDbs() So(err, ShouldBeNil) So(acc, ShouldNotBeNil) ses, err := modelhelper.CreateSessionForAccount(acc.Nick, groupName) So(err, ShouldBeNil) So(ses, ShouldNotBeNil) req, _ := http.NewRequest("GET", "/", nil) expire := time.Now().AddDate(0, 0, 1) cookie := http.Cookie{ Name: "clientId", Value: ses.ClientId, Path: "/", Domain: "localhost", Expires: expire, } req.AddCookie(&cookie) res := getAccount(req, models.Channel_KODING_NAME) So(res, ShouldNotBeNil) So(acc.Id, ShouldEqual, res.Id) }) }) Convey("while making sure account", t, func() { Convey("if account is not in postgres", func() { nick := models.RandomName() oldAcc := &kodingmodels.Account{ Id: bson.NewObjectId(), Profile: kodingmodels.AccountProfile{ Nickname: nick, }, } err := modelhelper.CreateAccount(oldAcc) So(err, ShouldBeNil) oldUser := &kodingmodels.User{ ObjectId: bson.NewObjectId(), Password: nick, Salt: nick, Name: nick, Email: nick + "@koding.com", EmailFrequency: &kodingmodels.EmailFrequency{}, } err = modelhelper.CreateUser(oldUser) So(err, ShouldBeNil) groupName := models.RandomGroupName() _, err = makeSureAccount(groupName, nick) So(err, ShouldBeNil) Convey("should create it in postgres", func() { a := models.NewAccount() err = a.ByNick(nick) So(err, ShouldBeNil) So(a.OldId, ShouldEqual, oldAcc.Id.Hex()) Convey("should set socialAPI id in mongo", func() { oldAccFromDB, err := modelhelper.GetAccount(nick) So(err, ShouldBeNil) So(oldAccFromDB.SocialApiId, ShouldEqual, strconv.FormatInt(a.Id, 10)) }) }) }) Convey("if account is in postgres", func() { acc, err := models.CreateAccountInBothDbs() So(err, ShouldBeNil) So(acc, ShouldNotBeNil) groupName := models.RandomGroupName() _, err = makeSureAccount(groupName, acc.Nick) So(err, ShouldBeNil) Convey("should be in postgres", func() { a := models.NewAccount() err = a.ByNick(acc.Nick) So(err, ShouldBeNil) So(a.OldId, ShouldEqual, acc.OldId) Convey("should have socialAPI set", func() { oldAccFromDB, err := modelhelper.GetAccount(acc.Nick) So(err, ShouldBeNil) So(oldAccFromDB.SocialApiId, ShouldEqual, strconv.FormatInt(a.Id, 10)) }) }) }) }) Convey("while making sure group membership", t, func() { Convey("if account is not not a member", func() { account := models.CreateAccountWithTest() requester := models.CreateAccountWithTest() groupChannel := models.CreateTypedPublicChannelWithTest(account.Id, models.Channel_TYPE_GROUP) err := makeSureMembership(groupChannel, requester.Id) So(err, ShouldBeNil) Convey("should add as participant", func() { status, err := groupChannel.IsParticipant(requester.Id) So(err, ShouldBeNil) So(status, ShouldBeTrue) Convey("if account is a member", func() { err := makeSureMembership(groupChannel, requester.Id) So(err, ShouldBeNil) Convey("should be a participant", func() { status, err := groupChannel.IsParticipant(requester.Id) So(err, ShouldBeNil) So(status, ShouldBeTrue) }) }) }) }) }) }