Permalink
Browse files

Add migrations to create the database schema.

Signed-off-by: David Calavera <david.calavera@gmail.com>
  • Loading branch information...
calavera committed Oct 27, 2017
1 parent d578de1 commit 553162511c8083df631f35d67855f4704910a17e
View
@@ -9,3 +9,4 @@ www/dist/
www/.DS_Store
www/node_modules
npm-debug.log
.data
View
@@ -3,9 +3,13 @@ language: go
go:
- 1.8
- 1.9
services:
- mysql
install: make deps
script: make all
script: make migrate_test all
notifications:
email: false
View
@@ -6,6 +6,7 @@ please read the [code of conduct](CODE_OF_CONDUCT.md).
## Setup
> Install Go and Glide https://github.com/Masterminds/glide
> Install Docker to run tests
```sh
$ git clone https://github.com/netlify/gotrue
@@ -19,6 +20,23 @@ $ make deps
$ make build
```
## Running database migrations for development and testing
- Make sure your database can be accessed with user `root` without a password.
- Alternatively, you can start MySQL inside a docker container running `hack/mysqld.sh`.
### Migrations for development
```sh
$ make migrate_dev
```
### Migrations for testing
```sh
$ make migrate_test
```
## Testing
```sh
View
@@ -1,4 +1,4 @@
.PONY: all build deps image lint test
.PHONY: all build deps image lint migrate test vet
CHECK_FILES?=$$(go list ./... | grep -v /vendor/)
help: ## Show this help.
@@ -10,17 +10,24 @@ build: ## Build the binary.
go build -ldflags "-X github.com/netlify/gotrue/cmd.Version=`git rev-parse HEAD`"
deps: ## Install dependencies.
@go get -u github.com/markbates/pop/soda
@go get -u github.com/golang/lint/golint
@go get -u github.com/Masterminds/glide && glide install
image: ## Build the Docker image.
docker build .
lint: ## Lint the code
lint: ## Lint the code.
golint $(CHECK_FILES)
vet: # Vet the code
go vet $(CHECK_FILES)
migrate_dev: ## Run database migrations for development.
hack/migrate.sh development
migrate_test: ## Run database migrations for test.
hack/migrate.sh test
test: ## Run tests.
go test -v $(CHECK_FILES)
vet: # Vet the code
go vet $(CHECK_FILES)
View
@@ -55,7 +55,7 @@ func (a *API) adminUsers(w http.ResponseWriter, r *http.Request) error {
return badRequestError("Bad Pagination Parameters: %v", err)
}
sortParams, err := sort(r, map[string]bool{"created_at": true}, []models.SortField{models.SortField{Name: "created_at", Dir: models.Descending}})
sortParams, err := sort(r, map[string]bool{models.CreatedAt: true}, []models.SortField{models.SortField{Name: models.CreatedAt, Dir: models.Descending}})
if err != nil {
return badRequestError("Bad Sort Parameters: %v", err)
}
View
@@ -6,13 +6,13 @@ import (
"fmt"
"net/http"
"net/http/httptest"
"os"
"testing"
"time"
"github.com/dgrijalva/jwt-go"
"github.com/netlify/gotrue/conf"
"github.com/netlify/gotrue/models"
"github.com/netlify/gotrue/storage/test"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
@@ -24,19 +24,25 @@ type AdminTestSuite struct {
API *API
Config *conf.Configuration
token string
token string
instanceID string
}
func (ts *AdminTestSuite) TearDownTest() {
os.Remove(ts.API.config.DB.URL)
func TestAdmin(t *testing.T) {
api, config, instanceID, err := setupAPIForTestForInstance()
require.NoError(t, err)
ts := &AdminTestSuite{
API: api,
Config: config,
instanceID: instanceID,
}
suite.Run(t, ts)
}
func (ts *AdminTestSuite) SetupTest() {
require.NoError(ts.T(), os.Setenv("GOTRUE_DB_DATABASE_URL", createTestDB()))
api, config, err := NewAPIFromConfigFile("test.env", "v1")
require.NoError(ts.T(), err)
ts.API = api
ts.Config = config
test.CleanupTables()
// Setup response recorder with super admin privileges
ts.token = ts.makeSuperAdmin("test@example.com")
@@ -52,12 +58,7 @@ func (ts *AdminTestSuite) TestAdminUsersUnauthorized() {
}
func (ts *AdminTestSuite) makeSuperAdmin(email string) string {
// Cleanup existing user, if they already exist
if u, _ := ts.API.db.FindUserByEmailAndAudience("", email, ts.Config.JWT.Aud); u != nil {
require.NoError(ts.T(), ts.API.db.DeleteUser(u), "Error deleting user")
}
u, err := models.NewUser("", email, "test", ts.Config.JWT.Aud, map[string]interface{}{"full_name": "Test User"})
u, err := models.NewUser(ts.instanceID, email, "test", ts.Config.JWT.Aud, map[string]interface{}{"full_name": "Test User"})
require.NoError(ts.T(), err, "Error making new user")
u.IsSuperAdmin = true
@@ -118,10 +119,11 @@ func (ts *AdminTestSuite) TestAdminUsers() {
// TestAdminUsers tests API /admin/users route
func (ts *AdminTestSuite) TestAdminUsers_Pagination() {
u, err := models.NewUser("", "test1@example.com", "test", ts.Config.JWT.Aud, nil)
u, err := models.NewUser(ts.instanceID, "test1@example.com", "test", ts.Config.JWT.Aud, nil)
require.NoError(ts.T(), err, "Error making new user")
require.NoError(ts.T(), ts.API.db.CreateUser(u), "Error creating user")
u, err = models.NewUser("", "test2@example.com", "test", ts.Config.JWT.Aud, nil)
u, err = models.NewUser(ts.instanceID, "test2@example.com", "test", ts.Config.JWT.Aud, nil)
require.NoError(ts.T(), err, "Error making new user")
require.NoError(ts.T(), ts.API.db.CreateUser(u), "Error creating user")
@@ -146,7 +148,7 @@ func (ts *AdminTestSuite) TestAdminUsers_Pagination() {
// TestAdminUsers tests API /admin/users route
func (ts *AdminTestSuite) TestAdminUsers_SortAsc() {
u, err := models.NewUser("", "test1@example.com", "test", ts.Config.JWT.Aud, nil)
u, err := models.NewUser(ts.instanceID, "test1@example.com", "test", ts.Config.JWT.Aud, nil)
require.NoError(ts.T(), err, "Error making new user")
require.NoError(ts.T(), ts.API.db.CreateUser(u), "Error creating user")
// Setup request
@@ -174,9 +176,10 @@ func (ts *AdminTestSuite) TestAdminUsers_SortAsc() {
// TestAdminUsers tests API /admin/users route
func (ts *AdminTestSuite) TestAdminUsers_SortDesc() {
u, err := models.NewUser("", "test1@example.com", "test", ts.Config.JWT.Aud, nil)
u, err := models.NewUser(ts.instanceID, "test1@example.com", "test", ts.Config.JWT.Aud, nil)
require.NoError(ts.T(), err, "Error making new user")
require.NoError(ts.T(), ts.API.db.CreateUser(u), "Error creating user")
// Setup request
w := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, "/admin/users", nil)
@@ -214,19 +217,20 @@ func (ts *AdminTestSuite) TestAdminUserCreate() {
ts.API.handler.ServeHTTP(w, req)
require.Equal(ts.T(), http.StatusOK, w.Code)
u, err := ts.API.db.FindUserByEmailAndAudience("", "test1@example.com", ts.Config.JWT.Aud)
require.NoError(ts.T(), err)
data := models.User{}
require.NoError(ts.T(), json.NewDecoder(w.Body).Decode(&data))
assert.Equal(ts.T(), data.Email, "test1@example.com")
u, err := ts.API.db.FindUserByEmailAndAudience(ts.instanceID, "test1@example.com", ts.Config.JWT.Aud)
require.NoError(ts.T(), err)
assert.Equal(ts.T(), u.Email, data.Email)
assert.Equal(ts.T(), "email", data.AppMetaData["provider"])
}
// TestAdminUserGet tests API /admin/user route (GET)
func (ts *AdminTestSuite) TestAdminUserGet() {
u, err := models.NewUser("", "test1@example.com", "test", ts.Config.JWT.Aud, nil)
u, err := models.NewUser(ts.instanceID, "test1@example.com", "test", ts.Config.JWT.Aud, nil)
require.NoError(ts.T(), err, "Error making new user")
require.NoError(ts.T(), ts.API.db.CreateUser(u), "Error creating user")
@@ -249,7 +253,7 @@ func (ts *AdminTestSuite) TestAdminUserGet() {
// TestAdminUserUpdate tests API /admin/user route (UPDATE)
func (ts *AdminTestSuite) TestAdminUserUpdate() {
u, err := models.NewUser("", "test1@example.com", "test", ts.Config.JWT.Aud, nil)
u, err := models.NewUser(ts.instanceID, "test1@example.com", "test", ts.Config.JWT.Aud, nil)
require.NoError(ts.T(), err, "Error making new user")
require.NoError(ts.T(), ts.API.db.CreateUser(u), "Error creating user")
@@ -278,7 +282,7 @@ func (ts *AdminTestSuite) TestAdminUserUpdate() {
assert.Equal(ts.T(), data["role"], "testing")
u, err = ts.API.db.FindUserByEmailAndAudience("", "test1@example.com", ts.Config.JWT.Aud)
u, err = ts.API.db.FindUserByEmailAndAudience(ts.instanceID, "test1@example.com", ts.Config.JWT.Aud)
require.NoError(ts.T(), err)
assert.Equal(ts.T(), u.Role, "testing")
assert.Equal(ts.T(), u.UserMetaData["name"], "David")
@@ -289,7 +293,7 @@ func (ts *AdminTestSuite) TestAdminUserUpdate() {
// TestAdminUserUpdate tests API /admin/user route (UPDATE) as system user
func (ts *AdminTestSuite) TestAdminUserUpdateAsSystemUser() {
u, err := models.NewUser("", "test1@example.com", "test", ts.Config.JWT.Aud, nil)
u, err := models.NewUser(ts.instanceID, "test1@example.com", "test", ts.Config.JWT.Aud, nil)
require.NoError(ts.T(), err, "Error making new user")
require.NoError(ts.T(), ts.API.db.CreateUser(u), "Error creating user")
@@ -320,7 +324,7 @@ func (ts *AdminTestSuite) TestAdminUserUpdateAsSystemUser() {
assert.Equal(ts.T(), data["role"], "testing")
u, err = ts.API.db.FindUserByEmailAndAudience("", "test1@example.com", ts.Config.JWT.Aud)
u, err = ts.API.db.FindUserByEmailAndAudience(ts.instanceID, "test1@example.com", ts.Config.JWT.Aud)
require.NoError(ts.T(), err)
assert.Equal(ts.T(), u.Role, "testing")
assert.Equal(ts.T(), u.UserMetaData["name"], "David")
@@ -331,7 +335,7 @@ func (ts *AdminTestSuite) TestAdminUserUpdateAsSystemUser() {
// TestAdminUserDelete tests API /admin/user route (DELETE)
func (ts *AdminTestSuite) TestAdminUserDelete() {
u, err := models.NewUser("", "test-delete@example.com", "test", ts.Config.JWT.Aud, nil)
u, err := models.NewUser(ts.instanceID, "test-delete@example.com", "test", ts.Config.JWT.Aud, nil)
require.NoError(ts.T(), err, "Error making new user")
require.NoError(ts.T(), ts.API.db.CreateUser(u), "Error creating user")
@@ -363,18 +367,14 @@ func (ts *AdminTestSuite) TestAdminUserCreateWithManagementToken() {
ts.API.handler.ServeHTTP(w, req)
require.Equal(ts.T(), http.StatusOK, w.Code)
_, err := ts.API.db.FindUserByEmailAndAudience("", "test2@example.com", ts.Config.JWT.Aud)
_, err := ts.API.db.FindUserByEmailAndAudience(ts.instanceID, "test2@example.com", ts.Config.JWT.Aud)
require.Error(ts.T(), err)
u, err := ts.API.db.FindUserByEmailAndAudience("", "test2@example.com", "op-test-aud")
u, err := ts.API.db.FindUserByEmailAndAudience(ts.instanceID, "test2@example.com", "op-test-aud")
require.NoError(ts.T(), err)
data := make(map[string]interface{})
require.NoError(ts.T(), json.NewDecoder(w.Body).Decode(&data))
assert.Equal(ts.T(), data["email"], u.Email)
}
func TestAdmin(t *testing.T) {
suite.Run(t, new(AdminTestSuite))
}
View
@@ -149,19 +149,20 @@ func NewAPIFromConfigFile(filename string, version string) (*API, *conf.Configur
if err != nil {
return nil, nil, err
}
config, err := conf.LoadConfig(filename)
if err != nil {
return nil, nil, err
}
db, err := dial.Dial(globalConfig)
ctx, err := WithInstanceConfig(context.Background(), globalConfig.SMTP, config, "")
if err != nil {
return nil, nil, err
logrus.Fatalf("Error loading instance config: %+v", err)
}
ctx, err := WithInstanceConfig(context.Background(), globalConfig.SMTP, config, "")
db, err := dial.Dial(globalConfig)
if err != nil {
logrus.Fatalf("Error loading instance config: %+v", err)
return nil, nil, err
}
return NewAPIWithVersion(ctx, globalConfig, db, version), config, nil
View
@@ -0,0 +1,77 @@
package api
import (
"context"
"github.com/netlify/gotrue/conf"
"github.com/netlify/gotrue/models"
"github.com/netlify/gotrue/storage"
"github.com/netlify/gotrue/storage/test"
"github.com/pborman/uuid"
)
const (
apiTestVersion = "1"
apiTestConfig = "../hack/test.env"
)
// setupAPIForTest creates a new API to run tests with.
// Using this function allows us to keep track of the database connection
// and cleaning up data between tests.
func setupAPIForTest() (*API, *conf.Configuration, error) {
return setupAPIForTestWithCallback(nil)
}
func setupAPIForMultiinstanceTest() (*API, *conf.Configuration, error) {
cb := func(gc *conf.GlobalConfiguration, c *conf.Configuration, conn storage.Connection) (string, error) {
gc.MultiInstanceMode = true
return "", nil
}
return setupAPIForTestWithCallback(cb)
}
func setupAPIForTestForInstance() (*API, *conf.Configuration, string, error) {
instanceID := uuid.NewRandom().String()
cb := func(gc *conf.GlobalConfiguration, c *conf.Configuration, conn storage.Connection) (string, error) {
err := conn.CreateInstance(&models.Instance{
ID: instanceID,
UUID: testUUID,
BaseConfig: c,
})
return instanceID, err
}
api, conf, err := setupAPIForTestWithCallback(cb)
if err != nil {
return nil, nil, "", err
}
return api, conf, instanceID, nil
}
func setupAPIForTestWithCallback(cb func(*conf.GlobalConfiguration, *conf.Configuration, storage.Connection) (string, error)) (*API, *conf.Configuration, error) {
globalConfig, conn, err := test.SetupDBConnection()
if err != nil {
return nil, nil, err
}
config, err := conf.LoadConfig(apiTestConfig)
if err != nil {
return nil, nil, err
}
instanceID := ""
if cb != nil {
instanceID, err = cb(globalConfig, config, conn)
if err != nil {
return nil, nil, err
}
}
ctx, err := WithInstanceConfig(context.Background(), globalConfig.SMTP, config, instanceID)
if err != nil {
return nil, nil, err
}
return NewAPIWithVersion(ctx, globalConfig, conn, apiTestVersion), config, nil
}
Oops, something went wrong.

0 comments on commit 5531625

Please sign in to comment.