Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
7 changes: 4 additions & 3 deletions internal/dev_server/db/backup/sqllite_backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ import (
"context"
"database/sql"
"fmt"
sqllite "github.com/mattn/go-sqlite3"
"github.com/pkg/errors"
"io"
"log"
"os"
"sync"
"sync/atomic"

sqllite "github.com/mattn/go-sqlite3"
"github.com/pkg/errors"
)

var c atomic.Int32
Expand Down Expand Up @@ -195,7 +196,7 @@ func runBackup(backupDbConn *sqllite.SQLiteConn, srcDbConn *sqllite.SQLiteConn,
}(backup)

var isDone = false
var stepError error = nil
var stepError error
for !isDone {
isDone, stepError = backup.Step(1)
if stepError != nil {
Expand Down
8 changes: 6 additions & 2 deletions internal/dev_server/db/sqlite.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ import (
"context"
"database/sql"
"encoding/json"
_ "github.com/mattn/go-sqlite3"
"github.com/pkg/errors"
"io"
"os"

_ "github.com/mattn/go-sqlite3"
"github.com/pkg/errors"

"github.com/launchdarkly/go-sdk-common/v3/ldvalue"
"github.com/launchdarkly/ldcli/internal/dev_server/db/backup"
"github.com/launchdarkly/ldcli/internal/dev_server/model"
Expand Down Expand Up @@ -380,6 +381,9 @@ func (s *Sqlite) RestoreBackup(ctx context.Context, stream io.Reader) (string, e

func (s *Sqlite) CreateBackup(ctx context.Context) (io.ReadCloser, int64, error) {
backupPath, err := s.backupManager.MakeBackupFile(ctx)
if err != nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oof nice catch - should we make a follow up item to add a linter rule to catch ineffectual assigns to err?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The linter is running if you use pre-commit, but it doesn't look like pre-commit checks are being run in ci.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But yeah. A follow up item to fixup the CI linter is a good idea.

return nil, 0, errors.Wrapf(err, "unable to make backup file, %s", backupPath)
}
fi, err := os.Open(backupPath)
if err != nil {
return nil, 0, errors.Wrapf(err, "unable to open backup db at %s", backupPath)
Expand Down
62 changes: 62 additions & 0 deletions internal/dev_server/sdk/http_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package sdk

import (
"fmt"
"net/http"
"net/http/httptest"
"testing"
"time"

"github.com/gorilla/mux"
"github.com/launchdarkly/go-sdk-common/v3/ldcontext"
"github.com/launchdarkly/ldcli/internal/dev_server/model"
"github.com/launchdarkly/ldcli/internal/dev_server/model/mocks"
"github.com/stretchr/testify/assert"
"go.uber.org/mock/gomock"
)

var exampleProjectKey = "my-project"
var exampleProject = &model.Project{
Key: exampleProjectKey,
SourceEnvironmentKey: "my-environment",
Context: ldcontext.Context{},
LastSyncTime: time.Unix(0, 0),
AllFlagsState: make(model.FlagsState),
AvailableVariations: nil,
}

func TestMobileAuth(t *testing.T) {
mockController := gomock.NewController(t)
store := mocks.NewMockStore(mockController)
observers := model.NewObservers()

// Wire up sdk routes in test server
router := mux.NewRouter()
router.Use(model.ObserversMiddleware(observers))
router.Use(model.StoreMiddleware(store))
BindRoutes(router)

t.Run("given project key prefixed with api_key, it should authenticate successfully", func(t *testing.T) {
store.EXPECT().GetDevProject(gomock.Any(), exampleProjectKey).Return(exampleProject, nil)
store.EXPECT().GetOverridesForProject(gomock.Any(), exampleProjectKey).Return(nil, nil)

req := httptest.NewRequest("GET", "/msdk/evalx/eyJrZXkiOiJib2FyZCBjYXQifQ==", nil)
req.Header.Set("Authorization", fmt.Sprintf("api_key %s", exampleProjectKey))
rec := httptest.NewRecorder()
router.ServeHTTP(rec, req)

assert.Equal(t, http.StatusOK, rec.Code)
})

t.Run("given just the project key, it should authenticate successfully", func(t *testing.T) {
store.EXPECT().GetDevProject(gomock.Any(), exampleProjectKey).Return(exampleProject, nil)
store.EXPECT().GetOverridesForProject(gomock.Any(), exampleProjectKey).Return(nil, nil)

req := httptest.NewRequest("GET", "/msdk/evalx/eyJrZXkiOiJib2FyZCBjYXQifQ==", nil)
req.Header.Set("Authorization", exampleProjectKey)
rec := httptest.NewRecorder()
router.ServeHTTP(rec, req)

assert.Equal(t, http.StatusOK, rec.Code)
})
}
2 changes: 2 additions & 0 deletions internal/dev_server/sdk/project_key_middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package sdk
import (
"context"
"net/http"
"strings"

"github.com/gorilla/mux"
)
Expand Down Expand Up @@ -38,6 +39,7 @@ func GetProjectKeyFromAuthorizationHeader(handler http.Handler) http.Handler {
return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
ctx := request.Context()
projectKey := request.Header.Get("Authorization")
projectKey = strings.TrimPrefix(projectKey, "api_key ") // some sdks set this as a prefix
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@keelerm84 Are there other scenarios we should be aware of for auth key formats?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure. The api_key prefix isn't coming from any of the SDKs I wouldn't think. We don't add additional prefixing, outside of the standard key formats.

Maybe that's something more aligned with the integrations team, or whoever is in charge of the auto-generated API SDKs?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lol glad we were both surprised by this behavior. It looks like iOS is doing this prefixing thing. Looks like same for android.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤯 Well that IS surprising. I wonder if that is still necessary.

I checked the relay, and there is a fetchAuthToken method that only checks for that api_key prefix, so maybe we can be more confident that prefix is the only one we have to worry about.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooh. Thank you for looking at the relay implementation. If that's all it supports, I think we're all good here.

if projectKey == "" {
http.Error(writer, "project key not on Authorization header", http.StatusUnauthorized)
return
Expand Down
Loading