Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ jobs:
steps:
- checkout
- setup_remote_docker:
version: 20.10.14
docker_layer_caching: true
- build-docker-image
- run:
Expand All @@ -67,7 +66,6 @@ jobs:
steps:
- checkout
- setup_remote_docker:
version: 20.10.14
docker_layer_caching: true
- attach_workspace:
at: /tmp/workspace
Expand Down
2 changes: 1 addition & 1 deletion docker/Dockerfile.dev
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ ENV CGO_ENABLED 0
ENV GOPATH /go
ENV GOCACHE /go-build

RUN go install github.com/cosmtrek/air@latest
RUN go install github.com/air-verse/air@latest

COPY go.mod go.sum ./

Expand Down
2 changes: 0 additions & 2 deletions internal/api/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,6 @@ func LoginUser(router *gin.RouterGroup, tokenMaker token.Maker) {
return
}

log.Infof("nonce: %s", nonce)

// validate signature
result := web3.ValidateMessageSignature(
f.WalletAddress,
Expand Down
17 changes: 9 additions & 8 deletions internal/api/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ func GetShareState(router *gin.RouterGroup) {
//get share state, if doesn't exist, create it
share_state, _, err := query.FindShareStateByFileUID(file_uid)
if err != nil {
log.Errorf("Error finding share state: %s", err)
//log.Errorf("Error finding share state: %s", err)
share_state, err = query.CreateShareState(tx, f)
if err != nil {
log.Errorf("cannot create share state: %s", err)
Expand Down Expand Up @@ -188,7 +188,7 @@ func GetShareState(router *gin.RouterGroup) {
// get share state, if doesn't exist, create it
shareState, _, err := query.FindShareStateByFileUID(fileUID)
if err != nil {
log.Errorf("Error finding share state: %s", err)
//log.Errorf("Error finding share state: %s", err)
shareState, err = query.CreateShareState(tx, f)
if err != nil {
log.Errorf("cannot create share state: %s", err)
Expand Down Expand Up @@ -411,7 +411,7 @@ func PublishFile(router *gin.RouterGroup) {
ctx.JSON(http.StatusBadRequest, gin.H{"error": "Invalid share type"})
return
}

//cancel if user not found
receiverNil := shareWithUser == nil || shareWithUser.ID == 0
if receiverNil {
Expand Down Expand Up @@ -458,7 +458,7 @@ func PublishFile(router *gin.RouterGroup) {
}

// delete the file share state user shared in case it exists
query.DeleteFileShareStatesUserShared(db.Db(),f.UID, shareWithUser.ID)
query.DeleteFileShareStatesUserShared(db.Db(), f.UID, shareWithUser.ID)
// create a new share state user shared
shareState, err := query.CreateShareStateUserShared(tx, newFile, shareWithUser.ID)
if err != nil {
Expand All @@ -484,7 +484,7 @@ func PublishFile(router *gin.RouterGroup) {
// Send email with the file link to the user if the share type is email
if shareType == "email" {
// Send email with the file link to the user and pass also the sender user's email
sendEmailLinkToUser(authPayload.UserName, shareWithUser, accountIdentifier, newFile, publicFile)
sendEmailLinkToUser(authPayload.UserName, accountIdentifier, newFile, publicFile)
}

// Save the updated shareState.PublicFile
Expand Down Expand Up @@ -518,15 +518,16 @@ func formatBytes(size int64) string {
return fmt.Sprintf("%.1f %cB", float64(size)/float64(div), "KMGTPE"[exp])
}

func sendEmailLinkToUser(username string, user *entity.User, email string, file *entity.File, publicFile *entity.PublicFileUserShared) {
func sendEmailLinkToUser(username string, email string, file *entity.File, publicFile *entity.PublicFileUserShared) {

mg := mg.Mailgun{
Domain: "hello.app",
ApiKey: config.Env().MailGunApiKey,
}

mg.Init()
id, err := mg.SendEmail(
//id, err := mg.SendEmail(
_, err := mg.SendEmail(
"noreply@hello.app",
email,
"hello.app | Received file named "+file.Name+"",
Expand All @@ -540,7 +541,7 @@ func sendEmailLinkToUser(username string, user *entity.User, email string, file
},
)

log.Infof("id: %s", id)
//log.Infof("id: %s", id)

if err != nil {
log.Errorf("failed to send email: %v", err)
Expand Down
6 changes: 2 additions & 4 deletions internal/api/file_upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,6 @@ func CheckFilesExistInPool(router *gin.RouterGroup) {
headObject, err := s3.HeadObject(s3Config, config.Env().WasabiBucket, customFileMeta.CID)
if err != nil {
//this means that the object doesn't exist at S3, so we can return CID to frontend for later upload of binary and metadata
log.Info("CID not found:")
log.Info(customFileMeta.CID)

} else {
//this means that the object exists at S3, so we can create a file entry on database for the file

Expand Down Expand Up @@ -155,7 +152,8 @@ func CheckFilesExistInPool(router *gin.RouterGroup) {
}

if headObject == nil {
log.Print("headObject is nil")
//file doesn't exist on pool
//log.Print("headObject is nil")
}
}

Expand Down
93 changes: 59 additions & 34 deletions internal/api/user_detail.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,72 +72,97 @@ func GetUserDetail(router *gin.RouterGroup) {
return
}

// get user files from the table "file_user" (where permission != deleted)
// get filesUser from the table "file_user" (where permission != deleted)
filesUser, err := query.GetFilesUserFromUser(user.ID)
if err != nil {
ctx.JSON(http.StatusInternalServerError, gin.H{"error": "error fetching user files"})
return
}

// start variables for shared files
var sharedWithUser entity.Files
var sharedByUser entity.Files
sharedByUserMap := make(map[uint]struct{})
sharedWithUserMap := make(map[string]struct{})

// iterate over files
// Create a channel to fetch files concurrently
type fileResult struct {
file *entity.File
err error
}
fileChan := make(chan fileResult, len(filesUser))

// Fetch files concurrently using goroutines
for _, fileUser := range filesUser {
// try to get file by its id
file, err := query.FindFileByID(fileUser.FileID)
if err != nil {
log.Errorf("error fetching file: %v", err)
if err != gorm.ErrRecordNotFound {
// if it's not a "not found" error it means it's probably an internal error, so stop here
go func(fileUser entity.FileUser) {
file, err := query.FindFileByID(fileUser.FileID)
fileChan <- fileResult{file: file, err: err}
}(fileUser)
}

for _, fileUser := range filesUser {
fileResult := <-fileChan
if fileResult.err != nil {
log.Errorf("error fetching file: %v", fileResult.err)
if fileResult.err != gorm.ErrRecordNotFound {
ctx.JSON(http.StatusInternalServerError, gin.H{"error": "error fetching file"})
return
}
// if it's a "not found" error, continue with the next file
continue
}

// get users with file CID
file := fileResult.file

// Filter files shared by the user
if file.FileShareState.ID != 0 && fileUser.Permission == entity.OwnerPermission {
if _, exists := sharedByUserMap[file.ID]; exists {
continue
}
/*|| !query.IsInSharedFolder(file.Root, authPayload.UserID) */
// TODO: check if the file/forder is in a shared folder or not
// (because if we only show the files in Root, the elements in a non-shared folder will not be shown)
sharedByUser = append(sharedByUser, *file)
sharedByUserMap[file.ID] = struct{}{}
}

// Check if the file CID has already been processed
if _, exists := sharedWithUserMap[file.CID]; exists {
continue // Skip processing the file if this CID has already been processed
}

// Concurrently fetch users with the file CID
usersWithFile, err := query.FindUsersByFileCID(file.CID)
if err != nil {
ctx.JSON(http.StatusInternalServerError, gin.H{"error": "error fetching users with file"})
return
}

// filter out usersID that belong to others than the current user
usersWithFileFiltered := []uint{}
// Filter out usersID that belong to others than the current user
usersWithFileFiltered := make([]uint, 0, len(usersWithFile))
for _, usrID := range usersWithFile {
if usrID != user.ID {
usersWithFileFiltered = append(usersWithFileFiltered, usrID)
}
}

if file.ID != 0 {
if fileUser.Permission == entity.SharedPermission && len(usersWithFileFiltered) > 0 {
// if the file is shared to current user and its more than one user with the file
// then it's a shared (with the user) file
if file.Root == "/" /*|| !query.IsInSharedFolder(file.Root, authPayload.UserID) */{
// if the file was shared by email or wallet, we need to get
// the public file and its share state
sharestatefound, err := query.GetFileShareStateByFileUIDAndUserID(file.UID, authPayload.UserID)
if err == nil {
file.FileShareState = query.ConvertToDomainEntities(sharestatefound)
}
sharedWithUser = append(sharedWithUser, *file)
}
} else if fileUser.Permission == entity.OwnerPermission && len(usersWithFileFiltered) > 0 {
// if the file owned by current user and its more than one user with the file
// then it's a shared (by the user) file
if file.Root == "/" /*|| !query.IsInSharedFolder(file.Root, authPayload.UserID) */{
// TODO: check if the file/forder is in a shared folder or not
// (because if we only show the files in Root, the elements in a non-shared folder will not be shown)
sharedByUser = append(sharedByUser, *file)
if file.ID != 0 && fileUser.Permission == entity.SharedPermission && len(usersWithFileFiltered) > 0 {
if file.Root == "/" {
// TODO: check if the file/forder is in a shared folder or not
// (because if we only show the files in Root, the elements in a non-shared folder will not be shown)
sharestatefound, err := query.GetFileShareStateByFileUIDAndUserID(file.UID, authPayload.UserID)
if err == nil {
file.FileShareState = query.ConvertToDomainEntities(sharestatefound)
}

sharedWithUser = append(sharedWithUser, *file)
// Mark this CID as processed to avoid duplicate entries
sharedWithUserMap[file.CID] = struct{}{}
}
}
}

// Close the channel after processing
close(fileChan)

// at this point we have all the shared files, now we need to get the folders

// get user folders from the table "folder_user"
Expand Down Expand Up @@ -185,7 +210,7 @@ func GetUserDetail(router *gin.RouterGroup) {
if folder.ID != 0 {
if folderUser.Permission == entity.SharedPermission && len(usersWithFolderFiltered) > 0 {
if folder.Root == "/" /*|| !query.IsInSharedFolder(folder.Root, authPayload.UserID)*/ {
// TODO: check if the file/forder is in a shared folder or not
// TODO: check if the file/forder is in a shared folder or not
// (because if we only show the files in Root, the elements in a non-shared folder will not be shown)
FoldersharedwithUser = append(FoldersharedwithUser, *folder)
}
Expand Down
8 changes: 4 additions & 4 deletions internal/config/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ type EnvVar struct {
DBPassword string
DBPort string
// Github OAuth credential
GithubClientID string
GithubClientSecret string
//GithubClientID string
//GithubClientSecret string
// Wasabi keys
WasabiAccessKey string
WasabiSecretKey string
Expand Down Expand Up @@ -76,8 +76,8 @@ func LoadEnv() (err error) {
DBPassword: os.Getenv("POSTGRES_PASSWORD"),
DBPort: os.Getenv("POSTGRES_PORT"),
// Github OAuth credentail
GithubClientID: os.Getenv("GITHUB_CLIENT_ID"),
GithubClientSecret: os.Getenv("GITHUB_CLIENT_SECRET"),
//GithubClientID: os.Getenv("GITHUB_CLIENT_ID"),
//GithubClientSecret: os.Getenv("GITHUB_CLIENT_SECRET"),
//Wasabi keys
WasabiAccessKey: os.Getenv("WASABI_ACCESS_KEY"),
WasabiSecretKey: os.Getenv("WASABI_SECRET_KEY"),
Expand Down
1 change: 0 additions & 1 deletion internal/entity/entity_init.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ func InitDb(opt migrate.Options) {
start := time.Now()

Entities.Migrate(db.Db(), opt)
Entities.WaitForMigration(db.Db())

log.Debugf("migrate: completed in %s", time.Since(start))
}
Expand Down
Loading