diff --git a/.editorconfig b/.editorconfig index 3fc4e8a..407b45b 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,9 +1,7 @@ -root = true - [*] -charset = utf-8 -indent_style = space indent_size = 4 +indent_style = space end_of_line = crlf -trim_trailing_whitespace = false -insert_final_newline = true \ No newline at end of file + +[*.cshtml] +indent_size = 4 \ No newline at end of file diff --git a/.gitignore b/.gitignore index eaaade2..70e5420 100644 --- a/.gitignore +++ b/.gitignore @@ -4,26 +4,34 @@ # User-specific files *.suo *.user +*.userosscache *.sln.docstates +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + # Build results [Dd]ebug/ [Dd]ebugPublic/ [Rr]elease/ +[Rr]eleases/ x64/ -build/ +x86/ bld/ [Bb]in/ [Oo]bj/ +[Ll]og/ -# Roslyn cache directories -*.ide/ +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +wwwroot/ # MSTest test Results [Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* -#NUNIT +# NUNIT *.VisualState.xml TestResult.xml @@ -32,6 +40,11 @@ TestResult.xml [Rr]eleasePS/ dlldata.c +# DNX +project.lock.json +project.fragment.lock.json +artifacts/ + *_i.c *_p.c *_i.h @@ -64,14 +77,18 @@ _Chutzpah* ipch/ *.aps *.ncb +*.opendb *.opensdf *.sdf *.cachefile +*.VC.db +*.VC.VC.opendb # Visual Studio profiler *.psess *.vsp *.vspx +*.sap # TFS 2012 Local Workspace $tf/ @@ -84,7 +101,7 @@ _ReSharper*/ *.[Rr]e[Ss]harper *.DotSettings.user -# JustCode is a .NET coding addin-in +# JustCode is a .NET coding add-in .JustCode # TeamCity is a build add-in @@ -96,6 +113,7 @@ _TeamCity* # NCrunch _NCrunch_* .*crunch*.local.xml +nCrunchTemp_* # MightyMoose *.mm.* @@ -123,43 +141,63 @@ publish/ # Publish Web Output *.[Pp]ublish.xml *.azurePubxml -## TODO: Comment the next line if you want to checkin your -## web deploy settings but do note that will include unencrypted -## passwords +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted #*.pubxml +*.publishproj -# NuGet Packages Directory -packages/* -## TODO: If the tool you use requires repositories.config -## uncomment the next line -#!packages/repositories.config +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ -# Enable "build/" folder in the NuGet Packages folder since -# NuGet packages use it for MSBuild targets. -# This line needs to be after the ignore of the build folder -# (and the packages folder if the line above has been uncommented) -!packages/build/ +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets -# Windows Azure Build Output +# Microsoft Azure Build Output csx/ *.build.csdef -# Windows Store app package directory +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ # Others -sql/ -*.Cache ClientBin/ -[Ss]tyle[Cc]op.* ~$* *~ *.dbmdl *.dbproj.schemaview +*.jfm *.pfx *.publishsettings node_modules/ -bower_components/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ # RIA/Silverlight projects Generated_Code/ @@ -184,26 +222,45 @@ UpgradeLog*.htm # Microsoft Fakes FakesAssemblies/ -# LightSwitch generated files -GeneratedArtifacts/ -_Pvt_Extensions/ -ModelManifest.xml -/Teknik/ConnectionStrings.config -/Teknik/App_Data/Config.json -/.vs/config/applicationhost.config -/Teknik/TransformWebConfig/assist/Web.config -/Teknik/Properties/PublishProfiles/IIS.pubxml -/Teknik/App_Data/ConnectionStrings.config -/Teknik/App_Data/Config.json.old +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc /Teknik/App_Data/MachineKey.config -/.vs/Teknik/v15/sqlite3/storage.ide -/.vs/Teknik/v15/sqlite3/storage.ide-wal -/.vs/Teknik/v15/sqlite3/storage.ide-shm -/.vs/Teknik/v15/sqlite3/db.lock -/.vs/Teknik/v15/sqlite3 -/.vs/Teknik/v15/Server/sqlite3/storage.ide-wal -/.vs/Teknik/v15/Server/sqlite3/storage.ide-shm -/.vs/Teknik/v15/Server/sqlite3/storage.ide -/.vs/Teknik/v15/Server/sqlite3/db.lock -/.vs/Teknik/v15/Server/sqlite3 -/.vs/Teknik/v15 +/Teknik/App_Data/ConnectionStrings.config +/Teknik/App_Data/Config.json +/Teknik/appsettings.Production.json +/Teknik/appsettings.Development.json diff --git a/Utilities/Configuration/ApiConfig.cs b/Configuration/ApiConfig.cs similarity index 60% rename from Utilities/Configuration/ApiConfig.cs rename to Configuration/ApiConfig.cs index 91cdd57..8d9b9b8 100644 --- a/Utilities/Configuration/ApiConfig.cs +++ b/Configuration/ApiConfig.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Teknik.Configuration +namespace Teknik.Configuration { public class ApiConfig { diff --git a/Utilities/Configuration/BlogConfig.cs b/Configuration/BlogConfig.cs similarity index 84% rename from Utilities/Configuration/BlogConfig.cs rename to Configuration/BlogConfig.cs index d4c2435..f3dd869 100644 --- a/Utilities/Configuration/BlogConfig.cs +++ b/Configuration/BlogConfig.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; - -namespace Teknik.Configuration +namespace Teknik.Configuration { public class BlogConfig { diff --git a/Utilities/Configuration/Config.cs b/Configuration/Config.cs similarity index 88% rename from Utilities/Configuration/Config.cs rename to Configuration/Config.cs index 47b47ec..a089a9c 100644 --- a/Utilities/Configuration/Config.cs +++ b/Configuration/Config.cs @@ -1,10 +1,7 @@ +using Newtonsoft.Json; using System; using System.IO; using System.Threading; -using System.Web; -using System.Web.Caching; -using Newtonsoft.Json; -using Teknik.Utilities; using Teknik.Utilities.Cryptography; namespace Teknik.Configuration @@ -12,9 +9,13 @@ namespace Teknik.Configuration public class Config { private const string _ConfigCacheKey = "ConfigCache"; + private const string _ConfigFileName = "Config.json"; private static Config _Config { get; set; } - + private static string _FileHash { get; set; } + + private ReaderWriterLockSlim _ConfigRWLock; + private ReaderWriterLockSlim _ConfigFileRWLock; private JsonSerializerSettings _JsonSettings; private bool _DevEnvironment; @@ -117,6 +118,8 @@ namespace Teknik.Configuration public Config() { + _ConfigRWLock = new ReaderWriterLockSlim(); + _ConfigFileRWLock = new ReaderWriterLockSlim(); _JsonSettings = new JsonSerializerSettings(); _JsonSettings.Formatting = Formatting.Indented; @@ -168,39 +171,26 @@ namespace Teknik.Configuration return JsonConvert.SerializeObject(config, Formatting.Indented); } - public static Config Load() - { - HttpContext context = HttpContext.Current; - if (context != null) - _Config = (Config)context.Cache[_ConfigCacheKey]; - if (_Config == null) - { - string path = AppDomain.CurrentDomain.GetData("DataDirectory").ToString(); - _Config = Load(path); - context?.Cache.Insert(_ConfigCacheKey, _Config, new CacheDependency(path)); - } - return _Config; - } - public static Config Load(string path) { - Config config = new Config(); - if (!File.Exists(Path.Combine(path, "Config.json"))) - { - Save(Path.Combine(path, "Config.json"), config); - } - else - { - string configContents = File.ReadAllText(Path.Combine(path, "Config.json")); - config = Deserialize(configContents); - } - return config; - } + string newHash = string.Empty; + string fullPath = Path.Combine(path, _ConfigFileName); - public static void Save(Config config) - { - string path = AppDomain.CurrentDomain.GetData("DataDirectory").ToString(); - Save(Path.Combine(path, "Config.json"), config); + if (!File.Exists(fullPath)) + { + Config config = new Config(); + Save(fullPath, config); + } + + newHash = MD5.FileHash(fullPath); + + if (_Config == null || _FileHash == null || newHash != _FileHash) + { + string configContents = File.ReadAllText(fullPath); + _Config = Deserialize(configContents); + _FileHash = newHash; + } + return _Config; } public static void Save(string path, Config config) diff --git a/Configuration/Configuration.csproj b/Configuration/Configuration.csproj new file mode 100644 index 0000000..f57773a --- /dev/null +++ b/Configuration/Configuration.csproj @@ -0,0 +1,17 @@ + + + + netcoreapp2.1 + Teknik.Configuration + Teknik.Configuration + + + + + + + + + + + diff --git a/Utilities/Configuration/ContactConfig.cs b/Configuration/ContactConfig.cs similarity index 66% rename from Utilities/Configuration/ContactConfig.cs rename to Configuration/ContactConfig.cs index 05a28b9..66511cf 100644 --- a/Utilities/Configuration/ContactConfig.cs +++ b/Configuration/ContactConfig.cs @@ -1,11 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Net.Mail; - -namespace Teknik.Configuration +namespace Teknik.Configuration { public class ContactConfig { diff --git a/Utilities/Configuration/DatabaseConfig.cs b/Configuration/DatabaseConfig.cs similarity index 100% rename from Utilities/Configuration/DatabaseConfig.cs rename to Configuration/DatabaseConfig.cs diff --git a/Utilities/Configuration/EmailAccount.cs b/Configuration/EmailAccount.cs similarity index 80% rename from Utilities/Configuration/EmailAccount.cs rename to Configuration/EmailAccount.cs index 37cf81a..c5a493b 100644 --- a/Utilities/Configuration/EmailAccount.cs +++ b/Configuration/EmailAccount.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Teknik.Configuration +namespace Teknik.Configuration { public class EmailAccount { diff --git a/Utilities/Configuration/EmailConfig.cs b/Configuration/EmailConfig.cs similarity index 84% rename from Utilities/Configuration/EmailConfig.cs rename to Configuration/EmailConfig.cs index f698e5d..b2d2c93 100644 --- a/Utilities/Configuration/EmailConfig.cs +++ b/Configuration/EmailConfig.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; - -namespace Teknik.Configuration +namespace Teknik.Configuration { public class EmailConfig { diff --git a/Utilities/Configuration/GitConfig.cs b/Configuration/GitConfig.cs similarity index 79% rename from Utilities/Configuration/GitConfig.cs rename to Configuration/GitConfig.cs index a1f9448..596e35c 100644 --- a/Utilities/Configuration/GitConfig.cs +++ b/Configuration/GitConfig.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Teknik.Configuration +namespace Teknik.Configuration { public class GitConfig { diff --git a/Utilities/Configuration/IRCConfig.cs b/Configuration/IRCConfig.cs similarity index 70% rename from Utilities/Configuration/IRCConfig.cs rename to Configuration/IRCConfig.cs index 4249ffc..1df9efc 100644 --- a/Utilities/Configuration/IRCConfig.cs +++ b/Configuration/IRCConfig.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Teknik.Configuration +namespace Teknik.Configuration { public class IRCConfig { diff --git a/Utilities/Configuration/LoggingConfig.cs b/Configuration/LoggingConfig.cs similarity index 89% rename from Utilities/Configuration/LoggingConfig.cs rename to Configuration/LoggingConfig.cs index 0fd5563..a36cae3 100644 --- a/Utilities/Configuration/LoggingConfig.cs +++ b/Configuration/LoggingConfig.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; - -namespace Teknik.Configuration +namespace Teknik.Configuration { public class LoggingConfig { diff --git a/Utilities/Configuration/PasteConfig.cs b/Configuration/PasteConfig.cs similarity index 75% rename from Utilities/Configuration/PasteConfig.cs rename to Configuration/PasteConfig.cs index 4afc356..d6f04a8 100644 --- a/Utilities/Configuration/PasteConfig.cs +++ b/Configuration/PasteConfig.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Teknik.Configuration +namespace Teknik.Configuration { public class PasteConfig { diff --git a/Utilities/Configuration/PiwikConfig.cs b/Configuration/PiwikConfig.cs similarity index 75% rename from Utilities/Configuration/PiwikConfig.cs rename to Configuration/PiwikConfig.cs index 0a78db7..d93b4fc 100644 --- a/Utilities/Configuration/PiwikConfig.cs +++ b/Configuration/PiwikConfig.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Teknik.Configuration +namespace Teknik.Configuration { public class PiwikConfig { diff --git a/Utilities/Configuration/PodcastConfig.cs b/Configuration/PodcastConfig.cs similarity index 87% rename from Utilities/Configuration/PodcastConfig.cs rename to Configuration/PodcastConfig.cs index cf3cc4a..ad17967 100644 --- a/Utilities/Configuration/PodcastConfig.cs +++ b/Configuration/PodcastConfig.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Web; +using System.IO; namespace Teknik.Configuration { diff --git a/Utilities/Configuration/ShortenerConfig.cs b/Configuration/ShortenerConfig.cs similarity index 73% rename from Utilities/Configuration/ShortenerConfig.cs rename to Configuration/ShortenerConfig.cs index dd3a4a6..8f7326c 100644 --- a/Utilities/Configuration/ShortenerConfig.cs +++ b/Configuration/ShortenerConfig.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; - -namespace Teknik.Configuration +namespace Teknik.Configuration { public class ShortenerConfig { diff --git a/Utilities/Configuration/StatsConfig.cs b/Configuration/StatsConfig.cs similarity index 82% rename from Utilities/Configuration/StatsConfig.cs rename to Configuration/StatsConfig.cs index f745d43..d9297d3 100644 --- a/Utilities/Configuration/StatsConfig.cs +++ b/Configuration/StatsConfig.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Teknik.Configuration +namespace Teknik.Configuration { public class StatsConfig { diff --git a/Utilities/Configuration/StreamConfig.cs b/Configuration/StreamConfig.cs similarity index 71% rename from Utilities/Configuration/StreamConfig.cs rename to Configuration/StreamConfig.cs index 67d6e5a..2090111 100644 --- a/Utilities/Configuration/StreamConfig.cs +++ b/Configuration/StreamConfig.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Collections.Generic; namespace Teknik.Configuration { diff --git a/Utilities/Configuration/UploadConfig.cs b/Configuration/UploadConfig.cs similarity index 97% rename from Utilities/Configuration/UploadConfig.cs rename to Configuration/UploadConfig.cs index f60514a..9a9bb54 100644 --- a/Utilities/Configuration/UploadConfig.cs +++ b/Configuration/UploadConfig.cs @@ -1,8 +1,5 @@ -using System; using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Web; namespace Teknik.Configuration { diff --git a/Utilities/Configuration/UserConfig.cs b/Configuration/UserConfig.cs similarity index 90% rename from Utilities/Configuration/UserConfig.cs rename to Configuration/UserConfig.cs index 60a602f..8de0d1c 100644 --- a/Utilities/Configuration/UserConfig.cs +++ b/Configuration/UserConfig.cs @@ -1,10 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Teknik.Utilities; - namespace Teknik.Configuration { public class UserConfig diff --git a/Utilities/Configuration/VaultConfig.cs b/Configuration/VaultConfig.cs similarity index 66% rename from Utilities/Configuration/VaultConfig.cs rename to Configuration/VaultConfig.cs index 7680af9..d75e996 100644 --- a/Utilities/Configuration/VaultConfig.cs +++ b/Configuration/VaultConfig.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; - -namespace Teknik.Configuration +namespace Teknik.Configuration { public class VaultConfig { diff --git a/GitVersionConfig.yaml b/GitVersionConfig.yaml deleted file mode 100644 index aa7fc6f..0000000 --- a/GitVersionConfig.yaml +++ /dev/null @@ -1,2 +0,0 @@ -assembly-versioning-scheme: MajorMinorPatch -next-version: 2.0.6 diff --git a/Utilities/Logging/LogMessage.cs b/Logging/LogMessage.cs similarity index 86% rename from Utilities/Logging/LogMessage.cs rename to Logging/LogMessage.cs index 59fee83..6a55d6a 100644 --- a/Utilities/Logging/LogMessage.cs +++ b/Logging/LogMessage.cs @@ -1,8 +1,5 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using System; using Teknik.Utilities; namespace Teknik.Logging @@ -21,7 +18,7 @@ namespace Teknik.Logging public void SetDefaults() { - Level = LogLevel.Info; + Level = LogLevel.Information; EntryDate = DateTime.Now; Message = string.Empty; Exception = null; diff --git a/Logging/Logger.cs b/Logging/Logger.cs new file mode 100644 index 0000000..169baca --- /dev/null +++ b/Logging/Logger.cs @@ -0,0 +1,161 @@ +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Mail; +using System.Text; +using Teknik.Configuration; +using Teknik.Utilities; + +namespace Teknik.Logging +{ + public class Logger : ILogger + { + private static readonly object Locker = new object(); + + private readonly string _name; + private readonly Config _config; + + public Logger(string name, Config config) + { + _name = name; + _config = config; + } + + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) + { + if (!IsEnabled(logLevel)) + return; + + // write an entry to the logs + LogMessage log = new LogMessage(); + log.Level = logLevel; + log.Message = formatter(state, exception); + log.Exception = exception; + + WriteLogMessage(log); + } + + public bool IsEnabled(LogLevel logLevel) + { + if (_config.LoggingConfig.Enabled) + { + // Do we want to write a log for this level? (Default to Error) + LogLevel minLogLevel = LogLevel.Error; + Enum.TryParse(_config.LoggingConfig.LogLevel, out minLogLevel); + if (logLevel >= minLogLevel) + return true; + } + return false; + } + + public IDisposable BeginScope(TState state) + { + return null; + } + + private void WriteLogMessage(LogMessage log) + { + + try + { + // Lock the file processing so only 1 thread is working on the log file at a time + lock (Locker) + { + if (!Directory.Exists(_config.LoggingConfig.OutputDirectory)) + { + Directory.CreateDirectory(_config.LoggingConfig.OutputDirectory); + } + // Get current log file + string fileName = Constants.LOG_FILE_NAME_PREFIX + Constants.LOG_FILE_EXT; + string logFile = Path.Combine(_config.LoggingConfig.OutputDirectory, fileName); + + if (File.Exists(logFile)) + { + // File already exists, so lets see if we need to rotate it + if (_config.LoggingConfig.RotateLogs) + { + FileInfo info = new FileInfo(logFile); + if (_config.LoggingConfig.MaxSize < info.Length && _config.LoggingConfig.MaxSize > 0) + { + // File is too large, so let's create a new name for it based on todays date + string newFileName = Constants.LOG_FILE_NAME_PREFIX + "_" + DateTime.Now.ToString("yyyyMMdd") + Constants.LOG_FILE_EXT; + newFileName = FileHelper.MakeUniqueFilename(newFileName, _config.LoggingConfig.OutputDirectory); + string newLog = Path.Combine(_config.LoggingConfig.OutputDirectory, newFileName); + + // Move the current file to the new file + File.Move(logFile, newLog); + } + + // Make sure we have less than the max number of logs + List totalFiles = Directory.GetFiles(_config.LoggingConfig.OutputDirectory, string.Format("{0}*{1}", Constants.LOG_FILE_NAME_PREFIX, Constants.LOG_FILE_EXT), SearchOption.TopDirectoryOnly).ToList(); + if (totalFiles.Count + 1 > _config.LoggingConfig.MaxCount && _config.LoggingConfig.MaxCount > 0) + { + // We will have too many logs, so let's remove the last one + totalFiles.Sort(); + string fileToRemove = totalFiles[totalFiles.Count - 1]; + File.Delete(fileToRemove); + } + } + } + + // We have rotated if needed, so let's write the entry + File.AppendAllText(logFile, log.ToString() + Environment.NewLine); + } + } + catch (Exception) { } // If we throw when writing the log, still try to send the email if needed + + try + { + // Send Email Message if enabled + if (_config.LoggingConfig.SendEmail) + { + // Do we want to send an email for this level? (Default to error) + LogLevel minEmailLevel = LogLevel.Error; + Enum.TryParse(_config.LoggingConfig.EmailLevel, out minEmailLevel); + if (log.Level >= minEmailLevel) + { + string subject = string.Format("{0} Log Message", log.Level); + string message = "Message: " + log.Message; + if (log.Exception != null) + { + message += Environment.NewLine + Environment.NewLine + "Exception: " + log.Exception.GetFullMessage(true, true); + } + SendErrorEmail(subject, message); + } + } + } + catch (Exception) + { + // Can't do anything about it. :/ + } + } + + private void SendErrorEmail(string subject, string message) + { + try + { + // Let's also email the message to support + SmtpClient client = new SmtpClient(); + client.Host = _config.LoggingConfig.SenderAccount.Host; + client.Port = _config.LoggingConfig.SenderAccount.Port; + client.EnableSsl = _config.LoggingConfig.SenderAccount.SSL; + client.DeliveryMethod = SmtpDeliveryMethod.Network; + client.UseDefaultCredentials = true; + client.Credentials = new System.Net.NetworkCredential(_config.LoggingConfig.SenderAccount.Username, _config.LoggingConfig.SenderAccount.Password); + client.Timeout = 5000; + + MailMessage mail = new MailMessage(_config.LoggingConfig.SenderAccount.EmailAddress, _config.LoggingConfig.RecipientEmailAddress); + mail.Subject = subject; + mail.Body = message; + mail.BodyEncoding = UTF8Encoding.UTF8; + mail.DeliveryNotificationOptions = DeliveryNotificationOptions.Never; + + client.Send(mail); + } + catch (Exception ex) { /* don't handle something in the handler */ + } + } + } +} diff --git a/Logging/LoggerExtensions.cs b/Logging/LoggerExtensions.cs new file mode 100644 index 0000000..6ea03a5 --- /dev/null +++ b/Logging/LoggerExtensions.cs @@ -0,0 +1,17 @@ +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Text; +using Teknik.Configuration; + +namespace Teknik.Logging +{ + public static class LoggerExtensions + { + public static ILoggerFactory AddLogger(this ILoggerFactory loggerFactory, Config config) + { + loggerFactory.AddProvider(new LoggerProvider(config)); + return loggerFactory; + } + } +} diff --git a/Logging/LoggerProvider.cs b/Logging/LoggerProvider.cs new file mode 100644 index 0000000..9d8f321 --- /dev/null +++ b/Logging/LoggerProvider.cs @@ -0,0 +1,30 @@ +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Text; +using Teknik.Configuration; + +namespace Teknik.Logging +{ + public class LoggerProvider : ILoggerProvider + { + private readonly Config _config; + private readonly ConcurrentDictionary _loggers = new ConcurrentDictionary(); + + public LoggerProvider(Config config) + { + _config = config; + } + + public ILogger CreateLogger(string categoryName) + { + return _loggers.GetOrAdd(categoryName, name => new Logger(name, _config)); + } + + public void Dispose() + { + _loggers.Clear(); + } + } +} diff --git a/Logging/Logging.csproj b/Logging/Logging.csproj new file mode 100644 index 0000000..6278cb6 --- /dev/null +++ b/Logging/Logging.csproj @@ -0,0 +1,14 @@ + + + + netcoreapp2.1 + Teknik.Logging + Teknik.Logging + + + + + + + + diff --git a/MailService/HMailService.cs b/MailService/HMailService.cs new file mode 100644 index 0000000..29dafae --- /dev/null +++ b/MailService/HMailService.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Teknik.MailService +{ + public class HMailService : MailService + { + private readonly hMailServer.Application _App; + + private string _Username { get; set; } + private string _Password { get; set; } + private string _Domain { get; set; } + + private string _CounterServer { get; set; } + private string _CounterDatabase { get; set; } + private string _CounterUsername { get; set; } + private string _CounterPassword { get; set; } + private int _CounterPort { get; set; } + + public HMailService(string username, string password, string domain, string counterServer, string counterDatabase, string counterUsername, string counterPassword, int counterPort) + { + _Username = username; + _Password = password; + _Domain = domain; + + _CounterServer = counterServer; + _CounterDatabase = counterDatabase; + _CounterUsername = counterUsername; + _CounterPassword = counterPassword; + _CounterPort = counterPort; + + _App = InitApp(); + } + + public override void CreateAccount(string username, string password, int size) + { + var domain = _App.Domains.ItemByName[_Domain]; + var newAccount = domain.Accounts.Add(); + newAccount.Address = username; + newAccount.Password = password; + newAccount.Active = true; + newAccount.MaxSize = size; + + newAccount.Save(); + } + + public override bool AccountExists(string username) + { + try + { + GetAccount(username); + // We didn't error out, so the email exists + return true; + } + catch { } + return false; + } + + public override void Delete(string username) + { + throw new NotImplementedException(); + } + + public override void Enable(string username) + { + EditActivity(username, true); + } + + public override void Disable(string username) + { + EditActivity(username, false); + } + + public override void EditActivity(string username, bool active) + { + var account = GetAccount(username); + account.Active = active; + account.Save(); + } + + public override void EditMaxEmailsPerDay(string username, int maxPerDay) + { + //We need to check the actual git database + MysqlDatabase mySQL = new MysqlDatabase(_CounterServer, _CounterDatabase, _CounterUsername, _CounterPassword, _CounterPort); + string sql = @"INSERT INTO mailcounter.counts (qname, lastdate, qlimit, count) VALUES ({1}, NOW(), {0}, 0) + ON DUPLICATE KEY UPDATE qlimit = {0}"; + mySQL.Execute(sql, new object[] { maxPerDay, username }); + } + + public override void EditMaxSize(string username, int size) + { + var account = GetAccount(username); + account.MaxSize = size; + account.Save(); + } + + public override void EditPassword(string username, string password) + { + var account = GetAccount(username); + account.Password = password; + account.Save(); + } + + public override DateTime LastActive(string username) + { + var account = GetAccount(username); + return (DateTime)account.LastLogonTime; + } + + private hMailServer.Application InitApp() + { + var app = new hMailServer.Application(); + app.Connect(); + app.Authenticate(_Username, _Password); + + return app; + } + + private hMailServer.Account GetAccount(string username) + { + var domain = _App.Domains.ItemByName[_Domain]; + return domain.Accounts.ItemByAddress[username]; + } + } +} diff --git a/MailService/IMailService.cs b/MailService/IMailService.cs new file mode 100644 index 0000000..ee902df --- /dev/null +++ b/MailService/IMailService.cs @@ -0,0 +1,27 @@ +using System; + +namespace Teknik.MailService +{ + public interface IMailService + { + bool AccountExists(string username); + + DateTime LastActive(string username); + + void CreateAccount(string username, string password, int size); + + void EditActivity(string username, bool active); + + void EditPassword(string username, string password); + + void EditMaxSize(string username, int size); + + void EditMaxEmailsPerDay(string username, int maxPerDay); + + void Enable(string username); + + void Disable(string username); + + void Delete(string username); + } +} diff --git a/MailService/MailService.cs b/MailService/MailService.cs new file mode 100644 index 0000000..7eb519e --- /dev/null +++ b/MailService/MailService.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Teknik.MailService +{ + public abstract class MailService : IMailService + { + public abstract void CreateAccount(string username, string password, int size); + + public abstract bool AccountExists(string username); + + public abstract void Delete(string username); + + public abstract void Disable(string username); + + public abstract void EditActivity(string username, bool active); + + public abstract void EditMaxEmailsPerDay(string username, int maxPerDay); + + public abstract void EditMaxSize(string username, int size); + + public abstract void EditPassword(string username, string password); + + public abstract void Enable(string username); + + public abstract DateTime LastActive(string username); + } +} diff --git a/MailService/MailService.csproj b/MailService/MailService.csproj new file mode 100644 index 0000000..293f231 --- /dev/null +++ b/MailService/MailService.csproj @@ -0,0 +1,19 @@ + + + + netstandard2.0 + Teknik.MailService + Teknik.MailService + + + + + + + + + lib\Teknik.hMailServer.dll + + + + diff --git a/MailService/MysqlDatabase.cs b/MailService/MysqlDatabase.cs new file mode 100644 index 0000000..f1100a5 --- /dev/null +++ b/MailService/MysqlDatabase.cs @@ -0,0 +1,173 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using MySql.Data.MySqlClient; + +namespace Teknik.MailService +{ + public class MysqlDatabase + { + public event EventHandler MysqlErrorEvent; + + private bool Connected { get; set; } + private MySqlConnection Connection { get; set; } + private ReaderWriterLockSlim DatabaseLock { get; set; } + + public MysqlDatabase(string server, string database, string username, string password, int port) + { + Connected = false; + Connection = null; + DatabaseLock = new ReaderWriterLockSlim(); + Connect(server, database, username, password, port); + } + + public List> Query(string query, params object[] args) + { + List> rows = new List>(); + if (Connected) + { + DatabaseLock.EnterWriteLock(); + MySqlCommand cmd = PrepareQuery(query, args); + try + { + MySqlDataReader reader = cmd.ExecuteReader(); + while (reader.Read()) + { + Dictionary row = new Dictionary(); + for (int i = 0; i < reader.FieldCount; i++) + { + row.Add(reader.GetName(i), reader.GetValue(i)); + } + rows.Add(row); + } + reader.Close(); + } + catch (MySqlException exception) + { + if (MysqlErrorEvent != null) + { + MysqlErrorEvent(this, exception.Message); + } + } + catch (Exception exception) + { + if (MysqlErrorEvent != null) + { + MysqlErrorEvent(this, exception.Message); + } + } + DatabaseLock.ExitWriteLock(); + } + return rows; + } + + public object ScalarQuery(string query, params object[] args) + { + if (Connected) + { + DatabaseLock.EnterWriteLock(); + MySqlCommand cmd = PrepareQuery(query, args); + object result = null; + try + { + + result = cmd.ExecuteScalar(); + } + catch (MySqlException exception) + { + if (MysqlErrorEvent != null) + { + MysqlErrorEvent(this, exception.Message); + } + } + catch (Exception exception) + { + if (MysqlErrorEvent != null) + { + MysqlErrorEvent(this, exception.Message); + } + } + DatabaseLock.ExitWriteLock(); + return result; + } + return null; + } + + public void Execute(string query, params object[] args) + { + if (Connected) + { + DatabaseLock.EnterWriteLock(); + MySqlCommand cmd = PrepareQuery(query, args); + try + { + int result = cmd.ExecuteNonQuery(); + } + catch (MySqlException exception) + { + if (MysqlErrorEvent != null) + { + MysqlErrorEvent(this, exception.Message); + } + } + catch (Exception exception) + { + if (MysqlErrorEvent != null) + { + MysqlErrorEvent(this, exception.Message); + } + } + DatabaseLock.ExitWriteLock(); + } + } + + private void Connect(string server, string database, string username, string password, int port) + { + if (Connection == null) + { + if (!string.IsNullOrEmpty(server) && !string.IsNullOrEmpty(database) && !string.IsNullOrEmpty(username) && !string.IsNullOrEmpty(password)) + { + string strCon = string.Format("Server={0}; database={1}; user={2}; password={3}; port={4}; charset=utf8; Allow Zero Datetime=true;", server, database, username, password, port); + Connection = new MySqlConnection(strCon); + try + { + Connection.Open(); + Connected = true; + } + catch (MySqlException ex) + { + Connected = false; + } + } + } + } + + private void Disconnect() + { + if (Connection != null && Connected) + { + Connected = false; + Connection.Close(); + } + } + + private MySqlCommand PrepareQuery(string query, object[] args) + { + if (Connected) + { + MySqlCommand cmd = new MySqlCommand(); + cmd.Connection = Connection; + for (int i = 0; i < args.Length; i++) + { + string param = "{" + i + "}"; + string paramName = "@DBVar_" + i; + query = query.Replace(param, paramName); + cmd.Parameters.AddWithValue(paramName, args[i]); + } + cmd.CommandText = query; + return cmd; + } + return null; + } + } +} \ No newline at end of file diff --git a/MailService/lib/Teknik.hMailServer.dll b/MailService/lib/Teknik.hMailServer.dll new file mode 100644 index 0000000..b58cd28 Binary files /dev/null and b/MailService/lib/Teknik.hMailServer.dll differ diff --git a/Piwik/Piwik.csproj b/Piwik/Piwik.csproj new file mode 100644 index 0000000..544abc7 --- /dev/null +++ b/Piwik/Piwik.csproj @@ -0,0 +1,13 @@ + + + + netcoreapp2.1 + Teknik.Piwik + Teknik.Piwik + + + + + + + diff --git a/Piwik/Reporting.cs b/Piwik/Reporting.cs new file mode 100644 index 0000000..d75945b --- /dev/null +++ b/Piwik/Reporting.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Teknik.Configuration; + +namespace Teknik.Piwik +{ + public static class Reporting + { + public static List GetVisitSummaryByDays(Config config, int days) + { + List visitorData = new List(); + try + { + if (config.PiwikConfig.Enabled) + { + //PiwikAnalytics.URL = config.PiwikConfig.API; + //VisitsSummary visitSummary = new VisitsSummary(); + //visitSummary.setTokenAuth(config.PiwikConfig.TokenAuth); + + //Hashtable results = visitSummary.Get( + // config.PiwikConfig.SiteId, + // PiwikPeriod.DAY, + // RelativeRangeDate.LAST(days) + // ); + + //foreach (string period in results.Keys) + //{ + // // Create a new object to return + // VisitorData data = new VisitorData(); + + // // Set Period Date + // DateTime date = new DateTime(1900, 1, 1); + // DateTime.TryParse(period, out date); + // data.Date = date; + + // // Pull Out Data + // if (results[period].GetType() == typeof(Hashtable)) + // { + // Hashtable result = (Hashtable) results[period]; + + // int UniqueVisitors = 0; + // int.TryParse(result["nb_uniq_visitors"].ToString(), out UniqueVisitors); + // data.UniqueVisitors = UniqueVisitors; + + // int visits = 0; + // int.TryParse(result[VisitsSummary.NB_VISITS].ToString(), out visits); + // data.Visits = visits; + + // int VisitsConverted = 0; + // int.TryParse(result[VisitsSummary.NB_VISITS_CONVERTED].ToString(), out VisitsConverted); + // data.VisitsConverted = VisitsConverted; + + // int Actions = 0; + // int.TryParse(result[VisitsSummary.NB_ACTIONS].ToString(), out Actions); + // data.Actions = Actions; + + // decimal ActionsPerVisit = 0; + // decimal.TryParse(result[VisitsSummary.NB_ACTIONS_PER_VISIT].ToString(), out ActionsPerVisit); + // data.ActionsPerVisit = ActionsPerVisit; + + // int MaxActions = 0; + // int.TryParse(result[VisitsSummary.MAX_ACTIONS].ToString(), out MaxActions); + // data.MaxActions = MaxActions; + + // int BounceCount = 0; + // int.TryParse(result[VisitsSummary.BOUNCE_COUNT].ToString(), out BounceCount); + // data.BounceCount = BounceCount; + + // data.BounceRate = result[VisitsSummary.BOUNCE_RATE].ToString(); + + // int AverageTimeOnSite = 0; + // int.TryParse(result[VisitsSummary.AVG_TIME_ON_SITE].ToString(), out AverageTimeOnSite); + // data.AverageTimeOnSite = AverageTimeOnSite; + + // int VisitLengthTotal = 0; + // int.TryParse(result[VisitsSummary.SUM_VISIT_LENGTH].ToString(), out VisitLengthTotal); + // data.VisitLengthTotal = VisitLengthTotal; + // } + + // visitorData.Add(data); + //} + } + } + catch (Exception ex) + { + + } + + return visitorData; + } + } +} diff --git a/Piwik/Tracking.cs b/Piwik/Tracking.cs new file mode 100644 index 0000000..3c72336 --- /dev/null +++ b/Piwik/Tracking.cs @@ -0,0 +1,93 @@ +using System; +using System.Web; +using Teknik.Configuration; +using Teknik.Utilities; + +namespace Teknik.Piwik +{ + public static class Tracking + { + public static void TrackPageView(Config config, string title, string sub, string clientIp, string url, string urlReferrer, string userAgent, int pixelWidth, int pixelHeight, bool hasCookies, string acceptLang, bool hasJava) + { + try + { + if (config.PiwikConfig.Enabled) + { + if (config.DevEnvironment) + { + sub = "dev - " + sub; + } + + //PiwikTracker.URL = config.PiwikConfig.Url; + //PiwikTracker tracker = new PiwikTracker(config.PiwikConfig.SiteId, config.PiwikConfig.Url); + + //// Set Request Info + //tracker.setIp(clientIp); + //tracker.setTokenAuth(config.PiwikConfig.TokenAuth); + + //tracker.setUserAgent(userAgent); + + //// Set browser info + //tracker.setResolution(pixelWidth, pixelHeight); + //tracker.setBrowserHasCookies(hasCookies); + //if (!string.IsNullOrEmpty(acceptLang)) + // tracker.setBrowserLanguage(acceptLang); + //tracker.setPlugins(new BrowserPlugins {java = hasJava}); + + //// Get Referral + //if (!string.IsNullOrEmpty(urlReferrer)) + // tracker.setUrlReferrer(urlReferrer); + + //if (!string.IsNullOrEmpty(url)) + // tracker.setUrl(url); + + //// Send the tracking request + //tracker.doTrackPageView(string.Format("{0}/{1}", sub, title)); + } + } + catch (Exception ex) + { + + } + } + + public static void TrackDownload(Config config, string userAgent, string clientIp, string url, string urlReferrer) + { + //TrackAction(config. PiwikTracker.ActionType.download, userAgent, clientIp, url, urlReferrer); + } + + public static void TrackLink(Config config, string userAgent, string clientIp, string url, string urlReferrer) + { + //TrackAction(config.PiwikTracker.ActionType.link, userAgent, clientIp, url, urlReferrer); + } + + //private static void TrackAction(Config config, PiwikTracker.ActionType type, string userAgent, string clientIp, string url, string urlReferrer) + //{ + // try + // { + // if (config.PiwikConfig.Enabled) + // { + // PiwikTracker tracker = new PiwikTracker(config.PiwikConfig.SiteId, config.PiwikConfig.Url); + + // tracker.setUserAgent(userAgent); + + // tracker.setIp(clientIp); + // tracker.setTokenAuth(config.PiwikConfig.TokenAuth); + + // // Get Referral + // if (!string.IsNullOrEmpty(urlReferrer)) + // tracker.setUrlReferrer(urlReferrer); + + // if (!string.IsNullOrEmpty(url)) + // tracker.setUrl(url); + + // tracker.doTrackAction(url, type); + // } + // } + // catch (Exception ex) + // { + + // } + //} + } +} diff --git a/Utilities/Piwik/VisitorData.cs b/Piwik/VisitorData.cs similarity index 100% rename from Utilities/Piwik/VisitorData.cs rename to Piwik/VisitorData.cs diff --git a/Teknik.sln b/Teknik.sln index 333abcc..64ba001 100644 --- a/Teknik.sln +++ b/Teknik.sln @@ -1,125 +1,62 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26430.15 +VisualStudioVersion = 15.0.27512.0 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Teknik", "Teknik\Teknik.csproj", "{B20317CD-76C6-4A7B-BCE1-E4BEF8E4F964}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Teknik", "Teknik\Teknik.csproj", "{1E52F0D0-9E89-4022-A905-C685EF3564E1}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{725ABF52-FD44-4682-81BB-D93598787643}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Configuration", "Configuration\Configuration.csproj", "{7A1F40CA-7C37-4B7B-973A-CDCDD424F31F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Utilities", "Utilities\Utilities.csproj", "{DD521101-7F10-407A-9788-49283D946FDA}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Logging", "Logging\Logging.csproj", "{3CAB11F5-9B07-4D17-BB00-725149087AB0}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C208CBF0-078E-409D-A433-DC1BC15248CE}" ProjectSection(SolutionItems) = preProject .editorconfig = .editorconfig - GitVersionConfig.yaml = GitVersionConfig.yaml - README.md = README.md + .gitattributes = .gitattributes + .gitignore = .gitignore EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServerMaint", "ServerMaint\ServerMaint.csproj", "{E08975F9-1B84-41B0-875A-CEC9778C4F9E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Piwik", "Piwik\Piwik.csproj", "{F8823907-092C-4055-9F8E-D6756793C24A}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{783361EC-DCD6-4A34-8479-5476DF752C34}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Utilities", "Utilities\Utilities\Utilities.csproj", "{F45DE6FC-3754-4954-A20A-4277362CC6C1}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Logging", "Utilities\Logging\Logging.csproj", "{77E865FD-F08B-4F07-9676-BC2FDCC7244C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Piwik", "Utilities\Piwik\Piwik.csproj", "{C492C2C6-D45A-498B-84A2-6D4C8BF9DE77}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Configuration", "Utilities\Configuration\Configuration.csproj", "{F0DA1B67-AF92-4B4A-8669-7E81645FF996}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TeknikStreaming", "TeknikStreaming\TeknikStreaming.csproj", "{7695CE9A-A0DB-4D73-BC9B-2206481F0254}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{FAC9FE6E-9AA9-45AD-AA72-40DDF7DC44C6}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UtilitiesTests", "UtilitiesTests\UtilitiesTests.csproj", "{88DEB506-3F7E-4B39-8264-861976DC7434}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TeknikTests", "TeknikTests\TeknikTests.csproj", "{9D7A805E-2629-476E-B36A-040AD332C7DC}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MailService", "MailService\MailService.csproj", "{03636C30-DA61-4307-8934-2FCC3BAC3255}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 Release|Any CPU = Release|Any CPU - Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {B20317CD-76C6-4A7B-BCE1-E4BEF8E4F964}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B20317CD-76C6-4A7B-BCE1-E4BEF8E4F964}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B20317CD-76C6-4A7B-BCE1-E4BEF8E4F964}.Debug|x64.ActiveCfg = Debug|x64 - {B20317CD-76C6-4A7B-BCE1-E4BEF8E4F964}.Debug|x64.Build.0 = Debug|x64 - {B20317CD-76C6-4A7B-BCE1-E4BEF8E4F964}.Debug|x64.Deploy.0 = Debug|x64 - {B20317CD-76C6-4A7B-BCE1-E4BEF8E4F964}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B20317CD-76C6-4A7B-BCE1-E4BEF8E4F964}.Release|Any CPU.Build.0 = Release|Any CPU - {B20317CD-76C6-4A7B-BCE1-E4BEF8E4F964}.Release|x64.ActiveCfg = Release|x64 - {B20317CD-76C6-4A7B-BCE1-E4BEF8E4F964}.Release|x64.Build.0 = Release|x64 - {E08975F9-1B84-41B0-875A-CEC9778C4F9E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E08975F9-1B84-41B0-875A-CEC9778C4F9E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E08975F9-1B84-41B0-875A-CEC9778C4F9E}.Debug|x64.ActiveCfg = Debug|Any CPU - {E08975F9-1B84-41B0-875A-CEC9778C4F9E}.Debug|x64.Build.0 = Debug|Any CPU - {E08975F9-1B84-41B0-875A-CEC9778C4F9E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E08975F9-1B84-41B0-875A-CEC9778C4F9E}.Release|Any CPU.Build.0 = Release|Any CPU - {E08975F9-1B84-41B0-875A-CEC9778C4F9E}.Release|x64.ActiveCfg = Release|Any CPU - {E08975F9-1B84-41B0-875A-CEC9778C4F9E}.Release|x64.Build.0 = Release|Any CPU - {F45DE6FC-3754-4954-A20A-4277362CC6C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F45DE6FC-3754-4954-A20A-4277362CC6C1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F45DE6FC-3754-4954-A20A-4277362CC6C1}.Debug|x64.ActiveCfg = Debug|Any CPU - {F45DE6FC-3754-4954-A20A-4277362CC6C1}.Debug|x64.Build.0 = Debug|Any CPU - {F45DE6FC-3754-4954-A20A-4277362CC6C1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F45DE6FC-3754-4954-A20A-4277362CC6C1}.Release|Any CPU.Build.0 = Release|Any CPU - {F45DE6FC-3754-4954-A20A-4277362CC6C1}.Release|x64.ActiveCfg = Release|Any CPU - {F45DE6FC-3754-4954-A20A-4277362CC6C1}.Release|x64.Build.0 = Release|Any CPU - {77E865FD-F08B-4F07-9676-BC2FDCC7244C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {77E865FD-F08B-4F07-9676-BC2FDCC7244C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {77E865FD-F08B-4F07-9676-BC2FDCC7244C}.Debug|x64.ActiveCfg = Debug|Any CPU - {77E865FD-F08B-4F07-9676-BC2FDCC7244C}.Debug|x64.Build.0 = Debug|Any CPU - {77E865FD-F08B-4F07-9676-BC2FDCC7244C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {77E865FD-F08B-4F07-9676-BC2FDCC7244C}.Release|Any CPU.Build.0 = Release|Any CPU - {77E865FD-F08B-4F07-9676-BC2FDCC7244C}.Release|x64.ActiveCfg = Release|Any CPU - {77E865FD-F08B-4F07-9676-BC2FDCC7244C}.Release|x64.Build.0 = Release|Any CPU - {C492C2C6-D45A-498B-84A2-6D4C8BF9DE77}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C492C2C6-D45A-498B-84A2-6D4C8BF9DE77}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C492C2C6-D45A-498B-84A2-6D4C8BF9DE77}.Debug|x64.ActiveCfg = Debug|Any CPU - {C492C2C6-D45A-498B-84A2-6D4C8BF9DE77}.Debug|x64.Build.0 = Debug|Any CPU - {C492C2C6-D45A-498B-84A2-6D4C8BF9DE77}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C492C2C6-D45A-498B-84A2-6D4C8BF9DE77}.Release|Any CPU.Build.0 = Release|Any CPU - {C492C2C6-D45A-498B-84A2-6D4C8BF9DE77}.Release|x64.ActiveCfg = Release|Any CPU - {C492C2C6-D45A-498B-84A2-6D4C8BF9DE77}.Release|x64.Build.0 = Release|Any CPU - {F0DA1B67-AF92-4B4A-8669-7E81645FF996}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F0DA1B67-AF92-4B4A-8669-7E81645FF996}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F0DA1B67-AF92-4B4A-8669-7E81645FF996}.Debug|x64.ActiveCfg = Debug|Any CPU - {F0DA1B67-AF92-4B4A-8669-7E81645FF996}.Debug|x64.Build.0 = Debug|Any CPU - {F0DA1B67-AF92-4B4A-8669-7E81645FF996}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F0DA1B67-AF92-4B4A-8669-7E81645FF996}.Release|Any CPU.Build.0 = Release|Any CPU - {F0DA1B67-AF92-4B4A-8669-7E81645FF996}.Release|x64.ActiveCfg = Release|Any CPU - {F0DA1B67-AF92-4B4A-8669-7E81645FF996}.Release|x64.Build.0 = Release|Any CPU - {7695CE9A-A0DB-4D73-BC9B-2206481F0254}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7695CE9A-A0DB-4D73-BC9B-2206481F0254}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7695CE9A-A0DB-4D73-BC9B-2206481F0254}.Debug|x64.ActiveCfg = Debug|Any CPU - {7695CE9A-A0DB-4D73-BC9B-2206481F0254}.Debug|x64.Build.0 = Debug|Any CPU - {7695CE9A-A0DB-4D73-BC9B-2206481F0254}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7695CE9A-A0DB-4D73-BC9B-2206481F0254}.Release|Any CPU.Build.0 = Release|Any CPU - {7695CE9A-A0DB-4D73-BC9B-2206481F0254}.Release|x64.ActiveCfg = Release|Any CPU - {7695CE9A-A0DB-4D73-BC9B-2206481F0254}.Release|x64.Build.0 = Release|Any CPU - {88DEB506-3F7E-4B39-8264-861976DC7434}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {88DEB506-3F7E-4B39-8264-861976DC7434}.Debug|Any CPU.Build.0 = Debug|Any CPU - {88DEB506-3F7E-4B39-8264-861976DC7434}.Debug|x64.ActiveCfg = Debug|Any CPU - {88DEB506-3F7E-4B39-8264-861976DC7434}.Debug|x64.Build.0 = Debug|Any CPU - {88DEB506-3F7E-4B39-8264-861976DC7434}.Release|Any CPU.ActiveCfg = Release|Any CPU - {88DEB506-3F7E-4B39-8264-861976DC7434}.Release|Any CPU.Build.0 = Release|Any CPU - {88DEB506-3F7E-4B39-8264-861976DC7434}.Release|x64.ActiveCfg = Release|Any CPU - {88DEB506-3F7E-4B39-8264-861976DC7434}.Release|x64.Build.0 = Release|Any CPU - {9D7A805E-2629-476E-B36A-040AD332C7DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9D7A805E-2629-476E-B36A-040AD332C7DC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9D7A805E-2629-476E-B36A-040AD332C7DC}.Debug|x64.ActiveCfg = Debug|Any CPU - {9D7A805E-2629-476E-B36A-040AD332C7DC}.Debug|x64.Build.0 = Debug|Any CPU - {9D7A805E-2629-476E-B36A-040AD332C7DC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9D7A805E-2629-476E-B36A-040AD332C7DC}.Release|Any CPU.Build.0 = Release|Any CPU - {9D7A805E-2629-476E-B36A-040AD332C7DC}.Release|x64.ActiveCfg = Release|Any CPU - {9D7A805E-2629-476E-B36A-040AD332C7DC}.Release|x64.Build.0 = Release|Any CPU + {1E52F0D0-9E89-4022-A905-C685EF3564E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1E52F0D0-9E89-4022-A905-C685EF3564E1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1E52F0D0-9E89-4022-A905-C685EF3564E1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1E52F0D0-9E89-4022-A905-C685EF3564E1}.Release|Any CPU.Build.0 = Release|Any CPU + {7A1F40CA-7C37-4B7B-973A-CDCDD424F31F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7A1F40CA-7C37-4B7B-973A-CDCDD424F31F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7A1F40CA-7C37-4B7B-973A-CDCDD424F31F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7A1F40CA-7C37-4B7B-973A-CDCDD424F31F}.Release|Any CPU.Build.0 = Release|Any CPU + {DD521101-7F10-407A-9788-49283D946FDA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DD521101-7F10-407A-9788-49283D946FDA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DD521101-7F10-407A-9788-49283D946FDA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DD521101-7F10-407A-9788-49283D946FDA}.Release|Any CPU.Build.0 = Release|Any CPU + {3CAB11F5-9B07-4D17-BB00-725149087AB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3CAB11F5-9B07-4D17-BB00-725149087AB0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3CAB11F5-9B07-4D17-BB00-725149087AB0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3CAB11F5-9B07-4D17-BB00-725149087AB0}.Release|Any CPU.Build.0 = Release|Any CPU + {F8823907-092C-4055-9F8E-D6756793C24A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F8823907-092C-4055-9F8E-D6756793C24A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F8823907-092C-4055-9F8E-D6756793C24A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F8823907-092C-4055-9F8E-D6756793C24A}.Release|Any CPU.Build.0 = Release|Any CPU + {03636C30-DA61-4307-8934-2FCC3BAC3255}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {03636C30-DA61-4307-8934-2FCC3BAC3255}.Debug|Any CPU.Build.0 = Debug|Any CPU + {03636C30-DA61-4307-8934-2FCC3BAC3255}.Release|Any CPU.ActiveCfg = Release|Any CPU + {03636C30-DA61-4307-8934-2FCC3BAC3255}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {E08975F9-1B84-41B0-875A-CEC9778C4F9E} = {783361EC-DCD6-4A34-8479-5476DF752C34} - {88DEB506-3F7E-4B39-8264-861976DC7434} = {FAC9FE6E-9AA9-45AD-AA72-40DDF7DC44C6} - {9D7A805E-2629-476E-B36A-040AD332C7DC} = {FAC9FE6E-9AA9-45AD-AA72-40DDF7DC44C6} + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {D5D09AC6-1E27-476C-BF7E-980E1640F432} EndGlobalSection EndGlobal diff --git a/Teknik/App_Start/BundleConfig.cs b/Teknik/App_Start/BundleConfig.cs deleted file mode 100644 index fff3f94..0000000 --- a/Teknik/App_Start/BundleConfig.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System.Web; -using System.Web.Optimization; -using Teknik.Configuration; -using Teknik.Utilities; - -namespace Teknik -{ - public class BundleConfig - { - // For more information on bundling, visit http://go.microsoft.com/fwlink/?LinkId=301862 - public static void RegisterBundles(BundleCollection bundles) - { - // Load the config options - Config config = Config.Load(); - - // Set if we are using Cdn - bundles.UseCdn = config.UseCdn; - - BundleTable.EnableOptimizations = false; -#if !DEBUG - BundleTable.EnableOptimizations = true; -#endif - - bundles.Add(new CdnStyleBundle("~/Content/Common", config.CdnHost).Include( - "~/Content/bootstrap.css", - "~/Content/font-awesome.css", - "~/Content/common.css")); - - bundles.Add(new CdnScriptBundle("~/bundles/common", config.CdnHost).Include( - "~/Scripts/jquery-{version}.js", - "~/Scripts/jquery.validate*", - "~/Scripts/bootstrap.js", - "~/Scripts/bootstrap-select.js", - "~/Scripts/common.js", - "~/Scripts/respond.js")); - - bundles.Add(new CdnScriptBundle("~/bundles/jquery", config.CdnHost).Include( - "~/Scripts/jquery-{version}.js", - "~/Scripts/jquery.validate*")); - - // Use the development version of Modernizr to develop with and learn from. Then, when you're - // ready for production, use the build tool at http://modernizr.com to pick only the tests you need. - bundles.Add(new CdnScriptBundle("~/bundles/modernizr", config.CdnHost).Include( - "~/Scripts/modernizr-*")); - - bundles.Add(new CdnScriptBundle("~/bundles/markdown", config.CdnHost).Include( - "~/Scripts/PageDown/Markdown.Converter.js", - "~/Scripts/PageDown/Markdown.Sanitizer.js")); - - bundles.Add(new CdnScriptBundle("~/bundles/signalr", config.CdnHost).Include( - "~/Scripts/jquery.signalR-{version}.js")); - } - } -} diff --git a/Teknik/App_Start/CustomRazorViewEngine.cs b/Teknik/App_Start/CustomRazorViewEngine.cs deleted file mode 100644 index 55a60a4..0000000 --- a/Teknik/App_Start/CustomRazorViewEngine.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Web.Mvc; - -namespace Teknik -{ - public class CustomRazorViewEngine : RazorViewEngine - { - public CustomRazorViewEngine() - { - base.AreaViewLocationFormats = new string[] - { - "~/Areas/{2}/Views/{1}/{0}.cshtml", - "~/Areas/{2}/Views/Shared/{0}.cshtml" - }; - - base.AreaMasterLocationFormats = new string[] - { - "~/Areas/{2}/Views/{1}/{0}.cshtml", - "~/Areas/{2}/Views/Shared/{0}.cshtml" - }; - - base.AreaPartialViewLocationFormats = new string[] - { - "~/Areas/{2}/Views/{1}/{0}.cshtml", - "~/Areas/{2}/Views/Shared/{0}.cshtml" - }; - - base.ViewLocationFormats = new string[] - { - "~/Views/{1}/{0}.cshtml", - "~/Views/Shared/{0}.cshtml" - }; - - base.PartialViewLocationFormats = new string[] - { - "~/Views/{1}/{0}.cshtml", - "~/Views/Shared/{0}.cshtml" - }; - - base.MasterLocationFormats = new string[] - { - "~/Views/{1}/{0}.cshtml", - "~/Views/Shared/{0}.cshtml" - }; - } - } -} diff --git a/Teknik/App_Start/FilterConfig.cs b/Teknik/App_Start/FilterConfig.cs deleted file mode 100644 index 8386953..0000000 --- a/Teknik/App_Start/FilterConfig.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.Web; -using System.Web.Mvc; -using Teknik.Attributes; -using Teknik.Filters; - -namespace Teknik -{ - public class FilterConfig - { - public static void RegisterGlobalFilters(GlobalFilterCollection filters) - { - //filters.Add(new HandleErrorAttribute()); - //filters.Add(new TeknikAuthorizeAttribute()); - filters.Add(new RequireHttpsAttribute()); - } - } -} diff --git a/Teknik/App_Start/RouteConfig.cs b/Teknik/App_Start/RouteConfig.cs deleted file mode 100644 index af259e5..0000000 --- a/Teknik/App_Start/RouteConfig.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Web.Mvc; -using System.Web.Routing; - -namespace Teknik -{ - public class RouteConfig - { - public static void RegisterRoutes(RouteCollection routes) - { - routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); - - // Add this code to handle non-existing urls - routes.MapRoute( - name: "404-PageNotFound", - // This will handle any non-existing urls - url: "{*url}", - // "Shared" is the name of your error controller, and "Error" is the action/page - // that handles all your custom errors - defaults: new { controller = "Default", action = "NotFound" } - ); - } - } -} diff --git a/Teknik/App_Start/SubdomainRoute.cs b/Teknik/App_Start/SubdomainRoute.cs deleted file mode 100644 index 4729072..0000000 --- a/Teknik/App_Start/SubdomainRoute.cs +++ /dev/null @@ -1,101 +0,0 @@ -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Web; -using System.Web.Mvc; -using System.Web.Routing; -using Teknik.Utilities; - -namespace Teknik -{ - public class SubdomainRoute : Route - { - public List Subdomains { get; set; } - - public List Domains { get; set; } - - public SubdomainRoute(List subdomains, List domains, string url, IRouteHandler handler) - : base(url, handler) - { - this.Subdomains = subdomains; - this.Domains = domains; - } - public SubdomainRoute(List subdomains, List domains, string url, RouteValueDictionary defaults, IRouteHandler handler) - : base(url, defaults, handler) - { - this.Subdomains = subdomains; - this.Domains = domains; - } - - public SubdomainRoute(List subdomains, List domains, string url, RouteValueDictionary defaults, RouteValueDictionary constraints, IRouteHandler handler) - : base(url, defaults, constraints, handler) - { - this.Subdomains = subdomains; - this.Domains = domains; - } - - public SubdomainRoute(List subdomains, List domains, string url, RouteValueDictionary defaults, RouteValueDictionary constraints, RouteValueDictionary dataTokens, IRouteHandler handler) - : base(url, defaults, constraints, dataTokens, handler) - { - this.Subdomains = subdomains; - this.Domains = domains; - } - - public override RouteData GetRouteData(HttpContextBase httpContext) - { - var routeData = base.GetRouteData(httpContext); - if (routeData == null) return null; // Only look at the subdomain if this route matches in the first place. - string subdomain = httpContext.Request.QueryString["sub"]; // A subdomain specified as a query parameter takes precedence over the hostname. - string host = httpContext.Request.Headers["Host"]; - if (host == null) return null; // no host, so don't process it - string domain = host.GetDomain(); - string curSub = host.GetSubdomain(); - - // special consideration for 'dev' subdomain - if (subdomain == null || subdomain == "dev") - { - if (!string.IsNullOrEmpty(curSub) && curSub == "dev") - { - // if we are on dev, and the param is dev or empty, we need to initialize it to 'www' - subdomain = "www"; - } - } - - if (subdomain == null) - { - subdomain = curSub; - } - else - { - if (routeData.Values["sub"] == null) - { - routeData.Values["sub"] = subdomain; - } - else - { - subdomain = routeData.Values["sub"].ToString(); - } - } - - // Check if this route is valid for the current domain - if (httpContext.Request.IsLocal || Domains.Contains(domain)) - { - // Check if this route is valid for the current subdomain ('*' means any subdomain is valid) - if (Subdomains.Contains("*") || Subdomains.Contains(subdomain)) - { - routeData.Values["sub"] = subdomain; - return routeData; - } - } - return null; - } - - public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) - { - object subdomainParam = requestContext.HttpContext.Request.QueryString["sub"]; - if (subdomainParam != null && values["sub"] == null) - values["sub"] = subdomainParam; - return base.GetVirtualPath(requestContext, values); // we now have the route based on subdomain - } - } -} \ No newline at end of file diff --git a/Teknik/App_Start/SubdomainRouteExtension.cs b/Teknik/App_Start/SubdomainRouteExtension.cs deleted file mode 100644 index 6083c12..0000000 --- a/Teknik/App_Start/SubdomainRouteExtension.cs +++ /dev/null @@ -1,154 +0,0 @@ -using System.Collections.Generic; -using System.Web.Mvc; -using System.Web.Routing; - -namespace Teknik -{ - public static class SubdomainRouteExtension - { - public static SubdomainRoute MapSubdomainRoute(this RouteCollection routes, string name, List subDomains, List domains, string url, object defaults) - { - SubdomainRoute route = new SubdomainRoute( - subDomains, - domains, - url, - new RouteValueDictionary(defaults), - new MvcRouteHandler()); - routes.Add(name, route); - - return route; - } - - public static SubdomainRoute MapSubdomainRoute(this RouteCollection routes, string name, List subDomains, List domains, string url, object defaults, object constraints) - { - SubdomainRoute route = new SubdomainRoute( - subDomains, - domains, - url, - new RouteValueDictionary(defaults), - new RouteValueDictionary(constraints), - new MvcRouteHandler()); - routes.Add(name, route); - return route; - } - - public static SubdomainRoute MapSubdomainRoute(this RouteCollection routes, string name, List subDomains, List domains, string area, string url, object defaults, string[] namespaces) - { - SubdomainRoute route = new SubdomainRoute( - subDomains, - domains, - url, - new RouteValueDictionary(defaults), - new RouteValueDictionary(new { }), - new RouteValueDictionary(new { Area = area, Namespaces = namespaces }), - new MvcRouteHandler()); - routes.Add(name, route); - return route; - } - - public static SubdomainRoute MapSubdomainRoute(this AreaRegistrationContext context, string name, List subDomains, List domains, string url, object defaults) - { - SubdomainRoute route = new SubdomainRoute( - subDomains, - domains, - url, - new RouteValueDictionary(defaults), - new RouteValueDictionary(new {}), - new RouteValueDictionary(new {Area = context.AreaName}), - new MvcRouteHandler()); - - context.Routes.Add(name, route); - return route; - } - - public static SubdomainRoute MapSubdomainRoute(this AreaRegistrationContext context, string name, List subDomains, List domains, string url, object defaults, object constraints) - { - SubdomainRoute route = new SubdomainRoute( - subDomains, - domains, - url, - new RouteValueDictionary(defaults), - new RouteValueDictionary(constraints), - new RouteValueDictionary(new {Area = context.AreaName}), - new MvcRouteHandler()); - - context.Routes.Add(name, route); - return route; - } - - public static SubdomainRoute MapSubdomainRoute(this AreaRegistrationContext context, string name, List subDomains, List domains, string url, object defaults, string[] namespaces) - { - SubdomainRoute route = new SubdomainRoute( - subDomains, - domains, - url, - new RouteValueDictionary(defaults), - new RouteValueDictionary(new {}), - new RouteValueDictionary(new { Area = context.AreaName, Namespaces = namespaces }), - new MvcRouteHandler()); - - context.Routes.Add(name, route); - return route; - } - - public static SubdomainRoute MapSubdomainRoute(this AreaRegistrationContext context, string name, List subDomains, List domains, string url, object defaults, object constraints, string[] namespaces) - { - SubdomainRoute route = new SubdomainRoute( - subDomains, - domains, - url, - new RouteValueDictionary(defaults), - new RouteValueDictionary(constraints), - new RouteValueDictionary(new { Area = context.AreaName, Namespaces = namespaces }), - new MvcRouteHandler()); - - context.Routes.Add(name, route); - return route; - } - - public static SubdomainRoute MapSubdomainRoute(this AreaRegistrationContext context, string name, List subDomains, List domains, string url, string area, object defaults) - { - SubdomainRoute route = new SubdomainRoute( - subDomains, - domains, - url, - new RouteValueDictionary(defaults), - new RouteValueDictionary(new { }), - new RouteValueDictionary(new { Area = area }), - new MvcRouteHandler()); - - context.Routes.Add(name, route); - return route; - } - - public static SubdomainRoute MapSubdomainRoute(this AreaRegistrationContext context, string name, List subDomains, List domains, string url, string area, object defaults, object constraints) - { - SubdomainRoute route = new SubdomainRoute( - subDomains, - domains, - url, - new RouteValueDictionary(defaults), - new RouteValueDictionary(constraints), - new RouteValueDictionary(new { Area = area }), - new MvcRouteHandler()); - - context.Routes.Add(name, route); - return route; - } - - public static SubdomainRoute MapSubdomainRoute(this AreaRegistrationContext context, string name, List subDomains, List domains, string url, string area, object defaults, string[] namespaces) - { - SubdomainRoute route = new SubdomainRoute( - subDomains, - domains, - url, - new RouteValueDictionary(defaults), - new RouteValueDictionary(new { }), - new RouteValueDictionary(new { Area = area, Namespaces = namespaces }), - new MvcRouteHandler()); - - context.Routes.Add(name, route); - return route; - } - } -} \ No newline at end of file diff --git a/Teknik/Areas/API/APIAreaRegistration.cs b/Teknik/Areas/API/APIAreaRegistration.cs deleted file mode 100644 index 7fc52d4..0000000 --- a/Teknik/Areas/API/APIAreaRegistration.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System.Collections.Generic; -using System.Web.Mvc; -using Teknik.Configuration; - -namespace Teknik.Areas.API -{ - public class APIAreaRegistration : AreaRegistration - { - public override string AreaName - { - get - { - return "API"; - } - } - - public override void RegisterArea(AreaRegistrationContext context) - { - Config config = Config.Load(); - #region API v1 - // Base Routing - context.MapSubdomainRoute( - "API.v1.Index", // Route name - new List() { "api" }, - new List() { config.Host }, - "v1", // URL with parameters - new { controller = "APIv1", action = "Index" }, // Parameter defaults - new[] { typeof(Controllers.APIv1Controller).Namespace } - ); - // Uploads - context.MapSubdomainRoute( - "API.v1.Upload", // Route name - new List() { "api" }, - new List() { config.Host }, - "v1/Upload", // URL with parameters - new { controller = "APIv1", action = "Upload" }, // Parameter defaults - new[] { typeof(Controllers.APIv1Controller).Namespace } - ); - // Pastes - context.MapSubdomainRoute( - "API.v1.Paste", // Route name - new List() { "api" }, - new List() { config.Host }, - "v1/Paste", // URL with parameters - new { controller = "APIv1", action = "Paste" }, // Parameter defaults - new[] { typeof(Controllers.APIv1Controller).Namespace } - ); - // Url Shortening - context.MapSubdomainRoute( - "API.v1.Shortener", // Route name - new List() { "api" }, - new List() { config.Host }, - "v1/Shorten", // URL with parameters - new { controller = "APIv1", action = "Shorten" }, // Parameter defaults - new[] { typeof(Controllers.APIv1Controller).Namespace } - ); - #endregion - - // Default Routing - context.MapSubdomainRoute( - "API.Index", // Route name - new List() { "api" }, - new List() { config.Host }, - "", // URL with parameters - new { controller = "API", action = "Index" }, // Parameter defaults - new[] { typeof(Controllers.APIController).Namespace } - ); - } - } -} \ No newline at end of file diff --git a/Teknik/Areas/API/Controllers/APIController.cs b/Teknik/Areas/API/Controllers/APIController.cs index f09c847..d666f9e 100644 --- a/Teknik/Areas/API/Controllers/APIController.cs +++ b/Teknik/Areas/API/Controllers/APIController.cs @@ -1,23 +1,30 @@ using System; using System.Collections.Generic; -using System.Data.Entity; using System.IO; using System.Linq; using System.Web; -using System.Web.Mvc; using Teknik.Areas.Upload; using Teknik.Controllers; using Teknik.Utilities; using Teknik.Models; using Teknik.Attributes; +using Microsoft.AspNetCore.Authorization; +using Microsoft.Extensions.Logging; +using Teknik.Configuration; +using Teknik.Data; +using Microsoft.AspNetCore.Mvc; +using Teknik.Logging; namespace Teknik.Areas.API.Controllers { [TeknikAuthorize] + [Area("API")] public class APIController : DefaultController { + public APIController(ILogger logger, Config config, TeknikEntities dbContext) : base(logger, config, dbContext) { } + [AllowAnonymous] - public ActionResult Index() + public IActionResult Index() { return Redirect(Url.SubRouteUrl("help", "Help.API")); } diff --git a/Teknik/Areas/API/Controllers/APIv1Controller.cs b/Teknik/Areas/API/Controllers/APIv1Controller.cs index f729867..2231ce6 100644 --- a/Teknik/Areas/API/Controllers/APIv1Controller.cs +++ b/Teknik/Areas/API/Controllers/APIv1Controller.cs @@ -1,10 +1,8 @@ using System; using System.Collections.Generic; -using System.Data.Entity; using System.IO; using System.Linq; using System.Web; -using System.Web.Mvc; using Teknik.Areas.Upload; using Teknik.Areas.Paste; using Teknik.Controllers; @@ -20,14 +18,26 @@ using Teknik.Areas.API.Models; using Teknik.Areas.Users.Models; using Teknik.Areas.Users.Utility; using Teknik.Attributes; +using Microsoft.AspNetCore.Authorization; +using Microsoft.Extensions.Logging; +using Teknik.Configuration; +using Teknik.Data; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using System.Threading.Tasks; +using Teknik.Areas.Shortener; +using Teknik.Logging; namespace Teknik.Areas.API.Controllers { [TeknikAuthorize(AuthType.Basic)] + [Area("APIv1")] public class APIv1Controller : DefaultController { + public APIv1Controller(ILogger logger, Config config, TeknikEntities dbContext) : base(logger, config, dbContext) { } + [AllowAnonymous] - public ActionResult Index() + public IActionResult Index() { return Redirect(Url.SubRouteUrl("help", "Help.API")); } @@ -35,35 +45,36 @@ namespace Teknik.Areas.API.Controllers [HttpPost] [AllowAnonymous] [TrackPageView] - public ActionResult Upload(APIv1UploadModel model) + public async Task UploadAsync(APIv1UploadModel model) { try { - if (Config.UploadConfig.UploadEnabled) + if (_config.UploadConfig.UploadEnabled) { if (model.file != null) { - long maxUploadSize = Config.UploadConfig.MaxUploadSize; + long maxUploadSize = _config.UploadConfig.MaxUploadSize; if (User.Identity.IsAuthenticated) { - maxUploadSize = Config.UploadConfig.MaxUploadSizeBasic; - if (User.Info.AccountType == AccountType.Premium) + maxUploadSize = _config.UploadConfig.MaxUploadSizeBasic; + User user = UserHelper.GetUser(_dbContext, User.Identity.Name); + if (user.AccountType == AccountType.Premium) { - maxUploadSize = Config.UploadConfig.MaxUploadSizePremium; + maxUploadSize = _config.UploadConfig.MaxUploadSizePremium; } } - if (model.file.ContentLength <= maxUploadSize) + if (model.file.Length <= maxUploadSize) { // convert file to bytes string fileExt = Path.GetExtension(model.file.FileName); - int contentLength = model.file.ContentLength; + long contentLength = model.file.Length; // Scan the file to detect a virus - if (Config.UploadConfig.VirusScanEnable) + if (_config.UploadConfig.VirusScanEnable) { - ClamClient clam = new ClamClient(Config.UploadConfig.ClamServer, Config.UploadConfig.ClamPort); + ClamClient clam = new ClamClient(_config.UploadConfig.ClamServer, _config.UploadConfig.ClamPort); clam.MaxStreamSize = maxUploadSize; - ClamScanResult scanResult = clam.SendAndScanFile(model.file.InputStream); + ClamScanResult scanResult = await clam.SendAndScanFileAsync(model.file.OpenReadStream()); switch (scanResult.Result) { @@ -85,13 +96,16 @@ namespace Teknik.Areas.API.Controllers if (string.IsNullOrEmpty(model.contentType)) { - model.file.InputStream.Seek(0, SeekOrigin.Begin); - FileType fileType = model.file.InputStream.GetFileType(); - if (fileType != null) - model.contentType = fileType.Mime; - if (string.IsNullOrEmpty(model.contentType)) + using (System.IO.Stream fileStream = model.file.OpenReadStream()) { - model.contentType = "application/octet-stream"; + fileStream.Seek(0, SeekOrigin.Begin); + FileType fileType = fileStream.GetFileType(); + if (fileType != null) + model.contentType = fileType.Mime; + if (string.IsNullOrEmpty(model.contentType)) + { + model.contentType = "application/octet-stream"; + } } } } @@ -99,7 +113,7 @@ namespace Teknik.Areas.API.Controllers // Check content type restrictions (Only for encrypting server side if (model.encrypt || !string.IsNullOrEmpty(model.key)) { - if (Config.UploadConfig.RestrictedContentTypes.Contains(model.contentType) || Config.UploadConfig.RestrictedExtensions.Contains(fileExt)) + if (_config.UploadConfig.RestrictedContentTypes.Contains(model.contentType) || _config.UploadConfig.RestrictedExtensions.Contains(fileExt)) { return Json(new { error = new { message = "File Type Not Allowed" } }); } @@ -107,66 +121,64 @@ namespace Teknik.Areas.API.Controllers // Initialize the key size and block size if empty if (model.keySize <= 0) - model.keySize = Config.UploadConfig.KeySize; + model.keySize = _config.UploadConfig.KeySize; if (model.blockSize <= 0) - model.blockSize = Config.UploadConfig.BlockSize; + model.blockSize = _config.UploadConfig.BlockSize; - using (TeknikEntities db = new TeknikEntities()) + // Save the file data + Upload.Models.Upload upload = Uploader.SaveFile(_dbContext, _config, model.file.OpenReadStream(), model.contentType, contentLength, model.encrypt, fileExt, model.iv, model.key, model.keySize, model.blockSize); + + if (upload != null) { - // Save the file data - Upload.Models.Upload upload = Uploader.SaveFile(db, Config, model.file.InputStream, model.contentType, contentLength, model.encrypt, fileExt, model.iv, model.key, model.keySize, model.blockSize); + string fileKey = upload.Key; - if (upload != null) + // Associate this with the user if they provided an auth key + if (User.Identity.IsAuthenticated) { - string fileKey = upload.Key; - - // Associate this with the user if they provided an auth key - if (User.Identity.IsAuthenticated) + User foundUser = UserHelper.GetUser(_dbContext, User.Identity.Name); + if (foundUser != null) { - User foundUser = UserHelper.GetUser(db, User.Identity.Name); - if (foundUser != null) - { - upload.UserId = foundUser.UserId; - db.Entry(upload).State = EntityState.Modified; - db.SaveChanges(); - } + upload.UserId = foundUser.UserId; + _dbContext.Entry(upload).State = EntityState.Modified; + _dbContext.SaveChanges(); } - - // Generate delete key only if asked to - if (!model.genDeletionKey) - { - upload.DeleteKey = string.Empty; - db.Entry(upload).State = EntityState.Modified; - db.SaveChanges(); - } - - // remove the key if we don't want to save it - if (!model.saveKey) - { - upload.Key = null; - db.Entry(upload).State = EntityState.Modified; - db.SaveChanges(); - } - - // Pull all the information together - string fullUrl = Url.SubRouteUrl("u", "Upload.Download", new { file = upload.Url }); - var returnData = new - { - url = (model.saveKey || string.IsNullOrEmpty(fileKey)) ? fullUrl : fullUrl + "#" + fileKey, - fileName = upload.Url, - contentType = upload.ContentType, - contentLength = upload.ContentLength, - key = fileKey, - keySize = upload.KeySize, - iv = upload.IV, - blockSize = upload.BlockSize, - deletionKey = upload.DeleteKey - - }; - return Json(new { result = returnData }); } - return Json(new { error = new { message = "Unable to save file" } }); + + // Generate delete key only if asked to + if (!model.genDeletionKey) + { + upload.DeleteKey = string.Empty; + _dbContext.Entry(upload).State = EntityState.Modified; + _dbContext.SaveChanges(); + } + + // remove the key if we don't want to save it + if (!model.saveKey) + { + upload.Key = null; + _dbContext.Entry(upload).State = EntityState.Modified; + _dbContext.SaveChanges(); + } + + // Pull all the information together + string fullUrl = Url.SubRouteUrl("u", "Upload.Download", new { file = upload.Url }); + var returnData = new + { + url = (model.saveKey || string.IsNullOrEmpty(fileKey)) ? fullUrl : fullUrl + "#" + fileKey, + fileName = upload.Url, + contentType = upload.ContentType, + contentLength = upload.ContentLength, + key = fileKey, + keySize = upload.KeySize, + iv = upload.IV, + blockSize = upload.BlockSize, + deletionKey = upload.DeleteKey + + }; + return Json(new { result = returnData }); } + return Json(new { error = new { message = "Unable to save file" } }); + } else { @@ -186,42 +198,39 @@ namespace Teknik.Areas.API.Controllers [HttpPost] [AllowAnonymous] [TrackPageView] - public ActionResult Paste(APIv1PasteModel model) + public IActionResult Paste(APIv1PasteModel model) { try { if (model != null && model.code != null) { - using (TeknikEntities db = new TeknikEntities()) + Paste.Models.Paste paste = PasteHelper.CreatePaste(_config, _dbContext, model.code, model.title, model.syntax, model.expireUnit, model.expireLength, model.password, model.hide); + + // Associate this with the user if they are logged in + if (User.Identity.IsAuthenticated) { - Paste.Models.Paste paste = PasteHelper.CreatePaste(db, model.code, model.title, model.syntax, model.expireUnit, model.expireLength, model.password, model.hide); - - // Associate this with the user if they are logged in - if (User.Identity.IsAuthenticated) + User foundUser = UserHelper.GetUser(_dbContext, User.Identity.Name); + if (foundUser != null) { - User foundUser = UserHelper.GetUser(db, User.Identity.Name); - if (foundUser != null) - { - paste.UserId = foundUser.UserId; - } + paste.UserId = foundUser.UserId; } - - db.Pastes.Add(paste); - db.SaveChanges(); - - return Json(new - { - result = new - { - id = paste.Url, - url = Url.SubRouteUrl("p", "Paste.View", new { type = "Full", url = paste.Url, password = model.password }), - title = paste.Title, - syntax = paste.Syntax, - expiration = paste.ExpireDate, - password = model.password - } - }); } + + _dbContext.Pastes.Add(paste); + _dbContext.SaveChanges(); + + return Json(new + { + result = new + { + id = paste.Url, + url = Url.SubRouteUrl("p", "Paste.View", new { type = "Full", url = paste.Url, password = model.password }), + title = paste.Title, + syntax = paste.Syntax, + expiration = paste.ExpireDate, + password = model.password + } + }); } return Json(new { error = new { message = "Invalid Paste Request" } }); } @@ -234,44 +243,41 @@ namespace Teknik.Areas.API.Controllers [HttpPost] [AllowAnonymous] [TrackPageView] - public ActionResult Shorten(APIv1ShortenModel model) + public IActionResult Shorten(APIv1ShortenModel model) { try { if (model.url.IsValidUrl()) { - using (TeknikEntities db = new TeknikEntities()) + ShortenedUrl newUrl = ShortenerHelper.ShortenUrl(_dbContext, model.url, _config.ShortenerConfig.UrlLength); + + // Associate this with the user if they are logged in + if (User.Identity.IsAuthenticated) { - ShortenedUrl newUrl = Shortener.Shortener.ShortenUrl(db, model.url, Config.ShortenerConfig.UrlLength); - - // Associate this with the user if they are logged in - if (User.Identity.IsAuthenticated) + User foundUser = UserHelper.GetUser(_dbContext, User.Identity.Name); + if (foundUser != null) { - User foundUser = UserHelper.GetUser(db, User.Identity.Name); - if (foundUser != null) - { - newUrl.UserId = foundUser.UserId; - } + newUrl.UserId = foundUser.UserId; } - - db.ShortenedUrls.Add(newUrl); - db.SaveChanges(); - - string shortUrl = string.Format("{0}://{1}/{2}", HttpContext.Request.Url.Scheme, Config.ShortenerConfig.ShortenerHost, newUrl.ShortUrl); - if (Config.DevEnvironment) - { - shortUrl = Url.SubRouteUrl("shortened", "Shortener.View", new { url = newUrl.ShortUrl }); - } - - return Json(new - { - result = new - { - shortUrl = shortUrl, - originalUrl = model.url - } - }); } + + _dbContext.ShortenedUrls.Add(newUrl); + _dbContext.SaveChanges(); + + string shortUrl = string.Format("{0}://{1}/{2}", HttpContext.Request.Scheme, _config.ShortenerConfig.ShortenerHost, newUrl.ShortUrl); + if (_config.DevEnvironment) + { + shortUrl = Url.SubRouteUrl("shortened", "Shortener.View", new { url = newUrl.ShortUrl }); + } + + return Json(new + { + result = new + { + shortUrl = shortUrl, + originalUrl = model.url + } + }); } return Json(new { error = new { message = "Must be a valid Url" } }); } diff --git a/Teknik/Areas/API/Models/APIv1PasteModel.cs b/Teknik/Areas/API/Models/APIv1PasteModel.cs index f743388..2914e3b 100644 --- a/Teknik/Areas/API/Models/APIv1PasteModel.cs +++ b/Teknik/Areas/API/Models/APIv1PasteModel.cs @@ -1,14 +1,7 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.Web.Mvc; - -namespace Teknik.Areas.API.Models +namespace Teknik.Areas.API.Models { public class APIv1PasteModel : APIv1BaseModel { - [AllowHtml] public string code { get; set; } public string title { get; set; } diff --git a/Teknik/Areas/API/Models/APIv1UploadModel.cs b/Teknik/Areas/API/Models/APIv1UploadModel.cs index e9e8000..57bf3fe 100644 --- a/Teknik/Areas/API/Models/APIv1UploadModel.cs +++ b/Teknik/Areas/API/Models/APIv1UploadModel.cs @@ -1,4 +1,5 @@ -using System; +using Microsoft.AspNetCore.Http; +using System; using System.Collections.Generic; using System.Linq; using System.Web; @@ -7,7 +8,7 @@ namespace Teknik.Areas.API.Models { public class APIv1UploadModel : APIv1BaseModel { - public HttpPostedFileWrapper file { get; set; } + public IFormFile file { get; set; } public string contentType { get; set; } diff --git a/Teknik/Areas/API/Views/web.config b/Teknik/Areas/API/Views/web.config deleted file mode 100644 index 013d8bf..0000000 --- a/Teknik/Areas/API/Views/web.config +++ /dev/null @@ -1,36 +0,0 @@ - - - - - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Teknik/Areas/About/AboutAreaRegistration.cs b/Teknik/Areas/About/AboutAreaRegistration.cs deleted file mode 100644 index afccc06..0000000 --- a/Teknik/Areas/About/AboutAreaRegistration.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Collections.Generic; -using System.Web.Mvc; -using Teknik.Configuration; - -namespace Teknik.Areas.About -{ - public class AboutAreaRegistration : AreaRegistration - { - public override string AreaName - { - get - { - return "About"; - } - } - - public override void RegisterArea(AreaRegistrationContext context) - { - Config config = Config.Load(); - context.MapSubdomainRoute( - "About.Index", // Route name - new List() { "about" }, - new List() { config.Host }, - "", // URL with parameters - new { controller = "About", action = "Index" }, // Parameter defaults - new[] { typeof(Controllers.AboutController).Namespace } - ); - } - } -} \ No newline at end of file diff --git a/Teknik/Areas/About/Controllers/AboutController.cs b/Teknik/Areas/About/Controllers/AboutController.cs index c140f75..d561326 100644 --- a/Teknik/Areas/About/Controllers/AboutController.cs +++ b/Teknik/Areas/About/Controllers/AboutController.cs @@ -1,23 +1,31 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Web; -using System.Web.Mvc; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; using Teknik.Areas.About.ViewModels; using Teknik.Attributes; +using Teknik.Configuration; using Teknik.Controllers; +using Teknik.Data; using Teknik.Filters; +using Teknik.Logging; namespace Teknik.Areas.About.Controllers { [TeknikAuthorize] + [Area("About")] public class AboutController : DefaultController { + public AboutController(ILogger logger, Config config, TeknikEntities dbContext) : base(logger, config, dbContext) { } + [AllowAnonymous] [TrackPageView] - public ActionResult Index() + public IActionResult Index([FromServices] Config config) { - ViewBag.Title = "About - " + Config.Title; + ViewBag.Title = "About - " + config.Title; ViewBag.Description = "What is Teknik?"; return View(new AboutViewModel()); diff --git a/Teknik/Areas/About/ViewModels/AboutViewModel.cs b/Teknik/Areas/About/ViewModels/AboutViewModel.cs index 108b5f1..577ac42 100644 --- a/Teknik/Areas/About/ViewModels/AboutViewModel.cs +++ b/Teknik/Areas/About/ViewModels/AboutViewModel.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Web; +using System.Threading.Tasks; using Teknik.ViewModels; namespace Teknik.Areas.About.ViewModels @@ -9,4 +9,4 @@ namespace Teknik.Areas.About.ViewModels public class AboutViewModel : ViewModelBase { } -} \ No newline at end of file +} diff --git a/Teknik/Areas/About/Views/About/Index.cshtml b/Teknik/Areas/About/Views/About/Index.cshtml index 313d628..3f6906d 100644 --- a/Teknik/Areas/About/Views/About/Index.cshtml +++ b/Teknik/Areas/About/Views/About/Index.cshtml @@ -1,7 +1,5 @@ @model Teknik.Areas.About.ViewModels.AboutViewModel -@using Teknik.Utilities - @{ string lifetimeAccount = "The account will not get deleted for inactivity as defined in the ToS"; string apiAccountAccess = "Passing user credentials allows linking for Uploads/Pastes/Shortened URLs and other account specific features"; @@ -35,7 +33,7 @@ - $@Model.Config.UserConfig.PremiumAccountPrice @Model.Config.UserConfig.PaymentType + $@Config.UserConfig.PremiumAccountPrice @Config.UserConfig.PaymentType Free Free @@ -113,15 +111,15 @@ Max Upload Filesize - @StringHelper.GetBytesReadable(Model.Config.UploadConfig.MaxUploadSizePremium) - @StringHelper.GetBytesReadable(Model.Config.UploadConfig.MaxUploadSizeBasic) - @StringHelper.GetBytesReadable(Model.Config.UploadConfig.MaxUploadSize) + @StringHelper.GetBytesReadable(Config.UploadConfig.MaxUploadSizePremium) + @StringHelper.GetBytesReadable(Config.UploadConfig.MaxUploadSizeBasic) + @StringHelper.GetBytesReadable(Config.UploadConfig.MaxUploadSize) Max Embedded Filesize Unlimited - @StringHelper.GetBytesReadable(Model.Config.UploadConfig.MaxDownloadSize) - @StringHelper.GetBytesReadable(Model.Config.UploadConfig.MaxDownloadSize) + @StringHelper.GetBytesReadable(Config.UploadConfig.MaxDownloadSize) + @StringHelper.GetBytesReadable(Config.UploadConfig.MaxDownloadSize) Url Shortening diff --git a/Teknik/Areas/About/Views/web.config b/Teknik/Areas/About/Views/web.config deleted file mode 100644 index 013d8bf..0000000 --- a/Teknik/Areas/About/Views/web.config +++ /dev/null @@ -1,36 +0,0 @@ - - - - - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Teknik/Areas/Abuse/AbuseAreaRegistration.cs b/Teknik/Areas/Abuse/AbuseAreaRegistration.cs deleted file mode 100644 index af8798c..0000000 --- a/Teknik/Areas/Abuse/AbuseAreaRegistration.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Collections.Generic; -using System.Web.Mvc; -using Teknik.Configuration; - -namespace Teknik.Areas.Abuse -{ - public class AbuseAreaRegistration : AreaRegistration - { - public override string AreaName - { - get - { - return "Abuse"; - } - } - - public override void RegisterArea(AreaRegistrationContext context) - { - Config config = Config.Load(); - context.MapSubdomainRoute( - "Abuse.Index", // Route name - new List() { "abuse" }, // Subdomains - new List() { config.Host }, // domains - "", // URL with parameters - new { controller = "Abuse", action = "Index" }, // Parameter defaults - new[] { typeof(Controllers.AbuseController).Namespace } - ); - } - } -} diff --git a/Teknik/Areas/Abuse/Controllers/AbuseController.cs b/Teknik/Areas/Abuse/Controllers/AbuseController.cs index c3e0e54..ce91654 100644 --- a/Teknik/Areas/Abuse/Controllers/AbuseController.cs +++ b/Teknik/Areas/Abuse/Controllers/AbuseController.cs @@ -1,23 +1,31 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Linq; using System.Web; -using System.Web.Mvc; using Teknik.Areas.Abuse.ViewModels; using Teknik.Attributes; +using Teknik.Configuration; using Teknik.Controllers; +using Teknik.Data; using Teknik.Filters; +using Teknik.Logging; namespace Teknik.Areas.Abuse.Controllers { [TeknikAuthorize] + [Area("Abuse")] public class AbuseController : DefaultController { + public AbuseController(ILogger logger, Config config, TeknikEntities dbContext) : base(logger, config, dbContext) { } + [TrackPageView] [AllowAnonymous] - public ActionResult Index() + public IActionResult Index() { - ViewBag.Title = "Abuse Reporting - " + Config.Title; + ViewBag.Title = "Abuse Reporting - " + _config.Title; ViewBag.Description = "Methods for reporting abuse reports to Teknik Services."; return View(new AbuseViewModel()); diff --git a/Teknik/Areas/Abuse/Views/Abuse/Index.cshtml b/Teknik/Areas/Abuse/Views/Abuse/Index.cshtml index 82eaa8d..29f0737 100644 --- a/Teknik/Areas/Abuse/Views/Abuse/Index.cshtml +++ b/Teknik/Areas/Abuse/Views/Abuse/Index.cshtml @@ -1,4 +1,3 @@ -@using Teknik.Utilities @model Teknik.Areas.Abuse.ViewModels.AbuseViewModel
diff --git a/Teknik/Areas/Abuse/Views/_ViewStart.cshtml b/Teknik/Areas/Abuse/Views/_ViewStart.cshtml deleted file mode 100644 index 2de6241..0000000 --- a/Teknik/Areas/Abuse/Views/_ViewStart.cshtml +++ /dev/null @@ -1,3 +0,0 @@ -@{ - Layout = "~/Views/Shared/_Layout.cshtml"; -} diff --git a/Teknik/Areas/Abuse/Views/web.config b/Teknik/Areas/Abuse/Views/web.config deleted file mode 100644 index ada5aaf..0000000 --- a/Teknik/Areas/Abuse/Views/web.config +++ /dev/null @@ -1,36 +0,0 @@ - - - - - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Teknik/Areas/Accounts/ResourceOwnerPasswordValidator.cs b/Teknik/Areas/Accounts/ResourceOwnerPasswordValidator.cs new file mode 100644 index 0000000..4dd731f --- /dev/null +++ b/Teknik/Areas/Accounts/ResourceOwnerPasswordValidator.cs @@ -0,0 +1,36 @@ +using IdentityServer4.Validation; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Teknik.Areas.Users.Models; +using Teknik.Areas.Users.Utility; +using Teknik.Configuration; +using Teknik.Data; + +namespace Teknik.Areas.Accounts +{ + public class ResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator + { + private readonly TeknikEntities _dbContext; + private readonly Config _config; + + public ResourceOwnerPasswordValidator(TeknikEntities dbContext, Config config) + { + _dbContext = dbContext; + _config = config; + } + + public Task ValidateAsync(ResourceOwnerPasswordValidationContext context) + { + // Get the user + string username = context.UserName; + User user = UserHelper.GetUser(_dbContext, context.UserName); + if (user != null) + { + bool userValid = UserHelper.UserPasswordCorrect(_dbContext, _config, user, context.Password); + } + return null; + } + } +} diff --git a/Teknik/Areas/Admin/AdminAreaRegistration.cs b/Teknik/Areas/Admin/AdminAreaRegistration.cs deleted file mode 100644 index 822a9f7..0000000 --- a/Teknik/Areas/Admin/AdminAreaRegistration.cs +++ /dev/null @@ -1,77 +0,0 @@ -using System.Collections.Generic; -using System.Web.Mvc; -using System.Web.Optimization; -using Teknik.Configuration; -using Teknik.Utilities; - -namespace Teknik.Areas.Admin -{ - public class AdminAreaRegistration : AreaRegistration - { - public override string AreaName - { - get - { - return "Admin"; - } - } - - public override void RegisterArea(AreaRegistrationContext context) - { - Config config = Config.Load(); - context.MapSubdomainRoute( - "Admin.Dashboard", // Route name - new List() { "admin" }, // Subdomains - new List() { config.Host }, - "", // URL with parameters - new { controller = "Admin", action = "Dashboard" }, // Parameter defaults - new[] { typeof(Controllers.AdminController).Namespace } - ); - context.MapSubdomainRoute( - "Admin.UserSearch", // Route name - new List() { "admin" }, // Subdomains - new List() { config.Host }, - "Search/Users", // URL with parameters - new { controller = "Admin", action = "UserSearch" }, // Parameter defaults - new[] { typeof(Controllers.AdminController).Namespace } - ); - context.MapSubdomainRoute( - "Admin.UploadSearch", // Route name - new List() { "admin" }, // Subdomains - new List() { config.Host }, - "Search/Uploads", // URL with parameters - new { controller = "Admin", action = "UploadSearch" }, // Parameter defaults - new[] { typeof(Controllers.AdminController).Namespace } - ); - context.MapSubdomainRoute( - "Admin.UserInfo", // Route name - new List() { "admin" }, // Subdomains - new List() { config.Host }, - "User/{username}", // URL with parameters - new { controller = "Admin", action = "UserInfo", username = string.Empty }, // Parameter defaults - new[] { typeof(Controllers.AdminController).Namespace } - ); - context.MapSubdomainRoute( - "Admin.Action", // Route name - new List() { "admin" }, // Subdomains - new List() { config.Host }, - "Action/{controller}/{action}", // URL with parameters - new { controller = "Admin", action = "Dashboard" }, // Parameter defaults - new[] { typeof(Controllers.AdminController).Namespace } - ); - - // Register Script Bundles - BundleTable.Bundles.Add(new CdnScriptBundle("~/bundles/UserSearch", config.CdnHost).Include( - "~/Areas/Admin/Scripts/UserSearch.js")); - - // Register Script Bundles - BundleTable.Bundles.Add(new CdnScriptBundle("~/bundles/UploadSearch", config.CdnHost).Include( - "~/Scripts/bootbox/bootbox.min.js", - "~/Areas/Admin/Scripts/UploadSearch.js")); - - BundleTable.Bundles.Add(new CdnScriptBundle("~/bundles/UserInfo", config.CdnHost).Include( - "~/Scripts/bootbox/bootbox.min.js", - "~/Areas/Admin/Scripts/UserInfo.js")); - } - } -} diff --git a/Teknik/Areas/Admin/Controllers/AdminController.cs b/Teknik/Areas/Admin/Controllers/AdminController.cs index f3b5706..d91e577 100644 --- a/Teknik/Areas/Admin/Controllers/AdminController.cs +++ b/Teknik/Areas/Admin/Controllers/AdminController.cs @@ -1,24 +1,30 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.ViewEngines; +using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Linq; -using System.Web; -using System.Web.Mvc; +using System.Threading.Tasks; using Teknik.Areas.Admin.ViewModels; using Teknik.Areas.Users.Models; using Teknik.Areas.Users.Utility; using Teknik.Attributes; +using Teknik.Configuration; using Teknik.Controllers; +using Teknik.Data; using Teknik.Filters; using Teknik.Models; using Teknik.Utilities; using Teknik.ViewModels; +using Teknik.Logging; namespace Teknik.Areas.Admin.Controllers { [TeknikAuthorize(Roles = "Admin")] + [Area("Admin")] public class AdminController : DefaultController { - private TeknikEntities db = new TeknikEntities(); + public AdminController(ILogger logger, Config config, TeknikEntities dbContext) : base (logger, config, dbContext) { } [HttpGet] [TrackPageView] @@ -40,9 +46,9 @@ namespace Teknik.Areas.Admin.Controllers [TrackPageView] public ActionResult UserInfo(string username) { - if (UserHelper.UserExists(db, username)) + if (UserHelper.UserExists(_dbContext, username)) { - User user = UserHelper.GetUser(db, username); + User user = UserHelper.GetUser(_dbContext, username); UserInfoViewModel model = new UserInfoViewModel(); model.Username = user.Username; model.AccountType = user.AccountType; @@ -60,11 +66,11 @@ namespace Teknik.Areas.Admin.Controllers } [HttpPost] - public ActionResult GetUserSearchResults(string query) + public async Task GetUserSearchResults(string query, [FromServices] ICompositeViewEngine viewEngine) { List models = new List(); - var results = db.Users.Where(u => u.Username.Contains(query)).ToList(); + var results = _dbContext.Users.Where(u => u.Username.Contains(query)).ToList(); if (results != null) { foreach (User user in results) @@ -73,12 +79,12 @@ namespace Teknik.Areas.Admin.Controllers { UserResultViewModel model = new UserResultViewModel(); model.Username = user.Username; - if (Config.EmailConfig.Enabled) + if (_config.EmailConfig.Enabled) { - model.Email = string.Format("{0}@{1}", user.Username, Config.EmailConfig.Domain); + model.Email = string.Format("{0}@{1}", user.Username, _config.EmailConfig.Domain); } model.JoinDate = user.JoinDate; - model.LastSeen = UserHelper.GetLastAccountActivity(db, Config, user); + model.LastSeen = UserHelper.GetLastAccountActivity(_dbContext, _config, user); models.Add(model); } catch (Exception ex) @@ -88,13 +94,15 @@ namespace Teknik.Areas.Admin.Controllers } } - return Json(new { result = new { html = PartialView("~/Areas/Admin/Views/Admin/UserResults.cshtml", models).RenderToString() } }); + string renderedView = await RenderPartialViewToString(viewEngine, "~/Areas/Admin/Views/Admin/UserResults.cshtml", models); + + return Json(new { result = new { html = renderedView } }); } [HttpPost] - public ActionResult GetUploadSearchResults(string url) + public async Task GetUploadSearchResults(string url, [FromServices] ICompositeViewEngine viewEngine) { - Upload.Models.Upload foundUpload = db.Uploads.Where(u => u.Url == url).FirstOrDefault(); + Upload.Models.Upload foundUpload = _dbContext.Uploads.Where(u => u.Url == url).FirstOrDefault(); if (foundUpload != null) { UploadResultViewModel model = new UploadResultViewModel(); @@ -106,7 +114,9 @@ namespace Teknik.Areas.Admin.Controllers model.Downloads = foundUpload.Downloads; model.DeleteKey = foundUpload.DeleteKey; - return Json(new { result = new { html = PartialView("~/Areas/Admin/Views/Admin/UploadResult.cshtml", model).RenderToString() } }); + string renderedView = await RenderPartialViewToString(viewEngine, "~/Areas/Admin/Views/Admin/UploadResult.cshtml", model); + + return Json(new { result = new { html = renderedView } }); } return Json(new { error = new { message = "Upload does not exist" } }); } @@ -115,10 +125,10 @@ namespace Teknik.Areas.Admin.Controllers [ValidateAntiForgeryToken] public ActionResult EditUserAccountType(string username, AccountType accountType) { - if (UserHelper.UserExists(db, username)) + if (UserHelper.UserExists(_dbContext, username)) { // Edit the user's account type - UserHelper.EditAccountType(db, Config, username, accountType); + UserHelper.EditAccountType(_dbContext, _config, username, accountType); return Json(new { result = new { success = true } }); } return Redirect(Url.SubRouteUrl("error", "Error.Http404")); @@ -128,10 +138,10 @@ namespace Teknik.Areas.Admin.Controllers [ValidateAntiForgeryToken] public ActionResult EditUserAccountStatus(string username, AccountStatus accountStatus) { - if (UserHelper.UserExists(db, username)) + if (UserHelper.UserExists(_dbContext, username)) { // Edit the user's account type - UserHelper.EditAccountStatus(db, Config, username, accountStatus); + UserHelper.EditAccountStatus(_dbContext, _config, username, accountStatus); return Json(new { result = new { success = true } }); } return Redirect(Url.SubRouteUrl("error", "Error.Http404")); @@ -141,15 +151,15 @@ namespace Teknik.Areas.Admin.Controllers [ValidateAntiForgeryToken] public ActionResult CreateInviteCode(string username) { - if (UserHelper.UserExists(db, username)) + if (UserHelper.UserExists(_dbContext, username)) { - User user = UserHelper.GetUser(db, username); - InviteCode inviteCode = db.InviteCodes.Create(); + User user = UserHelper.GetUser(_dbContext, username); + InviteCode inviteCode = new InviteCode(); inviteCode.Active = true; inviteCode.Code = Guid.NewGuid().ToString(); inviteCode.Owner = user; - db.InviteCodes.Add(inviteCode); - db.SaveChanges(); + _dbContext.InviteCodes.Add(inviteCode); + _dbContext.SaveChanges(); return Json(new { result = new { code = inviteCode.Code } }); } @@ -162,14 +172,11 @@ namespace Teknik.Areas.Admin.Controllers { try { - using (TeknikEntities db = new TeknikEntities()) + User user = UserHelper.GetUser(_dbContext, username); + if (user != null) { - User user = UserHelper.GetUser(db, username); - if (user != null) - { - UserHelper.DeleteAccount(db, Config, user); - return Json(new { result = true }); - } + UserHelper.DeleteAccount(_dbContext, _config, user); + return Json(new { result = true }); } } catch (Exception ex) diff --git a/Teknik/Areas/Admin/Views/Admin/Dashboard.cshtml b/Teknik/Areas/Admin/Views/Admin/Dashboard.cshtml index fea3490..1cc0ae1 100644 --- a/Teknik/Areas/Admin/Views/Admin/Dashboard.cshtml +++ b/Teknik/Areas/Admin/Views/Admin/Dashboard.cshtml @@ -1,7 +1,5 @@ @model Teknik.Areas.Admin.ViewModels.DashboardViewModel -@using Teknik.Utilities -
diff --git a/Teknik/Areas/Admin/Views/Admin/UploadResult.cshtml b/Teknik/Areas/Admin/Views/Admin/UploadResult.cshtml index 006e5a5..b0bbef9 100644 --- a/Teknik/Areas/Admin/Views/Admin/UploadResult.cshtml +++ b/Teknik/Areas/Admin/Views/Admin/UploadResult.cshtml @@ -1,7 +1,5 @@ @model Teknik.Areas.Admin.ViewModels.UploadResultViewModel -@using Teknik.Utilities -
@Url.SubRouteUrl("u", "Upload.Download", new { file = Model.Url }) diff --git a/Teknik/Areas/Admin/Views/Admin/UploadSearch.cshtml b/Teknik/Areas/Admin/Views/Admin/UploadSearch.cshtml index 8490e9b..5c2dbd3 100644 --- a/Teknik/Areas/Admin/Views/Admin/UploadSearch.cshtml +++ b/Teknik/Areas/Admin/Views/Admin/UploadSearch.cshtml @@ -1,23 +1,19 @@ @model Teknik.Areas.Admin.ViewModels.UploadSearchViewModel -@using Teknik.Utilities - - -@Scripts.Render("~/bundles/UploadSearch") -
-
+
-
+
@@ -26,3 +22,5 @@
+ + diff --git a/Teknik/Areas/Admin/Views/Admin/UserInfo.cshtml b/Teknik/Areas/Admin/Views/Admin/UserInfo.cshtml index 4ccf355..5429faf 100644 --- a/Teknik/Areas/Admin/Views/Admin/UserInfo.cshtml +++ b/Teknik/Areas/Admin/Views/Admin/UserInfo.cshtml @@ -1,8 +1,6 @@ @model Teknik.Areas.Admin.ViewModels.UserInfoViewModel -@using Teknik.Utilities - - -@Scripts.Render("~/bundles/UserInfo") -
@@ -33,7 +29,7 @@ @{ foreach (AccountType value in Enum.GetValues(typeof(AccountType))) { - + @value.ToString() } } @@ -49,7 +45,7 @@ @{ foreach (AccountStatus value in Enum.GetValues(typeof(AccountStatus))) { - + @value.ToString() } } @@ -68,3 +64,5 @@
+ + diff --git a/Teknik/Areas/Admin/Views/Admin/UserResult.cshtml b/Teknik/Areas/Admin/Views/Admin/UserResult.cshtml index b3f2995..eb1b995 100644 --- a/Teknik/Areas/Admin/Views/Admin/UserResult.cshtml +++ b/Teknik/Areas/Admin/Views/Admin/UserResult.cshtml @@ -1,7 +1,5 @@ @model Teknik.Areas.Admin.ViewModels.UserResultViewModel -@using Teknik.Utilities -
diff --git a/Teknik/Areas/Admin/Views/Admin/UserResults.cshtml b/Teknik/Areas/Admin/Views/Admin/UserResults.cshtml index 9f25406..988aa39 100644 --- a/Teknik/Areas/Admin/Views/Admin/UserResults.cshtml +++ b/Teknik/Areas/Admin/Views/Admin/UserResults.cshtml @@ -10,7 +10,7 @@
foreach (var post in Model) { - @Html.Partial("UserResult", post) + @await Html.PartialAsync("UserResult", post) } } else diff --git a/Teknik/Areas/Admin/Views/Admin/UserSearch.cshtml b/Teknik/Areas/Admin/Views/Admin/UserSearch.cshtml index 41cf673..47c68fa 100644 --- a/Teknik/Areas/Admin/Views/Admin/UserSearch.cshtml +++ b/Teknik/Areas/Admin/Views/Admin/UserSearch.cshtml @@ -1,22 +1,18 @@ @model Teknik.Areas.Admin.ViewModels.UserSearchViewModel -@using Teknik.Utilities - - -@Scripts.Render("~/bundles/UserSearch") -
-
+
-
+
@@ -28,3 +24,5 @@
+ + diff --git a/Teknik/Areas/Admin/Views/_ViewStart.cshtml b/Teknik/Areas/Admin/Views/_ViewStart.cshtml deleted file mode 100644 index 2de6241..0000000 --- a/Teknik/Areas/Admin/Views/_ViewStart.cshtml +++ /dev/null @@ -1,3 +0,0 @@ -@{ - Layout = "~/Views/Shared/_Layout.cshtml"; -} diff --git a/Teknik/Areas/Admin/Views/web.config b/Teknik/Areas/Admin/Views/web.config deleted file mode 100644 index 013d8bf..0000000 --- a/Teknik/Areas/Admin/Views/web.config +++ /dev/null @@ -1,36 +0,0 @@ - - - - - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Teknik/Areas/Blog/BlogAreaRegistration.cs b/Teknik/Areas/Blog/BlogAreaRegistration.cs deleted file mode 100644 index 121e3a5..0000000 --- a/Teknik/Areas/Blog/BlogAreaRegistration.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System.Collections.Generic; -using System.Web.Mvc; -using System.Web.Optimization; -using Teknik.Configuration; -using Teknik.Utilities; - -namespace Teknik.Areas.Blog -{ - public class BlogAreaRegistration : AreaRegistration - { - public override string AreaName - { - get - { - return "Blog"; - } - } - - public override void RegisterArea(AreaRegistrationContext context) - { - Config config = Config.Load(); - context.MapSubdomainRoute( - "Blog.Blog", // Route name - new List() { "blog" }, // Subdomains - new List() { config.Host }, - "{username}", // URL with parameters - new { controller = "Blog", action = "Blog", username = string.Empty }, // Parameter defaults - new[] { typeof(Controllers.BlogController).Namespace } - ); - context.MapSubdomainRoute( - "Blog.New", // Route name - new List() { "blog" }, // Subdomains - new List() { config.Host }, - "{username}/New", // URL with parameters - new { controller = "Blog", action = "NewPost", username = "" }, // Parameter defaults - new[] { typeof(Controllers.BlogController).Namespace } - ); - context.MapSubdomainRoute( - "Blog.Edit", // Route name - new List() { "blog" }, // Subdomains - new List() { config.Host }, - "{username}/Edit/{id}", // URL with parameters - new { controller = "Blog", action = "EditPost", username = "", id = 0 }, // Parameter defaults - new[] { typeof(Controllers.BlogController).Namespace } - ); - context.MapSubdomainRoute( - "Blog.Post", // Route name - new List() { "blog" }, // Subdomains - new List() { config.Host }, - "{username}/p/{id}", // URL with parameters - new { controller = "Blog", action = "Post", username = "", id = 0 }, // Parameter defaults - new[] { typeof(Controllers.BlogController).Namespace } - ); - context.MapSubdomainRoute( - "Blog.Action", // Route name - new List() { "blog" }, // Subdomains - new List() { config.Host }, - "Action/{controller}/{action}", // URL with parameters - new { controller = "Blog", action = "Blog" }, // Parameter defaults - new[] { typeof(Controllers.BlogController).Namespace } - ); - - // Register Script Bundles - BundleTable.Bundles.Add(new CdnScriptBundle("~/bundles/blog", config.CdnHost).Include( - "~/Scripts/bootbox/bootbox.min.js", - "~/Scripts/MarkdownDeepLib.min.js", - "~/Areas/Blog/Scripts/Blog.js")); - // Register Style Bundles - BundleTable.Bundles.Add(new CdnStyleBundle("~/Content/blog", config.CdnHost).Include( - "~/Content/mdd_styles.css", - "~/Areas/Blog/Content/Blog.css")); - } - } -} \ No newline at end of file diff --git a/Teknik/Areas/Blog/Controllers/BlogController.cs b/Teknik/Areas/Blog/Controllers/BlogController.cs index ec59d8f..cea7938 100644 --- a/Teknik/Areas/Blog/Controllers/BlogController.cs +++ b/Teknik/Areas/Blog/Controllers/BlogController.cs @@ -1,11 +1,9 @@ using System; using System.Collections.Generic; using System.Data; -using System.Data.Entity; using System.Linq; using System.Net; using System.Web; -using System.Web.Mvc; using Teknik.Areas.Blog.Models; using Teknik.Areas.Blog.ViewModels; using Teknik.Areas.Users.Models; @@ -15,61 +13,103 @@ using Teknik.Filters; using Teknik.Utilities; using Teknik.Models; using Teknik.Attributes; +using Microsoft.Extensions.Logging; +using Teknik.Configuration; +using Teknik.Data; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Teknik.Logging; namespace Teknik.Areas.Blog.Controllers { [TeknikAuthorize] + [Area("Blog")] public class BlogController : DefaultController { - private TeknikEntities db = new TeknikEntities(); - - // GET: Blogs/Details/5 + public BlogController(ILogger logger, Config config, TeknikEntities dbContext) : base(logger, config, dbContext) { } + [TrackPageView] [AllowAnonymous] - public ActionResult Blog(string username) + public IActionResult Blog(string username) { BlogViewModel model = new BlogViewModel(); // The blog is the main site's blog if (string.IsNullOrEmpty(username)) { - ViewBag.Title = Config.BlogConfig.Title + " - " + Config.Title; - ViewBag.Description = Config.BlogConfig.Description; + ViewBag.Title = _config.BlogConfig.Title + " - " + _config.Title; + ViewBag.Description = _config.BlogConfig.Description; bool isAuth = User.IsInRole("Admin"); - var foundPosts = db.BlogPosts.Where(p => ((p.System || isAuth) && p.Published)); model = new BlogViewModel(); - model.BlogId = Config.BlogConfig.ServerBlogId; + model.BlogId = _config.BlogConfig.ServerBlogId; - User user = (User.IsInRole("Admin")) ? UserHelper.GetUser(db, User.Identity.Name) : null; + User user = (User.IsInRole("Admin")) ? UserHelper.GetUser(_dbContext, User.Identity.Name) : null; model.UserId = (user != null) ? user.UserId : 0; model.User = user; - model.Title = Config.BlogConfig.Title; - model.Description = Config.BlogConfig.Description; - model.HasPosts = (foundPosts != null && foundPosts.Any()); + model.Title = _config.BlogConfig.Title; + model.Description = _config.BlogConfig.Description; + var posts = _dbContext.BlogPosts + .Include(p => p.Blog) + .Include(p => p.Blog.User) + .Include(p => p.Comments) + .Include(p => p.Tags) + .Where(p => (p.System || isAuth) && p.Published).OrderByDescending(p => p.DatePosted) + .OrderByDescending(p => p.DatePosted) + .Take(_config.BlogConfig.PostsToLoad).ToList(); + + List postViews = new List(); + if (posts != null) + { + foreach (BlogPost post in posts) + { + postViews.Add(new PostViewModel(post)); + } + } + model.Posts = postViews; return View(model); } else // A user specific blog { - Models.Blog blog = db.Blogs.Where(p => p.User.Username == username && p.BlogId != Config.BlogConfig.ServerBlogId).FirstOrDefault(); + Models.Blog blog = _dbContext.Blogs + .Include(b => b.User) + .Include(b => b.User.BlogSettings) + .Where(p => p.User.Username == username && p.BlogId != _config.BlogConfig.ServerBlogId) + .FirstOrDefault(); // find the blog specified if (blog != null) { - ViewBag.Title = blog.User.Username + "'s Blog - " + Config.Title; + ViewBag.Title = blog.User.Username + "'s Blog - " + _config.Title; if (!string.IsNullOrEmpty(blog.User.BlogSettings.Title)) { ViewBag.Title = blog.User.BlogSettings.Title + " - " + ViewBag.Title; } ViewBag.Description = blog.User.BlogSettings.Description; bool isAuth = User.IsInRole("Admin"); - var foundPosts = db.BlogPosts.Where(p => (p.BlogId == blog.BlogId && !p.System) && - (p.Published || p.Blog.User.Username == User.Identity.Name || isAuth)).FirstOrDefault(); model = new BlogViewModel(); model.BlogId = blog.BlogId; model.UserId = blog.UserId; model.User = blog.User; model.Title = blog.User.BlogSettings.Title; model.Description = blog.User.BlogSettings.Description; - model.HasPosts = (foundPosts != null); + var posts = _dbContext.BlogPosts + .Include(p => p.Blog) + .Include(p => p.Blog.User) + .Include(p => p.Comments) + .Include(p => p.Tags) + .Where(p => (p.BlogId == blog.BlogId && !p.System) && (p.Published || p.Blog.User.Username == User.Identity.Name || isAuth)) + .OrderByDescending(p => p.DatePosted) + .Take(_config.BlogConfig.PostsToLoad).ToList(); + + List postViews = new List(); + if (posts != null) + { + foreach (BlogPost post in posts) + { + postViews.Add(new PostViewModel(post)); + } + } + model.Posts = postViews; return View(model); } @@ -81,28 +121,34 @@ namespace Teknik.Areas.Blog.Controllers #region Posts [TrackPageView] [AllowAnonymous] - public ActionResult Post(string username, int id) + public IActionResult Post(string username, int id) { if (string.IsNullOrEmpty(username)) { - return new HttpStatusCodeResult(HttpStatusCode.BadRequest); + return new StatusCodeResult((int)HttpStatusCode.BadRequest); } PostViewModel model = new PostViewModel(); // find the post specified bool isAuth = User.IsInRole("Admin"); - var post = db.BlogPosts.Where(p => p.BlogPostId == id && (p.Published || p.Blog.User.Username == User.Identity.Name || isAuth)).FirstOrDefault(); + var post = _dbContext.BlogPosts + .Include(p => p.Blog) + .Include(p => p.Blog.User) + .Include(p => p.Comments) + .Include(p => p.Tags) + .Where(p => p.BlogPostId == id && (p.Published || p.Blog.User.Username == User.Identity.Name || isAuth)) + .FirstOrDefault(); if (post != null) { model = new PostViewModel(post); if (post.System) { - ViewBag.Title = model.Title + " - " + Config.BlogConfig.Title + " - " + Config.Title; - ViewBag.Description = Config.BlogConfig.Description; + ViewBag.Title = model.Title + " - " + _config.BlogConfig.Title + " - " + _config.Title; + ViewBag.Description = _config.BlogConfig.Description; } else { - ViewBag.Title = username + "'s Blog - " + Config.Title; + ViewBag.Title = username + "'s Blog - " + _config.Title; if (!string.IsNullOrEmpty(post.Blog.User.BlogSettings.Title)) { ViewBag.Title = post.Blog.User.BlogSettings.Title + " - " + ViewBag.Title; @@ -117,27 +163,31 @@ namespace Teknik.Areas.Blog.Controllers return View("~/Areas/Blog/Views/Blog/ViewPost.cshtml", model); } - public ActionResult NewPost(string username, int blogID) + public IActionResult NewPost(string username, int blogID) { if (string.IsNullOrEmpty(username)) { - return new HttpStatusCodeResult(HttpStatusCode.BadRequest); + return new StatusCodeResult((int)HttpStatusCode.BadRequest); } BlogViewModel model = new BlogViewModel(); // find the post specified bool isAuth = User.IsInRole("Admin"); - var blog = db.Blogs.Where(p => (p.BlogId == blogID) && (p.User.Username == User.Identity.Name || isAuth)).FirstOrDefault(); + var blog = _dbContext.Blogs + .Include(b => b.User) + .Include(b => b.User.BlogSettings) + .Where(p => (p.BlogId == blogID) && (p.User.Username == User.Identity.Name || isAuth)) + .FirstOrDefault(); if (blog != null) { model = new BlogViewModel(blog); if (blog.User.Username == Constants.SERVERUSER) { - ViewBag.Title = "Create Post - " + Config.BlogConfig.Title + " - " + Config.Title; - ViewBag.Description = Config.BlogConfig.Description; + ViewBag.Title = "Create Post - " + _config.BlogConfig.Title + " - " + _config.Title; + ViewBag.Description = _config.BlogConfig.Description; } else { - ViewBag.Title = username + "'s Blog - " + Config.Title; + ViewBag.Title = username + "'s Blog - " + _config.Title; if (!string.IsNullOrEmpty(blog.User.BlogSettings.Title)) { ViewBag.Title = blog.User.BlogSettings.Title + " - " + ViewBag.Title; @@ -151,29 +201,36 @@ namespace Teknik.Areas.Blog.Controllers model.ErrorMessage = "Blog does not exist."; return View("~/Areas/Blog/Views/Blog/Blog.cshtml", model); } - public ActionResult EditPost(string username, int id) + + public IActionResult EditPost(string username, int id) { if (string.IsNullOrEmpty(username)) { - return new HttpStatusCodeResult(HttpStatusCode.BadRequest); + return new StatusCodeResult((int)HttpStatusCode.BadRequest); } PostViewModel model = new PostViewModel(); // find the post specified bool isAuth = User.IsInRole("Admin"); - var post = db.BlogPosts.Where(p => (p.Blog.User.Username == username && p.BlogPostId == id) && - (p.Published || p.Blog.User.Username == User.Identity.Name || isAuth)).FirstOrDefault(); + var post = _dbContext.BlogPosts + .Include(p => p.Blog) + .Include(p => p.Blog.User) + .Include(p => p.Comments) + .Include(p => p.Tags) + .Where(p => (p.Blog.User.Username == username && p.BlogPostId == id) && + (p.Published || p.Blog.User.Username == User.Identity.Name || isAuth)) + .FirstOrDefault(); if (post != null) { model = new PostViewModel(post); if (post.System) { - ViewBag.Title = "Edit Post - " + model.Title + " - " + Config.BlogConfig.Title + " - " + Config.Title; - ViewBag.Description = Config.BlogConfig.Description; + ViewBag.Title = "Edit Post - " + model.Title + " - " + _config.BlogConfig.Title + " - " + _config.Title; + ViewBag.Description = _config.BlogConfig.Description; } else { - ViewBag.Title = username + "'s Blog - " + Config.Title; + ViewBag.Title = username + "'s Blog - " + _config.Title; if (!string.IsNullOrEmpty(post.Blog.User.BlogSettings.Title)) { ViewBag.Title = post.Blog.User.BlogSettings.Title + " - " + ViewBag.Title; @@ -190,11 +247,20 @@ namespace Teknik.Areas.Blog.Controllers [HttpPost] [AllowAnonymous] - public ActionResult GetPosts(int blogID, int startPostID, int count) + public IActionResult GetPosts(int blogID, int startPostID, int count) { bool isAuth = User.IsInRole("Admin"); - var posts = db.BlogPosts.Where(p => ((p.BlogId == blogID && !p.System) || (p.System && blogID == Config.BlogConfig.ServerBlogId)) && - (p.Published || p.Blog.User.Username == User.Identity.Name || isAuth)).OrderByDescending(p => p.DatePosted).Skip(startPostID).Take(count).ToList(); + var posts = _dbContext.BlogPosts + .Include(p => p.Blog) + .Include(p => p.Blog.User) + .Include(p => p.Comments) + .Include(p => p.Tags) + .Where(p => ((p.BlogId == blogID && !p.System) || (p.System && blogID == _config.BlogConfig.ServerBlogId)) && + (p.Published || p.Blog.User.Username == User.Identity.Name || isAuth)) + .OrderByDescending(p => p.DatePosted) + .Skip(startPostID) + .Take(count) + .ToList(); List postViews = new List(); if (posts != null) { @@ -207,16 +273,16 @@ namespace Teknik.Areas.Blog.Controllers } [HttpPost] - public ActionResult CreatePost(CreatePostViewModel data) + public IActionResult CreatePost(CreatePostViewModel data) { BlogViewModel model = new BlogViewModel(); if (ModelState.IsValid) { bool isAuth = User.IsInRole("Admin"); - var blog = db.Blogs.Where(p => (p.BlogId == data.BlogId) && (p.User.Username == User.Identity.Name || isAuth)).FirstOrDefault(); + var blog = _dbContext.Blogs.Where(p => (p.BlogId == data.BlogId) && (p.User.Username == User.Identity.Name || isAuth)).FirstOrDefault(); if (blog != null) { - if (User.IsInRole("Admin") || db.Blogs.Where(b => b.User.Username == User.Identity.Name).FirstOrDefault() != null) + if (User.IsInRole("Admin") || _dbContext.Blogs.Where(b => b.User.Username == User.Identity.Name).FirstOrDefault() != null) { // Validate the fields if (string.IsNullOrEmpty(data.Title)) @@ -233,16 +299,16 @@ namespace Teknik.Areas.Blog.Controllers return View("~/Areas/Blog/Views/Blog/NewPost.cshtml", model); } - bool system = (data.BlogId == Config.BlogConfig.ServerBlogId); + bool system = (data.BlogId == _config.BlogConfig.ServerBlogId); if (system) { - var user = db.Blogs.Where(b => b.User.Username == User.Identity.Name); + var user = _dbContext.Blogs.Where(b => b.User.Username == User.Identity.Name); if (user != null) { data.BlogId = user.First().BlogId; } } - BlogPost post = db.BlogPosts.Create(); + BlogPost post = new BlogPost(); post.BlogId = data.BlogId; post.Title = data.Title; post.Article = data.Article; @@ -251,8 +317,8 @@ namespace Teknik.Areas.Blog.Controllers post.DatePublished = DateTime.Now; post.DateEdited = DateTime.Now; - db.BlogPosts.Add(post); - db.SaveChanges(); + _dbContext.BlogPosts.Add(post); + _dbContext.SaveChanges(); return Redirect(Url.SubRouteUrl("blog", "Blog.Post", new { username = blog.User.Username, id = post.BlogPostId })); } model.Error = true; @@ -269,12 +335,12 @@ namespace Teknik.Areas.Blog.Controllers } [HttpPost] - public ActionResult EditPost(EditPostViewModel data) + public IActionResult EditPost(EditPostViewModel data) { PostViewModel model = new PostViewModel(); if (ModelState.IsValid) { - BlogPost post = db.BlogPosts.Where(p => p.BlogPostId == data.PostId).FirstOrDefault(); + BlogPost post = _dbContext.BlogPosts.Where(p => p.BlogPostId == data.PostId).FirstOrDefault(); if (post != null) { model = new PostViewModel(post); @@ -298,8 +364,8 @@ namespace Teknik.Areas.Blog.Controllers post.Title = data.Title; post.Article = data.Article; post.DateEdited = DateTime.Now; - db.Entry(post).State = EntityState.Modified; - db.SaveChanges(); + _dbContext.Entry(post).State = EntityState.Modified; + _dbContext.SaveChanges(); return Redirect(Url.SubRouteUrl("blog", "Blog.Post", new { username = post.Blog.User.Username, id = post.BlogPostId })); } model.Error = true; @@ -316,11 +382,11 @@ namespace Teknik.Areas.Blog.Controllers } [HttpPost] - public ActionResult PublishPost(int postID, bool publish) + public IActionResult PublishPost(int postID, bool publish) { if (ModelState.IsValid) { - BlogPost post = db.BlogPosts.Where(p => p.BlogPostId == postID).FirstOrDefault(); + BlogPost post = _dbContext.BlogPosts.Where(p => p.BlogPostId == postID).FirstOrDefault(); if (post != null) { if (User.IsInRole("Admin") || post.Blog.User.Username == User.Identity.Name) @@ -328,8 +394,8 @@ namespace Teknik.Areas.Blog.Controllers post.Published = publish; if (publish) post.DatePublished = DateTime.Now; - db.Entry(post).State = EntityState.Modified; - db.SaveChanges(); + _dbContext.Entry(post).State = EntityState.Modified; + _dbContext.SaveChanges(); return Json(new { result = true }); } return Json(new { error = "You are not authorized to publish this post" }); @@ -340,17 +406,17 @@ namespace Teknik.Areas.Blog.Controllers } [HttpPost] - public ActionResult DeletePost(int postID) + public IActionResult DeletePost(int postID) { if (ModelState.IsValid) { - BlogPost post = db.BlogPosts.Where(p => p.BlogPostId == postID).FirstOrDefault(); + BlogPost post = _dbContext.BlogPosts.Where(p => p.BlogPostId == postID).FirstOrDefault(); if (post != null) { if (User.IsInRole("Admin") || post.Blog.User.Username == User.Identity.Name) { - db.BlogPosts.Remove(post); - db.SaveChanges(); + _dbContext.BlogPosts.Remove(post); + _dbContext.SaveChanges(); return Json(new { result = true }); } return Json(new { error = "You are not authorized to delete this post" }); @@ -364,9 +430,9 @@ namespace Teknik.Areas.Blog.Controllers #region Comments [HttpPost] [AllowAnonymous] - public ActionResult GetComments(int postID, int startCommentID, int count) + public IActionResult GetComments(int postID, int startCommentID, int count) { - var comments = db.BlogComments.Where(p => (p.BlogPostId == postID)).OrderByDescending(p => p.DatePosted).Skip(startCommentID).Take(count).ToList(); + var comments = _dbContext.BlogPostComments.Where(p => (p.BlogPostId == postID)).OrderByDescending(p => p.DatePosted).Skip(startCommentID).Take(count).ToList(); List commentViews = new List(); if (comments != null) { @@ -380,9 +446,9 @@ namespace Teknik.Areas.Blog.Controllers [HttpPost] [AllowAnonymous] - public ActionResult GetCommentArticle(int commentID) + public IActionResult GetCommentArticle(int commentID) { - BlogPostComment comment = db.BlogComments.Where(p => (p.BlogPostCommentId == commentID)).First(); + BlogPostComment comment = _dbContext.BlogPostComments.Where(p => (p.BlogPostCommentId == commentID)).First(); if (comment != null) { return Json(new { result = comment.Article }); @@ -391,21 +457,21 @@ namespace Teknik.Areas.Blog.Controllers } [HttpPost] - public ActionResult CreateComment(int postID, string article) + public IActionResult CreateComment(int postID, string article) { if (ModelState.IsValid) { - if (db.BlogPosts.Where(p => p.BlogPostId == postID).FirstOrDefault() != null) + if (_dbContext.BlogPosts.Where(p => p.BlogPostId == postID).FirstOrDefault() != null) { - BlogPostComment comment = db.BlogComments.Create(); + BlogPostComment comment = new BlogPostComment(); comment.BlogPostId = postID; - comment.UserId = UserHelper.GetUser(db, User.Identity.Name).UserId; + comment.UserId = UserHelper.GetUser(_dbContext, User.Identity.Name).UserId; comment.Article = article; comment.DatePosted = DateTime.Now; comment.DateEdited = DateTime.Now; - db.BlogComments.Add(comment); - db.SaveChanges(); + _dbContext.BlogPostComments.Add(comment); + _dbContext.SaveChanges(); return Json(new { result = true }); } return Json(new { error = "The post does not exist" }); @@ -414,19 +480,19 @@ namespace Teknik.Areas.Blog.Controllers } [HttpPost] - public ActionResult EditComment(int commentID, string article) + public IActionResult EditComment(int commentID, string article) { if (ModelState.IsValid) { - BlogPostComment comment = db.BlogComments.Where(c => c.BlogPostCommentId == commentID).FirstOrDefault(); + BlogPostComment comment = _dbContext.BlogPostComments.Where(c => c.BlogPostCommentId == commentID).FirstOrDefault(); if (comment != null) { if (comment.User.Username == User.Identity.Name || User.IsInRole("Admin")) { comment.Article = article; comment.DateEdited = DateTime.Now; - db.Entry(comment).State = EntityState.Modified; - db.SaveChanges(); + _dbContext.Entry(comment).State = EntityState.Modified; + _dbContext.SaveChanges(); return Json(new { result = true }); } return Json(new { error = "You don't have permission to edit this comment" }); @@ -437,17 +503,17 @@ namespace Teknik.Areas.Blog.Controllers } [HttpPost] - public ActionResult DeleteComment(int commentID) + public IActionResult DeleteComment(int commentID) { if (ModelState.IsValid) { - BlogPostComment comment = db.BlogComments.Where(c => c.BlogPostCommentId == commentID).FirstOrDefault(); + BlogPostComment comment = _dbContext.BlogPostComments.Where(c => c.BlogPostCommentId == commentID).FirstOrDefault(); if (comment != null) { if (comment.User.Username == User.Identity.Name || User.IsInRole("Admin")) { - db.BlogComments.Remove(comment); - db.SaveChanges(); + _dbContext.BlogPostComments.Remove(comment); + _dbContext.SaveChanges(); return Json(new { result = true }); } return Json(new { error = "You don't have permission to delete this comment" }); diff --git a/Teknik/Areas/Blog/Models/BlogPost.cs b/Teknik/Areas/Blog/Models/BlogPost.cs index 846138a..d6bd7f3 100644 --- a/Teknik/Areas/Blog/Models/BlogPost.cs +++ b/Teknik/Areas/Blog/Models/BlogPost.cs @@ -26,7 +26,7 @@ namespace Teknik.Areas.Blog.Models public string Article { get; set; } - public List Tags { get; set; } + public virtual ICollection Tags { get; set; } public virtual ICollection Comments { get; set; } } diff --git a/Teknik/Areas/Blog/Models/BlogPostTag.cs b/Teknik/Areas/Blog/Models/BlogPostTag.cs new file mode 100644 index 0000000..020e122 --- /dev/null +++ b/Teknik/Areas/Blog/Models/BlogPostTag.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Teknik.Areas.Blog.Models +{ + public class BlogPostTag + { + public int BlogPostTagId { get; set; } + + public int BlogPostId { get; set; } + + public virtual BlogPost BlogPost { get; set; } + + public string Name { get; set; } + + public string Description { get; set; } + } +} diff --git a/Teknik/Areas/Blog/ViewModels/BlogViewModel.cs b/Teknik/Areas/Blog/ViewModels/BlogViewModel.cs index 58804b3..a8947b4 100644 --- a/Teknik/Areas/Blog/ViewModels/BlogViewModel.cs +++ b/Teknik/Areas/Blog/ViewModels/BlogViewModel.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Collections.Generic; using Teknik.Areas.Blog.Models; using Teknik.Areas.Users.Models; using Teknik.ViewModels; @@ -21,7 +17,15 @@ namespace Teknik.Areas.Blog.ViewModels public User User { get; set; } - public bool HasPosts { get; set; } + public bool HasPosts + { + get + { + return Posts != null && Posts.Count > 0; + } + } + + public List Posts { get; set; } public BlogViewModel() { @@ -35,7 +39,7 @@ namespace Teknik.Areas.Blog.ViewModels Title = blog.User.BlogSettings.Title; Description = blog.User.BlogSettings.Description; User = blog.User; - HasPosts = false; + Posts = new List(); } } } diff --git a/Teknik/Areas/Blog/ViewModels/CommentViewModel.cs b/Teknik/Areas/Blog/ViewModels/CommentViewModel.cs index ddadb4f..32254ec 100644 --- a/Teknik/Areas/Blog/ViewModels/CommentViewModel.cs +++ b/Teknik/Areas/Blog/ViewModels/CommentViewModel.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; using Teknik.Areas.Blog.Models; using Teknik.Areas.Users.Models; using Teknik.ViewModels; diff --git a/Teknik/Areas/Blog/ViewModels/CreatePostViewModel.cs b/Teknik/Areas/Blog/ViewModels/CreatePostViewModel.cs index 1194df4..54e1359 100644 --- a/Teknik/Areas/Blog/ViewModels/CreatePostViewModel.cs +++ b/Teknik/Areas/Blog/ViewModels/CreatePostViewModel.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.Web.Mvc; -using Teknik.ViewModels; +using Teknik.ViewModels; namespace Teknik.Areas.Blog.ViewModels { @@ -12,8 +7,7 @@ namespace Teknik.Areas.Blog.ViewModels public int BlogId { get; set; } public string Title { get; set; } - - [AllowHtml] + public string Article { get; set; } } } \ No newline at end of file diff --git a/Teknik/Areas/Blog/ViewModels/EditPostViewModel.cs b/Teknik/Areas/Blog/ViewModels/EditPostViewModel.cs index a65fe47..8d6f244 100644 --- a/Teknik/Areas/Blog/ViewModels/EditPostViewModel.cs +++ b/Teknik/Areas/Blog/ViewModels/EditPostViewModel.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.Web.Mvc; -using Teknik.ViewModels; +using Teknik.ViewModels; namespace Teknik.Areas.Blog.ViewModels { @@ -12,8 +7,7 @@ namespace Teknik.Areas.Blog.ViewModels public int PostId { get; set; } public string Title { get; set; } - - [AllowHtml] + public string Article { get; set; } } } \ No newline at end of file diff --git a/Teknik/Areas/Blog/ViewModels/PostViewModel.cs b/Teknik/Areas/Blog/ViewModels/PostViewModel.cs index 1bfd542..cfecaf9 100644 --- a/Teknik/Areas/Blog/ViewModels/PostViewModel.cs +++ b/Teknik/Areas/Blog/ViewModels/PostViewModel.cs @@ -1,9 +1,7 @@ using System; using System.Collections.Generic; using Teknik.Areas.Blog.Models; -using System.Security.Principal; using System.Linq; -using System.Web; using Teknik.ViewModels; namespace Teknik.Areas.Blog.ViewModels @@ -30,7 +28,7 @@ namespace Teknik.Areas.Blog.ViewModels public string Article { get; set; } - public List Tags { get; set; } + public List Tags { get; set; } public List Comments { get; set; } @@ -50,7 +48,7 @@ namespace Teknik.Areas.Blog.ViewModels DatePublished = post.DatePublished; DateEdited = post.DateEdited; Title = post.Title; - Tags = post.Tags; + Tags = post.Tags.ToList(); Article = post.Article; Comments = post.Comments.ToList(); } diff --git a/Teknik/Areas/Blog/Views/Blog/Blog.cshtml b/Teknik/Areas/Blog/Views/Blog/Blog.cshtml index ec93366..53047ec 100644 --- a/Teknik/Areas/Blog/Views/Blog/Blog.cshtml +++ b/Teknik/Areas/Blog/Views/Blog/Blog.cshtml @@ -1,8 +1,6 @@ @model Teknik.Areas.Blog.ViewModels.BlogViewModel -@using Teknik.Utilities - - -@Styles.Render("~/Content/blog") -@Scripts.Render("~/bundles/blog") +
@if (!Model.Error) @@ -33,7 +30,7 @@

- +

@@ -46,14 +43,25 @@
} + + if (Model.HasPosts) { -
- } else diff --git a/Teknik/Areas/Blog/Views/Blog/Comment.cshtml b/Teknik/Areas/Blog/Views/Blog/Comment.cshtml index c7b45c0..0e2d733 100644 --- a/Teknik/Areas/Blog/Views/Blog/Comment.cshtml +++ b/Teknik/Areas/Blog/Views/Blog/Comment.cshtml @@ -1,7 +1,5 @@ @model Teknik.Areas.Blog.ViewModels.CommentViewModel -@using Teknik.Utilities -
diff --git a/Teknik/Areas/Blog/Views/Blog/Comments.cshtml b/Teknik/Areas/Blog/Views/Blog/Comments.cshtml index 75e1b66..f054cb8 100644 --- a/Teknik/Areas/Blog/Views/Blog/Comments.cshtml +++ b/Teknik/Areas/Blog/Views/Blog/Comments.cshtml @@ -2,5 +2,5 @@ @foreach (var comment in Model) { - @Html.Partial("Comment", comment) + @await Html.PartialAsync("Comment", comment) } diff --git a/Teknik/Areas/Blog/Views/Blog/EditPost.cshtml b/Teknik/Areas/Blog/Views/Blog/EditPost.cshtml index 0b9e168..d3bf5f0 100644 --- a/Teknik/Areas/Blog/Views/Blog/EditPost.cshtml +++ b/Teknik/Areas/Blog/Views/Blog/EditPost.cshtml @@ -1,14 +1,11 @@ @model Teknik.Areas.Blog.ViewModels.PostViewModel -@using Teknik.Utilities - - -@Styles.Render("~/Content/blog") -@Scripts.Render("~/bundles/blog") +
@if (Model.Error) @@ -25,23 +22,33 @@

Edit Post

-
+
-
+
+
+
+
+
-
-
-
- -
- +
+
+
-
+
+
+
Article
+
+
+ +
+
+
+
Preview
@@ -50,10 +57,7 @@
-
-
- -
-
- +
+ + diff --git a/Teknik/Areas/Blog/Views/Blog/NewPost.cshtml b/Teknik/Areas/Blog/Views/Blog/NewPost.cshtml index bb8707a..320fbac 100644 --- a/Teknik/Areas/Blog/Views/Blog/NewPost.cshtml +++ b/Teknik/Areas/Blog/Views/Blog/NewPost.cshtml @@ -1,14 +1,11 @@ @model Teknik.Areas.Blog.ViewModels.BlogViewModel -@using Teknik.Utilities - - -@Styles.Render("~/Content/blog") -@Scripts.Render("~/bundles/blog") +
@if (Model.Error) @@ -25,23 +22,33 @@

Create a New Post

-
+
-
+
+
+
+
+
-
-
-
- -
- +
+
+
-
+
+
+
Article
+
+
+ +
+
+
+
Preview
@@ -50,10 +57,7 @@
-
-
- -
-
- +
+ + diff --git a/Teknik/Areas/Blog/Views/Blog/Post.cshtml b/Teknik/Areas/Blog/Views/Blog/Post.cshtml index 575cecf..1a231eb 100644 --- a/Teknik/Areas/Blog/Views/Blog/Post.cshtml +++ b/Teknik/Areas/Blog/Views/Blog/Post.cshtml @@ -1,7 +1,5 @@ @model Teknik.Areas.Blog.ViewModels.PostViewModel -@using Teknik.Utilities -
diff --git a/Teknik/Areas/Blog/Views/Blog/Posts.cshtml b/Teknik/Areas/Blog/Views/Blog/Posts.cshtml index a15e8f5..538c886 100644 --- a/Teknik/Areas/Blog/Views/Blog/Posts.cshtml +++ b/Teknik/Areas/Blog/Views/Blog/Posts.cshtml @@ -2,5 +2,5 @@ @foreach (var post in Model) { - @Html.Partial("Post", post) + @await Html.PartialAsync("Post", post) } \ No newline at end of file diff --git a/Teknik/Areas/Blog/Views/Blog/ViewPost.cshtml b/Teknik/Areas/Blog/Views/Blog/ViewPost.cshtml index 506108b..7f4c06c 100644 --- a/Teknik/Areas/Blog/Views/Blog/ViewPost.cshtml +++ b/Teknik/Areas/Blog/Views/Blog/ViewPost.cshtml @@ -1,8 +1,6 @@ @model Teknik.Areas.Blog.ViewModels.PostViewModel -@using Teknik.Utilities - - -@Styles.Render("~/Content/blog") -@Scripts.Render("~/bundles/blog") + +
@if (!Model.Error) { - @Html.Partial("../../Areas/Blog/Views/Blog/Post", Model) + @await Html.PartialAsync("../../Areas/Blog/Views/Blog/Post", Model) - if (Request.IsAuthenticated) + if (User.Identity.IsAuthenticated) {
@@ -42,7 +40,7 @@ }
- @@ -50,3 +47,5 @@
+ + diff --git a/Teknik/Areas/Error/Views/Error/Http401.cshtml b/Teknik/Areas/Error/Views/Error/Http401.cshtml index 316a2c7..9a17c10 100644 --- a/Teknik/Areas/Error/Views/Error/Http401.cshtml +++ b/Teknik/Areas/Error/Views/Error/Http401.cshtml @@ -1,7 +1,5 @@ @model Teknik.Areas.Error.ViewModels.ErrorViewModel -@using Teknik.Utilities -
diff --git a/Teknik/Areas/Error/Views/Error/Http403.cshtml b/Teknik/Areas/Error/Views/Error/Http403.cshtml index 0c96ccf..ad3c47c 100644 --- a/Teknik/Areas/Error/Views/Error/Http403.cshtml +++ b/Teknik/Areas/Error/Views/Error/Http403.cshtml @@ -1,7 +1,5 @@ @model Teknik.Areas.Error.ViewModels.ErrorViewModel -@using Teknik.Utilities -
diff --git a/Teknik/Areas/Error/Views/Error/Http404.cshtml b/Teknik/Areas/Error/Views/Error/Http404.cshtml index 83c0f7d..e2a7b60 100644 --- a/Teknik/Areas/Error/Views/Error/Http404.cshtml +++ b/Teknik/Areas/Error/Views/Error/Http404.cshtml @@ -1,7 +1,5 @@ @model Teknik.Areas.Error.ViewModels.ErrorViewModel -@using Teknik.Utilities -
diff --git a/Teknik/Areas/Error/Views/Error/Http500.cshtml b/Teknik/Areas/Error/Views/Error/Http500.cshtml index 64d37a3..79d1aee 100644 --- a/Teknik/Areas/Error/Views/Error/Http500.cshtml +++ b/Teknik/Areas/Error/Views/Error/Http500.cshtml @@ -1,9 +1,6 @@ @model Teknik.Areas.Error.ViewModels.ErrorViewModel -@using Teknik.Utilities - -@Scripts.Render("~/bundles/error") - @@ -52,4 +49,4 @@
- + \ No newline at end of file diff --git a/Teknik/Areas/Error/Views/Error/General.cshtml b/Teknik/Areas/Error/Views/Error/HttpGeneral.cshtml similarity index 84% rename from Teknik/Areas/Error/Views/Error/General.cshtml rename to Teknik/Areas/Error/Views/Error/HttpGeneral.cshtml index ec40e28..600ed01 100644 --- a/Teknik/Areas/Error/Views/Error/General.cshtml +++ b/Teknik/Areas/Error/Views/Error/HttpGeneral.cshtml @@ -1,13 +1,11 @@ @model Teknik.Areas.Error.ViewModels.ErrorViewModel -@using Teknik.Utilities -
-

Http Exception

-

Status Code: @((Model.Exception as HttpException).GetHttpCode())

+

Http Error

+

Status Code: @Model.StatusCode

Sorry, an error has occured: @Model.Description
diff --git a/Teknik/Areas/Error/Views/_ViewStart.cshtml b/Teknik/Areas/Error/Views/_ViewStart.cshtml deleted file mode 100644 index 2de6241..0000000 --- a/Teknik/Areas/Error/Views/_ViewStart.cshtml +++ /dev/null @@ -1,3 +0,0 @@ -@{ - Layout = "~/Views/Shared/_Layout.cshtml"; -} diff --git a/Teknik/Areas/Error/Views/web.config b/Teknik/Areas/Error/Views/web.config deleted file mode 100644 index 013d8bf..0000000 --- a/Teknik/Areas/Error/Views/web.config +++ /dev/null @@ -1,36 +0,0 @@ - - - - - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Teknik/Areas/FAQ/Controllers/FAQController.cs b/Teknik/Areas/FAQ/Controllers/FAQController.cs index f95abda..25fbb5a 100644 --- a/Teknik/Areas/FAQ/Controllers/FAQController.cs +++ b/Teknik/Areas/FAQ/Controllers/FAQController.cs @@ -1,23 +1,27 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.Web.Mvc; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; using Teknik.Areas.FAQ.ViewModels; using Teknik.Attributes; +using Teknik.Configuration; using Teknik.Controllers; +using Teknik.Data; using Teknik.Filters; +using Teknik.Logging; namespace Teknik.Areas.FAQ.Controllers { [TeknikAuthorize] + [Area("FAQ")] public class FAQController : DefaultController { + public FAQController(ILogger logger, Config config, TeknikEntities dbContext) : base(logger, config, dbContext) { } + [TrackPageView] [AllowAnonymous] - public ActionResult Index() + public IActionResult Index() { - ViewBag.Title = "Frequently Asked Questions - " + Config.Title; + ViewBag.Title = "Frequently Asked Questions - " + _config.Title; FAQViewModel model = new FAQViewModel(); return View(model); } diff --git a/Teknik/Areas/FAQ/FAQAreaRegistration.cs b/Teknik/Areas/FAQ/FAQAreaRegistration.cs deleted file mode 100644 index 6426e63..0000000 --- a/Teknik/Areas/FAQ/FAQAreaRegistration.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Collections.Generic; -using System.Web.Mvc; -using System.Web.Optimization; -using Teknik.Configuration; -using Teknik.Utilities; - -namespace Teknik.Areas.FAQ -{ - public class FAQAreaRegistration : AreaRegistration - { - public override string AreaName - { - get - { - return "FAQ"; - } - } - - public override void RegisterArea(AreaRegistrationContext context) - { - Config config = Config.Load(); - context.MapSubdomainRoute( - "FAQ.Index", // Route name - new List() { "faq" }, - new List() { config.Host }, - "", // URL with parameters - new { controller = "FAQ", action = "Index" }, // Parameter defaults - new[] { typeof(Controllers.FAQController).Namespace } - ); - - // Register Style Bundle - BundleTable.Bundles.Add(new CdnStyleBundle("~/Content/faq", config.CdnHost).Include( - "~/Areas/FAQ/Content/FAQ.css")); - } - } -} \ No newline at end of file diff --git a/Teknik/Areas/FAQ/Views/FAQ/Index.cshtml b/Teknik/Areas/FAQ/Views/FAQ/Index.cshtml index 84e4d60..3ecb075 100644 --- a/Teknik/Areas/FAQ/Views/FAQ/Index.cshtml +++ b/Teknik/Areas/FAQ/Views/FAQ/Index.cshtml @@ -1,8 +1,6 @@ @model Teknik.Areas.FAQ.ViewModels.FAQViewModel -@using Teknik.Utilities - -@Styles.Render("~/Content/faq") +
@@ -42,7 +40,7 @@
- You can contact us via the Contact page or email us at @Model.Config.SupportEmail. + You can contact us via the Contact page or email us at @Config.SupportEmail.
@@ -121,7 +119,7 @@
- The max file size for everyone is @StringHelper.GetBytesReadable(Model.Config.UploadConfig.MaxUploadSize), basic accounts are @StringHelper.GetBytesReadable(Model.Config.UploadConfig.MaxUploadSizeBasic), and Premium accounts are @StringHelper.GetBytesReadable(Model.Config.UploadConfig.MaxUploadSizePremium). + The max file size for everyone is @StringHelper.GetBytesReadable(Config.UploadConfig.MaxUploadSize), basic accounts are @StringHelper.GetBytesReadable(Config.UploadConfig.MaxUploadSizeBasic), and Premium accounts are @StringHelper.GetBytesReadable(Config.UploadConfig.MaxUploadSizePremium).
diff --git a/Teknik/Areas/FAQ/Views/_ViewStart.cshtml b/Teknik/Areas/FAQ/Views/_ViewStart.cshtml deleted file mode 100644 index 2de6241..0000000 --- a/Teknik/Areas/FAQ/Views/_ViewStart.cshtml +++ /dev/null @@ -1,3 +0,0 @@ -@{ - Layout = "~/Views/Shared/_Layout.cshtml"; -} diff --git a/Teknik/Areas/FAQ/Views/web.config b/Teknik/Areas/FAQ/Views/web.config deleted file mode 100644 index 013d8bf..0000000 --- a/Teknik/Areas/FAQ/Views/web.config +++ /dev/null @@ -1,36 +0,0 @@ - - - - - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Teknik/Areas/Help/Controllers/HelpController.cs b/Teknik/Areas/Help/Controllers/HelpController.cs index 0f1b1ce..816403c 100644 --- a/Teknik/Areas/Help/Controllers/HelpController.cs +++ b/Teknik/Areas/Help/Controllers/HelpController.cs @@ -1,123 +1,126 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.Web.Mvc; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; using Teknik.Areas.Help.ViewModels; using Teknik.Attributes; +using Teknik.Configuration; using Teknik.Controllers; +using Teknik.Data; using Teknik.Filters; +using Teknik.Logging; namespace Teknik.Areas.Help.Controllers { [TeknikAuthorize] + [Area("Help")] public class HelpController : DefaultController { - // GET: Help/Help + public HelpController(ILogger logger, Config config, TeknikEntities dbContext) : base(logger, config, dbContext) { } + [TrackPageView] [AllowAnonymous] - public ActionResult Index() + public IActionResult Index() { - ViewBag.Title = "Help - " + Config.Title; + ViewBag.Title = "Help - " + _config.Title; HelpViewModel model = new HelpViewModel(); return View(model); } [TrackPageView] [AllowAnonymous] - public ActionResult API(string version, string service) + public IActionResult API(string version, string service) { HelpViewModel model = new HelpViewModel(); if (string.IsNullOrEmpty(version) && string.IsNullOrEmpty(service)) { - ViewBag.Title = "API Help - " + Config.Title; + ViewBag.Title = "API Help - " + _config.Title; return View("~/Areas/Help/Views/Help/API/API.cshtml", model); } else if(!string.IsNullOrEmpty(version) && !string.IsNullOrEmpty(service)) { - ViewBag.Title = service + " API " + version + " Help - " + Config.Title; + ViewBag.Title = service + " API " + version + " Help - " + _config.Title; return View("~/Areas/Help/Views/Help/API/" + version + "/" + service + ".cshtml", model); } - return RedirectToRoute("*.Error.Http404"); + return RedirectToRoute("Error.Http404"); } [TrackPageView] [AllowAnonymous] - public ActionResult Blog() + public IActionResult Blog() { - ViewBag.Title = "Blogging Help - " + Config.Title; + ViewBag.Title = "Blogging Help - " + _config.Title; HelpViewModel model = new HelpViewModel(); return View("~/Areas/Help/Views/Help/Blog.cshtml", model); } [TrackPageView] [AllowAnonymous] - public ActionResult Git() + public IActionResult Git() { - ViewBag.Title = "Git Service Help - " + Config.Title; + ViewBag.Title = "Git Service Help - " + _config.Title; HelpViewModel model = new HelpViewModel(); return View("~/Areas/Help/Views/Help/Git.cshtml", model); } [TrackPageView] [AllowAnonymous] - public ActionResult IRC() + public IActionResult IRC() { - ViewBag.Title = "IRC Server Help - " + Config.Title; + ViewBag.Title = "IRC Server Help - " + _config.Title; HelpViewModel model = new HelpViewModel(); return View("~/Areas/Help/Views/Help/IRC.cshtml", model); } [TrackPageView] [AllowAnonymous] - public ActionResult Mail() + public IActionResult Mail() { - ViewBag.Title = "Mail Server Help - " + Config.Title; + ViewBag.Title = "Mail Server Help - " + _config.Title; HelpViewModel model = new HelpViewModel(); return View("~/Areas/Help/Views/Help/Mail.cshtml", model); } [TrackPageView] [AllowAnonymous] - public ActionResult Markdown() + public IActionResult Markdown() { - ViewBag.Title = "Markdown Help - " + Config.Title; + ViewBag.Title = "Markdown Help - " + _config.Title; HelpViewModel model = new HelpViewModel(); return View("~/Areas/Help/Views/Help/Markdown.cshtml", model); } [TrackPageView] [AllowAnonymous] - public ActionResult Mumble() + public IActionResult Mumble() { - ViewBag.Title = "Mumble Server Help - " + Config.Title; + ViewBag.Title = "Mumble Server Help - " + _config.Title; HelpViewModel model = new HelpViewModel(); return View("~/Areas/Help/Views/Help/Mumble.cshtml", model); } [TrackPageView] [AllowAnonymous] - public ActionResult RSS() + public IActionResult RSS() { - ViewBag.Title = "RSS Help - " + Config.Title; + ViewBag.Title = "RSS Help - " + _config.Title; HelpViewModel model = new HelpViewModel(); return View("~/Areas/Help/Views/Help/RSS.cshtml", model); } [TrackPageView] [AllowAnonymous] - public ActionResult Tools() + public IActionResult Tools() { - ViewBag.Title = "Tool Help - " + Config.Title; + ViewBag.Title = "Tool Help - " + _config.Title; HelpViewModel model = new HelpViewModel(); return View("~/Areas/Help/Views/Help/Tools.cshtml", model); } [TrackPageView] [AllowAnonymous] - public ActionResult Upload() + public IActionResult Upload() { - ViewBag.Title = "Upload Service Help - " + Config.Title; + ViewBag.Title = "Upload Service Help - " + _config.Title; HelpViewModel model = new HelpViewModel(); return View("~/Areas/Help/Views/Help/Upload.cshtml", model); } diff --git a/Teknik/Areas/Help/HelpAreaRegistration.cs b/Teknik/Areas/Help/HelpAreaRegistration.cs deleted file mode 100644 index 23218ca..0000000 --- a/Teknik/Areas/Help/HelpAreaRegistration.cs +++ /dev/null @@ -1,116 +0,0 @@ -using System.Collections.Generic; -using System.Web.Mvc; -using System.Web.Optimization; -using Teknik.Configuration; -using Teknik.Utilities; - -namespace Teknik.Areas.Help -{ - public class HelpAreaRegistration : AreaRegistration - { - public override string AreaName - { - get - { - return "Help"; - } - } - - public override void RegisterArea(AreaRegistrationContext context) - { - Config config = Config.Load(); - context.MapSubdomainRoute( - "Help.Index", // Route name - new List() { "help" }, // Subdomains - new List() { config.Host }, // domains - "", // URL with parameters - new { controller = "Help", action = "Index" }, // Parameter defaults - new[] { typeof(Controllers.HelpController).Namespace } - ); - context.MapSubdomainRoute( - "Help.API", // Route name - new List() { "help" }, // Subdomains - new List() { config.Host }, // domains - "API/{version}/{service}", // URL with parameters - new { controller = "Help", action = "API", version = UrlParameter.Optional, service = UrlParameter.Optional }, // Parameter defaults - new[] { typeof(Controllers.HelpController).Namespace } - ); - context.MapSubdomainRoute( - "Help.Blog", // Route name - new List() { "help" }, // Subdomains - new List() { config.Host }, // domains - "Blog", // URL with parameters - new { controller = "Help", action = "Blog" }, // Parameter defaults - new[] { typeof(Controllers.HelpController).Namespace } - ); - context.MapSubdomainRoute( - "Help.Git", // Route name - new List() { "help" }, // Subdomains - new List() { config.Host }, // domains - "Git", // URL with parameters - new { controller = "Help", action = "Git" }, // Parameter defaults - new[] { typeof(Controllers.HelpController).Namespace } - ); - context.MapSubdomainRoute( - "Help.IRC", // Route name - new List() { "help" }, // Subdomains - new List() { config.Host }, // domains - "IRC", // URL with parameters - new { controller = "Help", action = "IRC" }, // Parameter defaults - new[] { typeof(Controllers.HelpController).Namespace } - ); - context.MapSubdomainRoute( - "Help.Mail", // Route name - new List() { "help" }, // Subdomains - new List() { config.Host }, // domains - "Mail", // URL with parameters - new { controller = "Help", action = "Mail" }, // Parameter defaults - new[] { typeof(Controllers.HelpController).Namespace } - ); - context.MapSubdomainRoute( - "Help.Markdown", // Route name - new List() { "help" }, // Subdomains - new List() { config.Host }, // domains - "Markdown", // URL with parameters - new { controller = "Help", action = "Markdown" }, // Parameter defaults - new[] { typeof(Controllers.HelpController).Namespace } - ); - context.MapSubdomainRoute( - "Help.Mumble", // Route name - new List() { "help" }, // Subdomains - new List() { config.Host }, // domains - "Mumble", // URL with parameters - new { controller = "Help", action = "Mumble" }, // Parameter defaults - new[] { typeof(Controllers.HelpController).Namespace } - ); - context.MapSubdomainRoute( - "Help.RSS", // Route name - new List() { "help" }, // Subdomains - new List() { config.Host }, // domains - "RSS", // URL with parameters - new { controller = "Help", action = "RSS" }, // Parameter defaults - new[] { typeof(Controllers.HelpController).Namespace } - ); - context.MapSubdomainRoute( - "Help.Tools", // Route name - new List() { "help" }, // Subdomains - new List() { config.Host }, // domains - "Tools", // URL with parameters - new { controller = "Help", action = "Tools" }, // Parameter defaults - new[] { typeof(Controllers.HelpController).Namespace } - ); - context.MapSubdomainRoute( - "Help.Upload", // Route name - new List() { "help" }, // Subdomains - new List() { config.Host }, // domains - "Upload", // URL with parameters - new { controller = "Help", action = "Upload" }, // Parameter defaults - new[] { typeof(Controllers.HelpController).Namespace } - ); - - // Register Style Bundles - BundleTable.Bundles.Add(new CdnStyleBundle("~/Content/help", config.CdnHost).Include( - "~/Areas/Help/Content/Help.css")); - } - } -} \ No newline at end of file diff --git a/Teknik/Areas/Help/Views/Help/API/API.cshtml b/Teknik/Areas/Help/Views/Help/API/API.cshtml index 6784879..ac2649e 100644 --- a/Teknik/Areas/Help/Views/Help/API/API.cshtml +++ b/Teknik/Areas/Help/Views/Help/API/API.cshtml @@ -1,8 +1,6 @@ @model Teknik.Areas.Help.ViewModels.HelpViewModel -@using Teknik.Utilities - -@Styles.Render("~/Content/help"); +