Skip to content

Commit

Permalink
implement create&login user rpcs
Browse files Browse the repository at this point in the history
  • Loading branch information
aradwann committed Jan 2, 2024
1 parent 280a440 commit ff8861a
Show file tree
Hide file tree
Showing 7 changed files with 197 additions and 10 deletions.
1 change: 0 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ testci:
server:
go run main.go


protoc:
rm -f pb/*.go
protoc --proto_path=proto --go_out=pb --go_opt=paths=source_relative \
Expand Down
17 changes: 17 additions & 0 deletions gapi/converter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package gapi

import (
db "github.com/aradwann/eenergy/db/store"
"github.com/aradwann/eenergy/pb"
"google.golang.org/protobuf/types/known/timestamppb"
)

func convertUser(user db.User) *pb.User {
return &pb.User{
Username: user.Username,
FullName: user.FullName,
Email: user.Email,
PasswordChangedAt: timestamppb.New(user.PasswordChangedAt),
CreatedAt: timestamppb.New(user.CreatedAt),
}
}
38 changes: 38 additions & 0 deletions gapi/rpc_create_user.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package gapi

import (
"context"

db "github.com/aradwann/eenergy/db/store"
"github.com/aradwann/eenergy/pb"
"github.com/aradwann/eenergy/util"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)

func (server *Server) CreateUser(ctx context.Context, req *pb.CreateUserRequest) (*pb.CreateUserResponse, error) {
hashedPassword, err := util.HashPassword(req.GetPassword())
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to hash password: %s", err)
}

arg := db.CreateUserParams{
Username: req.GetUsername(),
HashedPassword: hashedPassword,
FullName: req.GetFullName(),
Email: req.GetEmail(),
}

user, err := server.store.CreateUser(ctx, arg)
if err != nil {
if db.ErrorCode(err) == db.UniqueViolation {
return nil, status.Errorf(codes.AlreadyExists, "username already exsits")
}
return nil, status.Errorf(codes.Internal, "failed to create user: %s", err)
}

rsp := &pb.CreateUserResponse{
User: convertUser(user),
}
return rsp, nil
}
70 changes: 70 additions & 0 deletions gapi/rpc_login_user.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package gapi

import (
"context"
"errors"

db "github.com/aradwann/eenergy/db/store"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/timestamppb"

"github.com/aradwann/eenergy/pb"
"github.com/aradwann/eenergy/util"
)

func (server *Server) LoginUser(ctx context.Context, req *pb.LoginUserRequest) (*pb.LoginUserResponse, error) {
user, err := server.store.GetUser(ctx, req.GetUsername())
if err != nil {
if errors.Is(err, db.ErrRecordNotFound) {
return nil, status.Errorf(codes.NotFound, "user not found")

}
return nil, status.Errorf(codes.Internal, "failed to find user")
}

err = util.CheckPassword(req.GetPassword(), user.HashedPassword)
if err != nil {
return nil, status.Errorf(codes.NotFound, "incorrect password")

}

accessToken, accessPayload, err := server.tokenMaker.CreateToken(
user.Username,
server.config.AccessTokenDuration,
)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to create access token")
}

refreshToken, refreshPayload, err := server.tokenMaker.CreateToken(
user.Username,
server.config.RefreshTokenDuration,
)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to create refresh token")
}

session, err := server.store.CreateSession(ctx, db.CreateSessionParams{
ID: refreshPayload.ID,
Username: user.Username,
RefreshToken: refreshToken,
UserAgent: "ctx.Request.UserAgent()",
ClientIp: "ctx.ClientIP()",
IsBlocked: false,
ExpiresAt: refreshPayload.ExpiredAt,
})
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to create session")
}

rsp := &pb.LoginUserResponse{
User: convertUser(user),
SessionId: session.ID.String(),
AccessToken: accessToken,
AccessTokenExpiresAt: timestamppb.New(accessPayload.ExpiredAt),
RefreshToken: refreshToken,
RefreshTokenExpiresAt: timestamppb.New(refreshPayload.ExpiredAt),
}
return rsp, nil
}
34 changes: 34 additions & 0 deletions gapi/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package gapi

import (
"fmt"

db "github.com/aradwann/eenergy/db/store"
"github.com/aradwann/eenergy/pb"
"github.com/aradwann/eenergy/token"
"github.com/aradwann/eenergy/util"
)

// Server serves gRPC requests for our banking service.
type Server struct {
pb.UnimplementedEenergyServiceServer
config util.Config
store db.Store
tokenMaker token.Maker
}

// NewServer creates a new gRPC server.
func NewServer(config util.Config, store db.Store) (*Server, error) {
tokenMaker, err := token.NewPASETOMaker(config.TokenSymmetricKey)
if err != nil {
return nil, fmt.Errorf("cannot create token maker: %w", err)
}

server := &Server{
config: config,
store: store,
tokenMaker: tokenMaker,
}

return server, nil
}
46 changes: 37 additions & 9 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,18 @@ package main
import (
"database/sql"
"fmt"
"log"
"net"
"os"

"github.com/aradwann/eenergy/api"
db "github.com/aradwann/eenergy/db/store"
"github.com/aradwann/eenergy/gapi"
"github.com/aradwann/eenergy/pb"
"github.com/aradwann/eenergy/util"
_ "github.com/golang-migrate/migrate/v4/source/file"
_ "github.com/jackc/pgx/v5/stdlib"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
)

func main() {
Expand All @@ -34,19 +39,42 @@ func main() {

store := db.NewStore(dbConn)

runGinServer(config, store)
runGrpcServer(config, store)
}

func runGinServer(config util.Config, store db.Store) {
server, err := api.NewServer(config, store)
// func runGinServer(config util.Config, store db.Store) {
// server, err := api.NewServer(config, store)
// if err != nil {
// // log.Fatal().Err(err).Msg("cannot create server")
// fmt.Fprintf(os.Stderr, "cannot create server: %v\n", err)
// }

// err = server.Start(config.HTTPServerAddress)
// if err != nil {
// // log.Fatal().Err(err).Msg("cannot start server")
// fmt.Fprintf(os.Stderr, "cannot start server: %v\n", err)
// }
// }

func runGrpcServer(config util.Config, store db.Store) {
server, err := gapi.NewServer(config, store)
if err != nil {
log.Fatal("cannot create server")
}

// gprcLogger := grpc.UnaryInterceptor(gapi.GrpcLogger)
grpcServer := grpc.NewServer()
pb.RegisterEenergyServiceServer(grpcServer, server)
reflection.Register(grpcServer)

listener, err := net.Listen("tcp", config.GRPCServerAddress)
if err != nil {
// log.Fatal().Err(err).Msg("cannot create server")
fmt.Fprintf(os.Stderr, "cannot create server: %v\n", err)
log.Fatal("cannot create listener")
}

err = server.Start(config.HTTPServerAddress)
log.Printf("start gRPC server at %s", listener.Addr().String())
err = grpcServer.Serve(listener)
if err != nil {
// log.Fatal().Err(err).Msg("cannot start server")
fmt.Fprintf(os.Stderr, "cannot start server: %v\n", err)
log.Fatal("cannot start gRPC server")
}
}
1 change: 1 addition & 0 deletions util/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type Config struct {
DBSource string `mapstructure:"DB_SOURCE"`
MigrationsURL string `mapstructure:"MIGRATIONS_URL"`
HTTPServerAddress string `mapstructure:"HTTP_SERVER_ADDRESS"`
GRPCServerAddress string `mapstructure:"GRPC_SERVER_ADDRESS"`
RedisAddress string `mapstructure:"REDIS_ADDRESS"`
TokenSymmetricKey string `mapstructure:"TOKEN_SYMMETRIC_KEY"`
AccessTokenDuration time.Duration `mapstructure:"ACCESS_TOKEN_DURATION"`
Expand Down

0 comments on commit ff8861a

Please sign in to comment.