Esempio n. 1
0
// 返回info.UserAndBlog
func (this *UserService) MapUserAndBlogByUserIds(userIds []bson.ObjectId) map[string]info.UserAndBlog {
	users := []info.User{}
	db.ListByQ(db.Users, bson.M{"_id": bson.M{"$in": userIds}}, &users)

	userBlogs := []info.UserBlog{}
	db.ListByQ(db.UserBlogs, bson.M{"_id": bson.M{"$in": userIds}}, &userBlogs)

	userBlogMap := make(map[bson.ObjectId]info.UserBlog, len(userBlogs))
	for _, user := range userBlogs {
		userBlogMap[user.UserId] = user
	}

	userAndBlogMap := make(map[string]info.UserAndBlog, len(users))

	for _, user := range users {
		this.setUserLogo(&user)

		userBlog, ok := userBlogMap[user.UserId]
		if !ok {
			continue
		}

		userAndBlogMap[user.UserId.Hex()] = info.UserAndBlog{
			UserId:    user.UserId,
			Username:  user.Username,
			Email:     user.Email,
			Logo:      user.Logo,
			BlogTitle: userBlog.Title,
			BlogLogo:  userBlog.Logo,
			BlogUrl:   blogService.GetUserBlogUrl(&userBlog, user.Username),
		}
	}
	return userAndBlogMap
}
Esempio n. 2
0
// 复制笔记时需要复制附件
// noteService调用, 权限已判断
func (this *AttachService) CopyAttachs(noteId, toNoteId, toUserId string) bool {
	attachs := []info.Attach{}
	db.ListByQ(db.Attachs, bson.M{"NoteId": bson.ObjectIdHex(noteId)}, &attachs)

	// 复制之
	toNoteIdO := bson.ObjectIdHex(toNoteId)
	for _, attach := range attachs {
		attach.AttachId = ""
		attach.NoteId = toNoteIdO

		// 文件复制一份
		_, ext := SplitFilename(attach.Name)
		newFilename := NewGuid() + ext
		dir := "files/" + toUserId + "/attachs"
		filePath := dir + "/" + newFilename
		err := os.MkdirAll(revel.BasePath+"/"+dir, 0755)
		if err != nil {
			return false
		}
		_, err = CopyFile(revel.BasePath+"/"+attach.Path, revel.BasePath+"/"+filePath)
		if err != nil {
			return false
		}
		attach.Name = newFilename
		attach.Path = filePath

		this.AddAttach(attach)
	}

	return true
}
Esempio n. 3
0
// 得到笔记本分享给的groups
func (this *ShareService) GetNotebookShareGroups(notebookId, userId string) []info.ShareNotebook {
	// 得到分组s
	groups := groupService.GetGroups(userId)

	// 得到有分享的分组
	shares := []info.ShareNotebook{}
	db.ListByQ(db.ShareNotebooks,
		bson.M{"NotebookId": bson.ObjectIdHex(notebookId), "UserId": bson.ObjectIdHex(userId), "ToGroupId": bson.M{"$exists": true}}, &shares)
	mapShares := map[bson.ObjectId]info.ShareNotebook{}
	for _, share := range shares {
		mapShares[share.ToGroupId] = share
	}
	LogJ(shares)

	// 所有的groups都有share, 但没有share的group没有shareId
	shares2 := make([]info.ShareNotebook, len(groups))
	for i, group := range groups {
		share, ok := mapShares[group.GroupId]
		if !ok {
			share = info.ShareNotebook{}
		}
		share.ToGroup = group
		shares2[i] = share
	}

	return shares2
}
Esempio n. 4
0
// 得到用户的所有*被*共享的Notebook
// 1 得到别人共享给我的所有notebooks
// 2 按parent进行层次化
// 3 每个层按seq进行排序
// 4 按用户分组
// [ok]
func (this *ShareService) GetShareNotebooks(userId string) (info.ShareNotebooksByUser, []info.User) {
	//-------------
	// 查询HasShareNote表得到所有其它用户信息
	hasShareNotes := []info.HasShareNote{}
	db.ListByQ(db.HasShareNotes, bson.M{"ToUserId": bson.ObjectIdHex(userId)}, &hasShareNotes)

	userIds := make([]bson.ObjectId, len(hasShareNotes))
	for i, each := range hasShareNotes {
		userIds[i] = each.UserId
	}
	userInfos := userService.GetUserInfosOrderBySeq(userIds)

	//--------------------
	// 得到他们共享给我的notebooks

	shareNotebooks := []info.ShareNotebook{}
	db.ShareNotebooks.Find(bson.M{"ToUserId": bson.ObjectIdHex(userId)}).All(&shareNotebooks)

	if len(shareNotebooks) == 0 {
		return nil, userInfos
	}

	shareNotebooksLen := len(shareNotebooks)

	// 找到了所有的notbookId, 那么找notebook表得到其详细信息
	notebookIds := make([]bson.ObjectId, shareNotebooksLen)
	shareNotebooksMap := make(map[bson.ObjectId]info.ShareNotebook, shareNotebooksLen)
	for i, each := range shareNotebooks {
		// 默认的是没有notebookId的
		notebookIds[i] = each.NotebookId
		shareNotebooksMap[each.NotebookId] = each
	}

	// 1, 2
	subNotebooks := notebookService.GetNotebooksByNotebookIds(notebookIds)
	// 填充其它信息变成SubShareNotebooks
	subShareNotebooks := this.parseToSubShareNotebooks(&subNotebooks, &shareNotebooksMap)

	// 3 按用户进行分组成ShareNotebooksByUser
	shareNotebooksByUsersMap := map[bson.ObjectId][]info.ShareNotebooks{}
	// 先建立userId => []
	for _, eachSub := range subShareNotebooks {
		userId := eachSub.Notebook.UserId
		if _, ok := shareNotebooksByUsersMap[userId]; ok {
			shareNotebooksByUsersMap[userId] = append(shareNotebooksByUsersMap[userId], eachSub)
		} else {
			shareNotebooksByUsersMap[userId] = []info.ShareNotebooks{eachSub}
		}
	}
	shareNotebooksByUser := info.ShareNotebooksByUser{}
	for userId, eachShareNotebooks := range shareNotebooksByUsersMap {
		// 4, 按用户排序
		shareNotebooksByUser[userId.Hex()] = sortSubShareNotebooks(eachShareNotebooks)
	}

	return shareNotebooksByUser, userInfos
}
Esempio n. 5
0
// 得到用户共享的notebooks
// 3/19 博客不是deleted
func (this *BlogService) ListBlogNotebooks(userId string) []info.Notebook {
	notebooks := []info.Notebook{}
	orQ := []bson.M{
		bson.M{"IsDeleted": false},
		bson.M{"IsDeleted": bson.M{"$exists": false}},
	}
	db.ListByQ(db.Notebooks, bson.M{"UserId": bson.ObjectIdHex(userId), "IsBlog": true, "$or": orQ}, &notebooks)
	return notebooks
}
Esempio n. 6
0
func (this *NoteImageService) getImagesByNoteIds(noteIds []bson.ObjectId) map[string][]info.File {
	noteNoteImages := []info.NoteImage{}
	db.ListByQ(db.NoteImages, bson.M{"NoteId": bson.M{"$in": noteIds}}, &noteNoteImages)

	// 得到imageId, 再去files表查所有的Files
	imageIds := []bson.ObjectId{}

	// 图片1 => N notes
	imageIdNotes := map[string][]string{} // imageId => [noteId1, noteId2, ...]
	for _, noteImage := range noteNoteImages {
		imageId := noteImage.ImageId
		imageIds = append(imageIds, imageId)

		imageIdHex := imageId.Hex()
		noteId := noteImage.NoteId.Hex()
		if notes, ok := imageIdNotes[imageIdHex]; ok {
			imageIdNotes[imageIdHex] = append(notes, noteId)
		} else {
			imageIdNotes[imageIdHex] = []string{noteId}
		}
	}

	// 得到所有files
	files := []info.File{}
	db.ListByQ(db.Files, bson.M{"_id": bson.M{"$in": imageIds}}, &files)

	// 建立note->file关联
	noteImages := make(map[string][]info.File)
	for _, file := range files {
		fileIdHex := file.FileId.Hex() // == imageId
		// 这个fileIdHex有哪些notes呢?
		if notes, ok := imageIdNotes[fileIdHex]; ok {
			for _, noteId := range notes {
				if files, ok2 := noteImages[noteId]; ok2 {
					noteImages[noteId] = append(files, file)
				} else {
					noteImages[noteId] = []info.File{file}
				}
			}
		}
	}
	return noteImages
}
Esempio n. 7
0
// 得到用户的所有分组(包括下的所有用户)
func (this *GroupService) GetGroupsAndUsers(userId string) []info.Group {
	// 得到分组s
	groups := []info.Group{}
	db.ListByQ(db.Groups, bson.M{"UserId": bson.ObjectIdHex(userId)}, &groups)
	// 得到其下的用户
	for i, group := range groups {
		group.Users = this.GetUsers(group.GroupId.Hex())
		groups[i] = group
	}
	return groups
}
Esempio n. 8
0
// 查看note的分享信息
// 分享给了哪些用户和权限
// ShareNotes表 userId = me, noteId = ...
// 还要查看该note的notebookId分享的信息
func (this *ShareService) ListNoteShareUserInfo(noteId, userId string) []info.ShareUserInfo {
	// 得到shareNote信息, 得到所有的ToUserId
	shareNotes := []info.ShareNote{}
	db.ListByQLimit(db.ShareNotes, bson.M{"NoteId": bson.ObjectIdHex(noteId), "UserId": bson.ObjectIdHex(userId)}, &shareNotes, 100)

	if len(shareNotes) == 0 {
		return nil
	}

	shareNotesMap := make(map[bson.ObjectId]info.ShareNote, len(shareNotes))
	for _, each := range shareNotes {
		shareNotesMap[each.ToUserId] = each
	}

	toUserIds := make([]bson.ObjectId, len(shareNotes))
	for i, eachShareNote := range shareNotes {
		toUserIds[i] = eachShareNote.ToUserId
	}

	note := noteService.GetNote(noteId, userId)
	if note.NoteId == "" {
		return nil
	}

	// 查看其notebook的shareNotebooks信息
	shareNotebooks := []info.ShareNotebook{}
	db.ListByQ(db.ShareNotebooks,
		bson.M{"NotebookId": note.NotebookId, "UserId": bson.ObjectIdHex(userId), "ToUserId": bson.M{"$in": toUserIds}},
		&shareNotebooks)
	shareNotebooksMap := make(map[bson.ObjectId]info.ShareNotebook, len(shareNotebooks))
	for _, each := range shareNotebooks {
		shareNotebooksMap[each.ToUserId] = each
	}

	// 得到用户信息
	userInfos := userService.ListUserInfosByUserIds(toUserIds)

	if len(userInfos) == 0 {
		return nil
	}

	shareUserInfos := make([]info.ShareUserInfo, len(userInfos))

	for i, userInfo := range userInfos {
		_, hasNotebook := shareNotebooksMap[userInfo.UserId]
		shareUserInfos[i] = info.ShareUserInfo{ToUserId: userInfo.UserId,
			Email:             userInfo.Email,
			Perm:              shareNotesMap[userInfo.UserId].Perm,
			NotebookHasShared: hasNotebook,
		}
	}

	return shareUserInfos
}
Esempio n. 9
0
// list attachs
func (this *AttachService) ListAttachs(noteId, userId string) []info.Attach {
	attachs := []info.Attach{}
	// 判断是否有权限为笔记添加附件
	if !shareService.HasUpdateNotePerm(noteId, userId) {
		return attachs
	}

	db.ListByQ(db.Attachs, bson.M{"NoteId": bson.ObjectIdHex(noteId)}, &attachs)

	return attachs
}
Esempio n. 10
0
// 得到note的perm信息
func (this *ShareService) getNotesPerm(noteIds []bson.ObjectId, myUserId, sharedUserId string) map[bson.ObjectId]int {
	shareNotes := []info.ShareNote{}
	db.ListByQ(db.ShareNotes, bson.M{"NoteId": bson.M{"$in": noteIds}, "UserId": bson.ObjectIdHex(sharedUserId), "ToUserId": bson.ObjectIdHex(myUserId)}, &shareNotes)

	notesPerm := make(map[bson.ObjectId]int, len(shareNotes))
	for _, each := range shareNotes {
		notesPerm[each.NoteId] = each.Perm
	}

	return notesPerm
}
Esempio n. 11
0
// 用户信息即可
func (this *UserService) MapUserInfoByUserIds(userIds []bson.ObjectId) map[bson.ObjectId]info.User {
	users := []info.User{}
	db.ListByQ(db.Users, bson.M{"_id": bson.M{"$in": userIds}}, &users)

	userMap := make(map[bson.ObjectId]info.User, len(users))
	for _, user := range users {
		this.setUserLogo(&user)
		userMap[user.UserId] = user
	}
	return userMap
}
Esempio n. 12
0
// 添加了PublicTime, RecommendTime
func (this *UpgradeService) UpgradeBlog() bool {
	notes := []info.Note{}
	db.ListByQ(db.Notes, bson.M{"IsBlog": true}, &notes)

	// PublicTime, RecommendTime = UpdatedTime
	for _, note := range notes {
		if note.IsBlog && note.PublicTime.Year() < 100 {
			db.UpdateByIdAndUserIdMap2(db.Notes, note.NoteId, note.UserId, bson.M{"PublicTime": note.UpdatedTime, "RecommendTime": note.UpdatedTime})
			Log(note.NoteId.Hex())
		}
	}

	return true
}
Esempio n. 13
0
// api调用, 通过noteIds得到note's attachs, 通过noteId归类返回
func (this *AttachService) getAttachsByNoteIds(noteIds []bson.ObjectId) map[string][]info.Attach {
	attachs := []info.Attach{}
	db.ListByQ(db.Attachs, bson.M{"NoteId": bson.M{"$in": noteIds}}, &attachs)
	noteAttchs := make(map[string][]info.Attach)
	for _, attach := range attachs {
		noteId := attach.NoteId.Hex()
		if itAttachs, ok := noteAttchs[noteId]; ok {
			noteAttchs[noteId] = append(itAttachs, attach)
		} else {
			noteAttchs[noteId] = []info.Attach{attach}
		}
	}
	return noteAttchs
}
Esempio n. 14
0
// Delete note to delete attas firstly
func (this *AttachService) DeleteAllAttachs(noteId, userId string) bool {
	note := noteService.GetNoteById(noteId)
	if note.UserId.Hex() == userId {
		attachs := []info.Attach{}
		db.ListByQ(db.Attachs, bson.M{"NoteId": bson.ObjectIdHex(noteId)}, &attachs)
		for _, attach := range attachs {
			attach.Path = strings.TrimLeft(attach.Path, "/")
			os.Remove(revel.BasePath + "/" + attach.Path)
		}
		return true
	}

	return false
}
Esempio n. 15
0
// 通过ids得到users, 按id的顺序组织users
func (this *UserService) GetUserInfosOrderBySeq(userIds []bson.ObjectId) []info.User {
	users := []info.User{}
	db.ListByQ(db.Users, bson.M{"_id": bson.M{"$in": userIds}}, &users)

	usersMap := map[bson.ObjectId]info.User{}
	for _, user := range users {
		usersMap[user.UserId] = user
	}

	users2 := []info.User{}
	for _, userId := range userIds {
		if user, ok := usersMap[userId]; ok {
			users2 = append(users2, user)
		}
	}
	return users2
}
Esempio n. 16
0
// appStart时 将全局的配置从数据库中得到作为全局
func (this *ConfigService) InitGlobalConfigs() bool {
	this.GlobalAllConfigs = map[string]interface{}{}
	this.GlobalStringConfigs = map[string]string{}
	this.GlobalArrayConfigs = map[string][]string{}
	this.GlobalMapConfigs = map[string]map[string]string{}
	this.GlobalArrMapConfigs = map[string][]map[string]string{}

	this.adminUsername, _ = revel.Config.String("adminUsername")
	if this.adminUsername == "" {
		this.adminUsername = "******"
	}
	this.siteUrl, _ = revel.Config.String("site.url")

	userInfo := userService.GetUserInfoByAny(this.adminUsername)
	if userInfo.UserId == "" {
		return false
	}
	this.adminUserId = userInfo.UserId.Hex()

	configs := []info.Config{}
	db.ListByQ(db.Configs, bson.M{"UserId": userInfo.UserId}, &configs)

	for _, config := range configs {
		if config.IsArr {
			this.GlobalArrayConfigs[config.Key] = config.ValueArr
			this.GlobalAllConfigs[config.Key] = config.ValueArr
		} else if config.IsMap {
			this.GlobalMapConfigs[config.Key] = config.ValueMap
			this.GlobalAllConfigs[config.Key] = config.ValueMap
		} else if config.IsArrMap {
			this.GlobalArrMapConfigs[config.Key] = config.ValueArrMap
			this.GlobalAllConfigs[config.Key] = config.ValueArrMap
		} else {
			this.GlobalStringConfigs[config.Key] = config.ValueStr
			this.GlobalAllConfigs[config.Key] = config.ValueStr
		}
	}

	// site URL
	if s, ok := this.GlobalStringConfigs["siteUrl"]; !ok || s != "" {
		this.GlobalStringConfigs["siteUrl"] = this.siteUrl
	}

	return true
}
Esempio n. 17
0
// list attachs
func (this *AttachService) ListAttachs(noteId, userId string) []info.Attach {
	attachs := []info.Attach{}

	// 判断是否有权限为笔记添加附件, userId为空时表示是分享笔记的附件
	if userId != "" && !shareService.HasUpdateNotePerm(noteId, userId) {
		return attachs
	}

	// 笔记是否是自己的
	note := noteService.GetNoteByIdAndUserId(noteId, userId)
	if note.NoteId == "" {
		return attachs
	}

	// TODO 这里, 优化权限控制

	db.ListByQ(db.Attachs, bson.M{"NoteId": bson.ObjectIdHex(noteId)}, &attachs)

	return attachs
}
Esempio n. 18
0
// 获取包含此用户的组对象数组
// 获取该用户所属组, 和我的组
func (this *GroupService) GetGroupsContainOf(userId string) []info.Group {
	// 我的组
	myGroups := this.GetGroups(userId)
	myGroupMap := map[bson.ObjectId]bool{}

	for _, group := range myGroups {
		myGroupMap[group.GroupId] = true
	}

	// 所属组
	groupIds := this.GetBelongToGroupIds(userId)

	groups := []info.Group{}
	db.ListByQ(db.Groups, bson.M{"_id": bson.M{"$in": groupIds}}, &groups)

	for _, group := range groups {
		if !myGroupMap[group.GroupId] {
			myGroups = append(myGroups, group)
		}
	}

	return myGroups
}
Esempio n. 19
0
func (this *UpgradeService) moveTag() {
	usnI := 1
	tags := []info.Tag{}
	db.ListByQ(db.Tags, bson.M{}, &tags)
	for _, eachTag := range tags {
		tagTitles := eachTag.Tags
		now := time.Now()
		if tagTitles != nil && len(tagTitles) > 0 {
			for _, tagTitle := range tagTitles {
				noteTag := info.NoteTag{}
				noteTag.TagId = bson.NewObjectId()
				noteTag.Count = 1
				noteTag.Tag = tagTitle
				noteTag.UserId = eachTag.UserId
				noteTag.CreatedTime = now
				noteTag.UpdatedTime = now
				noteTag.Usn = usnI
				noteTag.IsDeleted = false
				db.Insert(db.NoteTags, noteTag)
				usnI++
			}
		}
	}
}
Esempio n. 20
0
// 删除tag
// 返回所有note的Usn
func (this *NoteService) UpdateNoteToDeleteTag(userId string, targetTag string) map[string]int {
	query := bson.M{"UserId": bson.ObjectIdHex(userId),
		"Tags": bson.M{"$in": []string{targetTag}}}
	notes := []info.Note{}
	db.ListByQ(db.Notes, query, &notes)
	ret := map[string]int{}
	for _, note := range notes {
		tags := note.Tags
		if tags == nil {
			continue
		}
		for i, tag := range tags {
			if tag == targetTag {
				tags = tags
				tags = append(tags[:i], tags[i+1:]...)
				break
			}
		}
		usn := userService.IncrUsn(userId)
		db.UpdateByQMap(db.Notes, bson.M{"_id": note.NoteId}, bson.M{"Usn": usn, "Tags": tags})
		ret[note.NoteId.Hex()] = usn
	}
	return ret
}
Esempio n. 21
0
// 得到用户共享的notebooks
func (this *BlogService) ListBlogNotebooks(userId string) []info.Notebook {
	notebooks := []info.Notebook{}
	db.ListByQ(db.Notebooks, bson.M{"UserId": bson.ObjectIdHex(userId), "IsBlog": true}, &notebooks)
	return notebooks
}
Esempio n. 22
0
// 仅仅得到所有分组
func (this *GroupService) GetGroups(userId string) []info.Group {
	// 得到分组s
	groups := []info.Group{}
	db.ListByQ(db.Groups, bson.M{"UserId": bson.ObjectIdHex(userId)}, &groups)
	return groups
}
Esempio n. 23
0
// 得到默认主题供选择
func (this *ThemeService) GetDefaultThemes() (themes []info.Theme) {
	themes = []info.Theme{}
	db.ListByQ(db.Themes, bson.M{"IsDefault": true}, &themes)
	return
}
Esempio n. 24
0
/*
<li>Migrate "About me" to single(a single post)</li>
<li>Add some default themes to administrator</li>
<li>Generate "UrlTitle" for all notes. "UrlTitle" is a friendly url for post</li>
<li>Generate "UrlTitle" for all notebooks</li>
<li>Generate "UrlTitle" for all singles</li>
*/
func (this *UpgradeService) UpgradeBetaToBeta2(userId string) (ok bool, msg string) {
	if configService.GetGlobalStringConfig("UpgradeBetaToBeta2") != "" {
		return false, "Leanote have been upgraded"
	}

	// 1. aboutMe -> page
	userBlogs := []info.UserBlog{}
	db.ListByQ(db.UserBlogs, bson.M{}, &userBlogs)

	for _, userBlog := range userBlogs {
		blogService.AddOrUpdateSingle(userBlog.UserId.Hex(), "", "About Me", userBlog.AboutMe)
	}

	// 2. 默认主题, 给admin用户
	themeService.UpgradeThemeBeta2()

	// 3. UrlTitles

	// 3.1 note
	notes := []info.Note{}
	db.ListByQ(db.Notes, bson.M{}, &notes)
	for _, note := range notes {
		data := bson.M{}
		noteId := note.NoteId.Hex()
		// PublicTime, RecommendTime = UpdatedTime
		if note.IsBlog && note.PublicTime.Year() < 100 {
			data["PublicTime"] = note.UpdatedTime
			data["RecommendTime"] = note.UpdatedTime
			Log("Time " + noteId)
		}
		data["UrlTitle"] = GetUrTitle(note.UserId.Hex(), note.Title, "note", noteId)
		db.UpdateByIdAndUserIdMap2(db.Notes, note.NoteId, note.UserId, data)
		Log(noteId)
	}

	// 3.2
	Log("notebook")
	notebooks := []info.Notebook{}
	db.ListByQ(db.Notebooks, bson.M{}, &notebooks)
	for _, notebook := range notebooks {
		notebookId := notebook.NotebookId.Hex()
		data := bson.M{}
		data["UrlTitle"] = GetUrTitle(notebook.UserId.Hex(), notebook.Title, "notebook", notebookId)
		db.UpdateByIdAndUserIdMap2(db.Notebooks, notebook.NotebookId, notebook.UserId, data)
		Log(notebookId)
	}

	// 3.3 single
	/*
		singles := []info.BlogSingle{}
		db.ListByQ(db.BlogSingles, bson.M{}, &singles)
		for _, single := range singles {
			singleId := single.SingleId.Hex()
			blogService.UpdateSingleUrlTitle(single.UserId.Hex(), singleId, single.Title)
			Log(singleId)
		}
	*/

	// 删除索引
	db.ShareNotes.DropIndex("UserId", "ToUserId", "NoteId")
	ok = true
	msg = "success"
	configService.UpdateGlobalStringConfig(userId, "UpgradeBetaToBeta2", "1")

	return
}
Esempio n. 25
0
func (this *UserService) ListUserInfosByEmails(emails []string) []info.User {
	users := []info.User{}
	db.ListByQ(db.Users, bson.M{"Email": bson.M{"$in": emails}}, &users)
	return users
}
Esempio n. 26
0
func (this *UserService) ListUserInfosByUserIds(userIds []bson.ObjectId) []info.User {
	users := []info.User{}
	db.ListByQ(db.Users, bson.M{"_id": bson.M{"$in": userIds}}, &users)
	return users
}
Esempio n. 27
0
// get albums
func (this *AlbumService) GetAlbums(userId string) []info.Album {
	albums := []info.Album{}
	db.ListByQ(db.Albums, bson.M{"UserId": bson.ObjectIdHex(userId)}, &albums)
	return albums
}