Skip to content

Commit

Permalink
Add environment param to IAPI client
Browse files Browse the repository at this point in the history
  • Loading branch information
anbsky committed Oct 5, 2022
1 parent 209b04b commit 070b610
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 47 deletions.
16 changes: 12 additions & 4 deletions app/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ type ctxKey int
const userContextKey ctxKey = iota

type CurrentUser struct {
IP string
IAPIClient *iapi.Client
ipAddr string
iac *iapi.Client

user *models.User
err error
Expand Down Expand Up @@ -68,8 +68,8 @@ func GetCurrentUserData(ctx context.Context) (*CurrentUser, error) {
return res, nil
}

func NewCurrentUser(u *models.User, e error) *CurrentUser {
return &CurrentUser{user: u, err: e}
func NewCurrentUser(u *models.User, ipAddr string, iac *iapi.Client, e error) *CurrentUser {
return &CurrentUser{user: u, ipAddr: ipAddr, iac: iac, err: e}
}

func (cu CurrentUser) User() *models.User {
Expand All @@ -80,6 +80,14 @@ func (cu CurrentUser) Err() error {
return cu.err
}

func (cu CurrentUser) IP() string {
return cu.ipAddr
}

func (cu CurrentUser) IAPIClient() *iapi.Client {
return cu.iac
}

// NewIAPIProvider authenticates a user by hitting internal-api with the auth token
// and matching the response to a local user. If auth is successful, the user will have a
// lbrynet server assigned and a wallet that's created and ready to use.
Expand Down
8 changes: 2 additions & 6 deletions app/auth/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,7 @@ func Middleware(auther Authenticator) mux.MiddlewareFunc {
}
}

cu := NewCurrentUser(user, err)
cu.IP = ipAddr
cu.IAPIClient = iac
cu := NewCurrentUser(user, ipAddr, iac, err)
next.ServeHTTP(w, r.Clone(context.WithValue(r.Context(), userContextKey, cu)))
})
}
Expand Down Expand Up @@ -79,9 +77,7 @@ func LegacyMiddleware(provider Provider) mux.MiddlewareFunc {
hub.Scope().SetUser(sentry.User{ID: strconv.Itoa(user.ID), IPAddress: ipAddr})
}
}
cu := NewCurrentUser(user, err)
cu.IP = ipAddr
cu.IAPIClient = iac
cu := NewCurrentUser(user, ipAddr, iac, err)
next.ServeHTTP(w, r.Clone(context.WithValue(r.Context(), userContextKey, cu)))
return
}
Expand Down
2 changes: 1 addition & 1 deletion app/auth/middleware_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ func TestFromRequestFail(t *testing.T) {

func dummyHandler(w http.ResponseWriter, r *http.Request) {
cu, err := GetCurrentUserData(r.Context())
w.Header().Add("x-remote-ip", cu.IP)
w.Header().Add("x-remote-ip", cu.IP())
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(fmt.Sprintf("unexpected error: %s", err)))
Expand Down
9 changes: 4 additions & 5 deletions app/query/paid_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const (
noAccessPaidURL = "lbry://@PlayNice#4/Alexswar#c"
noAccessMembersOnlyURL = "lbry://@gifprofile#7/members-only-no-access#8"

livestreamURL = "lbry://@gifprofile#7/members-only-livestream#f"
livestreamURL = "lbry://@gifprofile:7/members-only-live-2:4"

falseIP = "8.8.8.8"
)
Expand Down Expand Up @@ -88,9 +88,8 @@ func (s *paidContentSuite) SetupSuite() {
)
s.Require().NoError(err)

cu := auth.NewCurrentUser(u, nil)
cu.IP = falseIP
cu.IAPIClient = iac
cu := auth.NewCurrentUser(
u, falseIP, iac, nil)
s.cu = cu
}

Expand All @@ -111,7 +110,7 @@ func (s *paidContentSuite) TestUnauthorized() {
for _, tc := range cases {
s.Run(tc.url, func() {
request := jsonrpc.NewRequest(MethodGet, map[string]interface{}{"uri": tc.url})
ctx := auth.AttachCurrentUser(bgctx(), auth.NewCurrentUser(nil, errors.Err("anonymous")))
ctx := auth.AttachCurrentUser(bgctx(), auth.NewCurrentUser(nil, falseIP, nil, errors.Err("anonymous")))
_, err := NewCaller(s.sdkAddress, 0).Call(ctx, request)
s.EqualError(err, tc.errString)
})
Expand Down
17 changes: 12 additions & 5 deletions app/query/processors.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ func preflightHookGet(caller *Caller, ctx context.Context) (*jsonrpc.RPCResponse
if err != nil {
return nil, err
}
ip := cu.IP
ip := cu.IP()
hlsHash := signStreamURL(hlsUrl, fmt.Sprintf("ip=%s&pass=%s", ip, pcfg["paidpass"]))

startQuery := fmt.Sprintf("hash-hls=%s&ip=%s&pass=%s", hlsHash, ip, pcfg["paidpass"])
Expand All @@ -113,7 +113,7 @@ func preflightHookGet(caller *Caller, ctx context.Context) (*jsonrpc.RPCResponse
if err != nil {
return nil, err
}
ip := cu.IP
ip := cu.IP()
query := fmt.Sprintf("ip=%s&pass=%s", ip, pcfg["paidpass"])
responseResult[ParamStreamingUrl] = fmt.Sprintf(
"%s?ip=%s&hash=%s",
Expand Down Expand Up @@ -217,11 +217,14 @@ func preflightHookGet(caller *Caller, ctx context.Context) (*jsonrpc.RPCResponse

func checkStreamAccess(ctx context.Context, claim *ljsonrpc.Claim) (bool, error) {
var (
accessType string
accessType, environ string
)

params := GetQuery(ctx).ParamsAsMap()
_, isLivestream := params["base_streaming_url"]
if p, ok := params[iapi.ParamEnviron]; ok {
environ, _ = p.(string)
}

TagLoop:
for _, t := range claim.Value.Tags {
Expand Down Expand Up @@ -252,10 +255,14 @@ TagLoop:
if err != nil {
return false, errors.Err("no user data in context: %w", err)
}
if cu.IAPIClient == nil {

iac := cu.IAPIClient()
if iac == nil {
return false, errors.Err("authentication required")
}
iac := cu.IAPIClient
if environ == iapi.EnvironTest {
iac = iac.Clone(iapi.WithEnvironment(iapi.EnvironTest))
}

switch accessType {
case accessTypePurchase, accessTypeRental:
Expand Down
4 changes: 1 addition & 3 deletions internal/e2etest/e2etest.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,7 @@ func (s *UserTestHelper) Setup(t *testing.T) error {
return err
}

cu := auth.NewCurrentUser(u, nil)
cu.IP = "8.8.8.8"
cu.IAPIClient = iac
cu := auth.NewCurrentUser(u, "8.8.8.8", iac, nil)

s.TestUser = &TestUser{
User: u,
Expand Down
56 changes: 33 additions & 23 deletions pkg/iapi/iapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ import (
)

const (
EnvironLive = "live"
EnvironTest = "test"
ParamEnviron = "environment"

defaultServerAddress = "https://api.odysee.com"
timeout = 5 * time.Second
headerForwardedFor = "X-Forwarded-For"
Expand All @@ -35,24 +39,17 @@ type httpClient interface {
// - RemoteIP — to forward the IP of a frontend client making the request
type clientOptions struct {
server string
legacyToken string
oauthToken string
remoteIP string
extraHeaders map[string]string
extraParams map[string]string
httpClient httpClient
}

func WithLegacyToken(token string) func(options *clientOptions) {
return func(options *clientOptions) {
options.legacyToken = token
}
return WithExtraParam(paramLegacyToken, token)
}

func WithOAuthToken(token string) func(options *clientOptions) {
return func(options *clientOptions) {
options.oauthToken = token
}
return WithExtraHeader(headerOauthToken, "Bearer "+token)
}

func WithServer(server string) func(options *clientOptions) {
Expand All @@ -62,16 +59,19 @@ func WithServer(server string) func(options *clientOptions) {
}

func WithRemoteIP(remoteIP string) func(options *clientOptions) {
return func(options *clientOptions) {
options.remoteIP = remoteIP
}
return WithExtraHeader(headerForwardedFor, remoteIP)
}

func WithExtraHeader(key, value string) func(options *clientOptions) {
return func(options *clientOptions) {
options.extraHeaders[key] = value
}
}

func WithEnvironment(name string) func(options *clientOptions) {
return WithExtraParam(ParamEnviron, name)
}

func WithExtraParam(key, value string) func(options *clientOptions) {
return func(options *clientOptions) {
options.extraParams[key] = value
Expand All @@ -90,30 +90,40 @@ func NewClient(optionFuncs ...func(*clientOptions)) (*Client, error) {
options := &clientOptions{
server: "https://api.odysee.com",
extraHeaders: map[string]string{},
extraParams: map[string]string{},
extraParams: map[string]string{ParamEnviron: EnvironLive},
httpClient: &http.Client{Timeout: timeout},
}

for _, optionFunc := range optionFuncs {
optionFunc(options)
}

if options.remoteIP != "" {
options.extraHeaders[headerForwardedFor] = options.remoteIP
}
if options.legacyToken != "" {
options.extraParams[paramLegacyToken] = options.legacyToken
} else if options.oauthToken != "" {
options.extraHeaders[headerOauthToken] = "Bearer " + options.oauthToken
} else {
if options.extraHeaders[headerOauthToken] == "" && options.extraParams[paramLegacyToken] == "" {
return nil, errors.New("either legacy or oauth token required")
}

c := &Client{options: *options}
return c, nil
}

func (c Client) prepareParams(params map[string]string) url.Values {
func (c Client) Clone(optionFuncs ...func(*clientOptions)) *Client {
o := c.options
o.extraHeaders = map[string]string{}
o.extraParams = map[string]string{}
for k, v := range c.options.extraHeaders {
o.extraHeaders[k] = v
}
for k, v := range c.options.extraParams {
o.extraParams[k] = v
}

for _, optionFunc := range optionFuncs {
optionFunc(&o)
}
return &Client{options: o}
}

func (c *Client) prepareParams(params map[string]string) url.Values {
data := url.Values{}
for k, v := range c.options.extraParams {
data.Add(k, v)
Expand All @@ -124,7 +134,7 @@ func (c Client) prepareParams(params map[string]string) url.Values {
return data
}

func (c Client) Call(path string, params map[string]string, target interface{}) error {
func (c *Client) Call(path string, params map[string]string, target interface{}) error {
r, err := http.NewRequest(
http.MethodPost,
fmt.Sprintf("%s/%s", c.options.server, path),
Expand Down
20 changes: 20 additions & 0 deletions pkg/iapi/iapi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,26 @@ import (
"github.com/stretchr/testify/require"
)

func TestNewClient(t *testing.T) {
dummyToken := randomdata.Alphanumeric(120)
remoteIP := "8.8.8.8"

_, err := NewClient(WithRemoteIP(remoteIP))
assert.Error(t, err)

c, err := NewClient(WithOAuthToken(dummyToken), WithRemoteIP(remoteIP))
require.NoError(t, err)
assert.Equal(t, "Bearer "+dummyToken, c.options.extraHeaders[headerOauthToken])
assert.Equal(t, remoteIP, c.options.extraHeaders[headerForwardedFor])
assert.Equal(t, EnvironLive, c.options.extraParams[ParamEnviron])

cc := c.Clone(WithEnvironment(EnvironTest))
assert.Equal(t, EnvironTest, cc.options.extraParams[ParamEnviron])
assert.Equal(t, remoteIP, cc.options.extraHeaders[headerForwardedFor])
assert.Equal(t, "Bearer "+dummyToken, cc.options.extraHeaders[headerOauthToken])
assert.Equal(t, EnvironLive, c.options.extraParams[ParamEnviron])
}

func TestCallCustomerList(t *testing.T) {
oat, err := test.GetTestToken()
require.NoError(t, err)
Expand Down

0 comments on commit 070b610

Please sign in to comment.