diff --git a/main.go b/main.go index 493220b..b37fc55 100644 --- a/main.go +++ b/main.go @@ -108,7 +108,8 @@ type RejectionCondition struct { // Optional: label that must also match in addition to the app and version. If empty, does not check label. Label string `yaml:"label"` // Alternative to matching app names, match the content of the user text - UserTextMatch string `yaml:"usertextmatch"` + UserTextMatch string `yaml:"usertext"` + UserTextMatchReason string `yaml:"reason"` } // shouldReject returns true in two situations: @@ -116,16 +117,15 @@ type RejectionCondition struct { // - if the text provided by the user matches a regex specified in the rejection condition // // If any one of these do not match the condition, it is not rejected. -func (c RejectionCondition) shouldReject(appName, version string, labels []string, userText string) bool { +func (c RejectionCondition) shouldReject(appName, version string, labels []string, userText string) (reject bool, reason string) { if c.App != "" { if appName != c.App { - return false + return false, "" } // version was a condition and it doesn't match => accept it if version != c.Version && c.Version != "" { - return false + return false, "" } - // label was a condition and no label matches it => accept it if c.Label != "" { labelMatch := false @@ -136,30 +136,39 @@ func (c RejectionCondition) shouldReject(appName, version string, labels []strin } } if !labelMatch { - return false + return false, "" } } + return true, "this application is not allowed to send rageshakes to this server" } if c.UserTextMatch != "" { var userTextRegexp = regexp.MustCompile(c.UserTextMatch) if userTextRegexp.MatchString(userText) { - return true + fmt.Println("Match:", c.UserTextMatch) + fmt.Println("Reason:", c.UserTextMatchReason) + reason := c.UserTextMatchReason + if c.UserTextMatchReason == "" { + reason = "user text" + } + return true, reason } } - return true + // Nothing matches + return false, "" } -func (c *config) matchesRejectionCondition(p *payload) bool { +func (c *config) matchesRejectionCondition(p *payload) (match bool, reason string) { for _, rc := range c.RejectionConditions { version := "" if p.Data != nil { version = p.Data["Version"] } - if rc.shouldReject(p.AppName, version, p.Labels, p.UserText) { - return true + reject, reason := rc.shouldReject(p.AppName, version, p.Labels, p.UserText) + if reject { + return true, reason } } - return false + return false, "" } func basicAuth(handler http.Handler, username, password, realm string) http.Handler { diff --git a/rageshake.sample.yaml b/rageshake.sample.yaml index 991f837..ad49ef5 100644 --- a/rageshake.sample.yaml +++ b/rageshake.sample.yaml @@ -13,8 +13,11 @@ listings_auth_pass: secret allowed_app_names: [] # If any submission matches one of these rejection conditions, the submission is rejected. -# The 'app' field is required, but 'version' and 'label' are both optional. A condition with just -# an 'app' will reject that app altogether, effectively acting as a blocklist for app in contrast to allowed_app_names. +# You can either match an 'app' name, with optional 'version' and 'label' or the 'usertext' submitted by the user when describing their issue. +# +# Adding an 'app' item will reject that app altogether, effectively acting as a blocklist for app in contrast to allowed_app_names. You can optionally add 'version' and 'label' to fine-tune the rejection condition +# +# 'usertext' is a regex to reject user descriptions with an optional 'reason' text to send to the client rejection_conditions: - app: my-app version: "0.4.9" # if the submission has a Version which is exactly this value, reject the submission. @@ -23,7 +26,8 @@ rejection_conditions: - app: my-app version: "0.4.9" label: "nightly" # both label and Version must match for this condition to be true - - usertextmatch: "(\\w{4}\\s){11}\\w{4}" # reject text containing possible recovery keys + - usertext: "(\\w{4}\\s){11}\\w{4}" # reject text containing possible recovery keys + reason: "it matches a recovery key and recovery keys are private" # a GitHub personal access token (https://github.com/settings/tokens), which # will be used to create a GitHub issue for each report. It requires diff --git a/submit.go b/submit.go index 1ef5c6a..72d35a1 100644 --- a/submit.go +++ b/submit.go @@ -226,13 +226,15 @@ func (s *submitServer) handleSubmission(w http.ResponseWriter, req *http.Request http.Error(w, "This server does not accept rageshakes from your application. See https://github.com/matrix-org/rageshake/blob/master/docs/blocked_rageshake.md", 400) return } - if s.cfg.matchesRejectionCondition(p) { - log.Printf("Blocking rageshake from app %s because it matches a rejection_condition", p.AppName) + matchesRejection, reason := s.cfg.matchesRejectionCondition(p) + if matchesRejection { + log.Printf("Blocking rageshake from app %s because it matches a rejection_condition: %s", p.AppName, reason) if err := os.RemoveAll(reportDir); err != nil { log.Printf("Unable to remove report dir %s after rejected upload: %v\n", reportDir, err) } - http.Error(w, "This server does not accept rageshakes from your application + version. See https://github.com/matrix-org/rageshake/blob/master/docs/blocked_rageshake.md", 400) + userErrorText := fmt.Sprintf("This server did not accept the rageshake because it matches a rejection condition: %s. See https://github.com/matrix-org/rageshake/blob/master/docs/blocked_rageshake.md", reason) + http.Error(w, userErrorText, 400) return }