├── proto-gen.sh
├── services
├── auth.service.go
├── user.service.go
├── post.service.go
├── auth.service.impl.go
├── user.service.impl.go
└── post.service.impl.go
├── proto
├── rpc_create_post.proto
├── user_service.proto
├── rpc_update_post.proto
├── rpc_signin_user.proto
├── rpc_signup_user.proto
├── post.proto
├── user.proto
├── auth_service.proto
└── post_service.proto
├── utils
├── helper.go
├── encode.go
├── password.go
├── token.go
└── email.go
├── Makefile
├── .gitignore
├── docker-compose.yml
├── tmp
└── build-errors.log
├── gapi
├── post-server.go
├── rpc_delete_post.go
├── user-server.go
├── rpc_get_me.go
├── auth-server.go
├── rpc_list_posts.go
├── rpc_get_post.go
├── rpc_verify_user.go
├── rpc_create_post.go
├── rpc_update_post.go
├── rpc_signin_user.go
└── rpc_signup_user.go
├── controllers
├── user.controller.go
├── post.controller.go
└── auth.controller.go
├── routes
├── user.routes.go
├── post.routes.go
└── auth.routes.go
├── client
├── geMe_client.go
├── getPost_client.go
├── signin_client.go
├── createPost_client.go
├── updatePost_client.go
├── signup_client.go
├── deletePost_client.go
└── listPosts_client.go
├── .air.toml
├── templates
├── base.html
├── verificationCode.html
├── resetPassword.html
└── styles.html
├── middleware
└── deserialize-user.go
├── config
└── default.go
├── models
├── post.model.go
└── user.model.go
├── example.env
├── go.mod
├── cmd
├── client
│ └── main.go
└── server
│ └── main.go
├── pb
├── user_service_grpc.pb.go
├── user_service.pb.go
├── rpc_create_post.pb.go
├── rpc_update_post.pb.go
├── auth_service_grpc.pb.go
├── auth_service.pb.go
├── rpc_signin_user.pb.go
├── rpc_signup_user.pb.go
├── post.pb.go
├── post_service_grpc.pb.go
├── user.pb.go
└── post_service.pb.go
└── readMe.md
/proto-gen.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | rm -rf pb/*.go
4 | protoc --proto_path=proto --go_out=pb --go_opt=paths=source_relative \
5 | --go-grpc_out=pb --go-grpc_opt=paths=source_relative \
6 | proto/*.proto
--------------------------------------------------------------------------------
/services/auth.service.go:
--------------------------------------------------------------------------------
1 | package services
2 |
3 | import "github.com/wpcodevo/golang-mongodb/models"
4 |
5 | type AuthService interface {
6 | SignUpUser(*models.SignUpInput) (*models.DBResponse, error)
7 | SignInUser(*models.SignInInput) (*models.DBResponse, error)
8 | }
9 |
--------------------------------------------------------------------------------
/proto/rpc_create_post.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package pb;
4 |
5 | option go_package = "github.com/wpcodevo/golang-mongodb/pb";
6 |
7 | message CreatePostRequest {
8 | string Title = 1;
9 | string Content = 2;
10 | string Image = 3;
11 | string User = 4;
12 | }
13 |
--------------------------------------------------------------------------------
/utils/helper.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import "go.mongodb.org/mongo-driver/bson"
4 |
5 | func ToDoc(v interface{}) (doc *bson.D, err error) {
6 | data, err := bson.Marshal(v)
7 | if err != nil {
8 | return
9 | }
10 |
11 | err = bson.Unmarshal(data, &doc)
12 | return
13 | }
14 |
--------------------------------------------------------------------------------
/proto/user_service.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package pb;
4 |
5 | import "user.proto";
6 |
7 | option go_package = "github.com/wpcodevo/golang-mongodb/pb";
8 |
9 | service UserService {
10 | rpc GetMe(GetMeRequest) returns (UserResponse) {}
11 | }
12 |
13 | message GetMeRequest { string Id = 1; }
14 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | .PHONY: dev dev-down go proto
2 |
3 | dev:
4 | docker-compose up -d
5 |
6 | dev-down:
7 | docker-compose down
8 |
9 | go:
10 | air
11 |
12 | proto:
13 | protoc --proto_path=proto --go_out=pb --go_opt=paths=source_relative \
14 | --go-grpc_out=pb --go-grpc_opt=paths=source_relative \
15 | proto/*.proto
--------------------------------------------------------------------------------
/proto/rpc_update_post.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package pb;
4 |
5 | option go_package = "github.com/wpcodevo/golang-mongodb/pb";
6 |
7 | message UpdatePostRequest {
8 | string Id = 1;
9 | optional string Title = 2;
10 | optional string Content = 3;
11 | optional string Image = 4;
12 | optional string User = 5;
13 | }
14 |
--------------------------------------------------------------------------------
/services/user.service.go:
--------------------------------------------------------------------------------
1 | package services
2 |
3 | import "github.com/wpcodevo/golang-mongodb/models"
4 |
5 | type UserService interface {
6 | FindUserById(id string) (*models.DBResponse, error)
7 | FindUserByEmail(email string) (*models.DBResponse, error)
8 | UpdateUserById(id string, data *models.UpdateInput) (*models.DBResponse, error)
9 | }
10 |
--------------------------------------------------------------------------------
/proto/rpc_signin_user.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package pb;
4 |
5 | option go_package = "github.com/wpcodevo/golang-mongodb/pb";
6 |
7 | message SignInUserInput {
8 | string email = 1;
9 | string password = 2;
10 | }
11 |
12 | message SignInUserResponse {
13 | string status = 1;
14 | string access_token = 2;
15 | string refresh_token = 3;
16 | }
--------------------------------------------------------------------------------
/proto/rpc_signup_user.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package pb;
4 |
5 | option go_package = "github.com/wpcodevo/golang-mongodb/pb";
6 |
7 | import "user.proto";
8 |
9 | message SignUpUserInput {
10 | string name = 1;
11 | string email = 2;
12 | string password = 3;
13 | string passwordConfirm = 4;
14 | }
15 |
16 | message SignUpUserResponse { User user = 1; }
17 |
--------------------------------------------------------------------------------
/utils/encode.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import "encoding/base64"
4 |
5 | func Encode(s string) string {
6 | data := base64.StdEncoding.EncodeToString([]byte(s))
7 | return string(data)
8 | }
9 |
10 | func Decode(s string) (string, error) {
11 | data, err := base64.StdEncoding.DecodeString(s)
12 | if err != nil {
13 | return "", err
14 | }
15 |
16 | return string(data), nil
17 | }
18 |
--------------------------------------------------------------------------------
/services/post.service.go:
--------------------------------------------------------------------------------
1 | package services
2 |
3 | import "github.com/wpcodevo/golang-mongodb/models"
4 |
5 | type PostService interface {
6 | CreatePost(*models.CreatePostRequest) (*models.DBPost, error)
7 | UpdatePost(string, *models.UpdatePost) (*models.DBPost, error)
8 | FindPostById(string) (*models.DBPost, error)
9 | FindPosts(page int, limit int) ([]*models.DBPost, error)
10 | DeletePost(string) error
11 | }
12 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Binaries for programs and plugins
2 | *.exe
3 | *.exe~
4 | *.dll
5 | *.so
6 | *.dylib
7 |
8 | # Test binary, built with `go test -c`
9 | *.test
10 |
11 | # Output of the go coverage tool, specifically when used with LiteIDE
12 | *.out
13 |
14 | # Dependency directories (remove the comment below to include it)
15 | # vendor/
16 | .DS_Store
17 | TODO.md
18 | logs.txt
19 | .idea/
20 | secret.md
21 | app.env
22 | /temp
23 | temp/
--------------------------------------------------------------------------------
/proto/post.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package pb;
4 |
5 | option go_package = "github.com/wpcodevo/golang-mongodb/pb";
6 | import "google/protobuf/timestamp.proto";
7 |
8 | message Post {
9 | string Id = 1;
10 | string Title = 2;
11 | string Content = 3;
12 | string Image = 4;
13 | string User = 5;
14 | google.protobuf.Timestamp created_at = 6;
15 | google.protobuf.Timestamp updated_at = 7;
16 | }
17 |
18 | message PostResponse { Post post = 1; }
19 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | mongodb:
4 | image: mongo
5 | container_name: mongodb
6 | restart: always
7 | env_file:
8 | - ./app.env
9 |
10 | ports:
11 | - '6000:27017'
12 | volumes:
13 | - mongodb:/data/db
14 |
15 | redis:
16 | image: redis:alpine
17 | container_name: redis
18 | ports:
19 | - '6379:6379'
20 | volumes:
21 | - redisDB:/data
22 | volumes:
23 | mongodb:
24 | redisDB:
25 |
--------------------------------------------------------------------------------
/tmp/build-errors.log:
--------------------------------------------------------------------------------
1 | exit status 1exit status 0xc000013aexit status 1exit status 1exit status 2exit status 2exit status 2exit status 2exit status 2exit status 2exit status 2exit status 2exit status 2exit status 2exit status 2exit status 2exit status 2exit status 2exit status 2exit status 2exit status 2exit status 1exit status 1exit status 2exit status 1exit status 1exit status 2exit status 1exit status 2exit status 1exit status 2exit status 1exit status 1exit status 2exit status 2exit status 0xc000013aexit status 2
--------------------------------------------------------------------------------
/proto/user.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package pb;
4 |
5 | import "google/protobuf/timestamp.proto";
6 | option go_package = "github.com/wpcodevo/golang-mongodb/pb";
7 |
8 | message User {
9 | string id = 1;
10 | string name = 2;
11 | string email = 3;
12 | string role = 4;
13 | google.protobuf.Timestamp created_at = 5;
14 | google.protobuf.Timestamp updated_at = 6;
15 | }
16 |
17 | message UserResponse { User user = 1; }
18 |
19 | message GenericResponse {
20 | string status = 1;
21 | string message = 2;
22 | }
--------------------------------------------------------------------------------
/proto/auth_service.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package pb;
4 |
5 | import "rpc_signin_user.proto";
6 | import "rpc_signup_user.proto";
7 | import "user.proto";
8 |
9 | option go_package = "github.com/wpcodevo/golang-mongodb/pb";
10 |
11 | service AuthService {
12 | rpc SignUpUser(SignUpUserInput) returns (GenericResponse) {}
13 | rpc SignInUser(SignInUserInput) returns (SignInUserResponse) {}
14 | rpc VerifyEmail(VerifyEmailRequest) returns (GenericResponse) {}
15 | }
16 |
17 | message VerifyEmailRequest { string verificationCode = 1; }
--------------------------------------------------------------------------------
/utils/password.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "fmt"
5 |
6 | "golang.org/x/crypto/bcrypt"
7 | )
8 |
9 | func HashPassword(password string) (string, error) {
10 | hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
11 |
12 | if err != nil {
13 | return "", fmt.Errorf("could not hash password %w", err)
14 | }
15 | return string(hashedPassword), nil
16 | }
17 |
18 | func VerifyPassword(hashedPassword string, candidatePassword string) error {
19 | return bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(candidatePassword))
20 | }
21 |
--------------------------------------------------------------------------------
/gapi/post-server.go:
--------------------------------------------------------------------------------
1 | package gapi
2 |
3 | import (
4 | "github.com/wpcodevo/golang-mongodb/pb"
5 | "github.com/wpcodevo/golang-mongodb/services"
6 | "go.mongodb.org/mongo-driver/mongo"
7 | )
8 |
9 | type PostServer struct {
10 | pb.UnimplementedPostServiceServer
11 | postCollection *mongo.Collection
12 | postService services.PostService
13 | }
14 |
15 | func NewGrpcPostServer(postCollection *mongo.Collection, postService services.PostService) (*PostServer, error) {
16 | postServer := &PostServer{
17 | postCollection: postCollection,
18 | postService: postService,
19 | }
20 |
21 | return postServer, nil
22 | }
23 |
--------------------------------------------------------------------------------
/controllers/user.controller.go:
--------------------------------------------------------------------------------
1 | package controllers
2 |
3 | import (
4 | "net/http"
5 |
6 | "github.com/gin-gonic/gin"
7 | "github.com/wpcodevo/golang-mongodb/models"
8 | "github.com/wpcodevo/golang-mongodb/services"
9 | )
10 |
11 | type UserController struct {
12 | userService services.UserService
13 | }
14 |
15 | func NewUserController(userService services.UserService) UserController {
16 | return UserController{userService}
17 | }
18 |
19 | func (uc *UserController) GetMe(ctx *gin.Context) {
20 | currentUser := ctx.MustGet("currentUser").(*models.DBResponse)
21 |
22 | ctx.JSON(http.StatusOK, gin.H{"status": "success", "data": gin.H{"user": models.FilteredResponse(currentUser)}})
23 | }
24 |
--------------------------------------------------------------------------------
/gapi/rpc_delete_post.go:
--------------------------------------------------------------------------------
1 | package gapi
2 |
3 | import (
4 | "context"
5 | "strings"
6 |
7 | "github.com/wpcodevo/golang-mongodb/pb"
8 | "google.golang.org/grpc/codes"
9 | "google.golang.org/grpc/status"
10 | )
11 |
12 | func (postServer *PostServer) DeletePost(ctx context.Context, req *pb.PostRequest) (*pb.DeletePostResponse, error) {
13 | postId := req.GetId()
14 |
15 | if err := postServer.postService.DeletePost(postId); err != nil {
16 | if strings.Contains(err.Error(), "Id exists") {
17 | return nil, status.Errorf(codes.NotFound, err.Error())
18 | }
19 | return nil, status.Errorf(codes.Internal, err.Error())
20 | }
21 |
22 | res := &pb.DeletePostResponse{
23 | Success: true,
24 | }
25 |
26 | return res, nil
27 | }
28 |
--------------------------------------------------------------------------------
/routes/user.routes.go:
--------------------------------------------------------------------------------
1 | package routes
2 |
3 | import (
4 | "github.com/gin-gonic/gin"
5 | "github.com/wpcodevo/golang-mongodb/controllers"
6 | "github.com/wpcodevo/golang-mongodb/middleware"
7 | "github.com/wpcodevo/golang-mongodb/services"
8 | )
9 |
10 | type UserRouteController struct {
11 | userController controllers.UserController
12 | }
13 |
14 | func NewRouteUserController(userController controllers.UserController) UserRouteController {
15 | return UserRouteController{userController}
16 | }
17 |
18 | func (uc *UserRouteController) UserRoute(rg *gin.RouterGroup, userService services.UserService) {
19 |
20 | router := rg.Group("users")
21 | router.Use(middleware.DeserializeUser(userService))
22 | router.GET("/me", uc.userController.GetMe)
23 | }
24 |
--------------------------------------------------------------------------------
/gapi/user-server.go:
--------------------------------------------------------------------------------
1 | package gapi
2 |
3 | import (
4 | "github.com/wpcodevo/golang-mongodb/config"
5 | "github.com/wpcodevo/golang-mongodb/pb"
6 | "github.com/wpcodevo/golang-mongodb/services"
7 | "go.mongodb.org/mongo-driver/mongo"
8 | )
9 |
10 | type UserServer struct {
11 | pb.UnimplementedUserServiceServer
12 | config config.Config
13 | userService services.UserService
14 | userCollection *mongo.Collection
15 | }
16 |
17 | func NewGrpcUserServer(config config.Config, userService services.UserService, userCollection *mongo.Collection) (*UserServer, error) {
18 | userServer := &UserServer{
19 | config: config,
20 | userService: userService,
21 | userCollection: userCollection,
22 | }
23 |
24 | return userServer, nil
25 | }
26 |
--------------------------------------------------------------------------------
/proto/post_service.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package pb;
4 |
5 | option go_package = "github.com/wpcodevo/golang-mongodb/pb";
6 | import "post.proto";
7 | import "rpc_create_post.proto";
8 | import "rpc_update_post.proto";
9 |
10 | service PostService {
11 | rpc CreatePost(CreatePostRequest) returns (PostResponse) {}
12 | rpc GetPost(PostRequest) returns (PostResponse) {}
13 | rpc GetPosts(GetPostsRequest) returns (stream Post) {}
14 | rpc UpdatePost(UpdatePostRequest) returns (PostResponse) {}
15 | rpc DeletePost(PostRequest) returns (DeletePostResponse) {}
16 | }
17 |
18 | message GetPostsRequest {
19 | optional int64 page = 1;
20 | optional int64 limit = 2;
21 | }
22 |
23 | message PostRequest { string Id = 1; }
24 |
25 | message DeletePostResponse { bool success = 1; }
--------------------------------------------------------------------------------
/routes/post.routes.go:
--------------------------------------------------------------------------------
1 | package routes
2 |
3 | import (
4 | "github.com/gin-gonic/gin"
5 | "github.com/wpcodevo/golang-mongodb/controllers"
6 | )
7 |
8 | type PostRouteController struct {
9 | postController controllers.PostController
10 | }
11 |
12 | func NewPostControllerRoute(postController controllers.PostController) PostRouteController {
13 | return PostRouteController{postController}
14 | }
15 |
16 | func (r *PostRouteController) PostRoute(rg *gin.RouterGroup) {
17 | router := rg.Group("/posts")
18 |
19 | router.GET("/", r.postController.FindPosts)
20 | router.GET("/:postId", r.postController.FindPostById)
21 | router.POST("/", r.postController.CreatePost)
22 | router.PATCH("/:postId", r.postController.UpdatePost)
23 | router.DELETE("/:postId", r.postController.DeletePost)
24 | }
25 |
--------------------------------------------------------------------------------
/client/geMe_client.go:
--------------------------------------------------------------------------------
1 | package client
2 |
3 | import (
4 | "context"
5 | "fmt"
6 | "log"
7 | "time"
8 |
9 | "github.com/wpcodevo/golang-mongodb/pb"
10 | "google.golang.org/grpc"
11 | )
12 |
13 | type GetMeClient struct {
14 | service pb.UserServiceClient
15 | }
16 |
17 | func NewGetMeClient(conn *grpc.ClientConn) *GetMeClient {
18 | service := pb.NewUserServiceClient(conn)
19 |
20 | return &GetMeClient{service}
21 | }
22 |
23 | func (getMeClient *GetMeClient) GetMeUser(credentials *pb.GetMeRequest) {
24 |
25 | ctx, cancel := context.WithTimeout(context.Background(), time.Duration(time.Millisecond*5000))
26 | defer cancel()
27 |
28 | res, err := getMeClient.service.GetMe(ctx, credentials)
29 |
30 | if err != nil {
31 | log.Fatalf("GeMe: %v", err)
32 | }
33 |
34 | fmt.Println(res)
35 | }
36 |
--------------------------------------------------------------------------------
/client/getPost_client.go:
--------------------------------------------------------------------------------
1 | package client
2 |
3 | import (
4 | "context"
5 | "fmt"
6 | "log"
7 | "time"
8 |
9 | "github.com/wpcodevo/golang-mongodb/pb"
10 | "google.golang.org/grpc"
11 | )
12 |
13 | type GetPostClient struct {
14 | service pb.PostServiceClient
15 | }
16 |
17 | func NewGetPostClient(conn *grpc.ClientConn) *GetPostClient {
18 | service := pb.NewPostServiceClient(conn)
19 |
20 | return &GetPostClient{service}
21 | }
22 |
23 | func (getPostClient *GetPostClient) GetPost(args *pb.PostRequest) {
24 |
25 | ctx, cancel := context.WithTimeout(context.Background(), time.Duration(time.Millisecond*5000))
26 | defer cancel()
27 |
28 | res, err := getPostClient.service.GetPost(ctx, args)
29 |
30 | if err != nil {
31 | log.Fatalf("GetPost: %v", err)
32 | }
33 |
34 | fmt.Println(res)
35 | }
36 |
--------------------------------------------------------------------------------
/client/signin_client.go:
--------------------------------------------------------------------------------
1 | package client
2 |
3 | import (
4 | "context"
5 | "fmt"
6 | "log"
7 | "time"
8 |
9 | "github.com/wpcodevo/golang-mongodb/pb"
10 | "google.golang.org/grpc"
11 | )
12 |
13 | type SignInUserClient struct {
14 | service pb.AuthServiceClient
15 | }
16 |
17 | func NewSignInUserClient(conn *grpc.ClientConn) *SignInUserClient {
18 | service := pb.NewAuthServiceClient(conn)
19 |
20 | return &SignInUserClient{service}
21 | }
22 |
23 | func (signInUserClient *SignInUserClient) SignInUser(credentials *pb.SignInUserInput) {
24 |
25 | ctx, cancel := context.WithTimeout(context.Background(), time.Second)
26 | defer cancel()
27 |
28 | res, err := signInUserClient.service.SignInUser(ctx, credentials)
29 |
30 | if err != nil {
31 | log.Fatalf("SignInUser: %v", err)
32 | }
33 |
34 | fmt.Println(res)
35 | }
36 |
--------------------------------------------------------------------------------
/.air.toml:
--------------------------------------------------------------------------------
1 | root = "."
2 | testdata_dir = "testdata"
3 | tmp_dir = "tmp"
4 |
5 | [build]
6 | bin = "tmp\\main.exe"
7 | cmd = "go build -o ./tmp/main.exe ./cmd/server/main.go"
8 | delay = 1000
9 | exclude_dir = ["assets", "tmp", "vendor", "testdata"]
10 | exclude_file = []
11 | exclude_regex = ["_test.go"]
12 | exclude_unchanged = false
13 | follow_symlink = false
14 | full_bin = ""
15 | include_dir = []
16 | include_ext = ["go", "tpl", "tmpl", "html"]
17 | kill_delay = "0s"
18 | log = "build-errors.log"
19 | send_interrupt = false
20 | stop_on_error = true
21 |
22 | [color]
23 | app = ""
24 | build = "yellow"
25 | main = "magenta"
26 | runner = "green"
27 | watcher = "cyan"
28 |
29 | [log]
30 | time = false
31 |
32 | [misc]
33 | clean_on_exit = false
34 |
35 | [screen]
36 | clear_on_rebuild = false
37 |
--------------------------------------------------------------------------------
/client/createPost_client.go:
--------------------------------------------------------------------------------
1 | package client
2 |
3 | import (
4 | "context"
5 | "fmt"
6 | "log"
7 | "time"
8 |
9 | "github.com/wpcodevo/golang-mongodb/pb"
10 | "google.golang.org/grpc"
11 | )
12 |
13 | type CreatePostClient struct {
14 | service pb.PostServiceClient
15 | }
16 |
17 | func NewCreatePostClient(conn *grpc.ClientConn) *CreatePostClient {
18 | service := pb.NewPostServiceClient(conn)
19 |
20 | return &CreatePostClient{service}
21 | }
22 |
23 | func (createPostClient *CreatePostClient) CreatePost(args *pb.CreatePostRequest) {
24 |
25 | ctx, cancel := context.WithTimeout(context.Background(), time.Duration(time.Millisecond*5000))
26 | defer cancel()
27 |
28 | res, err := createPostClient.service.CreatePost(ctx, args)
29 |
30 | if err != nil {
31 | log.Fatalf("CreatePost: %v", err)
32 | }
33 |
34 | fmt.Println(res)
35 | }
36 |
--------------------------------------------------------------------------------
/client/updatePost_client.go:
--------------------------------------------------------------------------------
1 | package client
2 |
3 | import (
4 | "context"
5 | "fmt"
6 | "log"
7 | "time"
8 |
9 | "github.com/wpcodevo/golang-mongodb/pb"
10 | "google.golang.org/grpc"
11 | )
12 |
13 | type UpdatePostClient struct {
14 | service pb.PostServiceClient
15 | }
16 |
17 | func NewUpdatePostClient(conn *grpc.ClientConn) *UpdatePostClient {
18 | service := pb.NewPostServiceClient(conn)
19 |
20 | return &UpdatePostClient{service}
21 | }
22 |
23 | func (updatePostClient *UpdatePostClient) UpdatePost(args *pb.UpdatePostRequest) {
24 |
25 | ctx, cancel := context.WithTimeout(context.Background(), time.Duration(time.Millisecond*5000))
26 | defer cancel()
27 |
28 | res, err := updatePostClient.service.UpdatePost(ctx, args)
29 |
30 | if err != nil {
31 | log.Fatalf("UpdatePost: %v", err)
32 | }
33 |
34 | fmt.Println(res)
35 | }
36 |
--------------------------------------------------------------------------------
/client/signup_client.go:
--------------------------------------------------------------------------------
1 | package client
2 |
3 | import (
4 | "context"
5 | "fmt"
6 | "log"
7 | "time"
8 |
9 | "github.com/wpcodevo/golang-mongodb/pb"
10 | "google.golang.org/grpc"
11 | )
12 |
13 | type SignUpUserClient struct {
14 | service pb.AuthServiceClient
15 | }
16 |
17 | func NewSignUpUserClient(conn *grpc.ClientConn) *SignUpUserClient {
18 | service := pb.NewAuthServiceClient(conn)
19 |
20 | return &SignUpUserClient{service}
21 | }
22 |
23 | func (signUpUserClient *SignUpUserClient) SignUpUser(credentials *pb.SignUpUserInput) {
24 |
25 | ctx, cancel := context.WithTimeout(context.Background(), time.Duration(time.Millisecond*5000))
26 | defer cancel()
27 |
28 | res, err := signUpUserClient.service.SignUpUser(ctx, credentials)
29 |
30 | if err != nil {
31 | log.Fatalf("SignUpUser: %v", err)
32 | }
33 |
34 | fmt.Println(res)
35 | }
36 |
--------------------------------------------------------------------------------
/client/deletePost_client.go:
--------------------------------------------------------------------------------
1 | package client
2 |
3 | import (
4 | "context"
5 | "fmt"
6 | "log"
7 | "time"
8 |
9 | "github.com/wpcodevo/golang-mongodb/pb"
10 | "google.golang.org/grpc"
11 | )
12 |
13 | type DeletePostClient struct {
14 | service pb.PostServiceClient
15 | }
16 |
17 | func NewDeletePostClient(conn *grpc.ClientConn) *DeletePostClient {
18 | service := pb.NewPostServiceClient(conn)
19 |
20 | return &DeletePostClient{service}
21 | }
22 |
23 | func (deletePostClient *DeletePostClient) DeletePost(args *pb.PostRequest) {
24 |
25 | ctx, cancel := context.WithTimeout(context.Background(), time.Duration(time.Millisecond*5000))
26 | defer cancel()
27 |
28 | _, err := deletePostClient.service.DeletePost(ctx, args)
29 |
30 | if err != nil {
31 | log.Fatalf("DeletePost: %v", err)
32 | }
33 |
34 | fmt.Println("Post deleted successfully")
35 | }
36 |
--------------------------------------------------------------------------------
/gapi/rpc_get_me.go:
--------------------------------------------------------------------------------
1 | package gapi
2 |
3 | import (
4 | "context"
5 |
6 | "github.com/wpcodevo/golang-mongodb/pb"
7 | "google.golang.org/grpc/codes"
8 | "google.golang.org/grpc/status"
9 | "google.golang.org/protobuf/types/known/timestamppb"
10 | )
11 |
12 | func (userServer *UserServer) GetMe(ctx context.Context, req *pb.GetMeRequest) (*pb.UserResponse, error) {
13 | id := req.GetId()
14 | user, err := userServer.userService.FindUserById(id)
15 |
16 | if err != nil {
17 | return nil, status.Errorf(codes.Unimplemented, err.Error())
18 | }
19 |
20 | res := &pb.UserResponse{
21 | User: &pb.User{
22 | Id: user.ID.Hex(),
23 | Name: user.Name,
24 | Email: user.Email,
25 | Role: user.Role,
26 | CreatedAt: timestamppb.New(user.CreatedAt),
27 | UpdatedAt: timestamppb.New(user.UpdatedAt),
28 | },
29 | }
30 | return res, nil
31 | }
32 |
--------------------------------------------------------------------------------
/gapi/auth-server.go:
--------------------------------------------------------------------------------
1 | package gapi
2 |
3 | import (
4 | "github.com/wpcodevo/golang-mongodb/config"
5 | "github.com/wpcodevo/golang-mongodb/pb"
6 | "github.com/wpcodevo/golang-mongodb/services"
7 | "go.mongodb.org/mongo-driver/mongo"
8 | )
9 |
10 | type AuthServer struct {
11 | pb.UnimplementedAuthServiceServer
12 | config config.Config
13 | authService services.AuthService
14 | userService services.UserService
15 | userCollection *mongo.Collection
16 | }
17 |
18 | func NewGrpcAuthServer(config config.Config, authService services.AuthService,
19 | userService services.UserService, userCollection *mongo.Collection) (*AuthServer, error) {
20 |
21 | authServer := &AuthServer{
22 | config: config,
23 | authService: authService,
24 | userService: userService,
25 | userCollection: userCollection,
26 | }
27 |
28 | return authServer, nil
29 | }
30 |
--------------------------------------------------------------------------------
/templates/base.html:
--------------------------------------------------------------------------------
1 | {{define "base"}}
2 |
3 |
4 |
5 |
6 |
7 | {{template "styles" .}}
8 | {{ .Subject}}
9 |
10 |
11 |
18 |
19 | | |
20 |
21 |
22 |
23 | {{block "content" .}}{{end}}
24 |
25 |
26 | |
27 | |
28 |
29 |
30 |
31 |
32 | {{end}}
33 |
--------------------------------------------------------------------------------
/gapi/rpc_list_posts.go:
--------------------------------------------------------------------------------
1 | package gapi
2 |
3 | import (
4 | "github.com/wpcodevo/golang-mongodb/pb"
5 | "google.golang.org/grpc/codes"
6 | "google.golang.org/grpc/status"
7 | "google.golang.org/protobuf/types/known/timestamppb"
8 | )
9 |
10 | func (postServer *PostServer) GetPosts(req *pb.GetPostsRequest, stream pb.PostService_GetPostsServer) error {
11 | var page = req.GetPage()
12 | var limit = req.GetLimit()
13 |
14 | posts, err := postServer.postService.FindPosts(int(page), int(limit))
15 | if err != nil {
16 | return status.Errorf(codes.Internal, err.Error())
17 | }
18 |
19 | for _, post := range posts {
20 | stream.Send(&pb.Post{
21 | Id: post.Id.Hex(),
22 | Title: post.Title,
23 | Content: post.Content,
24 | Image: post.Image,
25 | CreatedAt: timestamppb.New(post.CreateAt),
26 | UpdatedAt: timestamppb.New(post.UpdatedAt),
27 | })
28 | }
29 |
30 | return nil
31 | }
32 |
--------------------------------------------------------------------------------
/client/listPosts_client.go:
--------------------------------------------------------------------------------
1 | package client
2 |
3 | import (
4 | "context"
5 | "fmt"
6 | "io"
7 | "log"
8 | "time"
9 |
10 | "github.com/wpcodevo/golang-mongodb/pb"
11 | "google.golang.org/grpc"
12 | )
13 |
14 | type ListPostsClient struct {
15 | service pb.PostServiceClient
16 | }
17 |
18 | func NewListPostsClient(conn *grpc.ClientConn) *ListPostsClient {
19 | service := pb.NewPostServiceClient(conn)
20 |
21 | return &ListPostsClient{service}
22 | }
23 |
24 | func (listPostsClient *ListPostsClient) ListPosts(args *pb.GetPostsRequest) {
25 | ctx, cancel := context.WithTimeout(context.Background(), time.Duration(time.Millisecond*5000))
26 | defer cancel()
27 |
28 | stream, err := listPostsClient.service.GetPosts(ctx, args)
29 | if err != nil {
30 | log.Fatalf("ListPosts: %v", err)
31 | }
32 |
33 | for {
34 | res, err := stream.Recv()
35 |
36 | if err == io.EOF {
37 | break
38 | }
39 |
40 | if err != nil {
41 | log.Fatalf("ListPosts: %v", err)
42 | }
43 |
44 | fmt.Println(res)
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/gapi/rpc_get_post.go:
--------------------------------------------------------------------------------
1 | package gapi
2 |
3 | import (
4 | "context"
5 | "strings"
6 |
7 | "github.com/wpcodevo/golang-mongodb/pb"
8 | "google.golang.org/grpc/codes"
9 | "google.golang.org/grpc/status"
10 | "google.golang.org/protobuf/types/known/timestamppb"
11 | )
12 |
13 | func (postServer *PostServer) GetPost(ctx context.Context, req *pb.PostRequest) (*pb.PostResponse, error) {
14 | postId := req.GetId()
15 |
16 | post, err := postServer.postService.FindPostById(postId)
17 | if err != nil {
18 | if strings.Contains(err.Error(), "Id exists") {
19 | return nil, status.Errorf(codes.NotFound, err.Error())
20 |
21 | }
22 | return nil, status.Errorf(codes.Internal, err.Error())
23 | }
24 |
25 | res := &pb.PostResponse{
26 | Post: &pb.Post{
27 | Id: post.Id.Hex(),
28 | Title: post.Title,
29 | Content: post.Content,
30 | Image: post.Image,
31 | User: post.User,
32 | CreatedAt: timestamppb.New(post.CreateAt),
33 | UpdatedAt: timestamppb.New(post.UpdatedAt),
34 | },
35 | }
36 | return res, nil
37 | }
38 |
--------------------------------------------------------------------------------
/routes/auth.routes.go:
--------------------------------------------------------------------------------
1 | package routes
2 |
3 | import (
4 | "github.com/gin-gonic/gin"
5 | "github.com/wpcodevo/golang-mongodb/controllers"
6 | "github.com/wpcodevo/golang-mongodb/middleware"
7 | "github.com/wpcodevo/golang-mongodb/services"
8 | )
9 |
10 | type AuthRouteController struct {
11 | authController controllers.AuthController
12 | }
13 |
14 | func NewAuthRouteController(authController controllers.AuthController) AuthRouteController {
15 | return AuthRouteController{authController}
16 | }
17 |
18 | func (rc *AuthRouteController) AuthRoute(rg *gin.RouterGroup, userService services.UserService) {
19 | router := rg.Group("/auth")
20 |
21 | router.POST("/register", rc.authController.SignUpUser)
22 | router.POST("/login", rc.authController.SignInUser)
23 | router.GET("/refresh", rc.authController.RefreshAccessToken)
24 | router.GET("/logout", middleware.DeserializeUser(userService), rc.authController.LogoutUser)
25 | router.GET("/verifyemail/:verificationCode", rc.authController.VerifyEmail)
26 | router.POST("/forgotPassword", rc.authController.ForgotPassword)
27 | }
28 |
--------------------------------------------------------------------------------
/gapi/rpc_verify_user.go:
--------------------------------------------------------------------------------
1 | package gapi
2 |
3 | import (
4 | "context"
5 | "time"
6 |
7 | "github.com/wpcodevo/golang-mongodb/pb"
8 | "github.com/wpcodevo/golang-mongodb/utils"
9 | "go.mongodb.org/mongo-driver/bson"
10 | "google.golang.org/grpc/codes"
11 | "google.golang.org/grpc/status"
12 | )
13 |
14 | func (authServer *AuthServer) VerifyEmail(ctx context.Context, req *pb.VerifyEmailRequest) (*pb.GenericResponse, error) {
15 | code := req.GetVerificationCode()
16 |
17 | verificationCode := utils.Encode(code)
18 |
19 | query := bson.D{{Key: "verificationCode", Value: verificationCode}}
20 | update := bson.D{{Key: "$set", Value: bson.D{{Key: "verified", Value: true}, {Key: "updated_at", Value: time.Now()}}}, {Key: "$unset", Value: bson.D{{Key: "verificationCode", Value: ""}}}}
21 | result, err := authServer.userCollection.UpdateOne(ctx, query, update)
22 | if err != nil {
23 | return nil, status.Errorf(codes.Internal, err.Error())
24 | }
25 |
26 | if result.MatchedCount == 0 {
27 | return nil, status.Errorf(codes.PermissionDenied, "Could not verify email address")
28 | }
29 |
30 | res := &pb.GenericResponse{
31 | Status: "success",
32 | Message: "Email verified successfully",
33 | }
34 | return res, nil
35 | }
36 |
--------------------------------------------------------------------------------
/gapi/rpc_create_post.go:
--------------------------------------------------------------------------------
1 | package gapi
2 |
3 | import (
4 | "context"
5 | "strings"
6 |
7 | "github.com/wpcodevo/golang-mongodb/models"
8 | "github.com/wpcodevo/golang-mongodb/pb"
9 | "google.golang.org/grpc/codes"
10 | "google.golang.org/grpc/status"
11 | "google.golang.org/protobuf/types/known/timestamppb"
12 | )
13 |
14 | func (postServer *PostServer) CreatePost(ctx context.Context, req *pb.CreatePostRequest) (*pb.PostResponse, error) {
15 |
16 | post := &models.CreatePostRequest{
17 | Title: req.GetTitle(),
18 | Content: req.GetContent(),
19 | Image: req.GetImage(),
20 | User: req.GetUser(),
21 | }
22 |
23 | newPost, err := postServer.postService.CreatePost(post)
24 |
25 | if err != nil {
26 | if strings.Contains(err.Error(), "title already exists") {
27 | return nil, status.Errorf(codes.AlreadyExists, err.Error())
28 | }
29 |
30 | return nil, status.Errorf(codes.Internal, err.Error())
31 | }
32 |
33 | res := &pb.PostResponse{
34 | Post: &pb.Post{
35 | Id: newPost.Id.Hex(),
36 | Title: newPost.Title,
37 | Content: newPost.Content,
38 | User: newPost.User,
39 | CreatedAt: timestamppb.New(newPost.CreateAt),
40 | UpdatedAt: timestamppb.New(newPost.UpdatedAt),
41 | },
42 | }
43 | return res, nil
44 | }
45 |
--------------------------------------------------------------------------------
/gapi/rpc_update_post.go:
--------------------------------------------------------------------------------
1 | package gapi
2 |
3 | import (
4 | "context"
5 | "strings"
6 | "time"
7 |
8 | "github.com/wpcodevo/golang-mongodb/models"
9 | "github.com/wpcodevo/golang-mongodb/pb"
10 | "google.golang.org/grpc/codes"
11 | "google.golang.org/grpc/status"
12 | "google.golang.org/protobuf/types/known/timestamppb"
13 | )
14 |
15 | func (postServer *PostServer) UpdatePost(ctx context.Context, req *pb.UpdatePostRequest) (*pb.PostResponse, error) {
16 | postId := req.GetId()
17 |
18 | post := &models.UpdatePost{
19 | Title: req.GetTitle(),
20 | Content: req.GetContent(),
21 | Image: req.GetImage(),
22 | User: req.GetUser(),
23 | UpdatedAt: time.Now(),
24 | }
25 |
26 | updatedPost, err := postServer.postService.UpdatePost(postId, post)
27 |
28 | if err != nil {
29 | if strings.Contains(err.Error(), "Id exists") {
30 | return nil, status.Errorf(codes.NotFound, err.Error())
31 | }
32 | return nil, status.Errorf(codes.Internal, err.Error())
33 | }
34 |
35 | res := &pb.PostResponse{
36 | Post: &pb.Post{
37 | Id: updatedPost.Id.Hex(),
38 | Title: updatedPost.Title,
39 | Content: updatedPost.Content,
40 | Image: updatedPost.Image,
41 | User: updatedPost.User,
42 | CreatedAt: timestamppb.New(updatedPost.CreateAt),
43 | UpdatedAt: timestamppb.New(updatedPost.UpdatedAt),
44 | },
45 | }
46 | return res, nil
47 | }
48 |
--------------------------------------------------------------------------------
/middleware/deserialize-user.go:
--------------------------------------------------------------------------------
1 | package middleware
2 |
3 | import (
4 | "fmt"
5 | "net/http"
6 | "strings"
7 |
8 | "github.com/gin-gonic/gin"
9 | "github.com/wpcodevo/golang-mongodb/config"
10 | "github.com/wpcodevo/golang-mongodb/services"
11 | "github.com/wpcodevo/golang-mongodb/utils"
12 | )
13 |
14 | func DeserializeUser(userService services.UserService) gin.HandlerFunc {
15 | return func(ctx *gin.Context) {
16 | var access_token string
17 | cookie, err := ctx.Cookie("access_token")
18 |
19 | authorizationHeader := ctx.Request.Header.Get("Authorization")
20 | fields := strings.Fields(authorizationHeader)
21 |
22 | if len(fields) != 0 && fields[0] == "Bearer" {
23 | access_token = fields[1]
24 | } else if err == nil {
25 | access_token = cookie
26 | }
27 |
28 | if access_token == "" {
29 | ctx.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"status": "fail", "message": "You are not logged in"})
30 | return
31 | }
32 |
33 | config, _ := config.LoadConfig(".")
34 | sub, err := utils.ValidateToken(access_token, config.AccessTokenPublicKey)
35 | if err != nil {
36 | ctx.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"status": "fail", "message": err.Error()})
37 | return
38 | }
39 |
40 | user, err := userService.FindUserById(fmt.Sprint(sub))
41 | if err != nil {
42 | ctx.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"status": "fail", "message": "The user belonging to this token no logger exists"})
43 | return
44 | }
45 |
46 | ctx.Set("currentUser", user)
47 | ctx.Next()
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/config/default.go:
--------------------------------------------------------------------------------
1 | package config
2 |
3 | import (
4 | "time"
5 |
6 | "github.com/spf13/viper"
7 | )
8 |
9 | type Config struct {
10 | DBUri string `mapstructure:"MONGODB_LOCAL_URI"`
11 | RedisUri string `mapstructure:"REDIS_URL"`
12 | Port string `mapstructure:"PORT"`
13 |
14 | GrpcServerAddress string `mapstructure:"GRPC_SERVER_ADDRESS"`
15 |
16 | AccessTokenPrivateKey string `mapstructure:"ACCESS_TOKEN_PRIVATE_KEY"`
17 | AccessTokenPublicKey string `mapstructure:"ACCESS_TOKEN_PUBLIC_KEY"`
18 | RefreshTokenPrivateKey string `mapstructure:"REFRESH_TOKEN_PRIVATE_KEY"`
19 | RefreshTokenPublicKey string `mapstructure:"REFRESH_TOKEN_PUBLIC_KEY"`
20 | AccessTokenExpiresIn time.Duration `mapstructure:"ACCESS_TOKEN_EXPIRED_IN"`
21 | RefreshTokenExpiresIn time.Duration `mapstructure:"REFRESH_TOKEN_EXPIRED_IN"`
22 | AccessTokenMaxAge int `mapstructure:"ACCESS_TOKEN_MAXAGE"`
23 | RefreshTokenMaxAge int `mapstructure:"REFRESH_TOKEN_MAXAGE"`
24 |
25 | Origin string `mapstructure:"CLIENT_ORIGIN"`
26 |
27 | EmailFrom string `mapstructure:"EMAIL_FROM"`
28 | SMTPHost string `mapstructure:"SMTP_HOST"`
29 | SMTPPass string `mapstructure:"SMTP_PASS"`
30 | SMTPPort int `mapstructure:"SMTP_PORT"`
31 | SMTPUser string `mapstructure:"SMTP_USER"`
32 | }
33 |
34 | func LoadConfig(path string) (config Config, err error) {
35 | viper.AddConfigPath(path)
36 | viper.SetConfigType("env")
37 | viper.SetConfigName("app")
38 |
39 | viper.AutomaticEnv()
40 |
41 | err = viper.ReadInConfig()
42 | if err != nil {
43 | return
44 | }
45 |
46 | err = viper.Unmarshal(&config)
47 | return
48 | }
49 |
--------------------------------------------------------------------------------
/templates/verificationCode.html:
--------------------------------------------------------------------------------
1 | {{template "base" .}} {{define "content"}}
2 |
3 |
4 |
5 |
6 |
7 |
8 | |
9 | Hi {{ .FirstName}},
10 | Please verify your account to be able to login
11 |
18 |
19 |
20 | |
21 |
37 | |
38 |
39 |
40 |
41 | Good luck! Codevo CEO.
42 | |
43 |
44 |
45 | |
46 |
47 |
48 |
49 |
50 | {{end}}
51 |
--------------------------------------------------------------------------------
/models/post.model.go:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import (
4 | "time"
5 |
6 | "go.mongodb.org/mongo-driver/bson/primitive"
7 | )
8 |
9 | type CreatePostRequest struct {
10 | Title string `json:"title" bson:"title" binding:"required"`
11 | Content string `json:"content" bson:"content" binding:"required"`
12 | Image string `json:"image,omitempty" bson:"image,omitempty"`
13 | User string `json:"user" bson:"user" binding:"required"`
14 | CreateAt time.Time `json:"created_at,omitempty" bson:"created_at,omitempty"`
15 | UpdatedAt time.Time `json:"updated_at,omitempty" bson:"updated_at,omitempty"`
16 | }
17 |
18 | type DBPost struct {
19 | Id primitive.ObjectID `json:"id,omitempty" bson:"_id,omitempty"`
20 | Title string `json:"title,omitempty" bson:"title,omitempty"`
21 | Content string `json:"content,omitempty" bson:"content,omitempty"`
22 | Image string `json:"image,omitempty" bson:"image,omitempty"`
23 | User string `json:"user,omitempty" bson:"user,omitempty"`
24 | CreateAt time.Time `json:"created_at,omitempty" bson:"created_at,omitempty"`
25 | UpdatedAt time.Time `json:"updated_at,omitempty" bson:"updated_at,omitempty"`
26 | }
27 |
28 | type UpdatePost struct {
29 | Title string `json:"title,omitempty" bson:"title,omitempty"`
30 | Content string `json:"content,omitempty" bson:"content,omitempty"`
31 | Image string `json:"image,omitempty" bson:"image,omitempty"`
32 | User string `json:"user,omitempty" bson:"user,omitempty"`
33 | CreateAt time.Time `json:"created_at,omitempty" bson:"created_at,omitempty"`
34 | UpdatedAt time.Time `json:"updated_at,omitempty" bson:"updated_at,omitempty"`
35 | }
36 |
--------------------------------------------------------------------------------
/gapi/rpc_signin_user.go:
--------------------------------------------------------------------------------
1 | package gapi
2 |
3 | import (
4 | "context"
5 |
6 | "github.com/wpcodevo/golang-mongodb/pb"
7 | "github.com/wpcodevo/golang-mongodb/utils"
8 | "go.mongodb.org/mongo-driver/mongo"
9 | "google.golang.org/grpc/codes"
10 | "google.golang.org/grpc/status"
11 | )
12 |
13 | func (authServer *AuthServer) SignInUser(ctx context.Context, req *pb.SignInUserInput) (*pb.SignInUserResponse, error) {
14 | user, err := authServer.userService.FindUserByEmail(req.GetEmail())
15 | if err != nil {
16 | if err == mongo.ErrNoDocuments {
17 |
18 | return nil, status.Errorf(codes.InvalidArgument, "Invalid email or password")
19 |
20 | }
21 |
22 | return nil, status.Errorf(codes.Internal, err.Error())
23 |
24 | }
25 |
26 | if !user.Verified {
27 |
28 | return nil, status.Errorf(codes.PermissionDenied, "You are not verified, please verify your email to login")
29 |
30 | }
31 |
32 | if err := utils.VerifyPassword(user.Password, req.GetPassword()); err != nil {
33 |
34 | return nil, status.Errorf(codes.InvalidArgument, "Invalid email or Password")
35 |
36 | }
37 |
38 | // Generate Tokens
39 | access_token, err := utils.CreateToken(authServer.config.AccessTokenExpiresIn, user.ID, authServer.config.AccessTokenPrivateKey)
40 | if err != nil {
41 |
42 | return nil, status.Errorf(codes.PermissionDenied, err.Error())
43 |
44 | }
45 |
46 | refresh_token, err := utils.CreateToken(authServer.config.RefreshTokenExpiresIn, user.ID, authServer.config.RefreshTokenPrivateKey)
47 | if err != nil {
48 | return nil, status.Errorf(codes.PermissionDenied, err.Error())
49 | }
50 |
51 | res := &pb.SignInUserResponse{
52 | Status: "success",
53 | AccessToken: access_token,
54 | RefreshToken: refresh_token,
55 | }
56 |
57 | return res, nil
58 | }
59 |
--------------------------------------------------------------------------------
/templates/resetPassword.html:
--------------------------------------------------------------------------------
1 | {{template "base" .}} {{define "content"}}
2 |
3 |
4 |
5 |
6 |
7 |
8 | |
9 | Hi {{ .FirstName}},
10 |
11 | Forgot password? Send a PATCH request to with your password and
12 | passwordConfirm to {{.URL}}
13 |
14 |
21 |
22 |
23 | |
24 |
40 | |
41 |
42 |
43 |
44 | If you didn't forget your password, please ignore this email
45 | Good luck! Codevo CEO.
46 | |
47 |
48 |
49 | |
50 |
51 |
52 |
53 |
54 | {{end}}
55 |
--------------------------------------------------------------------------------
/utils/token.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "encoding/base64"
5 | "fmt"
6 | "time"
7 |
8 | "github.com/golang-jwt/jwt"
9 | )
10 |
11 | func CreateToken(ttl time.Duration, payload interface{}, privateKey string) (string, error) {
12 | decodedPrivateKey, err := base64.StdEncoding.DecodeString(privateKey)
13 | if err != nil {
14 | return "", fmt.Errorf("could not decode key: %w", err)
15 | }
16 | key, err := jwt.ParseRSAPrivateKeyFromPEM(decodedPrivateKey)
17 |
18 | if err != nil {
19 | return "", fmt.Errorf("create: parse key: %w", err)
20 | }
21 |
22 | now := time.Now().UTC()
23 |
24 | claims := make(jwt.MapClaims)
25 | claims["sub"] = payload
26 | claims["exp"] = now.Add(ttl).Unix()
27 | claims["iat"] = now.Unix()
28 | claims["nbf"] = now.Unix()
29 |
30 | token, err := jwt.NewWithClaims(jwt.SigningMethodRS256, claims).SignedString(key)
31 |
32 | if err != nil {
33 | return "", fmt.Errorf("create: sign token: %w", err)
34 | }
35 |
36 | return token, nil
37 | }
38 |
39 | func ValidateToken(token string, publicKey string) (interface{}, error) {
40 | decodedPublicKey, err := base64.StdEncoding.DecodeString(publicKey)
41 | if err != nil {
42 | return nil, fmt.Errorf("could not decode: %w", err)
43 | }
44 |
45 | key, err := jwt.ParseRSAPublicKeyFromPEM(decodedPublicKey)
46 |
47 | if err != nil {
48 | return "", fmt.Errorf("validate: parse key: %w", err)
49 | }
50 |
51 | parsedToken, err := jwt.Parse(token, func(t *jwt.Token) (interface{}, error) {
52 | if _, ok := t.Method.(*jwt.SigningMethodRSA); !ok {
53 | return nil, fmt.Errorf("unexpected method: %s", t.Header["alg"])
54 | }
55 | return key, nil
56 | })
57 |
58 | if err != nil {
59 | return nil, fmt.Errorf("validate: %w", err)
60 | }
61 |
62 | claims, ok := parsedToken.Claims.(jwt.MapClaims)
63 | if !ok || !parsedToken.Valid {
64 | return nil, fmt.Errorf("validate: invalid token")
65 | }
66 |
67 | return claims["sub"], nil
68 | }
69 |
--------------------------------------------------------------------------------
/services/auth.service.impl.go:
--------------------------------------------------------------------------------
1 | package services
2 |
3 | import (
4 | "context"
5 | "errors"
6 | "strings"
7 | "time"
8 |
9 | "github.com/wpcodevo/golang-mongodb/models"
10 | "github.com/wpcodevo/golang-mongodb/utils"
11 | "go.mongodb.org/mongo-driver/bson"
12 | "go.mongodb.org/mongo-driver/mongo"
13 | "go.mongodb.org/mongo-driver/mongo/options"
14 | )
15 |
16 | type AuthServiceImpl struct {
17 | collection *mongo.Collection
18 | ctx context.Context
19 | }
20 |
21 | func NewAuthService(collection *mongo.Collection, ctx context.Context) AuthService {
22 | return &AuthServiceImpl{collection, ctx}
23 | }
24 |
25 | func (uc *AuthServiceImpl) SignUpUser(user *models.SignUpInput) (*models.DBResponse, error) {
26 | user.CreatedAt = time.Now()
27 | user.UpdatedAt = user.CreatedAt
28 | user.Email = strings.ToLower(user.Email)
29 | user.PasswordConfirm = ""
30 | user.Verified = false
31 | user.Role = "user"
32 |
33 | hashedPassword, _ := utils.HashPassword(user.Password)
34 | user.Password = hashedPassword
35 | res, err := uc.collection.InsertOne(uc.ctx, &user)
36 |
37 | if err != nil {
38 | if er, ok := err.(mongo.WriteException); ok && er.WriteErrors[0].Code == 11000 {
39 | return nil, errors.New("user with that email already exist")
40 | }
41 | return nil, err
42 | }
43 |
44 | // Create a unique index for the email field
45 | opt := options.Index()
46 | opt.SetUnique(true)
47 | index := mongo.IndexModel{Keys: bson.M{"email": 1}, Options: opt}
48 |
49 | if _, err := uc.collection.Indexes().CreateOne(uc.ctx, index); err != nil {
50 | return nil, errors.New("could not create index for email")
51 | }
52 |
53 | var newUser *models.DBResponse
54 | query := bson.M{"_id": res.InsertedID}
55 |
56 | err = uc.collection.FindOne(uc.ctx, query).Decode(&newUser)
57 | if err != nil {
58 | return nil, err
59 | }
60 |
61 | return newUser, nil
62 | }
63 |
64 | func (uc *AuthServiceImpl) SignInUser(*models.SignInInput) (*models.DBResponse, error) {
65 | return nil, nil
66 | }
67 |
--------------------------------------------------------------------------------
/utils/email.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "bytes"
5 | "crypto/tls"
6 | "fmt"
7 | "log"
8 | "os"
9 | "path/filepath"
10 | "text/template"
11 |
12 | "github.com/k3a/html2text"
13 | "github.com/wpcodevo/golang-mongodb/config"
14 | "github.com/wpcodevo/golang-mongodb/models"
15 | "gopkg.in/gomail.v2"
16 | )
17 |
18 | type EmailData struct {
19 | URL string
20 | FirstName string
21 | Subject string
22 | }
23 |
24 | // 👇 Email template parser
25 |
26 | func ParseTemplateDir(dir string) (*template.Template, error) {
27 | var paths []string
28 | err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
29 | if err != nil {
30 | return err
31 | }
32 | if !info.IsDir() {
33 | paths = append(paths, path)
34 | }
35 | return nil
36 | })
37 |
38 | fmt.Println("Am parsing templates...")
39 |
40 | if err != nil {
41 | return nil, err
42 | }
43 |
44 | return template.ParseFiles(paths...)
45 | }
46 |
47 | func SendEmail(user *models.DBResponse, data *EmailData, templateName string) error {
48 | config, err := config.LoadConfig(".")
49 |
50 | if err != nil {
51 | log.Fatal("could not load config", err)
52 | }
53 |
54 | // Sender data.
55 | from := config.EmailFrom
56 | smtpPass := config.SMTPPass
57 | smtpUser := config.SMTPUser
58 | to := user.Email
59 | smtpHost := config.SMTPHost
60 | smtpPort := config.SMTPPort
61 |
62 | var body bytes.Buffer
63 |
64 | template, err := ParseTemplateDir("templates")
65 | if err != nil {
66 | log.Fatal("Could not parse template", err)
67 | }
68 |
69 | template = template.Lookup(templateName)
70 | template.Execute(&body, &data)
71 | fmt.Println(template.Name())
72 |
73 | m := gomail.NewMessage()
74 |
75 | m.SetHeader("From", from)
76 | m.SetHeader("To", to)
77 | m.SetHeader("Subject", data.Subject)
78 | m.SetBody("text/html", body.String())
79 | m.AddAlternative("text/plain", html2text.HTML2Text(body.String()))
80 |
81 | d := gomail.NewDialer(smtpHost, smtpPort, smtpUser, smtpPass)
82 | d.TLSConfig = &tls.Config{InsecureSkipVerify: true}
83 |
84 | // Send Email
85 | if err := d.DialAndSend(m); err != nil {
86 | return err
87 | }
88 | return nil
89 | }
90 |
--------------------------------------------------------------------------------
/gapi/rpc_signup_user.go:
--------------------------------------------------------------------------------
1 | package gapi
2 |
3 | import (
4 | "context"
5 | "strings"
6 |
7 | "github.com/thanhpk/randstr"
8 | "github.com/wpcodevo/golang-mongodb/models"
9 | "github.com/wpcodevo/golang-mongodb/pb"
10 | "github.com/wpcodevo/golang-mongodb/utils"
11 | "google.golang.org/grpc/codes"
12 | "google.golang.org/grpc/status"
13 | )
14 |
15 | func (authServer *AuthServer) SignUpUser(ctx context.Context, req *pb.SignUpUserInput) (*pb.GenericResponse, error) {
16 | if req.GetPassword() != req.GetPasswordConfirm() {
17 | return nil, status.Errorf(codes.InvalidArgument, "passwords do not match")
18 | }
19 |
20 | user := models.SignUpInput{
21 | Name: req.GetName(),
22 | Email: req.GetEmail(),
23 | Password: req.GetPassword(),
24 | PasswordConfirm: req.GetPasswordConfirm(),
25 | }
26 |
27 | newUser, err := authServer.authService.SignUpUser(&user)
28 |
29 | if err != nil {
30 | if strings.Contains(err.Error(), "email already exist") {
31 | return nil, status.Errorf(codes.AlreadyExists, "%s", err.Error())
32 |
33 | }
34 | return nil, status.Errorf(codes.Internal, "%s", err.Error())
35 | }
36 |
37 | // Generate Verification Code
38 | code := randstr.String(20)
39 |
40 | verificationCode := utils.Encode(code)
41 |
42 | updateData := &models.UpdateInput{
43 | VerificationCode: verificationCode,
44 | }
45 |
46 | // Update User in Database
47 | authServer.userService.UpdateUserById(newUser.ID.Hex(), updateData)
48 |
49 | var firstName = newUser.Name
50 |
51 | if strings.Contains(firstName, " ") {
52 | firstName = strings.Split(firstName, " ")[0]
53 | }
54 |
55 | // 👇 Send Email
56 | emailData := utils.EmailData{
57 | URL: authServer.config.Origin + "/verifyemail/" + code,
58 | FirstName: firstName,
59 | Subject: "Your account verification code",
60 | }
61 |
62 | err = utils.SendEmail(newUser, &emailData, "verificationCode.html")
63 | if err != nil {
64 | return nil, status.Errorf(codes.Internal, "There was an error sending email: %s", err.Error())
65 |
66 | }
67 |
68 | message := "We sent an email with a verification code to " + newUser.Email
69 |
70 | res := &pb.GenericResponse{
71 | Status: "success",
72 | Message: message,
73 | }
74 | return res, nil
75 | }
76 |
--------------------------------------------------------------------------------
/services/user.service.impl.go:
--------------------------------------------------------------------------------
1 | package services
2 |
3 | import (
4 | "context"
5 | "errors"
6 | "fmt"
7 | "strings"
8 |
9 | "github.com/wpcodevo/golang-mongodb/models"
10 | "github.com/wpcodevo/golang-mongodb/utils"
11 | "go.mongodb.org/mongo-driver/bson"
12 | "go.mongodb.org/mongo-driver/bson/primitive"
13 | "go.mongodb.org/mongo-driver/mongo"
14 | "go.mongodb.org/mongo-driver/mongo/options"
15 | )
16 |
17 | type UserServiceImpl struct {
18 | collection *mongo.Collection
19 | ctx context.Context
20 | }
21 |
22 | func NewUserServiceImpl(collection *mongo.Collection, ctx context.Context) UserService {
23 | return &UserServiceImpl{collection, ctx}
24 | }
25 |
26 | func (us *UserServiceImpl) FindUserById(id string) (*models.DBResponse, error) {
27 | oid, _ := primitive.ObjectIDFromHex(id)
28 |
29 | var user *models.DBResponse
30 |
31 | query := bson.M{"_id": oid}
32 | err := us.collection.FindOne(us.ctx, query).Decode(&user)
33 |
34 | if err != nil {
35 | if err == mongo.ErrNoDocuments {
36 | return &models.DBResponse{}, err
37 | }
38 | return nil, err
39 | }
40 |
41 | return user, nil
42 | }
43 |
44 | func (us *UserServiceImpl) FindUserByEmail(email string) (*models.DBResponse, error) {
45 | var user *models.DBResponse
46 |
47 | query := bson.M{"email": strings.ToLower(email)}
48 | err := us.collection.FindOne(us.ctx, query).Decode(&user)
49 |
50 | if err != nil {
51 | if err == mongo.ErrNoDocuments {
52 | return &models.DBResponse{}, err
53 | }
54 | return nil, err
55 | }
56 |
57 | return user, nil
58 | }
59 |
60 | func (uc *UserServiceImpl) UpdateUserById(id string, data *models.UpdateInput) (*models.DBResponse, error) {
61 | doc, err := utils.ToDoc(data)
62 | if err != nil {
63 | return &models.DBResponse{}, err
64 | }
65 |
66 | fmt.Println(data)
67 |
68 | obId, _ := primitive.ObjectIDFromHex(id)
69 |
70 | query := bson.D{{Key: "_id", Value: obId}}
71 | update := bson.D{{Key: "$set", Value: doc}}
72 | result := uc.collection.FindOneAndUpdate(uc.ctx, query, update, options.FindOneAndUpdate().SetReturnDocument(1))
73 |
74 | var updatedUser *models.DBResponse
75 | if err := result.Decode(&updatedUser); err != nil {
76 | return nil, errors.New("no document with that id exists")
77 | }
78 |
79 | return updatedUser, nil
80 | }
81 |
--------------------------------------------------------------------------------
/example.env:
--------------------------------------------------------------------------------
1 | PORT=8000
2 |
3 | GRPC_SERVER_ADDRESS=0.0.0.0:8080
4 |
5 | MONGO_INITDB_ROOT_USERNAME=root
6 | MONGO_INITDB_ROOT_PASSWORD=password123
7 |
8 | MONGODB_LOCAL_URI=mongodb://root:password123@localhost:6000
9 |
10 | REDIS_URL=localhost:6379
11 |
12 | CLIENT_ORIGIN=http://localhost:3000
13 |
14 | EMAIL_FROM=admin@admin.com
15 | SMTP_HOST=smtp.mailtrap.io
16 | SMTP_USER=
17 | SMTP_PASS=
18 | SMTP_PORT=587
19 |
20 |
21 | ACCESS_TOKEN_PRIVATE_KEY=LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlCUEFJQkFBSkJBTzVIKytVM0xrWC91SlRvRHhWN01CUURXSTdGU0l0VXNjbGFFKzlaUUg5Q2VpOGIxcUVmCnJxR0hSVDVWUis4c3UxVWtCUVpZTER3MnN3RTVWbjg5c0ZVQ0F3RUFBUUpCQUw4ZjRBMUlDSWEvQ2ZmdWR3TGMKNzRCdCtwOXg0TEZaZXMwdHdtV3Vha3hub3NaV0w4eVpSTUJpRmI4a25VL0hwb3piTnNxMmN1ZU9wKzVWdGRXNApiTlVDSVFENm9JdWxqcHdrZTFGY1VPaldnaXRQSjNnbFBma3NHVFBhdFYwYnJJVVI5d0loQVBOanJ1enB4ckhsCkUxRmJxeGtUNFZ5bWhCOU1HazU0Wk1jWnVjSmZOcjBUQWlFQWhML3UxOVZPdlVBWVd6Wjc3Y3JxMTdWSFBTcXoKUlhsZjd2TnJpdEg1ZGdjQ0lRRHR5QmFPdUxuNDlIOFIvZ2ZEZ1V1cjg3YWl5UHZ1YStxeEpXMzQrb0tFNXdJZwpQbG1KYXZsbW9jUG4rTkVRdGhLcTZuZFVYRGpXTTlTbktQQTVlUDZSUEs0PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ==
22 |
23 | ACCESS_TOKEN_PUBLIC_KEY=LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUZ3d0RRWUpLb1pJaHZjTkFRRUJCUUFEU3dBd1NBSkJBTzVIKytVM0xrWC91SlRvRHhWN01CUURXSTdGU0l0VQpzY2xhRSs5WlFIOUNlaThiMXFFZnJxR0hSVDVWUis4c3UxVWtCUVpZTER3MnN3RTVWbjg5c0ZVQ0F3RUFBUT09Ci0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQ==
24 | ACCESS_TOKEN_EXPIRED_IN=15m
25 | ACCESS_TOKEN_MAXAGE=15
26 |
27 |
28 | REFRESH_TOKEN_PRIVATE_KEY=LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlCT1FJQkFBSkJBSWFJcXZXeldCSndnYjR1SEhFQ01RdHFZMTI5b2F5RzVZMGlGcG51a0J1VHpRZVlQWkE4Cmx4OC9lTUh3Rys1MlJGR3VxMmE2N084d2s3TDR5dnY5dVY4Q0F3RUFBUUpBRUZ6aEJqOUk3LzAxR285N01CZUgKSlk5TUJLUEMzVHdQQVdwcSswL3p3UmE2ZkZtbXQ5NXNrN21qT3czRzNEZ3M5T2RTeWdsbTlVdndNWXh6SXFERAplUUloQVA5UStrMTBQbGxNd2ZJbDZtdjdTMFRYOGJDUlRaZVI1ZFZZb3FTeW40YmpBaUVBaHVUa2JtZ1NobFlZCnRyclNWZjN0QWZJcWNVUjZ3aDdMOXR5MVlvalZVRlVDSUhzOENlVHkwOWxrbkVTV0dvV09ZUEZVemhyc3Q2Z08KU3dKa2F2VFdKdndEQWlBdWhnVU8yeEFBaXZNdEdwUHVtb3hDam8zNjBMNXg4d012bWdGcEFYNW9uUUlnQzEvSwpNWG1heWtsaFRDeWtXRnpHMHBMWVdkNGRGdTI5M1M2ZUxJUlNIS009Ci0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0t
29 |
30 | REFRESH_TOKEN_PUBLIC_KEY=LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUZ3d0RRWUpLb1pJaHZjTkFRRUJCUUFEU3dBd1NBSkJBSWFJcXZXeldCSndnYjR1SEhFQ01RdHFZMTI5b2F5Rwo1WTBpRnBudWtCdVR6UWVZUFpBOGx4OC9lTUh3Rys1MlJGR3VxMmE2N084d2s3TDR5dnY5dVY4Q0F3RUFBUT09Ci0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQ==
31 |
32 | REFRESH_TOKEN_EXPIRED_IN=60m
33 | REFRESH_TOKEN_MAXAGE=60
34 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/wpcodevo/golang-mongodb
2 |
3 | go 1.18
4 |
5 | require (
6 | github.com/gin-contrib/cors v1.3.1
7 | github.com/gin-gonic/gin v1.7.7
8 | github.com/go-redis/redis/v8 v8.11.5
9 | github.com/golang-jwt/jwt v3.2.2+incompatible
10 | github.com/k3a/html2text v1.0.8
11 | github.com/spf13/viper v1.11.0
12 | github.com/thanhpk/randstr v1.0.4
13 | go.mongodb.org/mongo-driver v1.9.1
14 | golang.org/x/crypto v0.0.0-20220513210258-46612604a0f9
15 | google.golang.org/grpc v1.45.0
16 | google.golang.org/protobuf v1.28.0
17 | gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
18 | )
19 |
20 | require (
21 | github.com/cespare/xxhash/v2 v2.1.2 // indirect
22 | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
23 | github.com/fsnotify/fsnotify v1.5.1 // indirect
24 | github.com/gin-contrib/sse v0.1.0 // indirect
25 | github.com/go-playground/locales v0.14.0 // indirect
26 | github.com/go-playground/universal-translator v0.18.0 // indirect
27 | github.com/go-playground/validator/v10 v10.11.0 // indirect
28 | github.com/go-stack/stack v1.8.0 // indirect
29 | github.com/golang/protobuf v1.5.2 // indirect
30 | github.com/golang/snappy v0.0.1 // indirect
31 | github.com/hashicorp/hcl v1.0.0 // indirect
32 | github.com/json-iterator/go v1.1.12 // indirect
33 | github.com/klauspost/compress v1.13.6 // indirect
34 | github.com/leodido/go-urn v1.2.1 // indirect
35 | github.com/magiconair/properties v1.8.6 // indirect
36 | github.com/mattn/go-isatty v0.0.14 // indirect
37 | github.com/mitchellh/mapstructure v1.4.3 // indirect
38 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
39 | github.com/modern-go/reflect2 v1.0.2 // indirect
40 | github.com/pelletier/go-toml v1.9.4 // indirect
41 | github.com/pelletier/go-toml/v2 v2.0.0-beta.8 // indirect
42 | github.com/pkg/errors v0.9.1 // indirect
43 | github.com/spf13/afero v1.8.2 // indirect
44 | github.com/spf13/cast v1.4.1 // indirect
45 | github.com/spf13/jwalterweatherman v1.1.0 // indirect
46 | github.com/spf13/pflag v1.0.5 // indirect
47 | github.com/subosito/gotenv v1.2.0 // indirect
48 | github.com/ugorji/go/codec v1.2.7 // indirect
49 | github.com/xdg-go/pbkdf2 v1.0.0 // indirect
50 | github.com/xdg-go/scram v1.0.2 // indirect
51 | github.com/xdg-go/stringprep v1.0.2 // indirect
52 | github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
53 | golang.org/x/net v0.0.0-20220412020605-290c469a71a5 // indirect
54 | golang.org/x/sync v0.0.0-20201207232520-09787c993a3a // indirect
55 | golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a // indirect
56 | golang.org/x/text v0.3.7 // indirect
57 | google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac // indirect
58 | gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
59 | gopkg.in/ini.v1 v1.66.4 // indirect
60 | gopkg.in/yaml.v2 v2.4.0 // indirect
61 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
62 | )
63 |
--------------------------------------------------------------------------------
/cmd/client/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "log"
5 |
6 | "github.com/wpcodevo/golang-mongodb/client"
7 | "github.com/wpcodevo/golang-mongodb/pb"
8 | "google.golang.org/grpc"
9 | "google.golang.org/grpc/credentials/insecure"
10 | )
11 |
12 | const (
13 | address = "0.0.0.0:8080"
14 | )
15 |
16 | func main() {
17 | conn, err := grpc.Dial(address, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithBlock())
18 |
19 | if err != nil {
20 | log.Fatalf("failed to connect: %v", err)
21 | }
22 |
23 | defer conn.Close()
24 |
25 | // Sign Up
26 | if false {
27 | signUpUserClient := client.NewSignUpUserClient(conn)
28 | newUser := &pb.SignUpUserInput{
29 | Name: "Jane Smith",
30 | Email: "janesmith@gmail.com",
31 | Password: "password123",
32 | PasswordConfirm: "password123",
33 | }
34 | signUpUserClient.SignUpUser(newUser)
35 | }
36 |
37 | // Sign In
38 | if false {
39 | signInUserClient := client.NewSignInUserClient(conn)
40 |
41 | credentials := &pb.SignInUserInput{
42 | Email: "janesmith@gmail.com",
43 | Password: "password123",
44 | }
45 | signInUserClient.SignInUser(credentials)
46 | }
47 |
48 | // Get Me
49 | if false {
50 |
51 | getMeClient := client.NewGetMeClient(conn)
52 | id := &pb.GetMeRequest{
53 | Id: "628cffb91e50302d360c1a2c",
54 | }
55 | getMeClient.GetMeUser(id)
56 |
57 | }
58 |
59 | // List Posts
60 | if false {
61 | listPostsClient := client.NewListPostsClient(conn)
62 |
63 | var page int64 = 1
64 | var limit int64 = 10
65 | args := &pb.GetPostsRequest{
66 | Page: &page,
67 | Limit: &limit,
68 | }
69 |
70 | listPostsClient.ListPosts(args)
71 | }
72 |
73 | // Create Post
74 | if false {
75 | createPostClient := client.NewCreatePostClient(conn)
76 |
77 | args := &pb.CreatePostRequest{
78 | Title: "My second gRPC post with joy",
79 | Content: "It's always good to learn new technologies",
80 | User: "62908e0a42a608d5aeae2f64",
81 | Image: "default.png",
82 | }
83 |
84 | createPostClient.CreatePost(args)
85 | }
86 |
87 | // Update Post
88 | if false {
89 | updatePostClient := client.NewUpdatePostClient(conn)
90 |
91 | title := "My new updated title for my blog"
92 | args := &pb.UpdatePostRequest{
93 | Id: "629169e00a6c7cfd24e2129d",
94 | Title: &title,
95 | }
96 |
97 | updatePostClient.UpdatePost(args)
98 | }
99 |
100 | // Get Post
101 | if false {
102 | getPostClient := client.NewGetPostClient(conn)
103 |
104 | args := &pb.PostRequest{
105 | Id: "629169e00a6c7cfd24e2129d",
106 | }
107 |
108 | getPostClient.GetPost(args)
109 | }
110 |
111 | // Delete Post
112 | if false {
113 | deletePostClient := client.NewDeletePostClient(conn)
114 |
115 | args := &pb.PostRequest{
116 | Id: "629147ff3c92aed11d49394b",
117 | }
118 |
119 | deletePostClient.DeletePost(args)
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/controllers/post.controller.go:
--------------------------------------------------------------------------------
1 | package controllers
2 |
3 | import (
4 | "net/http"
5 | "strconv"
6 | "strings"
7 |
8 | "github.com/gin-gonic/gin"
9 | "github.com/wpcodevo/golang-mongodb/models"
10 | "github.com/wpcodevo/golang-mongodb/services"
11 | )
12 |
13 | type PostController struct {
14 | postService services.PostService
15 | }
16 |
17 | func NewPostController(postService services.PostService) PostController {
18 | return PostController{postService}
19 | }
20 |
21 | func (pc *PostController) CreatePost(ctx *gin.Context) {
22 | var post *models.CreatePostRequest
23 |
24 | if err := ctx.ShouldBindJSON(&post); err != nil {
25 | ctx.JSON(http.StatusBadRequest, err.Error())
26 | return
27 | }
28 |
29 | newPost, err := pc.postService.CreatePost(post)
30 |
31 | if err != nil {
32 | if strings.Contains(err.Error(), "title already exists") {
33 | ctx.JSON(http.StatusConflict, gin.H{"status": "fail", "message": err.Error()})
34 | return
35 | }
36 |
37 | ctx.JSON(http.StatusBadGateway, gin.H{"status": "fail", "message": err.Error()})
38 | return
39 | }
40 |
41 | ctx.JSON(http.StatusCreated, gin.H{"status": "success", "data": newPost})
42 | }
43 |
44 | func (pc *PostController) UpdatePost(ctx *gin.Context) {
45 | postId := ctx.Param("postId")
46 |
47 | var post *models.UpdatePost
48 | if err := ctx.ShouldBindJSON(&post); err != nil {
49 | ctx.JSON(http.StatusBadGateway, gin.H{"status": "fail", "message": err.Error()})
50 | return
51 | }
52 |
53 | updatedPost, err := pc.postService.UpdatePost(postId, post)
54 | if err != nil {
55 | if strings.Contains(err.Error(), "Id exists") {
56 | ctx.JSON(http.StatusNotFound, gin.H{"status": "fail", "message": err.Error()})
57 | return
58 | }
59 | ctx.JSON(http.StatusBadGateway, gin.H{"status": "fail", "message": err.Error()})
60 | return
61 | }
62 |
63 | ctx.JSON(http.StatusOK, gin.H{"status": "success", "data": updatedPost})
64 | }
65 |
66 | func (pc *PostController) FindPostById(ctx *gin.Context) {
67 | postId := ctx.Param("postId")
68 |
69 | post, err := pc.postService.FindPostById(postId)
70 |
71 | if err != nil {
72 | ctx.JSON(http.StatusBadGateway, gin.H{"status": "fail", "message": err.Error()})
73 | return
74 | }
75 |
76 | ctx.JSON(http.StatusOK, gin.H{"status": "success", "data": post})
77 | }
78 |
79 | func (pc *PostController) FindPosts(ctx *gin.Context) {
80 | var page = ctx.DefaultQuery("page", "1")
81 | var limit = ctx.DefaultQuery("limit", "10")
82 |
83 | intPage, err := strconv.Atoi(page)
84 | if err != nil {
85 | ctx.JSON(http.StatusBadGateway, gin.H{"status": "fail", "message": err.Error()})
86 | return
87 | }
88 |
89 | intLimit, err := strconv.Atoi(limit)
90 | if err != nil {
91 | ctx.JSON(http.StatusBadGateway, gin.H{"status": "fail", "message": err.Error()})
92 | return
93 | }
94 |
95 | posts, err := pc.postService.FindPosts(intPage, intLimit)
96 | if err != nil {
97 | ctx.JSON(http.StatusBadGateway, gin.H{"status": "fail", "message": err.Error()})
98 | return
99 | }
100 |
101 | ctx.JSON(http.StatusOK, gin.H{"status": "success", "results": len(posts), "data": posts})
102 | }
103 |
104 | func (pc *PostController) DeletePost(ctx *gin.Context) {
105 | postId := ctx.Param("postId")
106 |
107 | err := pc.postService.DeletePost(postId)
108 |
109 | if err != nil {
110 | if strings.Contains(err.Error(), "Id exists") {
111 | ctx.JSON(http.StatusNotFound, gin.H{"status": "fail", "message": err.Error()})
112 | return
113 | }
114 | ctx.JSON(http.StatusBadGateway, gin.H{"status": "fail", "message": err.Error()})
115 | return
116 | }
117 |
118 | ctx.JSON(http.StatusNoContent, nil)
119 | }
120 |
--------------------------------------------------------------------------------
/pb/user_service_grpc.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-go-grpc. DO NOT EDIT.
2 | // versions:
3 | // - protoc-gen-go-grpc v1.2.0
4 | // - protoc v3.20.1
5 | // source: user_service.proto
6 |
7 | package pb
8 |
9 | import (
10 | context "context"
11 | grpc "google.golang.org/grpc"
12 | codes "google.golang.org/grpc/codes"
13 | status "google.golang.org/grpc/status"
14 | )
15 |
16 | // This is a compile-time assertion to ensure that this generated file
17 | // is compatible with the grpc package it is being compiled against.
18 | // Requires gRPC-Go v1.32.0 or later.
19 | const _ = grpc.SupportPackageIsVersion7
20 |
21 | // UserServiceClient is the client API for UserService service.
22 | //
23 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
24 | type UserServiceClient interface {
25 | GetMe(ctx context.Context, in *GetMeRequest, opts ...grpc.CallOption) (*UserResponse, error)
26 | }
27 |
28 | type userServiceClient struct {
29 | cc grpc.ClientConnInterface
30 | }
31 |
32 | func NewUserServiceClient(cc grpc.ClientConnInterface) UserServiceClient {
33 | return &userServiceClient{cc}
34 | }
35 |
36 | func (c *userServiceClient) GetMe(ctx context.Context, in *GetMeRequest, opts ...grpc.CallOption) (*UserResponse, error) {
37 | out := new(UserResponse)
38 | err := c.cc.Invoke(ctx, "/pb.UserService/GetMe", in, out, opts...)
39 | if err != nil {
40 | return nil, err
41 | }
42 | return out, nil
43 | }
44 |
45 | // UserServiceServer is the server API for UserService service.
46 | // All implementations must embed UnimplementedUserServiceServer
47 | // for forward compatibility
48 | type UserServiceServer interface {
49 | GetMe(context.Context, *GetMeRequest) (*UserResponse, error)
50 | mustEmbedUnimplementedUserServiceServer()
51 | }
52 |
53 | // UnimplementedUserServiceServer must be embedded to have forward compatible implementations.
54 | type UnimplementedUserServiceServer struct {
55 | }
56 |
57 | func (UnimplementedUserServiceServer) GetMe(context.Context, *GetMeRequest) (*UserResponse, error) {
58 | return nil, status.Errorf(codes.Unimplemented, "method GetMe not implemented")
59 | }
60 | func (UnimplementedUserServiceServer) mustEmbedUnimplementedUserServiceServer() {}
61 |
62 | // UnsafeUserServiceServer may be embedded to opt out of forward compatibility for this service.
63 | // Use of this interface is not recommended, as added methods to UserServiceServer will
64 | // result in compilation errors.
65 | type UnsafeUserServiceServer interface {
66 | mustEmbedUnimplementedUserServiceServer()
67 | }
68 |
69 | func RegisterUserServiceServer(s grpc.ServiceRegistrar, srv UserServiceServer) {
70 | s.RegisterService(&UserService_ServiceDesc, srv)
71 | }
72 |
73 | func _UserService_GetMe_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
74 | in := new(GetMeRequest)
75 | if err := dec(in); err != nil {
76 | return nil, err
77 | }
78 | if interceptor == nil {
79 | return srv.(UserServiceServer).GetMe(ctx, in)
80 | }
81 | info := &grpc.UnaryServerInfo{
82 | Server: srv,
83 | FullMethod: "/pb.UserService/GetMe",
84 | }
85 | handler := func(ctx context.Context, req interface{}) (interface{}, error) {
86 | return srv.(UserServiceServer).GetMe(ctx, req.(*GetMeRequest))
87 | }
88 | return interceptor(ctx, in, info, handler)
89 | }
90 |
91 | // UserService_ServiceDesc is the grpc.ServiceDesc for UserService service.
92 | // It's only intended for direct use with grpc.RegisterService,
93 | // and not to be introspected or modified (even as a copy)
94 | var UserService_ServiceDesc = grpc.ServiceDesc{
95 | ServiceName: "pb.UserService",
96 | HandlerType: (*UserServiceServer)(nil),
97 | Methods: []grpc.MethodDesc{
98 | {
99 | MethodName: "GetMe",
100 | Handler: _UserService_GetMe_Handler,
101 | },
102 | },
103 | Streams: []grpc.StreamDesc{},
104 | Metadata: "user_service.proto",
105 | }
106 |
--------------------------------------------------------------------------------
/services/post.service.impl.go:
--------------------------------------------------------------------------------
1 | package services
2 |
3 | import (
4 | "context"
5 | "errors"
6 | "time"
7 |
8 | "github.com/wpcodevo/golang-mongodb/models"
9 | "github.com/wpcodevo/golang-mongodb/utils"
10 | "go.mongodb.org/mongo-driver/bson"
11 | "go.mongodb.org/mongo-driver/bson/primitive"
12 | "go.mongodb.org/mongo-driver/mongo"
13 | "go.mongodb.org/mongo-driver/mongo/options"
14 | )
15 |
16 | type PostServiceImpl struct {
17 | postCollection *mongo.Collection
18 | ctx context.Context
19 | }
20 |
21 | func NewPostService(postCollection *mongo.Collection, ctx context.Context) PostService {
22 | return &PostServiceImpl{postCollection, ctx}
23 | }
24 |
25 | func (p *PostServiceImpl) CreatePost(post *models.CreatePostRequest) (*models.DBPost, error) {
26 | post.CreateAt = time.Now()
27 | post.UpdatedAt = post.CreateAt
28 | res, err := p.postCollection.InsertOne(p.ctx, post)
29 |
30 | if err != nil {
31 | if er, ok := err.(mongo.WriteException); ok && er.WriteErrors[0].Code == 11000 {
32 | return nil, errors.New("post with that title already exists")
33 | }
34 | return nil, err
35 | }
36 |
37 | opt := options.Index()
38 | opt.SetUnique(true)
39 |
40 | index := mongo.IndexModel{Keys: bson.M{"title": 1}, Options: opt}
41 |
42 | if _, err := p.postCollection.Indexes().CreateOne(p.ctx, index); err != nil {
43 | return nil, errors.New("could not create index for title")
44 | }
45 |
46 | var newPost *models.DBPost
47 | query := bson.M{"_id": res.InsertedID}
48 | if err = p.postCollection.FindOne(p.ctx, query).Decode(&newPost); err != nil {
49 | return nil, err
50 | }
51 |
52 | return newPost, nil
53 | }
54 |
55 | func (p *PostServiceImpl) UpdatePost(id string, data *models.UpdatePost) (*models.DBPost, error) {
56 | doc, err := utils.ToDoc(data)
57 | if err != nil {
58 | return nil, err
59 | }
60 |
61 | obId, _ := primitive.ObjectIDFromHex(id)
62 | query := bson.D{{Key: "_id", Value: obId}}
63 | update := bson.D{{Key: "$set", Value: doc}}
64 | res := p.postCollection.FindOneAndUpdate(p.ctx, query, update, options.FindOneAndUpdate().SetReturnDocument(1))
65 |
66 | var updatedPost *models.DBPost
67 | if err := res.Decode(&updatedPost); err != nil {
68 | return nil, errors.New("no post with that Id exists")
69 | }
70 |
71 | return updatedPost, nil
72 | }
73 |
74 | func (p *PostServiceImpl) FindPostById(id string) (*models.DBPost, error) {
75 | obId, _ := primitive.ObjectIDFromHex(id)
76 |
77 | query := bson.M{"_id": obId}
78 |
79 | var post *models.DBPost
80 |
81 | if err := p.postCollection.FindOne(p.ctx, query).Decode(&post); err != nil {
82 | if err == mongo.ErrNoDocuments {
83 | return nil, errors.New("no document with that Id exists")
84 | }
85 |
86 | return nil, err
87 | }
88 |
89 | return post, nil
90 | }
91 |
92 | func (p *PostServiceImpl) FindPosts(page int, limit int) ([]*models.DBPost, error) {
93 | if page == 0 {
94 | page = 1
95 | }
96 |
97 | if limit == 0 {
98 | limit = 10
99 | }
100 |
101 | skip := (page - 1) * limit
102 |
103 | opt := options.FindOptions{}
104 | opt.SetLimit(int64(limit))
105 | opt.SetSkip(int64(skip))
106 | opt.SetSort(bson.M{"created_at": -1})
107 |
108 | query := bson.M{}
109 |
110 | cursor, err := p.postCollection.Find(p.ctx, query, &opt)
111 | if err != nil {
112 | return nil, err
113 | }
114 |
115 | defer cursor.Close(p.ctx)
116 |
117 | var posts []*models.DBPost
118 |
119 | for cursor.Next(p.ctx) {
120 | post := &models.DBPost{}
121 | err := cursor.Decode(post)
122 |
123 | if err != nil {
124 | return nil, err
125 | }
126 |
127 | posts = append(posts, post)
128 | }
129 |
130 | if err := cursor.Err(); err != nil {
131 | return nil, err
132 | }
133 |
134 | if len(posts) == 0 {
135 | return []*models.DBPost{}, nil
136 | }
137 |
138 | return posts, nil
139 | }
140 |
141 | func (p *PostServiceImpl) DeletePost(id string) error {
142 | obId, _ := primitive.ObjectIDFromHex(id)
143 | query := bson.M{"_id": obId}
144 |
145 | res, err := p.postCollection.DeleteOne(p.ctx, query)
146 | if err != nil {
147 | return err
148 | }
149 |
150 | if res.DeletedCount == 0 {
151 | return errors.New("no document with that Id exists")
152 | }
153 |
154 | return nil
155 | }
156 |
--------------------------------------------------------------------------------
/models/user.model.go:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import (
4 | "time"
5 |
6 | "go.mongodb.org/mongo-driver/bson/primitive"
7 | )
8 |
9 | // 👈 SignUpInput struct
10 | type SignUpInput struct {
11 | Name string `json:"name" bson:"name" binding:"required"`
12 | Email string `json:"email" bson:"email" binding:"required"`
13 | Password string `json:"password" bson:"password" binding:"required,min=8"`
14 | PasswordConfirm string `json:"passwordConfirm" bson:"passwordConfirm,omitempty" binding:"required"`
15 | Role string `json:"role" bson:"role"`
16 | VerificationCode string `json:"verificationCode,omitempty" bson:"verificationCode,omitempty"`
17 | ResetPasswordToken string `json:"resetPasswordToken,omitempty" bson:"resetPasswordToken,omitempty"`
18 | ResetPasswordAt time.Time `json:"resetPasswordAt,omitempty" bson:"resetPasswordAt,omitempty"`
19 | Verified bool `json:"verified" bson:"verified"`
20 | CreatedAt time.Time `json:"created_at" bson:"created_at"`
21 | UpdatedAt time.Time `json:"updated_at" bson:"updated_at"`
22 | }
23 |
24 | // 👈 SignInInput struct
25 | type SignInInput struct {
26 | Email string `json:"email" bson:"email" binding:"required"`
27 | Password string `json:"password" bson:"password" binding:"required"`
28 | }
29 |
30 | // 👈 DBResponse struct
31 | type DBResponse struct {
32 | ID primitive.ObjectID `json:"id" bson:"_id"`
33 | Name string `json:"name" bson:"name"`
34 | Email string `json:"email" bson:"email"`
35 | Password string `json:"password" bson:"password"`
36 | PasswordConfirm string `json:"passwordConfirm,omitempty" bson:"passwordConfirm,omitempty"`
37 | Role string `json:"role" bson:"role"`
38 | VerificationCode string `json:"verificationCode,omitempty" bson:"verificationCode"`
39 | ResetPasswordToken string `json:"resetPasswordToken,omitempty" bson:"resetPasswordToken,omitempty"`
40 | ResetPasswordAt time.Time `json:"resetPasswordAt,omitempty" bson:"resetPasswordAt,omitempty"`
41 | Verified bool `json:"verified" bson:"verified"`
42 | CreatedAt time.Time `json:"created_at" bson:"created_at"`
43 | UpdatedAt time.Time `json:"updated_at" bson:"updated_at"`
44 | }
45 |
46 | type UpdateInput struct {
47 | Name string `json:"name,omitempty" bson:"name,omitempty"`
48 | Email string `json:"email,omitempty" bson:"email,omitempty"`
49 | Password string `json:"password,omitempty" bson:"password,omitempty"`
50 | Role string `json:"role,omitempty" bson:"role,omitempty"`
51 | VerificationCode string `json:"verificationCode,omitempty" bson:"verificationCode,omitempty"`
52 | ResetPasswordToken string `json:"resetPasswordToken,omitempty" bson:"resetPasswordToken,omitempty"`
53 | ResetPasswordAt time.Time `json:"resetPasswordAt,omitempty" bson:"resetPasswordAt,omitempty"`
54 | Verified bool `json:"verified,omitempty" bson:"verified,omitempty"`
55 | CreatedAt time.Time `json:"created_at,omitempty" bson:"created_at,omitempty"`
56 | UpdatedAt time.Time `json:"updated_at,omitempty" bson:"updated_at,omitempty"`
57 | }
58 |
59 | // 👈 UserResponse struct
60 | type UserResponse struct {
61 | ID primitive.ObjectID `json:"id,omitempty" bson:"_id,omitempty"`
62 | Name string `json:"name,omitempty" bson:"name,omitempty"`
63 | Email string `json:"email,omitempty" bson:"email,omitempty"`
64 | Role string `json:"role,omitempty" bson:"role,omitempty"`
65 | CreatedAt time.Time `json:"created_at" bson:"created_at"`
66 | UpdatedAt time.Time `json:"updated_at" bson:"updated_at"`
67 | }
68 |
69 | // 👈 ForgotPasswordInput struct
70 | type ForgotPasswordInput struct {
71 | Email string `json:"email" bson:"email" binding:"required"`
72 | }
73 |
74 | // 👈 ResetPasswordInput struct
75 | type ResetPasswordInput struct {
76 | Password string `json:"password" bson:"password"`
77 | PasswordConfirm string `json:"passwordConfirm,omitempty" bson:"passwordConfirm,omitempty"`
78 | }
79 |
80 | func FilteredResponse(user *DBResponse) UserResponse {
81 | return UserResponse{
82 | ID: user.ID,
83 | Email: user.Email,
84 | Name: user.Name,
85 | Role: user.Role,
86 | CreatedAt: user.CreatedAt,
87 | UpdatedAt: user.UpdatedAt,
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/pb/user_service.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-go. DO NOT EDIT.
2 | // versions:
3 | // protoc-gen-go v1.28.0
4 | // protoc v3.20.1
5 | // source: user_service.proto
6 |
7 | package pb
8 |
9 | import (
10 | protoreflect "google.golang.org/protobuf/reflect/protoreflect"
11 | protoimpl "google.golang.org/protobuf/runtime/protoimpl"
12 | reflect "reflect"
13 | sync "sync"
14 | )
15 |
16 | const (
17 | // Verify that this generated code is sufficiently up-to-date.
18 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
19 | // Verify that runtime/protoimpl is sufficiently up-to-date.
20 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
21 | )
22 |
23 | type GetMeRequest struct {
24 | state protoimpl.MessageState
25 | sizeCache protoimpl.SizeCache
26 | unknownFields protoimpl.UnknownFields
27 |
28 | Id string `protobuf:"bytes,1,opt,name=Id,proto3" json:"Id,omitempty"`
29 | }
30 |
31 | func (x *GetMeRequest) Reset() {
32 | *x = GetMeRequest{}
33 | if protoimpl.UnsafeEnabled {
34 | mi := &file_user_service_proto_msgTypes[0]
35 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
36 | ms.StoreMessageInfo(mi)
37 | }
38 | }
39 |
40 | func (x *GetMeRequest) String() string {
41 | return protoimpl.X.MessageStringOf(x)
42 | }
43 |
44 | func (*GetMeRequest) ProtoMessage() {}
45 |
46 | func (x *GetMeRequest) ProtoReflect() protoreflect.Message {
47 | mi := &file_user_service_proto_msgTypes[0]
48 | if protoimpl.UnsafeEnabled && x != nil {
49 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
50 | if ms.LoadMessageInfo() == nil {
51 | ms.StoreMessageInfo(mi)
52 | }
53 | return ms
54 | }
55 | return mi.MessageOf(x)
56 | }
57 |
58 | // Deprecated: Use GetMeRequest.ProtoReflect.Descriptor instead.
59 | func (*GetMeRequest) Descriptor() ([]byte, []int) {
60 | return file_user_service_proto_rawDescGZIP(), []int{0}
61 | }
62 |
63 | func (x *GetMeRequest) GetId() string {
64 | if x != nil {
65 | return x.Id
66 | }
67 | return ""
68 | }
69 |
70 | var File_user_service_proto protoreflect.FileDescriptor
71 |
72 | var file_user_service_proto_rawDesc = []byte{
73 | 0x0a, 0x12, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70,
74 | 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x70, 0x62, 0x1a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x70,
75 | 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x1e, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x52, 0x65, 0x71,
76 | 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
77 | 0x52, 0x02, 0x49, 0x64, 0x32, 0x3c, 0x0a, 0x0b, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76,
78 | 0x69, 0x63, 0x65, 0x12, 0x2d, 0x0a, 0x05, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x12, 0x10, 0x2e, 0x70,
79 | 0x62, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10,
80 | 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
81 | 0x22, 0x00, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
82 | 0x2f, 0x77, 0x70, 0x63, 0x6f, 0x64, 0x65, 0x76, 0x6f, 0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67,
83 | 0x2d, 0x6d, 0x6f, 0x6e, 0x67, 0x6f, 0x64, 0x62, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f,
84 | 0x74, 0x6f, 0x33,
85 | }
86 |
87 | var (
88 | file_user_service_proto_rawDescOnce sync.Once
89 | file_user_service_proto_rawDescData = file_user_service_proto_rawDesc
90 | )
91 |
92 | func file_user_service_proto_rawDescGZIP() []byte {
93 | file_user_service_proto_rawDescOnce.Do(func() {
94 | file_user_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_user_service_proto_rawDescData)
95 | })
96 | return file_user_service_proto_rawDescData
97 | }
98 |
99 | var file_user_service_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
100 | var file_user_service_proto_goTypes = []interface{}{
101 | (*GetMeRequest)(nil), // 0: pb.GetMeRequest
102 | (*UserResponse)(nil), // 1: pb.UserResponse
103 | }
104 | var file_user_service_proto_depIdxs = []int32{
105 | 0, // 0: pb.UserService.GetMe:input_type -> pb.GetMeRequest
106 | 1, // 1: pb.UserService.GetMe:output_type -> pb.UserResponse
107 | 1, // [1:2] is the sub-list for method output_type
108 | 0, // [0:1] is the sub-list for method input_type
109 | 0, // [0:0] is the sub-list for extension type_name
110 | 0, // [0:0] is the sub-list for extension extendee
111 | 0, // [0:0] is the sub-list for field type_name
112 | }
113 |
114 | func init() { file_user_service_proto_init() }
115 | func file_user_service_proto_init() {
116 | if File_user_service_proto != nil {
117 | return
118 | }
119 | file_user_proto_init()
120 | if !protoimpl.UnsafeEnabled {
121 | file_user_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
122 | switch v := v.(*GetMeRequest); i {
123 | case 0:
124 | return &v.state
125 | case 1:
126 | return &v.sizeCache
127 | case 2:
128 | return &v.unknownFields
129 | default:
130 | return nil
131 | }
132 | }
133 | }
134 | type x struct{}
135 | out := protoimpl.TypeBuilder{
136 | File: protoimpl.DescBuilder{
137 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
138 | RawDescriptor: file_user_service_proto_rawDesc,
139 | NumEnums: 0,
140 | NumMessages: 1,
141 | NumExtensions: 0,
142 | NumServices: 1,
143 | },
144 | GoTypes: file_user_service_proto_goTypes,
145 | DependencyIndexes: file_user_service_proto_depIdxs,
146 | MessageInfos: file_user_service_proto_msgTypes,
147 | }.Build()
148 | File_user_service_proto = out.File
149 | file_user_service_proto_rawDesc = nil
150 | file_user_service_proto_goTypes = nil
151 | file_user_service_proto_depIdxs = nil
152 | }
153 |
--------------------------------------------------------------------------------
/cmd/server/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "context"
5 | "fmt"
6 | "log"
7 | "net"
8 | "net/http"
9 |
10 | "github.com/gin-contrib/cors"
11 | "github.com/gin-gonic/gin"
12 | "github.com/go-redis/redis/v8"
13 | "github.com/wpcodevo/golang-mongodb/config"
14 | "github.com/wpcodevo/golang-mongodb/controllers"
15 | "github.com/wpcodevo/golang-mongodb/gapi"
16 | "github.com/wpcodevo/golang-mongodb/pb"
17 | "github.com/wpcodevo/golang-mongodb/routes"
18 | "github.com/wpcodevo/golang-mongodb/services"
19 | "go.mongodb.org/mongo-driver/mongo"
20 | "go.mongodb.org/mongo-driver/mongo/options"
21 | "go.mongodb.org/mongo-driver/mongo/readpref"
22 | "google.golang.org/grpc"
23 | "google.golang.org/grpc/reflection"
24 | )
25 |
26 | var (
27 | server *gin.Engine
28 | ctx context.Context
29 | mongoclient *mongo.Client
30 | redisclient *redis.Client
31 |
32 | userService services.UserService
33 | UserController controllers.UserController
34 | UserRouteController routes.UserRouteController
35 |
36 | authCollection *mongo.Collection
37 | authService services.AuthService
38 | AuthController controllers.AuthController
39 | AuthRouteController routes.AuthRouteController
40 |
41 | // 👇 Create the Post Variables
42 | postService services.PostService
43 | PostController controllers.PostController
44 | postCollection *mongo.Collection
45 | PostRouteController routes.PostRouteController
46 | )
47 |
48 | func init() {
49 | config, err := config.LoadConfig(".")
50 | if err != nil {
51 | log.Fatal("Could not load environment variables", err)
52 | }
53 |
54 | ctx = context.TODO()
55 |
56 | // Connect to MongoDB
57 | mongoconn := options.Client().ApplyURI(config.DBUri)
58 | mongoclient, err := mongo.Connect(ctx, mongoconn)
59 |
60 | if err != nil {
61 | panic(err)
62 | }
63 |
64 | if err := mongoclient.Ping(ctx, readpref.Primary()); err != nil {
65 | panic(err)
66 | }
67 |
68 | fmt.Println("MongoDB successfully connected...")
69 |
70 | // Connect to Redis
71 | redisclient = redis.NewClient(&redis.Options{
72 | Addr: config.RedisUri,
73 | })
74 |
75 | if _, err := redisclient.Ping(ctx).Result(); err != nil {
76 | panic(err)
77 | }
78 |
79 | err = redisclient.Set(ctx, "test", "Welcome to Golang with Redis and MongoDB", 0).Err()
80 | if err != nil {
81 | panic(err)
82 | }
83 |
84 | fmt.Println("Redis client connected successfully...")
85 |
86 | // Collections
87 | authCollection = mongoclient.Database("golang_mongodb").Collection("users")
88 | userService = services.NewUserServiceImpl(authCollection, ctx)
89 | authService = services.NewAuthService(authCollection, ctx)
90 | AuthController = controllers.NewAuthController(authService, userService, ctx, authCollection)
91 | AuthRouteController = routes.NewAuthRouteController(AuthController)
92 |
93 | UserController = controllers.NewUserController(userService)
94 | UserRouteController = routes.NewRouteUserController(UserController)
95 |
96 | // 👇 Instantiate the Constructors
97 | postCollection = mongoclient.Database("golang_mongodb").Collection("posts")
98 | postService = services.NewPostService(postCollection, ctx)
99 | PostController = controllers.NewPostController(postService)
100 | PostRouteController = routes.NewPostControllerRoute(PostController)
101 |
102 | server = gin.Default()
103 | }
104 |
105 | func main() {
106 | config, err := config.LoadConfig(".")
107 |
108 | if err != nil {
109 | log.Fatal("Could not load config", err)
110 | }
111 |
112 | defer mongoclient.Disconnect(ctx)
113 |
114 | // startGinServer(config)
115 | startGrpcServer(config)
116 | }
117 |
118 | func startGrpcServer(config config.Config) {
119 | authServer, err := gapi.NewGrpcAuthServer(config, authService, userService, authCollection)
120 | if err != nil {
121 | log.Fatal("cannot create grpc authServer: ", err)
122 | }
123 |
124 | userServer, err := gapi.NewGrpcUserServer(config, userService, authCollection)
125 | if err != nil {
126 | log.Fatal("cannot create grpc userServer: ", err)
127 | }
128 |
129 | postServer, err := gapi.NewGrpcPostServer(postCollection, postService)
130 | if err != nil {
131 | log.Fatal("cannot create grpc postServer: ", err)
132 | }
133 |
134 | grpcServer := grpc.NewServer()
135 |
136 | pb.RegisterAuthServiceServer(grpcServer, authServer)
137 | pb.RegisterUserServiceServer(grpcServer, userServer)
138 | // 👇 Register the Post gRPC service
139 | pb.RegisterPostServiceServer(grpcServer, postServer)
140 | reflection.Register(grpcServer)
141 |
142 | listener, err := net.Listen("tcp", config.GrpcServerAddress)
143 | if err != nil {
144 | log.Fatal("cannot create grpc server: ", err)
145 | }
146 |
147 | log.Printf("start gRPC server on %s", listener.Addr().String())
148 | err = grpcServer.Serve(listener)
149 | if err != nil {
150 | log.Fatal("cannot create grpc server: ", err)
151 | }
152 | }
153 |
154 | func startGinServer(config config.Config) {
155 | value, err := redisclient.Get(ctx, "test").Result()
156 |
157 | if err == redis.Nil {
158 | fmt.Println("key: test does not exist")
159 | } else if err != nil {
160 | panic(err)
161 | }
162 |
163 | corsConfig := cors.DefaultConfig()
164 | corsConfig.AllowOrigins = []string{config.Origin}
165 | corsConfig.AllowCredentials = true
166 |
167 | server.Use(cors.New(corsConfig))
168 |
169 | router := server.Group("/api")
170 | router.GET("/healthchecker", func(ctx *gin.Context) {
171 | ctx.JSON(http.StatusOK, gin.H{"status": "success", "message": value})
172 | })
173 |
174 | AuthRouteController.AuthRoute(router, userService)
175 | UserRouteController.UserRoute(router, userService)
176 | // 👇 Post Route
177 | PostRouteController.PostRoute(router)
178 | log.Fatal(server.Run(":" + config.Port))
179 | }
180 |
--------------------------------------------------------------------------------
/pb/rpc_create_post.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-go. DO NOT EDIT.
2 | // versions:
3 | // protoc-gen-go v1.28.0
4 | // protoc v3.20.1
5 | // source: rpc_create_post.proto
6 |
7 | package pb
8 |
9 | import (
10 | protoreflect "google.golang.org/protobuf/reflect/protoreflect"
11 | protoimpl "google.golang.org/protobuf/runtime/protoimpl"
12 | reflect "reflect"
13 | sync "sync"
14 | )
15 |
16 | const (
17 | // Verify that this generated code is sufficiently up-to-date.
18 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
19 | // Verify that runtime/protoimpl is sufficiently up-to-date.
20 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
21 | )
22 |
23 | type CreatePostRequest struct {
24 | state protoimpl.MessageState
25 | sizeCache protoimpl.SizeCache
26 | unknownFields protoimpl.UnknownFields
27 |
28 | Title string `protobuf:"bytes,1,opt,name=Title,proto3" json:"Title,omitempty"`
29 | Content string `protobuf:"bytes,2,opt,name=Content,proto3" json:"Content,omitempty"`
30 | Image string `protobuf:"bytes,3,opt,name=Image,proto3" json:"Image,omitempty"`
31 | User string `protobuf:"bytes,4,opt,name=User,proto3" json:"User,omitempty"`
32 | }
33 |
34 | func (x *CreatePostRequest) Reset() {
35 | *x = CreatePostRequest{}
36 | if protoimpl.UnsafeEnabled {
37 | mi := &file_rpc_create_post_proto_msgTypes[0]
38 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
39 | ms.StoreMessageInfo(mi)
40 | }
41 | }
42 |
43 | func (x *CreatePostRequest) String() string {
44 | return protoimpl.X.MessageStringOf(x)
45 | }
46 |
47 | func (*CreatePostRequest) ProtoMessage() {}
48 |
49 | func (x *CreatePostRequest) ProtoReflect() protoreflect.Message {
50 | mi := &file_rpc_create_post_proto_msgTypes[0]
51 | if protoimpl.UnsafeEnabled && x != nil {
52 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
53 | if ms.LoadMessageInfo() == nil {
54 | ms.StoreMessageInfo(mi)
55 | }
56 | return ms
57 | }
58 | return mi.MessageOf(x)
59 | }
60 |
61 | // Deprecated: Use CreatePostRequest.ProtoReflect.Descriptor instead.
62 | func (*CreatePostRequest) Descriptor() ([]byte, []int) {
63 | return file_rpc_create_post_proto_rawDescGZIP(), []int{0}
64 | }
65 |
66 | func (x *CreatePostRequest) GetTitle() string {
67 | if x != nil {
68 | return x.Title
69 | }
70 | return ""
71 | }
72 |
73 | func (x *CreatePostRequest) GetContent() string {
74 | if x != nil {
75 | return x.Content
76 | }
77 | return ""
78 | }
79 |
80 | func (x *CreatePostRequest) GetImage() string {
81 | if x != nil {
82 | return x.Image
83 | }
84 | return ""
85 | }
86 |
87 | func (x *CreatePostRequest) GetUser() string {
88 | if x != nil {
89 | return x.User
90 | }
91 | return ""
92 | }
93 |
94 | var File_rpc_create_post_proto protoreflect.FileDescriptor
95 |
96 | var file_rpc_create_post_proto_rawDesc = []byte{
97 | 0x0a, 0x15, 0x72, 0x70, 0x63, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x6f, 0x73,
98 | 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x70, 0x62, 0x22, 0x6d, 0x0a, 0x11, 0x43,
99 | 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
100 | 0x12, 0x14, 0x0a, 0x05, 0x54, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
101 | 0x05, 0x54, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e,
102 | 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74,
103 | 0x12, 0x14, 0x0a, 0x05, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
104 | 0x05, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x18, 0x04,
105 | 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x55, 0x73, 0x65, 0x72, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69,
106 | 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x70, 0x63, 0x6f, 0x64, 0x65, 0x76,
107 | 0x6f, 0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2d, 0x6d, 0x6f, 0x6e, 0x67, 0x6f, 0x64, 0x62,
108 | 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
109 | }
110 |
111 | var (
112 | file_rpc_create_post_proto_rawDescOnce sync.Once
113 | file_rpc_create_post_proto_rawDescData = file_rpc_create_post_proto_rawDesc
114 | )
115 |
116 | func file_rpc_create_post_proto_rawDescGZIP() []byte {
117 | file_rpc_create_post_proto_rawDescOnce.Do(func() {
118 | file_rpc_create_post_proto_rawDescData = protoimpl.X.CompressGZIP(file_rpc_create_post_proto_rawDescData)
119 | })
120 | return file_rpc_create_post_proto_rawDescData
121 | }
122 |
123 | var file_rpc_create_post_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
124 | var file_rpc_create_post_proto_goTypes = []interface{}{
125 | (*CreatePostRequest)(nil), // 0: pb.CreatePostRequest
126 | }
127 | var file_rpc_create_post_proto_depIdxs = []int32{
128 | 0, // [0:0] is the sub-list for method output_type
129 | 0, // [0:0] is the sub-list for method input_type
130 | 0, // [0:0] is the sub-list for extension type_name
131 | 0, // [0:0] is the sub-list for extension extendee
132 | 0, // [0:0] is the sub-list for field type_name
133 | }
134 |
135 | func init() { file_rpc_create_post_proto_init() }
136 | func file_rpc_create_post_proto_init() {
137 | if File_rpc_create_post_proto != nil {
138 | return
139 | }
140 | if !protoimpl.UnsafeEnabled {
141 | file_rpc_create_post_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
142 | switch v := v.(*CreatePostRequest); i {
143 | case 0:
144 | return &v.state
145 | case 1:
146 | return &v.sizeCache
147 | case 2:
148 | return &v.unknownFields
149 | default:
150 | return nil
151 | }
152 | }
153 | }
154 | type x struct{}
155 | out := protoimpl.TypeBuilder{
156 | File: protoimpl.DescBuilder{
157 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
158 | RawDescriptor: file_rpc_create_post_proto_rawDesc,
159 | NumEnums: 0,
160 | NumMessages: 1,
161 | NumExtensions: 0,
162 | NumServices: 0,
163 | },
164 | GoTypes: file_rpc_create_post_proto_goTypes,
165 | DependencyIndexes: file_rpc_create_post_proto_depIdxs,
166 | MessageInfos: file_rpc_create_post_proto_msgTypes,
167 | }.Build()
168 | File_rpc_create_post_proto = out.File
169 | file_rpc_create_post_proto_rawDesc = nil
170 | file_rpc_create_post_proto_goTypes = nil
171 | file_rpc_create_post_proto_depIdxs = nil
172 | }
173 |
--------------------------------------------------------------------------------
/pb/rpc_update_post.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-go. DO NOT EDIT.
2 | // versions:
3 | // protoc-gen-go v1.28.0
4 | // protoc v3.20.1
5 | // source: rpc_update_post.proto
6 |
7 | package pb
8 |
9 | import (
10 | protoreflect "google.golang.org/protobuf/reflect/protoreflect"
11 | protoimpl "google.golang.org/protobuf/runtime/protoimpl"
12 | reflect "reflect"
13 | sync "sync"
14 | )
15 |
16 | const (
17 | // Verify that this generated code is sufficiently up-to-date.
18 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
19 | // Verify that runtime/protoimpl is sufficiently up-to-date.
20 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
21 | )
22 |
23 | type UpdatePostRequest struct {
24 | state protoimpl.MessageState
25 | sizeCache protoimpl.SizeCache
26 | unknownFields protoimpl.UnknownFields
27 |
28 | Id string `protobuf:"bytes,1,opt,name=Id,proto3" json:"Id,omitempty"`
29 | Title *string `protobuf:"bytes,2,opt,name=Title,proto3,oneof" json:"Title,omitempty"`
30 | Content *string `protobuf:"bytes,3,opt,name=Content,proto3,oneof" json:"Content,omitempty"`
31 | Image *string `protobuf:"bytes,4,opt,name=Image,proto3,oneof" json:"Image,omitempty"`
32 | User *string `protobuf:"bytes,5,opt,name=User,proto3,oneof" json:"User,omitempty"`
33 | }
34 |
35 | func (x *UpdatePostRequest) Reset() {
36 | *x = UpdatePostRequest{}
37 | if protoimpl.UnsafeEnabled {
38 | mi := &file_rpc_update_post_proto_msgTypes[0]
39 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
40 | ms.StoreMessageInfo(mi)
41 | }
42 | }
43 |
44 | func (x *UpdatePostRequest) String() string {
45 | return protoimpl.X.MessageStringOf(x)
46 | }
47 |
48 | func (*UpdatePostRequest) ProtoMessage() {}
49 |
50 | func (x *UpdatePostRequest) ProtoReflect() protoreflect.Message {
51 | mi := &file_rpc_update_post_proto_msgTypes[0]
52 | if protoimpl.UnsafeEnabled && x != nil {
53 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
54 | if ms.LoadMessageInfo() == nil {
55 | ms.StoreMessageInfo(mi)
56 | }
57 | return ms
58 | }
59 | return mi.MessageOf(x)
60 | }
61 |
62 | // Deprecated: Use UpdatePostRequest.ProtoReflect.Descriptor instead.
63 | func (*UpdatePostRequest) Descriptor() ([]byte, []int) {
64 | return file_rpc_update_post_proto_rawDescGZIP(), []int{0}
65 | }
66 |
67 | func (x *UpdatePostRequest) GetId() string {
68 | if x != nil {
69 | return x.Id
70 | }
71 | return ""
72 | }
73 |
74 | func (x *UpdatePostRequest) GetTitle() string {
75 | if x != nil && x.Title != nil {
76 | return *x.Title
77 | }
78 | return ""
79 | }
80 |
81 | func (x *UpdatePostRequest) GetContent() string {
82 | if x != nil && x.Content != nil {
83 | return *x.Content
84 | }
85 | return ""
86 | }
87 |
88 | func (x *UpdatePostRequest) GetImage() string {
89 | if x != nil && x.Image != nil {
90 | return *x.Image
91 | }
92 | return ""
93 | }
94 |
95 | func (x *UpdatePostRequest) GetUser() string {
96 | if x != nil && x.User != nil {
97 | return *x.User
98 | }
99 | return ""
100 | }
101 |
102 | var File_rpc_update_post_proto protoreflect.FileDescriptor
103 |
104 | var file_rpc_update_post_proto_rawDesc = []byte{
105 | 0x0a, 0x15, 0x72, 0x70, 0x63, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x6f, 0x73,
106 | 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x70, 0x62, 0x22, 0xba, 0x01, 0x0a, 0x11,
107 | 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
108 | 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49,
109 | 0x64, 0x12, 0x19, 0x0a, 0x05, 0x54, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
110 | 0x48, 0x00, 0x52, 0x05, 0x54, 0x69, 0x74, 0x6c, 0x65, 0x88, 0x01, 0x01, 0x12, 0x1d, 0x0a, 0x07,
111 | 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52,
112 | 0x07, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x88, 0x01, 0x01, 0x12, 0x19, 0x0a, 0x05, 0x49,
113 | 0x6d, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x05, 0x49, 0x6d,
114 | 0x61, 0x67, 0x65, 0x88, 0x01, 0x01, 0x12, 0x17, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x18, 0x05,
115 | 0x20, 0x01, 0x28, 0x09, 0x48, 0x03, 0x52, 0x04, 0x55, 0x73, 0x65, 0x72, 0x88, 0x01, 0x01, 0x42,
116 | 0x08, 0x0a, 0x06, 0x5f, 0x54, 0x69, 0x74, 0x6c, 0x65, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x43, 0x6f,
117 | 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x42,
118 | 0x07, 0x0a, 0x05, 0x5f, 0x55, 0x73, 0x65, 0x72, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68,
119 | 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x70, 0x63, 0x6f, 0x64, 0x65, 0x76, 0x6f, 0x2f,
120 | 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2d, 0x6d, 0x6f, 0x6e, 0x67, 0x6f, 0x64, 0x62, 0x2f, 0x70,
121 | 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
122 | }
123 |
124 | var (
125 | file_rpc_update_post_proto_rawDescOnce sync.Once
126 | file_rpc_update_post_proto_rawDescData = file_rpc_update_post_proto_rawDesc
127 | )
128 |
129 | func file_rpc_update_post_proto_rawDescGZIP() []byte {
130 | file_rpc_update_post_proto_rawDescOnce.Do(func() {
131 | file_rpc_update_post_proto_rawDescData = protoimpl.X.CompressGZIP(file_rpc_update_post_proto_rawDescData)
132 | })
133 | return file_rpc_update_post_proto_rawDescData
134 | }
135 |
136 | var file_rpc_update_post_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
137 | var file_rpc_update_post_proto_goTypes = []interface{}{
138 | (*UpdatePostRequest)(nil), // 0: pb.UpdatePostRequest
139 | }
140 | var file_rpc_update_post_proto_depIdxs = []int32{
141 | 0, // [0:0] is the sub-list for method output_type
142 | 0, // [0:0] is the sub-list for method input_type
143 | 0, // [0:0] is the sub-list for extension type_name
144 | 0, // [0:0] is the sub-list for extension extendee
145 | 0, // [0:0] is the sub-list for field type_name
146 | }
147 |
148 | func init() { file_rpc_update_post_proto_init() }
149 | func file_rpc_update_post_proto_init() {
150 | if File_rpc_update_post_proto != nil {
151 | return
152 | }
153 | if !protoimpl.UnsafeEnabled {
154 | file_rpc_update_post_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
155 | switch v := v.(*UpdatePostRequest); i {
156 | case 0:
157 | return &v.state
158 | case 1:
159 | return &v.sizeCache
160 | case 2:
161 | return &v.unknownFields
162 | default:
163 | return nil
164 | }
165 | }
166 | }
167 | file_rpc_update_post_proto_msgTypes[0].OneofWrappers = []interface{}{}
168 | type x struct{}
169 | out := protoimpl.TypeBuilder{
170 | File: protoimpl.DescBuilder{
171 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
172 | RawDescriptor: file_rpc_update_post_proto_rawDesc,
173 | NumEnums: 0,
174 | NumMessages: 1,
175 | NumExtensions: 0,
176 | NumServices: 0,
177 | },
178 | GoTypes: file_rpc_update_post_proto_goTypes,
179 | DependencyIndexes: file_rpc_update_post_proto_depIdxs,
180 | MessageInfos: file_rpc_update_post_proto_msgTypes,
181 | }.Build()
182 | File_rpc_update_post_proto = out.File
183 | file_rpc_update_post_proto_rawDesc = nil
184 | file_rpc_update_post_proto_goTypes = nil
185 | file_rpc_update_post_proto_depIdxs = nil
186 | }
187 |
--------------------------------------------------------------------------------
/pb/auth_service_grpc.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-go-grpc. DO NOT EDIT.
2 | // versions:
3 | // - protoc-gen-go-grpc v1.2.0
4 | // - protoc v3.20.1
5 | // source: auth_service.proto
6 |
7 | package pb
8 |
9 | import (
10 | context "context"
11 | grpc "google.golang.org/grpc"
12 | codes "google.golang.org/grpc/codes"
13 | status "google.golang.org/grpc/status"
14 | )
15 |
16 | // This is a compile-time assertion to ensure that this generated file
17 | // is compatible with the grpc package it is being compiled against.
18 | // Requires gRPC-Go v1.32.0 or later.
19 | const _ = grpc.SupportPackageIsVersion7
20 |
21 | // AuthServiceClient is the client API for AuthService service.
22 | //
23 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
24 | type AuthServiceClient interface {
25 | SignUpUser(ctx context.Context, in *SignUpUserInput, opts ...grpc.CallOption) (*GenericResponse, error)
26 | SignInUser(ctx context.Context, in *SignInUserInput, opts ...grpc.CallOption) (*SignInUserResponse, error)
27 | VerifyEmail(ctx context.Context, in *VerifyEmailRequest, opts ...grpc.CallOption) (*GenericResponse, error)
28 | }
29 |
30 | type authServiceClient struct {
31 | cc grpc.ClientConnInterface
32 | }
33 |
34 | func NewAuthServiceClient(cc grpc.ClientConnInterface) AuthServiceClient {
35 | return &authServiceClient{cc}
36 | }
37 |
38 | func (c *authServiceClient) SignUpUser(ctx context.Context, in *SignUpUserInput, opts ...grpc.CallOption) (*GenericResponse, error) {
39 | out := new(GenericResponse)
40 | err := c.cc.Invoke(ctx, "/pb.AuthService/SignUpUser", in, out, opts...)
41 | if err != nil {
42 | return nil, err
43 | }
44 | return out, nil
45 | }
46 |
47 | func (c *authServiceClient) SignInUser(ctx context.Context, in *SignInUserInput, opts ...grpc.CallOption) (*SignInUserResponse, error) {
48 | out := new(SignInUserResponse)
49 | err := c.cc.Invoke(ctx, "/pb.AuthService/SignInUser", in, out, opts...)
50 | if err != nil {
51 | return nil, err
52 | }
53 | return out, nil
54 | }
55 |
56 | func (c *authServiceClient) VerifyEmail(ctx context.Context, in *VerifyEmailRequest, opts ...grpc.CallOption) (*GenericResponse, error) {
57 | out := new(GenericResponse)
58 | err := c.cc.Invoke(ctx, "/pb.AuthService/VerifyEmail", in, out, opts...)
59 | if err != nil {
60 | return nil, err
61 | }
62 | return out, nil
63 | }
64 |
65 | // AuthServiceServer is the server API for AuthService service.
66 | // All implementations must embed UnimplementedAuthServiceServer
67 | // for forward compatibility
68 | type AuthServiceServer interface {
69 | SignUpUser(context.Context, *SignUpUserInput) (*GenericResponse, error)
70 | SignInUser(context.Context, *SignInUserInput) (*SignInUserResponse, error)
71 | VerifyEmail(context.Context, *VerifyEmailRequest) (*GenericResponse, error)
72 | mustEmbedUnimplementedAuthServiceServer()
73 | }
74 |
75 | // UnimplementedAuthServiceServer must be embedded to have forward compatible implementations.
76 | type UnimplementedAuthServiceServer struct {
77 | }
78 |
79 | func (UnimplementedAuthServiceServer) SignUpUser(context.Context, *SignUpUserInput) (*GenericResponse, error) {
80 | return nil, status.Errorf(codes.Unimplemented, "method SignUpUser not implemented")
81 | }
82 | func (UnimplementedAuthServiceServer) SignInUser(context.Context, *SignInUserInput) (*SignInUserResponse, error) {
83 | return nil, status.Errorf(codes.Unimplemented, "method SignInUser not implemented")
84 | }
85 | func (UnimplementedAuthServiceServer) VerifyEmail(context.Context, *VerifyEmailRequest) (*GenericResponse, error) {
86 | return nil, status.Errorf(codes.Unimplemented, "method VerifyEmail not implemented")
87 | }
88 | func (UnimplementedAuthServiceServer) mustEmbedUnimplementedAuthServiceServer() {}
89 |
90 | // UnsafeAuthServiceServer may be embedded to opt out of forward compatibility for this service.
91 | // Use of this interface is not recommended, as added methods to AuthServiceServer will
92 | // result in compilation errors.
93 | type UnsafeAuthServiceServer interface {
94 | mustEmbedUnimplementedAuthServiceServer()
95 | }
96 |
97 | func RegisterAuthServiceServer(s grpc.ServiceRegistrar, srv AuthServiceServer) {
98 | s.RegisterService(&AuthService_ServiceDesc, srv)
99 | }
100 |
101 | func _AuthService_SignUpUser_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
102 | in := new(SignUpUserInput)
103 | if err := dec(in); err != nil {
104 | return nil, err
105 | }
106 | if interceptor == nil {
107 | return srv.(AuthServiceServer).SignUpUser(ctx, in)
108 | }
109 | info := &grpc.UnaryServerInfo{
110 | Server: srv,
111 | FullMethod: "/pb.AuthService/SignUpUser",
112 | }
113 | handler := func(ctx context.Context, req interface{}) (interface{}, error) {
114 | return srv.(AuthServiceServer).SignUpUser(ctx, req.(*SignUpUserInput))
115 | }
116 | return interceptor(ctx, in, info, handler)
117 | }
118 |
119 | func _AuthService_SignInUser_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
120 | in := new(SignInUserInput)
121 | if err := dec(in); err != nil {
122 | return nil, err
123 | }
124 | if interceptor == nil {
125 | return srv.(AuthServiceServer).SignInUser(ctx, in)
126 | }
127 | info := &grpc.UnaryServerInfo{
128 | Server: srv,
129 | FullMethod: "/pb.AuthService/SignInUser",
130 | }
131 | handler := func(ctx context.Context, req interface{}) (interface{}, error) {
132 | return srv.(AuthServiceServer).SignInUser(ctx, req.(*SignInUserInput))
133 | }
134 | return interceptor(ctx, in, info, handler)
135 | }
136 |
137 | func _AuthService_VerifyEmail_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
138 | in := new(VerifyEmailRequest)
139 | if err := dec(in); err != nil {
140 | return nil, err
141 | }
142 | if interceptor == nil {
143 | return srv.(AuthServiceServer).VerifyEmail(ctx, in)
144 | }
145 | info := &grpc.UnaryServerInfo{
146 | Server: srv,
147 | FullMethod: "/pb.AuthService/VerifyEmail",
148 | }
149 | handler := func(ctx context.Context, req interface{}) (interface{}, error) {
150 | return srv.(AuthServiceServer).VerifyEmail(ctx, req.(*VerifyEmailRequest))
151 | }
152 | return interceptor(ctx, in, info, handler)
153 | }
154 |
155 | // AuthService_ServiceDesc is the grpc.ServiceDesc for AuthService service.
156 | // It's only intended for direct use with grpc.RegisterService,
157 | // and not to be introspected or modified (even as a copy)
158 | var AuthService_ServiceDesc = grpc.ServiceDesc{
159 | ServiceName: "pb.AuthService",
160 | HandlerType: (*AuthServiceServer)(nil),
161 | Methods: []grpc.MethodDesc{
162 | {
163 | MethodName: "SignUpUser",
164 | Handler: _AuthService_SignUpUser_Handler,
165 | },
166 | {
167 | MethodName: "SignInUser",
168 | Handler: _AuthService_SignInUser_Handler,
169 | },
170 | {
171 | MethodName: "VerifyEmail",
172 | Handler: _AuthService_VerifyEmail_Handler,
173 | },
174 | },
175 | Streams: []grpc.StreamDesc{},
176 | Metadata: "auth_service.proto",
177 | }
178 |
--------------------------------------------------------------------------------
/pb/auth_service.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-go. DO NOT EDIT.
2 | // versions:
3 | // protoc-gen-go v1.28.0
4 | // protoc v3.20.1
5 | // source: auth_service.proto
6 |
7 | package pb
8 |
9 | import (
10 | protoreflect "google.golang.org/protobuf/reflect/protoreflect"
11 | protoimpl "google.golang.org/protobuf/runtime/protoimpl"
12 | reflect "reflect"
13 | sync "sync"
14 | )
15 |
16 | const (
17 | // Verify that this generated code is sufficiently up-to-date.
18 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
19 | // Verify that runtime/protoimpl is sufficiently up-to-date.
20 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
21 | )
22 |
23 | type VerifyEmailRequest struct {
24 | state protoimpl.MessageState
25 | sizeCache protoimpl.SizeCache
26 | unknownFields protoimpl.UnknownFields
27 |
28 | VerificationCode string `protobuf:"bytes,1,opt,name=verificationCode,proto3" json:"verificationCode,omitempty"`
29 | }
30 |
31 | func (x *VerifyEmailRequest) Reset() {
32 | *x = VerifyEmailRequest{}
33 | if protoimpl.UnsafeEnabled {
34 | mi := &file_auth_service_proto_msgTypes[0]
35 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
36 | ms.StoreMessageInfo(mi)
37 | }
38 | }
39 |
40 | func (x *VerifyEmailRequest) String() string {
41 | return protoimpl.X.MessageStringOf(x)
42 | }
43 |
44 | func (*VerifyEmailRequest) ProtoMessage() {}
45 |
46 | func (x *VerifyEmailRequest) ProtoReflect() protoreflect.Message {
47 | mi := &file_auth_service_proto_msgTypes[0]
48 | if protoimpl.UnsafeEnabled && x != nil {
49 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
50 | if ms.LoadMessageInfo() == nil {
51 | ms.StoreMessageInfo(mi)
52 | }
53 | return ms
54 | }
55 | return mi.MessageOf(x)
56 | }
57 |
58 | // Deprecated: Use VerifyEmailRequest.ProtoReflect.Descriptor instead.
59 | func (*VerifyEmailRequest) Descriptor() ([]byte, []int) {
60 | return file_auth_service_proto_rawDescGZIP(), []int{0}
61 | }
62 |
63 | func (x *VerifyEmailRequest) GetVerificationCode() string {
64 | if x != nil {
65 | return x.VerificationCode
66 | }
67 | return ""
68 | }
69 |
70 | var File_auth_service_proto protoreflect.FileDescriptor
71 |
72 | var file_auth_service_proto_rawDesc = []byte{
73 | 0x0a, 0x12, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70,
74 | 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x70, 0x62, 0x1a, 0x15, 0x72, 0x70, 0x63, 0x5f, 0x73, 0x69,
75 | 0x67, 0x6e, 0x69, 0x6e, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
76 | 0x15, 0x72, 0x70, 0x63, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x75, 0x70, 0x5f, 0x75, 0x73, 0x65, 0x72,
77 | 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f,
78 | 0x74, 0x6f, 0x22, 0x40, 0x0a, 0x12, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x45, 0x6d, 0x61, 0x69,
79 | 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2a, 0x0a, 0x10, 0x76, 0x65, 0x72, 0x69,
80 | 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01,
81 | 0x28, 0x09, 0x52, 0x10, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
82 | 0x43, 0x6f, 0x64, 0x65, 0x32, 0xc2, 0x01, 0x0a, 0x0b, 0x41, 0x75, 0x74, 0x68, 0x53, 0x65, 0x72,
83 | 0x76, 0x69, 0x63, 0x65, 0x12, 0x38, 0x0a, 0x0a, 0x53, 0x69, 0x67, 0x6e, 0x55, 0x70, 0x55, 0x73,
84 | 0x65, 0x72, 0x12, 0x13, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x55, 0x70, 0x55, 0x73,
85 | 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x1a, 0x13, 0x2e, 0x70, 0x62, 0x2e, 0x47, 0x65, 0x6e,
86 | 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3b,
87 | 0x0a, 0x0a, 0x53, 0x69, 0x67, 0x6e, 0x49, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x12, 0x13, 0x2e, 0x70,
88 | 0x62, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x49, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75,
89 | 0x74, 0x1a, 0x16, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x49, 0x6e, 0x55, 0x73, 0x65,
90 | 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3c, 0x0a, 0x0b, 0x56,
91 | 0x65, 0x72, 0x69, 0x66, 0x79, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x16, 0x2e, 0x70, 0x62, 0x2e,
92 | 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65,
93 | 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x70, 0x62, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52,
94 | 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74,
95 | 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x70, 0x63, 0x6f, 0x64, 0x65, 0x76, 0x6f,
96 | 0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2d, 0x6d, 0x6f, 0x6e, 0x67, 0x6f, 0x64, 0x62, 0x2f,
97 | 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
98 | }
99 |
100 | var (
101 | file_auth_service_proto_rawDescOnce sync.Once
102 | file_auth_service_proto_rawDescData = file_auth_service_proto_rawDesc
103 | )
104 |
105 | func file_auth_service_proto_rawDescGZIP() []byte {
106 | file_auth_service_proto_rawDescOnce.Do(func() {
107 | file_auth_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_auth_service_proto_rawDescData)
108 | })
109 | return file_auth_service_proto_rawDescData
110 | }
111 |
112 | var file_auth_service_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
113 | var file_auth_service_proto_goTypes = []interface{}{
114 | (*VerifyEmailRequest)(nil), // 0: pb.VerifyEmailRequest
115 | (*SignUpUserInput)(nil), // 1: pb.SignUpUserInput
116 | (*SignInUserInput)(nil), // 2: pb.SignInUserInput
117 | (*GenericResponse)(nil), // 3: pb.GenericResponse
118 | (*SignInUserResponse)(nil), // 4: pb.SignInUserResponse
119 | }
120 | var file_auth_service_proto_depIdxs = []int32{
121 | 1, // 0: pb.AuthService.SignUpUser:input_type -> pb.SignUpUserInput
122 | 2, // 1: pb.AuthService.SignInUser:input_type -> pb.SignInUserInput
123 | 0, // 2: pb.AuthService.VerifyEmail:input_type -> pb.VerifyEmailRequest
124 | 3, // 3: pb.AuthService.SignUpUser:output_type -> pb.GenericResponse
125 | 4, // 4: pb.AuthService.SignInUser:output_type -> pb.SignInUserResponse
126 | 3, // 5: pb.AuthService.VerifyEmail:output_type -> pb.GenericResponse
127 | 3, // [3:6] is the sub-list for method output_type
128 | 0, // [0:3] is the sub-list for method input_type
129 | 0, // [0:0] is the sub-list for extension type_name
130 | 0, // [0:0] is the sub-list for extension extendee
131 | 0, // [0:0] is the sub-list for field type_name
132 | }
133 |
134 | func init() { file_auth_service_proto_init() }
135 | func file_auth_service_proto_init() {
136 | if File_auth_service_proto != nil {
137 | return
138 | }
139 | file_rpc_signin_user_proto_init()
140 | file_rpc_signup_user_proto_init()
141 | file_user_proto_init()
142 | if !protoimpl.UnsafeEnabled {
143 | file_auth_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
144 | switch v := v.(*VerifyEmailRequest); i {
145 | case 0:
146 | return &v.state
147 | case 1:
148 | return &v.sizeCache
149 | case 2:
150 | return &v.unknownFields
151 | default:
152 | return nil
153 | }
154 | }
155 | }
156 | type x struct{}
157 | out := protoimpl.TypeBuilder{
158 | File: protoimpl.DescBuilder{
159 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
160 | RawDescriptor: file_auth_service_proto_rawDesc,
161 | NumEnums: 0,
162 | NumMessages: 1,
163 | NumExtensions: 0,
164 | NumServices: 1,
165 | },
166 | GoTypes: file_auth_service_proto_goTypes,
167 | DependencyIndexes: file_auth_service_proto_depIdxs,
168 | MessageInfos: file_auth_service_proto_msgTypes,
169 | }.Build()
170 | File_auth_service_proto = out.File
171 | file_auth_service_proto_rawDesc = nil
172 | file_auth_service_proto_goTypes = nil
173 | file_auth_service_proto_depIdxs = nil
174 | }
175 |
--------------------------------------------------------------------------------
/templates/styles.html:
--------------------------------------------------------------------------------
1 | {{define "styles"}}
2 |
331 | {{end}}
332 |
--------------------------------------------------------------------------------
/pb/rpc_signin_user.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-go. DO NOT EDIT.
2 | // versions:
3 | // protoc-gen-go v1.28.0
4 | // protoc v3.20.1
5 | // source: rpc_signin_user.proto
6 |
7 | package pb
8 |
9 | import (
10 | protoreflect "google.golang.org/protobuf/reflect/protoreflect"
11 | protoimpl "google.golang.org/protobuf/runtime/protoimpl"
12 | reflect "reflect"
13 | sync "sync"
14 | )
15 |
16 | const (
17 | // Verify that this generated code is sufficiently up-to-date.
18 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
19 | // Verify that runtime/protoimpl is sufficiently up-to-date.
20 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
21 | )
22 |
23 | type SignInUserInput struct {
24 | state protoimpl.MessageState
25 | sizeCache protoimpl.SizeCache
26 | unknownFields protoimpl.UnknownFields
27 |
28 | Email string `protobuf:"bytes,1,opt,name=email,proto3" json:"email,omitempty"`
29 | Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"`
30 | }
31 |
32 | func (x *SignInUserInput) Reset() {
33 | *x = SignInUserInput{}
34 | if protoimpl.UnsafeEnabled {
35 | mi := &file_rpc_signin_user_proto_msgTypes[0]
36 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
37 | ms.StoreMessageInfo(mi)
38 | }
39 | }
40 |
41 | func (x *SignInUserInput) String() string {
42 | return protoimpl.X.MessageStringOf(x)
43 | }
44 |
45 | func (*SignInUserInput) ProtoMessage() {}
46 |
47 | func (x *SignInUserInput) ProtoReflect() protoreflect.Message {
48 | mi := &file_rpc_signin_user_proto_msgTypes[0]
49 | if protoimpl.UnsafeEnabled && x != nil {
50 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
51 | if ms.LoadMessageInfo() == nil {
52 | ms.StoreMessageInfo(mi)
53 | }
54 | return ms
55 | }
56 | return mi.MessageOf(x)
57 | }
58 |
59 | // Deprecated: Use SignInUserInput.ProtoReflect.Descriptor instead.
60 | func (*SignInUserInput) Descriptor() ([]byte, []int) {
61 | return file_rpc_signin_user_proto_rawDescGZIP(), []int{0}
62 | }
63 |
64 | func (x *SignInUserInput) GetEmail() string {
65 | if x != nil {
66 | return x.Email
67 | }
68 | return ""
69 | }
70 |
71 | func (x *SignInUserInput) GetPassword() string {
72 | if x != nil {
73 | return x.Password
74 | }
75 | return ""
76 | }
77 |
78 | type SignInUserResponse struct {
79 | state protoimpl.MessageState
80 | sizeCache protoimpl.SizeCache
81 | unknownFields protoimpl.UnknownFields
82 |
83 | Status string `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"`
84 | AccessToken string `protobuf:"bytes,2,opt,name=access_token,json=accessToken,proto3" json:"access_token,omitempty"`
85 | RefreshToken string `protobuf:"bytes,3,opt,name=refresh_token,json=refreshToken,proto3" json:"refresh_token,omitempty"`
86 | }
87 |
88 | func (x *SignInUserResponse) Reset() {
89 | *x = SignInUserResponse{}
90 | if protoimpl.UnsafeEnabled {
91 | mi := &file_rpc_signin_user_proto_msgTypes[1]
92 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
93 | ms.StoreMessageInfo(mi)
94 | }
95 | }
96 |
97 | func (x *SignInUserResponse) String() string {
98 | return protoimpl.X.MessageStringOf(x)
99 | }
100 |
101 | func (*SignInUserResponse) ProtoMessage() {}
102 |
103 | func (x *SignInUserResponse) ProtoReflect() protoreflect.Message {
104 | mi := &file_rpc_signin_user_proto_msgTypes[1]
105 | if protoimpl.UnsafeEnabled && x != nil {
106 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
107 | if ms.LoadMessageInfo() == nil {
108 | ms.StoreMessageInfo(mi)
109 | }
110 | return ms
111 | }
112 | return mi.MessageOf(x)
113 | }
114 |
115 | // Deprecated: Use SignInUserResponse.ProtoReflect.Descriptor instead.
116 | func (*SignInUserResponse) Descriptor() ([]byte, []int) {
117 | return file_rpc_signin_user_proto_rawDescGZIP(), []int{1}
118 | }
119 |
120 | func (x *SignInUserResponse) GetStatus() string {
121 | if x != nil {
122 | return x.Status
123 | }
124 | return ""
125 | }
126 |
127 | func (x *SignInUserResponse) GetAccessToken() string {
128 | if x != nil {
129 | return x.AccessToken
130 | }
131 | return ""
132 | }
133 |
134 | func (x *SignInUserResponse) GetRefreshToken() string {
135 | if x != nil {
136 | return x.RefreshToken
137 | }
138 | return ""
139 | }
140 |
141 | var File_rpc_signin_user_proto protoreflect.FileDescriptor
142 |
143 | var file_rpc_signin_user_proto_rawDesc = []byte{
144 | 0x0a, 0x15, 0x72, 0x70, 0x63, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x5f, 0x75, 0x73, 0x65,
145 | 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x70, 0x62, 0x22, 0x43, 0x0a, 0x0f, 0x53,
146 | 0x69, 0x67, 0x6e, 0x49, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x14,
147 | 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65,
148 | 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64,
149 | 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64,
150 | 0x22, 0x74, 0x0a, 0x12, 0x53, 0x69, 0x67, 0x6e, 0x49, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65,
151 | 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73,
152 | 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x21,
153 | 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02,
154 | 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65,
155 | 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x5f, 0x74, 0x6f, 0x6b,
156 | 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73,
157 | 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
158 | 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x70, 0x63, 0x6f, 0x64, 0x65, 0x76, 0x6f, 0x2f, 0x67, 0x6f,
159 | 0x6c, 0x61, 0x6e, 0x67, 0x2d, 0x6d, 0x6f, 0x6e, 0x67, 0x6f, 0x64, 0x62, 0x2f, 0x70, 0x62, 0x62,
160 | 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
161 | }
162 |
163 | var (
164 | file_rpc_signin_user_proto_rawDescOnce sync.Once
165 | file_rpc_signin_user_proto_rawDescData = file_rpc_signin_user_proto_rawDesc
166 | )
167 |
168 | func file_rpc_signin_user_proto_rawDescGZIP() []byte {
169 | file_rpc_signin_user_proto_rawDescOnce.Do(func() {
170 | file_rpc_signin_user_proto_rawDescData = protoimpl.X.CompressGZIP(file_rpc_signin_user_proto_rawDescData)
171 | })
172 | return file_rpc_signin_user_proto_rawDescData
173 | }
174 |
175 | var file_rpc_signin_user_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
176 | var file_rpc_signin_user_proto_goTypes = []interface{}{
177 | (*SignInUserInput)(nil), // 0: pb.SignInUserInput
178 | (*SignInUserResponse)(nil), // 1: pb.SignInUserResponse
179 | }
180 | var file_rpc_signin_user_proto_depIdxs = []int32{
181 | 0, // [0:0] is the sub-list for method output_type
182 | 0, // [0:0] is the sub-list for method input_type
183 | 0, // [0:0] is the sub-list for extension type_name
184 | 0, // [0:0] is the sub-list for extension extendee
185 | 0, // [0:0] is the sub-list for field type_name
186 | }
187 |
188 | func init() { file_rpc_signin_user_proto_init() }
189 | func file_rpc_signin_user_proto_init() {
190 | if File_rpc_signin_user_proto != nil {
191 | return
192 | }
193 | if !protoimpl.UnsafeEnabled {
194 | file_rpc_signin_user_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
195 | switch v := v.(*SignInUserInput); i {
196 | case 0:
197 | return &v.state
198 | case 1:
199 | return &v.sizeCache
200 | case 2:
201 | return &v.unknownFields
202 | default:
203 | return nil
204 | }
205 | }
206 | file_rpc_signin_user_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
207 | switch v := v.(*SignInUserResponse); i {
208 | case 0:
209 | return &v.state
210 | case 1:
211 | return &v.sizeCache
212 | case 2:
213 | return &v.unknownFields
214 | default:
215 | return nil
216 | }
217 | }
218 | }
219 | type x struct{}
220 | out := protoimpl.TypeBuilder{
221 | File: protoimpl.DescBuilder{
222 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
223 | RawDescriptor: file_rpc_signin_user_proto_rawDesc,
224 | NumEnums: 0,
225 | NumMessages: 2,
226 | NumExtensions: 0,
227 | NumServices: 0,
228 | },
229 | GoTypes: file_rpc_signin_user_proto_goTypes,
230 | DependencyIndexes: file_rpc_signin_user_proto_depIdxs,
231 | MessageInfos: file_rpc_signin_user_proto_msgTypes,
232 | }.Build()
233 | File_rpc_signin_user_proto = out.File
234 | file_rpc_signin_user_proto_rawDesc = nil
235 | file_rpc_signin_user_proto_goTypes = nil
236 | file_rpc_signin_user_proto_depIdxs = nil
237 | }
238 |
--------------------------------------------------------------------------------
/pb/rpc_signup_user.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-go. DO NOT EDIT.
2 | // versions:
3 | // protoc-gen-go v1.28.0
4 | // protoc v3.20.1
5 | // source: rpc_signup_user.proto
6 |
7 | package pb
8 |
9 | import (
10 | protoreflect "google.golang.org/protobuf/reflect/protoreflect"
11 | protoimpl "google.golang.org/protobuf/runtime/protoimpl"
12 | reflect "reflect"
13 | sync "sync"
14 | )
15 |
16 | const (
17 | // Verify that this generated code is sufficiently up-to-date.
18 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
19 | // Verify that runtime/protoimpl is sufficiently up-to-date.
20 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
21 | )
22 |
23 | type SignUpUserInput struct {
24 | state protoimpl.MessageState
25 | sizeCache protoimpl.SizeCache
26 | unknownFields protoimpl.UnknownFields
27 |
28 | Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
29 | Email string `protobuf:"bytes,2,opt,name=email,proto3" json:"email,omitempty"`
30 | Password string `protobuf:"bytes,3,opt,name=password,proto3" json:"password,omitempty"`
31 | PasswordConfirm string `protobuf:"bytes,4,opt,name=passwordConfirm,proto3" json:"passwordConfirm,omitempty"`
32 | }
33 |
34 | func (x *SignUpUserInput) Reset() {
35 | *x = SignUpUserInput{}
36 | if protoimpl.UnsafeEnabled {
37 | mi := &file_rpc_signup_user_proto_msgTypes[0]
38 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
39 | ms.StoreMessageInfo(mi)
40 | }
41 | }
42 |
43 | func (x *SignUpUserInput) String() string {
44 | return protoimpl.X.MessageStringOf(x)
45 | }
46 |
47 | func (*SignUpUserInput) ProtoMessage() {}
48 |
49 | func (x *SignUpUserInput) ProtoReflect() protoreflect.Message {
50 | mi := &file_rpc_signup_user_proto_msgTypes[0]
51 | if protoimpl.UnsafeEnabled && x != nil {
52 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
53 | if ms.LoadMessageInfo() == nil {
54 | ms.StoreMessageInfo(mi)
55 | }
56 | return ms
57 | }
58 | return mi.MessageOf(x)
59 | }
60 |
61 | // Deprecated: Use SignUpUserInput.ProtoReflect.Descriptor instead.
62 | func (*SignUpUserInput) Descriptor() ([]byte, []int) {
63 | return file_rpc_signup_user_proto_rawDescGZIP(), []int{0}
64 | }
65 |
66 | func (x *SignUpUserInput) GetName() string {
67 | if x != nil {
68 | return x.Name
69 | }
70 | return ""
71 | }
72 |
73 | func (x *SignUpUserInput) GetEmail() string {
74 | if x != nil {
75 | return x.Email
76 | }
77 | return ""
78 | }
79 |
80 | func (x *SignUpUserInput) GetPassword() string {
81 | if x != nil {
82 | return x.Password
83 | }
84 | return ""
85 | }
86 |
87 | func (x *SignUpUserInput) GetPasswordConfirm() string {
88 | if x != nil {
89 | return x.PasswordConfirm
90 | }
91 | return ""
92 | }
93 |
94 | type SignUpUserResponse struct {
95 | state protoimpl.MessageState
96 | sizeCache protoimpl.SizeCache
97 | unknownFields protoimpl.UnknownFields
98 |
99 | User *User `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"`
100 | }
101 |
102 | func (x *SignUpUserResponse) Reset() {
103 | *x = SignUpUserResponse{}
104 | if protoimpl.UnsafeEnabled {
105 | mi := &file_rpc_signup_user_proto_msgTypes[1]
106 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
107 | ms.StoreMessageInfo(mi)
108 | }
109 | }
110 |
111 | func (x *SignUpUserResponse) String() string {
112 | return protoimpl.X.MessageStringOf(x)
113 | }
114 |
115 | func (*SignUpUserResponse) ProtoMessage() {}
116 |
117 | func (x *SignUpUserResponse) ProtoReflect() protoreflect.Message {
118 | mi := &file_rpc_signup_user_proto_msgTypes[1]
119 | if protoimpl.UnsafeEnabled && x != nil {
120 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
121 | if ms.LoadMessageInfo() == nil {
122 | ms.StoreMessageInfo(mi)
123 | }
124 | return ms
125 | }
126 | return mi.MessageOf(x)
127 | }
128 |
129 | // Deprecated: Use SignUpUserResponse.ProtoReflect.Descriptor instead.
130 | func (*SignUpUserResponse) Descriptor() ([]byte, []int) {
131 | return file_rpc_signup_user_proto_rawDescGZIP(), []int{1}
132 | }
133 |
134 | func (x *SignUpUserResponse) GetUser() *User {
135 | if x != nil {
136 | return x.User
137 | }
138 | return nil
139 | }
140 |
141 | var File_rpc_signup_user_proto protoreflect.FileDescriptor
142 |
143 | var file_rpc_signup_user_proto_rawDesc = []byte{
144 | 0x0a, 0x15, 0x72, 0x70, 0x63, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x75, 0x70, 0x5f, 0x75, 0x73, 0x65,
145 | 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x70, 0x62, 0x1a, 0x0a, 0x75, 0x73, 0x65,
146 | 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x81, 0x01, 0x0a, 0x0f, 0x53, 0x69, 0x67, 0x6e,
147 | 0x55, 0x70, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e,
148 | 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12,
149 | 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05,
150 | 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72,
151 | 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72,
152 | 0x64, 0x12, 0x28, 0x0a, 0x0f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x43, 0x6f, 0x6e,
153 | 0x66, 0x69, 0x72, 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x70, 0x61, 0x73, 0x73,
154 | 0x77, 0x6f, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x22, 0x32, 0x0a, 0x12, 0x53,
155 | 0x69, 0x67, 0x6e, 0x55, 0x70, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
156 | 0x65, 0x12, 0x1c, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
157 | 0x08, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x42,
158 | 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x70,
159 | 0x63, 0x6f, 0x64, 0x65, 0x76, 0x6f, 0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2d, 0x6d, 0x6f,
160 | 0x6e, 0x67, 0x6f, 0x64, 0x62, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
161 | }
162 |
163 | var (
164 | file_rpc_signup_user_proto_rawDescOnce sync.Once
165 | file_rpc_signup_user_proto_rawDescData = file_rpc_signup_user_proto_rawDesc
166 | )
167 |
168 | func file_rpc_signup_user_proto_rawDescGZIP() []byte {
169 | file_rpc_signup_user_proto_rawDescOnce.Do(func() {
170 | file_rpc_signup_user_proto_rawDescData = protoimpl.X.CompressGZIP(file_rpc_signup_user_proto_rawDescData)
171 | })
172 | return file_rpc_signup_user_proto_rawDescData
173 | }
174 |
175 | var file_rpc_signup_user_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
176 | var file_rpc_signup_user_proto_goTypes = []interface{}{
177 | (*SignUpUserInput)(nil), // 0: pb.SignUpUserInput
178 | (*SignUpUserResponse)(nil), // 1: pb.SignUpUserResponse
179 | (*User)(nil), // 2: pb.User
180 | }
181 | var file_rpc_signup_user_proto_depIdxs = []int32{
182 | 2, // 0: pb.SignUpUserResponse.user:type_name -> pb.User
183 | 1, // [1:1] is the sub-list for method output_type
184 | 1, // [1:1] is the sub-list for method input_type
185 | 1, // [1:1] is the sub-list for extension type_name
186 | 1, // [1:1] is the sub-list for extension extendee
187 | 0, // [0:1] is the sub-list for field type_name
188 | }
189 |
190 | func init() { file_rpc_signup_user_proto_init() }
191 | func file_rpc_signup_user_proto_init() {
192 | if File_rpc_signup_user_proto != nil {
193 | return
194 | }
195 | file_user_proto_init()
196 | if !protoimpl.UnsafeEnabled {
197 | file_rpc_signup_user_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
198 | switch v := v.(*SignUpUserInput); i {
199 | case 0:
200 | return &v.state
201 | case 1:
202 | return &v.sizeCache
203 | case 2:
204 | return &v.unknownFields
205 | default:
206 | return nil
207 | }
208 | }
209 | file_rpc_signup_user_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
210 | switch v := v.(*SignUpUserResponse); i {
211 | case 0:
212 | return &v.state
213 | case 1:
214 | return &v.sizeCache
215 | case 2:
216 | return &v.unknownFields
217 | default:
218 | return nil
219 | }
220 | }
221 | }
222 | type x struct{}
223 | out := protoimpl.TypeBuilder{
224 | File: protoimpl.DescBuilder{
225 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
226 | RawDescriptor: file_rpc_signup_user_proto_rawDesc,
227 | NumEnums: 0,
228 | NumMessages: 2,
229 | NumExtensions: 0,
230 | NumServices: 0,
231 | },
232 | GoTypes: file_rpc_signup_user_proto_goTypes,
233 | DependencyIndexes: file_rpc_signup_user_proto_depIdxs,
234 | MessageInfos: file_rpc_signup_user_proto_msgTypes,
235 | }.Build()
236 | File_rpc_signup_user_proto = out.File
237 | file_rpc_signup_user_proto_rawDesc = nil
238 | file_rpc_signup_user_proto_goTypes = nil
239 | file_rpc_signup_user_proto_depIdxs = nil
240 | }
241 |
--------------------------------------------------------------------------------
/pb/post.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-go. DO NOT EDIT.
2 | // versions:
3 | // protoc-gen-go v1.28.0
4 | // protoc v3.20.1
5 | // source: post.proto
6 |
7 | package pb
8 |
9 | import (
10 | protoreflect "google.golang.org/protobuf/reflect/protoreflect"
11 | protoimpl "google.golang.org/protobuf/runtime/protoimpl"
12 | timestamppb "google.golang.org/protobuf/types/known/timestamppb"
13 | reflect "reflect"
14 | sync "sync"
15 | )
16 |
17 | const (
18 | // Verify that this generated code is sufficiently up-to-date.
19 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
20 | // Verify that runtime/protoimpl is sufficiently up-to-date.
21 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
22 | )
23 |
24 | type Post struct {
25 | state protoimpl.MessageState
26 | sizeCache protoimpl.SizeCache
27 | unknownFields protoimpl.UnknownFields
28 |
29 | Id string `protobuf:"bytes,1,opt,name=Id,proto3" json:"Id,omitempty"`
30 | Title string `protobuf:"bytes,2,opt,name=Title,proto3" json:"Title,omitempty"`
31 | Content string `protobuf:"bytes,3,opt,name=Content,proto3" json:"Content,omitempty"`
32 | Image string `protobuf:"bytes,4,opt,name=Image,proto3" json:"Image,omitempty"`
33 | User string `protobuf:"bytes,5,opt,name=User,proto3" json:"User,omitempty"`
34 | CreatedAt *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
35 | UpdatedAt *timestamppb.Timestamp `protobuf:"bytes,7,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"`
36 | }
37 |
38 | func (x *Post) Reset() {
39 | *x = Post{}
40 | if protoimpl.UnsafeEnabled {
41 | mi := &file_post_proto_msgTypes[0]
42 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
43 | ms.StoreMessageInfo(mi)
44 | }
45 | }
46 |
47 | func (x *Post) String() string {
48 | return protoimpl.X.MessageStringOf(x)
49 | }
50 |
51 | func (*Post) ProtoMessage() {}
52 |
53 | func (x *Post) ProtoReflect() protoreflect.Message {
54 | mi := &file_post_proto_msgTypes[0]
55 | if protoimpl.UnsafeEnabled && x != nil {
56 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
57 | if ms.LoadMessageInfo() == nil {
58 | ms.StoreMessageInfo(mi)
59 | }
60 | return ms
61 | }
62 | return mi.MessageOf(x)
63 | }
64 |
65 | // Deprecated: Use Post.ProtoReflect.Descriptor instead.
66 | func (*Post) Descriptor() ([]byte, []int) {
67 | return file_post_proto_rawDescGZIP(), []int{0}
68 | }
69 |
70 | func (x *Post) GetId() string {
71 | if x != nil {
72 | return x.Id
73 | }
74 | return ""
75 | }
76 |
77 | func (x *Post) GetTitle() string {
78 | if x != nil {
79 | return x.Title
80 | }
81 | return ""
82 | }
83 |
84 | func (x *Post) GetContent() string {
85 | if x != nil {
86 | return x.Content
87 | }
88 | return ""
89 | }
90 |
91 | func (x *Post) GetImage() string {
92 | if x != nil {
93 | return x.Image
94 | }
95 | return ""
96 | }
97 |
98 | func (x *Post) GetUser() string {
99 | if x != nil {
100 | return x.User
101 | }
102 | return ""
103 | }
104 |
105 | func (x *Post) GetCreatedAt() *timestamppb.Timestamp {
106 | if x != nil {
107 | return x.CreatedAt
108 | }
109 | return nil
110 | }
111 |
112 | func (x *Post) GetUpdatedAt() *timestamppb.Timestamp {
113 | if x != nil {
114 | return x.UpdatedAt
115 | }
116 | return nil
117 | }
118 |
119 | type PostResponse struct {
120 | state protoimpl.MessageState
121 | sizeCache protoimpl.SizeCache
122 | unknownFields protoimpl.UnknownFields
123 |
124 | Post *Post `protobuf:"bytes,1,opt,name=post,proto3" json:"post,omitempty"`
125 | }
126 |
127 | func (x *PostResponse) Reset() {
128 | *x = PostResponse{}
129 | if protoimpl.UnsafeEnabled {
130 | mi := &file_post_proto_msgTypes[1]
131 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
132 | ms.StoreMessageInfo(mi)
133 | }
134 | }
135 |
136 | func (x *PostResponse) String() string {
137 | return protoimpl.X.MessageStringOf(x)
138 | }
139 |
140 | func (*PostResponse) ProtoMessage() {}
141 |
142 | func (x *PostResponse) ProtoReflect() protoreflect.Message {
143 | mi := &file_post_proto_msgTypes[1]
144 | if protoimpl.UnsafeEnabled && x != nil {
145 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
146 | if ms.LoadMessageInfo() == nil {
147 | ms.StoreMessageInfo(mi)
148 | }
149 | return ms
150 | }
151 | return mi.MessageOf(x)
152 | }
153 |
154 | // Deprecated: Use PostResponse.ProtoReflect.Descriptor instead.
155 | func (*PostResponse) Descriptor() ([]byte, []int) {
156 | return file_post_proto_rawDescGZIP(), []int{1}
157 | }
158 |
159 | func (x *PostResponse) GetPost() *Post {
160 | if x != nil {
161 | return x.Post
162 | }
163 | return nil
164 | }
165 |
166 | var File_post_proto protoreflect.FileDescriptor
167 |
168 | var file_post_proto_rawDesc = []byte{
169 | 0x0a, 0x0a, 0x70, 0x6f, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x70, 0x62,
170 | 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
171 | 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74,
172 | 0x6f, 0x22, 0xe6, 0x01, 0x0a, 0x04, 0x50, 0x6f, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x64,
173 | 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x54, 0x69,
174 | 0x74, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x54, 0x69, 0x74, 0x6c, 0x65,
175 | 0x12, 0x18, 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28,
176 | 0x09, 0x52, 0x07, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x49, 0x6d,
177 | 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x49, 0x6d, 0x61, 0x67, 0x65,
178 | 0x12, 0x12, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
179 | 0x55, 0x73, 0x65, 0x72, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f,
180 | 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
181 | 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73,
182 | 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12,
183 | 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x07, 0x20,
184 | 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
185 | 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52,
186 | 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0x2c, 0x0a, 0x0c, 0x50, 0x6f,
187 | 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x04, 0x70, 0x6f,
188 | 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x6f,
189 | 0x73, 0x74, 0x52, 0x04, 0x70, 0x6f, 0x73, 0x74, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68,
190 | 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x70, 0x63, 0x6f, 0x64, 0x65, 0x76, 0x6f, 0x2f,
191 | 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2d, 0x6d, 0x6f, 0x6e, 0x67, 0x6f, 0x64, 0x62, 0x2f, 0x70,
192 | 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
193 | }
194 |
195 | var (
196 | file_post_proto_rawDescOnce sync.Once
197 | file_post_proto_rawDescData = file_post_proto_rawDesc
198 | )
199 |
200 | func file_post_proto_rawDescGZIP() []byte {
201 | file_post_proto_rawDescOnce.Do(func() {
202 | file_post_proto_rawDescData = protoimpl.X.CompressGZIP(file_post_proto_rawDescData)
203 | })
204 | return file_post_proto_rawDescData
205 | }
206 |
207 | var file_post_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
208 | var file_post_proto_goTypes = []interface{}{
209 | (*Post)(nil), // 0: pb.Post
210 | (*PostResponse)(nil), // 1: pb.PostResponse
211 | (*timestamppb.Timestamp)(nil), // 2: google.protobuf.Timestamp
212 | }
213 | var file_post_proto_depIdxs = []int32{
214 | 2, // 0: pb.Post.created_at:type_name -> google.protobuf.Timestamp
215 | 2, // 1: pb.Post.updated_at:type_name -> google.protobuf.Timestamp
216 | 0, // 2: pb.PostResponse.post:type_name -> pb.Post
217 | 3, // [3:3] is the sub-list for method output_type
218 | 3, // [3:3] is the sub-list for method input_type
219 | 3, // [3:3] is the sub-list for extension type_name
220 | 3, // [3:3] is the sub-list for extension extendee
221 | 0, // [0:3] is the sub-list for field type_name
222 | }
223 |
224 | func init() { file_post_proto_init() }
225 | func file_post_proto_init() {
226 | if File_post_proto != nil {
227 | return
228 | }
229 | if !protoimpl.UnsafeEnabled {
230 | file_post_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
231 | switch v := v.(*Post); i {
232 | case 0:
233 | return &v.state
234 | case 1:
235 | return &v.sizeCache
236 | case 2:
237 | return &v.unknownFields
238 | default:
239 | return nil
240 | }
241 | }
242 | file_post_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
243 | switch v := v.(*PostResponse); i {
244 | case 0:
245 | return &v.state
246 | case 1:
247 | return &v.sizeCache
248 | case 2:
249 | return &v.unknownFields
250 | default:
251 | return nil
252 | }
253 | }
254 | }
255 | type x struct{}
256 | out := protoimpl.TypeBuilder{
257 | File: protoimpl.DescBuilder{
258 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
259 | RawDescriptor: file_post_proto_rawDesc,
260 | NumEnums: 0,
261 | NumMessages: 2,
262 | NumExtensions: 0,
263 | NumServices: 0,
264 | },
265 | GoTypes: file_post_proto_goTypes,
266 | DependencyIndexes: file_post_proto_depIdxs,
267 | MessageInfos: file_post_proto_msgTypes,
268 | }.Build()
269 | File_post_proto = out.File
270 | file_post_proto_rawDesc = nil
271 | file_post_proto_goTypes = nil
272 | file_post_proto_depIdxs = nil
273 | }
274 |
--------------------------------------------------------------------------------
/controllers/auth.controller.go:
--------------------------------------------------------------------------------
1 | package controllers
2 |
3 | import (
4 | "context"
5 | "fmt"
6 | "log"
7 | "net/http"
8 | "strings"
9 | "time"
10 |
11 | "github.com/gin-gonic/gin"
12 | "github.com/thanhpk/randstr"
13 | "github.com/wpcodevo/golang-mongodb/config"
14 | "github.com/wpcodevo/golang-mongodb/models"
15 | "github.com/wpcodevo/golang-mongodb/services"
16 | "github.com/wpcodevo/golang-mongodb/utils"
17 | "go.mongodb.org/mongo-driver/bson"
18 | "go.mongodb.org/mongo-driver/mongo"
19 | )
20 |
21 | type AuthController struct {
22 | authService services.AuthService
23 | userService services.UserService
24 | ctx context.Context
25 | collection *mongo.Collection
26 | }
27 |
28 | func NewAuthController(authService services.AuthService, userService services.UserService, ctx context.Context, collection *mongo.Collection) AuthController {
29 | return AuthController{authService, userService, ctx, collection}
30 | }
31 |
32 | func (ac *AuthController) SignUpUser(ctx *gin.Context) {
33 | var user *models.SignUpInput
34 |
35 | if err := ctx.ShouldBindJSON(&user); err != nil {
36 | ctx.JSON(http.StatusBadRequest, gin.H{"status": "fail", "message": err.Error()})
37 | return
38 | }
39 |
40 | if user.Password != user.PasswordConfirm {
41 | ctx.JSON(http.StatusBadRequest, gin.H{"status": "fail", "message": "Passwords do not match"})
42 | return
43 | }
44 |
45 | newUser, err := ac.authService.SignUpUser(user)
46 |
47 | if err != nil {
48 | if strings.Contains(err.Error(), "email already exist") {
49 | ctx.JSON(http.StatusConflict, gin.H{"status": "error", "message": err.Error()})
50 | return
51 | }
52 | ctx.JSON(http.StatusBadGateway, gin.H{"status": "error", "message": err.Error()})
53 | return
54 | }
55 |
56 | config, err := config.LoadConfig(".")
57 | if err != nil {
58 | log.Fatal("Could not load config", err)
59 | }
60 |
61 | // Generate Verification Code
62 | code := randstr.String(20)
63 |
64 | verificationCode := utils.Encode(code)
65 |
66 | updateData := &models.UpdateInput{
67 | VerificationCode: verificationCode,
68 | }
69 |
70 | // Update User in Database
71 | ac.userService.UpdateUserById(newUser.ID.Hex(), updateData)
72 |
73 | var firstName = newUser.Name
74 |
75 | if strings.Contains(firstName, " ") {
76 | firstName = strings.Split(firstName, " ")[1]
77 | }
78 |
79 | // 👇 Send Email
80 | emailData := utils.EmailData{
81 | URL: config.Origin + "/verifyemail/" + code,
82 | FirstName: firstName,
83 | Subject: "Your account verification code",
84 | }
85 |
86 | err = utils.SendEmail(newUser, &emailData, "verificationCode.html")
87 | if err != nil {
88 | ctx.JSON(http.StatusBadGateway, gin.H{"status": "success", "message": "There was an error sending email"})
89 | return
90 | }
91 |
92 | message := "We sent an email with a verification code to " + user.Email
93 | ctx.JSON(http.StatusCreated, gin.H{"status": "success", "message": message})
94 | }
95 |
96 | func (ac *AuthController) SignInUser(ctx *gin.Context) {
97 | var credentials *models.SignInInput
98 |
99 | if err := ctx.ShouldBindJSON(&credentials); err != nil {
100 | ctx.JSON(http.StatusBadRequest, gin.H{"status": "fail", "message": err.Error()})
101 | return
102 | }
103 |
104 | user, err := ac.userService.FindUserByEmail(credentials.Email)
105 | if err != nil {
106 | if err == mongo.ErrNoDocuments {
107 | ctx.JSON(http.StatusBadRequest, gin.H{"status": "fail", "message": "Invalid email or password"})
108 | return
109 | }
110 | ctx.JSON(http.StatusBadRequest, gin.H{"status": "fail", "message": err.Error()})
111 | return
112 | }
113 |
114 | if !user.Verified {
115 | ctx.JSON(http.StatusUnauthorized, gin.H{"status": "fail", "message": "You are not verified, please verify your email to login"})
116 | return
117 | }
118 |
119 | if err := utils.VerifyPassword(user.Password, credentials.Password); err != nil {
120 | ctx.JSON(http.StatusBadRequest, gin.H{"status": "fail", "message": "Invalid email or Password"})
121 | return
122 | }
123 |
124 | config, _ := config.LoadConfig(".")
125 |
126 | // Generate Tokens
127 | access_token, err := utils.CreateToken(config.AccessTokenExpiresIn, user.ID, config.AccessTokenPrivateKey)
128 | if err != nil {
129 | ctx.JSON(http.StatusBadRequest, gin.H{"status": "fail", "message": err.Error()})
130 | return
131 | }
132 |
133 | refresh_token, err := utils.CreateToken(config.RefreshTokenExpiresIn, user.ID, config.RefreshTokenPrivateKey)
134 | if err != nil {
135 | ctx.JSON(http.StatusBadRequest, gin.H{"status": "fail", "message": err.Error()})
136 | return
137 | }
138 |
139 | ctx.SetCookie("access_token", access_token, config.AccessTokenMaxAge*60, "/", "localhost", false, true)
140 | ctx.SetCookie("refresh_token", refresh_token, config.RefreshTokenMaxAge*60, "/", "localhost", false, true)
141 | ctx.SetCookie("logged_in", "true", config.AccessTokenMaxAge*60, "/", "localhost", false, false)
142 |
143 | ctx.JSON(http.StatusOK, gin.H{"status": "success", "access_token": access_token})
144 | }
145 |
146 | func (ac *AuthController) RefreshAccessToken(ctx *gin.Context) {
147 | message := "could not refresh access token"
148 |
149 | cookie, err := ctx.Cookie("refresh_token")
150 |
151 | if err != nil {
152 | ctx.AbortWithStatusJSON(http.StatusForbidden, gin.H{"status": "fail", "message": message})
153 | return
154 | }
155 |
156 | config, _ := config.LoadConfig(".")
157 |
158 | sub, err := utils.ValidateToken(cookie, config.RefreshTokenPublicKey)
159 | if err != nil {
160 | ctx.AbortWithStatusJSON(http.StatusForbidden, gin.H{"status": "fail", "message": err.Error()})
161 | return
162 | }
163 |
164 | user, err := ac.userService.FindUserById(fmt.Sprint(sub))
165 | if err != nil {
166 | ctx.AbortWithStatusJSON(http.StatusForbidden, gin.H{"status": "fail", "message": "the user belonging to this token no logger exists"})
167 | return
168 | }
169 |
170 | access_token, err := utils.CreateToken(config.AccessTokenExpiresIn, user.ID, config.AccessTokenPrivateKey)
171 | if err != nil {
172 | ctx.AbortWithStatusJSON(http.StatusForbidden, gin.H{"status": "fail", "message": err.Error()})
173 | return
174 | }
175 |
176 | ctx.SetCookie("access_token", access_token, config.AccessTokenMaxAge*60, "/", "localhost", false, true)
177 | ctx.SetCookie("logged_in", "true", config.AccessTokenMaxAge*60, "/", "localhost", false, false)
178 |
179 | ctx.JSON(http.StatusOK, gin.H{"status": "success", "access_token": access_token})
180 | }
181 |
182 | func (ac *AuthController) LogoutUser(ctx *gin.Context) {
183 | ctx.SetCookie("access_token", "", -1, "/", "localhost", false, true)
184 | ctx.SetCookie("refresh_token", "", -1, "/", "localhost", false, true)
185 | ctx.SetCookie("logged_in", "", -1, "/", "localhost", false, true)
186 |
187 | ctx.JSON(http.StatusOK, gin.H{"status": "success"})
188 | }
189 |
190 | func (ac *AuthController) VerifyEmail(ctx *gin.Context) {
191 |
192 | code := ctx.Params.ByName("verificationCode")
193 | verificationCode := utils.Encode(code)
194 |
195 | query := bson.D{{Key: "verificationCode", Value: verificationCode}}
196 | update := bson.D{{Key: "$set", Value: bson.D{{Key: "verified", Value: true}}}, {Key: "$unset", Value: bson.D{{Key: "verificationCode", Value: ""}}}}
197 | result, err := ac.collection.UpdateOne(ac.ctx, query, update)
198 | if err != nil {
199 | ctx.JSON(http.StatusForbidden, gin.H{"status": "success", "message": err.Error()})
200 | return
201 | }
202 |
203 | if result.MatchedCount == 0 {
204 | ctx.JSON(http.StatusForbidden, gin.H{"status": "success", "message": "Could not verify email address"})
205 | return
206 | }
207 |
208 | fmt.Println(result)
209 |
210 | ctx.JSON(http.StatusOK, gin.H{"status": "success", "message": "Email verified successfully"})
211 |
212 | }
213 |
214 | func (ac *AuthController) ForgotPassword(ctx *gin.Context) {
215 | var userCredential *models.ForgotPasswordInput
216 |
217 | if err := ctx.ShouldBindJSON(&userCredential); err != nil {
218 | ctx.JSON(http.StatusBadRequest, gin.H{"status": "fail", "message": err.Error()})
219 | return
220 | }
221 |
222 | message := "You will receive a reset email if user with that email exist"
223 |
224 | user, err := ac.userService.FindUserByEmail(userCredential.Email)
225 | if err != nil {
226 | if err == mongo.ErrNoDocuments {
227 | ctx.JSON(http.StatusOK, gin.H{"status": "fail", "message": message})
228 | return
229 | }
230 | ctx.JSON(http.StatusBadGateway, gin.H{"status": "error", "message": err.Error()})
231 | return
232 | }
233 |
234 | if !user.Verified {
235 | ctx.JSON(http.StatusUnauthorized, gin.H{"status": "error", "message": "Account not verified"})
236 | return
237 | }
238 |
239 | config, err := config.LoadConfig(".")
240 | if err != nil {
241 | log.Fatal("Could not load config", err)
242 | }
243 |
244 | // Generate Verification Code
245 | resetToken := randstr.String(20)
246 |
247 | passwordResetToken := utils.Encode(resetToken)
248 |
249 | // Update User in Database
250 | query := bson.D{{Key: "email", Value: strings.ToLower(userCredential.Email)}}
251 | update := bson.D{{Key: "$set", Value: bson.D{{Key: "passwordResetToken", Value: passwordResetToken}, {Key: "passwordResetAt", Value: time.Now().Add(time.Minute * 15)}}}}
252 | result, err := ac.collection.UpdateOne(ac.ctx, query, update)
253 |
254 | if result.MatchedCount == 0 {
255 | ctx.JSON(http.StatusBadGateway, gin.H{"status": "success", "message": "There was an error sending email"})
256 | return
257 | }
258 |
259 | if err != nil {
260 | ctx.JSON(http.StatusForbidden, gin.H{"status": "success", "message": err.Error()})
261 | return
262 | }
263 | var firstName = user.Name
264 |
265 | if strings.Contains(firstName, " ") {
266 | firstName = strings.Split(firstName, " ")[1]
267 | }
268 |
269 | // 👇 Send Email
270 | emailData := utils.EmailData{
271 | URL: config.Origin + "/forgotPassword/" + resetToken,
272 | FirstName: firstName,
273 | Subject: "Your password reset token (valid for 10min)",
274 | }
275 |
276 | err = utils.SendEmail(user, &emailData, "resetPassword.html")
277 | if err != nil {
278 | ctx.JSON(http.StatusBadGateway, gin.H{"status": "success", "message": "There was an error sending email"})
279 | return
280 | }
281 | ctx.JSON(http.StatusOK, gin.H{"status": "success", "message": message})
282 | }
283 |
--------------------------------------------------------------------------------
/readMe.md:
--------------------------------------------------------------------------------
1 | # Build gRPC Server API & Client with Golang and MongoDB
2 |
3 | ## 1. API with Golang + MongoDB + Redis + Gin Gonic: Project Setup
4 |
5 | In this article, you'll learn how to set up a Golang application with MongoDB-Go-driver, Gin Gonic, and Go Redis. Later, we'll access both the Redis and MongoDB databases directly in VS Code using a MySQL VS Code extension.
6 |
7 | 
8 |
9 | ### Topics Covered
10 |
11 | - Setup Golang with MongoDB and Redis
12 | - Creating MongoDB and Redis Database with Docker-compose
13 | - Setup Environment Variables
14 | - How to Connect Golang App to Redis and MongoDB
15 | - Test the Golang API
16 | - How to Connect to MongoDB and Redis Servers in VS Code
17 |
18 | Read the entire article here: [https://codevoweb.com/api-golang-mongodb-gin-gonic-project-setup](https://codevoweb.com/api-golang-mongodb-gin-gonic-project-setup)
19 |
20 |
21 | ## 2. Golang & MongoDB: JWT Authentication and Authorization
22 |
23 | In this article, you'll learn how to implement RS256 JWT (JSON Web Token) Authentication and Authorization with Golang, Gin Gonic, MongoDB-Go-driver, and Docker-compose.
24 |
25 | 
26 |
27 | ### Topics Covered
28 |
29 | - Golang & MongoDB JWT Authentication Overview
30 | - JWT Authentication Example with Golang and MongoDB
31 | - How to Generate Public and Private Keys
32 | - Update Environment Variables with Viper
33 | - Creating the User models with structs
34 | - Creating an Auth and User Interfaces
35 | - Authentication Interface
36 | - User Interface
37 | - Create utility functions to hash and verify password
38 | - Create services that interact with the database
39 | - Auth interface implementation
40 | - User interface implementation
41 | - Create a utility function to sign and verify JWT tokens
42 | - Create Json Web Token
43 | - Verify JSON Web Token
44 | - Create the authentication controllers
45 | - Signup user controller
46 | - Login user controller
47 | - Refresh access token controller
48 | - Logout user controller
49 | - Authentication Middleware Guard
50 | - Create the user controllers
51 | - Create API Routes with Gin
52 | - Auth Routes
53 | - User Routes
54 | - Add the Routes to the Gin Middleware Pipeline
55 |
56 | Read the entire article here: [https://codevoweb.com/golang-mongodb-jwt-authentication-authorization](https://codevoweb.com/golang-mongodb-jwt-authentication-authorization)
57 |
58 | ## 3. API with Golang + MongoDB: Send HTML Emails with Gomail
59 |
60 | In this article, you'll learn how to send HTML emails with Golang, Gomail, MongoDB-Go-Driver, Redis, and Docker-compose. Also, you'll learn how to generate HTML templates with the standard Golang html/template package.
61 |
62 | 
63 |
64 | ### Topics Covered
65 |
66 | - Send Emails with Golang, MongoDB, and Gomail Overview
67 | - Creating the HTML Email Templates with Golang
68 | - Create an SMTP Provider Account
69 | - Load and Validate Environment Variables Viper
70 | - Create a Utility Function to Send the Emails
71 | - Update the SignUp Controller
72 |
73 | Read the entire article here: [https://codevoweb.com/api-golang-mongodb-send-html-emails-gomail](https://codevoweb.com/api-golang-mongodb-send-html-emails-gomail)
74 |
75 |
76 | ## 4. API with Golang, Gin Gonic & MongoDB: Forget/Reset Password
77 |
78 | In this article, you'll learn how to implement forget/reset password functionality with Golang, Gin Gonic, Gomail, MongoDB-Go-driver, Redis, and Docker-compose.
79 |
80 | 
81 |
82 | ### Topics Covered
83 |
84 | - Forget/Reset Password with Golang, Gin, and MongoDB
85 | - Create the MongoDB Model Structs
86 | - Create the HTML Email Templates with Golang
87 | - Define a Utility Function to Parse the HTML Templates
88 | - Create a Function to Send the HTML Emails
89 | - Add the Forgot Password Controller
90 | - Add the Reset Password Controller
91 | - Register the Gin API Routes
92 |
93 | Read the entire article here: [https://codevoweb.com/api-golang-gin-gonic-mongodb-forget-reset-password](https://codevoweb.com/api-golang-gin-gonic-mongodb-forget-reset-password)
94 |
95 |
96 | ## 5. Build Golang gRPC Server and Client: SignUp User & Verify Email
97 |
98 | In this article, you'll learn how to create a gRPC server to register a user and verify their email address using Golang, MongoDB-Go-driver, Gomail, and Docker-compose.
99 |
100 | 
101 |
102 | ### Topics Covered
103 |
104 | - gRPC Project setup in Golang
105 | - Create the gRPC Request and Response Messages
106 | - Define the gRPC User messages
107 | - Define the gRPC Request and Response Message to SignUp User
108 | - Create the gRPC Service Methods
109 | - Generate the gRPC client and server interfaces
110 | - Start the gRPC Server
111 | - Test the gRPC API Server with Golang Evans
112 | - Create the gRPC API Controllers
113 | - Register User gRPC Controller
114 | - Verify User gRPC Controller
115 | - Create the gRPC Client to Register a User
116 |
117 | Read the entire article here: [https://codevoweb.com/golang-grpc-server-and-client-signup-user-verify-email](https://codevoweb.com/golang-grpc-server-and-client-signup-user-verify-email)
118 |
119 | ## 6. Build Golang gRPC Server and Client: Access & Refresh Tokens
120 |
121 | In this article, you'll learn how to implement JWT access and refresh tokens with gRPC using Golang, MongoDB-Go-driver, Gomail, Docker, and Docker-compose.
122 |
123 | 
124 |
125 | ### Topics Covered
126 |
127 | - Create the gRPC Request and Response Messages
128 | - Create the gRPC User messages
129 | - Define the gRPC Request and Response Message to Login User
130 | - Update the Authentication gRPC Service
131 | - Create a gRPC User Service
132 | - Create the gRPC Controllers
133 | - Create the gRPC Servers
134 | - Register the gRPC Servers
135 | - Create the gRPC Clients in Golang
136 | - Connect the gRPC Client to the gRPC Server
137 |
138 | Read the entire article here: [https://codevoweb.com/golang-grpc-server-and-client-access-refresh-tokens](https://codevoweb.com/golang-grpc-server-and-client-access-refresh-tokens)
139 |
140 | ## 7. Build CRUD RESTful API Server with Golang, Gin, and MongoDB
141 |
142 | In this article, you'll learn how to build a CRUD RESTful API server with Golang, Gin Gonic, MongoDB-Go-driver, Docker, and Docker-compose.
143 |
144 | 
145 |
146 | ### Topics Covered
147 |
148 | - Golang, Gin Gonic, MongoDB CRUD RESTful API Overview
149 | - Create the Models with Structs
150 | - Create the Service Interface
151 | - Create Methods to Implement the Interface
152 | - Initialize the Service Struct
153 | - Define a Service to Create a Post
154 | - Define a Service to Update Post
155 | - Define a Service to Delete Post
156 | - Define a Service to Get Single Post
157 | - Define a Service to Get All Posts
158 | - Create Controllers to Perform the CRUD Operations
159 | - Initialize the Controller Struct
160 | - Define a Controller to Create a Post
161 | - Define a Controller to Update a Post
162 | - Define a Controller to Delete a Post
163 | - Define a Controller to Get a Single Post
164 | - Define a Controller to Get All Posts
165 | - Create the Routes for the Controllers
166 | - Initialize the Constructors and Start the Gin Server
167 |
168 | Read the entire article here: [https://codevoweb.com/crud-restful-api-server-with-golang-and-mongodb](https://codevoweb.com/crud-restful-api-server-with-golang-and-mongodb)
169 |
170 |
171 | ## 8. Build CRUD gRPC Server API & Client with Golang and MongoDB
172 |
173 | In this article, you'll learn how to build a CRUD gRPC API server with Golang, MongoDB-Go-driver, and Docker-compose. You'll also build a gRPC client to interact with the gRPC API.
174 |
175 | 
176 |
177 | ### Topics Covered
178 |
179 | - Define the Models with Structs
180 | - Create the ProtoBuf Messages
181 | - Define the gRPC Service and RPC Methods
182 | - Define a Custom Service Interface
183 | - Create Methods to Implement the Service Interface
184 | - Create a Constructor to Implement the Service Interface
185 | - Create a new Post
186 | - Update a Post
187 | - Find a Post
188 | - Retrieve All Posts
189 | - Delete a Post
190 | - Define the gRPC Controllers
191 | - Register the gRPC Services and Start the gRPC Server
192 | - Test the gRPC API Server with Evans CLI
193 | - Create the gRPC API Handlers in Golang
194 | - CreatePost gRPC Handler
195 | - UpdatePost gRPC Service Handler
196 | - GetPost gRPC Service Handler
197 | - DeletePost gRPC Service Handler
198 | - GetPosts gRPC Service Handler
199 | - Testing the gRPC Services with Evans Cli
200 | - Create the gRPC Clients
201 | - gRPC Client to Create a Post
202 | - gRPC Client to Update a Post
203 | - gRPC Client to Get a Single Post
204 | - gRPC Client to Get All Posts
205 | - gRPC Client to Delete a Post
206 | - Register the gRPC Services
207 |
208 | Read the entire article here: [https://codevoweb.com/crud-grpc-server-api-client-with-golang-and-mongodb](https://codevoweb.com/crud-grpc-server-api-client-with-golang-and-mongodb)
209 |
--------------------------------------------------------------------------------
/pb/post_service_grpc.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-go-grpc. DO NOT EDIT.
2 | // versions:
3 | // - protoc-gen-go-grpc v1.2.0
4 | // - protoc v3.20.1
5 | // source: post_service.proto
6 |
7 | package pb
8 |
9 | import (
10 | context "context"
11 | grpc "google.golang.org/grpc"
12 | codes "google.golang.org/grpc/codes"
13 | status "google.golang.org/grpc/status"
14 | )
15 |
16 | // This is a compile-time assertion to ensure that this generated file
17 | // is compatible with the grpc package it is being compiled against.
18 | // Requires gRPC-Go v1.32.0 or later.
19 | const _ = grpc.SupportPackageIsVersion7
20 |
21 | // PostServiceClient is the client API for PostService service.
22 | //
23 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
24 | type PostServiceClient interface {
25 | CreatePost(ctx context.Context, in *CreatePostRequest, opts ...grpc.CallOption) (*PostResponse, error)
26 | GetPost(ctx context.Context, in *PostRequest, opts ...grpc.CallOption) (*PostResponse, error)
27 | GetPosts(ctx context.Context, in *GetPostsRequest, opts ...grpc.CallOption) (PostService_GetPostsClient, error)
28 | UpdatePost(ctx context.Context, in *UpdatePostRequest, opts ...grpc.CallOption) (*PostResponse, error)
29 | DeletePost(ctx context.Context, in *PostRequest, opts ...grpc.CallOption) (*DeletePostResponse, error)
30 | }
31 |
32 | type postServiceClient struct {
33 | cc grpc.ClientConnInterface
34 | }
35 |
36 | func NewPostServiceClient(cc grpc.ClientConnInterface) PostServiceClient {
37 | return &postServiceClient{cc}
38 | }
39 |
40 | func (c *postServiceClient) CreatePost(ctx context.Context, in *CreatePostRequest, opts ...grpc.CallOption) (*PostResponse, error) {
41 | out := new(PostResponse)
42 | err := c.cc.Invoke(ctx, "/pb.PostService/CreatePost", in, out, opts...)
43 | if err != nil {
44 | return nil, err
45 | }
46 | return out, nil
47 | }
48 |
49 | func (c *postServiceClient) GetPost(ctx context.Context, in *PostRequest, opts ...grpc.CallOption) (*PostResponse, error) {
50 | out := new(PostResponse)
51 | err := c.cc.Invoke(ctx, "/pb.PostService/GetPost", in, out, opts...)
52 | if err != nil {
53 | return nil, err
54 | }
55 | return out, nil
56 | }
57 |
58 | func (c *postServiceClient) GetPosts(ctx context.Context, in *GetPostsRequest, opts ...grpc.CallOption) (PostService_GetPostsClient, error) {
59 | stream, err := c.cc.NewStream(ctx, &PostService_ServiceDesc.Streams[0], "/pb.PostService/GetPosts", opts...)
60 | if err != nil {
61 | return nil, err
62 | }
63 | x := &postServiceGetPostsClient{stream}
64 | if err := x.ClientStream.SendMsg(in); err != nil {
65 | return nil, err
66 | }
67 | if err := x.ClientStream.CloseSend(); err != nil {
68 | return nil, err
69 | }
70 | return x, nil
71 | }
72 |
73 | type PostService_GetPostsClient interface {
74 | Recv() (*Post, error)
75 | grpc.ClientStream
76 | }
77 |
78 | type postServiceGetPostsClient struct {
79 | grpc.ClientStream
80 | }
81 |
82 | func (x *postServiceGetPostsClient) Recv() (*Post, error) {
83 | m := new(Post)
84 | if err := x.ClientStream.RecvMsg(m); err != nil {
85 | return nil, err
86 | }
87 | return m, nil
88 | }
89 |
90 | func (c *postServiceClient) UpdatePost(ctx context.Context, in *UpdatePostRequest, opts ...grpc.CallOption) (*PostResponse, error) {
91 | out := new(PostResponse)
92 | err := c.cc.Invoke(ctx, "/pb.PostService/UpdatePost", in, out, opts...)
93 | if err != nil {
94 | return nil, err
95 | }
96 | return out, nil
97 | }
98 |
99 | func (c *postServiceClient) DeletePost(ctx context.Context, in *PostRequest, opts ...grpc.CallOption) (*DeletePostResponse, error) {
100 | out := new(DeletePostResponse)
101 | err := c.cc.Invoke(ctx, "/pb.PostService/DeletePost", in, out, opts...)
102 | if err != nil {
103 | return nil, err
104 | }
105 | return out, nil
106 | }
107 |
108 | // PostServiceServer is the server API for PostService service.
109 | // All implementations must embed UnimplementedPostServiceServer
110 | // for forward compatibility
111 | type PostServiceServer interface {
112 | CreatePost(context.Context, *CreatePostRequest) (*PostResponse, error)
113 | GetPost(context.Context, *PostRequest) (*PostResponse, error)
114 | GetPosts(*GetPostsRequest, PostService_GetPostsServer) error
115 | UpdatePost(context.Context, *UpdatePostRequest) (*PostResponse, error)
116 | DeletePost(context.Context, *PostRequest) (*DeletePostResponse, error)
117 | mustEmbedUnimplementedPostServiceServer()
118 | }
119 |
120 | // UnimplementedPostServiceServer must be embedded to have forward compatible implementations.
121 | type UnimplementedPostServiceServer struct {
122 | }
123 |
124 | func (UnimplementedPostServiceServer) CreatePost(context.Context, *CreatePostRequest) (*PostResponse, error) {
125 | return nil, status.Errorf(codes.Unimplemented, "method CreatePost not implemented")
126 | }
127 | func (UnimplementedPostServiceServer) GetPost(context.Context, *PostRequest) (*PostResponse, error) {
128 | return nil, status.Errorf(codes.Unimplemented, "method GetPost not implemented")
129 | }
130 | func (UnimplementedPostServiceServer) GetPosts(*GetPostsRequest, PostService_GetPostsServer) error {
131 | return status.Errorf(codes.Unimplemented, "method GetPosts not implemented")
132 | }
133 | func (UnimplementedPostServiceServer) UpdatePost(context.Context, *UpdatePostRequest) (*PostResponse, error) {
134 | return nil, status.Errorf(codes.Unimplemented, "method UpdatePost not implemented")
135 | }
136 | func (UnimplementedPostServiceServer) DeletePost(context.Context, *PostRequest) (*DeletePostResponse, error) {
137 | return nil, status.Errorf(codes.Unimplemented, "method DeletePost not implemented")
138 | }
139 | func (UnimplementedPostServiceServer) mustEmbedUnimplementedPostServiceServer() {}
140 |
141 | // UnsafePostServiceServer may be embedded to opt out of forward compatibility for this service.
142 | // Use of this interface is not recommended, as added methods to PostServiceServer will
143 | // result in compilation errors.
144 | type UnsafePostServiceServer interface {
145 | mustEmbedUnimplementedPostServiceServer()
146 | }
147 |
148 | func RegisterPostServiceServer(s grpc.ServiceRegistrar, srv PostServiceServer) {
149 | s.RegisterService(&PostService_ServiceDesc, srv)
150 | }
151 |
152 | func _PostService_CreatePost_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
153 | in := new(CreatePostRequest)
154 | if err := dec(in); err != nil {
155 | return nil, err
156 | }
157 | if interceptor == nil {
158 | return srv.(PostServiceServer).CreatePost(ctx, in)
159 | }
160 | info := &grpc.UnaryServerInfo{
161 | Server: srv,
162 | FullMethod: "/pb.PostService/CreatePost",
163 | }
164 | handler := func(ctx context.Context, req interface{}) (interface{}, error) {
165 | return srv.(PostServiceServer).CreatePost(ctx, req.(*CreatePostRequest))
166 | }
167 | return interceptor(ctx, in, info, handler)
168 | }
169 |
170 | func _PostService_GetPost_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
171 | in := new(PostRequest)
172 | if err := dec(in); err != nil {
173 | return nil, err
174 | }
175 | if interceptor == nil {
176 | return srv.(PostServiceServer).GetPost(ctx, in)
177 | }
178 | info := &grpc.UnaryServerInfo{
179 | Server: srv,
180 | FullMethod: "/pb.PostService/GetPost",
181 | }
182 | handler := func(ctx context.Context, req interface{}) (interface{}, error) {
183 | return srv.(PostServiceServer).GetPost(ctx, req.(*PostRequest))
184 | }
185 | return interceptor(ctx, in, info, handler)
186 | }
187 |
188 | func _PostService_GetPosts_Handler(srv interface{}, stream grpc.ServerStream) error {
189 | m := new(GetPostsRequest)
190 | if err := stream.RecvMsg(m); err != nil {
191 | return err
192 | }
193 | return srv.(PostServiceServer).GetPosts(m, &postServiceGetPostsServer{stream})
194 | }
195 |
196 | type PostService_GetPostsServer interface {
197 | Send(*Post) error
198 | grpc.ServerStream
199 | }
200 |
201 | type postServiceGetPostsServer struct {
202 | grpc.ServerStream
203 | }
204 |
205 | func (x *postServiceGetPostsServer) Send(m *Post) error {
206 | return x.ServerStream.SendMsg(m)
207 | }
208 |
209 | func _PostService_UpdatePost_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
210 | in := new(UpdatePostRequest)
211 | if err := dec(in); err != nil {
212 | return nil, err
213 | }
214 | if interceptor == nil {
215 | return srv.(PostServiceServer).UpdatePost(ctx, in)
216 | }
217 | info := &grpc.UnaryServerInfo{
218 | Server: srv,
219 | FullMethod: "/pb.PostService/UpdatePost",
220 | }
221 | handler := func(ctx context.Context, req interface{}) (interface{}, error) {
222 | return srv.(PostServiceServer).UpdatePost(ctx, req.(*UpdatePostRequest))
223 | }
224 | return interceptor(ctx, in, info, handler)
225 | }
226 |
227 | func _PostService_DeletePost_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
228 | in := new(PostRequest)
229 | if err := dec(in); err != nil {
230 | return nil, err
231 | }
232 | if interceptor == nil {
233 | return srv.(PostServiceServer).DeletePost(ctx, in)
234 | }
235 | info := &grpc.UnaryServerInfo{
236 | Server: srv,
237 | FullMethod: "/pb.PostService/DeletePost",
238 | }
239 | handler := func(ctx context.Context, req interface{}) (interface{}, error) {
240 | return srv.(PostServiceServer).DeletePost(ctx, req.(*PostRequest))
241 | }
242 | return interceptor(ctx, in, info, handler)
243 | }
244 |
245 | // PostService_ServiceDesc is the grpc.ServiceDesc for PostService service.
246 | // It's only intended for direct use with grpc.RegisterService,
247 | // and not to be introspected or modified (even as a copy)
248 | var PostService_ServiceDesc = grpc.ServiceDesc{
249 | ServiceName: "pb.PostService",
250 | HandlerType: (*PostServiceServer)(nil),
251 | Methods: []grpc.MethodDesc{
252 | {
253 | MethodName: "CreatePost",
254 | Handler: _PostService_CreatePost_Handler,
255 | },
256 | {
257 | MethodName: "GetPost",
258 | Handler: _PostService_GetPost_Handler,
259 | },
260 | {
261 | MethodName: "UpdatePost",
262 | Handler: _PostService_UpdatePost_Handler,
263 | },
264 | {
265 | MethodName: "DeletePost",
266 | Handler: _PostService_DeletePost_Handler,
267 | },
268 | },
269 | Streams: []grpc.StreamDesc{
270 | {
271 | StreamName: "GetPosts",
272 | Handler: _PostService_GetPosts_Handler,
273 | ServerStreams: true,
274 | },
275 | },
276 | Metadata: "post_service.proto",
277 | }
278 |
--------------------------------------------------------------------------------
/pb/user.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-go. DO NOT EDIT.
2 | // versions:
3 | // protoc-gen-go v1.28.0
4 | // protoc v3.20.1
5 | // source: user.proto
6 |
7 | package pb
8 |
9 | import (
10 | protoreflect "google.golang.org/protobuf/reflect/protoreflect"
11 | protoimpl "google.golang.org/protobuf/runtime/protoimpl"
12 | timestamppb "google.golang.org/protobuf/types/known/timestamppb"
13 | reflect "reflect"
14 | sync "sync"
15 | )
16 |
17 | const (
18 | // Verify that this generated code is sufficiently up-to-date.
19 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
20 | // Verify that runtime/protoimpl is sufficiently up-to-date.
21 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
22 | )
23 |
24 | type User struct {
25 | state protoimpl.MessageState
26 | sizeCache protoimpl.SizeCache
27 | unknownFields protoimpl.UnknownFields
28 |
29 | Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
30 | Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
31 | Email string `protobuf:"bytes,3,opt,name=email,proto3" json:"email,omitempty"`
32 | Role string `protobuf:"bytes,4,opt,name=role,proto3" json:"role,omitempty"`
33 | CreatedAt *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
34 | UpdatedAt *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"`
35 | }
36 |
37 | func (x *User) Reset() {
38 | *x = User{}
39 | if protoimpl.UnsafeEnabled {
40 | mi := &file_user_proto_msgTypes[0]
41 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
42 | ms.StoreMessageInfo(mi)
43 | }
44 | }
45 |
46 | func (x *User) String() string {
47 | return protoimpl.X.MessageStringOf(x)
48 | }
49 |
50 | func (*User) ProtoMessage() {}
51 |
52 | func (x *User) ProtoReflect() protoreflect.Message {
53 | mi := &file_user_proto_msgTypes[0]
54 | if protoimpl.UnsafeEnabled && x != nil {
55 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
56 | if ms.LoadMessageInfo() == nil {
57 | ms.StoreMessageInfo(mi)
58 | }
59 | return ms
60 | }
61 | return mi.MessageOf(x)
62 | }
63 |
64 | // Deprecated: Use User.ProtoReflect.Descriptor instead.
65 | func (*User) Descriptor() ([]byte, []int) {
66 | return file_user_proto_rawDescGZIP(), []int{0}
67 | }
68 |
69 | func (x *User) GetId() string {
70 | if x != nil {
71 | return x.Id
72 | }
73 | return ""
74 | }
75 |
76 | func (x *User) GetName() string {
77 | if x != nil {
78 | return x.Name
79 | }
80 | return ""
81 | }
82 |
83 | func (x *User) GetEmail() string {
84 | if x != nil {
85 | return x.Email
86 | }
87 | return ""
88 | }
89 |
90 | func (x *User) GetRole() string {
91 | if x != nil {
92 | return x.Role
93 | }
94 | return ""
95 | }
96 |
97 | func (x *User) GetCreatedAt() *timestamppb.Timestamp {
98 | if x != nil {
99 | return x.CreatedAt
100 | }
101 | return nil
102 | }
103 |
104 | func (x *User) GetUpdatedAt() *timestamppb.Timestamp {
105 | if x != nil {
106 | return x.UpdatedAt
107 | }
108 | return nil
109 | }
110 |
111 | type UserResponse struct {
112 | state protoimpl.MessageState
113 | sizeCache protoimpl.SizeCache
114 | unknownFields protoimpl.UnknownFields
115 |
116 | User *User `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"`
117 | }
118 |
119 | func (x *UserResponse) Reset() {
120 | *x = UserResponse{}
121 | if protoimpl.UnsafeEnabled {
122 | mi := &file_user_proto_msgTypes[1]
123 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
124 | ms.StoreMessageInfo(mi)
125 | }
126 | }
127 |
128 | func (x *UserResponse) String() string {
129 | return protoimpl.X.MessageStringOf(x)
130 | }
131 |
132 | func (*UserResponse) ProtoMessage() {}
133 |
134 | func (x *UserResponse) ProtoReflect() protoreflect.Message {
135 | mi := &file_user_proto_msgTypes[1]
136 | if protoimpl.UnsafeEnabled && x != nil {
137 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
138 | if ms.LoadMessageInfo() == nil {
139 | ms.StoreMessageInfo(mi)
140 | }
141 | return ms
142 | }
143 | return mi.MessageOf(x)
144 | }
145 |
146 | // Deprecated: Use UserResponse.ProtoReflect.Descriptor instead.
147 | func (*UserResponse) Descriptor() ([]byte, []int) {
148 | return file_user_proto_rawDescGZIP(), []int{1}
149 | }
150 |
151 | func (x *UserResponse) GetUser() *User {
152 | if x != nil {
153 | return x.User
154 | }
155 | return nil
156 | }
157 |
158 | type GenericResponse struct {
159 | state protoimpl.MessageState
160 | sizeCache protoimpl.SizeCache
161 | unknownFields protoimpl.UnknownFields
162 |
163 | Status string `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"`
164 | Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"`
165 | }
166 |
167 | func (x *GenericResponse) Reset() {
168 | *x = GenericResponse{}
169 | if protoimpl.UnsafeEnabled {
170 | mi := &file_user_proto_msgTypes[2]
171 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
172 | ms.StoreMessageInfo(mi)
173 | }
174 | }
175 |
176 | func (x *GenericResponse) String() string {
177 | return protoimpl.X.MessageStringOf(x)
178 | }
179 |
180 | func (*GenericResponse) ProtoMessage() {}
181 |
182 | func (x *GenericResponse) ProtoReflect() protoreflect.Message {
183 | mi := &file_user_proto_msgTypes[2]
184 | if protoimpl.UnsafeEnabled && x != nil {
185 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
186 | if ms.LoadMessageInfo() == nil {
187 | ms.StoreMessageInfo(mi)
188 | }
189 | return ms
190 | }
191 | return mi.MessageOf(x)
192 | }
193 |
194 | // Deprecated: Use GenericResponse.ProtoReflect.Descriptor instead.
195 | func (*GenericResponse) Descriptor() ([]byte, []int) {
196 | return file_user_proto_rawDescGZIP(), []int{2}
197 | }
198 |
199 | func (x *GenericResponse) GetStatus() string {
200 | if x != nil {
201 | return x.Status
202 | }
203 | return ""
204 | }
205 |
206 | func (x *GenericResponse) GetMessage() string {
207 | if x != nil {
208 | return x.Message
209 | }
210 | return ""
211 | }
212 |
213 | var File_user_proto protoreflect.FileDescriptor
214 |
215 | var file_user_proto_rawDesc = []byte{
216 | 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x70, 0x62,
217 | 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
218 | 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74,
219 | 0x6f, 0x22, 0xca, 0x01, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64,
220 | 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
221 | 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14,
222 | 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65,
223 | 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01,
224 | 0x28, 0x09, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61,
225 | 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67,
226 | 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54,
227 | 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65,
228 | 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61,
229 | 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
230 | 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74,
231 | 0x61, 0x6d, 0x70, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0x2c,
232 | 0x0a, 0x0c, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c,
233 | 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x70,
234 | 0x62, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, 0x43, 0x0a, 0x0f,
235 | 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
236 | 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
237 | 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61,
238 | 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
239 | 0x65, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
240 | 0x77, 0x70, 0x63, 0x6f, 0x64, 0x65, 0x76, 0x6f, 0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2d,
241 | 0x6d, 0x6f, 0x6e, 0x67, 0x6f, 0x64, 0x62, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
242 | 0x6f, 0x33,
243 | }
244 |
245 | var (
246 | file_user_proto_rawDescOnce sync.Once
247 | file_user_proto_rawDescData = file_user_proto_rawDesc
248 | )
249 |
250 | func file_user_proto_rawDescGZIP() []byte {
251 | file_user_proto_rawDescOnce.Do(func() {
252 | file_user_proto_rawDescData = protoimpl.X.CompressGZIP(file_user_proto_rawDescData)
253 | })
254 | return file_user_proto_rawDescData
255 | }
256 |
257 | var file_user_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
258 | var file_user_proto_goTypes = []interface{}{
259 | (*User)(nil), // 0: pb.User
260 | (*UserResponse)(nil), // 1: pb.UserResponse
261 | (*GenericResponse)(nil), // 2: pb.GenericResponse
262 | (*timestamppb.Timestamp)(nil), // 3: google.protobuf.Timestamp
263 | }
264 | var file_user_proto_depIdxs = []int32{
265 | 3, // 0: pb.User.created_at:type_name -> google.protobuf.Timestamp
266 | 3, // 1: pb.User.updated_at:type_name -> google.protobuf.Timestamp
267 | 0, // 2: pb.UserResponse.user:type_name -> pb.User
268 | 3, // [3:3] is the sub-list for method output_type
269 | 3, // [3:3] is the sub-list for method input_type
270 | 3, // [3:3] is the sub-list for extension type_name
271 | 3, // [3:3] is the sub-list for extension extendee
272 | 0, // [0:3] is the sub-list for field type_name
273 | }
274 |
275 | func init() { file_user_proto_init() }
276 | func file_user_proto_init() {
277 | if File_user_proto != nil {
278 | return
279 | }
280 | if !protoimpl.UnsafeEnabled {
281 | file_user_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
282 | switch v := v.(*User); i {
283 | case 0:
284 | return &v.state
285 | case 1:
286 | return &v.sizeCache
287 | case 2:
288 | return &v.unknownFields
289 | default:
290 | return nil
291 | }
292 | }
293 | file_user_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
294 | switch v := v.(*UserResponse); i {
295 | case 0:
296 | return &v.state
297 | case 1:
298 | return &v.sizeCache
299 | case 2:
300 | return &v.unknownFields
301 | default:
302 | return nil
303 | }
304 | }
305 | file_user_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
306 | switch v := v.(*GenericResponse); i {
307 | case 0:
308 | return &v.state
309 | case 1:
310 | return &v.sizeCache
311 | case 2:
312 | return &v.unknownFields
313 | default:
314 | return nil
315 | }
316 | }
317 | }
318 | type x struct{}
319 | out := protoimpl.TypeBuilder{
320 | File: protoimpl.DescBuilder{
321 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
322 | RawDescriptor: file_user_proto_rawDesc,
323 | NumEnums: 0,
324 | NumMessages: 3,
325 | NumExtensions: 0,
326 | NumServices: 0,
327 | },
328 | GoTypes: file_user_proto_goTypes,
329 | DependencyIndexes: file_user_proto_depIdxs,
330 | MessageInfos: file_user_proto_msgTypes,
331 | }.Build()
332 | File_user_proto = out.File
333 | file_user_proto_rawDesc = nil
334 | file_user_proto_goTypes = nil
335 | file_user_proto_depIdxs = nil
336 | }
337 |
--------------------------------------------------------------------------------
/pb/post_service.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-go. DO NOT EDIT.
2 | // versions:
3 | // protoc-gen-go v1.28.0
4 | // protoc v3.20.1
5 | // source: post_service.proto
6 |
7 | package pb
8 |
9 | import (
10 | protoreflect "google.golang.org/protobuf/reflect/protoreflect"
11 | protoimpl "google.golang.org/protobuf/runtime/protoimpl"
12 | reflect "reflect"
13 | sync "sync"
14 | )
15 |
16 | const (
17 | // Verify that this generated code is sufficiently up-to-date.
18 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
19 | // Verify that runtime/protoimpl is sufficiently up-to-date.
20 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
21 | )
22 |
23 | type GetPostsRequest struct {
24 | state protoimpl.MessageState
25 | sizeCache protoimpl.SizeCache
26 | unknownFields protoimpl.UnknownFields
27 |
28 | Page *int64 `protobuf:"varint,1,opt,name=page,proto3,oneof" json:"page,omitempty"`
29 | Limit *int64 `protobuf:"varint,2,opt,name=limit,proto3,oneof" json:"limit,omitempty"`
30 | }
31 |
32 | func (x *GetPostsRequest) Reset() {
33 | *x = GetPostsRequest{}
34 | if protoimpl.UnsafeEnabled {
35 | mi := &file_post_service_proto_msgTypes[0]
36 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
37 | ms.StoreMessageInfo(mi)
38 | }
39 | }
40 |
41 | func (x *GetPostsRequest) String() string {
42 | return protoimpl.X.MessageStringOf(x)
43 | }
44 |
45 | func (*GetPostsRequest) ProtoMessage() {}
46 |
47 | func (x *GetPostsRequest) ProtoReflect() protoreflect.Message {
48 | mi := &file_post_service_proto_msgTypes[0]
49 | if protoimpl.UnsafeEnabled && x != nil {
50 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
51 | if ms.LoadMessageInfo() == nil {
52 | ms.StoreMessageInfo(mi)
53 | }
54 | return ms
55 | }
56 | return mi.MessageOf(x)
57 | }
58 |
59 | // Deprecated: Use GetPostsRequest.ProtoReflect.Descriptor instead.
60 | func (*GetPostsRequest) Descriptor() ([]byte, []int) {
61 | return file_post_service_proto_rawDescGZIP(), []int{0}
62 | }
63 |
64 | func (x *GetPostsRequest) GetPage() int64 {
65 | if x != nil && x.Page != nil {
66 | return *x.Page
67 | }
68 | return 0
69 | }
70 |
71 | func (x *GetPostsRequest) GetLimit() int64 {
72 | if x != nil && x.Limit != nil {
73 | return *x.Limit
74 | }
75 | return 0
76 | }
77 |
78 | type PostRequest struct {
79 | state protoimpl.MessageState
80 | sizeCache protoimpl.SizeCache
81 | unknownFields protoimpl.UnknownFields
82 |
83 | Id string `protobuf:"bytes,1,opt,name=Id,proto3" json:"Id,omitempty"`
84 | }
85 |
86 | func (x *PostRequest) Reset() {
87 | *x = PostRequest{}
88 | if protoimpl.UnsafeEnabled {
89 | mi := &file_post_service_proto_msgTypes[1]
90 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
91 | ms.StoreMessageInfo(mi)
92 | }
93 | }
94 |
95 | func (x *PostRequest) String() string {
96 | return protoimpl.X.MessageStringOf(x)
97 | }
98 |
99 | func (*PostRequest) ProtoMessage() {}
100 |
101 | func (x *PostRequest) ProtoReflect() protoreflect.Message {
102 | mi := &file_post_service_proto_msgTypes[1]
103 | if protoimpl.UnsafeEnabled && x != nil {
104 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
105 | if ms.LoadMessageInfo() == nil {
106 | ms.StoreMessageInfo(mi)
107 | }
108 | return ms
109 | }
110 | return mi.MessageOf(x)
111 | }
112 |
113 | // Deprecated: Use PostRequest.ProtoReflect.Descriptor instead.
114 | func (*PostRequest) Descriptor() ([]byte, []int) {
115 | return file_post_service_proto_rawDescGZIP(), []int{1}
116 | }
117 |
118 | func (x *PostRequest) GetId() string {
119 | if x != nil {
120 | return x.Id
121 | }
122 | return ""
123 | }
124 |
125 | type DeletePostResponse struct {
126 | state protoimpl.MessageState
127 | sizeCache protoimpl.SizeCache
128 | unknownFields protoimpl.UnknownFields
129 |
130 | Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"`
131 | }
132 |
133 | func (x *DeletePostResponse) Reset() {
134 | *x = DeletePostResponse{}
135 | if protoimpl.UnsafeEnabled {
136 | mi := &file_post_service_proto_msgTypes[2]
137 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
138 | ms.StoreMessageInfo(mi)
139 | }
140 | }
141 |
142 | func (x *DeletePostResponse) String() string {
143 | return protoimpl.X.MessageStringOf(x)
144 | }
145 |
146 | func (*DeletePostResponse) ProtoMessage() {}
147 |
148 | func (x *DeletePostResponse) ProtoReflect() protoreflect.Message {
149 | mi := &file_post_service_proto_msgTypes[2]
150 | if protoimpl.UnsafeEnabled && x != nil {
151 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
152 | if ms.LoadMessageInfo() == nil {
153 | ms.StoreMessageInfo(mi)
154 | }
155 | return ms
156 | }
157 | return mi.MessageOf(x)
158 | }
159 |
160 | // Deprecated: Use DeletePostResponse.ProtoReflect.Descriptor instead.
161 | func (*DeletePostResponse) Descriptor() ([]byte, []int) {
162 | return file_post_service_proto_rawDescGZIP(), []int{2}
163 | }
164 |
165 | func (x *DeletePostResponse) GetSuccess() bool {
166 | if x != nil {
167 | return x.Success
168 | }
169 | return false
170 | }
171 |
172 | var File_post_service_proto protoreflect.FileDescriptor
173 |
174 | var file_post_service_proto_rawDesc = []byte{
175 | 0x0a, 0x12, 0x70, 0x6f, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70,
176 | 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x70, 0x62, 0x1a, 0x0a, 0x70, 0x6f, 0x73, 0x74, 0x2e, 0x70,
177 | 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x15, 0x72, 0x70, 0x63, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65,
178 | 0x5f, 0x70, 0x6f, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x15, 0x72, 0x70, 0x63,
179 | 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x6f, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f,
180 | 0x74, 0x6f, 0x22, 0x58, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x73, 0x74, 0x73, 0x52, 0x65,
181 | 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20,
182 | 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x88, 0x01, 0x01, 0x12, 0x19,
183 | 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x48, 0x01, 0x52,
184 | 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x88, 0x01, 0x01, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x70, 0x61,
185 | 0x67, 0x65, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x22, 0x1d, 0x0a, 0x0b,
186 | 0x50, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x49,
187 | 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x64, 0x22, 0x2e, 0x0a, 0x12, 0x44,
188 | 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
189 | 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01,
190 | 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x32, 0x97, 0x02, 0x0a, 0x0b,
191 | 0x50, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x37, 0x0a, 0x0a, 0x43,
192 | 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x6f, 0x73, 0x74, 0x12, 0x15, 0x2e, 0x70, 0x62, 0x2e, 0x43,
193 | 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
194 | 0x1a, 0x10, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
195 | 0x73, 0x65, 0x22, 0x00, 0x12, 0x2e, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x73, 0x74, 0x12,
196 | 0x0f, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
197 | 0x1a, 0x10, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
198 | 0x73, 0x65, 0x22, 0x00, 0x12, 0x2d, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x73, 0x74, 0x73,
199 | 0x12, 0x13, 0x2e, 0x70, 0x62, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x73, 0x74, 0x73, 0x52, 0x65,
200 | 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x08, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x22,
201 | 0x00, 0x30, 0x01, 0x12, 0x37, 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x6f, 0x73,
202 | 0x74, 0x12, 0x15, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x6f, 0x73,
203 | 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x70, 0x62, 0x2e, 0x50, 0x6f,
204 | 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x37, 0x0a, 0x0a,
205 | 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x6f, 0x73, 0x74, 0x12, 0x0f, 0x2e, 0x70, 0x62, 0x2e,
206 | 0x50, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x70, 0x62,
207 | 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f,
208 | 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
209 | 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x70, 0x63, 0x6f, 0x64, 0x65, 0x76, 0x6f, 0x2f, 0x67, 0x6f, 0x6c,
210 | 0x61, 0x6e, 0x67, 0x2d, 0x6d, 0x6f, 0x6e, 0x67, 0x6f, 0x64, 0x62, 0x2f, 0x70, 0x62, 0x62, 0x06,
211 | 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
212 | }
213 |
214 | var (
215 | file_post_service_proto_rawDescOnce sync.Once
216 | file_post_service_proto_rawDescData = file_post_service_proto_rawDesc
217 | )
218 |
219 | func file_post_service_proto_rawDescGZIP() []byte {
220 | file_post_service_proto_rawDescOnce.Do(func() {
221 | file_post_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_post_service_proto_rawDescData)
222 | })
223 | return file_post_service_proto_rawDescData
224 | }
225 |
226 | var file_post_service_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
227 | var file_post_service_proto_goTypes = []interface{}{
228 | (*GetPostsRequest)(nil), // 0: pb.GetPostsRequest
229 | (*PostRequest)(nil), // 1: pb.PostRequest
230 | (*DeletePostResponse)(nil), // 2: pb.DeletePostResponse
231 | (*CreatePostRequest)(nil), // 3: pb.CreatePostRequest
232 | (*UpdatePostRequest)(nil), // 4: pb.UpdatePostRequest
233 | (*PostResponse)(nil), // 5: pb.PostResponse
234 | (*Post)(nil), // 6: pb.Post
235 | }
236 | var file_post_service_proto_depIdxs = []int32{
237 | 3, // 0: pb.PostService.CreatePost:input_type -> pb.CreatePostRequest
238 | 1, // 1: pb.PostService.GetPost:input_type -> pb.PostRequest
239 | 0, // 2: pb.PostService.GetPosts:input_type -> pb.GetPostsRequest
240 | 4, // 3: pb.PostService.UpdatePost:input_type -> pb.UpdatePostRequest
241 | 1, // 4: pb.PostService.DeletePost:input_type -> pb.PostRequest
242 | 5, // 5: pb.PostService.CreatePost:output_type -> pb.PostResponse
243 | 5, // 6: pb.PostService.GetPost:output_type -> pb.PostResponse
244 | 6, // 7: pb.PostService.GetPosts:output_type -> pb.Post
245 | 5, // 8: pb.PostService.UpdatePost:output_type -> pb.PostResponse
246 | 2, // 9: pb.PostService.DeletePost:output_type -> pb.DeletePostResponse
247 | 5, // [5:10] is the sub-list for method output_type
248 | 0, // [0:5] is the sub-list for method input_type
249 | 0, // [0:0] is the sub-list for extension type_name
250 | 0, // [0:0] is the sub-list for extension extendee
251 | 0, // [0:0] is the sub-list for field type_name
252 | }
253 |
254 | func init() { file_post_service_proto_init() }
255 | func file_post_service_proto_init() {
256 | if File_post_service_proto != nil {
257 | return
258 | }
259 | file_post_proto_init()
260 | file_rpc_create_post_proto_init()
261 | file_rpc_update_post_proto_init()
262 | if !protoimpl.UnsafeEnabled {
263 | file_post_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
264 | switch v := v.(*GetPostsRequest); i {
265 | case 0:
266 | return &v.state
267 | case 1:
268 | return &v.sizeCache
269 | case 2:
270 | return &v.unknownFields
271 | default:
272 | return nil
273 | }
274 | }
275 | file_post_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
276 | switch v := v.(*PostRequest); i {
277 | case 0:
278 | return &v.state
279 | case 1:
280 | return &v.sizeCache
281 | case 2:
282 | return &v.unknownFields
283 | default:
284 | return nil
285 | }
286 | }
287 | file_post_service_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
288 | switch v := v.(*DeletePostResponse); i {
289 | case 0:
290 | return &v.state
291 | case 1:
292 | return &v.sizeCache
293 | case 2:
294 | return &v.unknownFields
295 | default:
296 | return nil
297 | }
298 | }
299 | }
300 | file_post_service_proto_msgTypes[0].OneofWrappers = []interface{}{}
301 | type x struct{}
302 | out := protoimpl.TypeBuilder{
303 | File: protoimpl.DescBuilder{
304 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
305 | RawDescriptor: file_post_service_proto_rawDesc,
306 | NumEnums: 0,
307 | NumMessages: 3,
308 | NumExtensions: 0,
309 | NumServices: 1,
310 | },
311 | GoTypes: file_post_service_proto_goTypes,
312 | DependencyIndexes: file_post_service_proto_depIdxs,
313 | MessageInfos: file_post_service_proto_msgTypes,
314 | }.Build()
315 | File_post_service_proto = out.File
316 | file_post_service_proto_rawDesc = nil
317 | file_post_service_proto_goTypes = nil
318 | file_post_service_proto_depIdxs = nil
319 | }
320 |
--------------------------------------------------------------------------------