diff --git a/internal/core/core.go b/internal/core/core.go
index f815525b..10ae82bf 100644
--- a/internal/core/core.go
+++ b/internal/core/core.go
@@ -36,6 +36,7 @@ type DataService interface {
StickPost(post *model.Post) error
GetPostByID(id int64) (*model.Post, error)
GetPosts(conditions *model.ConditionsT, offset, limit int) ([]*model.Post, error)
+ MergePosts(posts []*model.Post) ([]*model.PostFormated, error)
GetPostCount(conditions *model.ConditionsT) (int64, error)
UpdatePost(post *model.Post) error
GetUserPostStar(postID, userID int64) (*model.PostStar, error)
@@ -70,4 +71,6 @@ type DataService interface {
GetLatestPhoneCaptcha(phone string) (*model.Captcha, error)
UsePhoneCaptcha(captcha *model.Captcha) error
SendPhoneCaptcha(phone string) error
+
+ IsFriend(userID int64, friendID int64) bool
}
diff --git a/internal/core/index.go b/internal/core/index.go
index afc02048..0188e6a2 100644
--- a/internal/core/index.go
+++ b/internal/core/index.go
@@ -5,5 +5,5 @@ import (
)
type IndexPostsService interface {
- IndexPosts(offset int, limit int) ([]*model.PostFormated, error)
+ IndexPosts(userId int64, offset int, limit int) ([]*model.PostFormated, error)
}
diff --git a/internal/core/search.go b/internal/core/search.go
index b2033cd3..823da0d3 100644
--- a/internal/core/search.go
+++ b/internal/core/search.go
@@ -1,6 +1,7 @@
package core
import (
+ "github.com/rocboss/paopao-ce/internal/model"
"github.com/rocboss/paopao-ce/pkg/zinc"
)
@@ -12,8 +13,9 @@ const (
type SearchType string
type QueryT struct {
- Query string
- Type SearchType
+ Query string
+ Visibility []model.PostVisibleT
+ Type SearchType
}
// SearchService search service interface that implement base zinc
diff --git a/internal/dao/cache_index.go b/internal/dao/cache_index.go
index b8626be9..886cdb42 100644
--- a/internal/dao/cache_index.go
+++ b/internal/dao/cache_index.go
@@ -14,7 +14,7 @@ var (
errNotExist = errors.New("index posts cache not exist")
)
-func newSimpleCacheIndexServant(getIndexPosts func(offset, limit int) ([]*model.PostFormated, error)) *simpleCacheIndexServant {
+func newSimpleCacheIndexServant(getIndexPosts indexPostsFunc) *simpleCacheIndexServant {
s := conf.SimpleCacheIndexSetting
cacheIndex := &simpleCacheIndexServant{
getIndexPosts: getIndexPosts,
@@ -48,7 +48,7 @@ func newSimpleCacheIndexServant(getIndexPosts func(offset, limit int) ([]*model.
return cacheIndex
}
-func (s *simpleCacheIndexServant) IndexPosts(offset int, limit int) ([]*model.PostFormated, error) {
+func (s *simpleCacheIndexServant) IndexPosts(_userId int64, offset int, limit int) ([]*model.PostFormated, error) {
posts := s.atomicIndex.Load().([]*model.PostFormated)
end := offset + limit
size := len(posts)
@@ -78,7 +78,7 @@ func (s *simpleCacheIndexServant) startIndexPosts() {
case <-s.checkTick.C:
if len(s.indexPosts) == 0 {
logrus.Debugf("index posts by checkTick")
- if s.indexPosts, err = s.getIndexPosts(0, s.maxIndexSize); err == nil {
+ if s.indexPosts, err = s.getIndexPosts(0, 0, s.maxIndexSize); err == nil {
s.atomicIndex.Store(s.indexPosts)
} else {
logrus.Errorf("get index posts err: %v", err)
diff --git a/internal/dao/dao.go b/internal/dao/dao.go
index 59634bfb..fb82b71c 100644
--- a/internal/dao/dao.go
+++ b/internal/dao/dao.go
@@ -32,8 +32,9 @@ type dataServant struct {
zinc *zinc.ZincClient
}
+type indexPostsFunc func(int64, int, int) ([]*model.PostFormated, error)
type simpleCacheIndexServant struct {
- getIndexPosts func(offset, limit int) ([]*model.PostFormated, error)
+ getIndexPosts indexPostsFunc
indexActionCh chan core.IndexActionT
indexPosts []*model.PostFormated
atomicIndex atomic.Value
diff --git a/internal/dao/post_index.go b/internal/dao/post_index.go
index 0a184dd7..4353e938 100644
--- a/internal/dao/post_index.go
+++ b/internal/dao/post_index.go
@@ -6,15 +6,15 @@ import (
"github.com/sirupsen/logrus"
)
-func (d *dataServant) IndexPosts(offset int, limit int) ([]*model.PostFormated, error) {
+func (d *dataServant) IndexPosts(userId int64, offset int, limit int) ([]*model.PostFormated, error) {
if d.useCacheIndex {
- if posts, err := d.cacheIndex.IndexPosts(offset, limit); err == nil {
+ if posts, err := d.cacheIndex.IndexPosts(userId, offset, limit); err == nil {
logrus.Debugln("get index posts from cached")
return posts, nil
}
}
logrus.Debugf("get index posts from database but useCacheIndex: %t", d.useCacheIndex)
- return d.getIndexPosts(offset, limit)
+ return d.getIndexPosts(userId, offset, limit)
}
func (d *dataServant) MergePosts(posts []*model.Post) ([]*model.PostFormated, error) {
@@ -56,9 +56,11 @@ func (d *dataServant) MergePosts(posts []*model.Post) ([]*model.PostFormated, er
return postsFormated, nil
}
-func (d *dataServant) getIndexPosts(offset int, limit int) ([]*model.PostFormated, error) {
+// getIndexPosts _userId保留未来使用
+func (d *dataServant) getIndexPosts(_userId int64, offset int, limit int) ([]*model.PostFormated, error) {
posts, err := (&model.Post{}).List(d.engine, &model.ConditionsT{
- "ORDER": "is_top DESC, latest_replied_on DESC",
+ "visibility IN ?": []model.PostVisibleT{model.PostVisitPublic, model.PostVisitFriend},
+ "ORDER": "is_top DESC, latest_replied_on DESC",
}, offset, limit)
if err != nil {
logrus.Debugf("getIndexPosts err: %v", err)
diff --git a/internal/dao/user.go b/internal/dao/user.go
index ab0d72a8..ce07f5c9 100644
--- a/internal/dao/user.go
+++ b/internal/dao/user.go
@@ -158,3 +158,8 @@ func (d *dataServant) SendPhoneCaptcha(phone string) error {
captchaModel.Create(d.engine)
return nil
}
+
+func (d *dataServant) IsFriend(_userID int64, _friendID int64) bool {
+ // TODO: you are friend in all now
+ return true
+}
diff --git a/internal/middleware/jwt.go b/internal/middleware/jwt.go
index e8e99950..fc6db41e 100644
--- a/internal/middleware/jwt.go
+++ b/internal/middleware/jwt.go
@@ -74,3 +74,36 @@ func JWT() gin.HandlerFunc {
c.Next()
}
}
+
+func JwtLoose() gin.HandlerFunc {
+ return func(c *gin.Context) {
+ token, exist := c.GetQuery("token")
+ if !exist {
+ token = c.GetHeader("Authorization")
+ // 验证前端传过来的token格式,不为空,开头为Bearer
+ if strings.HasPrefix(token, "Bearer ") {
+ // 验证通过,提取有效部分(除去Bearer)
+ token = token[7:]
+ } else {
+ c.Next()
+ }
+ }
+ if len(token) > 0 {
+ if claims, err := app.ParseToken(token); err == nil {
+ c.Set("UID", claims.UID)
+ c.Set("USERNAME", claims.Username)
+ // 加载用户信息
+ user := &model.User{
+ Model: &model.Model{
+ ID: claims.UID,
+ },
+ }
+ user, err := user.Get(conf.DBEngine)
+ if err == nil && (conf.JWTSetting.Issuer+":"+user.Salt) == claims.Issuer {
+ c.Set("USER", user)
+ }
+ }
+ }
+ c.Next()
+ }
+}
diff --git a/internal/model/post.go b/internal/model/post.go
index 3ce80414..39bc5844 100644
--- a/internal/model/post.go
+++ b/internal/model/post.go
@@ -7,20 +7,30 @@ import (
"gorm.io/gorm"
)
+// PostVisibleT 可访问类型,0公开,1私密,2好友
+type PostVisibleT int
+
+const (
+ PostVisitPublic PostVisibleT = iota
+ PostVisitPrivate
+ PostVisitFriend
+)
+
type Post struct {
*Model
- UserID int64 `json:"user_id"`
- CommentCount int64 `json:"comment_count"`
- CollectionCount int64 `json:"collection_count"`
- UpvoteCount int64 `json:"upvote_count"`
- IsTop int `json:"is_top"`
- IsEssence int `json:"is_essence"`
- IsLock int `json:"is_lock"`
- LatestRepliedOn int64 `json:"latest_replied_on"`
- Tags string `json:"tags"`
- AttachmentPrice int64 `json:"attachment_price"`
- IP string `json:"ip"`
- IPLoc string `json:"ip_loc"`
+ UserID int64 `json:"user_id"`
+ CommentCount int64 `json:"comment_count"`
+ CollectionCount int64 `json:"collection_count"`
+ UpvoteCount int64 `json:"upvote_count"`
+ Visibility PostVisibleT `json:"visibility"`
+ IsTop int `json:"is_top"`
+ IsEssence int `json:"is_essence"`
+ IsLock int `json:"is_lock"`
+ LatestRepliedOn int64 `json:"latest_replied_on"`
+ Tags string `json:"tags"`
+ AttachmentPrice int64 `json:"attachment_price"`
+ IP string `json:"ip"`
+ IPLoc string `json:"ip_loc"`
}
type PostFormated struct {
@@ -31,6 +41,7 @@ type PostFormated struct {
CommentCount int64 `json:"comment_count"`
CollectionCount int64 `json:"collection_count"`
UpvoteCount int64 `json:"upvote_count"`
+ Visibility PostVisibleT `json:"visibility"`
IsTop int `json:"is_top"`
IsEssence int `json:"is_essence"`
IsLock int `json:"is_lock"`
diff --git a/internal/routers/api/post.go b/internal/routers/api/post.go
index 8b4f3703..c1452b8f 100644
--- a/internal/routers/api/post.go
+++ b/internal/routers/api/post.go
@@ -31,7 +31,8 @@ func GetPostList(c *gin.Context) {
return
}
totalRows, _ := service.GetPostCount(&model.ConditionsT{
- "ORDER": "latest_replied_on DESC",
+ "visibility IN ?": []model.PostVisibleT{model.PostVisitPublic, model.PostVisitFriend},
+ "ORDER": "latest_replied_on DESC",
})
response.ToResponseList(posts, totalRows)
diff --git a/internal/routers/api/user.go b/internal/routers/api/user.go
index 94b3bcb9..f7ca4633 100644
--- a/internal/routers/api/user.go
+++ b/internal/routers/api/user.go
@@ -313,13 +313,23 @@ func GetUserPosts(c *gin.Context) {
return
}
- conditions := &model.ConditionsT{
- "user_id": user.ID,
- "ORDER": "latest_replied_on DESC",
+ visibilities := []model.PostVisibleT{model.PostVisitPublic}
+ if u, exists := c.Get("USER"); exists {
+ self := u.(*model.User)
+ if self.ID == user.ID || self.IsAdmin {
+ visibilities = append(visibilities, model.PostVisitPrivate, model.PostVisitFriend)
+ } else if service.IsFriend(user.ID, self.ID) {
+ visibilities = append(visibilities, model.PostVisitFriend)
+ }
+ }
+ conditions := model.ConditionsT{
+ "user_id": user.ID,
+ "visibility IN ?": visibilities,
+ "ORDER": "latest_replied_on DESC",
}
posts, err := service.GetPostList(&service.PostListReq{
- Conditions: conditions,
+ Conditions: &conditions,
Offset: (app.GetPage(c) - 1) * app.GetPageSize(c),
Limit: app.GetPageSize(c),
})
@@ -328,7 +338,7 @@ func GetUserPosts(c *gin.Context) {
response.ToErrorResponse(errcode.GetPostsFailed)
return
}
- totalRows, _ := service.GetPostCount(conditions)
+ totalRows, _ := service.GetPostCount(&conditions)
response.ToResponseList(posts, totalRows)
}
diff --git a/internal/routers/router.go b/internal/routers/router.go
index 2a478664..9465ba4b 100644
--- a/internal/routers/router.go
+++ b/internal/routers/router.go
@@ -69,9 +69,13 @@ func NewRouter() *gin.Engine {
// 获取用户基本信息
noAuthApi.GET("/user/profile", api.GetUserProfile)
+ }
+ // 宽松鉴权路由组
+ looseApi := r.Group("/").Use(middleware.JwtLoose())
+ {
// 获取用户动态列表
- noAuthApi.GET("/user/posts", api.GetUserPosts)
+ looseApi.GET("/user/posts", api.GetUserPosts)
}
// 鉴权路由组
diff --git a/internal/service/post.go b/internal/service/post.go
index 00bc494c..b65ff0d9 100644
--- a/internal/service/post.go
+++ b/internal/service/post.go
@@ -36,6 +36,7 @@ type PostCreationReq struct {
Tags []string `json:"tags" binding:"required"`
Users []string `json:"users" binding:"required"`
AttachmentPrice int64 `json:"attachment_price"`
+ Visibility model.PostVisibleT `json:"visibility"`
}
type PostDelReq struct {
@@ -92,6 +93,7 @@ func CreatePost(c *gin.Context, userID int64, param PostCreationReq) (*model.Pos
IP: ip,
IPLoc: util.GetIPLoc(ip),
AttachmentPrice: param.AttachmentPrice,
+ Visibility: param.Visibility,
}
post, err := ds.CreatePost(post)
if err != nil {
@@ -325,7 +327,7 @@ func GetPostContentByID(id int64) (*model.PostContent, error) {
}
func GetIndexPosts(offset int, limit int) ([]*model.PostFormated, error) {
- return ds.IndexPosts(offset, limit)
+ return ds.IndexPosts(0, offset, limit)
}
func GetPostList(req *PostListReq) ([]*model.PostFormated, error) {
@@ -411,6 +413,11 @@ func GetPostListFromSearchByQuery(query string, offset, limit int) ([]*model.Pos
}
func PushPostToSearch(post *model.Post) {
+ // TODO: 暂时不索引私密文章,后续再完善
+ if post.Visibility == model.PostVisitPrivate {
+ return
+ }
+
indexName := conf.ZincSetting.Index
postFormated := post.Format()
@@ -447,6 +454,7 @@ func PushPostToSearch(post *model.Post) {
"comment_count": post.CommentCount,
"collection_count": post.CollectionCount,
"upvote_count": post.UpvoteCount,
+ "visibility": post.Visibility,
"is_top": post.IsTop,
"is_essence": post.IsEssence,
"content": contentFormated,
@@ -470,7 +478,9 @@ func DeleteSearchPost(post *model.Post) error {
func PushPostsToSearch(c *gin.Context) {
if ok, _ := conf.Redis.SetNX(c, "JOB_PUSH_TO_SEARCH", 1, time.Hour).Result(); ok {
splitNum := 1000
- totalRows, _ := GetPostCount(&model.ConditionsT{})
+ totalRows, _ := GetPostCount(&model.ConditionsT{
+ "visibility IN ?": []model.PostVisibleT{model.PostVisitPublic, model.PostVisitFriend},
+ })
pages := math.Ceil(float64(totalRows) / float64(splitNum))
nums := int(pages)
@@ -483,9 +493,11 @@ func PushPostsToSearch(c *gin.Context) {
data := []map[string]interface{}{}
posts, _ := GetPostList(&PostListReq{
- Conditions: &model.ConditionsT{},
- Offset: i * splitNum,
- Limit: splitNum,
+ Conditions: &model.ConditionsT{
+ "visibility IN ?": []model.PostVisibleT{model.PostVisitPublic, model.PostVisitFriend},
+ },
+ Offset: i * splitNum,
+ Limit: splitNum,
})
for _, post := range posts {
@@ -508,6 +520,7 @@ func PushPostsToSearch(c *gin.Context) {
"comment_count": post.CommentCount,
"collection_count": post.CollectionCount,
"upvote_count": post.UpvoteCount,
+ "visibility": post.Visibility,
"is_top": post.IsTop,
"is_essence": post.IsEssence,
"content": contentFormated,
diff --git a/internal/service/user.go b/internal/service/user.go
index 25f5a225..5b4edfc4 100644
--- a/internal/service/user.go
+++ b/internal/service/user.go
@@ -390,3 +390,7 @@ func GetSuggestTags(keyword string) ([]string, error) {
return ts, nil
}
+
+func IsFriend(userId, friendId int64) bool {
+ return ds.IsFriend(userId, friendId)
+}
diff --git a/scripts/migration/mysql/001-2206131310.sql b/scripts/migration/mysql/001-2206131310.sql
new file mode 100644
index 00000000..c654a3bb
--- /dev/null
+++ b/scripts/migration/mysql/001-2206131310.sql
@@ -0,0 +1,9 @@
+-- ----------------------------
+-- Table p_post alter add visibility column
+-- ----------------------------
+ALTER TABLE `p_post` ADD COLUMN `visibility` tinyint unsigned NOT NULL DEFAULT '0' COMMENT '可见性 0公开 1私密 2好友可见';
+
+-- ----------------------------
+-- Indexes structure for table p_post
+-- ----------------------------
+CREATE INDEX `idx_visibility` ON `p_post` ( `visibility` ) USING BTREE;
diff --git a/scripts/migration/sqlite3/001-2206131310.sql b/scripts/migration/sqlite3/001-2206131310.sql
new file mode 100644
index 00000000..63657693
--- /dev/null
+++ b/scripts/migration/sqlite3/001-2206131310.sql
@@ -0,0 +1,12 @@
+-- ----------------------------
+-- Table p_post alter add visibility column
+-- ----------------------------
+ALTER TABLE `p_post` ADD COLUMN `visibility` integer NOT NULL DEFAULT '0';
+
+-- ----------------------------
+-- Indexes structure for table p_post
+-- ----------------------------
+CREATE INDEX "main"."idx_visibility"
+ON "p_post" (
+ "visibility" ASC
+);
diff --git a/web/build/info.json b/web/build/info.json
index f430d3b0..290a7eb3 100644
--- a/web/build/info.json
+++ b/web/build/info.json
@@ -1,4 +1,4 @@
{
- "version": "3",
- "buildTime": "2022-06-08 23:29:43"
+ "version": "8",
+ "buildTime": "2022-06-13 17:16:22"
}
\ No newline at end of file
diff --git a/web/src/components/compose.vue b/web/src/components/compose.vue
index 8d5d8771..90961614 100644
--- a/web/src/components/compose.vue
+++ b/web/src/components/compose.vue
@@ -141,6 +141,19 @@
+
+