2021-12-05 13:55:18 +00:00
|
|
|
package server
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
|
2021-12-06 05:08:17 +00:00
|
|
|
"gitea.benny.dog/torjus/ezshare/certs"
|
2021-12-05 13:55:18 +00:00
|
|
|
"gitea.benny.dog/torjus/ezshare/pb"
|
|
|
|
"gitea.benny.dog/torjus/ezshare/store"
|
|
|
|
"github.com/google/uuid"
|
|
|
|
"golang.org/x/crypto/bcrypt"
|
|
|
|
"google.golang.org/grpc/codes"
|
|
|
|
"google.golang.org/grpc/status"
|
|
|
|
)
|
|
|
|
|
|
|
|
type GRPCUserServiceServer struct {
|
2021-12-06 05:08:17 +00:00
|
|
|
store store.UserStore
|
|
|
|
certService *certs.CertService
|
2021-12-05 13:55:18 +00:00
|
|
|
pb.UnimplementedUserServiceServer
|
|
|
|
}
|
|
|
|
|
2021-12-06 05:08:17 +00:00
|
|
|
func NewGRPCUserServiceServer(store store.UserStore, certSvc *certs.CertService) *GRPCUserServiceServer {
|
|
|
|
return &GRPCUserServiceServer{store: store, certService: certSvc}
|
2021-12-05 13:55:18 +00:00
|
|
|
}
|
|
|
|
func (s *GRPCUserServiceServer) Register(ctx context.Context, req *pb.RegisterUserRequest) (*pb.RegisterUserResponse, error) {
|
|
|
|
// Check if user already exists
|
|
|
|
if _, err := s.store.GetUserByUsername(req.Username); err != store.ErrNoSuchItem {
|
2021-12-06 05:08:17 +00:00
|
|
|
return nil, status.Error(codes.AlreadyExists, "user already exists")
|
2021-12-05 13:55:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pw, err := hashPassword(req.Password)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("unable to hash password: %w", err)
|
|
|
|
}
|
|
|
|
user := &pb.User{
|
|
|
|
Id: uuid.Must(uuid.NewRandom()).String(),
|
|
|
|
Username: req.Username,
|
|
|
|
HashedPassword: pw,
|
|
|
|
UserRole: pb.User_USER,
|
|
|
|
Active: true,
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := s.store.StoreUser(user); err != nil {
|
|
|
|
return nil, status.Error(codes.Internal, fmt.Sprintf("unable to store user: %s", err))
|
|
|
|
}
|
|
|
|
|
|
|
|
return &pb.RegisterUserResponse{Id: user.Id, Token: ""}, nil
|
|
|
|
}
|
|
|
|
|
2021-12-06 05:08:17 +00:00
|
|
|
func (s *GRPCUserServiceServer) Login(_ context.Context, req *pb.LoginUserRequest) (*pb.LoginUserResponse, error) {
|
|
|
|
user, err := s.store.GetUserByUsername(req.Username)
|
|
|
|
if err != nil {
|
|
|
|
if err == store.ErrNoSuchItem {
|
|
|
|
return nil, status.Error(codes.NotFound, "no such user")
|
|
|
|
}
|
|
|
|
return nil, status.Error(codes.Internal, "error getting user from store")
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := bcrypt.CompareHashAndPassword(user.HashedPassword, []byte(req.Password)); err != nil {
|
|
|
|
return nil, status.Error(codes.Unauthenticated, "wrong username and or password")
|
|
|
|
}
|
|
|
|
|
|
|
|
cert, key, err := s.certService.NewClient(user.Id)
|
|
|
|
if err != nil {
|
|
|
|
return nil, status.Error(codes.Internal, "unable to generate client certificate")
|
|
|
|
}
|
|
|
|
|
|
|
|
resp := &pb.LoginUserResponse{
|
|
|
|
ClientCert: cert,
|
|
|
|
ClientKey: key,
|
|
|
|
}
|
|
|
|
|
|
|
|
return resp, nil
|
2021-12-05 13:55:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *GRPCUserServiceServer) List(_ context.Context, _ *pb.ListUsersRequest) (*pb.ListUsersResponse, error) {
|
|
|
|
return nil, status.Error(codes.Unimplemented, "not yet implemented")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *GRPCUserServiceServer) Approve(_ context.Context, _ *pb.ApproveUserRequest) (*pb.Empty, error) {
|
|
|
|
return nil, status.Error(codes.Unimplemented, "not yet implemented")
|
|
|
|
}
|
|
|
|
|
|
|
|
func hashPassword(password string) ([]byte, error) {
|
|
|
|
return bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
|
|
|
}
|