|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Reflection;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Options;
using Moq;
namespace Microsoft.Extensions.DependencyInjection;
public class PageConventionCollectionExtensionsTest
{
[Fact]
public void AddFilter_AddsFiltersToAllPages()
{
// Arrange
var filter = Mock.Of<IFilterMetadata>();
var conventions = GetConventions();
var models = new[]
{
CreateApplicationModel("/Pages/Index.cshtml", "/Index"),
CreateApplicationModel("/Pages/Users/Account.cshtml", "/Users/Account"),
CreateApplicationModel("/Pages/Users/Contact.cshtml", "/Users/Contact"),
};
// Act
conventions.ConfigureFilter(filter);
ApplyConventions(conventions, models);
// Assert
Assert.Collection(models,
model => Assert.Same(filter, Assert.Single(model.Filters)),
model => Assert.Same(filter, Assert.Single(model.Filters)),
model => Assert.Same(filter, Assert.Single(model.Filters)));
}
[Fact]
public void AuthorizePage_AddsAllowAnonymousAttributeToSpecificPage()
{
// Arrange
var conventions = GetConventions();
var models = new[]
{
CreateApplicationModel("/Pages/Index.cshtml", "/Index"),
CreateApplicationModel("/Pages/Users/Account.cshtml", "/Users/Account"),
CreateApplicationModel("/Pages/Users/Contact.cshtml", "/Users/Contact"),
};
// Act
conventions.AuthorizeFolder("/Users");
conventions.AllowAnonymousToPage("/Users/Contact");
ApplyConventions(conventions, models);
// Assert
Assert.Collection(models,
model => Assert.Empty(model.EndpointMetadata),
model =>
{
Assert.Equal("/Users/Account", model.ViewEnginePath);
Assert.Empty(model.Filters);
Assert.IsType<AuthorizeAttribute>(Assert.Single(model.EndpointMetadata));
},
model =>
{
Assert.Equal("/Users/Contact", model.ViewEnginePath);
Assert.Empty(model.Filters);
Assert.IsType<AuthorizeAttribute>(model.EndpointMetadata[0]);
Assert.IsType<AllowAnonymousAttribute>(model.EndpointMetadata[1]);
});
}
[Fact]
public void AuthorizePage_WithoutEndpointRouting_AddsAllowAnonymousFilterToSpecificPage()
{
// Arrange
var conventions = GetConventions(enableEndpointRouting: false);
var models = new[]
{
CreateApplicationModel("/Pages/Index.cshtml", "/Index"),
CreateApplicationModel("/Pages/Users/Account.cshtml", "/Users/Account"),
CreateApplicationModel("/Pages/Users/Contact.cshtml", "/Users/Contact"),
};
// Act
conventions.AuthorizeFolder("/Users");
conventions.AllowAnonymousToPage("/Users/Contact");
ApplyConventions(conventions, models);
// Assert
Assert.Collection(models,
model => Assert.Empty(model.Filters),
model =>
{
Assert.Equal("/Users/Account", model.ViewEnginePath);
Assert.IsType<AuthorizeFilter>(Assert.Single(model.Filters));
},
model =>
{
Assert.Equal("/Users/Contact", model.ViewEnginePath);
Assert.IsType<AuthorizeFilter>(model.Filters[0]);
Assert.IsType<AllowAnonymousFilter>(model.Filters[1]);
});
}
[Fact]
public void AllowAnonymousToAreaPage_AddsAllowAnonymousAttributeToSpecificPage()
{
// Arrange
var conventions = GetConventions();
var models = new[]
{
CreateApplicationModel("/Profile.cshtml", "/Profile"),
CreateApplicationModel("/Areas/Accounts/Pages/Profile.cshtml", "/Profile", "Accounts"),
};
// Act
conventions.AllowAnonymousToAreaPage("Accounts", "/Profile");
ApplyConventions(conventions, models);
// Assert
Assert.Collection(models,
model => Assert.Empty(model.Filters),
model =>
{
Assert.Equal("/Areas/Accounts/Pages/Profile.cshtml", model.RelativePath);
Assert.Empty(model.Filters);
Assert.IsType<AllowAnonymousAttribute>(Assert.Single(model.EndpointMetadata));
});
}
[Fact]
public void AllowAnonymousToAreaPage_WithoutEndpointRouting_AddsAllowAnonymousFilterToSpecificPage()
{
// Arrange
var conventions = GetConventions(enableEndpointRouting: false);
var models = new[]
{
CreateApplicationModel("/Profile.cshtml", "/Profile"),
CreateApplicationModel("/Areas/Accounts/Pages/Profile.cshtml", "/Profile", "Accounts"),
};
// Act
conventions.AllowAnonymousToAreaPage("Accounts", "/Profile");
ApplyConventions(conventions, models);
// Assert
Assert.Collection(models,
model => Assert.Empty(model.Filters),
model =>
{
Assert.Equal("/Areas/Accounts/Pages/Profile.cshtml", model.RelativePath);
Assert.IsType<AllowAnonymousFilter>(Assert.Single(model.Filters));
});
}
[Theory]
[InlineData("/Users")]
[InlineData("/Users/")]
public void AuthorizePage_AddsAllowAnonymousAttributeToPageUnderFolder(string folderName)
{
// Arrange
var conventions = GetConventions();
var models = new[]
{
CreateApplicationModel("/Pages/Index.cshtml", "/Index"),
CreateApplicationModel("/Pages/Users/Account.cshtml", "/Users/Account"),
CreateApplicationModel("/Pages/Users/Contact.cshtml", "/Users/Contact"),
};
// Act
conventions.AuthorizeFolder("/");
conventions.AllowAnonymousToFolder(folderName);
ApplyConventions(conventions, models);
// Assert
Assert.Collection(models,
model =>
{
Assert.Equal("/Index", model.ViewEnginePath);
Assert.Empty(model.Filters);
Assert.Collection(model.EndpointMetadata,
metadata => Assert.IsType<AuthorizeAttribute>(metadata));
},
model =>
{
Assert.Equal("/Users/Account", model.ViewEnginePath);
Assert.Empty(model.Filters);
Assert.Collection(model.EndpointMetadata,
metadata => Assert.IsType<AuthorizeAttribute>(metadata),
metadata => Assert.IsType<AllowAnonymousAttribute>(metadata));
},
model =>
{
Assert.Equal("/Users/Contact", model.ViewEnginePath);
Assert.Collection(model.EndpointMetadata,
metadata => Assert.IsType<AuthorizeAttribute>(metadata),
metadata => Assert.IsType<AllowAnonymousAttribute>(metadata));
});
}
[Theory]
[InlineData("/Users")]
[InlineData("/Users/")]
public void AuthorizePage_WithoutEndpointRouting_AddsAllowAnonymousFilterToPageUnderFolder(string folderName)
{
// Arrange
var conventions = GetConventions(enableEndpointRouting: false);
var models = new[]
{
CreateApplicationModel("/Pages/Index.cshtml", "/Index"),
CreateApplicationModel("/Pages/Users/Account.cshtml", "/Users/Account"),
CreateApplicationModel("/Pages/Users/Contact.cshtml", "/Users/Contact"),
};
// Act
conventions.AuthorizeFolder("/");
conventions.AllowAnonymousToFolder(folderName);
ApplyConventions(conventions, models);
// Assert
Assert.Collection(models,
model =>
{
Assert.Equal("/Index", model.ViewEnginePath);
Assert.IsType<AuthorizeFilter>(Assert.Single(model.Filters));
},
model =>
{
Assert.Equal("/Users/Account", model.ViewEnginePath);
Assert.IsType<AuthorizeFilter>(model.Filters[0]);
Assert.IsType<AllowAnonymousFilter>(model.Filters[1]);
},
model =>
{
Assert.Equal("/Users/Contact", model.ViewEnginePath);
Assert.IsType<AuthorizeFilter>(model.Filters[0]);
Assert.IsType<AllowAnonymousFilter>(model.Filters[1]);
});
}
[Theory]
[InlineData("/Users")]
[InlineData("/Users/")]
public void AuthorizePage_AddsAllowAnonymousAttributeToPagesUnderFolder(string folderName)
{
// Arrange
var conventions = GetConventions();
var models = new[]
{
CreateApplicationModel("/Pages/Index.cshtml", "/Index"),
CreateApplicationModel("/Pages/Users/Account.cshtml", "/Users/Account"),
CreateApplicationModel("/Pages/Users/Contact.cshtml", "/Users/Contact"),
};
// Act
conventions.AuthorizeFolder("/");
conventions.AllowAnonymousToFolder("/Users");
ApplyConventions(conventions, models);
// Assert
Assert.Collection(models,
model =>
{
Assert.Equal("/Index", model.ViewEnginePath);
Assert.Empty(model.Filters);
Assert.Collection(model.EndpointMetadata,
metadata => Assert.IsType<AuthorizeAttribute>(metadata));
},
model =>
{
Assert.Equal("/Users/Account", model.ViewEnginePath);
Assert.Empty(model.Filters);
Assert.Collection(model.EndpointMetadata,
metadata => Assert.IsType<AuthorizeAttribute>(metadata),
metadata => Assert.IsType<AllowAnonymousAttribute>(metadata));
},
model =>
{
Assert.Equal("/Users/Contact", model.ViewEnginePath);
Assert.Empty(model.Filters);
Assert.Collection(model.EndpointMetadata,
metadata => Assert.IsType<AuthorizeAttribute>(metadata),
metadata => Assert.IsType<AllowAnonymousAttribute>(metadata));
});
}
[Theory]
[InlineData("/Users")]
[InlineData("/Users/")]
public void AuthorizePage_WithoutEndpointRouting_AddsAllowAnonymousFilterToPagesUnderFolder(string folderName)
{
// Arrange
var conventions = GetConventions(enableEndpointRouting: false);
var models = new[]
{
CreateApplicationModel("/Pages/Index.cshtml", "/Index"),
CreateApplicationModel("/Pages/Users/Account.cshtml", "/Users/Account"),
CreateApplicationModel("/Pages/Users/Contact.cshtml", "/Users/Contact"),
};
// Act
conventions.AuthorizeFolder("/");
conventions.AllowAnonymousToFolder("/Users");
ApplyConventions(conventions, models);
// Assert
Assert.Collection(models,
model =>
{
Assert.Equal("/Index", model.ViewEnginePath);
Assert.IsType<AuthorizeFilter>(Assert.Single(model.Filters));
},
model =>
{
Assert.Equal("/Users/Account", model.ViewEnginePath);
Assert.IsType<AuthorizeFilter>(model.Filters[0]);
Assert.IsType<AllowAnonymousFilter>(model.Filters[1]);
},
model =>
{
Assert.Equal("/Users/Contact", model.ViewEnginePath);
Assert.IsType<AuthorizeFilter>(model.Filters[0]);
Assert.IsType<AllowAnonymousFilter>(model.Filters[1]);
});
}
[Fact]
public void AllowAnonymousToAreaFolder_AddsEndpointMetadata()
{
// Arrange
var conventions = GetConventions();
var models = new[]
{
CreateApplicationModel("/Profile.cshtml", "/Profile"),
CreateApplicationModel("/Mange/Profile.cshtml", "/Manage/Profile"),
CreateApplicationModel("/Areas/Accounts/Pages/Manage/Profile.cshtml", "/Manage/Profile", "Accounts"),
CreateApplicationModel("/Areas/Accounts/Pages/Manage/2FA.cshtml", "/Manage/2FA", "Accounts"),
CreateApplicationModel("/Areas/Accounts/Pages/View/OrderHistory.cshtml", "/View/OrderHistory", "Accounts"),
};
// Act
conventions.AllowAnonymousToAreaFolder("Accounts", "/Manage");
ApplyConventions(conventions, models);
// Assert
Assert.Collection(models,
model => Assert.Empty(model.EndpointMetadata),
model => Assert.Empty(model.EndpointMetadata),
model =>
{
Assert.Equal("/Areas/Accounts/Pages/Manage/Profile.cshtml", model.RelativePath);
Assert.Empty(model.Filters);
Assert.IsType<AllowAnonymousAttribute>(Assert.Single(model.EndpointMetadata));
},
model =>
{
Assert.Equal("/Areas/Accounts/Pages/Manage/2FA.cshtml", model.RelativePath);
Assert.Empty(model.Filters);
Assert.IsType<AllowAnonymousAttribute>(Assert.Single(model.EndpointMetadata));
},
model => Assert.Empty(model.EndpointMetadata));
}
[Fact]
public void AllowAnonymousToAreaFolder_WithoutEndpointRouting_AddsAllowAnonymousFilterToFolderInArea()
{
// Arrange
var conventions = GetConventions(enableEndpointRouting: false);
var models = new[]
{
CreateApplicationModel("/Profile.cshtml", "/Profile"),
CreateApplicationModel("/Mange/Profile.cshtml", "/Manage/Profile"),
CreateApplicationModel("/Areas/Accounts/Pages/Manage/Profile.cshtml", "/Manage/Profile", "Accounts"),
CreateApplicationModel("/Areas/Accounts/Pages/Manage/2FA.cshtml", "/Manage/2FA", "Accounts"),
CreateApplicationModel("/Areas/Accounts/Pages/View/OrderHistory.cshtml", "/View/OrderHistory", "Accounts"),
};
// Act
conventions.AllowAnonymousToAreaFolder("Accounts", "/Manage");
ApplyConventions(conventions, models);
// Assert
Assert.Collection(models,
model => Assert.Empty(model.Filters),
model => Assert.Empty(model.Filters),
model =>
{
Assert.Equal("/Areas/Accounts/Pages/Manage/Profile.cshtml", model.RelativePath);
Assert.IsType<AllowAnonymousFilter>(Assert.Single(model.Filters));
},
model =>
{
Assert.Equal("/Areas/Accounts/Pages/Manage/2FA.cshtml", model.RelativePath);
Assert.IsType<AllowAnonymousFilter>(Assert.Single(model.Filters));
},
model => Assert.Empty(model.Filters));
}
[Fact]
public void AuthorizePage_AddsAuthorizeAttributeWithPolicyToSpecificPage()
{
// Arrange
var conventions = GetConventions();
var models = new[]
{
CreateApplicationModel("/Pages/Index.cshtml", "/Index"),
CreateApplicationModel("/Pages/Users/Account.cshtml", "/Users/Account"),
CreateApplicationModel("/Pages/Users/Contact.cshtml", "/Users/Contact"),
};
// Act
conventions.AuthorizePage("/Users/Account", "Manage-Accounts");
ApplyConventions(conventions, models);
// Assert
Assert.Collection(models,
model => Assert.Empty(model.Filters),
model =>
{
Assert.Equal("/Users/Account", model.ViewEnginePath);
Assert.Empty(model.Filters);
var authorizeData = Assert.IsType<AuthorizeAttribute>(Assert.Single(model.EndpointMetadata));
Assert.Equal("Manage-Accounts", authorizeData.Policy);
},
model => Assert.Empty(model.Filters));
}
[Fact]
public void AuthorizePage_WithoutEndpointRouting_AddsAuthorizeFilterWithPolicyToSpecificPage()
{
// Arrange
var conventions = GetConventions(enableEndpointRouting: false);
var models = new[]
{
CreateApplicationModel("/Pages/Index.cshtml", "/Index"),
CreateApplicationModel("/Pages/Users/Account.cshtml", "/Users/Account"),
CreateApplicationModel("/Pages/Users/Contact.cshtml", "/Users/Contact"),
};
// Act
conventions.AuthorizePage("/Users/Account", "Manage-Accounts");
ApplyConventions(conventions, models);
// Assert
Assert.Collection(models,
model => Assert.Empty(model.Filters),
model =>
{
Assert.Equal("/Users/Account", model.ViewEnginePath);
var authorizeFilter = Assert.IsType<AuthorizeFilter>(Assert.Single(model.Filters));
var authorizeData = Assert.IsType<AuthorizeAttribute>(Assert.Single(authorizeFilter.AuthorizeData));
Assert.Equal("Manage-Accounts", authorizeData.Policy);
},
model => Assert.Empty(model.Filters));
}
[Fact]
public void AuthorizeAreaPage_AddsAuthorizeAttributeWithDefaultPolicyToAreaPage()
{
// Arrange
var conventions = GetConventions();
var models = new[]
{
CreateApplicationModel("/Profile.cshtml", "/Profile"),
CreateApplicationModel("/Areas/Accounts/Pages/Profile.cshtml", "/Profile", "Accounts"),
};
// Act
conventions.AuthorizeAreaPage("Accounts", "/Profile");
ApplyConventions(conventions, models);
// Assert
Assert.Collection(models,
model => Assert.Empty(model.Filters),
model =>
{
Assert.Equal("/Areas/Accounts/Pages/Profile.cshtml", model.RelativePath);
Assert.Empty(model.Filters);
var authorizeAttribute = Assert.IsType<AuthorizeAttribute>(Assert.Single(model.EndpointMetadata));
Assert.Empty(authorizeAttribute.Policy);
});
}
[Fact]
public void AuthorizeAreaPage_WithoutEndpointRouting_AddsAuthorizeFilterWithDefaultPolicyToAreaPage()
{
// Arrange
var conventions = GetConventions(enableEndpointRouting: false);
var models = new[]
{
CreateApplicationModel("/Profile.cshtml", "/Profile"),
CreateApplicationModel("/Areas/Accounts/Pages/Profile.cshtml", "/Profile", "Accounts"),
};
// Act
conventions.AuthorizeAreaPage("Accounts", "/Profile");
ApplyConventions(conventions, models);
// Assert
Assert.Collection(models,
model => Assert.Empty(model.Filters),
model =>
{
Assert.Equal("/Areas/Accounts/Pages/Profile.cshtml", model.RelativePath);
var authFilter = Assert.IsType<AuthorizeFilter>(Assert.Single(model.Filters));
var authorizeAttribute = Assert.Single(authFilter.AuthorizeData);
Assert.Empty(authorizeAttribute.Policy);
});
}
[Fact]
public void AuthorizeAreaPage_AddsAuthorizeAttributeWithCustomPolicyToAreaPage()
{
// Arrange
var conventions = GetConventions();
var models = new[]
{
CreateApplicationModel("/Profile.cshtml", "/Profile"),
CreateApplicationModel("/Areas/Accounts/Pages/Profile.cshtml", "/Profile", "Accounts"),
};
// Act
conventions.AuthorizeAreaPage("Accounts", "/Profile", "custom");
ApplyConventions(conventions, models);
// Assert
Assert.Collection(models,
model => Assert.Empty(model.Filters),
model =>
{
Assert.Equal("/Areas/Accounts/Pages/Profile.cshtml", model.RelativePath);
Assert.Empty(model.Filters);
var authorizeAttribute = Assert.IsType<AuthorizeAttribute>(Assert.Single(model.EndpointMetadata));
Assert.Equal("custom", authorizeAttribute.Policy);
});
}
[Fact]
public void AuthorizeAreaPage_WithoutEndpointRouting_AddsAuthorizeFilterWithCustomPolicyToAreaPage()
{
// Arrange
var conventions = GetConventions(enableEndpointRouting: false);
var models = new[]
{
CreateApplicationModel("/Profile.cshtml", "/Profile"),
CreateApplicationModel("/Areas/Accounts/Pages/Profile.cshtml", "/Profile", "Accounts"),
};
// Act
conventions.AuthorizeAreaPage("Accounts", "/Profile", "custom");
ApplyConventions(conventions, models);
// Assert
Assert.Collection(models,
model => Assert.Empty(model.Filters),
model =>
{
Assert.Equal("/Areas/Accounts/Pages/Profile.cshtml", model.RelativePath);
var authFilter = Assert.IsType<AuthorizeFilter>(Assert.Single(model.Filters));
var authorizeAttribute = Assert.Single(authFilter.AuthorizeData);
Assert.Equal("custom", authorizeAttribute.Policy);
});
}
[Fact]
public void AuthorizePage_AddsAuthorizeAttributeWithoutPolicyToSpecificPage()
{
// Arrange
var conventions = GetConventions();
var models = new[]
{
CreateApplicationModel("/Pages/Index.cshtml", "/Index"),
CreateApplicationModel("/Pages/Users/Account.cshtml", "/Users/Account"),
CreateApplicationModel("/Pages/Users/Contact.cshtml", "/Users/Contact"),
};
// Act
conventions.AuthorizePage("/Users/Account");
ApplyConventions(conventions, models);
// Assert
Assert.Collection(models,
model => Assert.Empty(model.Filters),
model =>
{
Assert.Equal("/Users/Account", model.ViewEnginePath);
Assert.Empty(model.Filters);
var authorizeData = Assert.IsType<AuthorizeAttribute>(Assert.Single(model.EndpointMetadata));
Assert.Equal(string.Empty, authorizeData.Policy);
},
model => Assert.Empty(model.Filters));
}
[Fact]
public void AuthorizePage_WithoutEndpointRouting_AddsAuthorizeFilterWithoutPolicyToSpecificPage()
{
// Arrange
var conventions = GetConventions(enableEndpointRouting: false);
var models = new[]
{
CreateApplicationModel("/Pages/Index.cshtml", "/Index"),
CreateApplicationModel("/Pages/Users/Account.cshtml", "/Users/Account"),
CreateApplicationModel("/Pages/Users/Contact.cshtml", "/Users/Contact"),
};
// Act
conventions.AuthorizePage("/Users/Account");
ApplyConventions(conventions, models);
// Assert
Assert.Collection(models,
model => Assert.Empty(model.Filters),
model =>
{
Assert.Equal("/Users/Account", model.ViewEnginePath);
var authorizeFilter = Assert.IsType<AuthorizeFilter>(Assert.Single(model.Filters));
var authorizeData = Assert.IsType<AuthorizeAttribute>(Assert.Single(authorizeFilter.AuthorizeData));
Assert.Equal(string.Empty, authorizeData.Policy);
},
model => Assert.Empty(model.Filters));
}
[Theory]
[InlineData("/Users")]
[InlineData("/Users/")]
public void AuthorizePage_WithoutEndpointRouting_AddsAuthorizeFilterWithPolicyToPagesUnderFolder(string folderName)
{
// Arrange
var conventions = GetConventions();
var models = new[]
{
CreateApplicationModel("/Pages/Index.cshtml", "/Index"),
CreateApplicationModel("/Pages/Users/Account.cshtml", "/Users/Account"),
CreateApplicationModel("/Pages/Users/Contact.cshtml", "/Users/Contact"),
};
// Act
conventions.AuthorizeFolder(folderName, "Manage-Accounts");
ApplyConventions(conventions, models);
// Assert
Assert.Collection(models,
model => Assert.Empty(model.Filters),
model =>
{
Assert.Equal("/Users/Account", model.ViewEnginePath);
Assert.Empty(model.Filters);
var authorizeData = Assert.IsType<AuthorizeAttribute>(Assert.Single(model.EndpointMetadata));
Assert.Equal("Manage-Accounts", authorizeData.Policy);
},
model =>
{
Assert.Equal("/Users/Contact", model.ViewEnginePath);
Assert.Empty(model.Filters);
var authorizeData = Assert.IsType<AuthorizeAttribute>(Assert.Single(model.EndpointMetadata));
Assert.Equal("Manage-Accounts", authorizeData.Policy);
});
}
[Theory]
[InlineData("/Users")]
[InlineData("/Users/")]
public void AuthorizePage_WithoutEndpointRouting_AddsAuthorizeFilterWithoutPolicyToPagesUnderFolder(string folderName)
{
// Arrange
var conventions = GetConventions(enableEndpointRouting: false);
var models = new[]
{
CreateApplicationModel("/Pages/Index.cshtml", "/Index.cshtml"),
CreateApplicationModel("/Pages/Users/Account.cshtml", "/Users/Account"),
CreateApplicationModel("/Pages/Users/Contact.cshtml", "/Users/Contact"),
};
// Act
conventions.AuthorizeFolder(folderName);
ApplyConventions(conventions, models);
// Assert
Assert.Collection(models,
model => Assert.Empty(model.Filters),
model =>
{
Assert.Equal("/Users/Account", model.ViewEnginePath);
var authorizeFilter = Assert.IsType<AuthorizeFilter>(Assert.Single(model.Filters));
var authorizeData = Assert.IsType<AuthorizeAttribute>(Assert.Single(authorizeFilter.AuthorizeData));
Assert.Equal(string.Empty, authorizeData.Policy);
},
model =>
{
Assert.Equal("/Users/Contact", model.ViewEnginePath);
var authorizeFilter = Assert.IsType<AuthorizeFilter>(Assert.Single(model.Filters));
var authorizeData = Assert.IsType<AuthorizeAttribute>(Assert.Single(authorizeFilter.AuthorizeData));
Assert.Equal(string.Empty, authorizeData.Policy);
});
}
[Fact]
public void AuthorizeAreaFolder_AddsAuthorizeAttributeWithDefaultPolicyToAreaPagesInFolder()
{
// Arrange
var conventions = GetConventions();
var models = new[]
{
CreateApplicationModel("/Profile.cshtml", "/Profile"),
CreateApplicationModel("/Mange/Profile.cshtml", "/Manage/Profile"),
CreateApplicationModel("/Areas/Accounts/Pages/Manage/Profile.cshtml", "/Manage/Profile", "Accounts"),
CreateApplicationModel("/Areas/Accounts/Pages/Manage/2FA.cshtml", "/Manage/2FA", "Accounts"),
CreateApplicationModel("/Areas/Accounts/Pages/View/OrderHistory.cshtml", "/View/OrderHistory", "Accounts"),
};
// Act
conventions.AuthorizeAreaFolder("Accounts", "/Manage");
ApplyConventions(conventions, models);
// Assert
Assert.Collection(models,
model => Assert.Empty(model.Filters),
model => Assert.Empty(model.Filters),
model =>
{
Assert.Equal("/Areas/Accounts/Pages/Manage/Profile.cshtml", model.RelativePath);
Assert.Empty(model.Filters);
var authorizeData = Assert.IsType<AuthorizeAttribute>(Assert.Single(model.EndpointMetadata));
Assert.Empty(authorizeData.Policy);
},
model =>
{
Assert.Equal("/Areas/Accounts/Pages/Manage/2FA.cshtml", model.RelativePath);
Assert.Empty(model.Filters);
var authorizeData = Assert.IsType<AuthorizeAttribute>(Assert.Single(model.EndpointMetadata));
Assert.Empty(authorizeData.Policy);
},
model => Assert.Empty(model.Filters));
}
[Fact]
public void AuthorizeAreaFolder_WithoutEndpointRouting_AddsAuthorizeFilterWithDefaultPolicyToAreaPagesInFolder()
{
// Arrange
var conventions = GetConventions(enableEndpointRouting: false);
var models = new[]
{
CreateApplicationModel("/Profile.cshtml", "/Profile"),
CreateApplicationModel("/Mange/Profile.cshtml", "/Manage/Profile"),
CreateApplicationModel("/Areas/Accounts/Pages/Manage/Profile.cshtml", "/Manage/Profile", "Accounts"),
CreateApplicationModel("/Areas/Accounts/Pages/Manage/2FA.cshtml", "/Manage/2FA", "Accounts"),
CreateApplicationModel("/Areas/Accounts/Pages/View/OrderHistory.cshtml", "/View/OrderHistory", "Accounts"),
};
// Act
conventions.AuthorizeAreaFolder("Accounts", "/Manage");
ApplyConventions(conventions, models);
// Assert
Assert.Collection(models,
model => Assert.Empty(model.Filters),
model => Assert.Empty(model.Filters),
model =>
{
Assert.Equal("/Areas/Accounts/Pages/Manage/Profile.cshtml", model.RelativePath);
var authorizeFilter = Assert.IsType<AuthorizeFilter>(Assert.Single(model.Filters));
var authorizeData = Assert.IsType<AuthorizeAttribute>(Assert.Single(authorizeFilter.AuthorizeData));
Assert.Empty(authorizeData.Policy);
},
model =>
{
Assert.Equal("/Areas/Accounts/Pages/Manage/2FA.cshtml", model.RelativePath);
var authorizeFilter = Assert.IsType<AuthorizeFilter>(Assert.Single(model.Filters));
var authorizeData = Assert.IsType<AuthorizeAttribute>(Assert.Single(authorizeFilter.AuthorizeData));
Assert.Empty(authorizeData.Policy);
},
model => Assert.Empty(model.Filters));
}
[Fact]
public void AuthorizeAreaFolder_AddsAuthorizeAttributeWithCustomPolicyToAreaPagesInFolder()
{
// Arrange
var conventions = GetConventions();
var models = new[]
{
CreateApplicationModel("/Profile.cshtml", "/Profile"),
CreateApplicationModel("/Mange/Profile.cshtml", "/Manage/Profile"),
CreateApplicationModel("/Areas/Accounts/Pages/Manage/Profile.cshtml", "/Manage/Profile", "Accounts"),
CreateApplicationModel("/Areas/Accounts/Pages/Manage/2FA.cshtml", "/Manage/2FA", "Accounts"),
CreateApplicationModel("/Areas/Accounts/Pages/View/OrderHistory.cshtml", "/View/OrderHistory", "Accounts"),
};
// Act
conventions.AuthorizeAreaFolder("Accounts", "/Manage", "custom");
ApplyConventions(conventions, models);
// Assert
Assert.Collection(models,
model => Assert.Empty(model.EndpointMetadata),
model => Assert.Empty(model.EndpointMetadata),
model =>
{
Assert.Equal("/Areas/Accounts/Pages/Manage/Profile.cshtml", model.RelativePath);
Assert.Empty(model.Filters);
var authorizeData = Assert.IsType<AuthorizeAttribute>(Assert.Single(model.EndpointMetadata));
Assert.Equal("custom", authorizeData.Policy);
},
model =>
{
Assert.Equal("/Areas/Accounts/Pages/Manage/2FA.cshtml", model.RelativePath);
Assert.Empty(model.Filters);
var authorizeData = Assert.IsType<AuthorizeAttribute>(Assert.Single(model.EndpointMetadata));
Assert.Equal("custom", authorizeData.Policy);
},
model => Assert.Empty(model.Filters));
}
[Fact]
public void AuthorizeAreaFolder_WithoutEndpointRouting_AddsAuthorizeFilterWithCustomPolicyToAreaPagesInFolder()
{
// Arrange
var conventions = GetConventions(enableEndpointRouting: false);
var models = new[]
{
CreateApplicationModel("/Profile.cshtml", "/Profile"),
CreateApplicationModel("/Mange/Profile.cshtml", "/Manage/Profile"),
CreateApplicationModel("/Areas/Accounts/Pages/Manage/Profile.cshtml", "/Manage/Profile", "Accounts"),
CreateApplicationModel("/Areas/Accounts/Pages/Manage/2FA.cshtml", "/Manage/2FA", "Accounts"),
CreateApplicationModel("/Areas/Accounts/Pages/View/OrderHistory.cshtml", "/View/OrderHistory", "Accounts"),
};
// Act
conventions.AuthorizeAreaFolder("Accounts", "/Manage", "custom");
ApplyConventions(conventions, models);
// Assert
Assert.Collection(models,
model => Assert.Empty(model.Filters),
model => Assert.Empty(model.Filters),
model =>
{
Assert.Equal("/Areas/Accounts/Pages/Manage/Profile.cshtml", model.RelativePath);
var authorizeFilter = Assert.IsType<AuthorizeFilter>(Assert.Single(model.Filters));
var authorizeData = Assert.IsType<AuthorizeAttribute>(Assert.Single(authorizeFilter.AuthorizeData));
Assert.Equal("custom", authorizeData.Policy);
},
model =>
{
Assert.Equal("/Areas/Accounts/Pages/Manage/2FA.cshtml", model.RelativePath);
var authorizeFilter = Assert.IsType<AuthorizeFilter>(Assert.Single(model.Filters));
var authorizeData = Assert.IsType<AuthorizeAttribute>(Assert.Single(authorizeFilter.AuthorizeData));
Assert.Equal("custom", authorizeData.Policy);
},
model => Assert.Empty(model.Filters));
}
[Fact]
public void AddPageRoute_AddsRouteToSelector()
{
// Arrange
var conventions = GetConventions();
var models = new[]
{
new PageRouteModel("/Pages/Index.cshtml", "/Index")
{
Selectors =
{
CreateSelectorModel("Index", suppressLinkGeneration: true),
CreateSelectorModel(""),
}
},
new PageRouteModel("/Pages/About.cshtml", "/About")
{
Selectors =
{
CreateSelectorModel("About"),
}
}
};
// Act
conventions.AddPageRoute("/Index", "Different-Route");
ApplyConventions(conventions, models);
// Assert
Assert.Collection(models,
model =>
{
Assert.Equal("/Index", model.ViewEnginePath);
Assert.Collection(model.Selectors,
selector =>
{
Assert.Equal("Index", selector.AttributeRouteModel.Template);
Assert.True(selector.AttributeRouteModel.SuppressLinkGeneration);
},
selector =>
{
Assert.Equal("", selector.AttributeRouteModel.Template);
Assert.True(selector.AttributeRouteModel.SuppressLinkGeneration);
},
selector =>
{
Assert.Equal("Different-Route", selector.AttributeRouteModel.Template);
Assert.False(selector.AttributeRouteModel.SuppressLinkGeneration);
});
},
model =>
{
Assert.Equal("/About", model.ViewEnginePath);
Assert.Collection(model.Selectors,
selector =>
{
Assert.Equal("About", selector.AttributeRouteModel.Template);
Assert.False(selector.AttributeRouteModel.SuppressLinkGeneration);
});
});
}
[Fact]
public void AddAreaPageRoute_AddsRouteToSelector()
{
// Arrange
var conventions = GetConventions();
var models = new[]
{
new PageRouteModel("/Pages/Profile.cshtml", "/Profile")
{
Selectors =
{
CreateSelectorModel("Profile"),
}
},
new PageRouteModel("/Areas/Accounts/Pages/Profile.cshtml", "/Profile", "Accounts")
{
Selectors =
{
CreateSelectorModel("Accounts/Profile"),
}
}
};
// Act
conventions.AddAreaPageRoute("Accounts", "/Profile", "Different-Route");
ApplyConventions(conventions, models);
// Assert
Assert.Collection(models,
model =>
{
Assert.Equal("/Pages/Profile.cshtml", model.RelativePath);
Assert.Collection(model.Selectors,
selector =>
{
Assert.Equal("Profile", selector.AttributeRouteModel.Template);
Assert.False(selector.AttributeRouteModel.SuppressLinkGeneration);
});
},
model =>
{
Assert.Equal("/Areas/Accounts/Pages/Profile.cshtml", model.RelativePath);
Assert.Collection(model.Selectors,
selector =>
{
Assert.Equal("Accounts/Profile", selector.AttributeRouteModel.Template);
Assert.True(selector.AttributeRouteModel.SuppressLinkGeneration);
},
selector =>
{
Assert.Equal("Different-Route", selector.AttributeRouteModel.Template);
Assert.False(selector.AttributeRouteModel.SuppressLinkGeneration);
});
});
}
private PageConventionCollection GetConventions(bool enableEndpointRouting = true)
{
var options = new MvcOptions { EnableEndpointRouting = enableEndpointRouting };
var serviceProvider = new ServiceCollection()
.AddSingleton<IOptions<MvcOptions>>(Options.Options.Create(options))
.BuildServiceProvider();
return new PageConventionCollection(serviceProvider);
}
private static SelectorModel CreateSelectorModel(string template, bool suppressLinkGeneration = false)
{
return new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Template = template,
SuppressLinkGeneration = suppressLinkGeneration
},
};
}
private static void ApplyConventions(PageConventionCollection conventions, PageRouteModel[] models)
{
foreach (var convention in conventions.OfType<IPageRouteModelConvention>())
{
foreach (var model in models)
{
convention.Apply(model);
}
}
}
private static void ApplyConventions(PageConventionCollection conventions, PageApplicationModel[] models)
{
foreach (var convention in conventions.OfType<IPageApplicationModelConvention>())
{
foreach (var model in models)
{
convention.Apply(model);
}
}
}
private PageApplicationModel CreateApplicationModel(string relativePath, string viewEnginePath, string areaName = null)
{
var descriptor = new PageActionDescriptor
{
ViewEnginePath = viewEnginePath,
RelativePath = relativePath,
AreaName = areaName,
};
return new PageApplicationModel(descriptor, typeof(object).GetTypeInfo(), new object[0]);
}
}
|