diff --git a/README.md b/README.md index bb9e470..dd97c84 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,10 @@ ![system-design](docs/system-design.png) +## ERD Diagram + +![erd-diagram](docs/erd.png) + ## Start project ``` diff --git a/apps/api/db/connectDB.go b/apps/api/db/connectDB.go index 5f18c44..99a724d 100644 --- a/apps/api/db/connectDB.go +++ b/apps/api/db/connectDB.go @@ -16,8 +16,7 @@ func ConnectDB() { dsn := fmt.Sprintf("%s&parseTime=True", os.Getenv("DSN")) DB, err = gorm.Open(postgres.Open(dsn), &gorm.Config{ - TranslateError: true, - DisableForeignKeyConstraintWhenMigrating: true, + TranslateError: true, }) if err != nil { log.Fatal("failed to open db connection", err) diff --git a/apps/api/go.mod b/apps/api/go.mod index 513722b..e59fe29 100644 --- a/apps/api/go.mod +++ b/apps/api/go.mod @@ -19,6 +19,8 @@ require ( gorm.io/gorm v1.25.5 ) +require github.com/google/uuid v1.4.0 // indirect + require ( github.com/aws/aws-sdk-go-v2/credentials v1.16.4 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.5 // indirect diff --git a/apps/api/go.sum b/apps/api/go.sum index bfe54e3..6e040b9 100644 --- a/apps/api/go.sum +++ b/apps/api/go.sum @@ -78,6 +78,8 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= diff --git a/apps/api/handlers/auth.go b/apps/api/handlers/auth.go index dd73cb0..1c2f14f 100644 --- a/apps/api/handlers/auth.go +++ b/apps/api/handlers/auth.go @@ -21,7 +21,10 @@ func SignIn(c *gin.Context) { user, err := services.GetUserByMail(req.Email) - if err != nil { + if err != nil && err == gorm.ErrRecordNotFound { + h.Fail400(c, "User doesn't exist") + return + } else if err != nil { h.Fail400(c, err.Error()) return } diff --git a/apps/api/handlers/chat.go b/apps/api/handlers/chat.go index 1c070e5..6337895 100644 --- a/apps/api/handlers/chat.go +++ b/apps/api/handlers/chat.go @@ -40,11 +40,9 @@ func CreateChat(c *gin.Context) { return } - user := c.MustGet("user").(*models.User) - chat, err := services.CreateChat(models.Chat{ Name: req.Name, - OwnerID: user.ID, + OwnerID: c.MustGet("user").(*models.User).ID, }) if err != nil { diff --git a/apps/api/handlers/message.go b/apps/api/handlers/message.go index 1e20d27..95c9749 100644 --- a/apps/api/handlers/message.go +++ b/apps/api/handlers/message.go @@ -41,11 +41,9 @@ func SendMessage(c *gin.Context) { return } - chatID, err := strconv.ParseUint(c.Param("chatID"), 10, 64) - message, err := services.CreateMessage(models.Message{ Content: req.Content, - ChatID: chatID, + ChatID: c.Param("chatID"), OwnerID: c.MustGet("user").(*models.User).ID, }) @@ -54,7 +52,7 @@ func SendMessage(c *gin.Context) { return } - err = services.UpdateLastMessage(chatID, *message) + err = services.UpdateLastMessage(c.Param("chatID"), *message) if err != nil { h.Fail400(c, err.Error()) diff --git a/apps/api/migrations/main.go b/apps/api/migrations/main.go index cd7c68a..103a4dc 100644 --- a/apps/api/migrations/main.go +++ b/apps/api/migrations/main.go @@ -15,6 +15,12 @@ func init() { } func main() { - db.DB.AutoMigrate(&models.User{}, &models.Chat{}, &models.Message{}, &models.FriendRequest{}, &models.Community{}) + db.DB.AutoMigrate( + &models.User{}, + &models.Community{}, + &models.Chat{}, + &models.Message{}, + &models.FriendRequest{}, + ) fmt.Println("👍 Migration complete") } diff --git a/apps/api/models/base.go b/apps/api/models/base.go index b0a71ac..4f8454a 100644 --- a/apps/api/models/base.go +++ b/apps/api/models/base.go @@ -1,14 +1,24 @@ package models -import "time" +import ( + "time" + + "github.com/google/uuid" + "gorm.io/gorm" +) type Base struct { - ID uint `gorm:"primary_key" json:"id"` + ID string `gorm:"primary_key" json:"id"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` DeletedAt *time.Time `sql:"index" json:"deletedAt"` } +func (base *Base) BeforeCreate(tx *gorm.DB) (err error) { + base.ID = uuid.New().String() + return nil +} + type BasePaginationRequest struct { Page int `json:"page"` Limit int `json:"limit"` diff --git a/apps/api/models/chat.go b/apps/api/models/chat.go index 0220b0f..bb85e13 100644 --- a/apps/api/models/chat.go +++ b/apps/api/models/chat.go @@ -2,10 +2,12 @@ package models type Chat struct { Base - Name string `gorm:"not null;type:varchar(255)" json:"name"` - Members []*User `gorm:"many2many:chat_users;" json:"members"` - OwnerID uint `gorm:"not null" json:"ownerId"` - LastMessage Message `gorm:"foreignKey:ChatID" json:"lastMessage"` + Name string `gorm:"not null;type:varchar(255)" json:"name"` + Members []*User `gorm:"many2many:chat_users;" json:"members"` + OwnerID string `gorm:"not null" json:"ownerId"` + Owner User `gorm:"foreignKey:OwnerID;references:ID" json:"owner"` + LastMessageID string `json:"lastMessageId"` + LastMessage *Message `gorm:"foreignKey:LastMessageID;references:ID" json:"lastMessage"` } type CreateChatRequest struct { diff --git a/apps/api/models/community.go b/apps/api/models/community.go index 9e6c9fe..52784b7 100644 --- a/apps/api/models/community.go +++ b/apps/api/models/community.go @@ -2,10 +2,11 @@ package models type Community struct { Base - Name string `gorm:"not null;type:varchar(255)" json:"name"` - Logo string `gorm:"not null;type:text;" json:"logo"` - OwnerID uint `gorm:"not null" json:"ownerId"` - Users []User `gorm:"many2many:user_communities;" json:"users"` + Name string `gorm:"not null;type:varchar(255)" json:"name"` + Logo string `gorm:"not null;type:text;" json:"logo"` + OwnerID string `gorm:"not null" json:"ownerId"` + Owner *User `gorm:"foreignKey:OwnerID;references:ID" json:"owner"` + Users []*User `gorm:"many2many:user_communities;" json:"users"` } type CreateCommunityRequest struct { diff --git a/apps/api/models/friend-request.go b/apps/api/models/friend-request.go index 9079d43..eb77c53 100644 --- a/apps/api/models/friend-request.go +++ b/apps/api/models/friend-request.go @@ -2,13 +2,13 @@ package models type FriendRequest struct { Base - UserID uint `gorm:"not null" json:"userId"` - FriendID uint `gorm:"not null" json:"friendId"` + UserID string `gorm:"not null" json:"userId"` + FriendID string `gorm:"not null" json:"friendId"` } type AddFriendRequest struct { - UserID uint `json:"userId" validate:"required"` - FriendID uint `json:"friendId" validate:"required"` + UserID string `json:"userId" validate:"required"` + FriendID string `json:"friendId" validate:"required"` } type AcceptFriendRequest struct { diff --git a/apps/api/models/message.go b/apps/api/models/message.go index 04b8909..4f6d334 100644 --- a/apps/api/models/message.go +++ b/apps/api/models/message.go @@ -3,8 +3,10 @@ package models type Message struct { Base Content string `gorm:"not null;type:varchar(255)" json:"content"` - ChatID uint64 `gorm:"not null" json:"chatId"` - OwnerID uint `gorm:"not null" json:"ownerId"` + ChatID string `gorm:"not null" json:"chatId"` + Chat Chat `gorm:"foreignKey:ChatID;references:ID" json:"chat"` + OwnerID string `gorm:"not null;type:uuid" json:"ownerId"` + Owner User `gorm:"foreignKey:OwnerID;references:ID" json:"owner"` } type MessageRequest struct { diff --git a/apps/api/models/user.go b/apps/api/models/user.go index 8adb2e6..7b4fda4 100644 --- a/apps/api/models/user.go +++ b/apps/api/models/user.go @@ -15,9 +15,9 @@ type User struct { Password string `gorm:"not null" json:"-"` Gender string `gorm:"not null" json:"gender"` Chats []*Chat `gorm:"many2many:chat_users;" json:"chats"` - Communities []Community `gorm:"many2many:user_communities;" json:"communities"` + Communities []*Community `gorm:"many2many:user_communities;" json:"communities"` Friends []*User `gorm:"many2many:user_friends" json:"friends"` - FriendRequests []FriendRequest `json:"friendRequests"` + FriendRequests []FriendRequest `gorm:"foreignKey:UserID" json:"friendRequests"` } type UserFriend struct { diff --git a/apps/api/services/chat.go b/apps/api/services/chat.go index d7c163f..00dd16a 100644 --- a/apps/api/services/chat.go +++ b/apps/api/services/chat.go @@ -5,9 +5,9 @@ import ( "github.com/tranthaison1231/meta-clone/api/models" ) -func GetChats(userID uint) (*[]models.Chat, error) { +func GetChats(userID string) (*[]models.Chat, error) { var chats []models.Chat - err := db.DB.Model(&models.Chat{}).Preload("LastMessage").Preload("Members").Where("owner_id = ?", userID).Find(&chats).Error + err := db.DB.Model(&models.Chat{}).Preload("LastMessage").Preload("Members").Preload("Owner").Where("owner_id = ?", userID).Find(&chats).Error if err != nil { return nil, err @@ -48,11 +48,11 @@ func AddMemberToChat(chatID uint64, memberID uint) (*models.Chat, error) { return &chat, nil } -func UpdateLastMessage(chatID uint64, message models.Message) error { +func UpdateLastMessage(chatID string, message models.Message) error { var chat models.Chat err := db.DB.Model(&chat).Where("id = ?", chatID).First(&chat).Error - chat.LastMessage = message + chat.LastMessageID = message.ID err = db.DB.Save(&chat).Error diff --git a/apps/api/services/community.go b/apps/api/services/community.go index 557f5ca..5210f16 100644 --- a/apps/api/services/community.go +++ b/apps/api/services/community.go @@ -5,7 +5,7 @@ import ( "github.com/tranthaison1231/meta-clone/api/models" ) -func GetCommunities(userID uint) (*[]models.Community, error) { +func GetCommunities(userID string) (*[]models.Community, error) { var communities []models.Community err := db.DB.Model(&models.Community{}).Where("owner_id = ?", userID).Find(&communities).Error diff --git a/apps/api/services/user.go b/apps/api/services/user.go index 509287d..43d2d33 100644 --- a/apps/api/services/user.go +++ b/apps/api/services/user.go @@ -91,7 +91,7 @@ func GetUserFriends(userId uint, request *models.BasePaginationRequest) (*models }, nil } -func AddFriend(userId uint, friendId uint) (*models.FriendRequest, error) { +func AddFriend(userId string, friendId string) (*models.FriendRequest, error) { var friendRequest models.FriendRequest var user models.User @@ -132,7 +132,7 @@ func AddFriend(userId uint, friendId uint) (*models.FriendRequest, error) { return &newFriendRequest, nil } -func AcceptFriend(userId uint, friendId uint, isRejecting bool) (string, error) { +func AcceptFriend(userId string, friendId string, isRejecting bool) (string, error) { var friendRequest models.FriendRequest var user models.User var friend models.User diff --git a/apps/messenger-web/src/routes/(auth)/t/[id]/+layout.svelte b/apps/messenger-web/src/routes/(auth)/t/[id]/+layout.svelte index 6c274d3..d2a7beb 100644 --- a/apps/messenger-web/src/routes/(auth)/t/[id]/+layout.svelte +++ b/apps/messenger-web/src/routes/(auth)/t/[id]/+layout.svelte @@ -1,9 +1,7 @@ -
+

Chats

@@ -177,13 +175,13 @@ {#if !isSeenMessage} -
+
{/if}
{/each}
-
+
- +
messages.id [delete: No Action] + +Ref: chats.owner_id > users.id [delete: No Action] + +Ref: communities.owner_id > users.id [delete: No Action] + +Ref: chat_users.chat_id > chats.id [delete: No Action] + +Ref: chat_users.user_id > users.id [delete: No Action] + +Ref: friend_requests.user_id > users.id [delete: No Action] + +Ref: messages.chat_id - chats.id + +Ref: messages.owner_id > users.id [delete: No Action] + +Ref: user_communities.community_id > communities.id [delete: No Action] + +Ref: user_communities.user_id > users.id [delete: No Action] + +Ref: user_friends.friend_id > users.id [delete: No Action] + +Ref: user_friends.user_id > users.id [delete: No Action] diff --git a/docs/erd.png b/docs/erd.png new file mode 100644 index 0000000..7d754df Binary files /dev/null and b/docs/erd.png differ