@@ -23,15 +23,18 @@ package main
2323
2424import (
2525 "database/sql"
26+ "encoding/base64"
2627 "encoding/json"
2728 _ "github.com/go-sql-driver/mysql"
2829 "github.com/gorilla/handlers"
2930 "github.com/gorilla/mux"
3031 "github.com/spf13/viper"
32+ "golang.org/x/crypto/bcrypt"
3133 "log"
3234 "net/http"
3335 "os"
3436 "strconv"
37+ "strings"
3538)
3639
3740type App struct {
@@ -40,7 +43,7 @@ type App struct {
4043 DB * sql.DB
4144}
4245
43- // curl 127.0.0.1:8000/api/products/list
46+ // curl --user user1:pass1 127.0.0.1:8000/api/products/list
4447func (a * App ) getProducts (w http.ResponseWriter , r * http.Request ) {
4548 rows , err := a .DB .Query ("SELECT * FROM products" )
4649 if err != nil {
@@ -63,7 +66,7 @@ func (a *App) getProducts(w http.ResponseWriter, r *http.Request) {
6366}
6467
6568// curl --header "Content-Type: application/json" --request POST --data '{"name": "ABC", "manufacturer": "ACME"}' \
66- // 127.0.0.1:8000/api/products/new
69+ // --user user1:pass1 127.0.0.1:8000/api/products/new
6770func (a * App ) createProduct (w http.ResponseWriter , r * http.Request ) {
6871 var p Product
6972 decoder := json .NewDecoder (r .Body )
@@ -82,7 +85,7 @@ func (a *App) createProduct(w http.ResponseWriter, r *http.Request) {
8285 respondWithMessage (w , http .StatusCreated , "New row added." )
8386}
8487
85- // curl 127.0.0.1:8000/api/products/10
88+ // curl --user user1:pass1 127.0.0.1:8000/api/products/10
8689func (a * App ) getProduct (w http.ResponseWriter , r * http.Request ) {
8790 vars := mux .Vars (r )
8891 id , err := strconv .Atoi (vars ["id" ])
@@ -101,7 +104,7 @@ func (a *App) getProduct(w http.ResponseWriter, r *http.Request) {
101104 respondWithJSON (w , http .StatusOK , p )
102105}
103106
104- // curl --request PUT --data '{"name": "ABC", "manufacturer": "ACME"}' 127.0.0.1:8000/api/products/11
107+ // curl --request PUT --data '{"name": "ABC", "manufacturer": "ACME"}' --user user1:pass1 127.0.0.1:8000/api/products/11
105108func (a * App ) updateProduct (w http.ResponseWriter , r * http.Request ) {
106109 vars := mux .Vars (r )
107110 id , err := strconv .Atoi (vars ["id" ])
@@ -128,7 +131,7 @@ func (a *App) updateProduct(w http.ResponseWriter, r *http.Request) {
128131 respondWithJSON (w , http .StatusOK , p )
129132}
130133
131- // curl --request DELETE 127.0.0.1:8000/api/products/10
134+ // curl --request DELETE --user user1:pass1 127.0.0.1:8000/api/products/10
132135func (a * App ) deleteProduct (w http.ResponseWriter , r * http.Request ) {
133136 vars := mux .Vars (r )
134137 id , err := strconv .Atoi (vars ["id" ])
@@ -146,12 +149,48 @@ func (a *App) deleteProduct(w http.ResponseWriter, r *http.Request) {
146149 respondWithMessage (w , http .StatusOK , "Deleted." )
147150}
148151
152+ func (a * App ) authHandler (f http.HandlerFunc ) http.HandlerFunc {
153+ return func (w http.ResponseWriter , r * http.Request ) {
154+ s := strings .SplitN (r .Header .Get ("Authorization" ), " " , 2 )
155+ if len (s ) != 2 {
156+ respondWithError (w , http .StatusUnauthorized , "Invalid/Missing Credentials." )
157+ return
158+ }
159+
160+ b , err := base64 .StdEncoding .DecodeString (s [1 ])
161+ if err != nil {
162+ respondWithError (w , http .StatusUnauthorized , "Invalid/Missing Credentials." )
163+ return
164+ }
165+
166+ pair := strings .SplitN (string (b ), ":" , 2 )
167+ if len (pair ) != 2 {
168+ respondWithError (w , http .StatusUnauthorized , "Invalid/Missing Credentials." )
169+ return
170+ }
171+
172+ user := User {Username : pair [0 ]}
173+ row := a .DB .QueryRow ("SELECT id, saltedpassword, salt FROM users WHERE username=?" , user .Username )
174+ if err := row .Scan (& user .Id , & user .Saltedpassword , & user .Salt ); err != nil {
175+ respondWithError (w , http .StatusUnauthorized , "Invalid/Missing Credentials." )
176+ return
177+ }
178+
179+ if err := bcrypt .CompareHashAndPassword ([]byte (user .Saltedpassword ), []byte (pair [1 ]+ user .Salt )); err != nil {
180+ respondWithError (w , http .StatusUnauthorized , "Invalid/Missing Credentials." )
181+ return
182+ }
183+
184+ f (w , r )
185+ }
186+ }
187+
149188func (a * App ) InitializeRoutes () {
150- a .Router .HandleFunc ("/api/products/list" , a .getProducts ).Methods ("GET" )
151- a .Router .HandleFunc ("/api/products/new" , a .createProduct ).Methods ("POST" )
152- a .Router .HandleFunc ("/api/products/{id:[0-9]+}" , a .getProduct ).Methods ("GET" )
153- a .Router .HandleFunc ("/api/products/{id:[0-9]+}" , a .updateProduct ).Methods ("PUT" )
154- a .Router .HandleFunc ("/api/products/{id:[0-9]+}" , a .deleteProduct ).Methods ("DELETE" )
189+ a .Router .HandleFunc ("/api/products/list" , a .authHandler ( a . getProducts ) ).Methods ("GET" )
190+ a .Router .HandleFunc ("/api/products/new" , a .authHandler ( a . createProduct ) ).Methods ("POST" )
191+ a .Router .HandleFunc ("/api/products/{id:[0-9]+}" , a .authHandler ( a . getProduct ) ).Methods ("GET" )
192+ a .Router .HandleFunc ("/api/products/{id:[0-9]+}" , a .authHandler ( a . updateProduct ) ).Methods ("PUT" )
193+ a .Router .HandleFunc ("/api/products/{id:[0-9]+}" , a .authHandler ( a . deleteProduct ) ).Methods ("DELETE" )
155194}
156195
157196func (a * App ) Initialize (username , password , server , port , dbName string ) {
0 commit comments