package metastore import ( "sort" "warpbox/lib/config" ) func ResolveUserPermissions(cfg *config.Config, user User, tags []Tag) EffectivePermissions { perms := EffectivePermissions{ MaxFileSizeBytes: cfg.DefaultUserMaxFileSizeBytes, MaxBoxSizeBytes: cfg.DefaultUserMaxBoxSizeBytes, ZipDownloadAllowed: cfg.ZipDownloadsEnabled, OneTimeDownloadAllowed: cfg.OneTimeDownloadsEnabled, } expirySet := make(map[int64]bool) for _, tag := range tags { tagPerms := tag.Permissions perms.UploadAllowed = perms.UploadAllowed || tagPerms.UploadAllowed perms.OneTimeDownloadAllowed = perms.OneTimeDownloadAllowed || tagPerms.OneTimeDownloadAllowed perms.ZipDownloadAllowed = perms.ZipDownloadAllowed || tagPerms.ZipDownloadAllowed perms.RenewableAllowed = perms.RenewableAllowed || tagPerms.RenewableAllowed perms.AdminAccess = perms.AdminAccess || tagPerms.AdminAccess perms.AdminUsersManage = perms.AdminUsersManage || tagPerms.AdminUsersManage perms.AdminSettingsManage = perms.AdminSettingsManage || tagPerms.AdminSettingsManage perms.AdminBoxesView = perms.AdminBoxesView || tagPerms.AdminBoxesView perms.RenewOnAccessSeconds = maxInt64(perms.RenewOnAccessSeconds, tagPerms.RenewOnAccessSeconds) perms.RenewOnDownloadSeconds = maxInt64(perms.RenewOnDownloadSeconds, tagPerms.RenewOnDownloadSeconds) if tagPerms.MaxFileSizeBytes != nil { perms.MaxFileSizeBytes = morePermissiveLimit(perms.MaxFileSizeBytes, *tagPerms.MaxFileSizeBytes) } if tagPerms.MaxBoxSizeBytes != nil { perms.MaxBoxSizeBytes = morePermissiveLimit(perms.MaxBoxSizeBytes, *tagPerms.MaxBoxSizeBytes) } for _, seconds := range tagPerms.AllowedExpirySeconds { if seconds >= 0 { expirySet[seconds] = true } } } if user.MaxFileSizeBytes != nil { perms.MaxFileSizeBytes = morePermissiveLimit(perms.MaxFileSizeBytes, *user.MaxFileSizeBytes) } if user.MaxBoxSizeBytes != nil { perms.MaxBoxSizeBytes = morePermissiveLimit(perms.MaxBoxSizeBytes, *user.MaxBoxSizeBytes) } if user.MaxExpirySeconds != nil { perms.MaxExpirySeconds = *user.MaxExpirySeconds } perms.MaxFileSizeBytes = capLimit(perms.MaxFileSizeBytes, cfg.GlobalMaxFileSizeBytes) perms.MaxBoxSizeBytes = capLimit(perms.MaxBoxSizeBytes, cfg.GlobalMaxBoxSizeBytes) perms.AllowedExpirySeconds = sortedExpirySet(expirySet) if !cfg.ZipDownloadsEnabled { perms.ZipDownloadAllowed = false } if !cfg.OneTimeDownloadsEnabled { perms.OneTimeDownloadAllowed = false } return perms } func ResolveGuestPermissions(cfg *config.Config) EffectivePermissions { return EffectivePermissions{ UploadAllowed: cfg.GuestUploadsEnabled, AllowedExpirySeconds: guestExpirySeconds(cfg), MaxFileSizeBytes: cfg.GlobalMaxFileSizeBytes, MaxBoxSizeBytes: cfg.GlobalMaxBoxSizeBytes, MaxExpirySeconds: cfg.MaxGuestExpirySeconds, OneTimeDownloadAllowed: cfg.OneTimeDownloadsEnabled, ZipDownloadAllowed: cfg.ZipDownloadsEnabled, RenewableAllowed: cfg.RenewOnAccessEnabled || cfg.RenewOnDownloadEnabled, } } func morePermissiveLimit(current int64, candidate int64) int64 { if current == 0 || candidate == 0 { return 0 } if candidate > current { return candidate } return current } func capLimit(value int64, globalMax int64) int64 { if globalMax == 0 { return value } if value == 0 || value > globalMax { return globalMax } return value } func sortedExpirySet(expirySet map[int64]bool) []int64 { values := make([]int64, 0, len(expirySet)) for value := range expirySet { values = append(values, value) } sort.Slice(values, func(i int, j int) bool { return values[i] < values[j] }) return values } func guestExpirySeconds(cfg *config.Config) []int64 { values := []int64{} if cfg.DefaultGuestExpirySeconds >= 0 { values = append(values, cfg.DefaultGuestExpirySeconds) } if cfg.MaxGuestExpirySeconds > 0 && cfg.MaxGuestExpirySeconds != cfg.DefaultGuestExpirySeconds { values = append(values, cfg.MaxGuestExpirySeconds) } return uniqueInt64s(values) } func uniqueInt64s(values []int64) []int64 { seen := make(map[int64]bool, len(values)) out := make([]int64, 0, len(values)) for _, value := range values { if seen[value] { continue } seen[value] = true out = append(out, value) } sort.Slice(out, func(i int, j int) bool { return out[i] < out[j] }) return out } func maxInt64(a int64, b int64) int64 { if b > a { return b } return a }