@@ -8,7 +8,7 @@ using System.Net; | |||
using System.Net.Mail; | |||
using System.Reflection; | |||
using System.Text; | |||
using Teknik.Areas.Transparency.Models; | |||
using Teknik.Areas.Status.Models; | |||
using Teknik.Areas.Upload.Models; | |||
using Teknik.Areas.Users.Models; | |||
using Teknik.Areas.Users.Utility; |
@@ -5,6 +5,7 @@ using System.Linq; | |||
using System.Threading; | |||
using System.Web; | |||
using System.Web.Mvc; | |||
using Teknik.Areas.Status.Models; | |||
using Teknik.Areas.Status.ViewModels; | |||
using Teknik.Attributes; | |||
using Teknik.Controllers; | |||
@@ -24,12 +25,13 @@ namespace Teknik.Areas.Status.Controllers | |||
[AllowAnonymous] | |||
public ActionResult Index() | |||
{ | |||
ViewBag.Title = "Status Information - " + Config.Title; | |||
ViewBag.Title = "System Status - " + Config.Title; | |||
ViewBag.Description = "Current status information for the server and resources."; | |||
StatusViewModel model = new StatusViewModel(); | |||
// Load initial status info | |||
#region Statistics | |||
Upload.Models.Upload upload = db.Uploads.OrderByDescending(u => u.UploadId).FirstOrDefault(); | |||
model.UploadCount = (upload != null) ? upload.UploadId : 0; | |||
model.UploadSize = (upload != null) ? db.Uploads.Sum(u => (long)u.ContentLength) : 0; | |||
@@ -45,6 +47,116 @@ namespace Teknik.Areas.Status.Controllers | |||
Vault.Models.Vault vault = db.Vaults.OrderByDescending(v => v.VaultId).FirstOrDefault(); | |||
model.VaultCount = (url != null) ? vault.VaultId : 0; | |||
#endregion | |||
// Get Transaction Inforomation | |||
#region Transactions | |||
DateTime curTime = DateTime.Now; | |||
var billSums = db.Transactions.OfType<Bill>().GroupBy(b => new { b.Currency, b.DateSent.Month, b.DateSent.Year}).Select(b => new { month = b.Key.Month, year = b.Key.Year, currency = b.Key.Currency, total = b.Sum(c => c.Amount) }).ToList(); | |||
foreach (var sum in billSums) | |||
{ | |||
decimal exchangeRate = CurrencyHelper.GetExchangeRate(sum.currency); | |||
decimal realValue = sum.total * exchangeRate; | |||
model.Transactions.TotalBills += realValue; | |||
model.Transactions.TotalNet += realValue; | |||
if (curTime.Month == sum.month && curTime.Year == sum.year) | |||
{ | |||
model.Transactions.CurrentMonthBills += Math.Abs(realValue); | |||
} | |||
} | |||
var oneSums = db.Transactions.OfType<OneTime>().GroupBy(b => new { b.Currency, b.DateSent.Month, b.DateSent.Year }).Select(b => new { month = b.Key.Month, year = b.Key.Year, currency = b.Key.Currency, total = b.Sum(c => c.Amount) }).ToList(); | |||
foreach (var sum in oneSums) | |||
{ | |||
decimal exchangeRate = CurrencyHelper.GetExchangeRate(sum.currency); | |||
decimal realValue = sum.total * exchangeRate; | |||
model.Transactions.TotalOneTimes += realValue; | |||
model.Transactions.TotalNet += realValue; | |||
if (curTime.Month == sum.month && curTime.Year == sum.year) | |||
{ | |||
model.Transactions.CurrentMonthBills += Math.Abs(realValue); | |||
} | |||
} | |||
var donationSums = db.Transactions.OfType<Donation>().GroupBy(b => new { b.Currency, b.DateSent.Month, b.DateSent.Year }).Select(b => new { month = b.Key.Month, year = b.Key.Year, currency = b.Key.Currency, total = b.Sum(c => c.Amount) }).ToList(); | |||
foreach (var sum in donationSums) | |||
{ | |||
decimal exchangeRate = CurrencyHelper.GetExchangeRate(sum.currency); | |||
decimal realValue = sum.total * exchangeRate; | |||
model.Transactions.TotalDonations += realValue; | |||
model.Transactions.TotalNet += realValue; | |||
if (curTime.Month == sum.month && curTime.Year == sum.year) | |||
{ | |||
model.Transactions.CurrentMonthIncome += Math.Abs(realValue); | |||
} | |||
} | |||
List<Bill> bills = db.Transactions.OfType<Bill>().OrderByDescending(b => b.DateSent).ToList(); | |||
if (bills != null) | |||
{ | |||
foreach (Bill bill in bills) | |||
{ | |||
BillViewModel billModel = new BillViewModel(); | |||
billModel.Amount = bill.Amount; | |||
billModel.Currency = bill.Currency; | |||
billModel.Reason = bill.Reason; | |||
billModel.DateSent = bill.DateSent; | |||
billModel.Recipient = bill.Recipient; | |||
model.Transactions.Bills.Add(billModel); | |||
} | |||
} | |||
List<OneTime> oneTimes = db.Transactions.OfType<OneTime>().OrderByDescending(b => b.DateSent).ToList(); | |||
if (oneTimes != null) | |||
{ | |||
foreach (OneTime oneTime in oneTimes) | |||
{ | |||
OneTimeViewModel oneTimeModel = new OneTimeViewModel(); | |||
oneTimeModel.Amount = oneTime.Amount; | |||
oneTimeModel.Currency = oneTime.Currency; | |||
oneTimeModel.Reason = oneTime.Reason; | |||
oneTimeModel.DateSent = oneTime.DateSent; | |||
oneTimeModel.Recipient = oneTime.Recipient; | |||
model.Transactions.OneTimes.Add(oneTimeModel); | |||
} | |||
} | |||
List<Donation> donations = db.Transactions.OfType<Donation>().OrderByDescending(b => b.DateSent).ToList(); | |||
if (donations != null) | |||
{ | |||
foreach (Donation donation in donations) | |||
{ | |||
DonationViewModel donationModel = new DonationViewModel(); | |||
donationModel.Amount = donation.Amount; | |||
donationModel.Currency = donation.Currency; | |||
donationModel.Reason = donation.Reason; | |||
donationModel.DateSent = donation.DateSent; | |||
donationModel.Sender = donation.Sender; | |||
model.Transactions.Donations.Add(donationModel); | |||
} | |||
} | |||
#endregion | |||
// Takedown information | |||
#region Takedowns | |||
List<Takedown> takedowns = db.Takedowns.OrderByDescending(b => b.DateRequested).ToList(); | |||
if (takedowns != null) | |||
{ | |||
foreach (Takedown takedown in takedowns) | |||
{ | |||
TakedownViewModel takedownModel = new TakedownViewModel(); | |||
takedownModel.Requester = takedown.Requester; | |||
takedownModel.RequesterContact = takedown.RequesterContact; | |||
takedownModel.Reason = takedown.Reason; | |||
takedownModel.ActionTaken = takedown.ActionTaken; | |||
takedownModel.DateRequested = takedown.DateRequested; | |||
takedownModel.DateActionTaken = takedown.DateActionTaken; | |||
model.Takedowns.Add(takedownModel); | |||
} | |||
} | |||
#endregion | |||
return View(model); | |||
} |
@@ -4,7 +4,7 @@ using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
namespace Teknik.Areas.Transparency.Models | |||
namespace Teknik.Areas.Status.Models | |||
{ | |||
public class Bill : Transaction | |||
{ |
@@ -4,7 +4,7 @@ using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
namespace Teknik.Areas.Transparency.Models | |||
namespace Teknik.Areas.Status.Models | |||
{ | |||
public class Donation : Transaction | |||
{ |
@@ -4,7 +4,7 @@ using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
namespace Teknik.Areas.Transparency.Models | |||
namespace Teknik.Areas.Status.Models | |||
{ | |||
public class OneTime : Transaction | |||
{ |
@@ -4,7 +4,7 @@ using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
namespace Teknik.Areas.Transparency.Models | |||
namespace Teknik.Areas.Status.Models | |||
{ | |||
public class Takedown | |||
{ |
@@ -3,16 +3,17 @@ using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using Teknik.Utilities; | |||
namespace Teknik.Areas.Transparency.Models | |||
namespace Teknik.Areas.Status.Models | |||
{ | |||
public class Transaction | |||
{ | |||
public int TransactionId { get; set; } | |||
public double Amount { get; set; } | |||
public decimal Amount { get; set; } | |||
public string Currency { get; set; } | |||
public CurrencyType Currency { get; set; } | |||
public string Reason { get; set; } | |||
@@ -3,6 +3,11 @@ var memUsageChart; | |||
var networkUsageChart; | |||
$(document).ready(function () { | |||
$('#bills-section').collapse('hide'); | |||
$('#oneTime-section').collapse('hide'); | |||
$('#donations-section').collapse('hide'); | |||
$('#takedowns-section').collapse('hide'); | |||
/* ---------------------------------------- | |||
CPU Usage | |||
-----------------------------------------*/ | |||
@@ -22,11 +27,13 @@ $(document).ready(function () { | |||
}, | |||
yAxis: { | |||
title: { | |||
text: 'Percentage %' | |||
text: 'Percentage' | |||
}, | |||
max: 100, | |||
min: 0, | |||
format: '{value}', | |||
labels: { | |||
format: '{value}%' | |||
}, | |||
plotLines: [{ | |||
value: 0, | |||
width: 1, | |||
@@ -38,6 +45,9 @@ $(document).ready(function () { | |||
crosshairs: true, | |||
pointFormat: '<span style="color:{point.color}">\u25CF</span> {series.name}: <b>{point.y:.2f}%</b><br/>' | |||
}, | |||
credits: { | |||
enabled: false | |||
}, | |||
series: [ | |||
{ | |||
name: 'Total', | |||
@@ -98,6 +108,9 @@ $(document).ready(function () { | |||
return '<span style="color:' + this.color + '">\u25CF</span> ' + this.series.name + ': <b>' + yVal + '</b><br/>'; | |||
} | |||
}, | |||
credits: { | |||
enabled: false | |||
}, | |||
series: [ | |||
{ | |||
name: 'Total', | |||
@@ -156,6 +169,9 @@ $(document).ready(function () { | |||
return '<span style="color:' + this.color + '">\u25CF</span> ' + this.series.name + ': <b>' + yVal + '</b><br/>'; | |||
} | |||
}, | |||
credits: { | |||
enabled: false | |||
}, | |||
series: [ | |||
{ | |||
name: 'Sent', | |||
@@ -173,7 +189,9 @@ $(document).ready(function () { | |||
-----------------------------------------*/ | |||
visitChart = new Highcharts.chart({ | |||
chart: { | |||
renderTo: 'visitor-chart' | |||
renderTo: 'visitor-chart', | |||
type: 'line', | |||
marginRight: 10 | |||
}, | |||
title: { | |||
text: 'Daily Visitors' | |||
@@ -199,6 +217,9 @@ $(document).ready(function () { | |||
headerFormat: '<span style="font-size: 10px">{point.key:%B %e, %Y}</span><br/>', | |||
pointFormat: '<span style="color:{point.color}">\u25CF</span> {series.name}: <b>{point.y}</b><br/>' | |||
}, | |||
credits: { | |||
enabled: false | |||
}, | |||
series: [ | |||
{ | |||
name: 'All Visitors', | |||
@@ -260,8 +281,9 @@ $(document).ready(function () { | |||
url: getVisitorDataURL, | |||
success: function (response) { | |||
if (response.result) { | |||
visitChart.series[0].setData(response.result.totalVisitors); | |||
visitChart.series[1].setData(response.result.uniqueVisitors); | |||
visitChart.series[0].setData(response.result.totalVisitors, false); | |||
visitChart.series[1].setData(response.result.uniqueVisitors, false); | |||
visitChart.redraw(); | |||
} | |||
else { | |||
var err = response; | |||
@@ -274,4 +296,9 @@ $(document).ready(function () { | |||
} | |||
}); | |||
} | |||
// Resize the chart when viewing the tab (initial width is wrong due to chart being hidden) | |||
$('a[href="#site-stats"]').on('shown.bs.tab', function (e) { | |||
visitChart.setSize($('#visitor-chart').width(), $('#visitor-chart').height()); | |||
}) | |||
}); |
@@ -0,0 +1,13 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Web; | |||
using Teknik.ViewModels; | |||
namespace Teknik.Areas.Status.ViewModels | |||
{ | |||
public class BillViewModel : TransactionViewModel | |||
{ | |||
public string Recipient { get; set; } | |||
} | |||
} |
@@ -0,0 +1,13 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Web; | |||
using Teknik.ViewModels; | |||
namespace Teknik.Areas.Status.ViewModels | |||
{ | |||
public class DonationViewModel : TransactionViewModel | |||
{ | |||
public string Sender { get; set; } | |||
} | |||
} |
@@ -0,0 +1,13 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Web; | |||
using Teknik.ViewModels; | |||
namespace Teknik.Areas.Status.ViewModels | |||
{ | |||
public class OneTimeViewModel : TransactionViewModel | |||
{ | |||
public string Recipient { get; set; } | |||
} | |||
} |
@@ -2,6 +2,7 @@ | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Web; | |||
using Teknik.Areas.Status.Models; | |||
using Teknik.Models; | |||
using Teknik.ViewModels; | |||
@@ -21,6 +22,10 @@ namespace Teknik.Areas.Status.ViewModels | |||
public int VaultCount { get; set; } | |||
public TransactionsViewModel Transactions { get; set; } | |||
public List<TakedownViewModel> Takedowns { get; set; } | |||
public StatusViewModel() | |||
{ | |||
UploadCount = 0; | |||
@@ -29,6 +34,8 @@ namespace Teknik.Areas.Status.ViewModels | |||
UserCount = 0; | |||
ShortenedUrlCount = 0; | |||
VaultCount = 0; | |||
Transactions = new TransactionsViewModel(); | |||
Takedowns = new List<TakedownViewModel>(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,25 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Web; | |||
using Teknik.ViewModels; | |||
namespace Teknik.Areas.Status.ViewModels | |||
{ | |||
public class TakedownViewModel : ViewModelBase | |||
{ | |||
public string Requester { get; set; } | |||
public string RequesterContact { get; set; } | |||
public string Reason { get; set; } | |||
public string ActionTaken { get; set; } | |||
public DateTime DateRequested { get; set; } | |||
public DateTime DateActionTaken { get; set; } | |||
public virtual ICollection<Upload.Models.Upload> Attachments { get; set; } | |||
} | |||
} |
@@ -0,0 +1,21 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Web; | |||
using Teknik.Areas.Status.Models; | |||
using Teknik.Utilities; | |||
using Teknik.ViewModels; | |||
namespace Teknik.Areas.Status.ViewModels | |||
{ | |||
public class TransactionViewModel : ViewModelBase | |||
{ | |||
public decimal Amount { get; set; } | |||
public CurrencyType Currency { get; set; } | |||
public string Reason { get; set; } | |||
public DateTime DateSent { get; set; } | |||
} | |||
} |
@@ -0,0 +1,40 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Web; | |||
using Teknik.ViewModels; | |||
namespace Teknik.Areas.Status.ViewModels | |||
{ | |||
public class TransactionsViewModel : ViewModelBase | |||
{ | |||
public decimal CurrentMonthBills { get; set; } | |||
public decimal CurrentMonthIncome { get; set; } | |||
public decimal TotalBills { get; set; } | |||
public decimal TotalOneTimes { get; set; } | |||
public decimal TotalDonations { get; set; } | |||
public decimal TotalNet { get; set; } | |||
public List<BillViewModel> Bills { get; set; } | |||
public List<OneTimeViewModel> OneTimes { get; set; } | |||
public List<DonationViewModel> Donations { get; set; } | |||
public TransactionsViewModel() | |||
{ | |||
TotalBills = 0; | |||
TotalOneTimes = 0; | |||
TotalDonations = 0; | |||
TotalNet = 0; | |||
Bills = new List<BillViewModel>(); | |||
OneTimes = new List<OneTimeViewModel>(); | |||
Donations = new List<DonationViewModel>(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,35 @@ | |||
@model List<Teknik.Areas.Status.ViewModels.BillViewModel> | |||
@using Teknik.Areas.Status.ViewModels | |||
@if (Model != null && Model.Any()) | |||
{ | |||
<div class="row"> | |||
<div class="col-sm-12"> | |||
<h3>Bills</h3> | |||
<div class="row"> | |||
<div class="col-sm-12"> | |||
<button type="button" class="btn btn-default" data-toggle="collapse" data-target="#bills-section">View Bills</button> | |||
</div> | |||
</div> | |||
<br /> | |||
<div id="bills-section" class="collapse in"> | |||
<table class="table table-condensed table-bordered table-hover"> | |||
<tr> | |||
<th><strong>Date</strong></th> | |||
<th><strong>Amount</strong></th> | |||
<th><strong>Description</strong></th> | |||
</tr> | |||
@foreach (BillViewModel bill in Model) | |||
{ | |||
<tr> | |||
<td>@bill.DateSent.ToString("MMMM dd, yyyy")</td> | |||
<td>@bill.Amount <var>@bill.Currency.ToString()</var></td> | |||
<td>@bill.Reason</td> | |||
</tr> | |||
} | |||
</table> | |||
</div> | |||
</div> | |||
</div> | |||
} |
@@ -0,0 +1,37 @@ | |||
@model List<Teknik.Areas.Status.ViewModels.DonationViewModel> | |||
@using Teknik.Areas.Status.ViewModels | |||
@if (Model != null && Model.Any()) | |||
{ | |||
<div class="row"> | |||
<div class="col-sm-12"> | |||
<h3>Donations</h3> | |||
<div class="row"> | |||
<div class="col-sm-12"> | |||
<button type="button" class="btn btn-default" data-toggle="collapse" data-target="#donations-section">View Donations</button> | |||
</div> | |||
</div> | |||
<br /> | |||
<div id="donations-section" class="collapse in"> | |||
<table class="table table-condensed table-bordered table-hover"> | |||
<tr> | |||
<th><strong>Date</strong></th> | |||
<th><strong>Amount</strong></th> | |||
<th><strong>Donor</strong></th> | |||
<th><strong>Reason for Donation</strong></th> | |||
</tr> | |||
@foreach (DonationViewModel donation in Model) | |||
{ | |||
<tr> | |||
<td>@donation.DateSent.ToString("MMMM dd, yyyy")</td> | |||
<td>@donation.Amount <var>@donation.Currency.ToString()</var></td> | |||
<td>@donation.Sender</td> | |||
<td>@donation.Reason</td> | |||
</tr> | |||
} | |||
</table> | |||
</div> | |||
</div> | |||
</div> | |||
} |
@@ -1,7 +1,7 @@ | |||
@model Teknik.Areas.Status.ViewModels.StatusViewModel | |||
@using Teknik.Utilities | |||
@using Newtonsoft.Json | |||
@using Teknik.Areas.Status.Models | |||
@Scripts.Render("~/bundles/signalr") | |||
@Scripts.Render("~/signalr/hubs") | |||
@@ -20,9 +20,16 @@ | |||
<div class="container"> | |||
@if (Model.Config.StatusConfig.Enabled) | |||
{ | |||
<div class="row"> | |||
<div class="col-sm-10 col-sm-offset-1"> | |||
<h2 class="text-center"><b>Realtime Usage</b></h2> | |||
<ul class="nav nav-tabs" role="tablist"> | |||
<li role="presentation" class="active"><a href="#realtime-stats" role="tab" data-toggle="tab">Realtime Server Usage</a></li> | |||
<li role="presentation"><a href="#site-stats" role="tab" data-toggle="tab">Site Statistics</a></li> | |||
<li role="presentation"><a href="#transactions" role="tab" data-toggle="tab">Transactions</a></li> | |||
<li role="presentation"><a href="#takedowns" role="tab" data-toggle="tab">Takedowns</a></li> | |||
</ul> | |||
<div class="tab-content"> | |||
<div role="tabpanel" class="tab-pane active" id="realtime-stats"> | |||
<h2 class="text-center"><b>Realtime Server Usage</b></h2> | |||
<hr> | |||
<div class="row"> | |||
<div class="col-sm-12"> | |||
@@ -40,11 +47,8 @@ | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="row"> | |||
<div class="col-sm-10 col-sm-offset-1"> | |||
<br /> | |||
<h2 class="text-center"><b>Statistics</b></h2> | |||
<div role="tabpanel" class="tab-pane" id="site-stats"> | |||
<h2 class="text-center"><b>Site Statistics</b></h2> | |||
<hr> | |||
@if (Model.Config.PiwikConfig.Enabled) | |||
{ | |||
@@ -53,7 +57,6 @@ | |||
<div id="visitor-chart"></div> | |||
</div> | |||
</div> | |||
<br /> | |||
} | |||
<div class="row"> | |||
<div class="col-sm-3 text-center"> | |||
@@ -80,6 +83,13 @@ | |||
<p>Number of Users: @Model.UserCount</p> | |||
</div> | |||
</div> | |||
</div> | |||
<div role="tabpanel" class="tab-pane" id="transactions"> | |||
@Html.Partial("~/Areas/Status/Views/Status/Transactions.cshtml", Model.Transactions) | |||
</div> | |||
<div role="tabpanel" class="tab-pane" id="takedowns"> | |||
@Html.Partial("~/Areas/Status/Views/Status/Takedowns.cshtml", Model.Takedowns) | |||
</div> | |||
</div> | |||
} |
@@ -0,0 +1,35 @@ | |||
@model List<Teknik.Areas.Status.ViewModels.OneTimeViewModel> | |||
@using Teknik.Areas.Status.ViewModels | |||
@if (Model != null && Model.Any()) | |||
{ | |||
<div class="row"> | |||
<div class="col-sm-12"> | |||
<h3>One Time Payments</h3> | |||
<div class="row"> | |||
<div class="col-sm-12"> | |||
<button type="button" class="btn btn-default" data-toggle="collapse" data-target="#oneTime-section">View Payments</button> | |||
</div> | |||
</div> | |||
<br /> | |||
<div id="oneTime-section" class="collapse in"> | |||
<table class="table table-condensed table-bordered table-hover"> | |||
<tr> | |||
<th><strong>Date</strong></th> | |||
<th><strong>Amount</strong></th> | |||
<th><strong>Reason for Payment</strong></th> | |||
</tr> | |||
@foreach (OneTimeViewModel oneTime in Model) | |||
{ | |||
<tr> | |||
<td>@oneTime.DateSent.ToString("MMMM dd, yyyy")</td> | |||
<td>@oneTime.Amount <var>@oneTime.Currency.ToString()</var></td> | |||
<td>@oneTime.Reason</td> | |||
</tr> | |||
} | |||
</table> | |||
</div> | |||
</div> | |||
</div> | |||
} |
@@ -0,0 +1,37 @@ | |||
@model List<Teknik.Areas.Status.ViewModels.TakedownViewModel> | |||
@using Teknik.Areas.Status.ViewModels | |||
@if (Model != null && Model.Any()) | |||
{ | |||
<div class="row"> | |||
<div class="col-sm-12"> | |||
<h2 class="text-center"><b>Takedowns</b></h2> | |||
<hr> | |||
@if (Model != null && Model.Any()) | |||
{ | |||
<table class="table table-hover table-bordered table-condensed"> | |||
<tr> | |||
<th><strong>Requester</strong></th> | |||
<th><strong>Contact</strong></th> | |||
<th><strong>Date Requested</strong></th> | |||
<th><strong>Date Of Action</strong></th> | |||
<th><strong>Reason</strong></th> | |||
<th><strong>Action Taken</strong></th> | |||
</tr> | |||
@foreach (TakedownViewModel takedown in Model) | |||
{ | |||
<tr> | |||
<td>@takedown.Requester</td> | |||
<td>@takedown.RequesterContact</td> | |||
<td>@takedown.DateRequested.ToString("MMMM dd, yyyy")</td> | |||
<td>@takedown.DateActionTaken.ToString("MMMM dd, yyyy")</td> | |||
<td>@takedown.Reason</td> | |||
<td>@takedown.ActionTaken</td> | |||
</tr> | |||
} | |||
</table> | |||
} | |||
</div> | |||
</div> | |||
} |
@@ -0,0 +1,60 @@ | |||
@model Teknik.Areas.Status.ViewModels.TransactionsViewModel | |||
@using Teknik.Areas.Status.ViewModels | |||
@{ | |||
decimal totalBills = Model.CurrentMonthBills; | |||
decimal totalIncome = Model.CurrentMonthIncome; | |||
int incomePercentage = 100; | |||
if (totalIncome != 0 && totalBills != 0) | |||
{ | |||
incomePercentage = (int)Math.Max((Math.Floor(totalBills / totalIncome) * 100), 100); | |||
} | |||
string processStyle = "progress-bar progress-bar-success"; | |||
if (incomePercentage < 100) | |||
{ | |||
processStyle += " progress-bar-striped"; | |||
} | |||
} | |||
<div class="row"> | |||
<div class="col-sm-12"> | |||
<h2 class="text-center"><b>Transactions</b></h2> | |||
<hr> | |||
<div class="row"> | |||
<div class="col-sm-10 col-sm-offset-1"> | |||
<h3 class="text-center">Monthly Donation Target</h3> | |||
<div class="progress"> | |||
<div class="@processStyle" role="progressbar" style="width: @incomePercentage%"></div> | |||
</div> | |||
<div class="row"> | |||
<div class="col-sm-12 text-center">$@totalIncome Donated / $@totalBills Bills</div> | |||
</div> | |||
</div> | |||
</div> | |||
<h3 class="text-center">Transaction Totals</h3> | |||
<div class="row"> | |||
<div class="col-sm-3 text-center"> | |||
<h4>Donations</h4> | |||
<p>$@Math.Round(Model.TotalDonations, 2)</p> | |||
</div> | |||
<div class="col-sm-3 text-center"> | |||
<h4>Bills</h4> | |||
<p>$@Math.Round(Model.TotalBills, 2)</p> | |||
</div> | |||
<div class="col-sm-3 text-center"> | |||
<h4>One-Time Payments</h4> | |||
<p>$@Math.Round(Model.TotalOneTimes, 2)</p> | |||
</div> | |||
<div class="col-sm-3 text-center"> | |||
<h4>Net Profit</h4> | |||
<p>$@Math.Round(Model.TotalNet, 2)</p> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
@Html.Partial("~/Areas/Status/Views/Status/Bills.cshtml", Model.Bills) | |||
@Html.Partial("~/Areas/Status/Views/Status/OneTimes.cshtml", Model.OneTimes) | |||
@Html.Partial("~/Areas/Status/Views/Status/Donations.cshtml", Model.Donations) |
@@ -1,130 +0,0 @@ | |||
using System; | |||
using System.Collections; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Web; | |||
using System.Web.Mvc; | |||
using Teknik.Areas.Transparency.Models; | |||
using Teknik.Areas.Transparency.ViewModels; | |||
using Teknik.Attributes; | |||
using Teknik.Controllers; | |||
using Teknik.Filters; | |||
using Teknik.Models; | |||
using Teknik.Piwik; | |||
namespace Teknik.Areas.Transparency.Controllers | |||
{ | |||
[TeknikAuthorize] | |||
public class TransparencyController : DefaultController | |||
{ | |||
private TeknikEntities db = new TeknikEntities(); | |||
[TrackPageView] | |||
[AllowAnonymous] | |||
public ActionResult Index() | |||
{ | |||
ViewBag.Title = "Transparency - " + Config.Title; | |||
ViewBag.Description = "Teknik transparency and statistics."; | |||
TransparencyViewModel model = new TransparencyViewModel(); | |||
if (Config.TransparencyConfig.Enabled) | |||
{ | |||
model.TotalNet = new Dictionary<string, double>(); | |||
var billSums = db.Transactions.OfType<Bill>().GroupBy(b => b.Currency).Select(b => new { currency = b.Key, total = b.Sum(c => c.Amount) }).ToList(); | |||
model.TotalBills = new Dictionary<string, double>(); | |||
foreach (var sum in billSums) | |||
{ | |||
model.TotalBills.Add(sum.currency, sum.total); | |||
if (model.TotalNet.ContainsKey(sum.currency)) | |||
{ | |||
model.TotalNet[sum.currency] += sum.total; | |||
} | |||
else | |||
{ | |||
model.TotalNet.Add(sum.currency, sum.total); | |||
} | |||
} | |||
var oneSums = db.Transactions.OfType<OneTime>().GroupBy(b => b.Currency).Select(b => new { currency = b.Key, total = b.Sum(c => c.Amount) }).ToList(); | |||
model.TotalOneTimes = new Dictionary<string, double>(); | |||
foreach (var sum in oneSums) | |||
{ | |||
model.TotalOneTimes.Add(sum.currency, sum.total); | |||
if (model.TotalNet.ContainsKey(sum.currency)) | |||
{ | |||
model.TotalNet[sum.currency] += sum.total; | |||
} | |||
else | |||
{ | |||
model.TotalNet.Add(sum.currency, sum.total); | |||
} | |||
} | |||
var donationSums = db.Transactions.OfType<Donation>().GroupBy(b => b.Currency).Select(b => new { currency = b.Key, total = b.Sum(c => c.Amount) }).ToList(); | |||
model.TotalDonations = new Dictionary<string, double>(); | |||
foreach (var sum in donationSums) | |||
{ | |||
model.TotalDonations.Add(sum.currency, sum.total); | |||
if (model.TotalNet.ContainsKey(sum.currency)) | |||
{ | |||
model.TotalNet[sum.currency] += sum.total; | |||
} | |||
else | |||
{ | |||
model.TotalNet.Add(sum.currency, sum.total); | |||
} | |||
} | |||
List<Bill> bills = db.Transactions.OfType<Bill>().OrderByDescending(b => b.DateSent).ToList(); | |||
model.Bills = (bills != null) ? bills : new List<Bill>(); | |||
List<OneTime> oneTimes = db.Transactions.OfType<OneTime>().OrderByDescending(b => b.DateSent).ToList(); | |||
model.OneTimes = (oneTimes != null) ? oneTimes : new List<OneTime>(); | |||
List<Donation> donations = db.Transactions.OfType<Donation>().OrderByDescending(b => b.DateSent).ToList(); | |||
model.Donations = (donations != null) ? donations : new List<Donation>(); | |||
List<Takedown> takedowns = db.Takedowns.OrderByDescending(b => b.DateRequested).ToList(); | |||
model.Takedowns = (takedowns != null) ? takedowns : new List<Takedown>(); | |||
// Grab canary file | |||
if (System.IO.File.Exists(Config.TransparencyConfig.CanaryPath)) | |||
{ | |||
model.Canary = System.IO.File.ReadAllText(Config.TransparencyConfig.CanaryPath); | |||
} | |||
else | |||
{ | |||
model.Canary = string.Empty; | |||
} | |||
} | |||
return View(model); | |||
} | |||
[HttpGet] | |||
[AllowAnonymous] | |||
public ActionResult GetVisitorData() | |||
{ | |||
// Get the data from the Piwik | |||
if (!string.IsNullOrEmpty(Config.PiwikConfig.API)) | |||
{ | |||
List<VisitorData> dataList = Reporting.GetVisitSummaryByDays(Config, 31); | |||
List<object> uniqueData = new List<object>(); | |||
List<object> totalData = new List<object>(); | |||
foreach (VisitorData data in dataList.OrderBy(d => d.Date)) | |||
{ | |||
object uniqueDay = new { x = Convert.ToInt64((data.Date.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds), y = data.UniqueVisitors }; | |||
uniqueData.Add(uniqueDay); | |||
object totalDay = new { x = Convert.ToInt64((data.Date.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds), y = data.Visits }; | |||
totalData.Add(totalDay); | |||
} | |||
return Json(new { result = new { uniqueVisitors = uniqueData.ToArray(), totalVisitors = totalData.ToArray() } }, JsonRequestBehavior.AllowGet); | |||
} | |||
return Json(new { error = new { message = "Piwik not configured" } }, JsonRequestBehavior.AllowGet); | |||
} | |||
} | |||
} |
@@ -1,69 +0,0 @@ | |||
var visitChart; | |||
$(document).ready(function () { | |||
$('#bills-section').collapse('hide'); | |||
$('#oneTime-section').collapse('hide'); | |||
$('#donations-section').collapse('hide'); | |||
$('#takedowns-section').collapse('hide'); | |||
visitChart = new Highcharts.chart({ | |||
chart: { | |||
renderTo: 'visitor-chart' | |||
}, | |||
title: { | |||
text: 'Daily Visitors' | |||
}, | |||
xAxis: { | |||
type: 'datetime', | |||
dateTimeLabelFormats: { // don't display the dummy year | |||
month: '%e. %b', | |||
year: '%b' | |||
}, | |||
title: { | |||
text: 'Date' | |||
} | |||
}, | |||
yAxis: { | |||
title: { | |||
text: 'Visitors' | |||
} | |||
}, | |||
tooltip: { | |||
shared: true, | |||
crosshairs: true, | |||
headerFormat: '<span style="font-size: 10px">{point.key:%B %e, %Y}</span><br/>', | |||
pointFormat: '<span style="color:{point.color}">\u25CF</span> {series.name}: <b>{point.y}</b><br/>' | |||
}, | |||
series: [ | |||
{ | |||
name: 'All Visitors', | |||
data: [] | |||
}, | |||
{ | |||
name: 'Unique Visitors', | |||
data: [] | |||
} | |||
] | |||
}); | |||
if (statsEnabled) { | |||
$.ajax({ | |||
type: "GET", | |||
url: getVisitorDataURL, | |||
success: function (response) { | |||
if (response.result) { | |||
visitChart.series[0].setData(response.result.totalVisitors); | |||
visitChart.series[1].setData(response.result.uniqueVisitors); | |||
} | |||
else { | |||
var err = response; | |||
if (response.error) { | |||
err = response.error.message; | |||
} | |||
$("#top_msg").css('display', 'inline', 'important'); | |||
$("#top_msg").html('<div class="alert alert-danger alert-dismissable"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>' + err + '</div>'); | |||
} | |||
} | |||
}); | |||
} | |||
}); |
@@ -1,45 +0,0 @@ | |||
using System.Collections.Generic; | |||
using System.Web.Mvc; | |||
using System.Web.Optimization; | |||
using Teknik.Configuration; | |||
using Teknik.Utilities; | |||
namespace Teknik.Areas.Transparency | |||
{ | |||
public class TransparencyAreaRegistration : AreaRegistration | |||
{ | |||
public override string AreaName | |||
{ | |||
get | |||
{ | |||
return "Transparency"; | |||
} | |||
} | |||
public override void RegisterArea(AreaRegistrationContext context) | |||
{ | |||
Config config = Config.Load(); | |||
context.MapSubdomainRoute( | |||
"Transparency.Index", | |||
new List<string>() { "transparency" }, // Subdomains | |||
new List<string>() { config.Host }, // domains | |||
"", | |||
new { controller = "Transparency", action = "Index" }, | |||
new[] { typeof(Controllers.TransparencyController).Namespace } | |||
); | |||
context.MapSubdomainRoute( | |||
"Transparency.Action", | |||
new List<string>() { "transparency" }, // Subdomains | |||
new List<string>() { config.Host }, // domains | |||
"Action/{controller}/{action}", | |||
new { controller = "Transparency", action = "Index" }, | |||
new[] { typeof(Controllers.TransparencyController).Namespace } | |||
); | |||
// Register Script Bundle | |||
BundleTable.Bundles.Add(new CdnScriptBundle("~/bundles/transparency", config.CdnHost).Include( | |||
"~/Scripts/Highcharts/highcharts.js", | |||
"~/Areas/Transparency/Scripts/Transparency.js")); | |||
} | |||
} | |||
} |
@@ -1,31 +0,0 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using Teknik.Areas.Transparency.Models; | |||
using Teknik.ViewModels; | |||
namespace Teknik.Areas.Transparency.ViewModels | |||
{ | |||
public class TransparencyViewModel : ViewModelBase | |||
{ | |||
public string Canary { get; set; } | |||
public Dictionary<string, double> TotalBills { get; set; } | |||
public Dictionary<string, double> TotalOneTimes { get; set; } | |||
public Dictionary<string, double> TotalDonations { get; set; } | |||
public Dictionary<string, double> TotalNet { get; set; } | |||
public List<Bill> Bills { get; set; } | |||
public List<OneTime> OneTimes { get; set; } | |||
public List<Donation> Donations { get; set; } | |||
public List<Takedown> Takedowns { get; set; } | |||
} | |||
} |
@@ -1,255 +0,0 @@ | |||
@model Teknik.Areas.Transparency.ViewModels.TransparencyViewModel | |||
@using Teknik.Utilities | |||
@using Teknik.Areas.Transparency.Models | |||
@Scripts.Render("~/bundles/transparency") | |||
<script type="text/javascript"> | |||
var statsEnabled = @(Model.Config.PiwikConfig.Enabled.ToString().ToLower()); | |||
var getVisitorDataURL = '@Url.SubRouteUrl("transparency", "Transparency.Action", new { action = "GetVisitorData" })'; | |||
</script> | |||
<div class="container"> | |||
@if (Model.Config.TransparencyConfig.Enabled) | |||
{ | |||
<div class="row"> | |||
<div class="col-sm-10 col-sm-offset-1"> | |||
<h2 class="text-center"><b>Behind the Scenes</b></h2> | |||
<hr> | |||
<p> | |||
Here you can view all of Teknik's financial information, takedown requests and the actions we took. | |||
</p> | |||
<p> | |||
If you would like to request additional information about Teknik, please feel free to contact us through our <a href="@Url.SubRouteUrl("contact", "Contact.Index")" target="_blank">Contact Form</a> or by emailing us at <a href="mailto:@Model.Config.SupportEmail">@Model.Config.SupportEmail</a>. | |||
</p> | |||
<br /> | |||
<h2 class="text-center"><b>Transactions</b></h2> | |||
<hr> | |||
<h3 class="text-center">Total Amounts</h3> | |||
<div class="row"> | |||
<div class="col-sm-3 text-center"> | |||
<h4>Donations</h4> | |||
@foreach (var val in Model.TotalDonations) | |||
{ | |||
<p>@Math.Round(val.Value, 2) @val.Key</p> | |||
} | |||
</div> | |||
<div class="col-sm-3 text-center"> | |||
<h4>Bills</h4> | |||
@foreach (var val in Model.TotalBills) | |||
{ | |||
<p>@Math.Round(val.Value, 2) @val.Key</p> | |||
} | |||
</div> | |||
<div class="col-sm-3 text-center"> | |||
<h4>One-Time Payments</h4> | |||
@foreach (var val in Model.TotalOneTimes) | |||
{ | |||
<p>@Math.Round(val.Value, 2) @val.Key</p> | |||
} | |||
</div> | |||
<div class="col-sm-3 text-center"> | |||
<h4>Net Profit</h4> | |||
@foreach (var val in Model.TotalNet) | |||
{ | |||
<p>@Math.Round(val.Value, 2) @val.Key</p> | |||
} | |||
</div> | |||
</div> | |||
@if (Model.Bills != null && Model.Bills.Any()) | |||
{ | |||
<h3>Bills</h3> | |||
<div class="row"> | |||
<div class="col-sm-12"> | |||
<button type="button" class="btn btn-default" data-toggle="collapse" data-target="#bills-section">View Bills</button> | |||
</div> | |||
</div> | |||
<br /> | |||
<div id="bills-section" class="collapse in"> | |||
<div class="row"> | |||
<div class="col-sm-3"> | |||
<h4><strong>Date</strong></h4> | |||
</div> | |||
<div class="col-sm-2"> | |||
<h4><strong>Amount</strong></h4> | |||
</div> | |||
<div class="col-sm-7"> | |||
<h4><strong>Description</strong></h4> | |||
</div> | |||
</div> | |||
@foreach (Bill bill in Model.Bills) | |||
{ | |||
<div class="row"> | |||
<div class="col-sm-3"> | |||
@bill.DateSent.ToString("MMMM dd, yyyy") | |||
</div> | |||
<div class="col-sm-2"> | |||
@bill.Amount <var>@bill.Currency</var> | |||
</div> | |||
<div class="col-sm-7"> | |||
@bill.Reason | |||
</div> | |||
</div> | |||
} | |||
</div> | |||
} | |||
@if (Model.OneTimes != null && Model.OneTimes.Any()) | |||
{ | |||
<h3>One Time Payments</h3> | |||
<div class="row"> | |||
<div class="col-sm-12"> | |||
<button type="button" class="btn btn-default" data-toggle="collapse" data-target="#oneTime-section">View Payments</button> | |||
</div> | |||
</div> | |||
<br /> | |||
<div id="oneTime-section" class="collapse in"> | |||
<div class="row"> | |||
<div class="col-sm-3"> | |||
<h4><strong>Date</strong></h4> | |||
</div> | |||
<div class="col-sm-2"> | |||
<h4><strong>Amount</strong></h4> | |||
</div> | |||
<div class="col-sm-7"> | |||
<h4><strong>Reason for Payment</strong></h4> | |||
</div> | |||
</div> | |||
@foreach (OneTime oneTime in Model.OneTimes) | |||
{ | |||
<div class="row"> | |||
<div class="col-sm-3"> | |||
@oneTime.DateSent.ToString("MMMM dd, yyyy") | |||
</div> | |||
<div class="col-sm-2"> | |||
@oneTime.Amount <var>@oneTime.Currency</var> | |||
</div> | |||
<div class="col-sm-7"> | |||
@oneTime.Reason | |||
</div> | |||
</div> | |||
} | |||
</div> | |||
} | |||
@if (Model.Donations != null && Model.Donations.Any()) | |||
{ | |||
<h3>Donations</h3> | |||
<div class="row"> | |||
<div class="col-sm-12"> | |||
<button type="button" class="btn btn-default" data-toggle="collapse" data-target="#donations-section">View Donations</button> | |||
</div> | |||
</div> | |||
<br /> | |||
<div id="donations-section" class="collapse in"> | |||
<div class="row"> | |||
<div class="col-sm-3"> | |||
<h4><strong>Date</strong></h4> | |||
</div> | |||
<div class="col-sm-2"> | |||
<h4><strong>Amount</strong></h4> | |||
</div> | |||
<div class="col-sm-2"> | |||
<h4><strong>Donor</strong></h4> | |||
</div> | |||
<div class="col-sm-5"> | |||
<h4><strong>Reason for Donation</strong></h4> | |||
</div> | |||
</div> | |||
@foreach (Donation donation in Model.Donations) | |||
{ | |||
<div class="row"> | |||
<div class="col-sm-3"> | |||
@donation.DateSent.ToString("MMMM dd, yyyy") | |||
</div> | |||
<div class="col-sm-2"> | |||
@donation.Amount <var>@donation.Currency</var> | |||
</div> | |||
<div class="col-sm-2"> | |||
@donation.Sender | |||
</div> | |||
<div class="col-sm-5"> | |||
@donation.Reason | |||
</div> | |||
</div> | |||
} | |||
</div> | |||
} | |||
<br /> | |||
<h2 class="text-center"><b>Takedowns</b></h2> | |||
<hr> | |||
@if (Model.Takedowns != null && Model.Takedowns.Any()) | |||
{ | |||
<h3>Takedowns</h3> | |||
<div class="row"> | |||
<div class="col-sm-12"> | |||
<button type="button" class="btn btn-default" data-toggle="collapse" data-target="#takedowns-section">View Takedowns</button> | |||
</div> | |||
</div> | |||
<br /> | |||
<div id="takedowns-section" class="collapse in"> | |||
<div class="row"> | |||
<div class="col-sm-2"> | |||
<h4><strong>Requester</strong></h4> | |||
</div> | |||
<div class="col-sm-2"> | |||
<h4><strong>Contact</strong></h4> | |||
</div> | |||
<div class="col-sm-2"> | |||
<h4><strong>Reason</strong></h4> | |||
</div> | |||
<div class="col-sm-2"> | |||
<h4><strong>Action Taken</strong></h4> | |||
</div> | |||
<div class="col-sm-2"> | |||
<h4><strong>Date Requested</strong></h4> | |||
</div> | |||
<div class="col-sm-2"> | |||
<h4><strong>Date Of Action</strong></h4> | |||
</div> | |||
</div> | |||
@foreach (Takedown takedown in Model.Takedowns) | |||
{ | |||
<div class="row"> | |||
<div class="col-sm-2"> | |||
@takedown.Requester | |||
</div> | |||
<div class="col-sm-2"> | |||
@takedown.RequesterContact | |||
</div> | |||
<div class="col-sm-2"> | |||
@takedown.Reason | |||
</div> | |||
<div class="col-sm-2"> | |||
@takedown.ActionTaken | |||
</div> | |||
<div class="col-sm-2"> | |||
@takedown.DateRequested.ToString("MMMM dd, yyyy") | |||
</div> | |||
<div class="col-sm-2"> | |||
@takedown.DateActionTaken.ToString("MMMM dd, yyyy") | |||
</div> | |||
</div> | |||
} | |||
</div> | |||
} | |||
<br /> | |||
</div> | |||
</div> | |||
<div class="row"> | |||
<div class="col-sm-8 col-sm-offset-2"> | |||
@if (!string.IsNullOrEmpty(Model.Canary)) | |||
{ | |||
<pre>@Model.Canary</pre> | |||
} | |||
</div> | |||
</div> | |||
} | |||
else | |||
{ | |||
<div class="row"> | |||
<div class="col-sm-8 col-sm-offset-2 text-center"> | |||
<h3>Transparency Information has been disabled</h3> | |||
</div> | |||
</div> | |||
} | |||
</div> |
@@ -1,3 +0,0 @@ | |||
@{ | |||
Layout = "~/Views/Shared/_Layout.cshtml"; | |||
} |
@@ -1,36 +0,0 @@ | |||
<?xml version="1.0"?> | |||
<configuration> | |||
<configSections> | |||
<sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"> | |||
<section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" /> | |||
<section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" /> | |||
</sectionGroup> | |||
</configSections> | |||
<system.web.webPages.razor> | |||
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /> | |||
<pages pageBaseType="System.Web.Mvc.WebViewPage"> | |||
<namespaces> | |||
<add namespace="System.Web.Mvc" /> | |||
<add namespace="System.Web.Mvc.Ajax" /> | |||
<add namespace="System.Web.Mvc.Html" /> | |||
<add namespace="System.Web.Routing" /> | |||
<add namespace="System.Web.Optimization" /> | |||
<add namespace="Teknik" /> | |||
</namespaces> | |||
</pages> | |||
</system.web.webPages.razor> | |||
<appSettings> | |||
<add key="webpages:Enabled" value="false" /> | |||
</appSettings> | |||
<system.webServer> | |||
<handlers> | |||
<remove name="BlockViewHandler"/> | |||
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" /> | |||
</handlers> | |||
</system.webServer> | |||
</configuration> |
@@ -8,7 +8,7 @@ using Teknik.Migrations; | |||
using Teknik.Areas.Upload.Models; | |||
using Teknik.Areas.Paste.Models; | |||
using Teknik.Areas.Podcast.Models; | |||
using Teknik.Areas.Transparency.Models; | |||
using Teknik.Areas.Status.Models; | |||
using Teknik.Areas.Shortener.Models; | |||
using Teknik.Attributes; | |||
using System.Data.Entity.ModelConfiguration.Conventions; |
@@ -103,6 +103,10 @@ | |||
<HintPath>..\packages\MySql.Data.6.9.9\lib\net45\MySql.Data.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
<Reference Include="NBitcoin, Version=3.0.2.4, Culture=neutral, processorArchitecture=MSIL"> | |||
<HintPath>..\packages\NBitcoin.3.0.2.4\lib\net45\NBitcoin.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
<Reference Include="nClam, Version=2.0.6.0, Culture=neutral, processorArchitecture=MSIL"> | |||
<HintPath>..\packages\nClam.2.0.6.0\lib\net40-Client\nClam.dll</HintPath> | |||
<Private>True</Private> | |||
@@ -259,8 +263,19 @@ | |||
<Compile Include="Areas\Privacy\PrivacyAreaRegistration.cs" /> | |||
<Compile Include="Areas\Privacy\ViewModels\PrivacyViewModel.cs" /> | |||
<Compile Include="Areas\Status\Controllers\StatusController.cs" /> | |||
<Compile Include="Areas\Status\Models\Bill.cs" /> | |||
<Compile Include="Areas\Status\Models\Donation.cs" /> | |||
<Compile Include="Areas\Status\Models\OneTime.cs" /> | |||
<Compile Include="Areas\Status\Models\Takedown.cs" /> | |||
<Compile Include="Areas\Status\Models\Transaction.cs" /> | |||
<Compile Include="Areas\Status\StatusAreaRegistration.cs" /> | |||
<Compile Include="Areas\Status\ViewModels\OneTimeViewModel.cs" /> | |||
<Compile Include="Areas\Status\ViewModels\DonationViewModel.cs" /> | |||
<Compile Include="Areas\Status\ViewModels\StatusViewModel.cs" /> | |||
<Compile Include="Areas\Status\ViewModels\TakedownViewModel.cs" /> | |||
<Compile Include="Areas\Status\ViewModels\TransactionsViewModel.cs" /> | |||
<Compile Include="Areas\Status\ViewModels\BillViewModel.cs" /> | |||
<Compile Include="Areas\Status\ViewModels\TransactionViewModel.cs" /> | |||
<Compile Include="Areas\User\Controllers\UserController.cs" /> | |||
<Compile Include="Areas\User\Models\BlogSettings.cs" /> | |||
<Compile Include="Areas\User\Models\ResetPasswordVerification.cs" /> | |||
@@ -302,14 +317,6 @@ | |||
<Compile Include="Areas\TOS\Controllers\TOSController.cs" /> | |||
<Compile Include="Areas\TOS\TOSAreaRegistration.cs" /> | |||
<Compile Include="Areas\TOS\ViewModels\TOSViewModel.cs" /> | |||
<Compile Include="Areas\Transparency\Controllers\TransparencyController.cs" /> | |||
<Compile Include="Areas\Transparency\Models\Bill.cs" /> | |||
<Compile Include="Areas\Transparency\Models\Donation.cs" /> | |||
<Compile Include="Areas\Transparency\Models\OneTime.cs" /> | |||
<Compile Include="Areas\Transparency\Models\Takedown.cs" /> | |||
<Compile Include="Areas\Transparency\Models\Transaction.cs" /> | |||
<Compile Include="Areas\Transparency\TransparencyAreaRegistration.cs" /> | |||
<Compile Include="Areas\Transparency\ViewModels\TransparencyViewModel.cs" /> | |||
<Compile Include="Areas\Upload\Controllers\UploadController.cs" /> | |||
<Compile Include="Areas\Upload\Models\FileModel.cs" /> | |||
<Compile Include="Areas\Upload\Models\Upload.cs" /> | |||
@@ -371,7 +378,6 @@ | |||
<Content Include="Areas\Podcast\Content\Podcast.css" /> | |||
<Content Include="Areas\Podcast\Scripts\Podcast.js" /> | |||
<Content Include="Areas\Status\Scripts\Status.js" /> | |||
<Content Include="Areas\Transparency\Scripts\Transparency.js" /> | |||
<Content Include="Areas\Upload\Content\Upload.css" /> | |||
<Content Include="Areas\User\Scripts\CheckAuthCode.js" /> | |||
<Content Include="Areas\User\Scripts\Profile.js" /> | |||
@@ -564,9 +570,7 @@ | |||
<Content Include="Areas\Podcast\Views\Podcast\ViewPodcast.cshtml" /> | |||
<Content Include="App_Data\Config.json" /> | |||
<Content Include="Areas\User\Views\User\Settings.cshtml" /> | |||
<Content Include="Areas\Transparency\Views\web.config" /> | |||
<Content Include="Areas\Vault\Views\_ViewStart.cshtml" /> | |||
<Content Include="Areas\Transparency\Views\Transparency\Index.cshtml" /> | |||
<Content Include="Areas\Help\Views\Help\RSS.cshtml" /> | |||
<Content Include="Areas\Stream\Views\web.config" /> | |||
<Content Include="Areas\Stream\Views\_ViewStart.cshtml" /> | |||
@@ -612,14 +616,18 @@ | |||
<Content Include="Fonts\fontawesome-webfont.eot" /> | |||
<Content Include="Areas\User\Views\User\AuthToken.cshtml" /> | |||
<Content Include="Areas\Error\Views\Error\Http401.cshtml" /> | |||
<Content Include="Areas\Transparency\Views\_ViewStart.cshtml" /> | |||
<Content Include="Areas\Vault\Views\Vault\ModifyVault.cshtml" /> | |||
<Content Include="Areas\Vault\Views\Vault\ModifyVaultItem.cshtml" /> | |||
<Content Include="Areas\Vault\Views\Vault\PasteItem.cshtml" /> | |||
<Content Include="Areas\Vault\Views\Vault\UploadItem.cshtml" /> | |||
<Content Include="Areas\Status\Views\web.config" /> | |||
<Content Include="Areas\Status\Views\_ViewStart.cshtml" /> | |||
<Content Include="Areas\Status\Views\Shared\Index.cshtml" /> | |||
<Content Include="Areas\Status\Views\Status\Index.cshtml" /> | |||
<Content Include="Areas\Status\Views\Status\Transactions.cshtml" /> | |||
<Content Include="Areas\Status\Views\Status\Bills.cshtml" /> | |||
<Content Include="Areas\Status\Views\Status\OneTimes.cshtml" /> | |||
<Content Include="Areas\Status\Views\Status\Donations.cshtml" /> | |||
<Content Include="Areas\Status\Views\Status\Takedowns.cshtml" /> | |||
<None Include="Properties\PublishProfiles\Teknik Dev.pubxml" /> | |||
<None Include="Properties\PublishProfiles\Teknik Production.pubxml" /> | |||
<None Include="Scripts\jquery-2.1.4.intellisense.js" /> | |||
@@ -718,12 +726,10 @@ | |||
<Folder Include="Areas\Privacy\Models\" /> | |||
<Folder Include="Areas\Privacy\Views\Shared\" /> | |||
<Folder Include="Areas\Shortener\Views\Shared\" /> | |||
<Folder Include="Areas\Status\Models\" /> | |||
<Folder Include="Areas\Status\Views\Status\" /> | |||
<Folder Include="Areas\Status\Views\Shared\" /> | |||
<Folder Include="Areas\Stream\Views\Shared\" /> | |||
<Folder Include="Areas\TOS\Models\" /> | |||
<Folder Include="Areas\TOS\Views\Shared\" /> | |||
<Folder Include="Areas\Transparency\Views\Shared\" /> | |||
<Folder Include="Areas\Upload\Views\Shared\" /> | |||
<Folder Include="Areas\User\Repositories\" /> | |||
<Folder Include="Areas\User\Views\Shared\" /> |
@@ -51,7 +51,7 @@ | |||
} | |||
<div class="row"> | |||
<div class="col-sm-5 col-sm-offset-1 text-left text-muted"> | |||
© Teknik 2013-2017 | <a href="@Url.SubRouteUrl("privacy", "Privacy.Index")">Privacy</a> | <a href="@Url.SubRouteUrl("tos", "TOS.Index")">TOS</a> | <a href="@Url.SubRouteUrl("transparency", "Transparency.Index")">Transparency</a> | |||
© Teknik 2013-2017 | <a href="@Url.SubRouteUrl("privacy", "Privacy.Index")">Privacy</a> | <a href="@Url.SubRouteUrl("tos", "TOS.Index")">TOS</a> | <a href="@Url.SubRouteUrl("status", "Status.Index")">Status</a> | |||
</div> | |||
<div class="col-sm-5 text-right text-muted"> | |||
<div id="pagetime" style="display:none;"> |
@@ -32,6 +32,7 @@ | |||
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net46" userInstalled="true" /> | |||
<package id="Modernizr" version="2.8.3" targetFramework="net452" userInstalled="true" /> | |||
<package id="MySql.Data" version="6.9.9" targetFramework="net452" /> | |||
<package id="NBitcoin" version="3.0.2.4" targetFramework="net462" /> | |||
<package id="nClam" version="2.0.6.0" targetFramework="net462" /> | |||
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net452" userInstalled="true" /> | |||
<package id="Owin" version="1.0" targetFramework="net462" /> |
@@ -40,7 +40,6 @@ namespace Teknik.Configuration | |||
private StreamConfig _StreamConfig; | |||
private ShortenerConfig _ShortenerConfig; | |||
private VaultConfig _VaultConfig; | |||
private TransparencyConfig _TransparencyConfig; | |||
private StatusConfig _StatusConfig; | |||
private DatabaseConfig _DatabaseConfig; | |||
private LoggingConfig _LoggingConfig; | |||
@@ -98,9 +97,6 @@ namespace Teknik.Configuration | |||
// Vault Configuration | |||
public VaultConfig VaultConfig { get { return _VaultConfig; } set { _VaultConfig = value; } } | |||
// Transparency Configuration | |||
public TransparencyConfig TransparencyConfig { get { return _TransparencyConfig; } set { _TransparencyConfig = value; } } | |||
// Status Configuration | |||
public StatusConfig StatusConfig { get { return _StatusConfig; } set { _StatusConfig = value; } } | |||
@@ -150,7 +146,6 @@ namespace Teknik.Configuration | |||
StreamConfig = new StreamConfig(); | |||
ShortenerConfig = new ShortenerConfig(); | |||
VaultConfig = new VaultConfig(); | |||
TransparencyConfig = new TransparencyConfig(); | |||
StatusConfig = new StatusConfig(); | |||
DatabaseConfig = new DatabaseConfig(); | |||
LoggingConfig = new LoggingConfig(); |
@@ -63,7 +63,6 @@ | |||
<Compile Include="VaultConfig.cs" /> | |||
<Compile Include="ShortenerConfig.cs" /> | |||
<Compile Include="StreamConfig.cs" /> | |||
<Compile Include="TransparencyConfig.cs" /> | |||
<Compile Include="UploadConfig.cs" /> | |||
<Compile Include="UserConfig.cs" /> | |||
</ItemGroup> |
@@ -1,21 +0,0 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
namespace Teknik.Configuration | |||
{ | |||
public class TransparencyConfig | |||
{ | |||
public bool Enabled { get; set; } | |||
public string CanaryPath { get; set; } | |||
public TransparencyConfig() | |||
{ | |||
Enabled = false; | |||
CanaryPath = string.Empty; | |||
} | |||
} | |||
} |
@@ -0,0 +1,78 @@ | |||
using Newtonsoft.Json; | |||
using Newtonsoft.Json.Linq; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.IO; | |||
using System.Linq; | |||
using System.Net; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
namespace Teknik.Utilities | |||
{ | |||
public static class CurrencyHelper | |||
{ | |||
private static decimal m_CurrentBTCPrice = 0; | |||
private static DateTime m_LastBTCQuery = DateTime.MinValue; | |||
private static TimeSpan m_MaxBTCQueryTime = new TimeSpan(1, 0, 0); // Max query of every hour | |||
/// <summary> | |||
/// Gets the exchange rate for a given currency relative to USD | |||
/// </summary> | |||
/// <param name="target"></param> | |||
/// <returns></returns> | |||
public static decimal GetExchangeRate(CurrencyType target) | |||
{ | |||
decimal exchangeRate = 1; | |||
switch (target) | |||
{ | |||
case CurrencyType.USD: | |||
exchangeRate = 1; | |||
break; | |||
case CurrencyType.BTC: | |||
// get BTC usd price | |||
exchangeRate = GetBTCPrice(); | |||
break; | |||
} | |||
return exchangeRate; | |||
} | |||
public static decimal GetBTCPrice() | |||
{ | |||
DateTime curTime = DateTime.Now; | |||
if (curTime - m_LastBTCQuery > m_MaxBTCQueryTime) | |||
{ | |||
m_LastBTCQuery = curTime; | |||
string url = "http://api.bitcoincharts.com/v1/weighted_prices.json"; | |||
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); | |||
try | |||
{ | |||
WebResponse response = request.GetResponse(); | |||
using (Stream responseStream = response.GetResponseStream()) | |||
{ | |||
StreamReader reader = new StreamReader(responseStream, Encoding.UTF8); | |||
string jsonResult = reader.ReadToEnd(); | |||
JObject result = JsonConvert.DeserializeObject<JObject>(jsonResult); | |||
if (result["USD"] != null) | |||
{ | |||
string priceStr = result["USD"]["24h"].ToString(); | |||
decimal.TryParse(priceStr, out m_CurrentBTCPrice); | |||
} | |||
} | |||
} | |||
catch (WebException ex) | |||
{ | |||
WebResponse errorResponse = ex.Response; | |||
using (Stream responseStream = errorResponse.GetResponseStream()) | |||
{ | |||
StreamReader reader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8")); | |||
String errorText = reader.ReadToEnd(); | |||
} | |||
} | |||
} | |||
return m_CurrentBTCPrice; | |||
} | |||
} | |||
} |
@@ -0,0 +1,13 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Web; | |||
namespace Teknik.Utilities | |||
{ | |||
public enum CurrencyType | |||
{ | |||
USD, | |||
BTC | |||
} | |||
} |
@@ -105,6 +105,8 @@ | |||
</Reference> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<Compile Include="CurrencyHelper.cs" /> | |||
<Compile Include="CurrencyType.cs" /> | |||
<Compile Include="FileGenerateResult.cs" /> | |||
<Compile Include="HttpWebResponseResult.cs" /> | |||
<Compile Include="BundleExtensions.cs" /> |