summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--client/discovery.go26
-rw-r--r--docs/src/api/functiondocs.md52
-rw-r--r--exports/exports.go50
-rw-r--r--internal/discovery/discovery.go38
-rw-r--r--types/discovery/discovery.go5
-rw-r--r--wrappers/python/eduvpn_common/loader.py4
-rw-r--r--wrappers/python/eduvpn_common/main.py8
7 files changed, 150 insertions, 33 deletions
diff --git a/client/discovery.go b/client/discovery.go
index a1df585..49df8b2 100644
--- a/client/discovery.go
+++ b/client/discovery.go
@@ -13,11 +13,11 @@ func (c *Client) hasDiscovery() bool {
return strings.HasPrefix(c.Name, "org.eduvpn.app")
}
-// DiscoOrganizations gets the organizations list from the discovery server
+// DiscoOrganizations gets the organizations list from the discovery server with search string `search`
// If the list cannot be retrieved an error is returned.
// If this is the case then a previous version of the list is returned if there is any.
// This takes into account the frequency of updates, see: https://github.com/eduvpn/documentation/blob/v3/SERVER_DISCOVERY.md#organization-list.
-func (c *Client) DiscoOrganizations(ck *cookie.Cookie) (*discotypes.Organizations, error) {
+func (c *Client) DiscoOrganizations(ck *cookie.Cookie, search string) (*discotypes.Organizations, error) {
// Not supported with Let's Connect! & govVPN
if !c.hasDiscovery() {
return nil, i18nerr.NewInternal("Server/organization discovery with this client ID is not supported")
@@ -32,20 +32,23 @@ func (c *Client) DiscoOrganizations(ck *cookie.Cookie) (*discotypes.Organization
}
// convert to public subset
- retOrgs := make([]discotypes.Organization, len(orgs.List))
- for i, v := range orgs.List {
- retOrgs[i] = v.Organization
+ var retOrgs []discotypes.Organization
+ for _, v := range orgs.List {
+ if !v.Matches(search) {
+ continue
+ }
+ retOrgs = append(retOrgs, v.Organization)
}
return &discotypes.Organizations{
List: retOrgs,
}, err
}
-// DiscoServers gets the servers list from the discovery server
+// DiscoServers gets the servers list from the discovery server with search string `search`
// If the list cannot be retrieved an error is returned.
// If this is the case then a previous version of the list is returned if there is any.
// This takes into account the frequency of updates, see: https://github.com/eduvpn/documentation/blob/v3/SERVER_DISCOVERY.md#server-list.
-func (c *Client) DiscoServers(ck *cookie.Cookie) (*discotypes.Servers, error) {
+func (c *Client) DiscoServers(ck *cookie.Cookie, search string) (*discotypes.Servers, error) {
// Not supported with Let's Connect! & govVPN
if !c.hasDiscovery() {
return nil, i18nerr.NewInternal("Server/organization discovery with this client ID is not supported")
@@ -60,9 +63,12 @@ func (c *Client) DiscoServers(ck *cookie.Cookie) (*discotypes.Servers, error) {
}
// convert to public subset
- retServs := make([]discotypes.Server, len(servs.List))
- for i, v := range servs.List {
- retServs[i] = v.Server
+ var retServs []discotypes.Server
+ for _, v := range servs.List {
+ if !v.Matches(search) {
+ continue
+ }
+ retServs = append(retServs, v.Server)
}
return &discotypes.Servers{
List: retServs,
diff --git a/docs/src/api/functiondocs.md b/docs/src/api/functiondocs.md
index 58134f7..5d7d9ac 100644
--- a/docs/src/api/functiondocs.md
+++ b/docs/src/api/functiondocs.md
@@ -289,19 +289,21 @@ Example Output:
## DiscoOrganizations
Signature:
```go
-func DiscoOrganizations(c C.uintptr_t) (*C.char, *C.char)
+func DiscoOrganizations(c C.uintptr_t, search *C.char) (*C.char, *C.char)
```
DiscoOrganizations gets the organizations from discovery, returned as
types/discovery/discovery.go Organizations marshalled as JSON
`c` is the Cookie that needs to be passed. Create a new Cookie using
-`CookieNew`
+`CookieNew` `search` is the search string for filtering the list. It checks
+for keywords and display name case insensitive as a substring matching.
+If search is empty it returns ALL organizations currently known in common
If it was unsuccessful, it returns an error. Note that when the lib was
built in release mode the data is almost always non-nil, even when an error
has occurred This means it has just returned the cached list
-Example Input: ```DiscoOrganizations(myCookie)```
+Example Input: ```DiscoOrganizations(myCookie, "")```
Example Output:
@@ -332,22 +334,41 @@ Example Output:
"secure_inte .....................
}, null
+Example Input: ```DiscoOrganizations(myCookie, "rash")```
+
+Example Output:
+
+ {
+ "v": 1695291170,
+ "organization_list": [
+ {
+ "display_name": {
+ "en": "Academic Network of Albania - RASH"
+ },
+ "org_id": "https://idp.rash.al/simplesaml/saml2/idp/metadata.php",
+ "secure_internet_home": "https://eduvpn.rash.al/"
+ },
+ }, null
+
## DiscoServers
Signature:
```go
-func DiscoServers(c C.uintptr_t) (*C.char, *C.char)
+func DiscoServers(c C.uintptr_t, search *C.char) (*C.char, *C.char)
```
DiscoServers gets the servers from discovery, returned as
types/discovery/discovery.go Servers marshalled as JSON
`c` is the Cookie that needs to be passed. Create a new Cookie using
-`CookieNew`
+`CookieNew` `search` is the search string for filtering the list. It checks
+for keywords and display name case insensitive as a substring matching.
+If search is empty it returns ALL servers currently known in common,
+including secure internet servers that do not have a display name set
If it was unsuccessful, it returns an error. Note that when the lib was
built in release mode the data is almost always non-nil, even when an error
has occurred This means it has just returned the cached list
-Example Input: ```DiscoServers(myCookie)```
+Example Input: ```DiscoServers(myCookie, "")```
Example Output:
@@ -373,6 +394,25 @@ Example Output:
], ..................
} , null
+Example Input: ```DiscoServers(myCookie, "heanet")```
+
+Example Output:
+
+ {
+ "v": 1695291170,
+ "server_list": [
+ {
+ "base_url": "https://eduvpn.heanet.ie/",
+ "display_name": "HEAnet Staff",
+ "server_type": "institute_access",
+ "support_contact": [
+ "mailto:noc@heanet.ie",
+ "tel:+35316609040"
+ ]
+ },
+ ]
+ } , null
+
## ExpiryTimes
Signature:
```go
diff --git a/exports/exports.go b/exports/exports.go
index 4c9e0dc..d914120 100644
--- a/exports/exports.go
+++ b/exports/exports.go
@@ -671,11 +671,12 @@ func SetSecureLocation(orgID *C.char, cc *C.char) *C.char {
// DiscoServers gets the servers from discovery, returned as types/discovery/discovery.go Servers marshalled as JSON
//
// `c` is the Cookie that needs to be passed. Create a new Cookie using `CookieNew`
+// `search` is the search string for filtering the list. It checks for keywords and display name case insensitive as a substring matching. If search is empty it returns ALL servers currently known in common, including secure internet servers that do not have a display name set
//
// If it was unsuccessful, it returns an error. Note that when the lib was built in release mode the data is almost always non-nil, even when an error has occurred
// This means it has just returned the cached list
//
-// Example Input: ```DiscoServers(myCookie)```
+// Example Input: ```DiscoServers(myCookie, "")```
//
// Example Output:
//
@@ -701,8 +702,27 @@ func SetSecureLocation(orgID *C.char, cc *C.char) *C.char {
// ], ..................
// } , null
//
+// Example Input: ```DiscoServers(myCookie, "heanet")```
+//
+// Example Output:
+//
+// {
+// "v": 1695291170,
+// "server_list": [
+// {
+// "base_url": "https://eduvpn.heanet.ie/",
+// "display_name": "HEAnet Staff",
+// "server_type": "institute_access",
+// "support_contact": [
+// "mailto:noc@heanet.ie",
+// "tel:+35316609040"
+// ]
+// },
+// ]
+// } , null
+//
//export DiscoServers
-func DiscoServers(c C.uintptr_t) (*C.char, *C.char) {
+func DiscoServers(c C.uintptr_t, search *C.char) (*C.char, *C.char) {
state, stateErr := getVPNState()
if stateErr != nil {
return nil, getCError(stateErr)
@@ -711,7 +731,7 @@ func DiscoServers(c C.uintptr_t) (*C.char, *C.char) {
if err != nil {
return nil, getCError(err)
}
- servers, err := state.DiscoServers(ck)
+ servers, err := state.DiscoServers(ck, C.GoString(search))
if servers == nil && err != nil {
return nil, getCError(err)
}
@@ -725,11 +745,12 @@ func DiscoServers(c C.uintptr_t) (*C.char, *C.char) {
// DiscoOrganizations gets the organizations from discovery, returned as types/discovery/discovery.go Organizations marshalled as JSON
//
// `c` is the Cookie that needs to be passed. Create a new Cookie using `CookieNew`
+// `search` is the search string for filtering the list. It checks for keywords and display name case insensitive as a substring matching. If search is empty it returns ALL organizations currently known in common
//
// If it was unsuccessful, it returns an error. Note that when the lib was built in release mode the data is almost always non-nil, even when an error has occurred
// This means it has just returned the cached list
//
-// Example Input: ```DiscoOrganizations(myCookie)```
+// Example Input: ```DiscoOrganizations(myCookie, "")```
//
// Example Output:
//
@@ -760,8 +781,25 @@ func DiscoServers(c C.uintptr_t) (*C.char, *C.char) {
// "secure_inte .....................
// }, null
//
+// Example Input: ```DiscoOrganizations(myCookie, "rash")```
+//
+// Example Output:
+//
+// {
+// "v": 1695291170,
+// "organization_list": [
+// {
+// "display_name": {
+// "en": "Academic Network of Albania - RASH"
+// },
+// "org_id": "https://idp.rash.al/simplesaml/saml2/idp/metadata.php",
+// "secure_internet_home": "https://eduvpn.rash.al/"
+// },
+// }, null
+//
+//
//export DiscoOrganizations
-func DiscoOrganizations(c C.uintptr_t) (*C.char, *C.char) {
+func DiscoOrganizations(c C.uintptr_t, search *C.char) (*C.char, *C.char) {
state, stateErr := getVPNState()
if stateErr != nil {
return nil, getCError(stateErr)
@@ -770,7 +808,7 @@ func DiscoOrganizations(c C.uintptr_t) (*C.char, *C.char) {
if err != nil {
return nil, getCError(err)
}
- orgs, err := state.DiscoOrganizations(ck)
+ orgs, err := state.DiscoOrganizations(ck, C.GoString(search))
if orgs == nil && err != nil {
return nil, getCError(err)
}
diff --git a/internal/discovery/discovery.go b/internal/discovery/discovery.go
index 4a9ab92..6b7b961 100644
--- a/internal/discovery/discovery.go
+++ b/internal/discovery/discovery.go
@@ -5,6 +5,7 @@ import (
"context"
"encoding/json"
"fmt"
+ "strings"
"time"
"github.com/eduvpn/eduvpn-common/internal/http"
@@ -34,6 +35,25 @@ type Organization struct {
// SecureInternetHome is the secure internet home server that belongs to this organization
// Omitted if none is defined
SecureInternetHome string `json:"secure_internet_home"`
+ // KeywordList is the list of keywords
+ // Omitted if none is defined
+ KeywordList discotypes.MapOrString `json:"keyword_list,omitempty"`
+}
+
+// Matches returns if the search query `str` matches with this organization
+func (s *Organization) Matches(str string) bool {
+ var catalog strings.Builder
+ for _, v := range s.DisplayName {
+ // length and nil error is returned
+ _, _ = catalog.WriteString(strings.ToLower(v))
+ _, _ = catalog.WriteString(" ")
+ }
+ for _, v := range s.KeywordList {
+ // length and nil error is returned
+ _, _ = catalog.WriteString(strings.ToLower(v))
+ _, _ = catalog.WriteString(" ")
+ }
+ return strings.Contains(catalog.String(), str)
}
// Servers are the list of servers from https://disco.eduvpn.org/v2/server_list.json
@@ -55,12 +75,30 @@ type Server struct {
AuthenticationURLTemplate string `json:"authentication_url_template,omitempty"`
// CountryCode is the country code for the server in case of secure internet, e.g. NL
CountryCode string `json:"country_code,omitempty"`
+ // KeywordList are the keywords of the server, omitted if empty
+ KeywordList discotypes.MapOrString `json:"keyword_list,omitempty"`
// PublicKeyList are the public keys of the server. Currently not used in this lib but returned by the upstream discovery server
PublicKeyList []string `json:"public_key_list,omitempty"`
// SupportContact is the list/slice of support contacts
SupportContact []string `json:"support_contact,omitempty"`
}
+// Matches returns if the search query `str` matches with this server
+func (s *Server) Matches(str string) bool {
+ var catalog strings.Builder
+ for _, v := range s.DisplayName {
+ // length and nil error is returned
+ _, _ = catalog.WriteString(strings.ToLower(v))
+ _, _ = catalog.WriteString(" ")
+ }
+ for _, v := range s.KeywordList {
+ // length and nil error is returned
+ _, _ = catalog.WriteString(strings.ToLower(v))
+ _, _ = catalog.WriteString(" ")
+ }
+ return strings.Contains(catalog.String(), str)
+}
+
// Discovery is the main structure used for this package.
type Discovery struct {
// The httpClient for sending HTTP requests
diff --git a/types/discovery/discovery.go b/types/discovery/discovery.go
index da029e7..a6be5bf 100644
--- a/types/discovery/discovery.go
+++ b/types/discovery/discovery.go
@@ -17,9 +17,6 @@ type Organization struct {
DisplayName MapOrString `json:"display_name,omitempty"`
// OrgID is the organization ID for the server
OrgID string `json:"org_id"`
- // KeywordList is the list of keywords
- // Omitted if none is defined
- KeywordList MapOrString `json:"keyword_list,omitempty"`
}
// Servers is the type that defines the upstream discovery format for the list of servers
@@ -35,8 +32,6 @@ type Server struct {
BaseURL string `json:"base_url"`
// DisplayName is the display name of the server, omitted if empty
DisplayName MapOrString `json:"display_name,omitempty"`
- // DisplayName are the keywords of the server, omitted if empty
- KeywordList MapOrString `json:"keyword_list,omitempty"`
// Type is the type of the server, "secure_internet" or "institute_access"
Type string `json:"server_type"`
}
diff --git a/wrappers/python/eduvpn_common/loader.py b/wrappers/python/eduvpn_common/loader.py
index 08179ee..b74741f 100644
--- a/wrappers/python/eduvpn_common/loader.py
+++ b/wrappers/python/eduvpn_common/loader.py
@@ -49,8 +49,8 @@ def initialize_functions(lib: CDLL) -> None:
lib.Deregister.argtypes, lib.Deregister.restype = [], None
lib.ExpiryTimes.argtypes, lib.ExpiryTimes.restype = [], DataError
lib.FreeString.argtypes, lib.FreeString.restype = [c_void_p], None
- lib.DiscoOrganizations.argtypes, lib.DiscoOrganizations.restype = [c_int], DataError
- lib.DiscoServers.argtypes, lib.DiscoServers.restype = [c_int], DataError
+ lib.DiscoOrganizations.argtypes, lib.DiscoOrganizations.restype = [c_int, c_char_p], DataError
+ lib.DiscoServers.argtypes, lib.DiscoServers.restype = [c_int, c_char_p], DataError
lib.GetConfig.argtypes, lib.GetConfig.restype = (
[
c_int,
diff --git a/wrappers/python/eduvpn_common/main.py b/wrappers/python/eduvpn_common/main.py
index 4582c8d..cb81e53 100644
--- a/wrappers/python/eduvpn_common/main.py
+++ b/wrappers/python/eduvpn_common/main.py
@@ -178,13 +178,13 @@ class EduVPN(object):
forwardError(server_err)
return server
- def get_disco_organizations(self) -> str:
- orgs, _ = self.go_cookie_function(self.lib.DiscoOrganizations)
+ def get_disco_organizations(self, search="") -> str:
+ orgs, _ = self.go_cookie_function(self.lib.DiscoOrganizations, search)
# TODO: Log error
return orgs
- def get_disco_servers(self) -> str:
- servers, _ = self.go_cookie_function(self.lib.DiscoServers)
+ def get_disco_servers(self, search="") -> str:
+ servers, _ = self.go_cookie_function(self.lib.DiscoServers, search)
# TODO: Log error
return servers