diff --git a/cmd/answer/wire_gen.go b/cmd/answer/wire_gen.go index 807fd0ef..aafd3dc4 100644 --- a/cmd/answer/wire_gen.go +++ b/cmd/answer/wire_gen.go @@ -128,7 +128,7 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database, answerRepo := answer.NewAnswerRepo(dataData, uniqueIDRepo, userRankRepo, activityRepo) questionRepo := question.NewQuestionRepo(dataData, uniqueIDRepo) tagCommonRepo := tag_common.NewTagCommonRepo(dataData, uniqueIDRepo) - tagRelRepo := tag.NewTagRelRepo(dataData) + tagRelRepo := tag.NewTagRelRepo(dataData, uniqueIDRepo) tagRepo := tag.NewTagRepo(dataData, uniqueIDRepo) revisionRepo := revision.NewRevisionRepo(dataData, uniqueIDRepo) revisionService := revision_common.NewRevisionService(revisionRepo, userRepo) diff --git a/internal/controller/collection_controller.go b/internal/controller/collection_controller.go index c405acaa..2564f02a 100644 --- a/internal/controller/collection_controller.go +++ b/internal/controller/collection_controller.go @@ -7,6 +7,7 @@ import ( "github.com/answerdev/answer/internal/schema" "github.com/answerdev/answer/internal/service" "github.com/answerdev/answer/pkg/converter" + "github.com/answerdev/answer/pkg/uid" "github.com/gin-gonic/gin" "github.com/jinzhu/copier" "github.com/segmentfault/pacman/errors" @@ -37,6 +38,7 @@ func (cc *CollectionController) CollectionSwitch(ctx *gin.Context) { if handler.BindAndCheck(ctx, req) { return } + req.ObjectID = uid.DeShortID(req.ObjectID) dto := &schema.CollectionSwitchDTO{} _ = copier.Copy(dto, req) diff --git a/internal/controller/comment_controller.go b/internal/controller/comment_controller.go index 6b74b754..e998bb0d 100644 --- a/internal/controller/comment_controller.go +++ b/internal/controller/comment_controller.go @@ -8,6 +8,7 @@ import ( "github.com/answerdev/answer/internal/service/comment" "github.com/answerdev/answer/internal/service/permission" "github.com/answerdev/answer/internal/service/rank" + "github.com/answerdev/answer/pkg/uid" "github.com/gin-gonic/gin" "github.com/segmentfault/pacman/errors" ) @@ -40,7 +41,7 @@ func (cc *CommentController) AddComment(ctx *gin.Context) { if handler.BindAndCheck(ctx, req) { return } - + req.ObjectID = uid.DeShortID(req.ObjectID) req.UserID = middleware.GetLoginUserIDFromContext(ctx) canList, err := cc.rankService.CheckOperationPermissions(ctx, req.UserID, []string{ permission.CommentAdd, @@ -154,7 +155,7 @@ func (cc *CommentController) GetCommentWithPage(ctx *gin.Context) { if handler.BindAndCheck(ctx, req) { return } - + req.ObjectID = uid.DeShortID(req.ObjectID) req.UserID = middleware.GetLoginUserIDFromContext(ctx) canList, err := cc.rankService.CheckOperationPermissions(ctx, req.UserID, []string{ permission.CommentEdit, diff --git a/internal/controller/follow_controller.go b/internal/controller/follow_controller.go index 1ccc1220..0cf5ad6f 100644 --- a/internal/controller/follow_controller.go +++ b/internal/controller/follow_controller.go @@ -5,6 +5,7 @@ import ( "github.com/answerdev/answer/internal/base/middleware" "github.com/answerdev/answer/internal/schema" "github.com/answerdev/answer/internal/service/follow" + "github.com/answerdev/answer/pkg/uid" "github.com/gin-gonic/gin" "github.com/jinzhu/copier" ) @@ -34,7 +35,7 @@ func (fc *FollowController) Follow(ctx *gin.Context) { if handler.BindAndCheck(ctx, req) { return } - + req.ObjectID = uid.DeShortID(req.ObjectID) dto := &schema.FollowDTO{} _ = copier.Copy(dto, req) dto.UserID = middleware.GetLoginUserIDFromContext(ctx) diff --git a/internal/controller/report_controller.go b/internal/controller/report_controller.go index 85987e84..20ecd325 100644 --- a/internal/controller/report_controller.go +++ b/internal/controller/report_controller.go @@ -8,6 +8,7 @@ import ( "github.com/answerdev/answer/internal/service/permission" "github.com/answerdev/answer/internal/service/rank" "github.com/answerdev/answer/internal/service/report" + "github.com/answerdev/answer/pkg/uid" "github.com/gin-gonic/gin" "github.com/segmentfault/pacman/errors" ) @@ -39,7 +40,7 @@ func (rc *ReportController) AddReport(ctx *gin.Context) { if handler.BindAndCheck(ctx, req) { return } - + req.ObjectID = uid.DeShortID(req.ObjectID) req.UserID = middleware.GetLoginUserIDFromContext(ctx) can, err := rc.rankService.CheckOperationPermission(ctx, req.UserID, permission.ReportAdd, "") if err != nil { diff --git a/internal/controller/revision_controller.go b/internal/controller/revision_controller.go index 1327cb80..dfac4519 100644 --- a/internal/controller/revision_controller.go +++ b/internal/controller/revision_controller.go @@ -10,6 +10,7 @@ import ( "github.com/answerdev/answer/internal/service/permission" "github.com/answerdev/answer/internal/service/rank" "github.com/answerdev/answer/pkg/obj" + "github.com/answerdev/answer/pkg/uid" "github.com/gin-gonic/gin" "github.com/segmentfault/pacman/errors" ) @@ -45,7 +46,7 @@ func (rc *RevisionController) GetRevisionList(ctx *gin.Context) { handler.HandleResponse(ctx, errors.BadRequest(reason.RequestFormatError), nil) return } - + objectID = uid.DeShortID(objectID) req := &schema.GetRevisionListReq{ ObjectID: objectID, } @@ -137,6 +138,7 @@ func (rc *RevisionController) CheckCanUpdateRevision(ctx *gin.Context) { req.UserID = middleware.GetLoginUserIDFromContext(ctx) action := "" + req.ID = uid.DeShortID(req.ID) objectTypeStr, _ := obj.GetObjectTypeStrByObjectID(req.ID) switch objectTypeStr { case constant.QuestionObjectType: diff --git a/internal/repo/answer/answer_repo.go b/internal/repo/answer/answer_repo.go index 48a54d6a..6293a681 100644 --- a/internal/repo/answer/answer_repo.go +++ b/internal/repo/answer/answer_repo.go @@ -18,6 +18,7 @@ import ( answercommon "github.com/answerdev/answer/internal/service/answer_common" "github.com/answerdev/answer/internal/service/rank" "github.com/answerdev/answer/internal/service/unique" + "github.com/answerdev/answer/pkg/uid" "github.com/segmentfault/pacman/errors" ) @@ -46,6 +47,7 @@ func NewAnswerRepo( // AddAnswer add answer func (ar *answerRepo) AddAnswer(ctx context.Context, answer *entity.Answer) (err error) { + answer.QuestionID = uid.DeShortID(answer.QuestionID) ID, err := ar.uniqueIDRepo.GenUniqueIDStr(ctx, answer.TableName()) if err != nil { return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() @@ -56,11 +58,14 @@ func (ar *answerRepo) AddAnswer(ctx context.Context, answer *entity.Answer) (err if err != nil { return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() } + answer.ID = uid.EnShortID(answer.ID) + answer.QuestionID = uid.EnShortID(answer.QuestionID) return nil } // RemoveAnswer delete answer func (ar *answerRepo) RemoveAnswer(ctx context.Context, id string) (err error) { + id = uid.DeShortID(id) answer := &entity.Answer{ ID: id, Status: entity.AnswerStatusDeleted, @@ -74,6 +79,8 @@ func (ar *answerRepo) RemoveAnswer(ctx context.Context, id string) (err error) { // UpdateAnswer update answer func (ar *answerRepo) UpdateAnswer(ctx context.Context, answer *entity.Answer, Colar []string) (err error) { + answer.ID = uid.DeShortID(answer.ID) + answer.QuestionID = uid.DeShortID(answer.QuestionID) _, err = ar.data.DB.ID(answer.ID).Cols(Colar...).Update(answer) if err != nil { err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() @@ -83,6 +90,7 @@ func (ar *answerRepo) UpdateAnswer(ctx context.Context, answer *entity.Answer, C func (ar *answerRepo) UpdateAnswerStatus(ctx context.Context, answer *entity.Answer) (err error) { now := time.Now() + answer.ID = uid.DeShortID(answer.ID) answer.UpdatedAt = now _, err = ar.data.DB.Where("id =?", answer.ID).Cols("status", "updated_at").Update(answer) if err != nil { @@ -95,11 +103,15 @@ func (ar *answerRepo) UpdateAnswerStatus(ctx context.Context, answer *entity.Ans func (ar *answerRepo) GetAnswer(ctx context.Context, id string) ( answer *entity.Answer, exist bool, err error, ) { + id = uid.DeShortID(id) answer = &entity.Answer{} exist, err = ar.data.DB.ID(id).Get(answer) if err != nil { return nil, false, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() } + answer.ID = uid.EnShortID(answer.ID) + answer.QuestionID = uid.EnShortID(answer.QuestionID) + return } @@ -116,20 +128,32 @@ func (ar *answerRepo) GetAnswerCount(ctx context.Context) (count int64, err erro // GetAnswerList get answer list all func (ar *answerRepo) GetAnswerList(ctx context.Context, answer *entity.Answer) (answerList []*entity.Answer, err error) { answerList = make([]*entity.Answer, 0) + answer.ID = uid.DeShortID(answer.ID) + answer.QuestionID = uid.DeShortID(answer.QuestionID) err = ar.data.DB.Find(answerList, answer) if err != nil { err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() } + for _, item := range answerList { + item.ID = uid.EnShortID(item.ID) + item.QuestionID = uid.EnShortID(item.QuestionID) + } return } // GetAnswerPage get answer page func (ar *answerRepo) GetAnswerPage(ctx context.Context, page, pageSize int, answer *entity.Answer) (answerList []*entity.Answer, total int64, err error) { + answer.ID = uid.DeShortID(answer.ID) + answer.QuestionID = uid.DeShortID(answer.QuestionID) answerList = make([]*entity.Answer, 0) total, err = pager.Help(page, pageSize, answerList, answer, ar.data.DB.NewSession()) if err != nil { err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() } + for _, item := range answerList { + item.ID = uid.EnShortID(item.ID) + item.QuestionID = uid.EnShortID(item.QuestionID) + } return } @@ -139,6 +163,8 @@ func (ar *answerRepo) UpdateAccepted(ctx context.Context, id string, questionID if questionID == "" { return nil } + id = uid.DeShortID(id) + questionID = uid.DeShortID(questionID) var data entity.Answer data.ID = id @@ -160,24 +186,32 @@ func (ar *answerRepo) UpdateAccepted(ctx context.Context, id string, questionID // GetByID func (ar *answerRepo) GetByID(ctx context.Context, id string) (*entity.Answer, bool, error) { var resp entity.Answer + id = uid.DeShortID(id) has, err := ar.data.DB.Where("id =? ", id).Get(&resp) if err != nil { return &resp, false, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() } + resp.ID = uid.EnShortID(resp.ID) + resp.QuestionID = uid.EnShortID(resp.QuestionID) return &resp, has, nil } func (ar *answerRepo) GetByUserIDQuestionID(ctx context.Context, userID string, questionID string) (*entity.Answer, bool, error) { + questionID = uid.DeShortID(questionID) var resp entity.Answer has, err := ar.data.DB.Where("question_id =? and user_id = ?", questionID, userID).Get(&resp) if err != nil { return &resp, false, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() } + resp.ID = uid.EnShortID(resp.ID) + resp.QuestionID = uid.EnShortID(resp.QuestionID) return &resp, has, nil } // SearchList func (ar *answerRepo) SearchList(ctx context.Context, search *entity.AnswerSearch) ([]*entity.Answer, int64, error) { + search.QuestionID = uid.DeShortID(search.QuestionID) + search.ID = uid.DeShortID(search.ID) var count int64 var err error rows := make([]*entity.Answer, 0) @@ -215,6 +249,10 @@ func (ar *answerRepo) SearchList(ctx context.Context, search *entity.AnswerSearc if err != nil { return rows, count, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() } + for _, item := range rows { + item.ID = uid.EnShortID(item.ID) + item.QuestionID = uid.EnShortID(item.QuestionID) + } return rows, count, nil } @@ -224,6 +262,9 @@ func (ar *answerRepo) AdminSearchList(ctx context.Context, search *entity.AdminA err error session = ar.data.DB.Table([]string{entity.Answer{}.TableName(), "a"}).Select("a.*") ) + if search.QuestionID != "" { + search.QuestionID = uid.DeShortID(search.QuestionID) + } session.Where(builder.Eq{ "a.status": search.Status, @@ -250,6 +291,7 @@ func (ar *answerRepo) AdminSearchList(ctx context.Context, search *entity.AdminA if strings.Contains(search.Query, "answer:") { idSearch = true id = strings.TrimSpace(strings.TrimPrefix(search.Query, "answer:")) + id = uid.DeShortID(id) for _, r := range id { if !unicode.IsDigit(r) { idSearch = false @@ -285,5 +327,9 @@ func (ar *answerRepo) AdminSearchList(ctx context.Context, search *entity.AdminA if err != nil { return rows, count, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() } + for _, item := range rows { + item.ID = uid.EnShortID(item.ID) + item.QuestionID = uid.EnShortID(item.QuestionID) + } return rows, count, nil } diff --git a/internal/repo/collection/collection_repo.go b/internal/repo/collection/collection_repo.go index 396398c5..7fcf9335 100644 --- a/internal/repo/collection/collection_repo.go +++ b/internal/repo/collection/collection_repo.go @@ -30,6 +30,7 @@ func NewCollectionRepo(data *data.Data, uniqueIDRepo unique.UniqueIDRepo) collec // AddCollection add collection func (cr *collectionRepo) AddCollection(ctx context.Context, collection *entity.Collection) (err error) { + needAdd := false _, err = cr.data.DB.Transaction(func(session *xorm.Session) (result any, err error) { var has bool dbcollection := &entity.Collection{} @@ -41,16 +42,23 @@ func (cr *collectionRepo) AddCollection(ctx context.Context, collection *entity. if has { return } + needAdd = true + return + }) + if err != nil { + return + } + if needAdd { id, err := cr.uniqueIDRepo.GenUniqueIDStr(ctx, collection.TableName()) if err == nil { collection.ID = id - _, err = session.Insert(collection) + _, err = cr.data.DB.Insert(collection) if err != nil { - return result, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() + return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() } } - return - }) + } + return err } diff --git a/internal/repo/notification/notification_repo.go b/internal/repo/notification/notification_repo.go index 37c9337a..994113fc 100644 --- a/internal/repo/notification/notification_repo.go +++ b/internal/repo/notification/notification_repo.go @@ -10,6 +10,7 @@ import ( "github.com/answerdev/answer/internal/entity" "github.com/answerdev/answer/internal/schema" notficationcommon "github.com/answerdev/answer/internal/service/notification_common" + "github.com/answerdev/answer/pkg/uid" "github.com/segmentfault/pacman/errors" ) @@ -27,6 +28,7 @@ func NewNotificationRepo(data *data.Data) notficationcommon.NotificationRepo { // AddNotification add notification func (nr *notificationRepo) AddNotification(ctx context.Context, notification *entity.Notification) (err error) { + notification.ObjectID = uid.DeShortID(notification.ObjectID) _, err = nr.data.DB.Insert(notification) if err != nil { return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() @@ -37,6 +39,7 @@ func (nr *notificationRepo) AddNotification(ctx context.Context, notification *e func (nr *notificationRepo) UpdateNotificationContent(ctx context.Context, notification *entity.Notification) (err error) { now := time.Now() notification.UpdatedAt = now + notification.ObjectID = uid.DeShortID(notification.ObjectID) _, err = nr.data.DB.Where("id =?", notification.ID).Cols("content", "updated_at").Update(notification) if err != nil { return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() diff --git a/internal/repo/question/question_repo.go b/internal/repo/question/question_repo.go index 84d89987..a20718fe 100644 --- a/internal/repo/question/question_repo.go +++ b/internal/repo/question/question_repo.go @@ -18,6 +18,7 @@ import ( questioncommon "github.com/answerdev/answer/internal/service/question_common" "github.com/answerdev/answer/internal/service/unique" "github.com/answerdev/answer/pkg/htmltext" + "github.com/answerdev/answer/pkg/uid" "github.com/segmentfault/pacman/errors" ) @@ -49,11 +50,13 @@ func (qr *questionRepo) AddQuestion(ctx context.Context, question *entity.Questi if err != nil { return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() } + question.ID = uid.EnShortID(question.ID) return } // RemoveQuestion delete question func (qr *questionRepo) RemoveQuestion(ctx context.Context, id string) (err error) { + id = uid.DeShortID(id) _, err = qr.data.DB.Where("id =?", id).Delete(&entity.Question{}) if err != nil { err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() @@ -63,14 +66,17 @@ func (qr *questionRepo) RemoveQuestion(ctx context.Context, id string) (err erro // UpdateQuestion update question func (qr *questionRepo) UpdateQuestion(ctx context.Context, question *entity.Question, Cols []string) (err error) { + question.ID = uid.DeShortID(question.ID) _, err = qr.data.DB.Where("id =?", question.ID).Cols(Cols...).Update(question) if err != nil { return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() } + question.ID = uid.EnShortID(question.ID) return } func (qr *questionRepo) UpdatePvCount(ctx context.Context, questionID string) (err error) { + questionID = uid.DeShortID(questionID) question := &entity.Question{} _, err = qr.data.DB.Where("id =?", questionID).Incr("view_count", 1).Update(question) if err != nil { @@ -80,6 +86,7 @@ func (qr *questionRepo) UpdatePvCount(ctx context.Context, questionID string) (e } func (qr *questionRepo) UpdateAnswerCount(ctx context.Context, questionID string, num int) (err error) { + questionID = uid.DeShortID(questionID) question := &entity.Question{} _, err = qr.data.DB.Where("id =?", questionID).Incr("answer_count", num).Update(question) if err != nil { @@ -89,6 +96,7 @@ func (qr *questionRepo) UpdateAnswerCount(ctx context.Context, questionID string } func (qr *questionRepo) UpdateCollectionCount(ctx context.Context, questionID string, num int) (err error) { + questionID = uid.DeShortID(questionID) question := &entity.Question{} _, err = qr.data.DB.Where("id =?", questionID).Incr("collection_count", num).Update(question) if err != nil { @@ -98,6 +106,7 @@ func (qr *questionRepo) UpdateCollectionCount(ctx context.Context, questionID st } func (qr *questionRepo) UpdateQuestionStatus(ctx context.Context, question *entity.Question) (err error) { + question.ID = uid.DeShortID(question.ID) now := time.Now() question.UpdatedAt = now _, err = qr.data.DB.Where("id =?", question.ID).Cols("status", "updated_at").Update(question) @@ -108,6 +117,7 @@ func (qr *questionRepo) UpdateQuestionStatus(ctx context.Context, question *enti } func (qr *questionRepo) UpdateQuestionStatusWithOutUpdateTime(ctx context.Context, question *entity.Question) (err error) { + question.ID = uid.DeShortID(question.ID) _, err = qr.data.DB.Where("id =?", question.ID).Cols("status").Update(question) if err != nil { return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() @@ -116,6 +126,7 @@ func (qr *questionRepo) UpdateQuestionStatusWithOutUpdateTime(ctx context.Contex } func (qr *questionRepo) UpdateAccepted(ctx context.Context, question *entity.Question) (err error) { + question.ID = uid.DeShortID(question.ID) _, err = qr.data.DB.Where("id =?", question.ID).Cols("accepted_answer_id").Update(question) if err != nil { return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() @@ -124,6 +135,7 @@ func (qr *questionRepo) UpdateAccepted(ctx context.Context, question *entity.Que } func (qr *questionRepo) UpdateLastAnswer(ctx context.Context, question *entity.Question) (err error) { + question.ID = uid.DeShortID(question.ID) _, err = qr.data.DB.Where("id =?", question.ID).Cols("last_answer_id").Update(question) if err != nil { return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() @@ -135,12 +147,14 @@ func (qr *questionRepo) UpdateLastAnswer(ctx context.Context, question *entity.Q func (qr *questionRepo) GetQuestion(ctx context.Context, id string) ( question *entity.Question, exist bool, err error, ) { + id = uid.DeShortID(id) question = &entity.Question{} question.ID = id exist, err = qr.data.DB.Where("id = ?", id).Get(question) if err != nil { return nil, false, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() } + question.ID = uid.EnShortID(question.ID) return } @@ -151,25 +165,38 @@ func (qr *questionRepo) SearchByTitleLike(ctx context.Context, title string) (qu if err != nil { return nil, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() } + for _, item := range questionList { + item.ID = uid.EnShortID(item.ID) + } return } func (qr *questionRepo) FindByID(ctx context.Context, id []string) (questionList []*entity.Question, err error) { + for key, itemID := range id { + id[key] = uid.EnShortID(itemID) + } questionList = make([]*entity.Question, 0) err = qr.data.DB.Table("question").In("id", id).Find(&questionList) if err != nil { return nil, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() } + for _, item := range questionList { + item.ID = uid.DeShortID(item.ID) + } return } // GetQuestionList get question list all func (qr *questionRepo) GetQuestionList(ctx context.Context, question *entity.Question) (questionList []*entity.Question, err error) { + question.ID = uid.DeShortID(question.ID) questionList = make([]*entity.Question, 0) err = qr.data.DB.Find(questionList, question) if err != nil { return questionList, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() } + for _, item := range questionList { + item.ID = uid.DeShortID(item.ID) + } return } @@ -199,15 +226,19 @@ func (qr *questionRepo) GetQuestionIDsPage(ctx context.Context, page, pageSize i session = session.In("question.status", []int{entity.QuestionStatusAvailable, entity.QuestionStatusClosed}) session = session.Limit(pageSize, offset) session = session.OrderBy("question.created_at asc") - err = session.Select("id,title,post_update_time").Find(&rows) + err = session.Select("id,title,created_at,post_update_time").Find(&rows) if err != nil { return questionIDList, err } for _, question := range rows { item := &schema.SiteMapQuestionInfo{} - item.ID = question.ID + item.ID = uid.EnShortID(question.ID) item.Title = htmltext.UrlTitle(question.Title) - item.UpdateTime = fmt.Sprintf("%v", question.PostUpdateTime.Format(time.RFC3339)) + updateTime := fmt.Sprintf("%v", question.PostUpdateTime.Format(time.RFC3339)) + if question.PostUpdateTime.Unix() < 1 { + updateTime = fmt.Sprintf("%v", question.CreatedAt.Format(time.RFC3339)) + } + item.UpdateTime = updateTime questionIDList = append(questionIDList, item) } return questionIDList, nil @@ -246,6 +277,9 @@ func (qr *questionRepo) GetQuestionPage(ctx context.Context, page, pageSize int, if err != nil { err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() } + for _, item := range questionList { + item.ID = uid.EnShortID(item.ID) + } return questionList, total, err } @@ -277,9 +311,11 @@ func (qr *questionRepo) AdminSearchList(ctx context.Context, search *schema.Admi idSearch = false id = "" ) + if strings.Contains(search.Query, "question:") { idSearch = true id = strings.TrimSpace(strings.TrimPrefix(search.Query, "question:")) + id = uid.DeShortID(id) for _, r := range id { if !unicode.IsDigit(r) { idSearch = false @@ -308,5 +344,8 @@ func (qr *questionRepo) AdminSearchList(ctx context.Context, search *schema.Admi err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() return rows, count, err } + for _, item := range rows { + item.ID = uid.EnShortID(item.ID) + } return rows, count, nil } diff --git a/internal/repo/tag/tag_rel_repo.go b/internal/repo/tag/tag_rel_repo.go index edb25d47..22d26621 100644 --- a/internal/repo/tag/tag_rel_repo.go +++ b/internal/repo/tag/tag_rel_repo.go @@ -7,32 +7,44 @@ import ( "github.com/answerdev/answer/internal/base/reason" "github.com/answerdev/answer/internal/entity" tagcommon "github.com/answerdev/answer/internal/service/tag_common" + "github.com/answerdev/answer/internal/service/unique" + "github.com/answerdev/answer/pkg/uid" "github.com/segmentfault/pacman/errors" ) // tagRelRepo tag rel repository type tagRelRepo struct { - data *data.Data + data *data.Data + uniqueIDRepo unique.UniqueIDRepo } // NewTagRelRepo new repository -func NewTagRelRepo(data *data.Data) tagcommon.TagRelRepo { +func NewTagRelRepo(data *data.Data, + uniqueIDRepo unique.UniqueIDRepo) tagcommon.TagRelRepo { return &tagRelRepo{ - data: data, + data: data, + uniqueIDRepo: uniqueIDRepo, } } // AddTagRelList add tag list func (tr *tagRelRepo) AddTagRelList(ctx context.Context, tagList []*entity.TagRel) (err error) { + for _, item := range tagList { + item.ObjectID = uid.DeShortID(item.ObjectID) + } _, err = tr.data.DB.Insert(tagList) if err != nil { err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() } + for _, item := range tagList { + item.ObjectID = uid.EnShortID(item.ObjectID) + } return } // RemoveTagRelListByObjectID delete tag list func (tr *tagRelRepo) RemoveTagRelListByObjectID(ctx context.Context, objectID string) (err error) { + objectID = uid.DeShortID(objectID) _, err = tr.data.DB.Where("object_id = ?", objectID).Update(&entity.TagRel{Status: entity.TagRelStatusDeleted}) if err != nil { err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() @@ -53,12 +65,14 @@ func (tr *tagRelRepo) RemoveTagRelListByIDs(ctx context.Context, ids []int64) (e func (tr *tagRelRepo) GetObjectTagRelWithoutStatus(ctx context.Context, objectID, tagID string) ( tagRel *entity.TagRel, exist bool, err error, ) { + objectID = uid.DeShortID(objectID) tagRel = &entity.TagRel{} session := tr.data.DB.Where("object_id = ?", objectID).And("tag_id = ?", tagID) exist, err = session.Get(tagRel) if err != nil { err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() } + tagRel.ObjectID = uid.EnShortID(tagRel.ObjectID) return } @@ -73,6 +87,7 @@ func (tr *tagRelRepo) EnableTagRelByIDs(ctx context.Context, ids []int64) (err e // GetObjectTagRelList get object tag relation list all func (tr *tagRelRepo) GetObjectTagRelList(ctx context.Context, objectID string) (tagListList []*entity.TagRel, err error) { + objectID = uid.DeShortID(objectID) tagListList = make([]*entity.TagRel, 0) session := tr.data.DB.Where("object_id = ?", objectID) session.Where("status = ?", entity.TagRelStatusAvailable) @@ -80,11 +95,17 @@ func (tr *tagRelRepo) GetObjectTagRelList(ctx context.Context, objectID string) if err != nil { err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() } + for _, item := range tagListList { + item.ObjectID = uid.EnShortID(item.ObjectID) + } return } // BatchGetObjectTagRelList get object tag relation list all func (tr *tagRelRepo) BatchGetObjectTagRelList(ctx context.Context, objectIds []string) (tagListList []*entity.TagRel, err error) { + for num, item := range objectIds { + objectIds[num] = uid.DeShortID(item) + } tagListList = make([]*entity.TagRel, 0) session := tr.data.DB.In("object_id", objectIds) session.Where("status = ?", entity.TagRelStatusAvailable) @@ -92,6 +113,9 @@ func (tr *tagRelRepo) BatchGetObjectTagRelList(ctx context.Context, objectIds [] if err != nil { err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() } + for _, item := range tagListList { + item.ObjectID = uid.EnShortID(item.ObjectID) + } return } diff --git a/internal/service/comment/comment_service.go b/internal/service/comment/comment_service.go index 6a33ee90..30527cb5 100644 --- a/internal/service/comment/comment_service.go +++ b/internal/service/comment/comment_service.go @@ -18,6 +18,7 @@ import ( "github.com/answerdev/answer/internal/service/permission" usercommon "github.com/answerdev/answer/internal/service/user_common" "github.com/answerdev/answer/pkg/encryption" + "github.com/answerdev/answer/pkg/uid" "github.com/jinzhu/copier" "github.com/segmentfault/pacman/errors" "github.com/segmentfault/pacman/log" @@ -97,6 +98,9 @@ func (cs *CommentService) AddComment(ctx context.Context, req *schema.AddComment if err != nil { return nil, err } + objInfo.ObjectID = uid.DeShortID(objInfo.ObjectID) + objInfo.QuestionID = uid.DeShortID(objInfo.QuestionID) + objInfo.AnswerID = uid.DeShortID(objInfo.AnswerID) if objInfo.ObjectType == constant.QuestionObjectType || objInfo.ObjectType == constant.AnswerObjectType { comment.QuestionID = objInfo.QuestionID } diff --git a/internal/service/notification/notification_service.go b/internal/service/notification/notification_service.go index b6338258..6f5e5b0e 100644 --- a/internal/service/notification/notification_service.go +++ b/internal/service/notification/notification_service.go @@ -12,6 +12,7 @@ import ( "github.com/answerdev/answer/internal/schema" notficationcommon "github.com/answerdev/answer/internal/service/notification_common" "github.com/answerdev/answer/internal/service/revision_common" + "github.com/answerdev/answer/pkg/uid" "github.com/jinzhu/copier" "github.com/segmentfault/pacman/i18n" "github.com/segmentfault/pacman/log" @@ -140,6 +141,20 @@ func (ns *NotificationService) GetNotificationPage(ctx context.Context, searchCo if notificationInfo.IsRead == schema.NotificationRead { item.IsRead = true } + answerID, ok := item.ObjectInfo.ObjectMap["answer"] + if ok { + if item.ObjectInfo.ObjectID == answerID { + item.ObjectInfo.ObjectID = uid.EnShortID(item.ObjectInfo.ObjectMap["answer"]) + } + item.ObjectInfo.ObjectMap["answer"] = uid.EnShortID(item.ObjectInfo.ObjectMap["answer"]) + } + questionID, ok := item.ObjectInfo.ObjectMap["question"] + if ok { + if item.ObjectInfo.ObjectID == questionID { + item.ObjectInfo.ObjectID = uid.EnShortID(item.ObjectInfo.ObjectMap["question"]) + } + item.ObjectInfo.ObjectMap["question"] = uid.EnShortID(item.ObjectInfo.ObjectMap["question"]) + } resp = append(resp, item) } return pager.NewPageModel(total, resp), nil diff --git a/internal/service/notification_common/notification.go b/internal/service/notification_common/notification.go index fe11a389..1a14c466 100644 --- a/internal/service/notification_common/notification.go +++ b/internal/service/notification_common/notification.go @@ -14,6 +14,7 @@ import ( "github.com/answerdev/answer/internal/service/notice_queue" "github.com/answerdev/answer/internal/service/object_info" usercommon "github.com/answerdev/answer/internal/service/user_common" + "github.com/answerdev/answer/pkg/uid" "github.com/goccy/go-json" "github.com/jinzhu/copier" "github.com/segmentfault/pacman/errors" @@ -81,12 +82,13 @@ func (ns *NotificationCommon) HandleNotification() { // ObjectInfo.ObjectID // ObjectInfo.ObjectType func (ns *NotificationCommon) AddNotification(ctx context.Context, msg *schema.NotificationMsg) error { + req := &schema.NotificationContent{ TriggerUserID: msg.TriggerUserID, ReceiverUserID: msg.ReceiverUserID, ObjectInfo: schema.ObjectInfo{ Title: msg.Title, - ObjectID: msg.ObjectID, + ObjectID: uid.DeShortID(msg.ObjectID), ObjectType: msg.ObjectType, }, NotificationAction: msg.NotificationAction, @@ -100,8 +102,8 @@ func (ns *NotificationCommon) AddNotification(ctx context.Context, msg *schema.N req.ObjectInfo.Title = objInfo.Title questionID = objInfo.QuestionID objectMap := make(map[string]string) - objectMap["question"] = objInfo.QuestionID - objectMap["answer"] = objInfo.AnswerID + objectMap["question"] = uid.DeShortID(objInfo.QuestionID) + objectMap["answer"] = uid.DeShortID(objInfo.AnswerID) objectMap["comment"] = objInfo.CommentID req.ObjectInfo.ObjectMap = objectMap } diff --git a/internal/service/revision_common/revision_service.go b/internal/service/revision_common/revision_service.go index cf33e9d9..900cdda2 100644 --- a/internal/service/revision_common/revision_service.go +++ b/internal/service/revision_common/revision_service.go @@ -6,6 +6,7 @@ import ( "github.com/answerdev/answer/internal/base/reason" "github.com/answerdev/answer/internal/service/revision" usercommon "github.com/answerdev/answer/internal/service/user_common" + "github.com/answerdev/answer/pkg/uid" "github.com/segmentfault/pacman/errors" "github.com/segmentfault/pacman/log" @@ -20,7 +21,9 @@ type RevisionService struct { userRepo usercommon.UserRepo } -func NewRevisionService(revisionRepo revision.RevisionRepo, userRepo usercommon.UserRepo) *RevisionService { +func NewRevisionService(revisionRepo revision.RevisionRepo, + userRepo usercommon.UserRepo, +) *RevisionService { return &RevisionService{ revisionRepo: revisionRepo, userRepo: userRepo, @@ -42,6 +45,7 @@ func (rs *RevisionService) GetUnreviewedRevisionCount(ctx context.Context, req * // example: user can edit the object, but need audit, the revision_id will be updated when admin approved func (rs *RevisionService) AddRevision(ctx context.Context, req *schema.AddRevisionDTO, autoUpdateRevisionID bool) ( revisionID string, err error) { + req.ObjectID = uid.DeShortID(req.ObjectID) rev := &entity.Revision{} _ = copier.Copy(rev, req) err = rs.revisionRepo.AddRevision(ctx, rev, autoUpdateRevisionID) @@ -67,6 +71,7 @@ func (rs *RevisionService) GetRevision(ctx context.Context, revisionID string) ( // ExistUnreviewedByObjectID func (rs *RevisionService) ExistUnreviewedByObjectID(ctx context.Context, objectID string) (revision *entity.Revision, exist bool, err error) { + objectID = uid.DeShortID(objectID) revision, exist, err = rs.revisionRepo.ExistUnreviewedByObjectID(ctx, objectID) return revision, exist, err } diff --git a/pkg/uid/sid.go b/pkg/uid/sid.go new file mode 100644 index 00000000..e3151bd2 --- /dev/null +++ b/pkg/uid/sid.go @@ -0,0 +1,102 @@ +package uid + +import ( + "strconv" +) + +const salt = int64(0) + +var AlphanumericSet = []rune{ + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', +} + +var AlphanumericIndex map[rune]int + +func init() { + AlphanumericIndex = make(map[rune]int, len(AlphanumericSet)) + for i, ru := range AlphanumericSet { + AlphanumericIndex[ru] = i + } +} + +// NumToString num to string +func NumToShortID(id int64) string { + sid := strconv.FormatInt(id, 10) + if len(sid) < 17 { + return "" + } + sTypeCode := sid[1:4] + sid = sid[4:int32(len(sid))] + id, err := strconv.ParseInt(sid, 10, 64) + if err != nil { + return "" + } + typeCode, err := strconv.ParseInt(sTypeCode, 10, 64) + if err != nil { + return "" + } + id = id + salt + // fmt.Println("[EN1]", typeCode, id) + var code []rune + var tcode []rune + for id > 0 { + idx := id % int64(len(AlphanumericSet)) + code = append(code, AlphanumericSet[idx]) + id = id / int64(len(AlphanumericSet)) + } + for typeCode > 0 { + idx := typeCode % int64(len(AlphanumericSet)) + tcode = append(tcode, AlphanumericSet[idx]) + typeCode = typeCode / int64(len(AlphanumericSet)) + } + // fmt.Println("[EN2]", string(tcode), string(code)) + return string(tcode) + string(code) +} + +// StringToNum string to num +func ShortIDToNum(code string) int64 { + if len(code) < 2 { + return 0 + } + scodeType := code[0:1] + code = code[1:int32(len(code))] + // fmt.Println("[DE1]", scodeType, code) + var id, codeType int64 + runes := []rune(code) + codeRunes := []rune(scodeType) + + for i := len(runes) - 1; i >= 0; i-- { + ru := runes[i] + idx := AlphanumericIndex[ru] + id = id*int64(len(AlphanumericSet)) + int64(idx) + } + for i := len(codeRunes) - 1; i >= 0; i-- { + ru := codeRunes[i] + idx := AlphanumericIndex[ru] + codeType = codeType*int64(len(AlphanumericSet)) + int64(idx) + } + id = id - salt + // fmt.Println("[DE2]", codeType, id) + + return 10000000000000000 + codeType*10000000000000 + id +} + +func EnShortID(id string) string { + num, err := strconv.ParseInt(id, 10, 64) + if err != nil { + return "" + } + return NumToShortID(num) +} +func DeShortID(sid string) string { + num, err := strconv.ParseInt(sid, 10, 64) + if err != nil { + return strconv.FormatInt(ShortIDToNum(sid), 10) + } + if num < 10000000000000000 { + return strconv.FormatInt(ShortIDToNum(sid), 10) + } + return sid +} diff --git a/pkg/uid/sid_test.go b/pkg/uid/sid_test.go new file mode 100644 index 00000000..d7086c87 --- /dev/null +++ b/pkg/uid/sid_test.go @@ -0,0 +1,43 @@ +package uid + +import ( + "fmt" + "strconv" + "testing" +) + +func Test_ShortID(t *testing.T) { + nums := []int64{ + 10030000000000689, 10010000000000676, 10020000000000658, 10020000000000654, + 10030000009000689, 10010000009000676, 10020000009000658, 10020000009999999, + 10030000090000689, 10010000090000676, 10020000090000658, 10020000099999999, + 10030000900000689, 10010000900000676, 10020000900000658, 10020000999999999, + 10030009000000689, 10010009000000676, 10020009000000658, 10020009999999999, + 10030090000000689, 10010090000000676, 10020090000000658, 10020099999999999, + 10030900000000689, 10010900000000676, 10020900000000658, 10020999999999999, + 10039000000000689, 10019000000000676, 10029000000000658, 10029999999999999, + 10610000000000689, 10610000000000676, 10610000000000658, 10610000000000654, + } + for _, num := range nums { + code := NumToShortID(num) + denum := ShortIDToNum(code) + fmt.Println(num, code, denum) + } +} + +func Test_EnDeShortID(t *testing.T) { + nums := []string{"0", "1", "10", "100", "1000", "10000", "100000", "1234567", "10000000000000000", "10010000000001316", "10030000000001316", "99999999999999999", "999999999999999999", "1999999999999999999"} + for _, num := range nums { + code := EnShortID(num) + denum := DeShortID(code) + fmt.Println(num, code, denum) + } +} + +func Test_Demo(t *testing.T) { + nums := []int64{0, 1, 10, 100, 1000, 10000, 100000, 1000000001316, 9000000001316, 10000000000000000, 10010000000001316, 10030000000001316, 99999999999999999, 999999999999999999, 1999999999999999999} + for _, num := range nums { + code := strconv.FormatInt(num, 36) //10 yo 16 + fmt.Println(num, code) + } +}