summaryrefslogtreecommitdiff
path: root/internal/api.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/api.go')
-rw-r--r--internal/api.go192
1 files changed, 0 insertions, 192 deletions
diff --git a/internal/api.go b/internal/api.go
deleted file mode 100644
index 5c2cf6d..0000000
--- a/internal/api.go
+++ /dev/null
@@ -1,192 +0,0 @@
-package internal
-
-import (
- "encoding/json"
- "errors"
- "fmt"
- "net/http"
- "net/url"
-)
-
-// Authorized wrappers on top of HTTP
-// the errors will not be wrapped here so that the caller can check if we got a status error, to retry oauth
-func apiAuthorized(server Server, method string, endpoint string, opts *HTTPOptionalParams) (http.Header, []byte, error) {
- // Ensure optional is not nil as we will fill it with headers
- if opts == nil {
- opts = &HTTPOptionalParams{}
- }
- base, baseErr := server.GetBase()
-
- if baseErr != nil {
- return nil, nil, baseErr
- }
-
- url := base.Endpoints.API.V3.API + endpoint
-
- // Ensure we have valid tokens
- stateBefore := base.FSM.Current
- oauthErr := EnsureTokens(server)
-
- // we reset the state so that we go from the authorized state to the state we want
- base.FSM.Current = stateBefore
-
- if oauthErr != nil {
- return nil, nil, oauthErr
- }
-
- headerKey := "Authorization"
- headerValue := fmt.Sprintf("Bearer %s", server.GetOAuth().Token.Access)
- if opts.Headers != nil {
- opts.Headers.Add(headerKey, headerValue)
- } else {
- opts.Headers = http.Header{headerKey: {headerValue}}
- }
- return HTTPMethodWithOpts(method, url, opts)
-}
-
-func apiAuthorizedRetry(server Server, method string, endpoint string, opts *HTTPOptionalParams) (http.Header, []byte, error) {
- header, body, bodyErr := apiAuthorized(server, method, endpoint, opts)
- base, baseErr := server.GetBase()
-
- if baseErr != nil {
- return nil, nil, &APIAuthorizedError{Err: baseErr}
- }
- if bodyErr != nil {
- var error *HTTPStatusError
-
- // Only retry authorized if we get a HTTP 401
- if errors.As(bodyErr, &error) && error.Status == 401 {
- base.Logger.Log(LOG_INFO, fmt.Sprintf("API: Got HTTP error %v, retrying authorized", error))
- // Tell the method that the token is expired
- server.GetOAuth().Token.ExpiredTimestamp = GenerateTimeSeconds()
- retryHeader, retryBody, retryErr := apiAuthorized(server, method, endpoint, opts)
- if retryErr != nil {
- return nil, nil, &APIAuthorizedError{Err: retryErr}
- }
- return retryHeader, retryBody, nil
- }
- return nil, nil, &APIAuthorizedError{Err: bodyErr}
- }
- return header, body, nil
-}
-
-func APIInfo(server Server) error {
- _, body, bodyErr := apiAuthorizedRetry(server, http.MethodGet, "/info", nil)
- if bodyErr != nil {
- return &APIInfoError{Err: bodyErr}
- }
- structure := ServerProfileInfo{}
- jsonErr := json.Unmarshal(body, &structure)
-
- if jsonErr != nil {
- return &APIInfoError{Err: jsonErr}
- }
-
- base, baseErr := server.GetBase()
-
- if baseErr != nil {
- return &APIInfoError{Err: baseErr}
- }
-
- // Store the profiles and make sure that the current profile is not overwritten
- previousProfile := base.Profiles.Current
- base.Profiles = structure
- base.Profiles.Current = previousProfile
- base.ProfilesRaw = string(body)
- return nil
-}
-
-func APIConnectWireguard(server Server, profile_id string, pubkey string, supportsOpenVPN bool) (string, string, int64, error) {
- headers := http.Header{
- "content-type": {"application/x-www-form-urlencoded"},
- "accept": {"application/x-wireguard-profile"},
- }
-
- if supportsOpenVPN {
- headers.Add("accept", "application/x-openvpn-profile")
- }
-
- urlForm := url.Values{
- "profile_id": {profile_id},
- "public_key": {pubkey},
- }
- header, connectBody, connectErr := apiAuthorizedRetry(server, http.MethodPost, "/connect", &HTTPOptionalParams{Headers: headers, Body: urlForm})
- if connectErr != nil {
- return "", "", 0, &APIConnectWireguardError{Err: connectErr}
- }
-
- expires := header.Get("expires")
-
- pTime, pTimeErr := http.ParseTime(expires)
- if pTimeErr != nil {
- return "", "", 0, &APIConnectWireguardError{Err: pTimeErr}
- }
-
- contentType := header.Get("content-type")
-
- content := "openvpn"
- if contentType == "application/x-wireguard-profile" {
- content = "wireguard"
- }
- return string(connectBody), content, pTime.Unix(), nil
-}
-
-func APIConnectOpenVPN(server Server, profile_id string) (string, int64, error) {
- headers := http.Header{
- "content-type": {"application/x-www-form-urlencoded"},
- "accept": {"application/x-openvpn-profile"},
- }
-
- urlForm := url.Values{
- "profile_id": {profile_id},
- }
-
- header, connectBody, connectErr := apiAuthorizedRetry(server, http.MethodPost, "/connect", &HTTPOptionalParams{Headers: headers, Body: urlForm})
- if connectErr != nil {
- return "", 0, &APIConnectOpenVPNError{Err: connectErr}
- }
-
- expires := header.Get("expires")
- pTime, pTimeErr := http.ParseTime(expires)
- if pTimeErr != nil {
- return "", 0, &APIConnectOpenVPNError{Err: pTimeErr}
- }
- return string(connectBody), pTime.Unix(), nil
-}
-
-// This needs no further return value as it's best effort
-func APIDisconnect(server Server) {
- apiAuthorizedRetry(server, http.MethodPost, "/disconnect", nil)
-}
-
-type APIAuthorizedError struct {
- Err error
-}
-
-func (e *APIAuthorizedError) Error() string {
- return fmt.Sprintf("failed api authorized call with error: %v", e.Err)
-}
-
-type APIConnectWireguardError struct {
- Err error
-}
-
-func (e *APIConnectWireguardError) Error() string {
- return fmt.Sprintf("failed api /connect wireguard call with error: %v", e.Err)
-}
-
-type APIConnectOpenVPNError struct {
- Err error
-}
-
-func (e *APIConnectOpenVPNError) Error() string {
- return fmt.Sprintf("failed api /connect OpenVPN call with error: %v", e.Err)
-}
-
-type APIInfoError struct {
- Err error
-}
-
-func (e *APIInfoError) Error() string {
- return fmt.Sprintf("failed api /info call with error: %v", e.Err)
-}