fullstack web app-golang #3

f

So we already finished the authentication and all thats left to do is to add some posts. Remember what we’re trying to do is any authenticated users can post anything. And their posts are not monitored even by us.

So there will be no relationship between our documents. Lets actually start coding.

In posts.go which is inside models folder. we already wrote the schema

package model

import "go.mongodb.org/mongo-driver/bson/primitive"

//Post is the structure of the Post Data
type Post struct{
	ID primitive.ObjectID `bson:"_id" json:"_id,omitempty"`
	Title string `json:"title"`
	Body string `json:"body"`
}

Now lets write some helping functions. These helper functions will go inside db/postHandler.go

First lets write a function to add the Posts.

func AddNewPostDB(obj model.Post) {
	post := model.Post{}

	post.Body = obj.Body
	post.Title = obj.Title
	post.ID = primitive.NewObjectID()

	insertResult, err := postsCollection.InsertOne(context.TODO(), post)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println("Inserted a single document: ", insertResult.InsertedID)
}

Thats easy. But we also need to get all the posts. Let’s write a functions for it too.


func GetAllPostsDB() []*(model.Post){

	var posts []*(model.Post)

	// Passing bson.D{{}} as the filter matches all documents in the collection
	cur, err := postsCollection.Find(context.TODO(), bson.D{{}})
	if err != nil {
		log.Fatal(err)
	}

		// Finding multiple documents returns a cursor
	// Iterating through the cursor allows us to decode documents one at a time
	for cur.Next(context.TODO()) {

		// create a value into which the single document can be decoded
		var elem model.Post
		err := cur.Decode(&elem)
		if err != nil {
			log.Fatal(err)
		}

		posts = append(posts, &elem)
	}

	if err := cur.Err(); err != nil {
		log.Fatal(err)
	}

	// Close the cursor once finished
	cur.Close(context.TODO())

	return posts
}
  • create the variable var posts []*(model.Post)
  • use postsCollection.Find(), this returns a cursor.
  • Iterate the cursor
  • append the value to the variable posts
  • return posts

Now lets actually build the route handlers.

In the main.go


	// Route handles & endpoints
	r.HandleFunc("/", helpers.GetAllPosts).Methods("GET")
	r.HandleFunc("/register", helpers.SaveUser).Methods("POST")
	r.HandleFunc("/login", helpers.FindUser).Methods("POST")
	r.HandleFunc("/addpost", helpers.AddPost).Methods("POST")

Now go to routes.go under helpers.

func GetAllPosts(w http.ResponseWriter, r *http.Request) {
	posts := db.GetAllPostsDB()
	json.NewEncoder(w).Encode(posts)
}

Ah thats easy. Now to add posts


func AddPost(w http.ResponseWriter, r *http.Request) {
	decoder := json.NewDecoder(r.Body)

	var t model.Post
	err := decoder.Decode(&t)
	if err != nil {
		panic(err)
	}

	db.AddNewPostDB(t)

	json.NewEncoder(w).Encode("Post added successfully")
}

We almost finished now. But one important thing we missed is using the authentication.

Coz, by our current logic anyone can post. But we only want authenticated users to post.

So how to do that? MIDDLEWARES

MIDDLEWARES

consider the below code

func a{ //some code }

func callmefirst{ //some code}

Suppose we want to call a() but before that if we want to call callmefirst(), what should we do?

func a{ //some code }

func callmefirst{ 
//some code
a()
}

callmefirst()

So this what we’re gonna do here.

change the main.go

// Init router
	r := mux.NewRouter()
	secretHandler := http.HandlerFunc(helpers.AddPost)

	// Route handles & endpoints
	r.HandleFunc("/", helpers.GetAllPosts).Methods("GET")
	r.HandleFunc("/register", helpers.SaveUser).Methods("POST")
	r.HandleFunc("/login", helpers.FindUser).Methods("POST")
	r.Handle("/addpost", helpers.IsAuthorized(secretHandler)).Methods("POST")

Now in the routes.go


func IsAuthorized(endpoint http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

		fmt.Println(r.Header)
		fmt.Println()
		if r.Header["Token"] != nil {

			token, err := jwt.Parse(r.Header["Token"][0], func(token *jwt.Token) (interface{}, error) {
				if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
					return nil, fmt.Errorf("There was an error")
				}
				return mySigningKey, nil
			})

			if err != nil {
				json.NewEncoder(w).Encode("error")
			}

			if token.Valid {
				endpoint.ServeHTTP(w, r)
			}
		} else {
			json.NewEncoder(w).Encode("not authorized")
		}
	})
}

We already learnt about this in my previous article.

Now let’s test it.

If I send it without the jwt,

But with the JWT,

It worked.

And thats it. Thats almost it. We finished the backend.

Happy coding 🙂

About the author

vigneshwar

Add comment

Leave a Reply

By vigneshwar

Most common tags

%d bloggers like this: