func (pc PagesController) genCommentIndexResponse(curUser *CurrentUserInfo, wikiId string, pageId string, commentList *wikit.CommentIndexViewResponse) CommentIndexResponse { commentsUri := pc.genPageUri(wikiId, pageId) + "/comments" userRoles := curUser.User.Roles dbName := "wiki_" + wikiId admin := util.HasRole(userRoles, AdminRole(dbName)) || util.HasRole(userRoles, AdminRole(MainDbName())) || util.HasRole(userRoles, MasterRole()) write := util.HasRole(userRoles, WriteRole(dbName)) indexLinks := HatLinks{} indexLinks.Self = &HatLink{Href: commentsUri, Method: "GET"} if admin || write { indexLinks.Create = &HatLink{Href: commentsUri, Method: "POST"} } var entries []CommentResponse for _, com := range commentList.Rows { entries = append(entries, pc.genCommentRecordResponse(curUser, wikiId, pageId, com.Id, &com.Value)) } return CommentIndexResponse{ Links: indexLinks, TotalRows: commentList.TotalRows, Offset: commentList.Offset, Entries: CommentIndexList{ List: entries, }, } }
func (wc WikisController) genWikiLinks(userRoles []string, wikiId string, dbName string, uri string) wikiLinks { //First, add links for wikiRecord in main db links := wikiLinks{} //Now check admin rights for wiki db and add links wikiDb := "wiki_" + wikiId admin := util.HasRole(userRoles, AdminRole(wikiDb)) || util.HasRole(userRoles, AdminRole(MainDbName())) || util.HasRole(userRoles, MasterRole()) read := util.HasRole(userRoles, ReadRole(wikiDb)) write := util.HasRole(userRoles, WriteRole(wikiDb)) pageUri := uri + "/pages" links.Self = &HatLink{Href: uri, Method: "GET"} if admin || read || write { links.PageIndex = &HatLink{Href: pageUri, Method: "GET"} } if admin || write { links.Update = &HatLink{Href: uri, Method: "PUT"} links.CreatePage = &HatLink{Href: pageUri, Method: "POST"} } if admin { links.Delete = &HatLink{Href: uri, Method: "DELETE"} } return links }
//Revoke user access func (um *UserManager) RevokeRole(id string, revokeRequest *RoleRequest, curUser *CurrentUserInfo) (string, error) { theUser := curUser.User //Make sure user is an admin of the resource being requested resourceDbName := resourceDbName(revokeRequest) if !util.HasRole(theUser.Roles, AdminRole(MainDbName())) && !util.HasRole(theUser.Roles, AdminRole(resourceDbName)) { //Not an admin return "", NotAdminError() } //Fetch the user userDb := Connection.SelectDB(UserDbName, AdminAuth) readUser := new(User) rev, err := userDb.Read(UserPrefix+id, readUser, nil) if err != nil { return "", err } //validate the role request if revokeRequest.validate() == false { return "", BadRequestError() } //ok, revoke the role revokeRole := revokeRequest.roleString() rev, err = Connection.RevokeRole(id, revokeRole, AdminAuth) if err != nil { return "", err } return rev, nil }
//Get user list func (uc UsersController) list(request *restful.Request, response *restful.Response) { curUser := GetCurrentUser(request, response) if curUser == nil { Unauthenticated(request, response) return } var limit int var pageNum int limitString := request.QueryParameter("numPerPage") if limitString == "" { limit = 0 } else { ln, err := strconv.Atoi(limitString) if err != nil { log.Printf("Error: %v", err) WriteIllegalRequestError(response) return } limit = ln } pageNumString := request.QueryParameter("pageNum") if pageNumString == "" { pageNum = 1 } else { if ln, err := strconv.Atoi(pageNumString); err != nil { log.Printf("Error: %v", err) WriteIllegalRequestError(response) } else { pageNum = ln } } ulr := UserListQueryResponse{} forResource := request.QueryParameter("forResource") searchText := request.QueryParameter("searchText") var err error if forResource != "" { //Make sure the user is an admin for the given resource if !util.HasRole(curUser.User.Roles, AdminRole(forResource)) && !util.HasRole(curUser.User.Roles, AdminRole(MainDbName())) { WriteError(NotAdminError(), response) return } rolesArray := []string{AdminRole(forResource), WriteRole(forResource), ReadRole(forResource)} err = new(UserManager).GetUserListForRole( pageNum, limit, rolesArray, &ulr, curUser) } else if searchText != "" { err = new(UserManager).SearchForUsersByName(pageNum, limit, searchText, &ulr, curUser) } else { err = new(UserManager).GetUserList(pageNum, limit, &ulr, curUser) } if err != nil { WriteError(err, response) return } uir := uc.genUserListResponse(curUser, &ulr) SetAuth(response, curUser.Auth) response.WriteEntity(uir) }
//Create a normal user func (um *UserManager) Create(newUser *User, curUser *CurrentUserInfo) (string, error) { //Who am I? theUser := curUser.User //check for admin if !util.HasRole(theUser.Roles, AdminRole(MainDbName())) && !util.HasRole(theUser.Roles, MasterRole()) { return "", NotAdminError() } //ok, now create the user err := um.validateUser(newUser) if err != nil { return "", err } newUser.Roles = []string{ReadRole(MainDbName()), AllUsersRole()} newUser.Type = "user" namestring := UserPrefix + newUser.UserName nowTime := time.Now().UTC() newUser.CreatedAt = nowTime newUser.ModifiedAt = nowTime userDb := Connection.SelectDB(UserDbName, AdminAuth) log.Printf("Creating new user account for: %v", newUser.UserName) return userDb.Save(newUser, namestring, "") }
//Create usual links for an index func GenIndexLinks(userRoles []string, dbName string, uri string) HatLinks { links := HatLinks{} admin := util.HasRole(userRoles, AdminRole(dbName)) write := util.HasRole(userRoles, WriteRole(dbName)) //Generate the self link links.Self = &HatLink{Href: uri, Method: "GET"} if admin || write { links.Create = &HatLink{Href: uri, Method: "POST"} } return links }
func (fc FileController) genFileRecordLinks(userRoles []string, wikiDb string, uri string) fileLinks { links := fileLinks{} admin := util.HasRole(userRoles, AdminRole(wikiDb)) write := util.HasRole(userRoles, WriteRole(wikiDb)) links.Self = &HatLink{Href: uri, Method: "GET"} links.GetAttachment = &HatLink{Href: uri + "/content", Method: "GET"} if admin || write { links.Update = &HatLink{Href: uri, Method: "PUT"} links.Delete = &HatLink{Href: uri, Method: "DELETE"} links.SaveAttachment = &HatLink{Href: uri + "/content", Method: "PUT"} } return links }
//Create the basic CRUD links for a resource record func GenRecordLinks(userRoles []string, dbName string, uri string) HatLinks { links := HatLinks{} //Admin can be a resource admin OR a site admin/master admin := util.HasRole(userRoles, AdminRole(dbName)) || util.HasRole(userRoles, AdminRole(MainDbName())) || util.HasRole(userRoles, MasterRole()) write := util.HasRole(userRoles, WriteRole(dbName)) //Generate the self link links.Self = &HatLink{Href: uri, Method: "GET"} if admin || write { links.Update = &HatLink{Href: uri, Method: "PUT"} links.Delete = &HatLink{Href: uri, Method: "DELETE"} } return links }
//Update a user func (um *UserManager) Update(id string, rev string, updatedUser *User, curUser *CurrentUserInfo) (string, error) { //Who am I? theUser := curUser.User var auth couchdb.Auth //make sure Id matches the user object if id != updatedUser.UserName { return "", BadRequestError() } //check for admin if util.HasRole(theUser.Roles, AdminRole(MainDbName())) || util.HasRole(theUser.Roles, MasterRole()) { auth = AdminAuth } else { auth = curUser.Auth } if err := um.validateUser(updatedUser); err != nil { return "", err } userDb := Connection.SelectDB(UserDbName, auth) //pull the user record namestring := UserPrefix + id //readUser := FullUserRecord{} var userData interface{} _, err := userDb.Read(namestring, &userData, nil) if err != nil { return "", err } readUser := userData.(map[string]interface{}) //Update the user parameters of the read user //We do this instead of just pushing the updated user to CouchDB, //because the updated user doesn't contain password information, //and we don't want to wipe away the password. nowTime := time.Now().UTC() readUser["modifiedAt"] = nowTime readUser["userPublic"] = updatedUser.Public readUser["userName"] = updatedUser.UserName readUser["passwordReset"] = updatedUser.PassResetToken //And save the updated user uRev, err := userDb.Save(&readUser, namestring, rev) if err != nil { return "", err } //Censor the password //updatedUser.Password = "" return uRev, nil }
//Get a user func (um *UserManager) Read(id string, user *User, curUser *CurrentUserInfo) (string, error) { //Who am I? theUser := curUser.User readUser := User{} if util.HasRole(theUser.Roles, AdminRole(MainDbName())) { //This is an admin userDb := Connection.SelectDB(UserDbName, AdminAuth) rev, err := userDb.Read(UserPrefix+id, &readUser, nil) if err != nil { return "", err } else { *user = readUser return rev, nil } } else { userDb := Connection.SelectDB(UserDbName, curUser.Auth) if rev, err := userDb.Read(UserPrefix+id, &readUser, nil); err != nil { return "", err } else { *user = readUser return rev, nil } } }
//Create a new wiki func (wm *WikiManager) Create(id string, wr *WikiRecord, curUser *CurrentUserInfo) (string, error) { auth := curUser.Auth theUser := curUser.User //Verify user is authorized to create wikis mainDb := MainDbName() if !util.HasRole(theUser.Roles, AdminRole(mainDb)) && !util.HasRole(theUser.Roles, WriteRole(mainDb)) { return "", NotAdminError() } owner := theUser.UserName //Add an entry for this wiki to the Main db wr.Id = id wr.Slug = slugification.Slugify(wr.Name) wr.CreatedAt = time.Now().UTC() wr.ModifiedAt = time.Now().UTC() wr.Type = "wiki_record" if err := wr.Validate(); err != nil { return "", err } cDb := Connection.SelectDB(mainDb, auth) log.Printf("Adding wiki entry %v to db %v", id, mainDb) rev, err := cDb.Save(&wr, id, "") //Check for duplicate slugs err = wm.checkForDuplicateSlug(wr.Slug) if err != nil { //Delete the wiki record we just created cDb.Delete(id, rev) return "", err } //Create the Wiki log.Printf("Creating Wiki: %v", id) err = wikit.CreateWiki(Connection, AdminAuth, owner, WikiDbName(id)) if err != nil { //Delete the wiki record from maindb cDb.Delete(id, rev) return "", err } //Set Guest Acess if err := wm.setGuestAccess(id, wr, auth); err != nil { return rev, err } //wr.Id = id return rev, nil }
//Generates the Links for a UserAvatar Record Response func (ac AvatarController) genAvatarRecordLinks(user *User, userId string, uri string) avatarLinks { links := avatarLinks{} userRoles := user.Roles admin := util.HasRole(userRoles, AdminRole(MainDbName())) || util.HasRole(userRoles, MasterRole()) write := user.UserName == userId links.Self = &HatLink{Href: uri, Method: "GET"} links.GetLargeAvatar = &HatLink{Href: uri + "/image", Method: "GET"} links.GetThumbnailAvatar = &HatLink{Href: uri + "/thumbnail", Method: "GET"} if admin || write { links.Update = &HatLink{Href: uri, Method: "PUT"} links.Delete = &HatLink{Href: uri, Method: "DELETE"} links.SaveImage = &HatLink{Href: uri + "/image", Method: "PUT"} } return links }
// Permissions are a bit different for comments, so we need a custom function func (pc PagesController) genCommentRecordLinks(curUser *CurrentUserInfo, dbName string, commentUri string, commentAuthor string) HatLinks { links := HatLinks{} userRoles := curUser.User.Roles admin := util.HasRole(userRoles, AdminRole(dbName)) || util.HasRole(userRoles, AdminRole(MainDbName())) || util.HasRole(userRoles, MasterRole()) ownComment := commentAuthor == curUser.User.UserName //Generate the self link links.Self = &HatLink{Href: commentUri, Method: "GET"} //Update links if admin || ownComment { links.Update = &HatLink{Href: commentUri, Method: "PUT"} links.Delete = &HatLink{Href: commentUri, Method: "DELETE"} } return links }
//Delete a User Avatar Record func (uam *UserAvatarManager) Delete(id string, curUser *CurrentUserInfo) (string, error) { theUser := curUser.User var auth couchdb.Auth if util.HasRole(theUser.Roles, AdminRole(MainDbName())) || util.HasRole(theUser.Roles, MasterRole()) { auth = AdminAuth } else { auth = curUser.Auth } avatarDb := Connection.SelectDB(AvatarDbName(), auth) //Fetch the record avatarRecord := new(UserAvatar) rev, err := avatarDb.Read(id, avatarRecord, nil) if err != nil { return "", err } return avatarDb.Delete(id, rev) }
//Save User Avatar Record func (uam *UserAvatarManager) Save(id string, rev string, avatar *UserAvatar, curUser *CurrentUserInfo) (string, error) { nowTime := time.Now().UTC() if rev == "" { avatar.CreatedAt = nowTime } avatar.ModifiedAt = nowTime var auth couchdb.Auth //check for admin if util.HasRole(curUser.Roles, AdminRole(MainDbName())) || util.HasRole(curUser.Roles, MasterRole()) { auth = AdminAuth } else { auth = curUser.Auth } avatarDb := Connection.SelectDB(AvatarDbName(), auth) return avatarDb.Save(avatar, id, rev) }
// Change a user's password func (um *UserManager) ChangePassword(id string, rev string, cpr *ChangePasswordRequest, curUser *CurrentUserInfo) (string, error) { theUser := curUser.User var auth couchdb.Auth //check for admin isAdmin := util.HasRole(theUser.Roles, AdminRole(MainDbName())) || util.HasRole(theUser.Roles, MasterRole()) if isAdmin { auth = AdminAuth } else { auth = curUser.Auth } //Must we validate the old password? if !isAdmin || (isAdmin && theUser.UserName == id) { //yes, let's use the old password to do this thing auth = &couchdb.BasicAuth{Username: id, Password: cpr.OldPassword} } //validate password err := um.validatePassword(cpr.NewPassword) if err != nil { return "", err } userDb := Connection.SelectDB(UserDbName, auth) //pull the user record namestring := UserPrefix + id var userData interface{} _, err = userDb.Read(namestring, &userData, nil) if err != nil { return "", err } readUser := userData.(map[string]interface{}) //Update JUST the password (and modified time) nowTime := time.Now().UTC() readUser["modifiedAt"] = nowTime readUser["password"] = cpr.NewPassword //Save the updated user uRev, err := userDb.Save(&readUser, namestring, rev) if err != nil { return "", err } return uRev, nil }
//Grant a role to a user func (um *UserManager) GrantRole(id string, grantRequest *RoleRequest, curUser *CurrentUserInfo) (string, error) { newRole := grantRequest.roleString() //Who am I? theUser := curUser.User //Make sure user is an admin of the resource being requested resourceDbName := resourceDbName(grantRequest) if !util.HasRole(theUser.Roles, AdminRole(MainDbName())) && !util.HasRole(theUser.Roles, MasterRole()) && !util.HasRole(theUser.Roles, AdminRole(resourceDbName)) { //Not an admin return "", NotAdminError() } //Are we trying to grant the site admin role? //If so, curUser must be a master user if newRole == AdminRole(MainDbName()) && !util.HasRole(theUser.Roles, MasterRole()) { return "", NotAdminError() } //Fetch the user userDb := Connection.SelectDB(UserDbName, AdminAuth) readUser := new(User) rev, err := userDb.Read(UserPrefix+id, readUser, nil) if err != nil { return "", err } //validate the role request if grantRequest.validate() == false { return "", BadRequestError() } //All is well, grant the role rev, err = Connection.GrantRole(id, newRole, AdminAuth) if err != nil { return "", err } return rev, nil }
func (pm *PageManager) allowedToUpdateComment(wiki string, commentId string, curUser *CurrentUserInfo) bool { userName := curUser.User.UserName userRoles := curUser.User.Roles auth := curUser.Auth theWiki := wikit.SelectWiki(Connection, wikiDbString(wiki), auth) //First, we need to read the comment record comment := wikit.Comment{} _, err := theWiki.ReadComment(commentId, &comment) if err != nil { return false } //Only admins and the original comment author may update/delete isAdmin := util.HasRole(userRoles, AdminRole(wiki)) || util.HasRole(userRoles, AdminRole(MainDbName())) || util.HasRole(userRoles, MasterRole()) if comment.Author == userName || isAdmin { return true } else { return false } }
// Generate links for a user record response func (uc UsersController) genUserRecordLinks(userRoles []string, userId string, curUserId string, uri string) HatLinks { links := HatLinks{} dbName := MainDbName() admin := util.HasRole(userRoles, AdminRole(dbName)) //Write := util.HasRole(userRoles, WriteRole(dbName)) self := func() bool { if curUserId == userId { return true } else { return false } }() links.Self = &HatLink{Href: uri, Method: "GET"} if admin || self { links.Update = &HatLink{Href: uri, Method: "PUT"} } return links }
//Delete a user func (um *UserManager) Delete(id string, curUser *CurrentUserInfo) (string, error) { //Who am I? theUser := curUser.User //check for admin if !util.HasRole(theUser.Roles, AdminRole(MainDbName())) { return "", NotAdminError() } //pull the user record namestring := UserPrefix + id readUser := new(User) rev, err := um.Read(id, readUser, curUser) if err != nil { return "", err } //Do the delete theDb := Connection.SelectDB(UserDbName, AdminAuth) return theDb.Delete(namestring, rev) }
//Delete a wiki record and the associated wiki database func (wm *WikiManager) Delete(id string, curUser *CurrentUserInfo) error { //Who am I? theUser := curUser.User auth := curUser.Auth mainDb := MainDbName() cDb := Connection.SelectDB(mainDb, auth) //Check for admin if !util.HasRole(theUser.Roles, AdminRole(mainDb)) { return NotAdminError() } //Fetch the wiki record wikiRecord := new(WikiRecord) _, err := cDb.Read(id, wikiRecord, nil) if err != nil { return err } /*if wikiRecord.Id != id { return errors.New("WikiRecord doesn't match Database Id") }*/ err = DeleteDb(WikiDbName(id)) if err != nil { return err } delFunc := func() error { rev, err := cDb.Read(id, wikiRecord, nil) _, err = cDb.Delete(id, rev) if err != nil { return err } else { return nil } } err = util.Retry(3, delFunc) if err != nil { return err } return nil }
func TestUsers(t *testing.T) { setup() defer services.DeleteDb(services.MainDb) smithUser := func() *entities.CurrentUserInfo { smithAuth := &couchdb.BasicAuth{Username: "******", Password: "******"} smith, err := services.GetUserFromAuth(smithAuth) if err != nil { t.Error(err) return &entities.CurrentUserInfo{} } return &entities.CurrentUserInfo{ Auth: smithAuth, User: smith, } } //after test cleanup defer func() { getSmithUser := func() *entities.CurrentUserInfo { return smithUser() } um.Delete("Steven.Smith", getSmithUser()) }() Convey("Given a new account registration", t, func() { user := entities.User{ UserName: "******", Password: "******", Public: entities.UserPublic{ LastName: "Smith", FirstName: "Steven", }, } registration := user_service.Registration{ NewUser: user, } Convey("When the new user is registered", func() { rev, err := um.SetUp(®istration) Convey("The revision should be set and the error should be nil", func() { So(err, ShouldBeNil) So(rev, ShouldNotEqual, "") t.Logf("New user revision: %v", rev) }) }) Convey("When a new user for the account is created", func() { subUser := entities.User{ UserName: "******", Password: "******", Public: entities.UserPublic{ LastName: "Smith", FirstName: "Sally", }, } rev, err := um.Create(&subUser, smithUser()) Convey("The revision should be set and the error should be nil", func() { So(err, ShouldBeNil) So(rev, ShouldNotEqual, "") }) Convey("The user should have the appropriate roles", func() { So(util.HasRole(subUser.Roles, "all_users"), ShouldEqual, true) }) }) Convey("When the user is updated", func() { auth := couchdb.BasicAuth{Username: "******", Password: "******"} updateUser := entities.User{} rev, err := um.Read("Sally.Smith", &updateUser, smithUser()) So(err, ShouldBeNil) curUser := entities.CurrentUserInfo{ User: &updateUser, Auth: &auth, } updateUser.Public.MiddleName = "Marie" rev, err = um.Update("Sally.Smith", rev, &updateUser, &curUser) Convey("Error should be nil and the revision should be set", func() { So(err, ShouldBeNil) So(rev, ShouldNotEqual, "") }) rev, err = um.Read("Sally.Smith", &updateUser, smithUser()) Convey("The user's password should still be valid", func() { So(err, ShouldBeNil) So(rev, ShouldNotEqual, "") }) }) Convey("When the user's password is changed", func() { auth := couchdb.BasicAuth{Username: "******", Password: "******"} updateUser := entities.User{} rev, err := um.Read("Sally.Smith", &updateUser, smithUser()) So(err, ShouldBeNil) curUser := entities.CurrentUserInfo{ User: &updateUser, Auth: &auth, } newPassword := "******" cpr := user_service.ChangePasswordRequest{ NewPassword: newPassword, OldPassword: "******", } rev, err = um.ChangePassword("Sally.Smith", rev, &cpr, &curUser) Convey("Error should be nil and the revision should be set", func() { So(err, ShouldBeNil) So(rev, ShouldNotEqual, "") }) rev, err = um.Read("Sally.Smith", &updateUser, &curUser) Convey("Old password should NOT work", func() { So(err, ShouldNotBeNil) }) curUser.Auth = &couchdb.BasicAuth{Username: "******", Password: "******"} rev, err = um.Read("Sally.Smith", &updateUser, &curUser) Convey("New password should work", func() { So(err, ShouldBeNil) So(rev, ShouldNotEqual, "") }) }) Convey("When a user is granted a role", func() { curUser := smithUser() roleRequest := user_service.RoleRequest{ ResourceType: "main", ResourceId: "", AccessType: "write", } rev, err := um.GrantRole("Sally.Smith", &roleRequest, curUser) Convey("The revision should be set and the error should be nil", func() { So(err, ShouldBeNil) So(rev, ShouldNotEqual, "") }) Convey("User should have her new role", func() { readUser := new(entities.User) _, err := um.Read("Sally.Smith", readUser, smithUser()) So(err, ShouldBeNil) t.Logf("Sally's Record: %v", readUser) searchRole := "main_" + ":write" searchRoleFound := false if readUser.Roles[2] == searchRole { searchRoleFound = true } So(searchRoleFound, ShouldEqual, true) }) }) Convey("When a user has a role revoked", func() { curUser := smithUser() roleRequest := user_service.RoleRequest{ ResourceType: "main", ResourceId: "", AccessType: "write", } rev, err := um.RevokeRole("Sally.Smith", &roleRequest, curUser) Convey("The revision should be set and the error should be nil", func() { So(err, ShouldBeNil) So(rev, ShouldNotEqual, "") }) Convey("User should no longer have her role", func() { readUser := new(entities.User) _, err := um.Read("Sally.Smith", readUser, smithUser()) So(err, ShouldBeNil) searchRole := "main" + ":write" searchRoleFound := false if len(readUser.Roles) > 1 && readUser.Roles[1] == searchRole { searchRoleFound = true } So(searchRoleFound, ShouldEqual, false) }) }) Convey("When the user list is requested", func() { userList := user_service.UserListQueryResponse{} err := um.GetUserList(1, 5, &userList, smithUser()) Convey("Error should be nil and we should have some results", func() { So(err, ShouldBeNil) So(len(userList.Rows) >= 2, ShouldBeTrue) t.Logf("UserListResponse: %v", userList) }) }) Convey("When a user search is requested", func() { userList := user_service.UserListQueryResponse{} err := um.SearchForUsersByName(1, 5, "Smith", &userList, smithUser()) Convey("Error should be nil and we should have some results", func() { So(err, ShouldBeNil) So(len(userList.Rows), ShouldEqual, 2) t.Logf("UserListResponse: %v", userList) }) }) Convey("When the user is read", func() { readUser := entities.User{} rev, err := um.Read(user.UserName, &readUser, smithUser()) Convey("The revision should be set and the error should be nil", func() { So(err, ShouldBeNil) So(rev, ShouldNotEqual, "") }) Convey("The user data should be set", func() { So(readUser.CreatedAt, ShouldNotBeNil) So(readUser.UserName, ShouldEqual, "Steven.Smith") }) }) Convey("When the user by roles list is requested", func() { userList := user_service.UserListQueryResponse{} err := um.GetUserListForRole(1, 5, []string{"all_users"}, &userList, smithUser()) Convey("The error should be nil and we should have some results", func() { So(err, ShouldBeNil) t.Logf("Response: %v", userList) }) }) Convey("When a user password reset is requested", func() { err := um.RequestPasswordReset("Steven.Smith") Convey("The error should indicate no notifcation services are present", func() { So(err.Error(), ShouldEqual, "No notifications services listed!") }) }) Convey("When the user is deleted", func() { rev, err := um.Delete("Sally.Smith", smithUser()) Convey("The revision should be set and the error should be nil", func() { So(err, ShouldBeNil) So(rev, ShouldNotEqual, "") t.Logf("Deleted User rev: %v", rev) }) }) }) }
func TestUsers(t *testing.T) { setup() defer database.DeleteDb(database.MainDb) smithUser := func() *entities.CurrentUserInfo { smithAuth := &couchdb.BasicAuth{Username: "******", Password: "******"} smith, err := database.GetUserFromAuth(smithAuth) if err != nil { t.Error(err) return &entities.CurrentUserInfo{} } return &entities.CurrentUserInfo{ Auth: smithAuth, User: smith, } } //after test cleanup defer func() { getSmithUser := func() *entities.CurrentUserInfo { return smithUser() } um.Delete("Steven.Smith", getSmithUser()) }() //Create a new master user user := entities.User{ UserName: "******", Password: "******", Public: entities.UserPublic{ LastName: "Smith", FirstName: "Steven", }, } registration := user_service.Registration{ NewUser: user, } rev, err := um.SetUp(®istration) if err != nil { t.Error(err) } if rev == "" { t.Error("rev is empty!") } t.Logf("New user revision: %v", rev) //Create a new subuser subUser := entities.User{ UserName: "******", Password: "******", Public: entities.UserPublic{ LastName: "Smith", FirstName: "Sally", }, } rev, err = um.Create(&subUser, smithUser()) if err != nil { t.Error(err) } if rev == "" { t.Error("rev is empty!") } if !util.HasRole(subUser.Roles, "all_users") { t.Error("user doesn't have all_users role!") } //Update user auth := couchdb.BasicAuth{Username: "******", Password: "******"} updateUser := entities.User{} rev, err = um.Read("Sally.Smith", &updateUser, smithUser()) if err != nil { t.Error(err) } curUser := entities.CurrentUserInfo{ User: &updateUser, Auth: &auth, } updateUser.Public.MiddleName = "Marie" rev, err = um.Update("Sally.Smith", rev, &updateUser, &curUser) if err != nil { t.Error(err) } if rev == "" { t.Error("rev is empty!") } rev, err = um.Read("Sally.Smith", &updateUser, smithUser()) if err != nil { t.Error(err) } if rev == "" { t.Error("rev is empty!") } //Change password auth = couchdb.BasicAuth{Username: "******", Password: "******"} updateUser = entities.User{} rev, err = um.Read("Sally.Smith", &updateUser, smithUser()) if err != nil { t.Error(err) } curUser = entities.CurrentUserInfo{ User: &updateUser, Auth: &auth, } newPassword := "******" cpr := user_service.ChangePasswordRequest{ NewPassword: newPassword, OldPassword: "******", } rev, err = um.ChangePassword("Sally.Smith", rev, &cpr, &curUser) if err != nil { t.Error(err) } if rev == "" { t.Error("rev is empty!") } rev, err = um.Read("Sally.Smith", &updateUser, &curUser) if err == nil { t.Error("Old password should not have worked!") } curUser.Auth = &couchdb.BasicAuth{Username: "******", Password: "******"} rev, err = um.Read("Sally.Smith", &updateUser, &curUser) if err != nil { t.Error(err) } if rev == "" { t.Error("rev is empty!") } //Grant role curUser = *smithUser() roleRequest := user_service.RoleRequest{ ResourceType: "main", ResourceId: "", AccessType: "write", } rev, err = um.GrantRole("Sally.Smith", &roleRequest, &curUser) if err != nil { t.Error(err) } if rev == "" { t.Error("rev is empty!") } readUser := new(entities.User) _, err = um.Read("Sally.Smith", readUser, smithUser()) if err != nil { t.Error(err) } t.Logf("Sally's Record: %v", readUser) searchRole := "main_" + ":write" searchRoleFound := false if readUser.Roles[2] == searchRole { searchRoleFound = true } if !searchRoleFound { t.Error("Role not found!") } //Revoke role curUser = *smithUser() roleRequest = user_service.RoleRequest{ ResourceType: "main", ResourceId: "", AccessType: "write", } rev, err = um.RevokeRole("Sally.Smith", &roleRequest, &curUser) if err != nil { t.Error(err) } if rev == "" { t.Error("rev is empty!") } readUser = new(entities.User) _, err = um.Read("Sally.Smith", readUser, smithUser()) if err != nil { t.Error(err) } searchRole = "main" + ":write" searchRoleFound = false if len(readUser.Roles) > 1 && readUser.Roles[1] == searchRole { searchRoleFound = true } if searchRoleFound { t.Error("Role should not have been found!") } //User List userList := user_service.UserListQueryResponse{} err = um.GetUserList(1, 5, &userList, smithUser()) if err != nil { t.Error(err) } if !(len(userList.Rows) >= 2) { t.Error("User list should be greater than or equal to 2!") } t.Logf("UserListResponse: %v", userList) //User search userList = user_service.UserListQueryResponse{} err = um.SearchForUsersByName(1, 5, "Smith", &userList, smithUser()) if err != nil { t.Error(err) } if len(userList.Rows) != 2 { t.Errorf("Userlist should be length 2 was %v", len(userList.Rows)) } t.Logf("UserListResponse: %v", userList) //Read user readUser = &entities.User{} rev, err = um.Read(user.UserName, readUser, smithUser()) if err != nil { t.Error(err) } if rev == "" { t.Error("Rev is empty!") } if readUser.UserName != "Steven.Smith" { t.Errorf("username should be Seteven.Smith, was %v", readUser.UserName) } //User by Roles list userList = user_service.UserListQueryResponse{} err = um.GetUserListForRole(1, 5, []string{"all_users"}, &userList, smithUser()) if err != nil { t.Error(err) } t.Logf("Response: %v", userList) //Password reset err = um.RequestPasswordReset("Steven.Smith") if err.Error() != "No notifications services listed!" { t.Error("Error is wrong") } //Delete user rev, err = um.Delete("Sally.Smith", smithUser()) if err != nil { t.Error(err) } if rev == "" { t.Error("Rev is empty!") } t.Logf("Deleted User rev: %v", rev) }