Skip to content

Commit

Permalink
Merge pull request #4 from satanaroom/task6
Browse files Browse the repository at this point in the history
Task6
  • Loading branch information
satanaroom committed Jun 19, 2023
2 parents e6549ec + d8943c1 commit 3e8d3fe
Show file tree
Hide file tree
Showing 32 changed files with 1,912 additions and 80 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,9 @@ go.work
/.idea
/vendor.protogen
.env
ca.key
ca.cert
certificate.conf
service.csr
service.key
service.pem
10 changes: 9 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,12 @@ cover:
.PHONY: gen
gen:
mockgen -source=internal/repository/chat_server/repository.go \
-destination=internal/repository/mocks/mock_repository.go
-destination=internal/repository/mocks/mock_repository.go

cert:
openssl genrsa -out ca.key 4096
openssl req -new -x509 -key ca.key -sha256 -subj "/C=US/ST=NJ/O=Test, Inc." -days 365 -out ca.cert
openssl genrsa -out service.key 4096
openssl req -new -key service.key -out service.csr -config certificate.conf
openssl x509 -req -in service.csr -CA ca.cert -CAkey ca.key -CAcreateserial \
-out service.pem -days 365 -sha256 -extfile certificate.conf -extensions req_ext
38 changes: 37 additions & 1 deletion api/chat_v1/chat.proto
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ syntax = "proto3";
package chat_v1;

import "validate/validate.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/empty.proto";
import "google/api/annotations.proto";
import "protoc-gen-openapiv2/options/annotations.proto";

Expand Down Expand Up @@ -31,6 +33,20 @@ service ChatV1 {
body: "*"
};
};

rpc ConnectChat(ConnectChatRequest) returns (stream ConnectChatResponse) {
option (google.api.http) = {
post: "/chat/v1/connect"
body: "*"
};
};

rpc SendMessage(SendMessageRequest) returns (google.protobuf.Empty) {
option (google.api.http) = {
post: "/chat/v1/send"
body: "*"
};
}
}

message CreateChatRequest {
Expand All @@ -39,6 +55,26 @@ message CreateChatRequest {
}

message CreateChatResponse {
int64 chat_id = 1;
string chat_id = 1 [(validate.rules).string.uuid = true];
}

message ConnectChatRequest {
string chat_id = 1 [(validate.rules).string.uuid = true];
string username = 2 [(validate.rules).string = {min_len: 5, max_len: 50}];
}

message Message {
string text = 1 [(validate.rules).string = {min_len: 1, max_len: 500}];
string from = 2 [(validate.rules).string = {min_len: 5, max_len: 50}];
string to = 3 [(validate.rules).string = {min_len: 5, max_len: 50}];
google.protobuf.Timestamp sent_at = 4 [(validate.rules).timestamp.required = true];
}

message ConnectChatResponse {
Message message = 1;
}

message SendMessageRequest {
string chat_id = 1 [(validate.rules).string.uuid = true];
Message message = 2;
}
9 changes: 7 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@ go 1.20

require (
github.com/envoyproxy/protoc-gen-validate v0.10.0
github.com/fatih/color v1.15.0
github.com/golang/protobuf v1.5.3
github.com/google/uuid v1.3.0
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0
github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.2
github.com/joho/godotenv v1.5.1
github.com/pkg/errors v0.9.1
github.com/rakyll/statik v0.1.7
github.com/rs/cors v1.9.0
github.com/satanaroom/auth v0.0.0-20230526072419-e465008b530c
Expand All @@ -16,11 +20,12 @@ require (
)

require (
github.com/golang/protobuf v1.5.3 // indirect
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/sirupsen/logrus v1.4.2 // indirect
github.com/stretchr/testify v1.8.1 // indirect
golang.org/x/net v0.10.0 // indirect
golang.org/x/sys v0.8.0 // indirect
golang.org/x/sys v0.9.0 // indirect
golang.org/x/text v0.9.0 // indirect
)
17 changes: 15 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/envoyproxy/protoc-gen-validate v0.10.0 h1:oIfnZFdC0YhpNNEX+SuIqko4cqqVZeN9IGTrhZje83Y=
github.com/envoyproxy/protoc-gen-validate v0.10.0/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss=
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
Expand All @@ -29,6 +31,8 @@ github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI=
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.2 h1:gDLXvp5S9izjldquuoAhDzccbskOL6tDC5jMSyx3zxE=
Expand All @@ -43,8 +47,15 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxv
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
Expand Down Expand Up @@ -106,8 +117,10 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
Expand Down
51 changes: 51 additions & 0 deletions internal/api/chat_v1/connect_chat.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package chat_v1

import (
"github.com/satanaroom/chat_server/internal/sys"
"github.com/satanaroom/chat_server/internal/sys/codes"
desc "github.com/satanaroom/chat_server/pkg/chat_v1"
)

func (i *Implementation) ConnectChat(req *desc.ConnectChatRequest, stream desc.ChatV1_ConnectChatServer) error {
chatId := req.GetChatId()
username := req.GetUsername()

chatChannel, err := i.chatService.GetChatChannel(chatId)
if err != nil {
return err
}

i.chats.mu.Lock()
if _, ok := i.chats.m[chatId]; !ok {
i.chats.m[chatId] = &Chat{
streams: make(map[string]desc.ChatV1_ConnectChatServer),
}
}
i.chats.mu.Unlock()

i.chats.m[chatId].mu.Lock()
i.chats.m[chatId].streams[username] = stream
i.chats.m[chatId].mu.Unlock()

for {
select {
case msg, ok := <-chatChannel:
if !ok {
return nil
}

for _, str := range i.chats.m[chatId].streams {
if err = str.Send(&desc.ConnectChatResponse{
Message: msg,
}); err != nil {
return sys.NewCommonError("failed to send message", codes.Internal)
}
}
case <-stream.Context().Done():
i.chats.m[chatId].mu.Lock()
delete(i.chats.m[chatId].streams, username)
i.chats.m[chatId].mu.Unlock()
return nil
}
}
}
2 changes: 1 addition & 1 deletion internal/api/chat_v1/create_chat.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package chat_v1
import (
"context"

converter "github.com/satanaroom/chat_server/internal/converter/client/access"
converter "github.com/satanaroom/chat_server/internal/converter/client"
desc "github.com/satanaroom/chat_server/pkg/chat_v1"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
Expand Down
19 changes: 19 additions & 0 deletions internal/api/chat_v1/send_message.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package chat_v1

import (
"context"

"github.com/golang/protobuf/ptypes/empty"
desc "github.com/satanaroom/chat_server/pkg/chat_v1"
)

func (i *Implementation) SendMessage(_ context.Context, req *desc.SendMessageRequest) (*empty.Empty, error) {
chatChannel, err := i.chatService.GetChatChannel(req.GetChatId())
if err != nil {
return nil, err
}

chatChannel <- req.GetMessage()

return &empty.Empty{}, nil
}
14 changes: 14 additions & 0 deletions internal/api/chat_v1/service.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package chat_v1

import (
"sync"

"github.com/satanaroom/chat_server/internal/service/chat"
desc "github.com/satanaroom/chat_server/pkg/chat_v1"
)
Expand All @@ -9,10 +11,22 @@ type Implementation struct {
desc.UnimplementedChatV1Server

chatService chat.Service
chats Chats
}

type Chat struct {
streams map[string]desc.ChatV1_ConnectChatServer
mu sync.RWMutex
}

type Chats struct {
m map[string]*Chat
mu sync.RWMutex
}

func NewImplementation(chatService chat.Service) *Implementation {
return &Implementation{
chatService: chatService,
chats: Chats{m: make(map[string]*Chat)},
}
}
2 changes: 2 additions & 0 deletions internal/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,11 @@ func (a *App) initServiceProvider(_ context.Context) error {

func (a *App) initGRPCServer(ctx context.Context) error {
a.grpcServer = grpc.NewServer(
grpc.Creds(a.serviceProvider.TLSServerCredentials(ctx)),
grpc.UnaryInterceptor(
grpcMiddleware.ChainUnaryServer(
interceptor.ValidateInterceptor,
interceptor.ErrorCodesInterceptor,
interceptor.NewAuthInterceptor(a.serviceProvider.AuthClient(ctx)).Unary(),
),
),
Expand Down
47 changes: 38 additions & 9 deletions internal/app/service_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
accessV1 "github.com/satanaroom/auth/pkg/access_v1"
"github.com/satanaroom/auth/pkg/logger"
chatV1 "github.com/satanaroom/chat_server/internal/api/chat_v1"
"github.com/satanaroom/chat_server/internal/channels"
authClient "github.com/satanaroom/chat_server/internal/clients/grpc/auth"
"github.com/satanaroom/chat_server/internal/closer"
"github.com/satanaroom/chat_server/internal/config"
Expand All @@ -20,11 +21,13 @@ type serviceProvider struct {
httpConfig config.HTTPConfig
swaggerConfig config.SwaggerConfig
tlsConfig config.TLSConfig
chatConfig config.ChatConfig

authClient authClient.Client
chatService chatService.Service

tlsCredentials credentials.TransportCredentials
tlsAuthCredentials credentials.TransportCredentials
tlsServerCredentials credentials.TransportCredentials

chatImpl *chatV1.Implementation
}
Expand All @@ -35,7 +38,7 @@ func newServiceProvider() *serviceProvider {

func (s *serviceProvider) ChatService(ctx context.Context) chatService.Service {
if s.chatService == nil {
s.chatService = chatService.NewService(s.AuthClient(ctx))
s.chatService = chatService.NewService(s.AuthClient(ctx), channels.NewChannels(s.ChatConfig().Capacity()))
}

return s.chatService
Expand All @@ -56,7 +59,7 @@ func (s *serviceProvider) AuthClientConfig() config.AuthClientConfig {

func (s *serviceProvider) AuthClient(ctx context.Context) authClient.Client {
if s.authClient == nil {
opts := grpc.WithTransportCredentials(s.TLSCredentials(ctx))
opts := grpc.WithTransportCredentials(s.TLSAuthCredentials(ctx))

conn, err := grpc.DialContext(ctx, s.AuthClientConfig().Host(), opts)
if err != nil {
Expand Down Expand Up @@ -123,6 +126,19 @@ func (s *serviceProvider) TLSConfig() config.TLSConfig {
return s.tlsConfig
}

func (s *serviceProvider) ChatConfig() config.ChatConfig {
if s.chatConfig == nil {
cfg, err := config.NewChatConfig()
if err != nil {
logger.Fatalf("failed to get chat config: %s", err.Error())
}

s.chatConfig = cfg
}

return s.chatConfig
}

func (s *serviceProvider) ChatImpl(ctx context.Context) *chatV1.Implementation {
if s.chatImpl == nil {
s.chatImpl = chatV1.NewImplementation(s.ChatService(ctx))
Expand All @@ -131,15 +147,28 @@ func (s *serviceProvider) ChatImpl(ctx context.Context) *chatV1.Implementation {
return s.chatImpl
}

func (s *serviceProvider) TLSCredentials(_ context.Context) credentials.TransportCredentials {
if s.tlsCredentials == nil {
creds, err := credentials.NewClientTLSFromFile(s.TLSConfig().CertFile(), "")
func (s *serviceProvider) TLSAuthCredentials(_ context.Context) credentials.TransportCredentials {
if s.tlsAuthCredentials == nil {
creds, err := credentials.NewClientTLSFromFile(s.TLSConfig().AuthCertFile(), "")
if err != nil {
logger.Fatalf("new auth client tls from file: %s", err.Error())
}

s.tlsAuthCredentials = creds
}

return s.tlsAuthCredentials
}

func (s *serviceProvider) TLSServerCredentials(_ context.Context) credentials.TransportCredentials {
if s.tlsServerCredentials == nil {
creds, err := credentials.NewServerTLSFromFile(s.TLSConfig().ServerCertFile(), s.TLSConfig().ServerKeyFile())
if err != nil {
logger.Fatalf("new client tls from file: %s", err.Error())
logger.Fatalf("new server tls from file: %s", err.Error())
}

s.tlsCredentials = creds
s.tlsServerCredentials = creds
}

return s.tlsCredentials
return s.tlsServerCredentials
}
Loading

0 comments on commit 3e8d3fe

Please sign in to comment.