3
0
mirror of https://github.com/ergochat/ergo.git synced 2024-11-22 11:59:40 +01:00

schema change for #1345

Convert the flat list of channels for always-on clients
to a map from channel names to channel-user modes.
This commit is contained in:
Shivaram Lingamneni 2020-12-02 05:08:49 -05:00
parent 51f279289d
commit c0bc485840
2 changed files with 67 additions and 2 deletions

View File

@ -24,7 +24,7 @@ const (
// 'version' of the database schema // 'version' of the database schema
keySchemaVersion = "db.version" keySchemaVersion = "db.version"
// latest schema of the db // latest schema of the db
latestDbSchema = 18 latestDbSchema = 19
keyCloakSecret = "crypto.cloak_secret" keyCloakSecret = "crypto.cloak_secret"
) )
@ -903,6 +903,66 @@ func schemaChangeV17ToV18(config *Config, tx *buntdb.Tx) error {
return nil return nil
} }
// #1345: persist the channel-user modes of always-on clients
func schemaChangeV18To19(config *Config, tx *buntdb.Tx) error {
channelToAmodesCache := make(map[string]map[string]modes.Mode)
joinedto := "account.joinedto "
var accounts []string
var channels [][]string
tx.AscendGreaterOrEqual("", joinedto, func(key, value string) bool {
if !strings.HasPrefix(key, joinedto) {
return false
}
accounts = append(accounts, strings.TrimPrefix(key, joinedto))
var ch []string
if value != "" {
ch = strings.Split(value, ",")
}
channels = append(channels, ch)
return true
})
for i := 0; i < len(accounts); i++ {
account := accounts[i]
channels := channels[i]
tx.Delete(joinedto + account)
newValue := make(map[string]string, len(channels))
for _, channel := range channels {
chcfname, err := CasefoldChannel(channel)
if err != nil {
continue
}
// get amodes from the channelToAmodesCache, fill if necessary
amodes, ok := channelToAmodesCache[chcfname]
if !ok {
amodeStr, _ := tx.Get("channel.accounttoumode " + chcfname)
if amodeStr != "" {
jErr := json.Unmarshal([]byte(amodeStr), &amodes)
if jErr != nil {
log.Printf("error retrieving amodes for %s: %v\n", channel, jErr)
amodes = nil
}
}
// setting/using the nil value here is ok
channelToAmodesCache[chcfname] = amodes
}
if mode, ok := amodes[account]; ok {
newValue[channel] = string(mode)
} else {
newValue[channel] = ""
}
}
newValueBytes, jErr := json.Marshal(newValue)
if jErr != nil {
log.Printf("couldn't serialize new mode values for v19: %v\n", jErr)
continue
}
tx.Set("account.channeltomodes "+account, string(newValueBytes), nil)
}
return nil
}
func getSchemaChange(initialVersion int) (result SchemaChange, ok bool) { func getSchemaChange(initialVersion int) (result SchemaChange, ok bool) {
for _, change := range allChanges { for _, change := range allChanges {
if initialVersion == change.InitialVersion { if initialVersion == change.InitialVersion {
@ -998,4 +1058,9 @@ var allChanges = []SchemaChange{
TargetVersion: 18, TargetVersion: 18,
Changer: schemaChangeV17ToV18, Changer: schemaChangeV17ToV18,
}, },
{
InitialVersion: 18,
TargetVersion: 19,
Changer: schemaChangeV18To19,
},
} }

View File

@ -20,7 +20,7 @@ const (
// XXX instead of referencing, e.g., keyAccountExists, we should write in the string literal // XXX instead of referencing, e.g., keyAccountExists, we should write in the string literal
// (to ensure that no matter what code changes happen elsewhere, we're still producing a // (to ensure that no matter what code changes happen elsewhere, we're still producing a
// db of the hardcoded version) // db of the hardcoded version)
importDBSchemaVersion = 18 importDBSchemaVersion = 19
) )
type userImport struct { type userImport struct {