DefDrive provides a secure file management system with per-user directory isolation, file ownership tracking, and metadata storage. Files are stored on disk with database records tracking ownership, size, and access permissions.
// From controllers/file.go:24-30func (fc *FileController) Upload(c *gin.Context) { // Get current user ID from context (set by auth middleware) userID, exists := c.Get("userID") if !exists { c.JSON(http.StatusUnauthorized, gin.H{"error": "User not authenticated"}) return } // ...}
The upload endpoint requires authentication. The user ID is extracted from the JWT token by the AuthRequired() middleware.
// From controllers/file.go:81-86// Create user directory if it doesn't existuserDir := filepath.Join("/app/data/uploads", user.Username)if err := os.MkdirAll(userDir, 0755); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create user directory"}) return}
// From controllers/file.go:88-93// Check if file already existsfilePath := filepath.Join(userDir, filepath.Base(file.Filename))if _, err := os.Stat(filePath); err == nil { c.JSON(http.StatusConflict, gin.H{"error": "A file with this name already exists in your folder"}) return}
DefDrive prevents duplicate filenames within a user’s directory. To upload a file with the same name, the existing file must be deleted first.
// From controllers/file.go:101-116// Store only the relative path (username/filename) in the databaserelativePath := filepath.Join(user.Username, filepath.Base(file.Filename))// Create file record in databasefileRecord := models.File{ Name: file.Filename, Location: relativePath, UserID: userID.(uint), Size: file.Size, Public: false, // Default to private}if result := fc.DB.Create(&fileRecord); result.Error != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to record file in database"}) return}
Files default to private (Public = false). Use the TogglePublicAccess endpoint to make files public.
// From controllers/file.go:82 and 102userDir := filepath.Join("/app/data/uploads", user.Username) // Absolute path for disk operationsrelativePath := filepath.Join(user.Username, filepath.Base(file.Filename)) // Relative path for database
Example:
Absolute disk path: /app/data/uploads/johndoe/document.pdf
Relative database path: johndoe/document.pdf
Storing relative paths in the database makes the system portable and allows the base upload directory to be changed without database migrations.
// From controllers/file.go:162-166// Check if user owns the fileif file.UserID != userID.(uint) { c.JSON(http.StatusForbidden, gin.H{"error": "You don't have permission to modify this file"}) return}
All file modification operations (toggle public, delete) verify ownership before proceeding.
// From models/user.go:17Files []File `gorm:"foreignKey:UserID;references:ID"`// From models/file.go:15-16UserID uint `gorm:"index"`User User `gorm:"foreignKey:UserID;references:ID"`
The UserID field is indexed for efficient querying when listing a user’s files or calculating storage usage.
Access links must be deleted before the File record to maintain referential integrity. The File record is deleted before the physical file to ensure the database reflects the true state.
// From controllers/file.go:241-291func (fc *FileController) GetUserStats(c *gin.Context) { // Get current file count var fileCount int64 fc.DB.Model(&models.File{}).Where("user_id = ?", userID).Count(&fileCount) // Get current storage usage var totalSize int64 fc.DB.Model(&models.File{}).Where("user_id = ?", userID).Select("COALESCE(SUM(size), 0)").Scan(&totalSize) // Get file type breakdown var fileStats []struct { Extension string `json:"extension"` Count int64 `json:"count"` TotalSize int64 `json:"total_size"` } fc.DB.Raw(` SELECT CASE WHEN name ~ '\.' THEN LOWER(RIGHT(name, LENGTH(name) - POSITION('.' IN REVERSE(name)))) ELSE 'no_extension' END as extension, COUNT(*) as count, COALESCE(SUM(size), 0) as total_size FROM files WHERE user_id = ? AND deleted_at IS NULL GROUP BY extension ORDER BY total_size DESC `, userID).Scan(&fileStats) // ...}