forked from aspnet/AspNetWebStack
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSiteAdmin.cs
More file actions
233 lines (189 loc) · 8.56 KB
/
Copy pathSiteAdmin.cs
File metadata and controls
233 lines (189 loc) · 8.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.Globalization;
namespace System.Web.WebPages.Administration
{
public class SiteAdmin
{
internal const string DefaultAdminVirtualPath = "~/_Admin/";
internal const string AdminSettingsFolder = "~/App_Data/Admin/";
// Configuration settings
private const string AdminVirtualPathAppSettingsKey = "asp:AdminFolderVirtualPath";
private const string AdminEnabledAppSettingsKey = "asp:AdminManagerEnabled";
private const string ReturnUrlQueryString = "ReturnUrl";
// Virtual paths excluded from security. These urls are the same as the ones in the PageVirtulPath attribute.
internal const string LoginVirtualPath = "~/Login.cshtml";
internal const string LogoutVirtualPath = "~/Logout.cshtml";
internal const string RegisterVirtualPath = "~/Register.cshtml";
internal const string EnableInstructionsVirtualPath = "~/EnableInstructions.cshtml";
private static ConcurrentDictionary<string, SiteAdmin> _adminModules = new ConcurrentDictionary<string, SiteAdmin>();
// These only needs to be computed once per app domain
private static readonly Lazy<bool?> _adminEnabled = new Lazy<bool?>(GetAdminEnabledSetting);
private static readonly Lazy<string> _adminVirtualPath = new Lazy<string>(GetDefaultVirtualPath);
private SiteAdmin(string startPageVirtualPath, string displayName, string description)
{
Debug.Assert(startPageVirtualPath != null, "startPageVirtualPath can't be null");
Debug.Assert(displayName != null, "displayName can't be null");
StartPageVirtualPath = startPageVirtualPath;
DisplayName = displayName;
Description = description;
}
public static string AdminVirtualPath
{
get { return _adminVirtualPath.Value; }
}
public string StartPageVirtualPath { get; private set; }
public string DisplayName { get; private set; }
public string Description { get; private set; }
internal static bool Available
{
get
{
HttpContext context = HttpContext.Current;
if (context != null && context.Request.IsLocal)
{
// Check the configuration setting if there is any
if (_adminEnabled.Value != null)
{
return _adminEnabled.Value.Value;
}
// There was no setting so localhost is enough to verify availability
return true;
}
// If we're not on localhost then nothing is available
return false;
}
}
public static IEnumerable<SiteAdmin> Modules
{
get { return _adminModules.Values; }
}
internal static void RegisterAdminModule()
{
// Add a admin module as an application module (precompiled)
ApplicationPart.Register(new ApplicationPart(typeof(SiteAdmin).Assembly, AdminVirtualPath));
}
private static bool? GetAdminEnabledSetting()
{
bool enabled;
if (Boolean.TryParse(ConfigurationManager.AppSettings[AdminEnabledAppSettingsKey], out enabled))
{
return enabled;
}
return null;
}
public static string GetVirtualPath(string virtualPath)
{
if (virtualPath == null)
{
throw new ArgumentNullException("virtualPath");
}
// Don't add the virtual path more than once
if (virtualPath.StartsWith(AdminVirtualPath, StringComparison.OrdinalIgnoreCase))
{
return virtualPath;
}
if (virtualPath.StartsWith("~/", StringComparison.OrdinalIgnoreCase))
{
virtualPath = virtualPath.Substring(2);
}
if (virtualPath.StartsWith("/", StringComparison.OrdinalIgnoreCase))
{
virtualPath = virtualPath.Substring(1);
}
return VirtualPathUtility.Combine(AdminVirtualPath, virtualPath);
}
public static void Register(string startPageVirtualPath, string displayName, string description)
{
if (startPageVirtualPath == null)
{
throw new ArgumentNullException("startPageVirtualPath");
}
if (displayName == null)
{
throw new ArgumentNullException("displayName");
}
// Get the virtual path relative to the admin virtual path
string virtualPath = GetVirtualPath(startPageVirtualPath);
// Register that under the admin root
Register(new SiteAdmin(virtualPath, displayName, description));
}
private static string GetDefaultVirtualPath()
{
string virtualPath = ConfigurationManager.AppSettings[AdminVirtualPathAppSettingsKey];
if (String.IsNullOrEmpty(virtualPath))
{
virtualPath = DefaultAdminVirtualPath;
}
if (!virtualPath.EndsWith("/", StringComparison.OrdinalIgnoreCase))
{
virtualPath += "/";
}
return virtualPath;
}
internal static void RedirectToLogin(HttpResponseBase response)
{
response.Redirect(GetVirtualPath(LoginVirtualPath));
}
internal static void RedirectToRegister(HttpResponseBase response)
{
response.Redirect(GetVirtualPath(RegisterVirtualPath));
}
internal static void RedirectToHome(HttpResponseBase response)
{
response.Redirect(AdminVirtualPath);
}
internal static void Register(SiteAdmin module)
{
if (_adminModules.ContainsKey(module.StartPageVirtualPath))
{
throw new InvalidOperationException(
String.Format(CultureInfo.CurrentCulture,
AdminResources.ModuleAlreadyRegistered, module.StartPageVirtualPath));
}
// Add to the list of registered modules
_adminModules.TryAdd(module.StartPageVirtualPath, module);
}
internal static string GetReturnUrl(HttpRequestBase request)
{
// REVIEW: FormsAuthentication.GetReturlUrl also checks the form for the return url
// do we need that?
string returnUrl = request.QueryString[ReturnUrlQueryString];
// If the return url query string doesn't exist or is empty
// return the admin root virtual path
if (String.IsNullOrEmpty(returnUrl))
{
return null;
}
// REVIEW: FormsAuthentication.GetReturnUrl checks if the url is dangerous
// i.e it uses an internal helper in System.Web CrossSiteScriptingValidation.IsDangerousUrl.
// Should we copy that behavior?
if (!VirtualPathUtility.IsAppRelative(returnUrl))
{
// We only put app relative return urls in the query string (i.e starts with ~/)
throw new InvalidOperationException(AdminResources.InvalidReturnUrl);
}
return returnUrl;
}
internal static string GetRedirectUrl(string redirectUrl)
{
var request = new HttpRequestWrapper(HttpContext.Current.Request);
return GetRedirectUrl(request, redirectUrl, VirtualPathUtility.ToAppRelative);
}
internal static string GetRedirectUrl(HttpRequestBase request, string redirectUrl, Func<string, string> makeAppRelative)
{
// If there's already a return url then use it, otherwise the app relative url of the
// current request to redirect to after signing in
string returnUrl = GetReturnUrl(request) ?? makeAppRelative(request.RawUrl);
// Get the app relative path to the redirect url
redirectUrl = GetVirtualPath(redirectUrl);
// Get the current page with return url
redirectUrl += "?" + ReturnUrlQueryString + "=" + HttpUtility.UrlEncode(returnUrl);
return redirectUrl;
}
}
}