parent
26c5c11216
commit
f246ea1e40
@ -0,0 +1,6 @@
|
||||
package app
|
||||
|
||||
// We offer "un-passworded" profiles but our storage encrypts everything with a password. We need an agreed upon
|
||||
// password to use in that case, that the app case use behind the scenes to password and unlock with
|
||||
// https://docs.openprivacy.ca/cwtch-security-handbook/profile_encryption_and_storage.html
|
||||
const DefactoPasswordForUnencryptedProfiles = "be gay do crime"
|
@ -0,0 +1,146 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"cwtch.im/cwtch/event"
|
||||
"cwtch.im/cwtch/model/constants"
|
||||
"cwtch.im/cwtch/storage/v1"
|
||||
"encoding/json"
|
||||
"git.openprivacy.ca/openprivacy/log"
|
||||
"os"
|
||||
path "path/filepath"
|
||||
)
|
||||
|
||||
const (
|
||||
CwtchStarted = event.Type("CwtchStarted")
|
||||
CwtchStartError = event.Type("CwtchStartError")
|
||||
UpdateGlobalSettings = event.Type("UpdateGlobalSettings")
|
||||
)
|
||||
|
||||
const GlobalSettingsFilename = "ui.globals"
|
||||
const saltFile = "SALT"
|
||||
|
||||
type NotificationPolicy string
|
||||
|
||||
const (
|
||||
NotificationPolicyMute = NotificationPolicy("NotificationPolicy.Mute")
|
||||
NotificationPolicyOptIn = NotificationPolicy("NotificationPolicy.OptIn")
|
||||
NotificationPolicyDefaultAll = NotificationPolicy("NotificationPolicy.DefaultAll")
|
||||
)
|
||||
|
||||
type GlobalSettingsFile struct {
|
||||
v1.FileStore
|
||||
}
|
||||
|
||||
type GlobalSettings struct {
|
||||
Locale string
|
||||
Theme string
|
||||
ThemeMode string
|
||||
PreviousPid int64
|
||||
ExperimentsEnabled bool
|
||||
Experiments map[string]bool
|
||||
BlockUnknownConnections bool
|
||||
NotificationPolicy NotificationPolicy
|
||||
NotificationContent string
|
||||
StreamerMode bool
|
||||
StateRootPane int
|
||||
FirstTime bool
|
||||
UIColumnModePortrait string
|
||||
UIColumnModeLandscape string
|
||||
DownloadPath string
|
||||
AllowAdvancedTorConfig bool
|
||||
CustomTorrc string
|
||||
UseCustomTorrc bool
|
||||
UseExternalTor bool
|
||||
CustomSocksPort int
|
||||
CustomControlPort int
|
||||
UseTorCache bool
|
||||
TorCacheDir string
|
||||
}
|
||||
|
||||
var DefaultGlobalSettings = GlobalSettings{
|
||||
Locale: "en",
|
||||
Theme: "dark",
|
||||
PreviousPid: -1,
|
||||
ExperimentsEnabled: false,
|
||||
Experiments: map[string]bool{constants.MessageFormattingExperiment: true},
|
||||
StateRootPane: 0,
|
||||
FirstTime: true,
|
||||
BlockUnknownConnections: false,
|
||||
StreamerMode: false,
|
||||
UIColumnModePortrait: "DualpaneMode.Single",
|
||||
UIColumnModeLandscape: "DualpaneMode.CopyPortrait",
|
||||
NotificationPolicy: "NotificationPolicy.Mute",
|
||||
NotificationContent: "NotificationContent.SimpleEvent",
|
||||
DownloadPath: "",
|
||||
AllowAdvancedTorConfig: false,
|
||||
CustomTorrc: "",
|
||||
UseCustomTorrc: false,
|
||||
CustomSocksPort: -1,
|
||||
CustomControlPort: -1,
|
||||
UseTorCache: false,
|
||||
TorCacheDir: "",
|
||||
}
|
||||
|
||||
func InitGlobalSettingsFile(directory string, password string) (*GlobalSettingsFile, error) {
|
||||
var key [32]byte
|
||||
salt, err := os.ReadFile(path.Join(directory, saltFile))
|
||||
if err != nil {
|
||||
log.Infof("Could not find salt file: %v (creating a new settings file)", err)
|
||||
var newSalt [128]byte
|
||||
key, newSalt, err = v1.CreateKeySalt(password)
|
||||
if err != nil {
|
||||
log.Errorf("Could not initialize salt: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
os.Mkdir(directory, 0700)
|
||||
err := os.WriteFile(path.Join(directory, saltFile), newSalt[:], 0600)
|
||||
if err != nil {
|
||||
log.Errorf("Could not write salt file: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
key = v1.CreateKey(password, salt)
|
||||
}
|
||||
|
||||
gsFile := v1.NewFileStore(directory, GlobalSettingsFilename, key)
|
||||
log.Infof("initialized global settings file: %v", gsFile)
|
||||
globalSettingsFile := GlobalSettingsFile{
|
||||
gsFile,
|
||||
}
|
||||
return &globalSettingsFile, nil
|
||||
}
|
||||
|
||||
func (globalSettingsFile *GlobalSettingsFile) ReadGlobalSettings() GlobalSettings {
|
||||
settings := DefaultGlobalSettings
|
||||
|
||||
if globalSettingsFile == nil {
|
||||
log.Errorf("Global Settings File was not Initialized Properly")
|
||||
return settings
|
||||
}
|
||||
|
||||
settingsBytes, err := globalSettingsFile.Read()
|
||||
if err != nil {
|
||||
log.Infof("Could not read global ui settings: %v (assuming this is a first time app deployment...)", err)
|
||||
return settings //firstTime = true
|
||||
}
|
||||
|
||||
err = json.Unmarshal(settingsBytes, &settings)
|
||||
if err != nil {
|
||||
log.Errorf("Could not parse global ui settings: %v\n", err)
|
||||
// TODO if settings is corrupted, we probably want to alert the UI.
|
||||
return settings //firstTime = true
|
||||
}
|
||||
|
||||
log.Debugf("Settings: %#v", settings)
|
||||
return settings
|
||||
}
|
||||
|
||||
func (globalSettingsFile *GlobalSettingsFile) WriteGlobalSettings(globalSettings GlobalSettings) {
|
||||
bytes, _ := json.Marshal(globalSettings)
|
||||
// override first time setting
|
||||
globalSettings.FirstTime = true
|
||||
err := globalSettingsFile.Write(bytes)
|
||||
if err != nil {
|
||||
log.Errorf("Could not write global ui settings: %v\n", err)
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package model
|
||||
|
||||
// Experiments are optional functionality that can be enabled/disabled by an application either completely or individually.
|
||||
// examples of experiments include File Sharing, Profile Images and Groups.
|
||||
type Experiments struct {
|
||||
enabled bool
|
||||
experiments map[string]bool
|
||||
}
|
||||
|
||||
// InitExperiments encapsulates a set of experiments separate from their storage in GlobalSettings.
|
||||
func InitExperiments(enabled bool, experiments map[string]bool) Experiments {
|
||||
return Experiments{
|
||||
enabled: enabled,
|
||||
experiments: experiments,
|
||||
}
|
||||
}
|
||||
|
||||
// IsEnabled is a convenience function that takes in an experiment and returns true if it is enabled. Experiments
|
||||
// are only enabled if both global experiments are turned on and if the specific experiment is also turned on.
|
||||
// The one exception to this is experiments that have been promoted to default functionality which may be turned on
|
||||
// even if experiments turned off globally. These experiments are defined by DefaultEnabledFunctionality.
|
||||
func (e *Experiments) IsEnabled(experiment string) bool {
|
||||
if !e.enabled {
|
||||
// todo handle default-enabled functionality
|
||||
return false
|
||||
}
|
||||
enabled, exists := e.experiments[experiment]
|
||||
if !exists {
|
||||
return false
|
||||
}
|
||||
return enabled
|
||||
}
|
Loading…
Reference in new issue