You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

rest_api.go 3.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. // Copyright (c) 2016- Daniel Oaks <daniel@danieloaks.net>
  2. // released under the MIT license
  3. // viewing and modifying accounts, registered channels, dlines, rehashing, etc
  4. package irc
  5. import (
  6. "encoding/json"
  7. "net/http"
  8. "time"
  9. "fmt"
  10. "github.com/gorilla/mux"
  11. )
  12. const restErr = "{\"error\":\"An unknown error occurred\"}"
  13. // restAPIServer is used to keep a link to the current running server since this is the best
  14. // way to do it, given how HTTP handlers dispatch and work.
  15. var restAPIServer *Server
  16. type restVersionResp struct {
  17. Version string `json:"version"`
  18. }
  19. type restStatusResp struct {
  20. Clients int `json:"clients"`
  21. Opers int `json:"opers"`
  22. Channels int `json:"channels"`
  23. }
  24. type restDLinesResp struct {
  25. DLines map[string]IPBanInfo `json:"dlines"`
  26. }
  27. type restAcct struct {
  28. Name string
  29. RegisteredAt time.Time `json:"registered-at"`
  30. Clients int
  31. }
  32. type restAccountsResp struct {
  33. Accounts map[string]restAcct `json:"accounts"`
  34. }
  35. type restRehashResp struct {
  36. Successful bool `json:"successful"`
  37. Error string `json:"error"`
  38. Time time.Time `json:"time"`
  39. }
  40. func restVersion(w http.ResponseWriter, r *http.Request) {
  41. rs := restVersionResp{
  42. Version: SemVer,
  43. }
  44. b, err := json.Marshal(rs)
  45. if err != nil {
  46. fmt.Fprintln(w, restErr)
  47. } else {
  48. fmt.Fprintln(w, string(b))
  49. }
  50. }
  51. func restStatus(w http.ResponseWriter, r *http.Request) {
  52. rs := restStatusResp{
  53. Clients: restAPIServer.clients.Count(),
  54. Opers: len(restAPIServer.operators),
  55. Channels: len(restAPIServer.channels),
  56. }
  57. b, err := json.Marshal(rs)
  58. if err != nil {
  59. fmt.Fprintln(w, restErr)
  60. } else {
  61. fmt.Fprintln(w, string(b))
  62. }
  63. }
  64. func restGetDLines(w http.ResponseWriter, r *http.Request) {
  65. rs := restDLinesResp{
  66. DLines: restAPIServer.dlines.AllBans(),
  67. }
  68. b, err := json.Marshal(rs)
  69. if err != nil {
  70. fmt.Fprintln(w, restErr)
  71. } else {
  72. fmt.Fprintln(w, string(b))
  73. }
  74. }
  75. func restGetAccounts(w http.ResponseWriter, r *http.Request) {
  76. rs := restAccountsResp{
  77. Accounts: make(map[string]restAcct),
  78. }
  79. // get accts
  80. for key, info := range restAPIServer.accounts {
  81. rs.Accounts[key] = restAcct{
  82. Name: info.Name,
  83. RegisteredAt: info.RegisteredAt,
  84. Clients: len(info.Clients),
  85. }
  86. }
  87. b, err := json.Marshal(rs)
  88. if err != nil {
  89. fmt.Fprintln(w, restErr)
  90. } else {
  91. fmt.Fprintln(w, string(b))
  92. }
  93. }
  94. func restRehash(w http.ResponseWriter, r *http.Request) {
  95. err := restAPIServer.rehash()
  96. rs := restRehashResp{
  97. Successful: err == nil,
  98. Time: time.Now(),
  99. }
  100. if err != nil {
  101. rs.Error = err.Error()
  102. }
  103. b, err := json.Marshal(rs)
  104. if err != nil {
  105. fmt.Fprintln(w, restErr)
  106. } else {
  107. fmt.Fprintln(w, string(b))
  108. }
  109. }
  110. func (s *Server) startRestAPI() {
  111. // so handlers can ref it later
  112. restAPIServer = s
  113. // start router
  114. r := mux.NewRouter()
  115. // GET methods
  116. rg := r.Methods("GET").Subrouter()
  117. rg.HandleFunc("/version", restVersion)
  118. rg.HandleFunc("/status", restStatus)
  119. rg.HandleFunc("/dlines", restGetDLines)
  120. rg.HandleFunc("/accounts", restGetAccounts)
  121. // PUT methods
  122. rp := r.Methods("POST").Subrouter()
  123. rp.HandleFunc("/rehash", restRehash)
  124. // start api
  125. go http.ListenAndServe(s.restAPI.Listen, r)
  126. }