mirror of https://gitee.com/answerdev/answer.git
add question operation
This commit is contained in:
parent
5361f4e127
commit
b0d2cdc4a0
54
docs/docs.go
54
docs/docs.go
|
@ -3168,6 +3168,45 @@ const docTemplate = `{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/answer/api/v1/question/operation": {
|
||||||
|
"put": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"ApiKeyAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Operation question \\n operation [pin unpin hide show]",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Question"
|
||||||
|
],
|
||||||
|
"summary": "Operation question",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "question",
|
||||||
|
"name": "data",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/schema.OperationQuestionReq"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/handler.RespBody"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/answer/api/v1/question/page": {
|
"/answer/api/v1/question/page": {
|
||||||
"get": {
|
"get": {
|
||||||
"description": "get questions by page",
|
"description": "get questions by page",
|
||||||
|
@ -6739,6 +6778,21 @@ const docTemplate = `{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"schema.OperationQuestionReq": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"operation": {
|
||||||
|
"description": "operation [pin unpin hide show]",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"schema.PermissionMemberAction": {
|
"schema.PermissionMemberAction": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
|
@ -3156,6 +3156,45 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/answer/api/v1/question/operation": {
|
||||||
|
"put": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"ApiKeyAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Operation question \\n operation [pin unpin hide show]",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Question"
|
||||||
|
],
|
||||||
|
"summary": "Operation question",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "question",
|
||||||
|
"name": "data",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/schema.OperationQuestionReq"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/handler.RespBody"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/answer/api/v1/question/page": {
|
"/answer/api/v1/question/page": {
|
||||||
"get": {
|
"get": {
|
||||||
"description": "get questions by page",
|
"description": "get questions by page",
|
||||||
|
@ -6727,6 +6766,21 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"schema.OperationQuestionReq": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"operation": {
|
||||||
|
"description": "operation [pin unpin hide show]",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"schema.PermissionMemberAction": {
|
"schema.PermissionMemberAction": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
|
@ -983,6 +983,16 @@ definitions:
|
||||||
description: inbox achievement
|
description: inbox achievement
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
|
schema.OperationQuestionReq:
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: string
|
||||||
|
operation:
|
||||||
|
description: operation [pin unpin hide show]
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
type: object
|
||||||
schema.PermissionMemberAction:
|
schema.PermissionMemberAction:
|
||||||
properties:
|
properties:
|
||||||
action:
|
action:
|
||||||
|
@ -3888,6 +3898,30 @@ paths:
|
||||||
summary: get question details
|
summary: get question details
|
||||||
tags:
|
tags:
|
||||||
- Question
|
- Question
|
||||||
|
/answer/api/v1/question/operation:
|
||||||
|
put:
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
description: Operation question \n operation [pin unpin hide show]
|
||||||
|
parameters:
|
||||||
|
- description: question
|
||||||
|
in: body
|
||||||
|
name: data
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/schema.OperationQuestionReq'
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/handler.RespBody'
|
||||||
|
security:
|
||||||
|
- ApiKeyAuth: []
|
||||||
|
summary: Operation question
|
||||||
|
tags:
|
||||||
|
- Question
|
||||||
/answer/api/v1/question/page:
|
/answer/api/v1/question/page:
|
||||||
get:
|
get:
|
||||||
consumes:
|
consumes:
|
||||||
|
|
|
@ -70,6 +70,45 @@ func (qc *QuestionController) RemoveQuestion(ctx *gin.Context) {
|
||||||
handler.HandleResponse(ctx, err, nil)
|
handler.HandleResponse(ctx, err, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OperationQuestion Operation question
|
||||||
|
// @Summary Operation question
|
||||||
|
// @Description Operation question \n operation [pin unpin hide show]
|
||||||
|
// @Tags Question
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Param data body schema.OperationQuestionReq true "question"
|
||||||
|
// @Success 200 {object} handler.RespBody
|
||||||
|
// @Router /answer/api/v1/question/operation [put]
|
||||||
|
func (qc *QuestionController) OperationQuestion(ctx *gin.Context) {
|
||||||
|
req := &schema.OperationQuestionReq{}
|
||||||
|
if handler.BindAndCheck(ctx, req) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.ID = uid.DeShortID(req.ID)
|
||||||
|
req.UserID = middleware.GetLoginUserIDFromContext(ctx)
|
||||||
|
canList, err := qc.rankService.CheckOperationPermissions(ctx, req.UserID, []string{
|
||||||
|
permission.QuestionPin,
|
||||||
|
permission.QuestionHide,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
handler.HandleResponse(ctx, err, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.CanPin = canList[0]
|
||||||
|
req.CanList = canList[1]
|
||||||
|
if (req.Operation == schema.QuestionOperationPin || req.Operation == schema.QuestionOperationUnPin) && !req.CanPin {
|
||||||
|
handler.HandleResponse(ctx, errors.Forbidden(reason.RankFailToMeetTheCondition), nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (req.Operation == schema.QuestionOperationHide || req.Operation == schema.QuestionOperationShow) && !req.CanList {
|
||||||
|
handler.HandleResponse(ctx, errors.Forbidden(reason.RankFailToMeetTheCondition), nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
handler.HandleResponse(ctx, nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
// CloseQuestion Close question
|
// CloseQuestion Close question
|
||||||
// @Summary Close question
|
// @Summary Close question
|
||||||
// @Description Close question
|
// @Description Close question
|
||||||
|
|
|
@ -56,6 +56,7 @@ var migrations = []Migration{
|
||||||
NewMigration("add user role", addRoleFeatures, false),
|
NewMigration("add user role", addRoleFeatures, false),
|
||||||
NewMigration("add theme and private mode", addThemeAndPrivateMode, true),
|
NewMigration("add theme and private mode", addThemeAndPrivateMode, true),
|
||||||
NewMigration("add new answer notification", addNewAnswerNotification, true),
|
NewMigration("add new answer notification", addNewAnswerNotification, true),
|
||||||
|
NewMigration("add user pin hide features", addRolePinAndHideFeatures, true),
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCurrentDBVersion returns the current db version
|
// GetCurrentDBVersion returns the current db version
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
package migrations
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/answerdev/answer/internal/entity"
|
||||||
|
"github.com/answerdev/answer/internal/service/permission"
|
||||||
|
"xorm.io/xorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
func addRolePinAndHideFeatures(x *xorm.Engine) error {
|
||||||
|
|
||||||
|
powers := []*entity.Power{
|
||||||
|
{ID: 34, Name: "question pin", PowerType: permission.QuestionPin, Description: "Top or untop the question"},
|
||||||
|
{ID: 35, Name: "question hide", PowerType: permission.QuestionHide, Description: "hide or show the question"},
|
||||||
|
}
|
||||||
|
// insert default powers
|
||||||
|
for _, power := range powers {
|
||||||
|
exist, err := x.Get(&entity.Power{ID: power.ID})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if exist {
|
||||||
|
_, err = x.ID(power.ID).Update(power)
|
||||||
|
} else {
|
||||||
|
_, err = x.Insert(power)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rolePowerRels := []*entity.RolePowerRel{
|
||||||
|
|
||||||
|
{RoleID: 2, PowerType: permission.QuestionPin},
|
||||||
|
{RoleID: 2, PowerType: permission.QuestionHide},
|
||||||
|
|
||||||
|
{RoleID: 3, PowerType: permission.QuestionPin},
|
||||||
|
{RoleID: 3, PowerType: permission.QuestionHide},
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert default powers
|
||||||
|
for _, rel := range rolePowerRels {
|
||||||
|
exist, err := x.Get(&entity.RolePowerRel{RoleID: rel.RoleID, PowerType: rel.PowerType})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if exist {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
_, err = x.Insert(rel)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -190,6 +190,7 @@ func (a *AnswerAPIRouter) RegisterAnswerAPIRouter(r *gin.RouterGroup) {
|
||||||
r.PUT("/question", a.questionController.UpdateQuestion)
|
r.PUT("/question", a.questionController.UpdateQuestion)
|
||||||
r.DELETE("/question", a.questionController.RemoveQuestion)
|
r.DELETE("/question", a.questionController.RemoveQuestion)
|
||||||
r.PUT("/question/status", a.questionController.CloseQuestion)
|
r.PUT("/question/status", a.questionController.CloseQuestion)
|
||||||
|
r.PUT("/question/operation", a.questionController.OperationQuestion)
|
||||||
r.PUT("/question/reopen", a.questionController.ReopenQuestion)
|
r.PUT("/question/reopen", a.questionController.ReopenQuestion)
|
||||||
r.GET("/question/similar", a.questionController.SearchByTitleLike)
|
r.GET("/question/similar", a.questionController.SearchByTitleLike)
|
||||||
|
|
||||||
|
|
|
@ -8,9 +8,13 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
SitemapMaxSize = 50000
|
SitemapMaxSize = 50000
|
||||||
SitemapCachekey = "answer@sitemap"
|
SitemapCachekey = "answer@sitemap"
|
||||||
SitemapPageCachekey = "answer@sitemap@page%d"
|
SitemapPageCachekey = "answer@sitemap@page%d"
|
||||||
|
QuestionOperationPin = "pin"
|
||||||
|
QuestionOperationUnPin = "unpin"
|
||||||
|
QuestionOperationHide = "hide"
|
||||||
|
QuestionOperationShow = "show"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RemoveQuestionReq delete question request
|
// RemoveQuestionReq delete question request
|
||||||
|
@ -28,6 +32,14 @@ type CloseQuestionReq struct {
|
||||||
UserID string `json:"-"` // user_id
|
UserID string `json:"-"` // user_id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type OperationQuestionReq struct {
|
||||||
|
ID string `validate:"required" json:"id"`
|
||||||
|
Operation string `json:"operation"` // operation [pin unpin hide show]
|
||||||
|
UserID string `json:"-"` // user_id
|
||||||
|
CanPin bool `json:"-"`
|
||||||
|
CanList bool `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
type CloseQuestionMeta struct {
|
type CloseQuestionMeta struct {
|
||||||
CloseType int `json:"close_type"`
|
CloseType int `json:"close_type"`
|
||||||
CloseMsg string `json:"close_msg"`
|
CloseMsg string `json:"close_msg"`
|
||||||
|
|
|
@ -10,6 +10,8 @@ const (
|
||||||
QuestionReopen = "question.reopen"
|
QuestionReopen = "question.reopen"
|
||||||
QuestionVoteUp = "question.vote_up"
|
QuestionVoteUp = "question.vote_up"
|
||||||
QuestionVoteDown = "question.vote_down"
|
QuestionVoteDown = "question.vote_down"
|
||||||
|
QuestionPin = "question.pin" //Top or untop the question
|
||||||
|
QuestionHide = "question.hide" //hide or show the question
|
||||||
AnswerAdd = "answer.add"
|
AnswerAdd = "answer.add"
|
||||||
AnswerEdit = "answer.edit"
|
AnswerEdit = "answer.edit"
|
||||||
AnswerEditWithoutReview = "answer.edit_without_review"
|
AnswerEditWithoutReview = "answer.edit_without_review"
|
||||||
|
|
Loading…
Reference in New Issue