Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/SpeedReach/monify
Browse files Browse the repository at this point in the history
modify the function "createGroupMember()": remove memberId
  • Loading branch information
Danielllllllllllllll committed May 24, 2024
2 parents f978791 + 655c5ea commit 8229233
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 8 deletions.
11 changes: 8 additions & 3 deletions internal/services/group/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ package group
import (
"context"
"database/sql"
"monify/internal/middlewares"
monify "monify/protobuf"

"github.com/google/uuid"
"go.uber.org/zap"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"monify/internal/middlewares"
monify "monify/protobuf"
)

func createGroup(ctx context.Context, db *sql.DB, name string) (uuid.UUID, error) {
Expand All @@ -18,7 +20,8 @@ func createGroup(ctx context.Context, db *sql.DB, name string) (uuid.UUID, error
return groupId, err
}

func (g Service) CreateGroup(ctx context.Context, req *monify.CreateGroupRequest) (*monify.CreateGroupResponse, error) {
func (s Service) CreateGroup(ctx context.Context, req *monify.CreateGroupRequest) (*monify.CreateGroupResponse, error) {
logger := ctx.Value(middlewares.LoggerContextKey{}).(*zap.Logger)
userId := ctx.Value(middlewares.UserIdContextKey{})
if userId == nil {
return nil, status.Error(codes.Unauthenticated, "Unauthorized.")
Expand All @@ -29,11 +32,13 @@ func (g Service) CreateGroup(ctx context.Context, req *monify.CreateGroupRequest
db := ctx.Value(middlewares.StorageContextKey{}).(*sql.DB)
groupId, err := createGroup(ctx, db, req.Name)
if err != nil {
logger.Error("", zap.Error(err))
return nil, status.Error(codes.Internal, "internal")
}

memberId, err := createGroupMember(ctx, db, groupId, userUid)
if err != nil {
logger.Error("", zap.Error(err))
return nil, status.Errorf(codes.Internal, "internal")
}

Expand Down
81 changes: 81 additions & 0 deletions internal/services/group/generate_invite_code.go
Original file line number Diff line number Diff line change
@@ -1 +1,82 @@
package group

import (
"context"
"database/sql"
"github.com/google/uuid"
"go.uber.org/zap"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"math"
"math/rand"
"monify/internal/middlewares"
monify "monify/protobuf"
"time"
)

const (
inviteCodeChars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
timeDeterLength = 4
randomLength = 2
inviteCodeLength = timeDeterLength + randomLength
expiresInterval = int64(time.Minute * 10)
)

func checkPermission(ctx context.Context, db *sql.DB, groupId uuid.UUID, userId uuid.UUID) (bool, error) {
var count int
err := db.QueryRow(`
SELECT COUNT(*) FROM group_member WHERE group_id = $1 AND user_id = $2
`, groupId, userId).Scan(&count)
if err != nil {
return false, err
}
return count > 0, nil
}

func (s Service) GenerateInviteCode(ctx context.Context, req *monify.GenerateInviteCodeRequest) (*monify.GenerateInviteCodeResponse, error) {
userId, ok := ctx.Value(middlewares.UserIdContextKey{}).(uuid.UUID)
db := ctx.Value(middlewares.StorageContextKey{}).(*sql.DB)
logger := ctx.Value(middlewares.LoggerContextKey{}).(*zap.Logger)
if !ok {
return nil, status.Error(codes.Unauthenticated, "Unauthorized.")
}
groupId, err := uuid.Parse(req.GroupId)
if err != nil {
return nil, status.Error(codes.InvalidArgument, "Invalid group ID")
}
hasPerm, err := checkPermission(ctx, db, groupId, userId)
if err != nil {
logger.Error("Failed to check permission", zap.Error(err))
return nil, status.Error(codes.Internal, "Internal")
}
if !hasPerm {
return nil, status.Error(codes.PermissionDenied, "Permission denied")
}
inviteCode := generateInviteCode()
_, err = db.Exec(`
INSERT INTO invite_code (group_id, code) VALUES ($1, $2)
`, groupId, inviteCode)
return nil, err
}

func indexToChar(index int) byte {
return inviteCodeChars[index]
}
func generateInviteCode() string {
charsCount := len(inviteCodeChars)
seed := time.Now().UnixMilli() % expiresInterval
inviteCodeRange := int(math.Pow(float64(charsCount), timeDeterLength))
code := int(seed) % inviteCodeRange
inviteCode := ""

for i := 0; i < timeDeterLength; i++ {
index := code % charsCount
code /= charsCount
inviteCode += string(indexToChar(index))
}

for i := 0; i < randomLength; i++ {
inviteCode += string(indexToChar(rand.Int() % charsCount))
}
return inviteCode
}
45 changes: 45 additions & 0 deletions internal/services/group/invite_code_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package group

import (
"github.com/stretchr/testify/assert"
"testing"
"time"
)

func TestIndexToChar(t *testing.T) {
assert.Equal(t, byte('0'), indexToChar(0), "Expected '0' for index 0")
assert.Equal(t, byte('1'), indexToChar(1), "Expected '1' for index 1")
assert.Equal(t, byte('2'), indexToChar(2), "Expected '2' for index 2")
assert.Equal(t, byte('8'), indexToChar(8), "Expected '8' for index 8")
assert.Equal(t, byte('a'), indexToChar(10), "Expected 'a' for index 10")
assert.Equal(t, byte('b'), indexToChar(11), "Expected 'b' for index 11")
assert.Equal(t, byte('z'), indexToChar(35), "Expected 'z' for index 35")
assert.Equal(t, byte('A'), indexToChar(36), "Expected 'A' for index 36")
assert.Equal(t, byte('B'), indexToChar(37), "Expected 'B' for index 37")
assert.Equal(t, byte('Z'), indexToChar(61), "Expected 'Z' for index 61")
}

func TestGenerateInviteCodeUniqueness(t *testing.T) {
inviteCode := generateInviteCode()
println(inviteCode)
assert.Len(t, inviteCode, inviteCodeLength, "Expected invite code to be 6 characters long")
for _, char := range inviteCode {
assert.True(t, char >= '0' && char <= '9' || char >= 'a' && char <= 'z' || char >= 'A' && char <= 'Z', "Expected invite code to contain only alphanumeric characters")
}
time.Sleep(time.Millisecond)
inviteCode2 := generateInviteCode()
assert.NotEqual(t, inviteCode, inviteCode2, "Expected two different invite codes")
}

func TestGenerateInviteCodeRandomness(t *testing.T) {
//try to generate 1000 invite codes and check if 990 of them are unique
failCount := 0
tries := 1000
for i := 0; i < tries; i++ {
if generateInviteCode() == generateInviteCode() {
failCount++
}
}
println(failCount)
assert.LessOrEqual(t, failCount, 10, "Expected 990 out of 1000 invite codes to be unique")
}
2 changes: 1 addition & 1 deletion internal/services/group/list_joined.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"google.golang.org/grpc/status"
)

func (g Service) ListJoinedGroups(ctx context.Context, empty *monify.Empty) (*monify.ListJoinedGroupsResponse, error) {
func (s Service) ListJoinedGroups(ctx context.Context, empty *monify.Empty) (*monify.ListJoinedGroupsResponse, error) {
logger := ctx.Value(middlewares.LoggerContextKey{}).(*zap.Logger)
userId := ctx.Value(middlewares.UserIdContextKey{})
if userId == nil {
Expand Down
7 changes: 4 additions & 3 deletions internal/services/group/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ package group
import (
"context"
"database/sql"
"github.com/google/uuid"
monify "monify/protobuf"

"github.com/google/uuid"
)

type Service struct {
Expand All @@ -14,8 +15,8 @@ type Service struct {
func createGroupMember(ctx context.Context, db *sql.DB, groupId uuid.UUID, userId uuid.UUID) (uuid.UUID, error) {
memberId := uuid.New()
_, err := db.Exec(`
INSERT INTO group_member (group_member_id, group_id, user_id) VALUES ($1,$2,$3)
`, memberId, groupId, userId)
INSERT INTO group_member (group_id, user_id) VALUES ($1,$2)
`, groupId, userId)
if err != nil {
return uuid.Nil, err
}
Expand Down
1 change: 0 additions & 1 deletion internal/test/group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,5 @@ func TestCreateGroup(t *testing.T) {
group, err := client.CreateGroup(context.TODO(), &monify.CreateGroupRequest{Name: "test"})
assert.NoError(t, err)
assert.NotEmpty(t, group)
//userId2 := client.CreateTestUser()
client.SetTestUser(userId1)
}

0 comments on commit 8229233

Please sign in to comment.