diff options
| author | jwijenbergh <jeroenwijenbergh@protonmail.com> | 2022-04-22 16:29:59 +0200 |
|---|---|---|
| committer | jwijenbergh <jeroenwijenbergh@protonmail.com> | 2022-04-22 16:29:59 +0200 |
| commit | b1d92b395322f2164ccfb44b0f7caebbaece6b62 (patch) | |
| tree | 2133e4045b4af4d07a98674b7ae3a234670f0305 /state.go | |
| parent | 3a4ae2942b43923ff98fd2eca8878c3cf145686c (diff) | |
Refactor: Restructure project
- Add an internal folder where all the internal code lives
- Make a state.go and state_test.go for the public interface
This gives a more clear separation between functions and modules. It
also makes this a more typical Go project setup.
Diffstat (limited to 'state.go')
| -rw-r--r-- | state.go | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/state.go b/state.go new file mode 100644 index 0000000..bafdfb9 --- /dev/null +++ b/state.go @@ -0,0 +1,143 @@ +package eduvpn + +import ( + "errors" + "github.com/jwijenbergh/eduvpn-common/internal" +) + +type VPNState struct { + // The chosen server + Servers internal.Servers `json:"servers"` + + // The list of servers and organizations from disco + Discovery internal.Discovery `json:"-"` + + // The fsm + FSM internal.FSM `json:"-"` + + // The logger + Logger internal.FileLogger `json:"-"` + + // The config + Config internal.Config `json:"-"` + + // Whether to enable debugging + Debug bool `json:"-"` +} + +var VPNStateInstance *VPNState + +func GetVPNState() *VPNState { + if VPNStateInstance == nil { + VPNStateInstance = &VPNState{} + } + return VPNStateInstance +} + +func (state *VPNState) Register(name string, directory string, stateCallback func(string, string, string), debug bool) error { + if !state.FSM.InState(internal.DEREGISTERED) { + return errors.New("app already registered") + } + // Initialize the logger + logLevel := internal.LOG_WARNING + + if debug { + logLevel = internal.LOG_INFO + } + + loggerErr := state.Logger.Init(logLevel, name, directory) + if loggerErr != nil { + return errors.New("Failed to create a logger") + } + + // Initialize the FSM + state.FSM.Init(stateCallback, &state.Logger, debug) + state.Debug = debug + + // Initialize the Config + state.Config.Init(name, directory) + + // Initialize Discovery + state.Discovery.Init(&state.FSM, &state.Logger) + + // Try to load the previous configuration + if state.Config.Load(&state) != nil { + // This error can be safely ignored, as when the config does not load, the struct will not be filled + state.Logger.Log(internal.LOG_INFO, "Previous configuration not found") + } + state.FSM.GoTransition(internal.NO_SERVER) + return nil +} + +func (state *VPNState) Deregister() error { + // Close the log file + state.Logger.Close() + + // Save the config + state.Config.Save(&state) + + // Empty out fsm + state.FSM = internal.FSM{} + return nil +} + +func (state *VPNState) Connect(url string) (string, error) { + if state.FSM.InState(internal.DEREGISTERED) { + return "", errors.New("app not registered") + } + // New server chosen, ensure the server is fresh + server := state.Servers.EnsureServer(url, &state.FSM, &state.Logger) + // Make sure we are in the chosen state if available + state.FSM.GoTransition(internal.CHOSEN_SERVER) + // Relogin with oauth + // This moves the state to authenticated + if server.NeedsRelogin() { + loginErr := server.Login() + + if loginErr != nil { + return "", loginErr + } + } else { // OAuth was valid, ensure we are in the authenticated state + state.FSM.GoTransition(internal.AUTHENTICATED) + } + + state.FSM.GoTransition(internal.REQUEST_CONFIG) + + config, configErr := server.GetConfig() + + if configErr != nil { + return "", configErr + } else { + state.FSM.GoTransition(internal.HAS_CONFIG) + } + + return config, nil +} + +func (state *VPNState) GetDiscoOrganizations() (string, error) { + if state.FSM.InState(internal.DEREGISTERED) { + return "", errors.New("app not registered") + } + return state.Discovery.GetOrganizationsList() +} + + +func (state *VPNState) GetDiscoServers() (string, error) { + if state.FSM.InState(internal.DEREGISTERED) { + return "", errors.New("app not registered") + } + return state.Discovery.GetServersList() +} + +func (state *VPNState) SetProfileID(profileID string) error { + if !state.FSM.InState(internal.ASK_PROFILE) { + return errors.New("Invalid state for setting a profile") + } + + server, serverErr := state.Servers.GetCurrentServer() + if serverErr != nil { + return errors.New("No server found for setting a profile ID") + } + server.Profiles.Current = profileID + return nil +} |
