mirror of
https://github.com/ergochat/ergo.git
synced 2024-11-10 22:19:31 +01:00
Merge remote-tracking branch 'origin/master' into passhashing.2
This commit is contained in:
commit
cbc2b07d35
74
Gopkg.lock
generated
74
Gopkg.lock
generated
@ -2,132 +2,157 @@
|
|||||||
|
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:1bd4d273de93fce29ca3636145ccfcb932754f56e4c099297319e677e89f658d"
|
||||||
name = "code.cloudfoundry.org/bytefmt"
|
name = "code.cloudfoundry.org/bytefmt"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = ""
|
||||||
revision = "cbe033486cf0620d3bb77d8ef7f22ab346ad3628"
|
revision = "cbe033486cf0620d3bb77d8ef7f22ab346ad3628"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:20da7140359cab99772431cbeb195bd8cbe76312fcf6509fd8125cf91ab2847b"
|
||||||
name = "github.com/docopt/docopt-go"
|
name = "github.com/docopt/docopt-go"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = ""
|
||||||
revision = "ee0de3bc6815ee19d4a46c7eb90f829db0e014b1"
|
revision = "ee0de3bc6815ee19d4a46c7eb90f829db0e014b1"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:5d1f0cdebbc2a5237b572fa539bdb0aefea36780cdc1dbeda3b2f5d39f8f375d"
|
||||||
name = "github.com/goshuirc/e-nfa"
|
name = "github.com/goshuirc/e-nfa"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = ""
|
||||||
revision = "7071788e394065e6456458a5e9cb503cad545154"
|
revision = "7071788e394065e6456458a5e9cb503cad545154"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:d7ff716c49f33735c9e25e11b67e70f9eac7eb6c21b9806b0552b52541a568f5"
|
||||||
name = "github.com/goshuirc/irc-go"
|
name = "github.com/goshuirc/irc-go"
|
||||||
packages = [
|
packages = [
|
||||||
"ircfmt",
|
"ircfmt",
|
||||||
"ircmatch",
|
"ircmatch",
|
||||||
"ircmsg"
|
"ircmsg",
|
||||||
]
|
]
|
||||||
|
pruneopts = ""
|
||||||
revision = "8d136c4f92871c1c132bf702022363add479291b"
|
revision = "8d136c4f92871c1c132bf702022363add479291b"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:5be6259a2ab7350284d8c25b8df78153dcca360247be48ea7c55be37689802f4"
|
||||||
name = "github.com/mattn/go-colorable"
|
name = "github.com/mattn/go-colorable"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = ""
|
||||||
revision = "7dc3415be66d7cc68bf0182f35c8d31f8d2ad8a7"
|
revision = "7dc3415be66d7cc68bf0182f35c8d31f8d2ad8a7"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:78229b46ddb7434f881390029bd1af7661294af31f6802e0e1bedaad4ab0af3c"
|
||||||
name = "github.com/mattn/go-isatty"
|
name = "github.com/mattn/go-isatty"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = ""
|
||||||
revision = "0360b2af4f38e8d38c7fce2a9f4e702702d73a39"
|
revision = "0360b2af4f38e8d38c7fce2a9f4e702702d73a39"
|
||||||
version = "v0.0.3"
|
version = "v0.0.3"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:50416da10e189bc201e122e20078fb8e680a439cbdd24aaece06c434b4415b60"
|
||||||
name = "github.com/mgutz/ansi"
|
name = "github.com/mgutz/ansi"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = ""
|
||||||
revision = "9520e82c474b0a04dd04f8a40959027271bab992"
|
revision = "9520e82c474b0a04dd04f8a40959027271bab992"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:2251e6a17ea4a6eaa708882a1cda837aae3e425edbb190ef39b761ecf15a5c3d"
|
||||||
name = "github.com/oragono/go-ident"
|
name = "github.com/oragono/go-ident"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = ""
|
||||||
revision = "337fed0fd21ad538725cfcb55053ea4cf8056abc"
|
revision = "337fed0fd21ad538725cfcb55053ea4cf8056abc"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "github.com/stackimpact/stackimpact-go"
|
digest = "1:b28f2f9253cbb1bf2bcb3c0ab7421d2f88a245386199a6668b0a66eb09ce3e1f"
|
||||||
packages = [
|
|
||||||
".",
|
|
||||||
"internal",
|
|
||||||
"internal/pprof/profile"
|
|
||||||
]
|
|
||||||
revision = "8b5b02c181e477dafcf505342d8a79b5c8241da7"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/tidwall/btree"
|
name = "github.com/tidwall/btree"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = ""
|
||||||
revision = "9876f1454cf0993a53d74c27196993e345f50dd1"
|
revision = "9876f1454cf0993a53d74c27196993e345f50dd1"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:18342f164260096848ceff7c53cf797dbc1556d8161ad51cfc22281916209a5a"
|
||||||
name = "github.com/tidwall/buntdb"
|
name = "github.com/tidwall/buntdb"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = ""
|
||||||
revision = "2da7c106683f522198cdf55ed8db42b374de50d7"
|
revision = "2da7c106683f522198cdf55ed8db42b374de50d7"
|
||||||
version = "v1.0.0"
|
version = "v1.0.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:82fa3d995465f05e4c5e7f44a94d084b84a547ad77e41458fe9ec0877d04dced"
|
||||||
name = "github.com/tidwall/gjson"
|
name = "github.com/tidwall/gjson"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = ""
|
||||||
revision = "87033efcaec6215741137e8ca61952c53ef2685d"
|
revision = "87033efcaec6215741137e8ca61952c53ef2685d"
|
||||||
version = "v1.0.6"
|
version = "v1.0.6"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:bf59f997bab72b8ecd044aed35d706edb6abd6128afe0502c94398b2374f1f3f"
|
||||||
name = "github.com/tidwall/grect"
|
name = "github.com/tidwall/grect"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = ""
|
||||||
revision = "ba9a043346eba55344e40d66a5e74cfda3a9d293"
|
revision = "ba9a043346eba55344e40d66a5e74cfda3a9d293"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:4db4f92bb9cb04cfc4fccb36aba2598b02a988008c4cc0692b241214ad8ac96e"
|
||||||
name = "github.com/tidwall/match"
|
name = "github.com/tidwall/match"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = ""
|
||||||
revision = "1731857f09b1f38450e2c12409748407822dc6be"
|
revision = "1731857f09b1f38450e2c12409748407822dc6be"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:5d9d865e55b95f001e52a7f5d1f812e8a80f0f05d5b04ede006f24206ebba33c"
|
||||||
name = "github.com/tidwall/rtree"
|
name = "github.com/tidwall/rtree"
|
||||||
packages = [
|
packages = [
|
||||||
".",
|
".",
|
||||||
"base"
|
"base",
|
||||||
]
|
]
|
||||||
|
pruneopts = ""
|
||||||
revision = "6cd427091e0e662cb4f8e2c9eb1a41e1c46ff0d3"
|
revision = "6cd427091e0e662cb4f8e2c9eb1a41e1c46ff0d3"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:261a5770e68d10884a6d334396842d69ddb57ac5ecef60057eb5bce6f4bc7512"
|
||||||
name = "github.com/tidwall/tinyqueue"
|
name = "github.com/tidwall/tinyqueue"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = ""
|
||||||
revision = "1feaf062ef04a231c9126f99a68eaa579fd0e390"
|
revision = "1feaf062ef04a231c9126f99a68eaa579fd0e390"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:295363031beef7eb063d53138806b43f26c38d8a3e2543324ce2af3c766069de"
|
||||||
name = "golang.org/x/crypto"
|
name = "golang.org/x/crypto"
|
||||||
packages = [
|
packages = [
|
||||||
"bcrypt",
|
"bcrypt",
|
||||||
"blowfish",
|
"blowfish",
|
||||||
"ssh/terminal"
|
"ssh/terminal",
|
||||||
]
|
]
|
||||||
|
pruneopts = ""
|
||||||
revision = "5119cf507ed5294cc409c092980c7497ee5d6fd2"
|
revision = "5119cf507ed5294cc409c092980c7497ee5d6fd2"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:407b5f905024dd94ee08c1777fabb380fb3d380f92a7f7df2592be005337eeb3"
|
||||||
name = "golang.org/x/sys"
|
name = "golang.org/x/sys"
|
||||||
packages = [
|
packages = [
|
||||||
"unix",
|
"unix",
|
||||||
"windows"
|
"windows",
|
||||||
]
|
]
|
||||||
|
pruneopts = ""
|
||||||
revision = "37707fdb30a5b38865cfb95e5aab41707daec7fd"
|
revision = "37707fdb30a5b38865cfb95e5aab41707daec7fd"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:31985a0ed491dba5ba7fe92e18be008acd92ca9435ed9b35b06f3e6c00fd82cb"
|
||||||
name = "golang.org/x/text"
|
name = "golang.org/x/text"
|
||||||
packages = [
|
packages = [
|
||||||
"cases",
|
"cases",
|
||||||
@ -148,19 +173,36 @@
|
|||||||
"unicode/cldr",
|
"unicode/cldr",
|
||||||
"unicode/norm",
|
"unicode/norm",
|
||||||
"unicode/rangetable",
|
"unicode/rangetable",
|
||||||
"width"
|
"width",
|
||||||
]
|
]
|
||||||
|
pruneopts = ""
|
||||||
revision = "4e4a3210bb54bb31f6ab2cdca2edcc0b50c420c1"
|
revision = "4e4a3210bb54bb31f6ab2cdca2edcc0b50c420c1"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "v2"
|
branch = "v2"
|
||||||
|
digest = "1:4b4e5848dfe7f316f95f754df071bebfb40cf4482da62e17e7e1aebdf11f4918"
|
||||||
name = "gopkg.in/yaml.v2"
|
name = "gopkg.in/yaml.v2"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
|
pruneopts = ""
|
||||||
revision = "d670f9405373e636a5a2765eea47fac0c9bc91a4"
|
revision = "d670f9405373e636a5a2765eea47fac0c9bc91a4"
|
||||||
|
|
||||||
[solve-meta]
|
[solve-meta]
|
||||||
analyzer-name = "dep"
|
analyzer-name = "dep"
|
||||||
analyzer-version = 1
|
analyzer-version = 1
|
||||||
inputs-digest = "1f6e6db999e9e75b04aee6f0018be1557848f8248a28cf21783188fdeb866718"
|
input-imports = [
|
||||||
|
"code.cloudfoundry.org/bytefmt",
|
||||||
|
"github.com/docopt/docopt-go",
|
||||||
|
"github.com/goshuirc/irc-go/ircfmt",
|
||||||
|
"github.com/goshuirc/irc-go/ircmatch",
|
||||||
|
"github.com/goshuirc/irc-go/ircmsg",
|
||||||
|
"github.com/mattn/go-colorable",
|
||||||
|
"github.com/mgutz/ansi",
|
||||||
|
"github.com/oragono/go-ident",
|
||||||
|
"github.com/tidwall/buntdb",
|
||||||
|
"golang.org/x/crypto/bcrypt",
|
||||||
|
"golang.org/x/crypto/ssh/terminal",
|
||||||
|
"golang.org/x/text/secure/precis",
|
||||||
|
"gopkg.in/yaml.v2",
|
||||||
|
]
|
||||||
solver-name = "gps-cdcl"
|
solver-name = "gps-cdcl"
|
||||||
solver-version = 1
|
solver-version = 1
|
||||||
|
@ -75,10 +75,6 @@
|
|||||||
branch = "master"
|
branch = "master"
|
||||||
name = "github.com/mgutz/ansi"
|
name = "github.com/mgutz/ansi"
|
||||||
|
|
||||||
[[dependencies]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/stackimpact/stackimpact-go"
|
|
||||||
|
|
||||||
[[dependencies]]
|
[[dependencies]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "github.com/tidwall/buntdb"
|
name = "github.com/tidwall/buntdb"
|
||||||
|
@ -250,7 +250,7 @@ func (reg *ChannelRegistry) deleteChannel(tx *buntdb.Tx, key string, info Regist
|
|||||||
founder, _ := tx.Get(fmt.Sprintf(keyChannelFounder, key))
|
founder, _ := tx.Get(fmt.Sprintf(keyChannelFounder, key))
|
||||||
|
|
||||||
// to see if we're deleting the right channel, confirm the founder and the registration time
|
// to see if we're deleting the right channel, confirm the founder and the registration time
|
||||||
if founder == info.Founder && registeredAt == info.RegisteredAt {
|
if founder == info.Founder && registeredAt.Unix() == info.RegisteredAt.Unix() {
|
||||||
for _, keyFmt := range channelKeyStrings {
|
for _, keyFmt := range channelKeyStrings {
|
||||||
tx.Delete(fmt.Sprintf(keyFmt, key))
|
tx.Delete(fmt.Sprintf(keyFmt, key))
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,9 @@ invoking the command without a code will display the necessary code.`,
|
|||||||
helpShort: `$bUNREGISTER$b deletes a channel registration.`,
|
helpShort: `$bUNREGISTER$b deletes a channel registration.`,
|
||||||
enabled: chanregEnabled,
|
enabled: chanregEnabled,
|
||||||
},
|
},
|
||||||
|
"drop": {
|
||||||
|
aliasOf: "unregister",
|
||||||
|
},
|
||||||
"amode": {
|
"amode": {
|
||||||
handler: csAmodeHandler,
|
handler: csAmodeHandler,
|
||||||
help: `Syntax: $bAMODE #channel [mode change] [account]$b
|
help: `Syntax: $bAMODE #channel [mode change] [account]$b
|
||||||
|
@ -7,7 +7,6 @@ package irc
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"net"
|
"net"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -82,8 +81,8 @@ type Client struct {
|
|||||||
vhost string
|
vhost string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClient returns a client with all the appropriate info setup.
|
// NewClient sets up a new client and starts its goroutine.
|
||||||
func NewClient(server *Server, conn net.Conn, isTLS bool) *Client {
|
func NewClient(server *Server, conn net.Conn, isTLS bool) {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
config := server.Config()
|
config := server.Config()
|
||||||
fullLineLenLimit := config.Limits.LineLen.Tags + config.Limits.LineLen.Rest
|
fullLineLenLimit := config.Limits.LineLen.Tags + config.Limits.LineLen.Rest
|
||||||
@ -114,15 +113,17 @@ func NewClient(server *Server, conn net.Conn, isTLS bool) *Client {
|
|||||||
}
|
}
|
||||||
if config.Server.CheckIdent && !utils.AddrIsUnix(conn.RemoteAddr()) {
|
if config.Server.CheckIdent && !utils.AddrIsUnix(conn.RemoteAddr()) {
|
||||||
_, serverPortString, err := net.SplitHostPort(conn.LocalAddr().String())
|
_, serverPortString, err := net.SplitHostPort(conn.LocalAddr().String())
|
||||||
|
if err != nil {
|
||||||
|
server.logger.Error("internal", "bad server address", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
serverPort, _ := strconv.Atoi(serverPortString)
|
serverPort, _ := strconv.Atoi(serverPortString)
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
clientHost, clientPortString, err := net.SplitHostPort(conn.RemoteAddr().String())
|
clientHost, clientPortString, err := net.SplitHostPort(conn.RemoteAddr().String())
|
||||||
clientPort, _ := strconv.Atoi(clientPortString)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
server.logger.Error("internal", "bad client address", err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
clientPort, _ := strconv.Atoi(clientPortString)
|
||||||
|
|
||||||
client.Notice(client.t("*** Looking up your username"))
|
client.Notice(client.t("*** Looking up your username"))
|
||||||
resp, err := ident.Query(clientHost, serverPort, clientPort, IdentTimeoutSeconds)
|
resp, err := ident.Query(clientHost, serverPort, clientPort, IdentTimeoutSeconds)
|
||||||
@ -141,8 +142,6 @@ func NewClient(server *Server, conn net.Conn, isTLS bool) *Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
go client.run()
|
go client.run()
|
||||||
|
|
||||||
return client
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *Client) resetFakelag() {
|
func (client *Client) resetFakelag() {
|
||||||
@ -766,11 +765,12 @@ func (client *Client) destroy(beingResumed bool) {
|
|||||||
|
|
||||||
// send quit messages to friends
|
// send quit messages to friends
|
||||||
if !beingResumed {
|
if !beingResumed {
|
||||||
|
if client.Registered() {
|
||||||
client.server.stats.ChangeTotal(-1)
|
client.server.stats.ChangeTotal(-1)
|
||||||
|
}
|
||||||
if client.HasMode(modes.Invisible) {
|
if client.HasMode(modes.Invisible) {
|
||||||
client.server.stats.ChangeInvisible(-1)
|
client.server.stats.ChangeInvisible(-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if client.HasMode(modes.Operator) || client.HasMode(modes.LocalOperator) {
|
if client.HasMode(modes.Operator) || client.HasMode(modes.LocalOperator) {
|
||||||
client.server.stats.ChangeOperators(-1)
|
client.server.stats.ChangeOperators(-1)
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,6 @@ type AccountRegistrationConfig struct {
|
|||||||
VerifyMessage string `yaml:"verify-message"`
|
VerifyMessage string `yaml:"verify-message"`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AllowMultiplePerConnection bool `yaml:"allow-multiple-per-connection"`
|
|
||||||
BcryptCost uint `yaml:"bcrypt-cost"`
|
BcryptCost uint `yaml:"bcrypt-cost"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,13 +192,6 @@ func (sts *STSConfig) Value() string {
|
|||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
// StackImpactConfig is the config used for StackImpact's profiling.
|
|
||||||
type StackImpactConfig struct {
|
|
||||||
Enabled bool
|
|
||||||
AgentKey string `yaml:"agent-key"`
|
|
||||||
AppName string `yaml:"app-name"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type FakelagConfig struct {
|
type FakelagConfig struct {
|
||||||
Enabled bool
|
Enabled bool
|
||||||
Window time.Duration
|
Window time.Duration
|
||||||
@ -266,7 +258,6 @@ type Config struct {
|
|||||||
Debug struct {
|
Debug struct {
|
||||||
RecoverFromErrors *bool `yaml:"recover-from-errors"`
|
RecoverFromErrors *bool `yaml:"recover-from-errors"`
|
||||||
PprofListener *string `yaml:"pprof-listener"`
|
PprofListener *string `yaml:"pprof-listener"`
|
||||||
StackImpact StackImpactConfig
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Limits Limits
|
Limits Limits
|
||||||
@ -406,17 +397,17 @@ func (conf *Config) Operators(oc map[string]*OperClass) (map[string]*Oper, error
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TLSListeners returns a list of TLS listeners and their configs.
|
// TLSListeners returns a list of TLS listeners and their configs.
|
||||||
func (conf *Config) TLSListeners() map[string]*tls.Config {
|
func (conf *Config) TLSListeners() (map[string]*tls.Config, error) {
|
||||||
tlsListeners := make(map[string]*tls.Config)
|
tlsListeners := make(map[string]*tls.Config)
|
||||||
for s, tlsListenersConf := range conf.Server.TLSListeners {
|
for s, tlsListenersConf := range conf.Server.TLSListeners {
|
||||||
config, err := tlsListenersConf.Config()
|
config, err := tlsListenersConf.Config()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
config.ClientAuth = tls.RequestClientCert
|
config.ClientAuth = tls.RequestClientCert
|
||||||
tlsListeners[s] = config
|
tlsListeners[s] = config
|
||||||
}
|
}
|
||||||
return tlsListeners
|
return tlsListeners, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadConfig loads the given YAML configuration file.
|
// LoadConfig loads the given YAML configuration file.
|
||||||
|
@ -84,13 +84,9 @@ func parseCallback(spec string, config *AccountConfig) (callbackNamespace string
|
|||||||
func accRegisterHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool {
|
func accRegisterHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool {
|
||||||
// clients can't reg new accounts if they're already logged in
|
// clients can't reg new accounts if they're already logged in
|
||||||
if client.LoggedIntoAccount() {
|
if client.LoggedIntoAccount() {
|
||||||
if server.AccountConfig().Registration.AllowMultiplePerConnection {
|
|
||||||
server.accounts.Logout(client)
|
|
||||||
} else {
|
|
||||||
rb.Add(nil, server.name, ERR_REG_UNSPECIFIED_ERROR, client.nick, "*", client.t("You're already logged into an account"))
|
rb.Add(nil, server.name, ERR_REG_UNSPECIFIED_ERROR, client.nick, "*", client.t("You're already logged into an account"))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// get and sanitise account name
|
// get and sanitise account name
|
||||||
account := strings.TrimSpace(msg.Params[1])
|
account := strings.TrimSpace(msg.Params[1])
|
||||||
|
@ -124,7 +124,9 @@ func (logger *Manager) ApplyConfig(config []LoggingConfig) error {
|
|||||||
stdoutWriteLock: &logger.stdoutWriteLock,
|
stdoutWriteLock: &logger.stdoutWriteLock,
|
||||||
fileWriteLock: &logger.fileWriteLock,
|
fileWriteLock: &logger.fileWriteLock,
|
||||||
}
|
}
|
||||||
if typeMap["userinput"] || typeMap["useroutput"] || (typeMap["*"] && !(excludedTypeMap["userinput"] && excludedTypeMap["useroutput"])) {
|
ioEnabled := typeMap["userinput"] || typeMap["useroutput"] || (typeMap["*"] && !(excludedTypeMap["userinput"] && excludedTypeMap["useroutput"]))
|
||||||
|
// raw I/O is only logged at level debug;
|
||||||
|
if ioEnabled && logConfig.Level == LogDebug {
|
||||||
atomic.StoreUint32(&logger.loggingRawIO, 1)
|
atomic.StoreUint32(&logger.loggingRawIO, 1)
|
||||||
}
|
}
|
||||||
if sLogger.MethodFile.Enabled {
|
if sLogger.MethodFile.Enabled {
|
||||||
@ -177,13 +179,6 @@ func (logger *Manager) Error(logType string, messageParts ...string) {
|
|||||||
logger.Log(LogError, logType, messageParts...)
|
logger.Log(LogError, logType, messageParts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fatal logs the given message as an error message, then exits.
|
|
||||||
func (logger *Manager) Fatal(logType string, messageParts ...string) {
|
|
||||||
logger.Error(logType, messageParts...)
|
|
||||||
logger.Error("FATAL", "Fatal error encountered, application exiting")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
type fileMethod struct {
|
type fileMethod struct {
|
||||||
Enabled bool
|
Enabled bool
|
||||||
Filename string
|
Filename string
|
||||||
|
@ -20,6 +20,11 @@ func servCmdRequiresAuthEnabled(server *Server) bool {
|
|||||||
return server.AccountConfig().AuthenticationEnabled
|
return server.AccountConfig().AuthenticationEnabled
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func nsGroupEnabled(server *Server) bool {
|
||||||
|
conf := server.Config()
|
||||||
|
return conf.Accounts.AuthenticationEnabled && conf.Accounts.NickReservation.Enabled
|
||||||
|
}
|
||||||
|
|
||||||
const nickservHelp = `NickServ lets you register and login to an account.
|
const nickservHelp = `NickServ lets you register and login to an account.
|
||||||
|
|
||||||
To see in-depth help for a specific NickServ command, try:
|
To see in-depth help for a specific NickServ command, try:
|
||||||
@ -55,7 +60,7 @@ same user account, letting you reclaim your nickname.`,
|
|||||||
GROUP links your current nickname with your logged-in account, preventing other
|
GROUP links your current nickname with your logged-in account, preventing other
|
||||||
users from changing to it (or forcing them to rename).`,
|
users from changing to it (or forcing them to rename).`,
|
||||||
helpShort: `$bGROUP$b links your current nickname to your user account.`,
|
helpShort: `$bGROUP$b links your current nickname to your user account.`,
|
||||||
enabled: servCmdRequiresAccreg,
|
enabled: nsGroupEnabled,
|
||||||
authRequired: true,
|
authRequired: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -94,7 +99,7 @@ certificate (and you will need to use that certificate to login in future).`,
|
|||||||
|
|
||||||
SADROP forcibly de-links the given nickname from the attached user account.`,
|
SADROP forcibly de-links the given nickname from the attached user account.`,
|
||||||
helpShort: `$bSADROP$b forcibly de-links the given nickname from its user account.`,
|
helpShort: `$bSADROP$b forcibly de-links the given nickname from its user account.`,
|
||||||
capabs: []string{"unregister"},
|
capabs: []string{"accreg"},
|
||||||
enabled: servCmdRequiresAccreg,
|
enabled: servCmdRequiresAccreg,
|
||||||
},
|
},
|
||||||
"unregister": {
|
"unregister": {
|
||||||
@ -259,13 +264,9 @@ func nsRegisterHandler(server *Server, client *Client, command, params string, r
|
|||||||
}
|
}
|
||||||
|
|
||||||
if client.LoggedIntoAccount() {
|
if client.LoggedIntoAccount() {
|
||||||
if server.AccountConfig().Registration.AllowMultiplePerConnection {
|
|
||||||
server.accounts.Logout(client)
|
|
||||||
} else {
|
|
||||||
nsNotice(rb, client.t("You're already logged into an account"))
|
nsNotice(rb, client.t("You're already logged into an account"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
config := server.AccountConfig()
|
config := server.AccountConfig()
|
||||||
var callbackNamespace, callbackValue string
|
var callbackNamespace, callbackValue string
|
||||||
|
@ -9,7 +9,6 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -143,22 +142,6 @@ func NewServer(config *Config, logger *logger.Manager) (*Server, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// confirm help entries for ChanServ exist.
|
|
||||||
// this forces people to write help entries for every single CS command.
|
|
||||||
for commandName, commandInfo := range chanservCommands {
|
|
||||||
if commandInfo.help == "" || commandInfo.helpShort == "" {
|
|
||||||
return nil, fmt.Errorf("Help entry does not exist for ChanServ command %s", commandName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// confirm help entries for NickServ exist.
|
|
||||||
// this forces people to write help entries for every single NS command.
|
|
||||||
for commandName, commandInfo := range nickservCommands {
|
|
||||||
if commandInfo.help == "" || commandInfo.helpShort == "" {
|
|
||||||
return nil, fmt.Errorf("Help entry does not exist for NickServ command %s", commandName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attempt to clean up when receiving these signals.
|
// Attempt to clean up when receiving these signals.
|
||||||
signal.Notify(server.signals, ServerExitSignals...)
|
signal.Notify(server.signals, ServerExitSignals...)
|
||||||
signal.Notify(server.rehashSignal, syscall.SIGHUP)
|
signal.Notify(server.rehashSignal, syscall.SIGHUP)
|
||||||
@ -325,8 +308,8 @@ func (server *Server) checkBans(ipaddr net.IP) (banned bool, message string) {
|
|||||||
// IRC protocol listeners
|
// IRC protocol listeners
|
||||||
//
|
//
|
||||||
|
|
||||||
// createListener starts the given listeners.
|
// createListener starts a given listener.
|
||||||
func (server *Server) createListener(addr string, tlsConfig *tls.Config) *ListenerWrapper {
|
func (server *Server) createListener(addr string, tlsConfig *tls.Config) (*ListenerWrapper, error) {
|
||||||
// make listener
|
// make listener
|
||||||
var listener net.Listener
|
var listener net.Listener
|
||||||
var err error
|
var err error
|
||||||
@ -339,7 +322,7 @@ func (server *Server) createListener(addr string, tlsConfig *tls.Config) *Listen
|
|||||||
listener, err = net.Listen("tcp", addr)
|
listener, err = net.Listen("tcp", addr)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(server, "listen error: ", err)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// throw our details to the server so we can be modified/killed later
|
// throw our details to the server so we can be modified/killed later
|
||||||
@ -382,7 +365,7 @@ func (server *Server) createListener(addr string, tlsConfig *tls.Config) *Listen
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return &wrapper
|
return &wrapper, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// generateMessageID returns a network-unique message ID.
|
// generateMessageID returns a network-unique message ID.
|
||||||
@ -896,7 +879,7 @@ func (server *Server) applyConfig(config *Config, initial bool) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// we are now open for business
|
// we are now open for business
|
||||||
server.setupListeners(config)
|
err = server.setupListeners(config)
|
||||||
|
|
||||||
if !initial {
|
if !initial {
|
||||||
// push new info to all of our clients
|
// push new info to all of our clients
|
||||||
@ -911,7 +894,7 @@ func (server *Server) applyConfig(config *Config, initial bool) (err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *Server) setupPprofListener(config *Config) {
|
func (server *Server) setupPprofListener(config *Config) {
|
||||||
@ -1000,15 +983,20 @@ func (server *Server) loadDatastore(config *Config) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *Server) setupListeners(config *Config) {
|
func (server *Server) setupListeners(config *Config) (err error) {
|
||||||
logListener := func(addr string, tlsconfig *tls.Config) {
|
logListener := func(addr string, tlsconfig *tls.Config) {
|
||||||
server.logger.Info("listeners",
|
server.logger.Info("listeners",
|
||||||
fmt.Sprintf("now listening on %s, tls=%t.", addr, (tlsconfig != nil)),
|
fmt.Sprintf("now listening on %s, tls=%t.", addr, (tlsconfig != nil)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tlsListeners, err := config.TLSListeners()
|
||||||
|
if err != nil {
|
||||||
|
server.logger.Error("rehash", "failed to reload TLS certificates, aborting rehash", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// update or destroy all existing listeners
|
// update or destroy all existing listeners
|
||||||
tlsListeners := config.TLSListeners()
|
|
||||||
for addr := range server.listeners {
|
for addr := range server.listeners {
|
||||||
currentListener := server.listeners[addr]
|
currentListener := server.listeners[addr]
|
||||||
var stillConfigured bool
|
var stillConfigured bool
|
||||||
@ -1044,7 +1032,13 @@ func (server *Server) setupListeners(config *Config) {
|
|||||||
if !exists {
|
if !exists {
|
||||||
// make new listener
|
// make new listener
|
||||||
tlsConfig := tlsListeners[newaddr]
|
tlsConfig := tlsListeners[newaddr]
|
||||||
server.listeners[newaddr] = server.createListener(newaddr, tlsConfig)
|
listener, listenerErr := server.createListener(newaddr, tlsConfig)
|
||||||
|
if listenerErr != nil {
|
||||||
|
server.logger.Error("rehash", "couldn't listen on", newaddr, listenerErr.Error())
|
||||||
|
err = listenerErr
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
server.listeners[newaddr] = listener
|
||||||
logListener(newaddr, tlsConfig)
|
logListener(newaddr, tlsConfig)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1054,8 +1048,8 @@ func (server *Server) setupListeners(config *Config) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var usesStandardTLSPort bool
|
var usesStandardTLSPort bool
|
||||||
for addr := range config.TLSListeners() {
|
for addr := range tlsListeners {
|
||||||
if strings.Contains(addr, "6697") {
|
if strings.HasSuffix(addr, ":6697") {
|
||||||
usesStandardTLSPort = true
|
usesStandardTLSPort = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -1063,6 +1057,8 @@ func (server *Server) setupListeners(config *Config) {
|
|||||||
if 0 < len(tlsListeners) && !usesStandardTLSPort {
|
if 0 < len(tlsListeners) && !usesStandardTLSPort {
|
||||||
server.logger.Warning("startup", "Port 6697 is the standard TLS port for IRC. You should (also) expose port 6697 as a TLS port to ensure clients can connect securely")
|
server.logger.Warning("startup", "Port 6697 is the standard TLS port for IRC. You should (also) expose port 6697 as a TLS port to ensure clients can connect securely")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// elistMatcher takes and matches ELIST conditions
|
// elistMatcher takes and matches ELIST conditions
|
||||||
|
@ -5,6 +5,7 @@ package irc
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -25,6 +26,7 @@ type ircService struct {
|
|||||||
|
|
||||||
// defines a command associated with a service, e.g., NICKSERV IDENTIFY
|
// defines a command associated with a service, e.g., NICKSERV IDENTIFY
|
||||||
type serviceCommand struct {
|
type serviceCommand struct {
|
||||||
|
aliasOf string // marks this command as an alias of another
|
||||||
capabs []string // oper capabs the given user has to have to access this command
|
capabs []string // oper capabs the given user has to have to access this command
|
||||||
handler func(server *Server, client *Client, command, params string, rb *ResponseBuffer)
|
handler func(server *Server, client *Client, command, params string, rb *ResponseBuffer)
|
||||||
help string
|
help string
|
||||||
@ -33,6 +35,24 @@ type serviceCommand struct {
|
|||||||
enabled func(*Server) bool // is this command enabled in the server config?
|
enabled func(*Server) bool // is this command enabled in the server config?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// looks up a command in the table of command definitions for a service, resolving aliases
|
||||||
|
func lookupServiceCommand(commands map[string]*serviceCommand, command string) *serviceCommand {
|
||||||
|
maxDepth := 1
|
||||||
|
depth := 0
|
||||||
|
for depth <= maxDepth {
|
||||||
|
result, ok := commands[command]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
} else if result.aliasOf == "" {
|
||||||
|
return result
|
||||||
|
} else {
|
||||||
|
command = result.aliasOf
|
||||||
|
depth += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// all services, by lowercase name
|
// all services, by lowercase name
|
||||||
var OragonoServices = map[string]*ircService{
|
var OragonoServices = map[string]*ircService{
|
||||||
"nickserv": {
|
"nickserv": {
|
||||||
@ -93,7 +113,7 @@ func servicePrivmsgHandler(service *ircService, server *Server, client *Client,
|
|||||||
rb.Add(nil, service.Name, "NOTICE", nick, notice)
|
rb.Add(nil, service.Name, "NOTICE", nick, notice)
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := service.Commands[commandName]
|
cmd := lookupServiceCommand(service.Commands, commandName)
|
||||||
if cmd == nil {
|
if cmd == nil {
|
||||||
sendNotice(fmt.Sprintf("%s /%s HELP", client.t("Unknown command. To see available commands, run"), service.ShortName))
|
sendNotice(fmt.Sprintf("%s /%s HELP", client.t("Unknown command. To see available commands, run"), service.ShortName))
|
||||||
return
|
return
|
||||||
@ -140,6 +160,9 @@ func serviceHelpHandler(service *ircService, server *Server, client *Client, par
|
|||||||
if 0 < len(commandInfo.capabs) && !client.HasRoleCapabs(commandInfo.capabs...) {
|
if 0 < len(commandInfo.capabs) && !client.HasRoleCapabs(commandInfo.capabs...) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if commandInfo.aliasOf != "" {
|
||||||
|
continue // don't show help lines for aliases
|
||||||
|
}
|
||||||
if commandInfo.enabled != nil && !commandInfo.enabled(server) {
|
if commandInfo.enabled != nil && !commandInfo.enabled(server) {
|
||||||
disabledCommands = true
|
disabledCommands = true
|
||||||
continue
|
continue
|
||||||
@ -164,7 +187,8 @@ func serviceHelpHandler(service *ircService, server *Server, client *Client, par
|
|||||||
sendNotice(line)
|
sendNotice(line)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
commandInfo := service.Commands[strings.ToLower(strings.TrimSpace(params))]
|
commandName := strings.ToLower(strings.TrimSpace(params))
|
||||||
|
commandInfo := lookupServiceCommand(service.Commands, commandName)
|
||||||
if commandInfo == nil {
|
if commandInfo == nil {
|
||||||
sendNotice(client.t(fmt.Sprintf("Unknown command. To see available commands, run /%s HELP", service.ShortName)))
|
sendNotice(client.t(fmt.Sprintf("Unknown command. To see available commands, run /%s HELP", service.ShortName)))
|
||||||
} else {
|
} else {
|
||||||
@ -196,5 +220,12 @@ func initializeServices() {
|
|||||||
Commands[ircCmd] = ircCmdDef
|
Commands[ircCmd] = ircCmdDef
|
||||||
oragonoServicesByCommandAlias[ircCmd] = service
|
oragonoServicesByCommandAlias[ircCmd] = service
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// force devs to write a help entry for every command
|
||||||
|
for commandName, commandInfo := range service.Commands {
|
||||||
|
if commandInfo.aliasOf == "" && (commandInfo.help == "" || commandInfo.helpShort == "") {
|
||||||
|
log.Fatal(fmt.Sprintf("help entry missing for %s command %s", serviceName, commandName))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
15
oragono.go
15
oragono.go
@ -17,7 +17,6 @@ import (
|
|||||||
"github.com/oragono/oragono/irc"
|
"github.com/oragono/oragono/irc"
|
||||||
"github.com/oragono/oragono/irc/logger"
|
"github.com/oragono/oragono/irc/logger"
|
||||||
"github.com/oragono/oragono/irc/mkcerts"
|
"github.com/oragono/oragono/irc/mkcerts"
|
||||||
stackimpact "github.com/stackimpact/stackimpact-go"
|
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
"golang.org/x/crypto/ssh/terminal"
|
"golang.org/x/crypto/ssh/terminal"
|
||||||
)
|
)
|
||||||
@ -127,20 +126,6 @@ Options:
|
|||||||
irc.Ver = fmt.Sprintf("%s-%s", irc.Ver, commit)
|
irc.Ver = fmt.Sprintf("%s-%s", irc.Ver, commit)
|
||||||
}
|
}
|
||||||
|
|
||||||
// profiling
|
|
||||||
if config.Debug.StackImpact.Enabled {
|
|
||||||
if config.Debug.StackImpact.AgentKey == "" || config.Debug.StackImpact.AppName == "" {
|
|
||||||
logman.Error("startup", "Could not start StackImpact - agent-key or app-name are undefined")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
agent := stackimpact.NewAgent()
|
|
||||||
agent.Start(stackimpact.Options{AgentKey: config.Debug.StackImpact.AgentKey, AppName: config.Debug.StackImpact.AppName})
|
|
||||||
defer agent.RecordPanic()
|
|
||||||
|
|
||||||
logman.Info("startup", fmt.Sprintf("StackImpact profiling started as %s", config.Debug.StackImpact.AppName))
|
|
||||||
}
|
|
||||||
|
|
||||||
// warning if running a non-final version
|
// warning if running a non-final version
|
||||||
if strings.Contains(irc.SemVer, "unreleased") {
|
if strings.Contains(irc.SemVer, "unreleased") {
|
||||||
logman.Warning("startup", "You are currently running an unreleased beta version of Oragono that may be unstable and could corrupt your database.\nIf you are running a production network, please download the latest build from https://oragono.io/downloads.html and run that instead.")
|
logman.Warning("startup", "You are currently running an unreleased beta version of Oragono that may be unstable and could corrupt your database.\nIf you are running a production network, please download the latest build from https://oragono.io/downloads.html and run that instead.")
|
||||||
|
15
oragono.yaml
15
oragono.yaml
@ -166,10 +166,6 @@ accounts:
|
|||||||
# password: ""
|
# password: ""
|
||||||
# sender: "admin@my.network"
|
# sender: "admin@my.network"
|
||||||
|
|
||||||
# allow multiple account registrations per connection
|
|
||||||
# this is for testing purposes and shouldn't be allowed on real networks
|
|
||||||
allow-multiple-per-connection: false
|
|
||||||
|
|
||||||
# is account authentication enabled?
|
# is account authentication enabled?
|
||||||
authentication-enabled: true
|
authentication-enabled: true
|
||||||
|
|
||||||
@ -362,17 +358,6 @@ debug:
|
|||||||
# set to `null`, "", leave blank, or omit to disable
|
# set to `null`, "", leave blank, or omit to disable
|
||||||
# pprof-listener: "localhost:6060"
|
# pprof-listener: "localhost:6060"
|
||||||
|
|
||||||
# enabling StackImpact profiling
|
|
||||||
stackimpact:
|
|
||||||
# whether to use StackImpact
|
|
||||||
enabled: false
|
|
||||||
|
|
||||||
# the AgentKey to use
|
|
||||||
agent-key: examplekeyhere
|
|
||||||
|
|
||||||
# the app name to report
|
|
||||||
app-name: Oragono
|
|
||||||
|
|
||||||
# datastore configuration
|
# datastore configuration
|
||||||
datastore:
|
datastore:
|
||||||
# path to the datastore
|
# path to the datastore
|
||||||
|
2
vendor
2
vendor
@ -1 +1 @@
|
|||||||
Subproject commit 9dd7467d3dfc045cf5dee2f6f6951465437e2ac5
|
Subproject commit 77ddc3dbc1ec085c73670510a8fece80599741ce
|
Loading…
Reference in New Issue
Block a user