Go micro project practice one create user service

Keywords: github Database MySQL Mobile

User service

User service, providing login, registration, password modification and other functions.

New service

micro new shopping/user

Finishing structure

Add the model directory and repository directory, delete the default example folder in proto, and create the user folder.
Development steps: 1. Define interface - > 2. Generate interface code - > 3. Write model layer code - > 4. Write repository data operation code - > 5. Implement interface - > 6. Modify main.go
Because this is the first microservice, the process of creating a microservice will be described in as much detail as possible

Define user service interface

syntax = "proto3";

package go.micro.srv.user;

service UserService {
	rpc Register (RegisterRequest) returns (Response){}
	rpc Login (LoginRequest) returns (Response){}
	rpc UpdatePassword (UpdatePasswordRequest) returns (Response){}
}

message User {
	uint32 id = 1;
	string name = 2;
	string phone = 3;
	string password = 4;
}

message RegisterRequest{
	User user = 1;
}

message LoginRequest{
	string phone = 1;
	string password = 2;
}

message UpdatePasswordRequest{
	uint32 uid = 1;
	string oldPassword = 2;
	string newPassword = 3;
	string confirmPassword = 4;
}

message Response {
	string code = 1;
	string msg = 2;
}


Generate interface code

Execute the command protoc -- proto_path =. - micro_out =. - go_out =. Proto / user / user.proto

Write model.user

package model

import "github.com/jinzhu/gorm"

type User struct {
	gorm.Model
	Name string
	Phone string `gorm:"type:char(11);`
	Password string
}

Write repository.user

package repository

import (
	"github.com/jinzhu/gorm"
	"shopping/user/model"
)

type Repository interface {
	Find(id int32) (*model.User, error)
	Create(*model.User) error
	Update(*model.User, int64) (*model.User, error)
	FindByField(string, string, string) (*model.User, error)
}

type User struct {
	Db *gorm.DB
}

func (repo *User) Find(id uint32) (*model.User, error) {
	user :=  &model.User{}
	user.ID = uint(id)
	if err := repo.Db.First(user).Error; err != nil {
		return nil, err
	}
	return user, nil
}

func (repo *User) Create(user *model.User) error {
	if err := repo.Db.Create(user).Error; err != nil {
		return err
	}
	return nil
}

func (repo *User) Update(user *model.User) (*model.User, error) {
	if err := repo.Db.Model(user).Updates(&user).Error; err != nil {
		return nil, err
	}
	return user, nil
}

func (repo *User) FindByField(key string, value string, fields string) (*model.User, error) {
	if len(fields) == 0 {
		fields = "*"
	}
	user :=  &model.User{}
	if err := repo.Db.Select(fields).Where(key+" = ?", value).First(user).Error; err != nil {
		return nil, err
	}
	return user, nil
}

Implement interface handler.user

package handler

import (
	"context"
	"github.com/micro/go-log"
	"github.com/micro/go-micro/errors"
	"golang.org/x/crypto/bcrypt"
	"shopping/user/model"
	"shopping/user/repository"

	user "shopping/user/proto/user"
)

type User struct{
	Repo *repository.User
}

// Call is a single request handler called via client.Call or the generated client code
func (e *User) Register(ctx context.Context, req *user.RegisterRequest, rsp *user.Response) error {
	hashedPwd, err := bcrypt.GenerateFromPassword([]byte(req.User.Password), bcrypt.DefaultCost)
	if err != nil {
		return err
	}

	user := &model.User{
		Name:req.User.Name,
		Phone:req.User.Phone,
		Password:string(hashedPwd),
	}

	if err := e.Repo.Create(user);err != nil{
		log.Log("create error")
		return err
	}

	rsp.Code = "200"
	rsp.Msg = "login was successful"

	return nil
}

func (e *User)Login(ctx context.Context, req *user.LoginRequest, rsp *user.Response) error {
	user , err := e.Repo.FindByField("phone" , req.Phone , "id , password")
	if err != err{
		return err
	}

	if user == nil{
		return errors.Unauthorized("go.micro.srv.user.login", "The mobile number does not exist")
	}

	if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(req.Password)); err != nil {
		return errors.Unauthorized("go.micro.srv.user.login", "Password error")
	}

	rsp.Code = "200"
	rsp.Msg = "Login successfully"

	return nil
}

func (e *User)UpdatePassword(ctx context.Context, req *user.UpdatePasswordRequest, rsp *user.Response) error {
	user,err := e.Repo.Find(req.Uid)

	if user == nil{
		return errors.Unauthorized("go.micro.srv.user.login", "The user does not exist")
	}

	if err != nil {
		return err
	}
	//Verify whether the old password is normal
	if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(req.OldPassword)); err != nil {
		return errors.Unauthorized("go.micro.srv.user.login", "Old password authentication failed")
	}

	//After verification, save the new password hash
	hashedPwd, err := bcrypt.GenerateFromPassword([]byte(req.NewPassword), bcrypt.DefaultCost)
	if err != nil {
		return err
	}
	user.Password = string(hashedPwd)
	e.Repo.Update(user)

	rsp.Code = "200"
	rsp.Msg =user.Name+",Your password has been updated successfully"

	return nil
}

Modify main.go

Because you need to establish a database connection in main.go, create database.go in the root directory

package main

import (
	"fmt"
	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mysql"
)

func CreateConnection() (*gorm.DB, error) {
	host := "192.168.0.111"
	user := "mytestroot"
	dbName := "shopping"
	password := "mytestroot"
	return gorm.Open("mysql", fmt.Sprintf(
		"%s:%s@tcp(%s:3306)/%s?charset=utf8&parseTime=True&loc=Local",
		user, password, host, dbName,
	),
	)
}

Then modify main.go

package main

import (
	"github.com/micro/go-log"
	"github.com/micro/go-micro"
	"github.com/micro/go-grpc"
	"shopping/user/handler"
	"shopping/user/model"
	"shopping/user/repository"

	user "shopping/user/proto/user"
)

func main() {

	db,err := CreateConnection()
	defer db.Close()

	db.AutoMigrate(&model.User{})

	if err != nil {
		log.Fatalf("connection error : %v \n" , err)
	}

	repo := &repository.User{db}

	// New Service
	service := grpc.NewService(
		micro.Name("go.micro.srv.user"),
		micro.Version("latest"),
	)

	// Initialise service
	service.Init()

	// Register Handler
	user.RegisterUserServiceHandler(service.Server(), &handler.User{repo})

	// Register Struct as Subscriber
	//micro.RegisterSubscriber("go.micro.srv.user", service.Server(), new(subscriber.Example))

	// Register Function as Subscriber
	//micro.RegisterSubscriber("go.micro.srv.user", service.Server(), subscriber.Handler)

	// Run service
	if err := service.Run(); err != nil {
		log.Fatal(err)
	}
}

Start service, verify interface

go run main.go database.go and micro api --namespace=go.micro.srv
Registration interface

Logon interface

Modify password interface

Posted by proiek on Sat, 23 Nov 2019 09:31:55 -0800