-
Notifications
You must be signed in to change notification settings - Fork 0
/
TODO.html
414 lines (395 loc) · 33.4 KB
/
TODO.html
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
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>ASP.NET Core GraphQL Boxed</title>
<link href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet" />
<style>
.alert-close-checkbox {
display: none;
}
</style>
</head>
<body>
<div id="main" class="container body-content" role="main">
<a href="Dotnet-Boxed/Templates">
<img alt=".NET Boxed"
class="img-responsive"
src="https://raw.githubusercontent.com/Dotnet-Boxed/Templates/master/Images/Banner.png"
style="margin-bottom: 20px">
</a>
<section>
<h2>Task Check List</h2>
<p>This is a check-list of tasks you must perform to get your site up and running faster. Open this file in the browser of your choice and it will remember what you have checked, just don't clear your cache.</p>
<article>
<h3><span aria-hidden="true" class="fa fa-list"></span> Pre-Requisites</h3>
<ul class="list-group">
<li class="list-group-item">
<input name="PreRequisites-UpdateVisualStudio" type="checkbox"> <strong>Update Visual Studio / Visual Studio Code</strong> -
Update your version of Visual Studio or Visual Studio Code with all patches and updates.
</li>
<li class="list-group-item">
<input name="PreRequisites-UpdateNuGet" type="checkbox"> <strong>Update NuGet</strong> -
Update the NuGet Visual Studio extension from the Tools -> Extensions and Updates menu.
</li>
<li class="list-group-item">
<input name="PreRequisites-UpdateDNVM" type="checkbox"> <strong>Update Visual Studio ASP.NET Core Tools</strong> -
Update the Visual Studio ASP.NET Core tools. Find out more at <a href="https://dot.net">dot.net</a>.
</li>
<li class="list-group-item">
<input name="PreRequisites-IISNETCoreWindowsServerHosting" type="checkbox"> <strong>IIS .NET Core Windows Server Hosting Bundle</strong> -
If you are using IIS and configuring it yourself, install the <a href="https://docs.asp.net/en/latest/publishing/iis.html">.NET Core Windows Server Hosting</a> bundle from <a href="http://go.microsoft.com/fwlink/?LinkId=798480">here</a>.
</li>
</ul>
</article>
<article>
<h3><span aria-hidden="true" class="fa fa-lock"></span> Security</h3>
<h4>TLS over HTTPS</h4>
<ul class="list-group">
<li class="list-group-item">
<input name="HTTPS-ConfigureSitewideHTTPS" type="checkbox"> <strong>Configure Site-Wide HTTPS</strong> -
Please note that <a href="http://en.wikipedia.org/wiki/SSL">SSL</a> has been superseded by <a href="http://en.wikipedia.org/wiki/Transport_Layer_Security">TLS</a>. SSL is vulnerable to the <a href="http://en.wikipedia.org/wiki/POODLE">POODLE</a> security vulnerability and should not be used. These steps outline how to secure your site so that all requests and responses are made over <a href="http://en.wikipedia.org/wiki/HTTPS">HTTPS</a> using TLS, you should consider using it across your whole site for best security, rather than having a mix of HTTP and HTTPS pages. TLS certificates can be obtained for free at:
<ul>
<li><a href="https://letsencrypt.org/">LetsEncrypt.org</a></li>
<li><a href="https://www.startssl.com/">StartSSL.com</a> (You can follow <a href="http://www.troyhunt.com/2013/09/the-complete-guide-to-loading-free-ssl.html">this</a> guide to setting up TLS using StartSSL.)</li>
<li><a href="https://www.digicert.com/friends/mvp.php">Digicert</a> (Digicert is only for Microsoft employees or MVP's)</li>
</ul>
</li>
<li class="list-group-item">
<input name="HTTPS-ConfigureHSTSPreload" type="checkbox"> <strong>Configure Strict Transport Security (HSTS) Preloading</strong> -
If using Strict-Transport-Security, submit your domain to the <a href="https://hstspreload.appspot.com/">HSTS Preload</a> site so that your domain can be preloaded using HTTPS rather than HTTP See <a href="https://developer.mozilla.org/en-US/docs/Web/Security/HTTP_strict_transport_security#Preloading_Strict_Transport_Security">this</a> for more information about preloading.
</li>
<li class="list-group-item">
<input name="HTTPS-ConfigureHPKP" type="checkbox"> <strong>Configure Public Key Pinning (HPKP)</strong> -
Open the <em>ApplicationBuilderExtensions.cs</em> file and uncomment the <code>application.UseHpkp(...);</code> line to turn on <a href="https://developer.mozilla.org/en-US/docs/Web/Security/Public_Key_Pinning">Public Key Pinning (HPKP)</a>. Please note that there is some risk to setting up Public Key Pinning (HPKP), if you get it wrong people who have visited your site will get an error in their browser upon visiting your site so be careful.
</li>
<li class="list-group-item">
<input name="HTTPS-TestHttps" type="checkbox"> <strong>Test Your HTTPS Implementation</strong> -
Use the <a href="https://www.ssllabs.com/ssltest">SSLLabs.com</a> site to check that you have implemented TLS over HTTPS correctly.
</li>
<li class="list-group-item">
<input name="HTTPS-CertificateTransparency" type="checkbox"> <strong>Certificate Transparency</strong> -
<a href="https://scotthelme.co.uk/revocation-is-broken/">Certificate Transparency (CT)</a> requires that all Certificate Authorities (CA's) publically log all certificates they create. If a certificate is mistakenly issued for your site you can be notified by the following services:
<ul>
<li><a href="https://developers.facebook.com/tools/ct/">Facebook Certificate Transparency Monitoring</a></li>
<li><a href="https://sslmate.com/certspotter/">sslmate CertSpotter</a></li>
<li><a href="https://crt.sh/?q=example.com">crt.sh</a></li>
</ul>
</li>
</ul>
<h4>Understand Web Security</h4>
<ul class="list-group">
<li class="list-group-item">
<input name="OtherSecurity-UnderstandOWASPTopTen" type="checkbox"> <strong>Understand OWASP Top 10</strong> -
Understand the top ten security vulnerabilities and how you can protect yourself from them at <a href="https://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project">OWASP Top 10</a>. Also take a look at the <a href="https://www.owasp.org/index.php/Cheat_Sheets">OWASP Top Ten Cheat Sheet</a>.
</li>
<li class="list-group-item">
<input name="OtherSecurity-UnderstandCrossSiteScripting" type="checkbox"> <strong>Understand Cross Site Scripting (XSS)</strong> -
Understand Cross Site Scripting (XSS) security vulnerabilities and how you can protect yourself from them using the <a href="https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet">OWASP XSS Cheat Sheet</a> and <a href="https://www.owasp.org/index.php/DOM_based_XSS_Prevention_Cheat_Sheet">OWASP DOM Based XSS Cheat Sheet</a>.
</li>
<li class="list-group-item">
<input name="OtherSecurity-UnderstandCrossSiteRequestForgery" type="checkbox"> <strong>Understand Cross Site Request Forgery (CSRF)</strong> -
Understand Cross Site Request Forgery security vulnerabilities and how you can protect yourself from them using the <a href="https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29_Prevention_Cheat_Sheet">OWASP CSRF Cheat Sheet</a>.
</li>
</ul>
<h4>Other Security</h4>
<ul class="list-group">
<li class="list-group-item">
<input name="OtherSecurity-SecretStore" type="checkbox"> <strong>Use Secret Store</strong> -
If you want to use connection strings or other secrets without checking them in to your source control repository, use the secret store. See <a href="http://go.microsoft.com/fwlink/?LinkID=532709">this</a> and <a href="http://docs.asp.net/en/latest/security/app-secrets.html">this</a> for more information.
</li>
<li class="list-group-item">
<input name="OtherSecurity-RequestLimits" type="checkbox"> <strong>Adjust Request Limits</strong> -
There are settings in the <em>Web.config</em> file under the <code>requestLimits</code> element that limit maximum size of HTTP requests clients can make to your site. You can limit the maximum content size, maximum URL length and maximum query string length. You should lower these as much as possible, while still having a working site.
</li>
<li class="list-group-item">
<input name="OtherSecurity-KeepNuGetUpToDate" type="checkbox"> <strong>Keep NuGet Up To Date</strong> -
Keep your NuGet packages up to date to patch security vulnerabilities. See the section about updating below.
</li>
</ul>
</article>
<article>
<h3><span aria-hidden="true" class="fa fa-tachometer"></span> Performance</h3>
<h4>Content Delivery Networks (CDN)</h4>
<ul class="list-group">
<li class="list-group-item">
<input name="ContentDeliveryNetworks-UploadStaticFilesToCDN" type="checkbox"> <strong>Upload Static Files to CDN</strong> -
Upload the static files to a <a href="http://en.wikipedia.org/wiki/Content_delivery_network">CDN</a> for vastly better performance.
Examples of static content include your images, minified CSS bundle content, minified JavaScript bundle content, etc.
<ul>
<li><a href="http://www.cloudflare.com/CDN">Cloudflare CDN</a></li>
<li><a href="http://azure.microsoft.com/en-us/documentation/articles/cdn-serve-content-from-cdn-in-your-web-application/">Azure CDN</a></li>
</ul>
</li>
</ul>
<h4>Caching</h4>
<ul class="list-group">
<li class="list-group-item">
<input name="Caching-ConfigureCaching" type="checkbox"> <strong>Configure Caching</strong> -
Some resources are generated programmatically and then cached for a certain time period.
If these resources won't change much on your site, change the length of time they are cached. Open the <em>appsettings.json</em> file and take a look at the cache profiles section.
</li>
</ul>
<h4>Benchmarking</h4>
<ul class="list-group">
<li class="list-group-item">
<input name="OtherPerformance-RunGooglePageSpeed" type="checkbox"> <strong>Run Google Page Speed</strong> -
Use <a href="https://developers.google.com/speed/pagespeed/">Google Page Speed</a> to benchmark your sites performance and to get suggestions on how to further improve performance. Note that this template is already very quick to begin with.
</li>
<li class="list-group-item">
<input name="OtherPerformance-RunYahooYSlow" type="checkbox"> <strong>Run Yahoo's YSlow</strong> -
Use <a href="http://yslow.org/">Yahoo's YSlow</a> to benchmark your sites performance and to get suggestions on how to further improve performance.
</li>
</ul>
<h4>Other Performance</h4>
<ul class="list-group">
<li class="list-group-item">
<input name="OtherPerformance-Prefetcher" type="checkbox"> <strong>Enable Windows Server Pre-fetcher</strong> -
This is only relevant if your site is hosted on Windows Server. You can enable the <a href="http://en.wikipedia.org/wiki/Prefetcher">pre-fetcher</a> to get a performance and reduce the disk-read cost of application start-up. Click <a href="http://www.asp.net/aspnet/overview/aspnet-and-visual-studio-2012/whats-new#_Toc_perf_6">here</a> for more information on how to do this.
</li>
</ul>
</article>
<article>
<h3><span aria-hidden="true" class="fa fa-puzzle-piece"></span> Compatibility</h3>
<ul class="list-group">
<li class="list-group-item">
<input name="Compatibility-OldIIS" type="checkbox"> <strong>IIS 7.5/8</strong> -
Some <em>web.config</em> settings do not exist in older versions of IIS (7.5 and 8). If you are using an older version, edit the <em>web.config</em> file and remove the <code>dynamicIpSecurity</code> settings.
</li>
</ul>
</article>
<article>
<h3><span aria-hidden="true" class="fa fa-user"></span> Authentication & Authorization</h3>
<ul class="list-group">
<li class="list-group-item">
<input name="Authentication-Provider" type="checkbox"> <strong>Choose Authentication Provider</strong> -
If you want no authentication, then you don't need to do anything. <strong>Do not</strong> build your own authentication provider unless you are a security expert, it is much harder than it looks and even professionals get it wrong. Choose from one of the options below:
<ol>
<li>IdentityServer4 - This is another site that handles all authentication with OAuth and Open ID Connect.</li>
<li>ASP.NET Identity - This is basically forms authentication with OAuth and Open ID Connect. This is what you get when you select 'Individual Account' from Microsoft's '<a href="http://i2.asp.net/media/47397/ConfigureAuthDialog.png?cdn_id=2015-05-22-001">Change Authentication</a>' dialogue, when you create a new Web Project. Follow <a href="http://www.asp.net/identity/overview/getting-started">this</a> tutorial. Don't forget to add the <code>NoLowercaseQueryStringAttribute</code> to the <code>AccountController</code> to enable the <code>RedirectToCanonicalUrlAttribute</code> to work (See comments on these classes for more information about what they do).</li>
<li>Windows Authentication - Follow <a href="http://www.asp.net/aspnet/overview/owin-and-katana/enabling-windows-authentication-in-katana">this</a> tutorial.</li>
</ol>
</li>
</ul>
</article>
<article>
<h3><span aria-hidden="true" class="fa fa-exclamation-triangle"></span> Resilience and Error Handling</h3>
<ul class="list-group">
<li class="list-group-item">
<input name="ResilienceAndErrorHandling-DosProtection" type="checkbox"> <strong>Denial of Service (DoS) Protection</strong> -
There are a number of ways to protect your site from <a href="http://en.wikipedia.org/wiki/Denial-of-service_attack">Denial of Service (DoS)</a> attacks:
<ul>
<li>
<a href="https://www.cloudflare.com/">Cloudflare</a> - You can use the Cloudflare service as a proxy to your site. Cloudflare has sophisticated techniques to block attackers from accessing your site and is used by a large proportion of websites on the internet.
</li>
<li>
<a href="http://www.iis.net/configreference/system.webserver/security/dynamicipsecurity">Dynamic IP Security</a> is a feature of IIS that can be configured using the <code>dynamicIpSecurity</code> section of the <em>web.config</em> file. Dynamic IP Security is set to logging only mode in this site, so IIS will log malicious requests from clients without actually rejecting them. If you decide to use this feature, run your site in this mode for some time and slowly raise the limits until you get no more 403.501 or 403.502 errors. Normal legitimate requests that can look like a DoS attack are:
<ol>
<li>Google and Bing often make large numbers of requests that can look like a DoS attack and you do not want to block them by accident.</li>
<li>Some organizations put themselves behind a proxy and their requests can look like they are from a single IP address.</li>
<li>Pages on your site that cause a large number of requests to be made your site may trigger the Dynamic IP Security limits to be triggered and the page loading will be treated like a Denial of Service (DoS) attack.</li>
</ol>
You can test this feature by recording a request to your site using <a href="http://www.telerik.com/fiddler">Fiddler</a> and then replaying it many times.
</li>
</ul>
</li>
<li class="list-group-item">
<input name="ResilienceAndErrorHandling-Logging" type="checkbox"> <strong>Add Logging</strong> -
This template comes with basic logging enabled in development mode. Consider using <a href="http://serilog.net/">Serilog</a> or another logging framework in production. Logging can be configured in <em>Startup.cs</em>.
</li>
</ul>
</article>
<article>
<h3><span aria-hidden="true" class="fa fa-users"></span> Thank Developers</h3>
<ul class="list-group">
<li class="list-group-item">
<input name="ThankDevelopers-ConfigureHumansTxt" type="checkbox"> <strong>Configure Humans.txt</strong> -
Edit the <em>humans.txt</em> file at the root of the site. This is totally optional, you can delete this file if you want.
Be careful what you put into this file, you could give away clues about potential attack vectors on your site.
Even giving contact details can be an attack vector (Most hackers manipulate people to get access).
</li>
<li class="list-group-item">
<input name="ThankDevelopers-Review" type="checkbox"> <strong>Thank Developers</strong> -
A lot of work was put into this project template. Show your appreciation by giving the project a star on <a href="https://github.com/Dotnet-Boxed/Templates">GitHub</a>.
</li>
</ul>
</article>
<article>
<h3><span aria-hidden="true" class="fa fa-refresh"></span> Keeping Your Site Up To Date</h3>
<ul class="list-group">
<li class="list-group-item">
<input name="KeepingYourSiteUpToDate-KeepNuGetPackagesUpToDate" type="checkbox"> <strong>Keep NuGet Packages Up To Date</strong> -
Most updates can be easily carried out by simply updating <a href="https://www.nuget.org/">NuGet</a> packages. See <a href="https://docs.nuget.org/consume/package-manager-dialog">this</a> link for more information. However, there are a few things to watch out for before updating a package:
<ol>
<li>It's worth reading the NuGet package release notes to see what has changed and base the urgency of upgrading on this information. Blindly updating, can sometimes cause things to break. Sometimes packages are incompatible with other packages or there are special upgrade steps that need to be carried out.</li>
<li>When updating JavaScript or CSS framework Bower Packages, be careful that the particular version you are updating to is also available on the <a href="http://en.wikipedia.org/wiki/Content_delivery_network">CDN</a>. Some CDN's update more often than others. This project template uses the popular Google and Microsoft CDN's as it is likely that their scripts are already preloaded in a browsers cache. However, their CDN service also does not update too often.</li>
<li>You need to ensure that you update your JavaScript and CSS framework Bower packages when there are new versions to obtain security patches but also because <a href="http://en.wikipedia.org/wiki/Content_delivery_network">CDN</a>'s sometimes retire very old scripts. This template provides fallback scripts, so if a CDN does retire a script or goes down, it will use the scripts in this template instead. This will result in a slight performance degradation.</li>
</ol>
</li>
<li class="list-group-item">
<input name="KeepingYourSiteUpToDate-KeepTemplateUpToDate" type="checkbox"> <strong>Keep Template Up To Date</strong> -
Keep an eye on the <a href="https://github.com/Dotnet-Boxed/Templates/releases">release notes</a> and update your site accordingly.
</li>
</ul>
</article>
</section>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.1/bootstrap.min.js"></script>
<script>
// https://github.com/jeremydurham/persist-js
(function () {
if (window.google && google.gears) { return; }
var F = null; if (typeof GearsFactory != 'undefined') { F = new GearsFactory(); } else { try { F = new ActiveXObject('Gears.Factory'); if (F.getBuildInfo().indexOf('ie_mobile') != -1) { F.privateSetGlobalObject(this); } } catch (e) { if ((typeof navigator.mimeTypes != 'undefined') && navigator.mimeTypes["application/x-googlegears"]) { F = document.createElement("object"); F.style.display = "none"; F.width = 0; F.height = 0; F.type = "application/x-googlegears"; document.documentElement.appendChild(F); } } }
if (!F) { return; }
if (!window.google) { google = {}; }
if (!google.gears) { google.gears = { factory: F }; }
})(); Persist = (function () {
var VERSION = '0.3.1', P, B, esc, init, empty, ec; ec = (function () {
var EPOCH = 'Thu, 01-Jan-1970 00:00:01 GMT', RATIO = 1000 * 60 * 60 * 24, KEYS = ['expires', 'path', 'domain'], esc = escape, un = unescape, doc = document, me; var get_now = function () { var r = new Date(); r.setTime(r.getTime()); return r; }; var cookify = function (c_key, c_val) {
var i, key, val, r = [], opt = (arguments.length > 2) ? arguments[2] : {}; r.push(esc(c_key) + '=' + esc(c_val)); for (var idx = 0; idx < KEYS.length; idx++) { key = KEYS[idx]; val = opt[key]; if (val) { r.push(key + '=' + val); } }
if (opt.secure) { r.push('secure'); }
return r.join('; ');
}; var alive = function () { var k = '__EC_TEST__', v = new Date(); v = v.toGMTString(); this.set(k, v); this.enabled = (this.remove(k) == v); return this.enabled; }; me = {
set: function (key, val) {
var opt = (arguments.length > 2) ? arguments[2] : {}, now = get_now(), expire_at, cfg = {}; if (opt.expires) {
if (opt.expires == -1) { cfg.expires = -1 }
else { var expires = opt.expires * RATIO; cfg.expires = new Date(now.getTime() + expires); cfg.expires = cfg.expires.toGMTString(); }
}
var keys = ['path', 'domain', 'secure']; for (var i = 0; i < keys.length; i++) { if (opt[keys[i]]) { cfg[keys[i]] = opt[keys[i]]; } }
var r = cookify(key, val, cfg); doc.cookie = r; return val;
}, has: function (key) { key = esc(key); var c = doc.cookie, ofs = c.indexOf(key + '='), len = ofs + key.length + 1, sub = c.substring(0, key.length); return ((!ofs && key != sub) || ofs < 0) ? false : true; }, get: function (key) {
key = esc(key); var c = doc.cookie, ofs = c.indexOf(key + '='), len = ofs + key.length + 1, sub = c.substring(0, key.length), end; if ((!ofs && key != sub) || ofs < 0) { return null; }
end = c.indexOf(';', len); if (end < 0) { end = c.length; }
return un(c.substring(len, end));
}, remove: function (k) { var r = me.get(k), opt = { expires: EPOCH }; doc.cookie = cookify(k, '', opt); return r; }, keys: function () {
var c = doc.cookie, ps = c.split('; '), i, p, r = []; for (var idx = 0; idx < ps.length; idx++) { p = ps[idx].split('='); r.push(un(p[0])); }
return r;
}, all: function () {
var c = doc.cookie, ps = c.split('; '), i, p, r = []; for (var idx = 0; idx < ps.length; idx++) { p = ps[idx].split('='); r.push([un(p[0]), un(p[1])]); }
return r;
}, version: '0.2.1', enabled: false
}; me.enabled = alive.call(me); return me;
}()); var index_of = (function () {
if (Array.prototype.indexOf) { return function (ary, val) { return Array.prototype.indexOf.call(ary, val); }; } else {
return function (ary, val) {
var i, l; for (var idx = 0, len = ary.length; idx < len; idx++) { if (ary[idx] == val) { return idx; } }
return -1;
};
}
})(); empty = function () { }; esc = function (str) { return 'PS' + str.replace(/_/g, '__').replace(/ /g, '_s'); }; var C = { search_order: ['localstorage', 'globalstorage', 'gears', 'cookie', 'ie', 'flash'], name_re: /^[a-z][a-z0-9_ \-]+$/i, methods: ['init', 'get', 'set', 'remove', 'load', 'save', 'iterate'], sql: { version: '1', create: "CREATE TABLE IF NOT EXISTS persist_data (k TEXT UNIQUE NOT NULL PRIMARY KEY, v TEXT NOT NULL)", get: "SELECT v FROM persist_data WHERE k = ?", set: "INSERT INTO persist_data(k, v) VALUES (?, ?)", remove: "DELETE FROM persist_data WHERE k = ?", keys: "SELECT * FROM persist_data" }, flash: { div_id: '_persist_flash_wrap', id: '_persist_flash', path: 'persist.swf', size: { w: 1, h: 1 }, params: { autostart: true } } }; B = {
gears: {
size: -1, test: function () { return (window.google && window.google.gears) ? true : false; }, methods: {
init: function () { var db; db = this.db = google.gears.factory.create('beta.database'); db.open(esc(this.name)); db.execute(C.sql.create).close(); }, get: function (key) { var r, sql = C.sql.get; var db = this.db; var ret; db.execute('BEGIN').close(); r = db.execute(sql, [key]); ret = r.isValidRow() ? r.field(0) : null; r.close(); db.execute('COMMIT').close(); return ret; }, set: function (key, val) { var rm_sql = C.sql.remove, sql = C.sql.set, r; var db = this.db; var ret; db.execute('BEGIN').close(); db.execute(rm_sql, [key]).close(); db.execute(sql, [key, val]).close(); db.execute('COMMIT').close(); return val; }, remove: function (key) { var get_sql = C.sql.get, sql = C.sql.remove, r, val = null, is_valid = false; var db = this.db; db.execute('BEGIN').close(); db.execute(sql, [key]).close(); db.execute('COMMIT').close(); return true; }, iterate: function (fn, scope) {
var key_sql = C.sql.keys; var r; var db = this.db; r = db.execute(key_sql); while (r.isValidRow()) { fn.call(scope || this, r.field(0), r.field(1)); r.next(); }
r.close();
}
}
}, globalstorage: {
size: 5 * 1024 * 1024, test: function () {
if (window.globalStorage) {
var domain = '127.0.0.1'; if (this.o && this.o.domain) { domain = this.o.domain; }
try { var dontcare = globalStorage[domain]; return true; } catch (e) {
if (window.console && window.console.warn) { console.warn("globalStorage exists, but couldn't use it because your browser is running on domain:", domain); }
return false;
}
} else { return false; }
}, methods: { key: function (key) { return esc(this.name) + esc(key); }, init: function () { this.store = globalStorage[this.o.domain]; }, get: function (key) { key = this.key(key); return this.store.getItem(key); }, set: function (key, val) { key = this.key(key); this.store.setItem(key, val); return val; }, remove: function (key) { var val; key = this.key(key); val = this.store.getItem[key]; this.store.removeItem(key); return val; } }
}, localstorage: {
size: -1, test: function () {
try {
if (window.localStorage && window.localStorage.setItem("test", null) == undefined) {
if (/Firefox[\/\s](\d+\.\d+)/.test(navigator.userAgent)) {
var ffVersion = RegExp.$1; if (ffVersion >= 9) { return true; }
if (window.location.protocol == 'file:') { return false; }
} else { return true; }
} else { return false; }
return window.localStorage ? true : false;
} catch (e) { return false; }
}, methods: { key: function (key) { return this.name + '>' + key; }, init: function () { this.store = localStorage; }, get: function (key) { key = this.key(key); return this.store.getItem(key); }, set: function (key, val) { key = this.key(key); this.store.setItem(key, val); return val; }, remove: function (key) { var val; key = this.key(key); val = this.store.getItem(key); this.store.removeItem(key); return val; }, iterate: function (fn, scope) { var l = this.store, key, keys; for (var i = 0; i < l.length; i++) { key = l.key(i); keys = key.split('>'); if ((keys.length == 2) && (keys[0] == this.name)) { fn.call(scope || this, keys[1], l.getItem(key)); } } } }
}, ie: {
prefix: '_persist_data-', size: 64 * 1024, test: function () { return window.ActiveXObject ? true : false; }, make_userdata: function (id) { var el = document.createElement('div'); el.id = id; el.style.display = 'none'; el.addBehavior('#default#userdata'); document.body.appendChild(el); return el; }, methods: {
init: function () { var id = B.ie.prefix + esc(this.name); this.el = B.ie.make_userdata(id); if (this.o.defer) { this.load(); } }, get: function (key) {
var val; key = esc(key); if (!this.o.defer) { this.load(); }
val = this.el.getAttribute(key); return val;
}, set: function (key, val) {
key = esc(key); this.el.setAttribute(key, val); if (!this.o.defer) { this.save(); }
return val;
}, remove: function (key) {
var val; key = esc(key); if (!this.o.defer) { this.load(); }
val = this.el.getAttribute(key); this.el.removeAttribute(key); if (!this.o.defer) { this.save(); }
return val;
}, load: function () { this.el.load(esc(this.name)); }, save: function () { this.el.save(esc(this.name)); }
}
}, cookie: { delim: ':', size: 4000, test: function () { return P.Cookie.enabled ? true : false; }, methods: { key: function (key) { return this.name + B.cookie.delim + key; }, get: function (key, fn) { var val; key = this.key(key); val = ec.get(key); return val; }, set: function (key, val, fn) { key = this.key(key); ec.set(key, val, this.o); return val; }, remove: function (key, val) { var val; key = this.key(key); val = ec.remove(key); return val; } } }, flash: {
test: function () {
try { if (!swfobject) { return false; } } catch (e) { return false; }
var major = swfobject.getFlashPlayerVersion().major; return (major >= 8) ? true : false;
}, methods: {
init: function () {
if (!B.flash.el) { var key, el, fel, cfg = C.flash; el = document.createElement('div'); el.id = cfg.div_id; fel = document.createElement('div'); fel.id = cfg.id; el.appendChild(fel); document.body.appendChild(el); B.flash.el = swfobject.createSWF({ id: cfg.id, data: this.o.swf_path || cfg.path, width: cfg.size.w, height: cfg.size.h }, cfg.params, cfg.id); }
this.el = B.flash.el;
}, get: function (key) { var val; key = esc(key); val = this.el.get(this.name, key); return val; }, set: function (key, val) { var old_val; key = esc(key); old_val = this.el.set(this.name, key, val); return old_val; }, remove: function (key) { var val; key = esc(key); val = this.el.remove(this.name, key); return val; }
}
}
}; init = function () {
var i, l, b, key, fns = C.methods, keys = C.search_order; for (var idx = 0, len = fns.length; idx < len; idx++) { P.Store.prototype[fns[idx]] = empty; }
P.type = null; P.size = -1; for (var idx2 = 0, len2 = keys.length; !P.type && idx2 < len2; idx2++) { b = B[keys[idx2]]; if (b.test()) { P.type = keys[idx2]; P.size = b.size; for (key in b.methods) { P.Store.prototype[key] = b.methods[key]; } } }
P._init = true;
}; P = {
VERSION: VERSION, type: null, size: 0, add: function (o) { B[o.id] = o; C.search_order = [o.id].concat(C.search_order); init(); }, remove: function (id) {
var ofs = index_of(C.search_order, id); if (ofs < 0) { return; }
C.search_order.splice(ofs, 1); delete B[id]; init();
}, Cookie: ec, Store: function (name, o) {
if (!C.name_re.exec(name)) { throw new Error("Invalid name"); }
if (!P.type) { throw new Error("No suitable storage found"); }
o = o || {}; this.name = name; o.domain = o.domain || location.hostname || 'localhost'; o.domain = o.domain.replace(/:\d+$/, ''); o.domain = (o.domain == 'localhost') ? '' : o.domain; this.o = o; o.expires = o.expires || 365 * 2; o.path = o.path || '/'; if (this.o.search_order) { C.search_order = this.o.search_order; init(); }
this.init();
}
}; init(); return P;
})();
</script>
<script>
$(function () {
var store = new Persist.Store('ASP NET Core GraphQL Boxed ReadMe');
function turnOn($checkbox) {
if ($checkbox.hasClass('alert-close-checkbox')) {
$checkbox.parent().hide();
}
else {
$checkbox.parent().addClass('list-group-item-success');
}
}
function turnOff($checkbox) {
if ($checkbox.hasClass('alert-close-checkbox')) {
$checkbox.parent().show();
}
else {
$checkbox.parent().removeClass('list-group-item-success');
}
}
$(':checkbox').click(function () {
var name = this.name;
var value = this.value;
if ($(this).is(':checked')) {
store.set(this.name, 'checked');
turnOn($(this));
} else {
store.remove(this.name);
turnOff($(this));
}
});
$(':checkbox').each(function () {
var isChecked = store.get(this.name) == 'checked';
$(this).prop('checked', isChecked);
if (isChecked) {
turnOn($(this));
}
else {
turnOff($(this));
}
});
})
</script>
</body>
</html>