Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move token handling to identity #4

Merged
merged 8 commits into from
Dec 23, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Clearer structure, add copyrights
  • Loading branch information
andig committed Dec 21, 2024
commit 4443325030c5414562fd9953dffe1c0843ebcfb9
82 changes: 82 additions & 0 deletions functions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package sensonet

func GetDhwData(state SystemStatus, index int) *DhwData {
// Extracting correct State.Dhw element
if len(state.State.Dhw) == 0 {
return nil
}
var dhwData DhwData
for _, stateDhw := range state.State.Dhw {
if stateDhw.Index == index || (stateDhw.Index == HOTWATERINDEX_DEFAULT && index < 0) {
dhwData.State = stateDhw
break
}
}
for _, propDhw := range state.Properties.Dhw {
if propDhw.Index == index || (propDhw.Index == HOTWATERINDEX_DEFAULT && index < 0) {
dhwData.Properties = propDhw
break
}
}
for _, confDhw := range state.Configuration.Dhw {
if confDhw.Index == index || (confDhw.Index == HOTWATERINDEX_DEFAULT && index < 0) {
dhwData.Configuration = confDhw
break
}
}
return &dhwData
}

func GetDomesticHotWaterData(state SystemStatus, index int) *DomesticHotWaterData {
// Extracting correct State.DomesticHotWater element
if len(state.State.DomesticHotWater) == 0 {
return nil
}
var domesticHotWaterData DomesticHotWaterData
for _, stateDomesticHotWater := range state.State.DomesticHotWater {
if stateDomesticHotWater.Index == index || (stateDomesticHotWater.Index == HOTWATERINDEX_DEFAULT && index < 0) {
domesticHotWaterData.State = stateDomesticHotWater
break
}
}
for _, propDomesticHotWater := range state.Properties.DomesticHotWater {
if propDomesticHotWater.Index == index || (propDomesticHotWater.Index == HOTWATERINDEX_DEFAULT && index < 0) {
domesticHotWaterData.Properties = propDomesticHotWater
break
}
}
for _, confDomesticHotWater := range state.Configuration.DomesticHotWater {
if confDomesticHotWater.Index == index || (confDomesticHotWater.Index == HOTWATERINDEX_DEFAULT && index < 0) {
domesticHotWaterData.Configuration = confDomesticHotWater
break
}
}
return &domesticHotWaterData
}

func GetZoneData(state SystemStatus, index int) *ZoneData {
// Extracting correct State.Zones element
if len(state.State.Zones) == 0 {
return nil
}
var zoneData ZoneData
for _, stateZone := range state.State.Zones {
if stateZone.Index == index || (stateZone.Index == ZONEINDEX_DEFAULT && index < 0) {
zoneData.State = stateZone
break
}
}
for _, propZone := range state.Properties.Zones {
if propZone.Index == index || (propZone.Index == ZONEINDEX_DEFAULT && index < 0) {
zoneData.Properties = propZone
break
}
}
for _, confZone := range state.Configuration.Zones {
if confZone.Index == index || (confZone.Index == ZONEINDEX_DEFAULT && index < 0) {
zoneData.Configuration = confZone
break
}
}
return &zoneData
}
74 changes: 13 additions & 61 deletions identity.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,10 @@ import (
"net/http/cookiejar"
"net/url"
"strings"
"sync"
"time"

"github.com/coreos/go-oidc/v3/oidc"

"dario.cat/mergo"
"golang.org/x/oauth2"
)

Expand Down Expand Up @@ -156,65 +154,6 @@ func (v *Identity) Login() (oauth2.TokenSource, error) {
return ts, nil
}

type tokenRefresher interface {
RefreshToken(token *oauth2.Token) (*oauth2.Token, error)
}

type TokenSource struct {
mu sync.Mutex
token *oauth2.Token
refresher tokenRefresher
}

func refreshTokenSource(token *oauth2.Token, refresher tokenRefresher) oauth2.TokenSource {
if token == nil {
// allocate an (expired) token or mergeToken will fail
token = new(oauth2.Token)
}

ts := &TokenSource{
token: token,
refresher: refresher,
}

return ts
}

func (ts *TokenSource) Token() (*oauth2.Token, error) {
ts.mu.Lock()
defer ts.mu.Unlock()

if ts.token.Valid() {
return ts.token, nil
}

token, err := ts.refresher.RefreshToken(ts.token)
if err != nil {
return ts.token, err
}

if token.AccessToken == "" {
err = errors.New("token refresh failed to obtain access token")
} else {
err = mergo.Merge(ts.token, token, mergo.WithOverride)
}

return ts.token, err
}

func computeLoginUrl(body, realm string) string {
url := fmt.Sprintf(LOGIN_URL, realm)
index1 := strings.Index(body, "authenticate?")
if index1 < 0 {
return ""
}
index2 := strings.Index(body[index1:], "\"")
if index2 < 0 {
return ""
}
return html.UnescapeString(url + body[index1+12:index1+index2])
}

func (v *Identity) RefreshToken(token *oauth2.Token) (*oauth2.Token, error) {
params := url.Values{
"grant_type": {"refresh_token"},
Expand Down Expand Up @@ -242,3 +181,16 @@ func (v *Identity) RefreshToken(token *oauth2.Token) (*oauth2.Token, error) {

return &res.Token, nil
}

func computeLoginUrl(body, realm string) string {
url := fmt.Sprintf(LOGIN_URL, realm)
index1 := strings.Index(body, "authenticate?")
if index1 < 0 {
return ""
}
index2 := strings.Index(body[index1:], "\"")
if index2 < 0 {
return ""
}
return html.UnescapeString(url + body[index1+12:index1+index2])
}
57 changes: 57 additions & 0 deletions tokensource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package sensonet

// Copied from https://github.com/evcc-io/evcc

import (
"errors"
"sync"

"dario.cat/mergo"
"golang.org/x/oauth2"
)

type tokenRefresher interface {
RefreshToken(token *oauth2.Token) (*oauth2.Token, error)
}

type tokenSource struct {
mu sync.Mutex
token *oauth2.Token
refresher tokenRefresher
}

func refreshTokenSource(token *oauth2.Token, refresher tokenRefresher) oauth2.TokenSource {
if token == nil {
// allocate an (expired) token or mergeToken will fail
token = new(oauth2.Token)
}

ts := &tokenSource{
token: token,
refresher: refresher,
}

return ts
}

func (ts *tokenSource) Token() (*oauth2.Token, error) {
ts.mu.Lock()
defer ts.mu.Unlock()

if ts.token.Valid() {
return ts.token, nil
}

token, err := ts.refresher.RefreshToken(ts.token)
if err != nil {
return ts.token, err
}

if token.AccessToken == "" {
err = errors.New("token refresh failed to obtain access token")
} else {
err = mergo.Merge(ts.token, token, mergo.WithOverride)
}

return ts.token, err
}
83 changes: 2 additions & 81 deletions util.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package sensonet

// Copied from https://github.com/evcc-io/evcc

import (
"encoding/json"
"fmt"
Expand Down Expand Up @@ -105,84 +107,3 @@ func ReadBody(resp *http.Response) ([]byte, error) {
}
return b, nil
}

func GetDhwData(state SystemStatus, index int) *DhwData {
// Extracting correct State.Dhw element
if len(state.State.Dhw) == 0 {
return nil
}
var dhwData DhwData
for _, stateDhw := range state.State.Dhw {
if stateDhw.Index == index || (stateDhw.Index == HOTWATERINDEX_DEFAULT && index < 0) {
dhwData.State = stateDhw
break
}
}
for _, propDhw := range state.Properties.Dhw {
if propDhw.Index == index || (propDhw.Index == HOTWATERINDEX_DEFAULT && index < 0) {
dhwData.Properties = propDhw
break
}
}
for _, confDhw := range state.Configuration.Dhw {
if confDhw.Index == index || (confDhw.Index == HOTWATERINDEX_DEFAULT && index < 0) {
dhwData.Configuration = confDhw
break
}
}
return &dhwData
}

func GetDomesticHotWaterData(state SystemStatus, index int) *DomesticHotWaterData {
// Extracting correct State.DomesticHotWater element
if len(state.State.DomesticHotWater) == 0 {
return nil
}
var domesticHotWaterData DomesticHotWaterData
for _, stateDomesticHotWater := range state.State.DomesticHotWater {
if stateDomesticHotWater.Index == index || (stateDomesticHotWater.Index == HOTWATERINDEX_DEFAULT && index < 0) {
domesticHotWaterData.State = stateDomesticHotWater
break
}
}
for _, propDomesticHotWater := range state.Properties.DomesticHotWater {
if propDomesticHotWater.Index == index || (propDomesticHotWater.Index == HOTWATERINDEX_DEFAULT && index < 0) {
domesticHotWaterData.Properties = propDomesticHotWater
break
}
}
for _, confDomesticHotWater := range state.Configuration.DomesticHotWater {
if confDomesticHotWater.Index == index || (confDomesticHotWater.Index == HOTWATERINDEX_DEFAULT && index < 0) {
domesticHotWaterData.Configuration = confDomesticHotWater
break
}
}
return &domesticHotWaterData
}

func GetZoneData(state SystemStatus, index int) *ZoneData {
// Extracting correct State.Zones element
if len(state.State.Zones) == 0 {
return nil
}
var zoneData ZoneData
for _, stateZone := range state.State.Zones {
if stateZone.Index == index || (stateZone.Index == ZONEINDEX_DEFAULT && index < 0) {
zoneData.State = stateZone
break
}
}
for _, propZone := range state.Properties.Zones {
if propZone.Index == index || (propZone.Index == ZONEINDEX_DEFAULT && index < 0) {
zoneData.Properties = propZone
break
}
}
for _, confZone := range state.Configuration.Zones {
if confZone.Index == index || (confZone.Index == ZONEINDEX_DEFAULT && index < 0) {
zoneData.Configuration = confZone
break
}
}
return &zoneData
}