Add API to allow the physical file provider to show hidden files - #280
Conversation
|
Not sure about HiddenFileOptions as a name - hidden files has a specific meaning on NTFS, and you're including that, plus system, plus dot files. Maybe ExcludedFiles? Also is that enum a flag? Shouldn't we then mark it as such, or has that fallen out of favour? Then we'd switch to None / All as names, and remove Show from the others. |
Yes, it's a flag. Naming stuff is hard. ExcludedFiles sounds better than HiddenFileOptions. Is this what you had in mind? [Flags]
public enum ExcludedFiles
{
Default = 0xFFFF,
None = 0,
StartingWithPeriod = 0x0001,
Hidden = 0x0002,
System = 0x0004,
} |
|
All rather than default, but yes. Maybe PeriodPrefixed rather than StartingWithPeriod? Period is also very american, maybe DotPrefixed? |
|
DotFiles?
|
|
Ah yea, all doesn't make sense. Default is kinda smelly though. Does Dot* whatever also include directories? If so, DotFiles doesn't work either. |
|
Hmm, yup, includes directories. DotPrefixed more correct. That or |
|
Or PeriodMeansFullStopInProperEnglishNotSimplifiedEnglish ... |
|
Naming aside, I like the guts of this. I still think its weird filtering out dotprefixed files / folders by default - (I think this is special casing for tooling that wants to ignore things like .git folder) but I understand why you want to keep the default behaviour compatible. Flags for the win. |
|
Shouldn't overloads of |
That's a good observation. I originally couldn't come up with a scenario for these overloads that aren't solved by changing options passed to the PhysicalFilesProvider constructor overload. @nil4 do you have scenarios in mind? GetDirectoryContents will be easy to overload. Watch is going to be tricky. |
|
Attempt 3 at picking good names [Flags]
public enum ExcludedFiles
{
Sensitive = DotPrefixed | Hidden | System,
DotPrefixed = 0x0001,
Hidden = 0x0002,
System = 0x0004,
None = 0
} |
|
I don't have an actual scenario in mind, it's just that the abstraction seems inconsistent if one can pass To put it another way, if directory listing and It seems to me either no overload should take One argument to all methods having overloads would be the following: I'd like to use the default file provider for the static files middleware and not serve sensitive files by default, to keep my app secure. Using the same file provider, I should be able to pass explicit flags in those areas of my app where I need to enumerate the full contents of the file system, bypassing the default filters. I agree that |
|
I just saw your last commit now and it makes my feedback obsolete. Thanks! 👍 |
|
FYI - I added GetDirectoryContents.
You basically explained the scenario I'm thinking of. In many places in the code, you don't really want to allocate a new provider just to get a "hidden" file in one part of the code. |
|
|
|
Sensitive works. Because you are a gentle soul :D |
Scratch that. Turns out this is expensive and mangles the code. It's better to just create a new watcher altogether if you want to override the file provider's exclusion setting. |
| /// <paramref name="subpath" /> is absolute, if the directory does not exist, or <paramref name="subpath" /> has invalid | ||
| /// characters. | ||
| /// </returns> | ||
| public IDirectoryContents GetDirectoryContents(string subpath, ExcludedFiles excludedFiles) |
There was a problem hiding this comment.
Why add this method? It doesn't look like it's used by anything else here, and it's hidden the IFileProvider interface
There was a problem hiding this comment.
Same reason for adding the GetFileInfo overload. I'd like to use the default file provider most of the time, but still be able to bypass its filtering in special cases.
| /// Specifies while files are excluded by the physical file provider. | ||
| /// </summary> | ||
| [Flags] | ||
| public enum ExcludedFiles |
There was a problem hiding this comment.
FileFilterOptions \ FileFilter?
There was a problem hiding this comment.
Ah yes, this still says files when it could also be directories.
There was a problem hiding this comment.
ExclusionFilters?
There was a problem hiding this comment.
That sounds like a good name.
| { | ||
| return false; | ||
| } | ||
| else if (fileSystemInfo.Name.StartsWith(".") && (excluded & ExcludedFiles.DotPrefixed) != 0) |
There was a problem hiding this comment.
StartsWith(".", StringComparison.Ordinal)
There was a problem hiding this comment.
No non ordinal string comparisons! Security!
| /// <param name="excludedFiles">Specifies which files are excluded from the directory listing.</param> | ||
| public PhysicalDirectoryContents(string directory, ExcludedFiles excludedFiles) | ||
| { | ||
| _directory = directory ?? throw new ArgumentNullException(nameof(directory)); |
There was a problem hiding this comment.
Nope, we don't use throw expressions in our code.
There was a problem hiding this comment.
They have Fowler's (relucant) approval. I'll conceded throw expressions are not always the right choice, but I think they're a win for simple ctor checks.
| public enum ExcludedFiles | ||
| { | ||
| /// <summary> | ||
| /// Exclude files and directories when the name begins with a period, or has either <see cref="FileAttributes.Hidden"/> or <see cref="FileAttributes.System"/> is set on <see cref="FileSystemInfo.Attributes"/>. |
There was a problem hiding this comment.
Can we list the individual features here (combination of DotPrefixed, Hidden and System rather than re-iterate the description?
| /// <param name="subpath">A path under the root directory</param> | ||
| /// <param name="excludedFiles">Overrides default file exclusion behavior.</param> | ||
| /// <returns>The file information. Caller must check <see cref="IFileInfo.Exists"/> property. </returns> | ||
| public IFileInfo GetFileInfo(string subpath, ExcludedFiles excludedFiles) |
There was a problem hiding this comment.
This feels weird - why have the options at two different levels? It doesn't seem intuitive, for instance, if I specified ExcludedFiles.Hidden in the ctor, and ExcludedFiles.System here, I'd sort of expect it to filter both, not just the latter.
There was a problem hiding this comment.
Consider another scenario. The ctor was set to Hidden | DotPrefixed | System. If I call .GetFileInfo(".env", ExcludedFiles.None), what should happen? IMO the override behavior is easier to reason about.
|
|
||
| [Theory] | ||
| [MemberData(nameof(Combinations))] | ||
| public void FiltersExcludedFiles(string filename, FileAttributes attributes, ExcludedFiles excludedFiles, bool excluded) |
There was a problem hiding this comment.
Make these two separate tests. One for exclusion and one for inclusion.
There was a problem hiding this comment.
Not sure I understand the request. Am I missing scenarios? Or is this just a coding preference?
There was a problem hiding this comment.
The excluded parameter is essentially an if and ifs in a test are generally an indication of a conflating different scenarios.
| <TestSdkVersion>15.3.0-*</TestSdkVersion> | ||
| <XunitVersion>2.3.0-beta2-*</XunitVersion> | ||
| <MoqVersion>4.7.1</MoqVersion> | ||
| <MoqVersion>4.7.58</MoqVersion> |
There was a problem hiding this comment.
Make this a separate PR. Completely unrelated to this change.
There was a problem hiding this comment.
Seems like overkill. We're already in agreement that we want to upgrade. Ryan just hasn't done this repo yet. https://github.com/aspnet/Coherence-Signed/issues/583.
|
Attempt 4 at picking good names [Flags]
public enum ExclusionFilters
{
Sensitive= DotPrefixed | Hidden | System,
DotPrefixed = 0x0001,
Hidden = 0x0002,
System = 0x0004,
None = 0
} |
|
🔔 now that we've branched for 2.1, @Tratcher are you okay with this API addition? |
The default behavior remains consistent: files beginning with a period, Hidden and System files are filtered from the watcher, enumeration, and any other file listing. Adds ExclusionFilters. These flags to control the filtering behavior of the physical files provider.
cf0f6c1 to
a97b3ef
Compare
| /// <summary> | ||
| /// Helpful methods for FileSystem APIs. | ||
| /// </summary> | ||
| public static class FileSystemInfoHelper |
There was a problem hiding this comment.
Can this type stay internal? We kind of mostly regret having so many 'pub-ternal' types, so we'd rather not add too many more...
There was a problem hiding this comment.
Sure. It's not meant to be used by other components.
There was a problem hiding this comment.
Yeah that would be good... less future pain for us. Can you send an update for that? (New PR of course)
|
Hi. I as many others encountered shortcomings in PhysicalFileProvider in 2.0 and had to create my own implementation for allowing serving dot-files.
what if it will be needed to add something more? Another argument? and use it as ctor argument instead:
usage: I know you will say - use
|
|
@evil-shrike this PR was closed quite a while ago. Please open a new issue with your feedback. |


Resolves #186
The default behavior remains consistent: files beginning with a period, Hidden and System files are filtered from the watcher, enumeration, and any other file listing.
The ExclusionFilters enum allows consumers to override this behavior by passing in these flags to one of the new overrides.
cc @dazinator