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

moving user ID back to an int #4345

Merged
merged 12 commits into from
May 20, 2016
32 changes: 22 additions & 10 deletions src/github.com/getlantern/flashlight/app/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ package app

import (
"encoding/base64"
"encoding/json"
"io/ioutil"
"net/http"
"path/filepath"
"reflect"
"sync"

"code.google.com/p/go-uuid/uuid"
Expand All @@ -30,7 +32,7 @@ var (
// Settings is a struct of all settings unique to this particular Lantern instance.
type Settings struct {
DeviceID string `json:"deviceID,omitempty"`
UserID string `json:"userID,omitempty"`
UserID int64 `json:"userID,omitempty"`
UserToken string `json:"userToken,omitempty"`

AutoReport bool `json:"autoReport"`
Expand Down Expand Up @@ -130,8 +132,8 @@ func (s *Settings) read(in <-chan interface{}, out chan<- interface{}) {
s.checkBool(data, "proxyAll", s.SetProxyAll)
s.checkBool(data, "autoLaunch", s.SetAutoLaunch)
s.checkBool(data, "systemProxy", s.SetSystemProxy)
s.checkString(data, "userID", s.SetUserID)
s.checkString(data, "token", s.SetToken)
s.checkNum(data, "userID", s.SetUserID)
s.checkString(data, "userToken", s.SetToken)

out <- s
}
Expand All @@ -145,6 +147,18 @@ func (s *Settings) checkBool(data map[string]interface{}, name string, f func(bo
}
}

func (s *Settings) checkNum(data map[string]interface{}, name string, f func(int64)) {
if v, ok := data[name].(json.Number); ok {
if bigint, err := v.Int64(); err != nil {
log.Errorf("Could not get int64 value for %v with error %v", name, err)
} else {
f(bigint)
}
} else {
log.Errorf("Could not convert %v of type %v", name, reflect.TypeOf(data[name]))
}
}

func (s *Settings) checkString(data map[string]interface{}, name string, f func(string)) {
if v, ok := data[name].(string); ok {
f(v)
Expand All @@ -155,15 +169,15 @@ func (s *Settings) checkString(data map[string]interface{}, name string, f func(

// Save saves settings to disk.
func (s *Settings) save() {
log.Debug("Saving settings")
log.Trace("Saving settings")
s.Lock()
defer s.Unlock()
if bytes, err := yaml.Marshal(s); err != nil {
log.Errorf("Could not create yaml from settings %v", err)
} else if err := ioutil.WriteFile(path, bytes, 0644); err != nil {
log.Errorf("Could not write settings file %v", err)
} else {
log.Debugf("Saved settings to %s with contents %v", path, string(bytes))
log.Tracef("Saved settings to %s with contents %v", path, string(bytes))
}
}

Expand Down Expand Up @@ -214,9 +228,7 @@ func (s *Settings) GetSystemProxy() bool {

// SetDeviceID sets the device ID
func (s *Settings) SetDeviceID(deviceID string) {
s.Lock()
defer s.unlockAndSave()
s.DeviceID = deviceID
// Cannot set the device ID.
}

// GetDeviceID returns the unique ID of this device.
Expand All @@ -241,14 +253,14 @@ func (s *Settings) GetToken() string {
}

// SetUserID sets the user ID
func (s *Settings) SetUserID(id string) {
func (s *Settings) SetUserID(id int64) {
s.Lock()
defer s.unlockAndSave()
s.UserID = id
}

// GetUserID returns the user ID
func (s *Settings) GetUserID() string {
func (s *Settings) GetUserID() int64 {
s.RLock()
defer s.RUnlock()
return s.UserID
Expand Down
75 changes: 60 additions & 15 deletions src/github.com/getlantern/flashlight/app/settings_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
package app

import (
"encoding/base64"
"encoding/json"
"io/ioutil"
"os"
"strings"
"testing"

"code.google.com/p/go-uuid/uuid"

"github.com/stretchr/testify/assert"
)

Expand All @@ -17,50 +22,90 @@ func TestRead(t *testing.T) {

defer os.Remove(tmpfile.Name()) // clean up

var uid int64
s := loadSettingsFrom("1", "1/1/1", "1/1/1", tmpfile.Name())
assert.Equal(t, s.GetProxyAll(), false)
assert.Equal(t, s.GetUserID(), "")
assert.Equal(t, s.GetUserID(), uid)
assert.Equal(t, s.GetSystemProxy(), true)
assert.Equal(t, s.IsAutoReport(), true)

m := make(map[string]interface{})
// Start with raw JSON so we actually decode the map from scratch, as that
// will then simulate real world use where we rely on Go to generate the
// actual types of the JSON values. For example, all numbers will be
// decoded as float64.
var data = []byte(`{
"autoReport": false,
"proxyAll": true,
"autoLaunch": false,
"systemProxy": false,
"deviceID": "8208fja09493",
"userID": 890238588
}`)

m["autoReport"] = false
m["proxyAll"] = true
m["autoLaunch"] = false
m["systemProxy"] = false
var m map[string]interface{}
d := json.NewDecoder(strings.NewReader(string(data)))

// These should be strings, but make sure things don't fail if we send
// bogus stuff.
m["userID"] = true
m["token"] = true
// Make sure to use json.Number here to avoid issues with 64 bit integers.
d.UseNumber()
err = d.Decode(&m)

in := make(chan interface{}, 100)
in <- m
out := make(chan interface{})
go s.read(in, out)

//close(in)
<-out

uid = 890238588
assert.Equal(t, s.GetProxyAll(), true)
assert.Equal(t, s.GetSystemProxy(), false)
assert.Equal(t, s.IsAutoReport(), false)
assert.Equal(t, s.GetUserID(), "")
assert.Equal(t, s.GetUserID(), uid)
assert.Equal(t, s.GetDeviceID(), base64.StdEncoding.EncodeToString(uuid.NodeID()))

// Test that setting something random doesn't break stuff.
m["randomjfdklajfla"] = "fadldjfdla"

// Test tokens while we're at it.
token := "token"
m["userToken"] = token
in <- m
<-out
assert.Equal(t, s.GetProxyAll(), true)
assert.Equal(t, s.GetToken(), token)

// Test with an actual user ID.
id := "qrueiquriqepuriop"
var id json.Number = "483109"
var expected int64 = 483109
m["userID"] = id
in <- m
<-out
assert.Equal(t, s.GetUserID(), id)
assert.Equal(t, s.GetProxyAll(), true)
assert.Equal(t, expected, s.GetUserID())
assert.Equal(t, true, s.GetProxyAll())
}

func TestCheckNum(t *testing.T) {
set := &Settings{}
m := make(map[string]interface{})

var val json.Number = "4809"
m["test"] = val

var expected int64 = 4809
var received int64
set.checkNum(m, "test", func(val int64) {
received = val
assert.Equal(t, val, val)
})
assert.Equal(t, expected, received)

set.checkString(m, "test", func(val string) {
assert.Fail(t, "Should not have been called")
})

set.checkBool(m, "test", func(val bool) {
assert.Fail(t, "Should not have been called")
})
}

func TestNotPersistVersion(t *testing.T) {
Expand Down
8 changes: 5 additions & 3 deletions src/github.com/getlantern/flashlight/config/fetcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"math/rand"
"net/http"
"net/http/httputil"
"strconv"
"time"

"github.com/getlantern/yamlconf"
Expand Down Expand Up @@ -42,7 +43,7 @@ type fetcher struct {

// UserConfig retrieves any custom user info for fetching the config.
type UserConfig interface {
GetUserID() string
GetUserID() int64
GetToken() string
}

Expand Down Expand Up @@ -117,8 +118,9 @@ func (cf *fetcher) fetchCloudConfig(cfg *Config) ([]byte, error) {
req.Header.Set("Lantern-Fronted-URL", cfg.FrontedCloudConfig+cb)

id := cf.user.GetUserID()
if id != "" {
req.Header.Set(userIDHeader, id)
if id != 0 {
strID := strconv.FormatInt(id, 10)
req.Header.Set(userIDHeader, strID)
}
tok := cf.user.GetToken()
if tok != "" {
Expand Down
4 changes: 2 additions & 2 deletions src/github.com/getlantern/flashlight/config/fetcher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ func (uc *userConfig) GetToken() string {
return "token"
}

func (uc *userConfig) GetUserID() string {
return "10"
func (uc *userConfig) GetUserID() int64 {
return 10
}

// TestFetcher actually fetches a config file over the network.
Expand Down
5 changes: 4 additions & 1 deletion src/github.com/getlantern/flashlight/ui/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package ui
import (
"encoding/json"
"fmt"
"strings"
"sync"
)

Expand Down Expand Up @@ -153,7 +154,9 @@ func read() {
}

env := &Envelope{}
err = json.Unmarshal(b, env)
d := json.NewDecoder(strings.NewReader(string(b)))
d.UseNumber()
err = d.Decode(env)
if err != nil {
log.Errorf("Unable to unmarshal message of type %v: %v", envType.Type, err)
continue
Expand Down
4 changes: 2 additions & 2 deletions src/github.com/getlantern/lantern/lantern.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@ func (uc *userConfig) GetToken() string {
return ""
}

func (uc *userConfig) GetUserID() string {
return "0"
func (uc *userConfig) GetUserID() int64 {
return 0
}

func run(configDir string) {
Expand Down