Skip to content

Commit

Permalink
All: Refactor to Discovery v3
Browse files Browse the repository at this point in the history
And rename `instance` to `provider`
  • Loading branch information
jwijenbergh committed Dec 3, 2024
1 parent 433c4df commit 7c5eba8
Show file tree
Hide file tree
Showing 9 changed files with 458 additions and 325 deletions.
30 changes: 15 additions & 15 deletions cmd/geteduroam-cli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ import (

"github.com/geteduroam/linux-app/internal/discovery"
"github.com/geteduroam/linux-app/internal/handler"
"github.com/geteduroam/linux-app/internal/instance"
"github.com/geteduroam/linux-app/internal/log"
"github.com/geteduroam/linux-app/internal/network"
"github.com/geteduroam/linux-app/internal/notification"
"github.com/geteduroam/linux-app/internal/provider"
"github.com/geteduroam/linux-app/internal/utils"
"github.com/geteduroam/linux-app/internal/version"
)
Expand Down Expand Up @@ -73,8 +73,8 @@ func ask(prompt string, validator func(input string) bool) string {
}
}

// filteredOrganizations gets the instances as filtered by the user
func filteredOrganizations(orgs *instance.Instances, q string) (f *instance.Instances) {
// filteredOrganizations gets the providers as filtered by the user
func filteredOrganizations(orgs *provider.Providers, q string) (f *provider.Providers) {
for {
empties := 0
x := ask(q, func(x string) bool {
Expand Down Expand Up @@ -116,8 +116,8 @@ func validateRange(input string, n int) bool {
return true
}

// organization gets an organization/instance from the user
func organization(orgs *instance.Instances) *instance.Instance {
// organization gets an organization/provider from the user
func organization(orgs *provider.Providers) *provider.Provider {
_, h, err := term.GetSize(0)
if err != nil {
slog.Warn("Could not get height")
Expand Down Expand Up @@ -152,7 +152,7 @@ func organization(orgs *instance.Instances) *instance.Instance {
}

// profile gets a profile for a list of profiles by asking the user one if there are multiple
func profile(profiles []instance.Profile) *instance.Profile {
func profile(profiles []provider.Profile) *provider.Profile {
// Only one profile, return it immediately
if len(profiles) == 1 {
return &profiles[0]
Expand Down Expand Up @@ -312,7 +312,7 @@ func file(metadata []byte) (*time.Time, error) {
}

// direct does the handling for the direct flow
func direct(p *instance.Profile) {
func direct(p *provider.Profile) {
config, err := p.EAPDirect()
if err != nil {
slog.Error("Could not obtain eap config", "error", err)
Expand All @@ -330,7 +330,7 @@ func direct(p *instance.Profile) {
}

// redirect does the handling for the redirect flow
func redirect(p *instance.Profile) {
func redirect(p *provider.Profile) {
r, err := p.RedirectURI()
if err != nil {
slog.Error("Failed to complete the flow, no redirect URI is available")
Expand All @@ -347,7 +347,7 @@ func redirect(p *instance.Profile) {
}

// oauth does the handling for the OAuth flow
func oauth(p *instance.Profile) *time.Time {
func oauth(p *provider.Profile) *time.Time {
config, err := p.EAPOAuth(context.Background(), func(url string) {
fmt.Println("Your browser has been opened to authorize the client")
fmt.Println("Or copy and paste the following url:", url)
Expand Down Expand Up @@ -384,10 +384,10 @@ func doLocal(filename string) *time.Time {

func doDiscovery() *time.Time {
c := discovery.NewCache()
i, err := c.Instances()
i, err := c.Providers()
if err != nil {
slog.Error("Failed to get instances from discovery", "error", err)
fmt.Printf("Failed to get instances from discovery %v\n", err)
slog.Error("Failed to get providers from discovery", "error", err)
fmt.Printf("Failed to get providers from discovery %v\n", err)
os.Exit(1)
}

Expand All @@ -397,11 +397,11 @@ func doDiscovery() *time.Time {
// TODO: This switch statement should probably be moved to the profile code
// By providing an "EAP" method on profile
switch p.Flow() {
case instance.DirectFlow:
case provider.DirectFlow:
direct(p)
case instance.RedirectFlow:
case provider.RedirectFlow:
redirect(p)
case instance.OAuthFlow:
case provider.OAuthFlow:
return oauth(p)
}
return nil
Expand Down
38 changes: 19 additions & 19 deletions cmd/geteduroam-gui/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,31 +21,31 @@ import (

"github.com/geteduroam/linux-app/internal/discovery"
"github.com/geteduroam/linux-app/internal/handler"
"github.com/geteduroam/linux-app/internal/instance"
"github.com/geteduroam/linux-app/internal/log"
"github.com/geteduroam/linux-app/internal/network"
"github.com/geteduroam/linux-app/internal/provider"
"github.com/geteduroam/linux-app/internal/version"
)

type serverList struct {
sync.Mutex
store *gtk.StringList
instances instance.Instances
providers provider.Providers
list *SelectList
}

func (s *serverList) get(idx int) (*instance.Instance, error) {
if idx < 0 || idx > len(s.instances) {
func (s *serverList) get(idx int) (*provider.Provider, error) {
if idx < 0 || idx > len(s.providers) {
return nil, errors.New("index out of range")
}
return &s.instances[idx], nil
return &s.providers[idx], nil
}

func (s *serverList) Fill() {
s.Lock()
defer s.Unlock()
for idx, inst := range s.instances {
s.list.Add(idx, inst.Name)
for idx, inst := range s.providers {
s.list.Add(idx, inst.Name.Get())
}
}

Expand Down Expand Up @@ -93,7 +93,7 @@ func (m *mainState) file(metadata []byte) (*time.Time, error) {
return h.Configure(metadata)
}

func (m *mainState) direct(p instance.Profile) error {
func (m *mainState) direct(p provider.Profile) error {
config, err := p.EAPDirect()
if err != nil {
return err
Expand All @@ -114,7 +114,7 @@ func (m *mainState) local(path string) (*time.Time, error) {
return v, nil
}

func (m *mainState) oauth(ctx context.Context, p instance.Profile) (*time.Time, error) {
func (m *mainState) oauth(ctx context.Context, p provider.Profile) (*time.Time, error) {
ctx, cancel := context.WithCancel(ctx)
defer cancel()
config, err := p.EAPOAuth(ctx, func(url string) {
Expand All @@ -135,31 +135,31 @@ func (m *mainState) oauth(ctx context.Context, p instance.Profile) (*time.Time,
return m.file(config)
}

func (m *mainState) rowActivated(sel instance.Instance) {
func (m *mainState) rowActivated(sel provider.Provider) {
var page gtk.Box
m.builder.GetObject("searchPage").Cast(&page)
defer page.Unref()
l := NewLoadingPage(m.builder, m.stack, "Loading organization details...", nil)
l.Initialize()
ctx := context.Background()
chosen := func(p instance.Profile) (err error) {
chosen := func(p provider.Profile) (err error) {
defer func() {
err = ensureContextError(ctx, err)
}()
var valid *time.Time
var isredirect bool
switch p.Flow() {
case instance.DirectFlow:
case provider.DirectFlow:
err = m.direct(p)
if err != nil {
return err
}
case instance.OAuthFlow:
case provider.OAuthFlow:
valid, err = m.oauth(ctx, p)
if err != nil {
return err
}
case instance.RedirectFlow:
case provider.RedirectFlow:
isredirect = true
url, err := p.RedirectURI()
if err != nil {
Expand All @@ -177,7 +177,7 @@ func (m *mainState) rowActivated(sel instance.Instance) {
})
return nil
}
cb := func(p instance.Profile) {
cb := func(p provider.Profile) {
err := chosen(p)
if err != nil {
l.Hide()
Expand All @@ -200,12 +200,12 @@ func (m *mainState) initList() {
defer list.Unref()

cache := discovery.NewCache()
inst, err := cache.Instances()
inst, err := cache.Providers()
if err != nil {
m.ShowError(err)
return
}
m.servers.instances = *inst
m.servers.providers = *inst

var search gtk.SearchEntry
m.builder.GetObject("searchBox").Cast(&search)
Expand All @@ -222,11 +222,11 @@ func (m *mainState) initList() {
}

sorter := func(a, b string) int {
return instance.SortNames(a, b, search.GetText())
return provider.SortNames(a, b, search.GetText())
}

m.servers.list = NewSelectList(m.scroll, &list, activated, sorter).WithFiltering(func(a string) bool {
return instance.FilterSingle(a, search.GetText())
return provider.FilterSingle(a, search.GetText())
})

// Fill the servers in the select list
Expand Down
12 changes: 6 additions & 6 deletions cmd/geteduroam-gui/profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,20 @@ package main
import (
"golang.org/x/exp/slog"

"github.com/geteduroam/linux-app/internal/instance"
"github.com/geteduroam/linux-app/internal/provider"
"github.com/jwijenbergh/puregotk/v4/adw"
"github.com/jwijenbergh/puregotk/v4/gtk"
)

type ProfileState struct {
builder *gtk.Builder
stack *adw.ViewStack
profiles []instance.Profile
success func(instance.Profile)
profiles []provider.Profile
success func(provider.Profile)
sl *SelectList
}

func NewProfileState(builder *gtk.Builder, stack *adw.ViewStack, profiles []instance.Profile, success func(instance.Profile)) *ProfileState {
func NewProfileState(builder *gtk.Builder, stack *adw.ViewStack, profiles []provider.Profile, success func(provider.Profile)) *ProfileState {
return &ProfileState{
builder: builder,
stack: stack,
Expand Down Expand Up @@ -55,7 +55,7 @@ func (p *ProfileState) Initialize() {

sorter := func(a, b string) int {
// Here we have no search query
return instance.SortNames(a, b, "")
return provider.SortNames(a, b, "")
}
activated := func(idx int) {
go p.success(p.profiles[idx])
Expand All @@ -65,7 +65,7 @@ func (p *ProfileState) Initialize() {
p.sl = NewSelectList(&scroll, &list, activated, sorter)

for idx, prof := range p.profiles {
p.sl.Add(idx, prof.Name)
p.sl.Add(idx, prof.Name.Get())
}

p.sl.Setup()
Expand Down
50 changes: 20 additions & 30 deletions internal/discovery/discovery.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// package discovery contains methods to parse the discovery format from https://discovery.eduroam.app/v1/discovery.json into instances
// package discovery contains methods to parse the discovery format from https://discovery.eduroam.app/v3/discovery.json into providers
package discovery

import (
Expand All @@ -10,15 +10,18 @@ import (

"golang.org/x/exp/slog"

"github.com/geteduroam/linux-app/internal/instance"
"github.com/geteduroam/linux-app/internal/provider"
)

// Discovery is the main structure that is used for unmarshalling the JSON
type Discovery struct {
Instances instance.Instances `json:"instances"`
Value Value `json:"http://letswifi.app/discovery#v3"`
}

type Value struct {
Providers provider.Providers `json:"providers"`
// See: https://github.com/geteduroam/windows-app/blob/22cd90f36031907c7174fbdc678edafaa627ce49/CHANGELOG.md#changed
Seq int `json:"seq"`
Version int `json:"version"`
Seq int `json:"seq"`
}

// Cache is the cached discovery list
Expand Down Expand Up @@ -46,62 +49,49 @@ func (c *Cache) ToUpdate() bool {
return n.After(u)
}

// Instances gets the instances either from the cache or from scratch
func (c *Cache) Instances() (*instance.Instances, error) {
// Providers gets the providers either from the cache or from scratch
func (c *Cache) Providers() (*provider.Providers, error) {
if !c.ToUpdate() {
return &c.Cached.Instances, nil
return &c.Cached.Value.Providers, nil
}

req, err := http.NewRequest("GET", "https://discovery.eduroam.app/v1/discovery.json", nil)
req, err := http.NewRequest("GET", "https://discovery.eduroam.app/v3/discovery.json", nil)
if err != nil {
return &c.Cached.Instances, err
return &c.Cached.Value.Providers, err
}

// Do request
client := http.Client{Timeout: 10 * time.Second}
res, err := client.Do(req)
if err != nil {
slog.Debug("Error requesting discovery.json", "error", err)
return &c.Cached.Instances, err
return &c.Cached.Value.Providers, err
}
defer res.Body.Close()

body, err := io.ReadAll(res.Body)
if err != nil {
slog.Debug("Error reading discovery.json response", "error", err)
return &c.Cached.Instances, err
return &c.Cached.Value.Providers, err
}
if res.StatusCode < 200 || res.StatusCode > 299 {
return &c.Cached.Instances, fmt.Errorf("status code is not 2xx for discovery. Status code: %v, body: %v", res.StatusCode, string(body))
return &c.Cached.Value.Providers, fmt.Errorf("status code is not 2xx for discovery. Status code: %v, body: %v", res.StatusCode, string(body))
}

var d *Discovery
err = json.Unmarshal(body, &d)
if err != nil {
slog.Debug("Error loading discovery.json", "error", err)
return &c.Cached.Instances, err
return &c.Cached.Value.Providers, err
}

d.Instances = append(d.Instances, instance.Instance{
Name: "LetsWifi development banaan",
Profiles: []instance.Profile{
{
AuthorizationEndpoint: "http://0.0.0.0:8080/oauth/authorize/",
Default: true,
EapConfigEndpoint: "http://0.0.0.0:8080/api/eap-config/",
OAuth: true,
TokenEndpoint: "http://0.0.0.0:8080/oauth/token/",
},
},
})

// Do not accept older versions
// This happens if the cached version is higher
if c.Cached.Seq > d.Seq {
return &c.Cached.Instances, fmt.Errorf("cached seq is higher")
if c.Cached.Value.Seq > d.Value.Seq {
return &c.Cached.Value.Providers, fmt.Errorf("cached seq is higher")
}

c.Cached = *d
c.LastUpdate = time.Now()
return &d.Instances, nil
return &d.Value.Providers, nil
}
Loading

0 comments on commit 7c5eba8

Please sign in to comment.