1package api 2 3import ( 4 "encoding/json" 5 "net/http" 6 "strings" 7 "time" 8 9 "github.com/0xERR0R/blocky/util" 10 11 "github.com/go-chi/chi" 12 log "github.com/sirupsen/logrus" 13) 14 15// BlockingControl interface to control the blocking status 16type BlockingControl interface { 17 EnableBlocking() 18 DisableBlocking(duration time.Duration, disableGroups []string) error 19 BlockingStatus() BlockingStatus 20} 21 22// ListRefresher interface to control the list refresh 23type ListRefresher interface { 24 RefreshLists() 25} 26 27// BlockingEndpoint endpoint for the blocking status control 28type BlockingEndpoint struct { 29 control BlockingControl 30} 31 32// ListRefreshEndpoint endpoint for list refresh 33type ListRefreshEndpoint struct { 34 refresher ListRefresher 35} 36 37// RegisterEndpoint registers an implementation as HTTP endpoint 38func RegisterEndpoint(router chi.Router, t interface{}) { 39 if a, ok := t.(BlockingControl); ok { 40 registerBlockingEndpoints(router, a) 41 } 42 43 if a, ok := t.(ListRefresher); ok { 44 registerListRefreshEndpoints(router, a) 45 } 46} 47 48func registerListRefreshEndpoints(router chi.Router, refresher ListRefresher) { 49 l := &ListRefreshEndpoint{refresher} 50 51 router.Post(PathListsRefresh, l.apiListRefresh) 52} 53 54// apiListRefresh is the http endpoint to trigger the refresh of all lists 55// @Summary List refresh 56// @Description Refresh all lists 57// @Tags lists 58// @Success 200 "Lists were reloaded" 59// @Router /lists/refresh [post] 60func (l *ListRefreshEndpoint) apiListRefresh(_ http.ResponseWriter, _ *http.Request) { 61 l.refresher.RefreshLists() 62} 63 64func registerBlockingEndpoints(router chi.Router, control BlockingControl) { 65 s := &BlockingEndpoint{control} 66 // register API endpoints 67 router.Get(PathBlockingEnablePath, s.apiBlockingEnable) 68 router.Get(PathBlockingDisablePath, s.apiBlockingDisable) 69 router.Get(PathBlockingStatusPath, s.apiBlockingStatus) 70} 71 72// apiBlockingEnable is the http endpoint to enable the blocking status 73// @Summary Enable blocking 74// @Description enable the blocking status 75// @Tags blocking 76// @Success 200 "Blocking is enabled" 77// @Router /blocking/enable [get] 78func (s *BlockingEndpoint) apiBlockingEnable(_ http.ResponseWriter, _ *http.Request) { 79 log.Info("enabling blocking...") 80 81 s.control.EnableBlocking() 82} 83 84// apiBlockingDisable is the http endpoint to disable the blocking status 85// @Summary Disable blocking 86// @Description disable the blocking status 87// @Tags blocking 88// @Param duration query string false "duration of blocking (Example: 300s, 5m, 1h, 5m30s)" Format(duration) 89// @Param groups query string false "groups to disable (comma separated). If empty, disable all groups" Format(string) 90// @Success 200 "Blocking is disabled" 91// @Failure 400 "Wrong duration format" 92// @Failure 400 "Unknown group" 93// @Router /blocking/disable [get] 94func (s *BlockingEndpoint) apiBlockingDisable(rw http.ResponseWriter, req *http.Request) { 95 var ( 96 duration time.Duration 97 groups []string 98 err error 99 ) 100 101 // parse duration from query parameter 102 durationParam := req.URL.Query().Get("duration") 103 if len(durationParam) > 0 { 104 duration, err = time.ParseDuration(durationParam) 105 if err != nil { 106 log.Errorf("wrong duration format '%s'", durationParam) 107 rw.WriteHeader(http.StatusBadRequest) 108 109 return 110 } 111 } 112 113 groupsParam := req.URL.Query().Get("groups") 114 if len(groupsParam) > 0 { 115 groups = strings.Split(groupsParam, ",") 116 } 117 118 err = s.control.DisableBlocking(duration, groups) 119 if err != nil { 120 log.Error("can't disable the blocking: ", err) 121 rw.WriteHeader(http.StatusBadRequest) 122 } 123} 124 125// apiBlockingStatus is the http endpoint to get current blocking status 126// @Summary Blocking status 127// @Description get current blocking status 128// @Tags blocking 129// @Produce json 130// @Success 200 {object} api.BlockingStatus "Returns current blocking status" 131// @Router /blocking/status [get] 132func (s *BlockingEndpoint) apiBlockingStatus(rw http.ResponseWriter, _ *http.Request) { 133 status := s.control.BlockingStatus() 134 135 response, _ := json.Marshal(status) 136 _, err := rw.Write(response) 137 138 util.LogOnError("unable to write response ", err) 139} 140