new database schema

This commit is contained in:
kayos@tcp.direct 2022-02-12 01:18:24 -08:00
parent 12e342cb61
commit cacd32801e
Signed by: kayos
GPG Key ID: 4B841471B4BEE979
7 changed files with 84 additions and 183 deletions

2
.gitattributes vendored
View File

@ -1,2 +0,0 @@
vendor/* linguist-vendored
languages/* linguist-vendored

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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 &registrationCallbackError{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
}

View File

@ -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,
},
}

View File

@ -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])