diff --git a/api/database/migrations/0001_init.down.sql b/api/database/migrations/0001_init.down.sql new file mode 100644 index 00000000..c99ddcdc --- /dev/null +++ b/api/database/migrations/0001_init.down.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS users; diff --git a/api/database/migrations/0001_init.up.sql b/api/database/migrations/0001_init.up.sql new file mode 100644 index 00000000..6f67a145 --- /dev/null +++ b/api/database/migrations/0001_init.up.sql @@ -0,0 +1,9 @@ +CREATE TABLE IF NOT EXISTS users ( + user_id int NOT NULL AUTO_INCREMENT, + username varchar(255) NOT NULL, + password varchar(255) NOT NULL, + root_path varchar(512) NOT NULL, + admin boolean, + + PRIMARY KEY (user_id) +); diff --git a/api/database/mysql.go b/api/database/mysql.go index a9466177..6261f129 100644 --- a/api/database/mysql.go +++ b/api/database/mysql.go @@ -3,22 +3,34 @@ package database import ( "database/sql" "log" + "net/url" "os" // Load mysql driver - // _ "github.com/go-sql-driver/mysql" + _ "github.com/go-sql-driver/mysql" - // Load postgres driver - _ "github.com/lib/pq" + "github.com/golang-migrate/migrate" + "github.com/golang-migrate/migrate/database/mysql" + // Migrate from file + _ "github.com/golang-migrate/migrate/source/file" ) // SetupDatabase connects to the database using environment variables func SetupDatabase() *sql.DB { - address := os.Getenv("POSTGRES_URL") + address, err := url.Parse(os.Getenv("MYSQL_URL")) + if err != nil { + log.Fatalf("Could not parse mysql url: %s\n", err) + } + + queryValues := address.Query() + queryValues.Add("multiStatements", "true") + + address.RawQuery = queryValues.Encode() + log.Printf("Connecting to database: %s", address) - db, err := sql.Open("postgres", address) + db, err := sql.Open("mysql", address.String()) if err != nil { log.Fatalf("Could not connect to database: %s\n", err.Error()) } @@ -29,3 +41,31 @@ func SetupDatabase() *sql.DB { return db } + +func MigrateDatabase(db *sql.DB) error { + driver, err := mysql.WithInstance(db, &mysql.Config{}) + if err != nil { + return err + } + + m, err := migrate.NewWithDatabaseInstance( + "file://database/migrations", + "mysql", + driver, + ) + if err != nil { + return err + } + + if err := m.Up(); err != nil { + if err.Error() == "no change" { + log.Println("Database is up to date") + } else { + return err + } + } else { + log.Println("Database migrated") + } + + return nil +} diff --git a/api/example.env b/api/example.env index 77a7129a..97820231 100644 --- a/api/example.env +++ b/api/example.env @@ -1,5 +1,5 @@ # Copy this file to .env -POSTGRES_URL=postgres://username:password@localhost/database?sslmode=disable +MYSQL_URL=user:password@/dbname API_PORT=4001 \ No newline at end of file diff --git a/api/go.mod b/api/go.mod index 737e031b..3284960f 100644 --- a/api/go.mod +++ b/api/go.mod @@ -5,6 +5,7 @@ go 1.13 require ( github.com/99designs/gqlgen v0.10.2 github.com/go-sql-driver/mysql v1.5.0 + github.com/golang-migrate/migrate v3.5.4+incompatible github.com/joho/godotenv v1.3.0 github.com/lib/pq v1.3.0 github.com/vektah/gqlparser v1.2.0 diff --git a/api/go.sum b/api/go.sum index 37ad3c66..a9fc3eb2 100644 --- a/api/go.sum +++ b/api/go.sum @@ -9,6 +9,8 @@ github.com/go-chi/chi v3.3.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxm github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/golang-migrate/migrate v3.5.4+incompatible h1:R7OzwvCJTCgwapPCiX6DyBiu2czIUMDCB118gFTKTUA= +github.com/golang-migrate/migrate v3.5.4+incompatible/go.mod h1:IsVUlFN5puWOmXrqjgGUfIRIbU7mr8oNBE2tyERd9Wk= github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/mux v1.6.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/websocket v1.2.0 h1:VJtLvh6VQym50czpZzx07z/kw9EgAxI3x1ZB8taTMQQ= diff --git a/api/graphql/resolver.go b/api/graphql/resolver.go index a40046cb..eef1db4c 100644 --- a/api/graphql/resolver.go +++ b/api/graphql/resolver.go @@ -2,9 +2,12 @@ package api import ( "context" + "database/sql" ) // THIS CODE IS A STARTING POINT ONLY. IT WILL NOT BE UPDATED WITH SCHEMA CHANGES. -type Resolver struct{} +type Resolver struct { + Database *sql.DB +} func (r *Resolver) Mutation() MutationResolver { return &mutationResolver{r} diff --git a/api/server/server.go b/api/server/server.go index f8f7a8cb..b5fe12b3 100644 --- a/api/server/server.go +++ b/api/server/server.go @@ -26,10 +26,18 @@ func main() { port = defaultPort } - database.SetupDatabase() + db := database.SetupDatabase() + defer db.Close() + + // Migrate database + if err := database.MigrateDatabase(db); err != nil { + log.Fatalf("Could not migrate database: %s\n", err) + } + + graphqlResolver := photoview_graphql.Resolver{Database: db} http.Handle("/", handler.Playground("GraphQL playground", "/query")) - http.Handle("/query", handler.GraphQL(photoview_graphql.NewExecutableSchema(photoview_graphql.Config{Resolvers: &photoview_graphql.Resolver{}}))) + http.Handle("/query", handler.GraphQL(photoview_graphql.NewExecutableSchema(photoview_graphql.Config{Resolvers: &graphqlResolver}))) log.Printf("connect to http://localhost:%s/ for GraphQL playground", port) log.Fatal(http.ListenAndServe(":"+port, nil))