Added topics validation, fixed repo topics duplication (#4031)
Signed-off-by: Alexey Terentyev <axifnx@gmail.com>
This commit is contained in:
parent
85414d8b75
commit
42096c63e8
|
|
@ -11,6 +11,7 @@ import (
|
|||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"github.com/go-xorm/builder"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
|
@ -20,6 +21,8 @@ func init() {
|
|||
)
|
||||
}
|
||||
|
||||
var topicPattern = regexp.MustCompile(`^[a-z0-9+#_.-]+$`)
|
||||
|
||||
// Topic represents a topic of repositories
|
||||
type Topic struct {
|
||||
ID int64
|
||||
|
|
@ -51,6 +54,26 @@ func (err ErrTopicNotExist) Error() string {
|
|||
return fmt.Sprintf("topic is not exist [name: %s]", err.Name)
|
||||
}
|
||||
|
||||
func TopicValidator(topic string) bool {
|
||||
return len(topic) <= 35 && topicPattern.MatchString(topic)
|
||||
}
|
||||
|
||||
// Remove duplicates from topics slice
|
||||
func RemoveDuplicateTopics(topics []string) []string {
|
||||
// Map to record duplicates
|
||||
saved := make(map[string]struct{}, len(topics))
|
||||
i := 0
|
||||
for _, v := range topics {
|
||||
v = strings.TrimSpace(strings.ToLower(v))
|
||||
if _, ok := saved[v]; !ok {
|
||||
saved[v] = struct{}{}
|
||||
topics[i] = v
|
||||
i++
|
||||
}
|
||||
}
|
||||
return topics[:i]
|
||||
}
|
||||
|
||||
// GetTopicByName retrieves topic by name
|
||||
func GetTopicByName(name string) (*Topic, error) {
|
||||
var topic Topic
|
||||
|
|
|
|||
|
|
@ -1167,6 +1167,8 @@ branch.protected_deletion_failed = Branch '%s' is protected. It cannot be delete
|
|||
|
||||
topic.manage_topics = Manage Topics
|
||||
topic.done = Done
|
||||
topic.count_prompt = You can't select more than 25 topics
|
||||
topic.format_prompt = Topics must use letter or number and can include hyphen(-), underscore(_), plus(+), hash(#), dot(.) with max length of 35
|
||||
|
||||
[org]
|
||||
org_name_holder = Organization Name
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import (
|
|||
)
|
||||
|
||||
// TopicPost response for creating repository
|
||||
func TopicPost(ctx *context.Context) {
|
||||
func TopicsPost(ctx *context.Context) {
|
||||
if ctx.User == nil {
|
||||
ctx.JSON(403, map[string]interface{}{
|
||||
"message": "Only owners could change the topics.",
|
||||
|
|
@ -27,6 +27,33 @@ func TopicPost(ctx *context.Context) {
|
|||
topics = strings.Split(topicsStr, ",")
|
||||
}
|
||||
|
||||
topics = models.RemoveDuplicateTopics(topics)
|
||||
|
||||
if len(topics) > 25 {
|
||||
log.Error(2, "Incorrect number of topics(max 25): %v", )
|
||||
ctx.JSON(422, map[string]interface{}{
|
||||
"invalidTopics": topics[:0],
|
||||
"message": ctx.Tr("repo.topic.count_error"),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
var invalidTopics = make([]string, 0)
|
||||
for _, topic := range topics {
|
||||
if !models.TopicValidator(topic) {
|
||||
invalidTopics = append(invalidTopics, topic)
|
||||
}
|
||||
}
|
||||
|
||||
if len(invalidTopics) > 0 {
|
||||
log.Error(2, "Invalid topics: %v", invalidTopics)
|
||||
ctx.JSON(422, map[string]interface{}{
|
||||
"invalidTopics": invalidTopics,
|
||||
"message": ctx.Tr("repo.topic.pattern_error"),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
err := models.SaveTopics(ctx.Repo.Repository.ID, topics...)
|
||||
if err != nil {
|
||||
log.Error(2, "SaveTopics failed: %v", err)
|
||||
|
|
|
|||
|
|
@ -626,7 +626,7 @@ func RegisterRoutes(m *macaron.Macaron) {
|
|||
}, context.RepoAssignment(), context.UnitTypes(), context.LoadRepoUnits(), context.CheckUnit(models.UnitTypeReleases))
|
||||
|
||||
m.Group("/:username/:reponame", func() {
|
||||
m.Post("/topics", repo.TopicPost)
|
||||
m.Post("/topics", repo.TopicsPost)
|
||||
}, context.RepoAssignment(), reqRepoAdmin)
|
||||
|
||||
m.Group("/:username/:reponame", func() {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user