Interim commit; started work on routes

This commit is contained in:
Daniel J. Summers 2018-01-18 11:29:01 -06:00
parent 0807aa300a
commit 8c801ea49f
4 changed files with 109 additions and 8 deletions

3
.gitignore vendored
View File

@ -256,4 +256,5 @@ paket-files/
src/api/public/index.html src/api/public/index.html
src/api/public/static src/api/public/static
src/api/appsettings.json src/api/appsettings.json
build/ build/
src/*.exe

View File

@ -7,6 +7,8 @@ import (
"log" "log"
"time" "time"
// Register the PostgreSQL driver.
_ "github.com/lib/pq"
"github.com/lucsky/cuid" "github.com/lucsky/cuid"
) )
@ -21,6 +23,15 @@ const (
AND "lastStatus" <> 'Answered'` AND "lastStatus" <> 'Answered'`
) )
// Settings holds the PostgreSQL configuration for myPrayerJournal.
type Settings struct {
Host string `json:"host"`
Port int `json:"port"`
User string `json:"user"`
Password string `json:"password"`
DbName string `json:"dbname"`
}
/* Data Access */ /* Data Access */
// Retrieve a basic request // Retrieve a basic request
@ -74,7 +85,7 @@ func AddHistory(db *sql.DB, userID, reqID, status, text string) int {
} }
_, err := db.Exec(` _, err := db.Exec(`
INSERT INTO mpj.history INSERT INTO mpj.history
("requestId", "asOf", "status", "text") ("requestId", "asOf", "status", "text")
VALUES VALUES
($1, $2, $3, NULLIF($4, ''))`, ($1, $2, $3, NULLIF($4, ''))`,
reqID, jsNow(), status, text) reqID, jsNow(), status, text)
@ -123,9 +134,9 @@ func AddNote(db *sql.DB, userID, reqID, note string) int {
return 404 return 404
} }
_, err := db.Exec(` _, err := db.Exec(`
INSERT INTO mpj.note INSERT INTO mpj.note
("requestId", "asOf", "notes") ("requestId", "asOf", "notes")
VALUES VALUES
($1, $2, $3)`, ($1, $2, $3)`,
reqID, jsNow(), note) reqID, jsNow(), note)
if err != nil { if err != nil {
@ -166,6 +177,24 @@ func ByID(db *sql.DB, userID, reqID string) (*JournalRequest, bool) {
return &req, true return &req, true
} }
// Connect establishes a connection to the database.
func Connect(s *Settings) (*sql.DB, bool) {
connStr := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable",
s.Host, s.Port, s.User, s.Password, s.DbName)
db, err := sql.Open("postgres", connStr)
if err != nil {
log.Print(err)
return nil, false
}
err = db.Ping()
if err != nil {
log.Print(err)
return nil, false
}
log.Printf("Connected to postgres://%s@%s:%d/%s\n", s.User, s.Host, s.Port, s.DbName)
return db, true
}
// FullByID retrieves a journal request, including its full history and notes. // FullByID retrieves a journal request, including its full history and notes.
func FullByID(db *sql.DB, userID, reqID string) (*JournalRequest, bool) { func FullByID(db *sql.DB, userID, reqID string) (*JournalRequest, bool) {
req, ok := ByID(db, userID, reqID) req, ok := ByID(db, userID, reqID)

64
src/api/routes/routes.go Normal file
View File

@ -0,0 +1,64 @@
// Package routes contains endpoint handlers for the myPrayerJournal API.
package routes
import (
"database/sql"
"encoding/json"
"log"
"net/http"
"github.com/danieljsummers/myPrayerJournal/src/api/data"
"github.com/julienschmidt/httprouter"
)
/* Support */
// Set the content type, the HTTP error code, and return the error message.
func sendError(w http.ResponseWriter, r *http.Request, err error) {
m := map[string]string{"error": err.Error()}
j, jErr := json.Marshal(m)
if jErr != nil {
log.Print("Error creating error JSON: " + jErr.Error())
}
w.WriteHeader(500)
w.Header().Set("Content-Type", "application/json")
w.Write(j)
}
// Set the content type and return the JSON to the user.
func sendJSON(w http.ResponseWriter, r *http.Request, result interface{}) {
payload, err := json.Marshal(result)
if err != nil {
sendError(w, r, err)
return
}
w.Header().Set("Content-Type", "application/json")
w.Write([]byte("{ data: "))
w.Write(payload)
w.Write([]byte(" }"))
}
/* Handlers */
func journal(w http.ResponseWriter, r *http.Request, _ httprouter.Params, db *sql.DB) {
reqs := data.Journal(db, "TODO: get user ID")
if reqs == nil {
reqs = []data.JournalRequest{}
}
sendJSON(w, r, reqs)
}
/* Wrappers */
func withDB(fn func(w http.ResponseWriter, r *http.Request, p httprouter.Params, db *sql.DB), db *sql.DB) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
fn(w, r, p, db)
}
}
// Routes returns a configured router to handle all incoming requests.
func Routes(db *sql.DB) *httprouter.Router {
router := httprouter.New()
router.GET("/journal", withDB(journal, db))
return router
}

View File

@ -2,10 +2,17 @@
package main package main
import ( import (
"fmt" "log"
"time"
"github.com/danieljsummers/myPrayerJournal/src/api/data"
"github.com/danieljsummers/myPrayerJournal/src/api/routes"
) )
func main() { func main() {
fmt.Print(time.Now().UnixNano() / int64(1000000)) db, ok := data.Connect(&data.Settings{})
if !ok {
log.Fatal("Unable to connect to database; exiting")
}
router := routes.Routes(db)
_ = router // TODO: remove
} }