new database schema
This commit is contained in:
parent
12e342cb61
commit
cacd32801e
|
@ -1,2 +0,0 @@
|
|||
vendor/* linguist-vendored
|
||||
languages/* linguist-vendored
|
|
@ -1,56 +0,0 @@
|
|||
# .goreleaser.yml
|
||||
# Build customization
|
||||
project_name: ergo
|
||||
builds:
|
||||
- main: ergo.go
|
||||
binary: ergo
|
||||
goos:
|
||||
- freebsd
|
||||
- windows
|
||||
- darwin
|
||||
- linux
|
||||
goarch:
|
||||
- "386"
|
||||
- amd64
|
||||
- arm
|
||||
- arm64
|
||||
goarm:
|
||||
- 6
|
||||
- 7
|
||||
ignore:
|
||||
- goos: windows
|
||||
goarch: arm
|
||||
- goos: darwin
|
||||
goarch: arm
|
||||
- goos: darwin
|
||||
goarch: 386
|
||||
- goos: freebsd
|
||||
goarch: arm
|
||||
- goos: freebsd
|
||||
goarch: arm64
|
||||
flags:
|
||||
- -trimpath
|
||||
|
||||
archives:
|
||||
- name_template: "{{ .ProjectName }}-{{ .Version }}-{{ .Os }}-{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}"
|
||||
format: tar.gz
|
||||
replacements:
|
||||
amd64: x86_64
|
||||
darwin: macos
|
||||
format_overrides:
|
||||
- goos: windows
|
||||
format: zip
|
||||
files:
|
||||
- README
|
||||
- CHANGELOG.md
|
||||
- ergo.motd
|
||||
- default.yaml
|
||||
- traditional.yaml
|
||||
- docs/MANUAL.md
|
||||
- docs/USERGUIDE.md
|
||||
- languages/*.yaml
|
||||
- languages/*.json
|
||||
- languages/*.md
|
||||
wrap_in_directory: true
|
||||
checksum:
|
||||
name_template: "{{ .ProjectName }}-{{ .Version }}-checksums.txt"
|
48
Dockerfile
48
Dockerfile
|
@ -1,48 +0,0 @@
|
|||
## build ergo binary
|
||||
FROM golang:1.17-alpine AS build-env
|
||||
|
||||
RUN apk add -U --force-refresh --no-cache --purge --clean-protected -l -u make
|
||||
|
||||
# copy ergo source
|
||||
WORKDIR /go/src/github.com/ergochat/ergo
|
||||
COPY . .
|
||||
|
||||
# modify default config file so that it doesn't die on IPv6
|
||||
# and so it can be exposed via 6667 by default
|
||||
RUN sed -i 's/^\(\s*\)\"127.0.0.1:6667\":.*$/\1":6667":/' /go/src/github.com/ergochat/ergo/default.yaml && \
|
||||
sed -i 's/^\s*\"\[::1\]:6667\":.*$//' /go/src/github.com/ergochat/ergo/default.yaml
|
||||
|
||||
# compile
|
||||
RUN make
|
||||
|
||||
## build ergo container
|
||||
FROM alpine:3.13
|
||||
|
||||
# metadata
|
||||
LABEL maintainer="Daniel Oaks <daniel@danieloaks.net>,Daniel Thamdrup <dallemon@protonmail.com>" \
|
||||
description="Ergo is a modern, experimental IRC server written in Go"
|
||||
|
||||
# standard ports listened on
|
||||
EXPOSE 6667/tcp 6697/tcp
|
||||
|
||||
# ergo itself
|
||||
COPY --from=build-env /go/bin/ergo \
|
||||
/go/src/github.com/ergochat/ergo/default.yaml \
|
||||
/go/src/github.com/ergochat/ergo/distrib/docker/run.sh \
|
||||
/ircd-bin/
|
||||
COPY --from=build-env /go/src/github.com/ergochat/ergo/languages /ircd-bin/languages/
|
||||
|
||||
# running volume holding config file, db, certs
|
||||
VOLUME /ircd
|
||||
WORKDIR /ircd
|
||||
|
||||
# default motd
|
||||
COPY --from=build-env /go/src/github.com/ergochat/ergo/ergo.motd /ircd/ergo.motd
|
||||
|
||||
# launch
|
||||
ENTRYPOINT ["/ircd-bin/run.sh"]
|
||||
|
||||
# # uncomment to debug
|
||||
# RUN apk add --no-cache bash
|
||||
# RUN apk add --no-cache vim
|
||||
# CMD /bin/bash
|
1
LICENSE
1
LICENSE
|
@ -4,6 +4,7 @@ Copyright (c) 2012-2014 Jeremy Latt
|
|||
Copyright (c) 2014-2015 Edmund Huber
|
||||
Copyright (c) 2016-2020 Daniel Oaks
|
||||
Copyright (c) 2017-2020 Shivaram Lingamneni
|
||||
Copyright (c) 2020-2022 kayos@tcp.direct
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
|
@ -194,8 +194,8 @@ func (am *AccountManager) buildNickToAccountIndex(config *Config) {
|
|||
|
||||
if config.Accounts.NickReservation.Method == NickEnforcementStrict {
|
||||
unregisteredPrefix := fmt.Sprintf(keyAccountUnregistered, "")
|
||||
am.server.store.View(func(tx *buntdb.Tx) error {
|
||||
tx.AscendGreaterOrEqual("", unregisteredPrefix, func(key, value string) bool {
|
||||
err := am.server.store.View(func(tx *buntdb.Tx) error {
|
||||
err = tx.AscendGreaterOrEqual("", unregisteredPrefix, func(key, value string) bool {
|
||||
if !strings.HasPrefix(key, unregisteredPrefix) {
|
||||
return false
|
||||
}
|
||||
|
@ -206,8 +206,11 @@ func (am *AccountManager) buildNickToAccountIndex(config *Config) {
|
|||
skeletonToAccount[skeleton] = account
|
||||
return true
|
||||
})
|
||||
return nil
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
am.server.logger.Error("internal", "buildNickToAccountIndex buntdb transaction error during AscendGreaterOrEqual", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
@ -403,7 +406,10 @@ func (am *AccountManager) Register(client *Client, account string, callbackNames
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
creds.AddCertfp(certfp)
|
||||
err = creds.AddCertfp(certfp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
credStr, err := creds.Serialize()
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -471,7 +477,7 @@ func (am *AccountManager) Register(client *Client, account string, callbackNames
|
|||
|
||||
code, err := am.dispatchCallback(client, account, callbackNamespace, callbackValue)
|
||||
if err != nil {
|
||||
am.Unregister(casefoldedAccount, true)
|
||||
_ = am.Unregister(casefoldedAccount, true)
|
||||
return ®istrationCallbackError{underlying: err}
|
||||
} else {
|
||||
am.server.logger.Info("accounts",
|
||||
|
@ -537,11 +543,11 @@ func (am *AccountManager) setPassword(accountName string, password string, hasPr
|
|||
|
||||
credKey := fmt.Sprintf(keyAccountCredentials, cfAccount)
|
||||
var credStr string
|
||||
am.server.store.View(func(tx *buntdb.Tx) error {
|
||||
err = am.server.store.View(func(tx *buntdb.Tx) error {
|
||||
// no need to check verification status here or below;
|
||||
// you either need to be auth'ed to the account or be an oper to do this
|
||||
credStr, err = tx.Get(credKey)
|
||||
return nil
|
||||
return err
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
|
@ -651,12 +657,14 @@ func (am *AccountManager) saveLastSeen(account string, lastSeen map[string]time.
|
|||
val = string(text)
|
||||
}
|
||||
err := am.server.store.Update(func(tx *buntdb.Tx) error {
|
||||
if val != "" {
|
||||
tx.Set(key, val, nil)
|
||||
} else {
|
||||
tx.Delete(key)
|
||||
var err error
|
||||
switch val {
|
||||
case "":
|
||||
_, err = tx.Delete(key)
|
||||
default:
|
||||
_, _, err = tx.Set(key, val, nil)
|
||||
}
|
||||
return nil
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
am.server.logger.Error("internal", "error persisting lastSeen", account, err.Error())
|
||||
|
@ -714,9 +722,9 @@ func (am *AccountManager) addRemoveCertfp(account, certfp string, add bool, hasP
|
|||
|
||||
credKey := fmt.Sprintf(keyAccountCredentials, cfAccount)
|
||||
var credStr string
|
||||
am.server.store.View(func(tx *buntdb.Tx) error {
|
||||
err = am.server.store.View(func(tx *buntdb.Tx) error {
|
||||
credStr, err = tx.Get(credKey)
|
||||
return nil
|
||||
return err
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
|
@ -733,16 +741,18 @@ func (am *AccountManager) addRemoveCertfp(account, certfp string, add bool, hasP
|
|||
return errCredsExternallyManaged
|
||||
}
|
||||
|
||||
if add {
|
||||
switch add {
|
||||
case true:
|
||||
err = creds.AddCertfp(certfp)
|
||||
} else {
|
||||
default:
|
||||
err = creds.RemoveCertfp(certfp)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if creds.Empty() && !hasPrivs {
|
||||
if creds.Empty() {
|
||||
return errEmptyCredentials
|
||||
}
|
||||
|
||||
|
|
|
@ -24,8 +24,7 @@ const (
|
|||
// 'version' of the database schema
|
||||
keySchemaVersion = "db.version"
|
||||
// latest schema of the db
|
||||
latestDbSchema = 22
|
||||
|
||||
latestDbSchema = 23
|
||||
keyCloakSecret = "crypto.cloak_secret"
|
||||
)
|
||||
|
||||
|
@ -1113,6 +1112,56 @@ func schemaChangeV21To22(config *Config, tx *buntdb.Tx) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func schemaChangeV22To23(config *Config, tx *buntdb.Tx) error {
|
||||
type accountSettingsv23 struct {
|
||||
NickEnforcement NickEnforcementMethod
|
||||
AllowBouncer MulticlientAllowedSetting
|
||||
AutoreplayMissed bool
|
||||
AutoAway PersistentStatus
|
||||
GitAuth bool
|
||||
Email string
|
||||
}
|
||||
|
||||
var accounts []string
|
||||
var serializedSettings []string
|
||||
settingsPrefix := "account.settings "
|
||||
err := tx.AscendGreaterOrEqual("", settingsPrefix, func(key, value string) bool {
|
||||
if !strings.HasPrefix(key, settingsPrefix) {
|
||||
return false
|
||||
}
|
||||
if value == "" {
|
||||
return true
|
||||
}
|
||||
account := strings.TrimPrefix(key, settingsPrefix)
|
||||
var settings accountSettingsv23
|
||||
err := json.Unmarshal([]byte(value), &settings)
|
||||
if err != nil {
|
||||
log.Printf("error (v22-23) processing settings for %s: %v\n", account, err)
|
||||
return true
|
||||
}
|
||||
|
||||
b, err := json.Marshal(settings)
|
||||
|
||||
if err != nil {
|
||||
log.Printf("error (v22-23) processing settings for %s: %v\n", account, err)
|
||||
return true
|
||||
}
|
||||
|
||||
accounts = append(accounts, account)
|
||||
serializedSettings = append(serializedSettings, string(b))
|
||||
return true
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
log.Printf("error (v22-23) processing db transaction (invalid index): %v\n", err)
|
||||
}
|
||||
|
||||
for i, account := range accounts {
|
||||
tx.Set(settingsPrefix+account, serializedSettings[i], nil)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getSchemaChange(initialVersion int) (result SchemaChange, ok bool) {
|
||||
for _, change := range allChanges {
|
||||
if initialVersion == change.InitialVersion {
|
||||
|
@ -1228,4 +1277,9 @@ var allChanges = []SchemaChange{
|
|||
TargetVersion: 22,
|
||||
Changer: schemaChangeV21To22,
|
||||
},
|
||||
{
|
||||
InitialVersion: 22,
|
||||
TargetVersion: 23,
|
||||
Changer: schemaChangeV22To23,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -421,15 +421,6 @@ func displaySetting(service *ircService, settingName string, settings AccountSet
|
|||
service.Notice(rb, client.t("Multiclient functionality is currently enabled for your account"))
|
||||
}
|
||||
}
|
||||
case "always-on":
|
||||
stored := settings.AlwaysOn
|
||||
actual := persistenceEnabled(config.Accounts.Multiclient.AlwaysOn, stored)
|
||||
service.Notice(rb, fmt.Sprintf(client.t("Your stored always-on setting is: %s"), userPersistentStatusToString(stored)))
|
||||
if actual {
|
||||
service.Notice(rb, client.t("Given current server settings, your client is always-on"))
|
||||
} else {
|
||||
service.Notice(rb, client.t("Given current server settings, your client is not always-on"))
|
||||
}
|
||||
case "auto-away":
|
||||
stored := settings.AutoAway
|
||||
alwaysOn := persistenceEnabled(config.Accounts.Multiclient.AlwaysOn, settings.AlwaysOn)
|
||||
|
@ -500,22 +491,6 @@ func nsSetHandler(service *ircService, server *Server, client *Client, command s
|
|||
if err == nil {
|
||||
finalSettings.NickEnforcement = method // success
|
||||
}
|
||||
case "autoreplay-lines":
|
||||
var newValue *int
|
||||
if strings.ToLower(params[1]) != "default" {
|
||||
val, err_ := strconv.Atoi(params[1])
|
||||
if err_ != nil || val < 0 {
|
||||
err = errInvalidParams
|
||||
break
|
||||
}
|
||||
newValue = new(int)
|
||||
*newValue = val
|
||||
}
|
||||
munger = func(in AccountSettings) (out AccountSettings, err error) {
|
||||
out = in
|
||||
out.AutoreplayLines = newValue
|
||||
return
|
||||
}
|
||||
case "multiclient":
|
||||
var newValue MulticlientAllowedSetting
|
||||
if strings.ToLower(params[1]) == "default" {
|
||||
|
@ -546,39 +521,6 @@ func nsSetHandler(service *ircService, server *Server, client *Client, command s
|
|||
return
|
||||
}
|
||||
}
|
||||
case "always-on":
|
||||
// #821: it's problematic to alter the value of always-on if you're not
|
||||
// the (actual or potential) always-on client yourself. make an exception
|
||||
// for `saset` to give operators an escape hatch (any consistency problems
|
||||
// can probably be fixed by restarting the server):
|
||||
if command != "saset" {
|
||||
details := client.Details()
|
||||
if details.nick != details.accountName {
|
||||
err = errNickAccountMismatch
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
var newValue PersistentStatus
|
||||
newValue, err = persistentStatusFromString(params[1])
|
||||
// "opt-in" and "opt-out" don't make sense as user preferences
|
||||
if err == nil && newValue != PersistentOptIn && newValue != PersistentOptOut {
|
||||
munger = func(in AccountSettings) (out AccountSettings, err error) {
|
||||
out = in
|
||||
out.AlwaysOn = newValue
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
case "autoreplay-missed":
|
||||
var newValue bool
|
||||
newValue, err = utils.StringToBool(params[1])
|
||||
if err == nil {
|
||||
munger = func(in AccountSettings) (out AccountSettings, err error) {
|
||||
out = in
|
||||
out.AutoreplayMissed = newValue
|
||||
return
|
||||
}
|
||||
}
|
||||
case "auto-away":
|
||||
var newValue PersistentStatus
|
||||
newValue, err = persistentStatusFromString(params[1])
|
||||
|
|
Loading…
Reference in New Issue