This commit is contained in:
Ruidy Nemausat 2020-03-16 19:00:03 +01:00
parent db947b17f3
commit 85af1381ef
20 changed files with 190 additions and 163 deletions

View file

@ -1,6 +1,6 @@
# Go-Wiki
Wiki web application model built using `Go`
Wiki web application models built using `Go`
<!-- img.shields.io -->

View file

@ -1,88 +0,0 @@
package controller
import (
"fmt"
"net/http"
"regexp"
"github.com/rjNemo/go-wiki/model"
"github.com/rjNemo/go-wiki/service"
"github.com/rjNemo/go-wiki/views"
)
var validPath = regexp.MustCompile("^/(edit|save|view)/([a-zA-Z0-9]+)$")
// Router dispatch the request to the corresponding route handlers.
func Router() {
// http.HandleFunc("/", loveHandler)
http.HandleFunc("/view/", makeHandler(viewHandler))
http.HandleFunc("/edit/", makeHandler(editHandler))
http.HandleFunc("/save/", makeHandler(saveHandler))
http.HandleFunc("/contact/", contactHandler)
http.HandleFunc("/contact/post/", postContactHandler)
http.HandleFunc("/", homeHandler)
}
func homeHandler(w http.ResponseWriter, r *http.Request) {
views.Template(w, "home", nil)
}
func viewHandler(w http.ResponseWriter, r *http.Request, title string) {
p, err := model.LoadPage(title)
if err != nil {
http.Redirect(w, r, "/edit/"+title, http.StatusFound)
return
}
views.Template(w, "view", p)
}
func editHandler(w http.ResponseWriter, r *http.Request, title string) {
p, err := model.LoadPage(title)
if err != nil {
p = model.NewPage(title, nil)
}
views.Template(w, "edit", p)
}
func saveHandler(w http.ResponseWriter, r *http.Request, title string) {
body := r.FormValue("body")
p := model.NewPage(title, []byte(body))
err := p.Save()
checkError(err, w)
http.Redirect(w, r, "/view/"+title, http.StatusFound)
}
func contactHandler(w http.ResponseWriter, r *http.Request) {
views.Template(w, "contact", nil)
}
func postContactHandler(w http.ResponseWriter, r *http.Request) {
err := r.ParseForm()
checkError(err, w) // bad error handling
mail := parseContactForm(r)
mail.Send()
fmt.Println(mail)
views.Template(w, "contact_sent", nil)
}
func parseContactForm(r *http.Request) service.Mail {
return service.NewMail(r.PostFormValue("email"), r.PostFormValue("message"))
}
func checkError(err error, w http.ResponseWriter) {
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
func makeHandler(fn func(http.ResponseWriter, *http.Request, string)) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
m := validPath.FindStringSubmatch(r.URL.Path)
if m == nil {
http.NotFound(w, r)
return
}
fn(w, r, m[2])
}
}

View file

@ -1,11 +1,11 @@
package controller
package controllers
import (
"io"
"net/http"
"testing"
"github.com/rjNemo/go-wiki/service"
"github.com/rjNemo/go-wiki/services"
)
func TestParseContactForm(t *testing.T) {
@ -15,7 +15,7 @@ func TestParseContactForm(t *testing.T) {
t.Errorf("%s", err)
}
ans := parseContactForm(r)
if ans != service.NewMail("", "") {
if ans != services.NewMail("", "") {
t.Errorf("parseContactForm(r) = %v", ans)
}
}

41
controllers/home.go Normal file
View file

@ -0,0 +1,41 @@
package controllers
import (
"log"
"net/http"
"github.com/rjNemo/go-wiki/services"
"github.com/rjNemo/go-wiki/views"
)
// type HomeHandler struct {
// }
func homeHandler(w http.ResponseWriter, r *http.Request) {
views.Template(w, "home", nil)
}
func contactHandler(w http.ResponseWriter, r *http.Request) {
views.Template(w, "contact", nil)
}
func postContactHandler(w http.ResponseWriter, r *http.Request) {
err := r.ParseForm()
checkError(err, w) // bad error handling
mail := parseContactForm(r)
// mail.Send()
log.Println(mail)
views.Template(w, "contact_sent", nil)
}
func parseContactForm(r *http.Request) services.Mail {
log.Println(r.PostForm)
return services.NewMail(r.PostFormValue("email"), r.PostFormValue("message"))
}
func checkError(err error, w http.ResponseWriter) {
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}

37
controllers/page.go Normal file
View file

@ -0,0 +1,37 @@
package controllers
import (
"net/http"
"github.com/rjNemo/go-wiki/models"
"github.com/rjNemo/go-wiki/views"
)
// type PageHandler struct {
// Pages data.PageStore
// }
func viewHandler(w http.ResponseWriter, r *http.Request, title string) {
p, err := models.LoadPage(title)
if err != nil {
http.Redirect(w, r, "/edit/"+title, http.StatusFound)
return
}
views.Template(w, "view", p)
}
func editHandler(w http.ResponseWriter, r *http.Request, title string) {
p, err := models.LoadPage(title)
if err != nil {
p = models.NewPage(title, nil)
}
views.Template(w, "edit", p)
}
func saveHandler(w http.ResponseWriter, r *http.Request, title string) {
body := r.FormValue("body")
p := models.NewPage(title, []byte(body))
err := p.Save()
checkError(err, w)
http.Redirect(w, r, "/view/"+title, http.StatusFound)
}

30
controllers/router.go Normal file
View file

@ -0,0 +1,30 @@
package controllers
import (
"net/http"
"regexp"
)
// Router dispatch the request to the corresponding route handlers.
func Router() {
// http.HandleFunc("/", loveHandler)
http.HandleFunc("/view/", makeHandler(viewHandler))
http.HandleFunc("/edit/", makeHandler(editHandler))
http.HandleFunc("/save/", makeHandler(saveHandler))
http.HandleFunc("/contact/", contactHandler)
http.HandleFunc("/contact/post/", postContactHandler)
http.HandleFunc("/", homeHandler)
}
func makeHandler(fn func(http.ResponseWriter, *http.Request, string)) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
m := validPath.FindStringSubmatch(r.URL.Path)
if m == nil {
http.NotFound(w, r)
return
}
fn(w, r, m[2])
}
}
var validPath = regexp.MustCompile("^/(edit|save|view)/([a-zA-Z0-9]+)$")

View file

@ -5,3 +5,4 @@ If it already exist you will reach this page.
If it is not yet defined you will have the possibility to create it.
Have fun

View file

@ -5,7 +5,7 @@ import (
"log"
_ "github.com/lib/pq" // postgresql database package
"github.com/rjNemo/go-wiki/model"
"github.com/rjNemo/go-wiki/models"
"github.com/rjNemo/go-wiki/settings"
)
@ -24,41 +24,28 @@ func UsePSQL() {
log.Fatal(err)
}
log.Println("Database successfully connected!")
log.Println("Connection to database successfully established!")
createUserTable(db)
store := NewUserStore(db)
// u := model.TestUser()
store.CreateTable()
// u := models.TestUser()
// store.Add(u)
// log.Print(u)
u1 := model.NewUser(3, 20, "paul", "newman", "PdsNz@FDKML.COM")
store.Update(16, u1)
log.Println(store.Get(1))
// u1 := models.NewUser(3, 20, "paul", "newman", "PdsNz@FDKML.COM")
// store.Update(16, u1)
// log.Println(store.Get(1))
// store.Delete(8)
log.Println(store.GetAll())
log.Println(store.Find("first_name", "John"))
}
func sqlExec(db *sql.DB, s string) {
if _, err := db.Exec(s); err != nil {
log.Fatal(err)
return
}
log.Printf("Command successfully executed!: %s", s)
}
func createUserTable(db *sql.DB) {
sqlExec(db, QueryCreateTable)
log.Print("Table successfully created!")
// log.Println(store.GetAll())
// log.Println(store.Find("first_name", "John"))
}
// Store interface defines the methods any store must satisfy
type Store interface {
// CreateTable()
CreateTable()
Add(i interface{})
Get(id int) (model.User, error)
GetAll(id int) ([]model.User, error)
Get(id int) (models.User, error)
GetAll(id int) ([]models.User, error)
Delete(id int)
Find(ex string)
// Find(ex string)
Update(id int, i interface{})
}

View file

@ -4,7 +4,7 @@ import (
"database/sql"
"log"
"github.com/rjNemo/go-wiki/model"
"github.com/rjNemo/go-wiki/models"
)
// UserStore is used to perform user-related CRUD operations on the DB
@ -17,8 +17,16 @@ func NewUserStore(db *sql.DB) UserStore {
return UserStore{db: db}
}
// CreateTable creates the user table in the database if it exits not yet.
func (us UserStore) CreateTable() {
if _, err := us.db.Exec(QueryCreateTable); err != nil {
log.Fatal(err)
}
// log.Print("Table successfully created!")
}
// GetAll retrieves all the users from the database.
func (us UserStore) GetAll() ([]model.User, error) {
func (us UserStore) GetAll() ([]models.User, error) {
var id, age int
var firstName, lastName, email string
@ -27,42 +35,42 @@ func (us UserStore) GetAll() ([]model.User, error) {
return nil, err
}
var users []model.User
var users []models.User
for rows.Next() {
err := rows.Scan(&id, &age, &firstName, &lastName, &email)
if err != nil {
log.Fatal(err) // too severe
}
u := model.NewUser(id, age, firstName, lastName, email)
u := models.NewUser(id, age, firstName, lastName, email)
users = append(users, u)
}
return users, nil
}
// Find retrieves a user from the database using an expression
func (us UserStore) Find(k interface{}, v interface{}) ([]model.User, error) {
var id, age int
var firstName, lastName, email string
// func (us UserStore) Find(k interface{}, v interface{}) ([]models.User, error) {
// var id, age int
// var firstName, lastName, email string
rows, err := us.db.Query(QueryFind, k, v)
if err != nil {
return nil, err
}
// rows, err := us.db.Query(QueryFind, k, v)
// if err != nil {
// return nil, err
// }
var users []model.User
for rows.Next() {
err := rows.Scan(&id, &age, &firstName, &lastName, &email)
if err != nil {
log.Fatal(err) // too severe
}
u := model.NewUser(id, age, firstName, lastName, email)
users = append(users, u)
}
return users, nil
}
// var users []models.User
// for rows.Next() {
// err := rows.Scan(&id, &age, &firstName, &lastName, &email)
// if err != nil {
// log.Fatal(err) // too severe
// }
// u := models.NewUser(id, age, firstName, lastName, email)
// users = append(users, u)
// }
// return users, nil
// }
// Get retrieves the user identified by 'id' from database
func (us UserStore) Get(uid int) (model.User, error) {
func (us UserStore) Get(uid int) (models.User, error) {
var id, age int
var firstName, lastName, email string
@ -70,17 +78,17 @@ func (us UserStore) Get(uid int) (model.User, error) {
switch err := row.Scan(&id, &age, &firstName, &lastName, &email); err {
case sql.ErrNoRows:
log.Println("No entry returned")
return model.User{}, err
return models.User{}, err
case nil:
return model.NewUser(id, age, firstName, lastName, email), nil
return models.NewUser(id, age, firstName, lastName, email), nil
default:
log.Fatal(err)
return model.User{}, err
return models.User{}, err
}
}
// Add inserts a user in the database.
func (us UserStore) Add(u model.User) {
func (us UserStore) Add(u models.User) {
id := 0
err := us.db.QueryRow(QueryInsert, u.Age(), u.Email(), u.FirstName(), u.LastName()).Scan(&id)
if err != nil {
@ -90,7 +98,7 @@ func (us UserStore) Add(u model.User) {
}
// Update edits user identified by 'id' in the database
func (us UserStore) Update(id int, u model.User) {
func (us UserStore) Update(id int, u models.User) {
res, err := us.db.Exec(QueryUpdate, id, u.Age(), u.Email(), u.FirstName(), u.LastName())
if err != nil {
log.Fatal(err) // too severe

View file

@ -4,12 +4,14 @@ import (
"log"
"net/http"
"github.com/rjNemo/go-wiki/controllers"
"github.com/rjNemo/go-wiki/data"
"github.com/rjNemo/go-wiki/settings"
)
func main() {
data.UsePSQL()
// startServer(settings.Port, controller.Router)
startServer(settings.Port, controllers.Router)
}
func startServer(p string, r func()) {

View file

@ -1,4 +1,4 @@
package model
package models
import "testing"

View file

@ -1,4 +1,4 @@
package model
package models
import (
"io/ioutil"
@ -42,13 +42,13 @@ func NewPage(title string, body []byte) *Page {
// Save a page to the 'data/' folder in txt format.
func (p *Page) Save() error {
fileName := "data/" + p.title + ".txt"
fileName := "data/files/" + p.title + ".txt"
return ioutil.WriteFile(fileName, p.body, 0600)
}
// LoadPage reads a saved page data and returns a pointer to the Page.
func LoadPage(title string) (*Page, error) {
fileName := "data/" + title + ".txt"
fileName := "data/files/" + title + ".txt"
body, err := ioutil.ReadFile(fileName)
if err != nil {
return nil, err

View file

@ -1,4 +1,4 @@
package model
package models
import "strings"

View file

@ -1,4 +1,4 @@
package service
package services
import (
"fmt"

View file

@ -1,4 +1,4 @@
package service
package services
import (
"github.com/stripe/stripe-go"
@ -8,7 +8,7 @@ import (
// secret API key
var secretKey string = "sk_test_dyp7eLEq2KnxpWE0qIMihTYZ"
// service.PaymentIntent(1000, "ruidy.nemausat@gmail.com")
// services.PaymentIntent(1000, "ruidy.nemausat@gmail.com")
// PaymentIntent creates a payment intent
func PaymentIntent(a int64, m string) (*stripe.PaymentIntent, error) {

View file

@ -1,19 +1,28 @@
package views
import (
"log"
"net/http"
"text/template"
"github.com/rjNemo/go-wiki/model"
"github.com/rjNemo/go-wiki/models"
"github.com/rjNemo/go-wiki/settings"
)
func Template(w http.ResponseWriter, tmpl string, p *model.Page) {
func Template(w http.ResponseWriter, tmpl string, p *models.Page) {
// err := templates.ExecuteTemplate(w, "templates/"+tmpl+".html", p)
t, err := template.ParseFiles(getTmplName("base"), getTmplName(tmpl))
checkError(err, w)
if err != nil {
log.Println(err.Error())
return
}
err = t.Execute(w, p)
checkError(err, w)
if err != nil {
log.Println(err.Error())
return
}
}
func getTmplName(tmpl string) string {