diff --git a/README.md b/README.md index 3218706f..906ae536 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). For the purpo ## Features -* UTF-8 nick and channel names with rfc7613 +* UTF-8 nick and channel names with rfc7613 (PRECIS) * [yaml](http://yaml.org/) configuration * native TLS/SSL support * server password (`PASS` command) @@ -32,7 +32,6 @@ This project adheres to [Semantic Versioning](http://semver.org/). For the purpo * banning ips/nets and masks with `KLINE` and `DLINE` * [IRCv3 support](http://ircv3.net/software/servers.html) * a heavy focus on developing with [specifications](http://oragono.io/specs.html) -* integrated (alpha) REST API and web interface ## Installation @@ -131,27 +130,6 @@ After this, your channel will remember the fact that you're the owner, the topic Make sure to setup [SASL](https://freenode.net/kb/answer/sasl) in your client to automatically login to your account when you next join the server. - - # Credits * Jeremy Latt, creator of Ergonomadic, diff --git a/docs/INFO.md b/docs/INFO.md index 56b3e2eb..8560431a 100644 --- a/docs/INFO.md +++ b/docs/INFO.md @@ -72,21 +72,6 @@ This will make the server rehash its configuration files and TLS certificates, a useful if you're automatically updating your TLS certs! -## REST API - -Oragono contains a draft, very early REST API implementation. My plans for this is to allow -external web interfaces or other automated programs to monitor what's going on with the -server, apply/remove bans, and to essentially allow administration of the server without -being connected to it and opered-up. This sort of API mimics InspIRCd and Anope, which -contain similar APIs. - -I'm not sure exactly how it's going to continue to be developed, and I'm sure there'll be -lots of changes around appropriately restricting access to the API, which is why it's -disabled for now and not exposed in our Docker builds. As well, while it's very unstable, -the REST API doesn't count for our SemVer versioning. When this feature is more developed -and I'm happy with where it's at, I'll provide proper support and documentation for the API. - - ## Rejected Features 'Rejected' sounds harsh, but basically these are features I've decided I'm not gonna diff --git a/irc/config.go b/irc/config.go index 24f2d324..22dcfdf0 100644 --- a/irc/config.go +++ b/irc/config.go @@ -108,12 +108,6 @@ func (conf *OperConfig) PasswordBytes() []byte { return bytes } -// RestAPIConfig controls the integrated REST API. -type RestAPIConfig struct { - Enabled bool - Listen string -} - // ConnectionLimitsConfig controls the automated connection limits. type ConnectionLimitsConfig struct { Enabled bool @@ -198,8 +192,7 @@ type Config struct { Listen []string TLSListeners map[string]*TLSListenConfig `yaml:"tls-listeners"` STS STSConfig - RestAPI RestAPIConfig `yaml:"rest-api"` - CheckIdent bool `yaml:"check-ident"` + CheckIdent bool `yaml:"check-ident"` MOTD string ProxyAllowedFrom []string `yaml:"proxy-allowed-from"` MaxSendQString string `yaml:"max-sendq"` diff --git a/irc/rest_api.go b/irc/rest_api.go deleted file mode 100644 index 817406ed..00000000 --- a/irc/rest_api.go +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright (c) 2016-2017 Daniel Oaks -// released under the MIT license - -// viewing and modifying accounts, registered channels, dlines, rehashing, etc - -package irc - -import ( - "encoding/json" - "net/http" - "strconv" - "time" - - "fmt" - - "github.com/gorilla/mux" - "github.com/tidwall/buntdb" -) - -const restErr = "{\"error\":\"An unknown error occurred\"}" - -// ircServer is used to keep a link to the current running server since this is the best -// way to do it, given how HTTP handlers dispatch and work. -var ircServer *Server - -type restInfoResp struct { - ServerName string `json:"server-name"` - NetworkName string `json:"network-name"` - - Version string `json:"version"` -} - -type restStatusResp struct { - Clients int `json:"clients"` - Opers int `json:"opers"` - Channels int `json:"channels"` -} - -type restXLinesResp struct { - DLines map[string]IPBanInfo `json:"dlines"` - KLines map[string]IPBanInfo `json:"klines"` -} - -type restAcct struct { - Name string `json:"name"` - RegisteredAt time.Time `json:"registered-at"` - Clients int `json:"clients"` -} - -type restAccountsResp struct { - Verified map[string]restAcct `json:"verified"` -} - -type restRehashResp struct { - Successful bool `json:"successful"` - Error string `json:"error"` - Time time.Time `json:"time"` -} - -func restInfo(w http.ResponseWriter, r *http.Request) { - rs := restInfoResp{ - Version: SemVer, - ServerName: ircServer.name, - NetworkName: ircServer.networkName, - } - b, err := json.Marshal(rs) - if err != nil { - fmt.Fprintln(w, restErr) - } else { - fmt.Fprintln(w, string(b)) - } -} - -func restStatus(w http.ResponseWriter, r *http.Request) { - rs := restStatusResp{ - Clients: ircServer.clients.Count(), - Opers: len(ircServer.operators), - Channels: ircServer.channels.Len(), - } - b, err := json.Marshal(rs) - if err != nil { - fmt.Fprintln(w, restErr) - } else { - fmt.Fprintln(w, string(b)) - } -} - -func restGetXLines(w http.ResponseWriter, r *http.Request) { - rs := restXLinesResp{ - DLines: ircServer.dlines.AllBans(), - KLines: ircServer.klines.AllBans(), - } - b, err := json.Marshal(rs) - if err != nil { - fmt.Fprintln(w, restErr) - } else { - fmt.Fprintln(w, string(b)) - } -} - -func restGetAccounts(w http.ResponseWriter, r *http.Request) { - rs := restAccountsResp{ - Verified: make(map[string]restAcct), - } - - // get accounts - err := ircServer.store.View(func(tx *buntdb.Tx) error { - tx.AscendKeys("account.exists *", func(key, value string) bool { - key = key[len("account.exists "):] - _, err := tx.Get(fmt.Sprintf(keyAccountVerified, key)) - verified := err == nil - fmt.Println(fmt.Sprintf(keyAccountVerified, key)) - - // get other details - name, _ := tx.Get(fmt.Sprintf(keyAccountName, key)) - regTimeStr, _ := tx.Get(fmt.Sprintf(keyAccountRegTime, key)) - regTimeInt, _ := strconv.ParseInt(regTimeStr, 10, 64) - regTime := time.Unix(regTimeInt, 0) - - var clients int - acct := ircServer.accounts[key] - if acct != nil { - clients = len(acct.Clients) - } - - if verified { - rs.Verified[key] = restAcct{ - Name: name, - RegisteredAt: regTime, - Clients: clients, - } - } else { - //TODO(dan): Add to unverified list - } - - return true // true to continue I guess? - }) - - return nil - }) - - b, err := json.Marshal(rs) - if err != nil { - fmt.Fprintln(w, restErr) - } else { - fmt.Fprintln(w, string(b)) - } -} - -func restRehash(w http.ResponseWriter, r *http.Request) { - err := ircServer.rehash() - - rs := restRehashResp{ - Successful: err == nil, - Time: time.Now(), - } - if err != nil { - rs.Error = err.Error() - } - - b, err := json.Marshal(rs) - if err != nil { - fmt.Fprintln(w, restErr) - } else { - fmt.Fprintln(w, string(b)) - } -} - -func StartRestAPI(s *Server, listenAddr string) (*http.Server, error) { - // so handlers can ref it later - ircServer = s - - // start router - r := mux.NewRouter() - - // GET methods - rg := r.Methods("GET").Subrouter() - rg.HandleFunc("/info", restInfo) - rg.HandleFunc("/status", restStatus) - rg.HandleFunc("/xlines", restGetXLines) - rg.HandleFunc("/accounts", restGetAccounts) - - // PUT methods - rp := r.Methods("POST").Subrouter() - rp.HandleFunc("/rehash", restRehash) - - // start api - httpserver := http.Server{ - Addr: listenAddr, - Handler: r, - } - - go func() { - if err := httpserver.ListenAndServe(); err != nil { - s.logger.Error("listeners", fmt.Sprintf("Rest API listenAndServe error: %s", err)) - } - }() - - return &httpserver, nil -} diff --git a/irc/server.go b/irc/server.go index 555afcc0..8e411b1a 100644 --- a/irc/server.go +++ b/irc/server.go @@ -7,14 +7,12 @@ package irc import ( "bufio" - "context" "crypto/tls" "encoding/base64" "fmt" "log" "math/rand" "net" - "net/http" "os" "os/signal" "strconv" @@ -39,14 +37,6 @@ var ( couldNotParseIPMsg, _ = (&[]ircmsg.IrcMessage{ircmsg.MakeMessage(nil, "", "ERROR", "Unable to parse your IP address")}[0]).Line() ) -const ( - // when shutting down the REST server, wait this long - // before killing active connections. TODO: this might not be - // necessary at all? but it seems prudent to avoid potential resource - // leaks - httpShutdownTimeout = time.Second -) - // Limits holds the maximum limits for various things such as topic lengths. type Limits struct { AwayLen int @@ -116,8 +106,6 @@ type Server struct { registeredChannelsMutex sync.RWMutex rehashMutex sync.Mutex rehashSignal chan os.Signal - restAPI RestAPIConfig - restAPIServer *http.Server proxyAllowedFrom []string signals chan os.Signal snomasks *SnoManager @@ -1445,7 +1433,6 @@ func (server *Server) applyConfig(config *Config, initial bool) error { // we are now open for business server.setupListeners(config) - server.setupRestAPI(config) return nil } @@ -1583,32 +1570,6 @@ func (server *Server) setupListeners(config *Config) { } } -func (server *Server) setupRestAPI(config *Config) { - restAPIEnabled := config.Server.RestAPI.Enabled - restAPIStarted := server.restAPIServer != nil - restAPIListenAddrChanged := server.restAPI.Listen != config.Server.RestAPI.Listen - - // stop an existing REST server if it's been disabled or the addr changed - if restAPIStarted && (!restAPIEnabled || restAPIListenAddrChanged) { - ctx, _ := context.WithTimeout(context.Background(), httpShutdownTimeout) - server.restAPIServer.Shutdown(ctx) - server.restAPIServer.Close() - server.logger.Info("rehash", "server", fmt.Sprintf("%s rest API stopped on %s.", server.name, server.restAPI.Listen)) - server.restAPIServer = nil - } - - // start a new one if it's enabled or the addr changed - if restAPIEnabled && (!restAPIStarted || restAPIListenAddrChanged) { - server.restAPIServer, _ = StartRestAPI(server, config.Server.RestAPI.Listen) - server.logger.Info( - "rehash", "server", - fmt.Sprintf("%s rest API started on %s.", server.name, config.Server.RestAPI.Listen)) - } - - // save the config information - server.restAPI = config.Server.RestAPI -} - func (server *Server) GetDefaultChannelModes() Modes { server.configurableStateMutex.RLock() defer server.configurableStateMutex.RUnlock() diff --git a/oragono-web.yaml b/oragono-web.yaml deleted file mode 100644 index 341069f5..00000000 --- a/oragono-web.yaml +++ /dev/null @@ -1,17 +0,0 @@ -# oragono web interface config - -# hostname of the web interface -hostname: localhost - -# address to listen on -listen: "localhost:8090" - -# tls listeners -tls-listeners: - # listener on ":6697" - ":8090": - key: web-tls.key - cert: web-tls.crt - -# log level, one of error, warn, info, debug -log: debug diff --git a/oragono.yaml b/oragono.yaml index e601954c..b759cece 100644 --- a/oragono.yaml +++ b/oragono.yaml @@ -43,14 +43,6 @@ server: # should clients include this STS policy when they ship their inbuilt preload lists? preload: false - # rest management API, for use with web interface - rest-api: - # whether the API is enabled or not - enabled: false - - # rest API listening port - listen: "localhost:8090" - # use ident protocol to get usernames check-ident: true diff --git a/web/config.go b/web/config.go deleted file mode 100644 index fa68e03e..00000000 --- a/web/config.go +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) 2012-2014 Jeremy Latt -// Copyright (c) 2014-2015 Edmund Huber -// Copyright (c) 2016 Daniel Oaks -// released under the MIT license - -package web - -import ( - "crypto/tls" - "errors" - "io/ioutil" - "log" - - "gopkg.in/yaml.v2" -) - -// TLSListenConfig defines configuration options for listening on TLS -type TLSListenConfig struct { - Cert string - Key string -} - -// Certificate returns the TLS certificate assicated with this TLSListenConfig -func (conf *TLSListenConfig) Config() (*tls.Config, error) { - cert, err := tls.LoadX509KeyPair(conf.Cert, conf.Key) - if err != nil { - return nil, errors.New("tls cert+key: invalid pair") - } - - return &tls.Config{ - Certificates: []tls.Certificate{cert}, - }, err -} - -type Config struct { - Host string - Listen string - TLSListenersConf map[string]*TLSListenConfig `yaml:"tls-listeners"` - Log string -} - -func (conf *Config) TLSListeners() map[string]*tls.Config { - tlsListeners := make(map[string]*tls.Config) - for s, tlsListenersConf := range conf.TLSListenersConf { - config, err := tlsListenersConf.Config() - if err != nil { - log.Fatal(err) - } - tlsListeners[name] = config - } - return tlsListeners -} - -func LoadConfig(filename string) (config *Config, err error) { - data, err := ioutil.ReadFile(filename) - if err != nil { - return nil, err - } - - err = yaml.Unmarshal(data, &config) - if err != nil { - return nil, err - } - - if config.Listen == "" { - return nil, errors.New("Listening address missing") - } - - return config, nil -} diff --git a/web/server.go b/web/server.go deleted file mode 100644 index 66573aaa..00000000 --- a/web/server.go +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2012-2014 Jeremy Latt -// Copyright (c) 2014-2015 Edmund Huber -// Copyright (c) 2016 Daniel Oaks -// released under the MIT license - -package web - -// Server is the webserver -type Server struct { -} - -// NewServer returns a new Oragono server. -func NewServer(config *Config) *Server { - server := &Server{} - - return server -} - -func (*Server) Run() { - -}