1
0
mirror of https://git.teknik.io/Teknikode/Teknik.git synced 2023-08-02 14:16:22 +02:00

Ported existing projects to Asp.Net Core (Except ServerMaint)

This commit is contained in:
Uncled1023 2018-06-14 17:57:03 -07:00
parent 2980817d57
commit 5eb45263d9
619 changed files with 11016 additions and 101090 deletions

View File

@ -1,9 +1,7 @@
root = true
[*] [*]
charset = utf-8
indent_style = space
indent_size = 4 indent_size = 4
indent_style = space
end_of_line = crlf end_of_line = crlf
trim_trailing_whitespace = false
insert_final_newline = true [*.cshtml]
indent_size = 4

149
.gitignore vendored
View File

@ -4,26 +4,34 @@
# User-specific files # User-specific files
*.suo *.suo
*.user *.user
*.userosscache
*.sln.docstates *.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results # Build results
[Dd]ebug/ [Dd]ebug/
[Dd]ebugPublic/ [Dd]ebugPublic/
[Rr]elease/ [Rr]elease/
[Rr]eleases/
x64/ x64/
build/ x86/
bld/ bld/
[Bb]in/ [Bb]in/
[Oo]bj/ [Oo]bj/
[Ll]og/
# Roslyn cache directories # Visual Studio 2015 cache/options directory
*.ide/ .vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
wwwroot/
# MSTest test Results # MSTest test Results
[Tt]est[Rr]esult*/ [Tt]est[Rr]esult*/
[Bb]uild[Ll]og.* [Bb]uild[Ll]og.*
#NUNIT # NUNIT
*.VisualState.xml *.VisualState.xml
TestResult.xml TestResult.xml
@ -32,6 +40,11 @@ TestResult.xml
[Rr]eleasePS/ [Rr]eleasePS/
dlldata.c dlldata.c
# DNX
project.lock.json
project.fragment.lock.json
artifacts/
*_i.c *_i.c
*_p.c *_p.c
*_i.h *_i.h
@ -64,14 +77,18 @@ _Chutzpah*
ipch/ ipch/
*.aps *.aps
*.ncb *.ncb
*.opendb
*.opensdf *.opensdf
*.sdf *.sdf
*.cachefile *.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler # Visual Studio profiler
*.psess *.psess
*.vsp *.vsp
*.vspx *.vspx
*.sap
# TFS 2012 Local Workspace # TFS 2012 Local Workspace
$tf/ $tf/
@ -84,7 +101,7 @@ _ReSharper*/
*.[Rr]e[Ss]harper *.[Rr]e[Ss]harper
*.DotSettings.user *.DotSettings.user
# JustCode is a .NET coding addin-in # JustCode is a .NET coding add-in
.JustCode .JustCode
# TeamCity is a build add-in # TeamCity is a build add-in
@ -96,6 +113,7 @@ _TeamCity*
# NCrunch # NCrunch
_NCrunch_* _NCrunch_*
.*crunch*.local.xml .*crunch*.local.xml
nCrunchTemp_*
# MightyMoose # MightyMoose
*.mm.* *.mm.*
@ -123,43 +141,63 @@ publish/
# Publish Web Output # Publish Web Output
*.[Pp]ublish.xml *.[Pp]ublish.xml
*.azurePubxml *.azurePubxml
## TODO: Comment the next line if you want to checkin your # TODO: Comment the next line if you want to checkin your web deploy settings
## web deploy settings but do note that will include unencrypted # but database connection strings (with potential passwords) will be unencrypted
## passwords
#*.pubxml #*.pubxml
*.publishproj
# NuGet Packages Directory # Microsoft Azure Web App publish settings. Comment the next line if you want to
packages/* # checkin your Azure Web App publish settings, but sensitive information contained
## TODO: If the tool you use requires repositories.config # in these scripts will be unencrypted
## uncomment the next line PublishScripts/
#!packages/repositories.config
# Enable "build/" folder in the NuGet Packages folder since # NuGet Packages
# NuGet packages use it for MSBuild targets. *.nupkg
# This line needs to be after the ignore of the build folder # The packages folder can be ignored because of Package Restore
# (and the packages folder if the line above has been uncommented) **/packages/*
!packages/build/ # 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/ csx/
*.build.csdef *.build.csdef
# Windows Store app package directory # Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/ 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 # Others
sql/
*.Cache
ClientBin/ ClientBin/
[Ss]tyle[Cc]op.*
~$* ~$*
*~ *~
*.dbmdl *.dbmdl
*.dbproj.schemaview *.dbproj.schemaview
*.jfm
*.pfx *.pfx
*.publishsettings *.publishsettings
node_modules/ 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 # RIA/Silverlight projects
Generated_Code/ Generated_Code/
@ -184,26 +222,45 @@ UpgradeLog*.htm
# Microsoft Fakes # Microsoft Fakes
FakesAssemblies/ FakesAssemblies/
# LightSwitch generated files # GhostDoc plugin setting file
GeneratedArtifacts/ *.GhostDoc.xml
_Pvt_Extensions/
ModelManifest.xml # Node.js Tools for Visual Studio
/Teknik/ConnectionStrings.config .ntvs_analysis.dat
/Teknik/App_Data/Config.json
/.vs/config/applicationhost.config # Visual Studio 6 build log
/Teknik/TransformWebConfig/assist/Web.config *.plg
/Teknik/Properties/PublishProfiles/IIS.pubxml
/Teknik/App_Data/ConnectionStrings.config # Visual Studio 6 workspace options file
/Teknik/App_Data/Config.json.old *.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 /Teknik/App_Data/MachineKey.config
/.vs/Teknik/v15/sqlite3/storage.ide /Teknik/App_Data/ConnectionStrings.config
/.vs/Teknik/v15/sqlite3/storage.ide-wal /Teknik/App_Data/Config.json
/.vs/Teknik/v15/sqlite3/storage.ide-shm /Teknik/appsettings.Production.json
/.vs/Teknik/v15/sqlite3/db.lock /Teknik/appsettings.Development.json
/.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

View File

@ -1,10 +1,4 @@
using System; namespace Teknik.Configuration
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Teknik.Configuration
{ {
public class ApiConfig public class ApiConfig
{ {

View File

@ -1,9 +1,4 @@
using System; namespace Teknik.Configuration
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace Teknik.Configuration
{ {
public class BlogConfig public class BlogConfig
{ {

View File

@ -1,10 +1,7 @@
using Newtonsoft.Json;
using System; using System;
using System.IO; using System.IO;
using System.Threading; using System.Threading;
using System.Web;
using System.Web.Caching;
using Newtonsoft.Json;
using Teknik.Utilities;
using Teknik.Utilities.Cryptography; using Teknik.Utilities.Cryptography;
namespace Teknik.Configuration namespace Teknik.Configuration
@ -12,9 +9,13 @@ namespace Teknik.Configuration
public class Config public class Config
{ {
private const string _ConfigCacheKey = "ConfigCache"; private const string _ConfigCacheKey = "ConfigCache";
private const string _ConfigFileName = "Config.json";
private static Config _Config { get; set; } private static Config _Config { get; set; }
private static string _FileHash { get; set; }
private ReaderWriterLockSlim _ConfigRWLock;
private ReaderWriterLockSlim _ConfigFileRWLock;
private JsonSerializerSettings _JsonSettings; private JsonSerializerSettings _JsonSettings;
private bool _DevEnvironment; private bool _DevEnvironment;
@ -117,6 +118,8 @@ namespace Teknik.Configuration
public Config() public Config()
{ {
_ConfigRWLock = new ReaderWriterLockSlim();
_ConfigFileRWLock = new ReaderWriterLockSlim();
_JsonSettings = new JsonSerializerSettings(); _JsonSettings = new JsonSerializerSettings();
_JsonSettings.Formatting = Formatting.Indented; _JsonSettings.Formatting = Formatting.Indented;
@ -168,39 +171,26 @@ namespace Teknik.Configuration
return JsonConvert.SerializeObject(config, Formatting.Indented); 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) public static Config Load(string path)
{ {
Config config = new Config(); string newHash = string.Empty;
if (!File.Exists(Path.Combine(path, "Config.json"))) string fullPath = Path.Combine(path, _ConfigFileName);
{
Save(Path.Combine(path, "Config.json"), config);
}
else
{
string configContents = File.ReadAllText(Path.Combine(path, "Config.json"));
config = Deserialize(configContents);
}
return config;
}
public static void Save(Config config) if (!File.Exists(fullPath))
{ {
string path = AppDomain.CurrentDomain.GetData("DataDirectory").ToString(); Config config = new Config();
Save(Path.Combine(path, "Config.json"), 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) public static void Save(string path, Config config)

View File

@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<RootNamespace>Teknik.Configuration</RootNamespace>
<AssemblyName>Teknik.Configuration</AssemblyName>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Utilities\Utilities.csproj" />
</ItemGroup>
</Project>

View File

@ -1,11 +1,4 @@
using System; namespace Teknik.Configuration
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Mail;
namespace Teknik.Configuration
{ {
public class ContactConfig public class ContactConfig
{ {

View File

@ -1,10 +1,4 @@
using System; namespace Teknik.Configuration
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Teknik.Configuration
{ {
public class EmailAccount public class EmailAccount
{ {

View File

@ -1,9 +1,4 @@
using System; namespace Teknik.Configuration
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace Teknik.Configuration
{ {
public class EmailConfig public class EmailConfig
{ {

View File

@ -1,10 +1,4 @@
using System; namespace Teknik.Configuration
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Teknik.Configuration
{ {
public class GitConfig public class GitConfig
{ {

View File

@ -1,10 +1,4 @@
using System; namespace Teknik.Configuration
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Teknik.Configuration
{ {
public class IRCConfig public class IRCConfig
{ {

View File

@ -1,9 +1,4 @@
using System; namespace Teknik.Configuration
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace Teknik.Configuration
{ {
public class LoggingConfig public class LoggingConfig
{ {

View File

@ -1,10 +1,4 @@
using System; namespace Teknik.Configuration
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Teknik.Configuration
{ {
public class PasteConfig public class PasteConfig
{ {

View File

@ -1,10 +1,4 @@
using System; namespace Teknik.Configuration
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Teknik.Configuration
{ {
public class PiwikConfig public class PiwikConfig
{ {

View File

@ -1,8 +1,4 @@
using System; using System.IO;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
namespace Teknik.Configuration namespace Teknik.Configuration
{ {

View File

@ -1,9 +1,4 @@
using System; namespace Teknik.Configuration
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace Teknik.Configuration
{ {
public class ShortenerConfig public class ShortenerConfig
{ {

View File

@ -1,10 +1,4 @@
using System; namespace Teknik.Configuration
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Teknik.Configuration
{ {
public class StatsConfig public class StatsConfig
{ {

View File

@ -1,8 +1,4 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Teknik.Configuration namespace Teknik.Configuration
{ {

View File

@ -1,8 +1,5 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Web;
namespace Teknik.Configuration namespace Teknik.Configuration
{ {

View File

@ -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 namespace Teknik.Configuration
{ {
public class UserConfig public class UserConfig

View File

@ -1,9 +1,4 @@
using System; namespace Teknik.Configuration
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace Teknik.Configuration
{ {
public class VaultConfig public class VaultConfig
{ {

View File

@ -1,2 +0,0 @@
assembly-versioning-scheme: MajorMinorPatch
next-version: 2.0.6

View File

@ -1,8 +1,5 @@
using System; using Microsoft.Extensions.Logging;
using System.Collections.Generic; using System;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Teknik.Utilities; using Teknik.Utilities;
namespace Teknik.Logging namespace Teknik.Logging
@ -21,7 +18,7 @@ namespace Teknik.Logging
public void SetDefaults() public void SetDefaults()
{ {
Level = LogLevel.Info; Level = LogLevel.Information;
EntryDate = DateTime.Now; EntryDate = DateTime.Now;
Message = string.Empty; Message = string.Empty;
Exception = null; Exception = null;

161
Logging/Logger.cs Normal file
View File

@ -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<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> 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>(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<string> 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 */
}
}
}
}

View File

@ -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;
}
}
}

30
Logging/LoggerProvider.cs Normal file
View File

@ -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<string, Logger> _loggers = new ConcurrentDictionary<string, Logger>();
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();
}
}
}

14
Logging/Logging.csproj Normal file
View File

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<AssemblyName>Teknik.Logging</AssemblyName>
<RootNamespace>Teknik.Logging</RootNamespace>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Configuration\Configuration.csproj" />
<ProjectReference Include="..\Utilities\Utilities.csproj" />
</ItemGroup>
</Project>

126
MailService/HMailService.cs Normal file
View File

@ -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];
}
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Teknik.MailService</AssemblyName>
<RootNamespace>Teknik.MailService</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MySql.Data" Version="8.0.11" />
</ItemGroup>
<ItemGroup>
<Reference Include="Teknik.hMailServer">
<HintPath>lib\Teknik.hMailServer.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

View File

@ -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<string> 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<Dictionary<string, object>> Query(string query, params object[] args)
{
List<Dictionary<string, object>> rows = new List<Dictionary<string, object>>();
if (Connected)
{
DatabaseLock.EnterWriteLock();
MySqlCommand cmd = PrepareQuery(query, args);
try
{
MySqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
Dictionary<string, object> row = new Dictionary<string, object>();
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;
}
}
}

Binary file not shown.

13
Piwik/Piwik.csproj Normal file
View File

@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<AssemblyName>Teknik.Piwik</AssemblyName>
<RootNamespace>Teknik.Piwik</RootNamespace>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Configuration\Configuration.csproj" />
</ItemGroup>
</Project>

96
Piwik/Reporting.cs Normal file
View File

@ -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<VisitorData> GetVisitSummaryByDays(Config config, int days)
{
List<VisitorData> visitorData = new List<VisitorData>();
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;
}
}
}

93
Piwik/Tracking.cs Normal file
View File

@ -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)
// {
// }
//}
}
}

View File

@ -1,125 +1,62 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15 # Visual Studio 15
VisualStudioVersion = 15.0.26430.15 VisualStudioVersion = 15.0.27512.0
MinimumVisualStudioVersion = 10.0.40219.1 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 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 ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig .editorconfig = .editorconfig
GitVersionConfig.yaml = GitVersionConfig.yaml .gitattributes = .gitattributes
README.md = README.md .gitignore = .gitignore
EndProjectSection EndProjectSection
EndProject 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 EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{783361EC-DCD6-4A34-8479-5476DF752C34}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MailService", "MailService\MailService.csproj", "{03636C30-DA61-4307-8934-2FCC3BAC3255}"
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}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Release|Any CPU = Release|Any CPU Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B20317CD-76C6-4A7B-BCE1-E4BEF8E4F964}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1E52F0D0-9E89-4022-A905-C685EF3564E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B20317CD-76C6-4A7B-BCE1-E4BEF8E4F964}.Debug|Any CPU.Build.0 = Debug|Any CPU {1E52F0D0-9E89-4022-A905-C685EF3564E1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B20317CD-76C6-4A7B-BCE1-E4BEF8E4F964}.Debug|x64.ActiveCfg = Debug|x64 {1E52F0D0-9E89-4022-A905-C685EF3564E1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B20317CD-76C6-4A7B-BCE1-E4BEF8E4F964}.Debug|x64.Build.0 = Debug|x64 {1E52F0D0-9E89-4022-A905-C685EF3564E1}.Release|Any CPU.Build.0 = Release|Any CPU
{B20317CD-76C6-4A7B-BCE1-E4BEF8E4F964}.Debug|x64.Deploy.0 = Debug|x64 {7A1F40CA-7C37-4B7B-973A-CDCDD424F31F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B20317CD-76C6-4A7B-BCE1-E4BEF8E4F964}.Release|Any CPU.ActiveCfg = Release|Any CPU {7A1F40CA-7C37-4B7B-973A-CDCDD424F31F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B20317CD-76C6-4A7B-BCE1-E4BEF8E4F964}.Release|Any CPU.Build.0 = Release|Any CPU {7A1F40CA-7C37-4B7B-973A-CDCDD424F31F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B20317CD-76C6-4A7B-BCE1-E4BEF8E4F964}.Release|x64.ActiveCfg = Release|x64 {7A1F40CA-7C37-4B7B-973A-CDCDD424F31F}.Release|Any CPU.Build.0 = Release|Any CPU
{B20317CD-76C6-4A7B-BCE1-E4BEF8E4F964}.Release|x64.Build.0 = Release|x64 {DD521101-7F10-407A-9788-49283D946FDA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E08975F9-1B84-41B0-875A-CEC9778C4F9E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DD521101-7F10-407A-9788-49283D946FDA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E08975F9-1B84-41B0-875A-CEC9778C4F9E}.Debug|Any CPU.Build.0 = Debug|Any CPU {DD521101-7F10-407A-9788-49283D946FDA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E08975F9-1B84-41B0-875A-CEC9778C4F9E}.Debug|x64.ActiveCfg = Debug|Any CPU {DD521101-7F10-407A-9788-49283D946FDA}.Release|Any CPU.Build.0 = Release|Any CPU
{E08975F9-1B84-41B0-875A-CEC9778C4F9E}.Debug|x64.Build.0 = Debug|Any CPU {3CAB11F5-9B07-4D17-BB00-725149087AB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E08975F9-1B84-41B0-875A-CEC9778C4F9E}.Release|Any CPU.ActiveCfg = Release|Any CPU {3CAB11F5-9B07-4D17-BB00-725149087AB0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E08975F9-1B84-41B0-875A-CEC9778C4F9E}.Release|Any CPU.Build.0 = Release|Any CPU {3CAB11F5-9B07-4D17-BB00-725149087AB0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E08975F9-1B84-41B0-875A-CEC9778C4F9E}.Release|x64.ActiveCfg = Release|Any CPU {3CAB11F5-9B07-4D17-BB00-725149087AB0}.Release|Any CPU.Build.0 = Release|Any CPU
{E08975F9-1B84-41B0-875A-CEC9778C4F9E}.Release|x64.Build.0 = Release|Any CPU {F8823907-092C-4055-9F8E-D6756793C24A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F45DE6FC-3754-4954-A20A-4277362CC6C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F8823907-092C-4055-9F8E-D6756793C24A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F45DE6FC-3754-4954-A20A-4277362CC6C1}.Debug|Any CPU.Build.0 = Debug|Any CPU {F8823907-092C-4055-9F8E-D6756793C24A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F45DE6FC-3754-4954-A20A-4277362CC6C1}.Debug|x64.ActiveCfg = Debug|Any CPU {F8823907-092C-4055-9F8E-D6756793C24A}.Release|Any CPU.Build.0 = Release|Any CPU
{F45DE6FC-3754-4954-A20A-4277362CC6C1}.Debug|x64.Build.0 = Debug|Any CPU {03636C30-DA61-4307-8934-2FCC3BAC3255}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F45DE6FC-3754-4954-A20A-4277362CC6C1}.Release|Any CPU.ActiveCfg = Release|Any CPU {03636C30-DA61-4307-8934-2FCC3BAC3255}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F45DE6FC-3754-4954-A20A-4277362CC6C1}.Release|Any CPU.Build.0 = Release|Any CPU {03636C30-DA61-4307-8934-2FCC3BAC3255}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F45DE6FC-3754-4954-A20A-4277362CC6C1}.Release|x64.ActiveCfg = Release|Any CPU {03636C30-DA61-4307-8934-2FCC3BAC3255}.Release|Any CPU.Build.0 = 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
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
EndGlobalSection EndGlobalSection
GlobalSection(NestedProjects) = preSolution GlobalSection(ExtensibilityGlobals) = postSolution
{E08975F9-1B84-41B0-875A-CEC9778C4F9E} = {783361EC-DCD6-4A34-8479-5476DF752C34} SolutionGuid = {D5D09AC6-1E27-476C-BF7E-980E1640F432}
{88DEB506-3F7E-4B39-8264-861976DC7434} = {FAC9FE6E-9AA9-45AD-AA72-40DDF7DC44C6}
{9D7A805E-2629-476E-B36A-040AD332C7DC} = {FAC9FE6E-9AA9-45AD-AA72-40DDF7DC44C6}
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

View File

@ -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"));
}
}
}

View File

@ -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"
};
}
}
}

View File

@ -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());
}
}
}

View File

@ -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" }
);
}
}
}

View File

@ -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<string> Subdomains { get; set; }
public List<string> Domains { get; set; }
public SubdomainRoute(List<string> subdomains, List<string> domains, string url, IRouteHandler handler)
: base(url, handler)
{
this.Subdomains = subdomains;
this.Domains = domains;
}
public SubdomainRoute(List<string> subdomains, List<string> domains, string url, RouteValueDictionary defaults, IRouteHandler handler)
: base(url, defaults, handler)
{
this.Subdomains = subdomains;
this.Domains = domains;
}
public SubdomainRoute(List<string> subdomains, List<string> domains, string url, RouteValueDictionary defaults, RouteValueDictionary constraints, IRouteHandler handler)
: base(url, defaults, constraints, handler)
{
this.Subdomains = subdomains;
this.Domains = domains;
}
public SubdomainRoute(List<string> subdomains, List<string> 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
}
}
}

View File

@ -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<string> subDomains, List<string> 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<string> subDomains, List<string> 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<string> subDomains, List<string> 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<string> subDomains, List<string> 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<string> subDomains, List<string> 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<string> subDomains, List<string> 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<string> subDomains, List<string> 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<string> subDomains, List<string> 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<string> subDomains, List<string> 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<string> subDomains, List<string> 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;
}
}
}

View File

@ -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<string>() { "api" },
new List<string>() { 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<string>() { "api" },
new List<string>() { 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<string>() { "api" },
new List<string>() { 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<string>() { "api" },
new List<string>() { 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<string>() { "api" },
new List<string>() { config.Host },
"", // URL with parameters
new { controller = "API", action = "Index" }, // Parameter defaults
new[] { typeof(Controllers.APIController).Namespace }
);
}
}
}

View File

@ -1,23 +1,30 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data.Entity;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Web; using System.Web;
using System.Web.Mvc;
using Teknik.Areas.Upload; using Teknik.Areas.Upload;
using Teknik.Controllers; using Teknik.Controllers;
using Teknik.Utilities; using Teknik.Utilities;
using Teknik.Models; using Teknik.Models;
using Teknik.Attributes; 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 namespace Teknik.Areas.API.Controllers
{ {
[TeknikAuthorize] [TeknikAuthorize]
[Area("API")]
public class APIController : DefaultController public class APIController : DefaultController
{ {
public APIController(ILogger<Logger> logger, Config config, TeknikEntities dbContext) : base(logger, config, dbContext) { }
[AllowAnonymous] [AllowAnonymous]
public ActionResult Index() public IActionResult Index()
{ {
return Redirect(Url.SubRouteUrl("help", "Help.API")); return Redirect(Url.SubRouteUrl("help", "Help.API"));
} }

View File

@ -1,10 +1,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data.Entity;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Web; using System.Web;
using System.Web.Mvc;
using Teknik.Areas.Upload; using Teknik.Areas.Upload;
using Teknik.Areas.Paste; using Teknik.Areas.Paste;
using Teknik.Controllers; using Teknik.Controllers;
@ -20,14 +18,26 @@ using Teknik.Areas.API.Models;
using Teknik.Areas.Users.Models; using Teknik.Areas.Users.Models;
using Teknik.Areas.Users.Utility; using Teknik.Areas.Users.Utility;
using Teknik.Attributes; 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 namespace Teknik.Areas.API.Controllers
{ {
[TeknikAuthorize(AuthType.Basic)] [TeknikAuthorize(AuthType.Basic)]
[Area("APIv1")]
public class APIv1Controller : DefaultController public class APIv1Controller : DefaultController
{ {
public APIv1Controller(ILogger<Logger> logger, Config config, TeknikEntities dbContext) : base(logger, config, dbContext) { }
[AllowAnonymous] [AllowAnonymous]
public ActionResult Index() public IActionResult Index()
{ {
return Redirect(Url.SubRouteUrl("help", "Help.API")); return Redirect(Url.SubRouteUrl("help", "Help.API"));
} }
@ -35,35 +45,36 @@ namespace Teknik.Areas.API.Controllers
[HttpPost] [HttpPost]
[AllowAnonymous] [AllowAnonymous]
[TrackPageView] [TrackPageView]
public ActionResult Upload(APIv1UploadModel model) public async Task<IActionResult> UploadAsync(APIv1UploadModel model)
{ {
try try
{ {
if (Config.UploadConfig.UploadEnabled) if (_config.UploadConfig.UploadEnabled)
{ {
if (model.file != null) if (model.file != null)
{ {
long maxUploadSize = Config.UploadConfig.MaxUploadSize; long maxUploadSize = _config.UploadConfig.MaxUploadSize;
if (User.Identity.IsAuthenticated) if (User.Identity.IsAuthenticated)
{ {
maxUploadSize = Config.UploadConfig.MaxUploadSizeBasic; maxUploadSize = _config.UploadConfig.MaxUploadSizeBasic;
if (User.Info.AccountType == AccountType.Premium) 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 // convert file to bytes
string fileExt = Path.GetExtension(model.file.FileName); string fileExt = Path.GetExtension(model.file.FileName);
int contentLength = model.file.ContentLength; long contentLength = model.file.Length;
// Scan the file to detect a virus // 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; clam.MaxStreamSize = maxUploadSize;
ClamScanResult scanResult = clam.SendAndScanFile(model.file.InputStream); ClamScanResult scanResult = await clam.SendAndScanFileAsync(model.file.OpenReadStream());
switch (scanResult.Result) switch (scanResult.Result)
{ {
@ -85,13 +96,16 @@ namespace Teknik.Areas.API.Controllers
if (string.IsNullOrEmpty(model.contentType)) if (string.IsNullOrEmpty(model.contentType))
{ {
model.file.InputStream.Seek(0, SeekOrigin.Begin); using (System.IO.Stream fileStream = model.file.OpenReadStream())
FileType fileType = model.file.InputStream.GetFileType();
if (fileType != null)
model.contentType = fileType.Mime;
if (string.IsNullOrEmpty(model.contentType))
{ {
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 // Check content type restrictions (Only for encrypting server side
if (model.encrypt || !string.IsNullOrEmpty(model.key)) 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" } }); 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 // Initialize the key size and block size if empty
if (model.keySize <= 0) if (model.keySize <= 0)
model.keySize = Config.UploadConfig.KeySize; model.keySize = _config.UploadConfig.KeySize;
if (model.blockSize <= 0) 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 string fileKey = upload.Key;
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);
if (upload != null) // Associate this with the user if they provided an auth key
if (User.Identity.IsAuthenticated)
{ {
string fileKey = upload.Key; User foundUser = UserHelper.GetUser(_dbContext, User.Identity.Name);
if (foundUser != null)
// Associate this with the user if they provided an auth key
if (User.Identity.IsAuthenticated)
{ {
User foundUser = UserHelper.GetUser(db, User.Identity.Name); upload.UserId = foundUser.UserId;
if (foundUser != null) _dbContext.Entry(upload).State = EntityState.Modified;
{ _dbContext.SaveChanges();
upload.UserId = foundUser.UserId;
db.Entry(upload).State = EntityState.Modified;
db.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 else
{ {
@ -186,42 +198,39 @@ namespace Teknik.Areas.API.Controllers
[HttpPost] [HttpPost]
[AllowAnonymous] [AllowAnonymous]
[TrackPageView] [TrackPageView]
public ActionResult Paste(APIv1PasteModel model) public IActionResult Paste(APIv1PasteModel model)
{ {
try try
{ {
if (model != null && model.code != null) 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); User foundUser = UserHelper.GetUser(_dbContext, User.Identity.Name);
if (foundUser != null)
// Associate this with the user if they are logged in
if (User.Identity.IsAuthenticated)
{ {
User foundUser = UserHelper.GetUser(db, User.Identity.Name); paste.UserId = foundUser.UserId;
if (foundUser != null)
{
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" } }); return Json(new { error = new { message = "Invalid Paste Request" } });
} }
@ -234,44 +243,41 @@ namespace Teknik.Areas.API.Controllers
[HttpPost] [HttpPost]
[AllowAnonymous] [AllowAnonymous]
[TrackPageView] [TrackPageView]
public ActionResult Shorten(APIv1ShortenModel model) public IActionResult Shorten(APIv1ShortenModel model)
{ {
try try
{ {
if (model.url.IsValidUrl()) 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); User foundUser = UserHelper.GetUser(_dbContext, User.Identity.Name);
if (foundUser != null)
// Associate this with the user if they are logged in
if (User.Identity.IsAuthenticated)
{ {
User foundUser = UserHelper.GetUser(db, User.Identity.Name); newUrl.UserId = foundUser.UserId;
if (foundUser != null)
{
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" } }); return Json(new { error = new { message = "Must be a valid Url" } });
} }

View File

@ -1,14 +1,7 @@
using System; namespace Teknik.Areas.API.Models
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace Teknik.Areas.API.Models
{ {
public class APIv1PasteModel : APIv1BaseModel public class APIv1PasteModel : APIv1BaseModel
{ {
[AllowHtml]
public string code { get; set; } public string code { get; set; }
public string title { get; set; } public string title { get; set; }

View File

@ -1,4 +1,5 @@
using System; using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Web; using System.Web;
@ -7,7 +8,7 @@ namespace Teknik.Areas.API.Models
{ {
public class APIv1UploadModel : APIv1BaseModel public class APIv1UploadModel : APIv1BaseModel
{ {
public HttpPostedFileWrapper file { get; set; } public IFormFile file { get; set; }
public string contentType { get; set; } public string contentType { get; set; }

View File

@ -1,36 +0,0 @@
<?xml version="1.0"?>
<configuration>
<configSections>
<sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
<section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
</sectionGroup>
</configSections>
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="Teknik.BaseViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="System.Web.Optimization" />
<add namespace="Teknik" />
</namespaces>
</pages>
</system.web.webPages.razor>
<appSettings>
<add key="webpages:Enabled" value="false" />
</appSettings>
<system.webServer>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" />
</handlers>
</system.webServer>
</configuration>

View File

@ -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<string>() { "about" },
new List<string>() { config.Host },
"", // URL with parameters
new { controller = "About", action = "Index" }, // Parameter defaults
new[] { typeof(Controllers.AboutController).Namespace }
);
}
}
}

View File

@ -1,23 +1,31 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Web; using System.Threading.Tasks;
using System.Web.Mvc; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Teknik.Areas.About.ViewModels; using Teknik.Areas.About.ViewModels;
using Teknik.Attributes; using Teknik.Attributes;
using Teknik.Configuration;
using Teknik.Controllers; using Teknik.Controllers;
using Teknik.Data;
using Teknik.Filters; using Teknik.Filters;
using Teknik.Logging;
namespace Teknik.Areas.About.Controllers namespace Teknik.Areas.About.Controllers
{ {
[TeknikAuthorize] [TeknikAuthorize]
[Area("About")]
public class AboutController : DefaultController public class AboutController : DefaultController
{ {
public AboutController(ILogger<Logger> logger, Config config, TeknikEntities dbContext) : base(logger, config, dbContext) { }
[AllowAnonymous] [AllowAnonymous]
[TrackPageView] [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?"; ViewBag.Description = "What is Teknik?";
return View(new AboutViewModel()); return View(new AboutViewModel());

View File

@ -1,7 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Web; using System.Threading.Tasks;
using Teknik.ViewModels; using Teknik.ViewModels;
namespace Teknik.Areas.About.ViewModels namespace Teknik.Areas.About.ViewModels
@ -9,4 +9,4 @@ namespace Teknik.Areas.About.ViewModels
public class AboutViewModel : ViewModelBase public class AboutViewModel : ViewModelBase
{ {
} }
} }

View File

@ -1,7 +1,5 @@
@model Teknik.Areas.About.ViewModels.AboutViewModel @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 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"; string apiAccountAccess = "Passing user credentials allows linking for Uploads/Pastes/Shortened URLs and other account specific features";
@ -35,7 +33,7 @@
<!-- Prices --> <!-- Prices -->
<tr> <tr>
<td class="text-left"></td> <td class="text-left"></td>
<td class="text-center">$@Model.Config.UserConfig.PremiumAccountPrice @Model.Config.UserConfig.PaymentType</td> <td class="text-center">$@Config.UserConfig.PremiumAccountPrice @Config.UserConfig.PaymentType</td>
<td class="text-center">Free</td> <td class="text-center">Free</td>
<td class="text-center">Free</td> <td class="text-center">Free</td>
</tr> </tr>
@ -113,15 +111,15 @@
</tr> </tr>
<tr> <tr>
<td class="text-left">Max Upload Filesize</td> <td class="text-left">Max Upload Filesize</td>
<td class="text-center">@StringHelper.GetBytesReadable(Model.Config.UploadConfig.MaxUploadSizePremium)</td> <td class="text-center">@StringHelper.GetBytesReadable(Config.UploadConfig.MaxUploadSizePremium)</td>
<td class="text-center">@StringHelper.GetBytesReadable(Model.Config.UploadConfig.MaxUploadSizeBasic)</td> <td class="text-center">@StringHelper.GetBytesReadable(Config.UploadConfig.MaxUploadSizeBasic)</td>
<td class="text-center">@StringHelper.GetBytesReadable(Model.Config.UploadConfig.MaxUploadSize)</td> <td class="text-center">@StringHelper.GetBytesReadable(Config.UploadConfig.MaxUploadSize)</td>
</tr> </tr>
<tr> <tr>
<td class="text-left">Max Embedded Filesize</td> <td class="text-left">Max Embedded Filesize</td>
<td class="text-center">Unlimited</td> <td class="text-center">Unlimited</td>
<td class="text-center">@StringHelper.GetBytesReadable(Model.Config.UploadConfig.MaxDownloadSize)</td> <td class="text-center">@StringHelper.GetBytesReadable(Config.UploadConfig.MaxDownloadSize)</td>
<td class="text-center">@StringHelper.GetBytesReadable(Model.Config.UploadConfig.MaxDownloadSize)</td> <td class="text-center">@StringHelper.GetBytesReadable(Config.UploadConfig.MaxDownloadSize)</td>
</tr> </tr>
<tr> <tr>
<td class="text-left">Url Shortening</td> <td class="text-left">Url Shortening</td>

View File

@ -1,36 +0,0 @@
<?xml version="1.0"?>
<configuration>
<configSections>
<sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
<section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
</sectionGroup>
</configSections>
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="Teknik.BaseViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="System.Web.Optimization" />
<add namespace="Teknik" />
</namespaces>
</pages>
</system.web.webPages.razor>
<appSettings>
<add key="webpages:Enabled" value="false" />
</appSettings>
<system.webServer>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" />
</handlers>
</system.webServer>
</configuration>

View File

@ -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<string>() { "abuse" }, // Subdomains
new List<string>() { config.Host }, // domains
"", // URL with parameters
new { controller = "Abuse", action = "Index" }, // Parameter defaults
new[] { typeof(Controllers.AbuseController).Namespace }
);
}
}
}

View File

@ -1,23 +1,31 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Web; using System.Web;
using System.Web.Mvc;
using Teknik.Areas.Abuse.ViewModels; using Teknik.Areas.Abuse.ViewModels;
using Teknik.Attributes; using Teknik.Attributes;
using Teknik.Configuration;
using Teknik.Controllers; using Teknik.Controllers;
using Teknik.Data;
using Teknik.Filters; using Teknik.Filters;
using Teknik.Logging;
namespace Teknik.Areas.Abuse.Controllers namespace Teknik.Areas.Abuse.Controllers
{ {
[TeknikAuthorize] [TeknikAuthorize]
[Area("Abuse")]
public class AbuseController : DefaultController public class AbuseController : DefaultController
{ {
public AbuseController(ILogger<Logger> logger, Config config, TeknikEntities dbContext) : base(logger, config, dbContext) { }
[TrackPageView] [TrackPageView]
[AllowAnonymous] [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."; ViewBag.Description = "Methods for reporting abuse reports to Teknik Services.";
return View(new AbuseViewModel()); return View(new AbuseViewModel());

View File

@ -1,4 +1,3 @@
@using Teknik.Utilities
@model Teknik.Areas.Abuse.ViewModels.AbuseViewModel @model Teknik.Areas.Abuse.ViewModels.AbuseViewModel
<div class="container"> <div class="container">

View File

@ -1,3 +0,0 @@
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}

View File

@ -1,36 +0,0 @@
<?xml version="1.0"?>
<configuration>
<configSections>
<sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
<section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
</sectionGroup>
</configSections>
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="System.Web.Optimization" />
<add namespace="Teknik" />
</namespaces>
</pages>
</system.web.webPages.razor>
<appSettings>
<add key="webpages:Enabled" value="false" />
</appSettings>
<system.webServer>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" />
</handlers>
</system.webServer>
</configuration>

View File

@ -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;
}
}
}

View File

@ -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<string>() { "admin" }, // Subdomains
new List<string>() { 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<string>() { "admin" }, // Subdomains
new List<string>() { 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<string>() { "admin" }, // Subdomains
new List<string>() { 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<string>() { "admin" }, // Subdomains
new List<string>() { 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<string>() { "admin" }, // Subdomains
new List<string>() { 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"));
}
}
}

View File

@ -1,24 +1,30 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ViewEngines;
using Microsoft.Extensions.Logging;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Web; using System.Threading.Tasks;
using System.Web.Mvc;
using Teknik.Areas.Admin.ViewModels; using Teknik.Areas.Admin.ViewModels;
using Teknik.Areas.Users.Models; using Teknik.Areas.Users.Models;
using Teknik.Areas.Users.Utility; using Teknik.Areas.Users.Utility;
using Teknik.Attributes; using Teknik.Attributes;
using Teknik.Configuration;
using Teknik.Controllers; using Teknik.Controllers;
using Teknik.Data;
using Teknik.Filters; using Teknik.Filters;
using Teknik.Models; using Teknik.Models;
using Teknik.Utilities; using Teknik.Utilities;
using Teknik.ViewModels; using Teknik.ViewModels;
using Teknik.Logging;
namespace Teknik.Areas.Admin.Controllers namespace Teknik.Areas.Admin.Controllers
{ {
[TeknikAuthorize(Roles = "Admin")] [TeknikAuthorize(Roles = "Admin")]
[Area("Admin")]
public class AdminController : DefaultController public class AdminController : DefaultController
{ {
private TeknikEntities db = new TeknikEntities(); public AdminController(ILogger<Logger> logger, Config config, TeknikEntities dbContext) : base (logger, config, dbContext) { }
[HttpGet] [HttpGet]
[TrackPageView] [TrackPageView]
@ -40,9 +46,9 @@ namespace Teknik.Areas.Admin.Controllers
[TrackPageView] [TrackPageView]
public ActionResult UserInfo(string username) 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(); UserInfoViewModel model = new UserInfoViewModel();
model.Username = user.Username; model.Username = user.Username;
model.AccountType = user.AccountType; model.AccountType = user.AccountType;
@ -60,11 +66,11 @@ namespace Teknik.Areas.Admin.Controllers
} }
[HttpPost] [HttpPost]
public ActionResult GetUserSearchResults(string query) public async Task<ActionResult> GetUserSearchResults(string query, [FromServices] ICompositeViewEngine viewEngine)
{ {
List<UserResultViewModel> models = new List<UserResultViewModel>(); List<UserResultViewModel> models = new List<UserResultViewModel>();
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) if (results != null)
{ {
foreach (User user in results) foreach (User user in results)
@ -73,12 +79,12 @@ namespace Teknik.Areas.Admin.Controllers
{ {
UserResultViewModel model = new UserResultViewModel(); UserResultViewModel model = new UserResultViewModel();
model.Username = user.Username; 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.JoinDate = user.JoinDate;
model.LastSeen = UserHelper.GetLastAccountActivity(db, Config, user); model.LastSeen = UserHelper.GetLastAccountActivity(_dbContext, _config, user);
models.Add(model); models.Add(model);
} }
catch (Exception ex) 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] [HttpPost]
public ActionResult GetUploadSearchResults(string url) public async Task<ActionResult> 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) if (foundUpload != null)
{ {
UploadResultViewModel model = new UploadResultViewModel(); UploadResultViewModel model = new UploadResultViewModel();
@ -106,7 +114,9 @@ namespace Teknik.Areas.Admin.Controllers
model.Downloads = foundUpload.Downloads; model.Downloads = foundUpload.Downloads;
model.DeleteKey = foundUpload.DeleteKey; 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" } }); return Json(new { error = new { message = "Upload does not exist" } });
} }
@ -115,10 +125,10 @@ namespace Teknik.Areas.Admin.Controllers
[ValidateAntiForgeryToken] [ValidateAntiForgeryToken]
public ActionResult EditUserAccountType(string username, AccountType accountType) public ActionResult EditUserAccountType(string username, AccountType accountType)
{ {
if (UserHelper.UserExists(db, username)) if (UserHelper.UserExists(_dbContext, username))
{ {
// Edit the user's account type // 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 Json(new { result = new { success = true } });
} }
return Redirect(Url.SubRouteUrl("error", "Error.Http404")); return Redirect(Url.SubRouteUrl("error", "Error.Http404"));
@ -128,10 +138,10 @@ namespace Teknik.Areas.Admin.Controllers
[ValidateAntiForgeryToken] [ValidateAntiForgeryToken]
public ActionResult EditUserAccountStatus(string username, AccountStatus accountStatus) public ActionResult EditUserAccountStatus(string username, AccountStatus accountStatus)
{ {
if (UserHelper.UserExists(db, username)) if (UserHelper.UserExists(_dbContext, username))
{ {
// Edit the user's account type // 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 Json(new { result = new { success = true } });
} }
return Redirect(Url.SubRouteUrl("error", "Error.Http404")); return Redirect(Url.SubRouteUrl("error", "Error.Http404"));
@ -141,15 +151,15 @@ namespace Teknik.Areas.Admin.Controllers
[ValidateAntiForgeryToken] [ValidateAntiForgeryToken]
public ActionResult CreateInviteCode(string username) public ActionResult CreateInviteCode(string username)
{ {
if (UserHelper.UserExists(db, username)) if (UserHelper.UserExists(_dbContext, username))
{ {
User user = UserHelper.GetUser(db, username); User user = UserHelper.GetUser(_dbContext, username);
InviteCode inviteCode = db.InviteCodes.Create(); InviteCode inviteCode = new InviteCode();
inviteCode.Active = true; inviteCode.Active = true;
inviteCode.Code = Guid.NewGuid().ToString(); inviteCode.Code = Guid.NewGuid().ToString();
inviteCode.Owner = user; inviteCode.Owner = user;
db.InviteCodes.Add(inviteCode); _dbContext.InviteCodes.Add(inviteCode);
db.SaveChanges(); _dbContext.SaveChanges();
return Json(new { result = new { code = inviteCode.Code } }); return Json(new { result = new { code = inviteCode.Code } });
} }
@ -162,14 +172,11 @@ namespace Teknik.Areas.Admin.Controllers
{ {
try try
{ {
using (TeknikEntities db = new TeknikEntities()) User user = UserHelper.GetUser(_dbContext, username);
if (user != null)
{ {
User user = UserHelper.GetUser(db, username); UserHelper.DeleteAccount(_dbContext, _config, user);
if (user != null) return Json(new { result = true });
{
UserHelper.DeleteAccount(db, Config, user);
return Json(new { result = true });
}
} }
} }
catch (Exception ex) catch (Exception ex)

View File

@ -1,7 +1,5 @@
@model Teknik.Areas.Admin.ViewModels.DashboardViewModel @model Teknik.Areas.Admin.ViewModels.DashboardViewModel
@using Teknik.Utilities
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-sm-10 col-sm-offset-1"> <div class="col-sm-10 col-sm-offset-1">

View File

@ -1,7 +1,5 @@
@model Teknik.Areas.Admin.ViewModels.UploadResultViewModel @model Teknik.Areas.Admin.ViewModels.UploadResultViewModel
@using Teknik.Utilities
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading text-center"> <div class="panel-heading text-center">
<a id="upload-url" href="@Url.SubRouteUrl("u", "Upload.Download", new { file = Model.Url })">@Url.SubRouteUrl("u", "Upload.Download", new { file = Model.Url })</a> <a id="upload-url" href="@Url.SubRouteUrl("u", "Upload.Download", new { file = Model.Url })">@Url.SubRouteUrl("u", "Upload.Download", new { file = Model.Url })</a>

View File

@ -1,23 +1,19 @@
@model Teknik.Areas.Admin.ViewModels.UploadSearchViewModel @model Teknik.Areas.Admin.ViewModels.UploadSearchViewModel
@using Teknik.Utilities <script>
<script nonce="@Context.Items[Constants.NONCE_KEY]">
// We need to define the action URLs for the script // We need to define the action URLs for the script
var searchResultsURL = '@Url.SubRouteUrl("admin", "Admin.Action", new { action = "GetUploadSearchResults" })'; var searchResultsURL = '@Url.SubRouteUrl("admin", "Admin.Action", new { action = "GetUploadSearchResults" })';
var generateDeleteKeyURL = '@Url.SubRouteUrl("u", "Upload.GenerateDeleteKey")'; var generateDeleteKeyURL = '@Url.SubRouteUrl("u", "Upload.GenerateDeleteKey")';
</script> </script>
@Scripts.Render("~/bundles/UploadSearch")
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-sm-6 col-sm-offset-3"> <div class="col-sm-6 col-sm-offset-3">
<form> <!form>
<div class="form-group center-block"> <div class="form-group center-block">
<input type="text" class="form-control" id="Query" name="Query" placeholder="Upload Url" /> <input type="text" class="form-control" id="Query" name="Query" placeholder="Upload Url" />
</div> </div>
</form> </!form>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
@ -26,3 +22,5 @@
</div> </div>
</div> </div>
</div> </div>
<bundle src="js/uploadSearch.min.js" append-version="true"></bundle>

View File

@ -1,8 +1,6 @@
@model Teknik.Areas.Admin.ViewModels.UserInfoViewModel @model Teknik.Areas.Admin.ViewModels.UserInfoViewModel
@using Teknik.Utilities <script>
<script nonce="@Context.Items[Constants.NONCE_KEY]">
// We need to define the action URLs for the script // We need to define the action URLs for the script
var homeUrl = '@Url.SubRouteUrl("admin", "Admin.UserSearch")'; var homeUrl = '@Url.SubRouteUrl("admin", "Admin.UserSearch")';
var deleteUserURL = '@Url.SubRouteUrl("admin", "Admin.Action", new { action = "DeleteAccount" })'; var deleteUserURL = '@Url.SubRouteUrl("admin", "Admin.Action", new { action = "DeleteAccount" })';
@ -12,8 +10,6 @@
var username = '@Model.Username'; var username = '@Model.Username';
</script> </script>
@Scripts.Render("~/bundles/UserInfo")
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-sm-2 col-sm-offset-1"> <div class="col-sm-2 col-sm-offset-1">
@ -33,7 +29,7 @@
@{ @{
foreach (AccountType value in Enum.GetValues(typeof(AccountType))) foreach (AccountType value in Enum.GetValues(typeof(AccountType)))
{ {
<option @(value == Model.AccountType ? "selected" : string.Empty)>@value.ToString()</option> <!option @(value == Model.AccountType ? "selected" : string.Empty)>@value.ToString()</!option>
} }
} }
</select> </select>
@ -49,7 +45,7 @@
@{ @{
foreach (AccountStatus value in Enum.GetValues(typeof(AccountStatus))) foreach (AccountStatus value in Enum.GetValues(typeof(AccountStatus)))
{ {
<option @(value == Model.AccountStatus ? "selected" : string.Empty)>@value.ToString()</option> <!option @(value == Model.AccountStatus ? "selected" : string.Empty)>@value.ToString()</!option>
} }
} }
</select> </select>
@ -68,3 +64,5 @@
</div> </div>
</div> </div>
</div> </div>
<bundle src="js/userInfo.min.js" append-version="true"></bundle>

View File

@ -1,7 +1,5 @@
@model Teknik.Areas.Admin.ViewModels.UserResultViewModel @model Teknik.Areas.Admin.ViewModels.UserResultViewModel
@using Teknik.Utilities
<div class="row"> <div class="row">
<div class="row"> <div class="row">
<div class="col-sm-3"> <div class="col-sm-3">

View File

@ -10,7 +10,7 @@
</div> </div>
foreach (var post in Model) foreach (var post in Model)
{ {
@Html.Partial("UserResult", post) @await Html.PartialAsync("UserResult", post)
} }
} }
else else

View File

@ -1,22 +1,18 @@
@model Teknik.Areas.Admin.ViewModels.UserSearchViewModel @model Teknik.Areas.Admin.ViewModels.UserSearchViewModel
@using Teknik.Utilities <script>
<script nonce="@Context.Items[Constants.NONCE_KEY]">
// We need to define the action URLs for the script // We need to define the action URLs for the script
var userSearchResultsURL = '@Url.SubRouteUrl("admin", "Admin.Action", new { action = "GetUserSearchResults" })'; var userSearchResultsURL = '@Url.SubRouteUrl("admin", "Admin.Action", new { action = "GetUserSearchResults" })';
</script> </script>
@Scripts.Render("~/bundles/UserSearch")
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-sm-6 col-sm-offset-3"> <div class="col-sm-6 col-sm-offset-3">
<form> <!form>
<div class="form-group center-block"> <div class="form-group center-block">
<input type="text" class="form-control" id="query" name="query" placeholder="Username" /> <input type="text" class="form-control" id="query" name="query" placeholder="Username" />
</div> </div>
</form> </!form>
</div> </div>
<div class="col-sm-2"> <div class="col-sm-2">
<button type="button" class="btn btn-info text-center" id="search">Search</button> <button type="button" class="btn btn-info text-center" id="search">Search</button>
@ -28,3 +24,5 @@
</div> </div>
</div> </div>
</div> </div>
<bundle src="js/userInfo.min.js" append-version="true"></bundle>

View File

@ -1,3 +0,0 @@
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}

View File

@ -1,36 +0,0 @@
<?xml version="1.0"?>
<configuration>
<configSections>
<sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
<section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
</sectionGroup>
</configSections>
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="Teknik.BaseViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="System.Web.Optimization" />
<add namespace="Teknik" />
</namespaces>
</pages>
</system.web.webPages.razor>
<appSettings>
<add key="webpages:Enabled" value="false" />
</appSettings>
<system.webServer>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" />
</handlers>
</system.webServer>
</configuration>

View File

@ -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<string>() { "blog" }, // Subdomains
new List<string>() { 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<string>() { "blog" }, // Subdomains
new List<string>() { 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<string>() { "blog" }, // Subdomains
new List<string>() { 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<string>() { "blog" }, // Subdomains
new List<string>() { 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<string>() { "blog" }, // Subdomains
new List<string>() { 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"));
}
}
}

View File

@ -1,11 +1,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data; using System.Data;
using System.Data.Entity;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Web; using System.Web;
using System.Web.Mvc;
using Teknik.Areas.Blog.Models; using Teknik.Areas.Blog.Models;
using Teknik.Areas.Blog.ViewModels; using Teknik.Areas.Blog.ViewModels;
using Teknik.Areas.Users.Models; using Teknik.Areas.Users.Models;
@ -15,61 +13,103 @@ using Teknik.Filters;
using Teknik.Utilities; using Teknik.Utilities;
using Teknik.Models; using Teknik.Models;
using Teknik.Attributes; 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 namespace Teknik.Areas.Blog.Controllers
{ {
[TeknikAuthorize] [TeknikAuthorize]
[Area("Blog")]
public class BlogController : DefaultController public class BlogController : DefaultController
{ {
private TeknikEntities db = new TeknikEntities(); public BlogController(ILogger<Logger> logger, Config config, TeknikEntities dbContext) : base(logger, config, dbContext) { }
// GET: Blogs/Details/5
[TrackPageView] [TrackPageView]
[AllowAnonymous] [AllowAnonymous]
public ActionResult Blog(string username) public IActionResult Blog(string username)
{ {
BlogViewModel model = new BlogViewModel(); BlogViewModel model = new BlogViewModel();
// The blog is the main site's blog // The blog is the main site's blog
if (string.IsNullOrEmpty(username)) if (string.IsNullOrEmpty(username))
{ {
ViewBag.Title = Config.BlogConfig.Title + " - " + Config.Title; ViewBag.Title = _config.BlogConfig.Title + " - " + _config.Title;
ViewBag.Description = Config.BlogConfig.Description; ViewBag.Description = _config.BlogConfig.Description;
bool isAuth = User.IsInRole("Admin"); bool isAuth = User.IsInRole("Admin");
var foundPosts = db.BlogPosts.Where(p => ((p.System || isAuth) && p.Published));
model = new BlogViewModel(); 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.UserId = (user != null) ? user.UserId : 0;
model.User = user; model.User = user;
model.Title = Config.BlogConfig.Title; model.Title = _config.BlogConfig.Title;
model.Description = Config.BlogConfig.Description; model.Description = _config.BlogConfig.Description;
model.HasPosts = (foundPosts != null && foundPosts.Any()); 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<PostViewModel> postViews = new List<PostViewModel>();
if (posts != null)
{
foreach (BlogPost post in posts)
{
postViews.Add(new PostViewModel(post));
}
}
model.Posts = postViews;
return View(model); return View(model);
} }
else // A user specific blog 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 // find the blog specified
if (blog != null) 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)) if (!string.IsNullOrEmpty(blog.User.BlogSettings.Title))
{ {
ViewBag.Title = blog.User.BlogSettings.Title + " - " + ViewBag.Title; ViewBag.Title = blog.User.BlogSettings.Title + " - " + ViewBag.Title;
} }
ViewBag.Description = blog.User.BlogSettings.Description; ViewBag.Description = blog.User.BlogSettings.Description;
bool isAuth = User.IsInRole("Admin"); 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 = new BlogViewModel();
model.BlogId = blog.BlogId; model.BlogId = blog.BlogId;
model.UserId = blog.UserId; model.UserId = blog.UserId;
model.User = blog.User; model.User = blog.User;
model.Title = blog.User.BlogSettings.Title; model.Title = blog.User.BlogSettings.Title;
model.Description = blog.User.BlogSettings.Description; 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<PostViewModel> postViews = new List<PostViewModel>();
if (posts != null)
{
foreach (BlogPost post in posts)
{
postViews.Add(new PostViewModel(post));
}
}
model.Posts = postViews;
return View(model); return View(model);
} }
@ -81,28 +121,34 @@ namespace Teknik.Areas.Blog.Controllers
#region Posts #region Posts
[TrackPageView] [TrackPageView]
[AllowAnonymous] [AllowAnonymous]
public ActionResult Post(string username, int id) public IActionResult Post(string username, int id)
{ {
if (string.IsNullOrEmpty(username)) if (string.IsNullOrEmpty(username))
{ {
return new HttpStatusCodeResult(HttpStatusCode.BadRequest); return new StatusCodeResult((int)HttpStatusCode.BadRequest);
} }
PostViewModel model = new PostViewModel(); PostViewModel model = new PostViewModel();
// find the post specified // find the post specified
bool isAuth = User.IsInRole("Admin"); 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) if (post != null)
{ {
model = new PostViewModel(post); model = new PostViewModel(post);
if (post.System) if (post.System)
{ {
ViewBag.Title = model.Title + " - " + Config.BlogConfig.Title + " - " + Config.Title; ViewBag.Title = model.Title + " - " + _config.BlogConfig.Title + " - " + _config.Title;
ViewBag.Description = Config.BlogConfig.Description; ViewBag.Description = _config.BlogConfig.Description;
} }
else else
{ {
ViewBag.Title = username + "'s Blog - " + Config.Title; ViewBag.Title = username + "'s Blog - " + _config.Title;
if (!string.IsNullOrEmpty(post.Blog.User.BlogSettings.Title)) if (!string.IsNullOrEmpty(post.Blog.User.BlogSettings.Title))
{ {
ViewBag.Title = post.Blog.User.BlogSettings.Title + " - " + ViewBag.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); 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)) if (string.IsNullOrEmpty(username))
{ {
return new HttpStatusCodeResult(HttpStatusCode.BadRequest); return new StatusCodeResult((int)HttpStatusCode.BadRequest);
} }
BlogViewModel model = new BlogViewModel(); BlogViewModel model = new BlogViewModel();
// find the post specified // find the post specified
bool isAuth = User.IsInRole("Admin"); 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) if (blog != null)
{ {
model = new BlogViewModel(blog); model = new BlogViewModel(blog);
if (blog.User.Username == Constants.SERVERUSER) if (blog.User.Username == Constants.SERVERUSER)
{ {
ViewBag.Title = "Create Post - " + Config.BlogConfig.Title + " - " + Config.Title; ViewBag.Title = "Create Post - " + _config.BlogConfig.Title + " - " + _config.Title;
ViewBag.Description = Config.BlogConfig.Description; ViewBag.Description = _config.BlogConfig.Description;
} }
else else
{ {
ViewBag.Title = username + "'s Blog - " + Config.Title; ViewBag.Title = username + "'s Blog - " + _config.Title;
if (!string.IsNullOrEmpty(blog.User.BlogSettings.Title)) if (!string.IsNullOrEmpty(blog.User.BlogSettings.Title))
{ {
ViewBag.Title = blog.User.BlogSettings.Title + " - " + ViewBag.Title; ViewBag.Title = blog.User.BlogSettings.Title + " - " + ViewBag.Title;
@ -151,29 +201,36 @@ namespace Teknik.Areas.Blog.Controllers
model.ErrorMessage = "Blog does not exist."; model.ErrorMessage = "Blog does not exist.";
return View("~/Areas/Blog/Views/Blog/Blog.cshtml", model); 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)) if (string.IsNullOrEmpty(username))
{ {
return new HttpStatusCodeResult(HttpStatusCode.BadRequest); return new StatusCodeResult((int)HttpStatusCode.BadRequest);
} }
PostViewModel model = new PostViewModel(); PostViewModel model = new PostViewModel();
// find the post specified // find the post specified
bool isAuth = User.IsInRole("Admin"); bool isAuth = User.IsInRole("Admin");
var post = db.BlogPosts.Where(p => (p.Blog.User.Username == username && p.BlogPostId == id) && var post = _dbContext.BlogPosts
(p.Published || p.Blog.User.Username == User.Identity.Name || isAuth)).FirstOrDefault(); .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) if (post != null)
{ {
model = new PostViewModel(post); model = new PostViewModel(post);
if (post.System) if (post.System)
{ {
ViewBag.Title = "Edit Post - " + model.Title + " - " + Config.BlogConfig.Title + " - " + Config.Title; ViewBag.Title = "Edit Post - " + model.Title + " - " + _config.BlogConfig.Title + " - " + _config.Title;
ViewBag.Description = Config.BlogConfig.Description; ViewBag.Description = _config.BlogConfig.Description;
} }
else else
{ {
ViewBag.Title = username + "'s Blog - " + Config.Title; ViewBag.Title = username + "'s Blog - " + _config.Title;
if (!string.IsNullOrEmpty(post.Blog.User.BlogSettings.Title)) if (!string.IsNullOrEmpty(post.Blog.User.BlogSettings.Title))
{ {
ViewBag.Title = post.Blog.User.BlogSettings.Title + " - " + ViewBag.Title; ViewBag.Title = post.Blog.User.BlogSettings.Title + " - " + ViewBag.Title;
@ -190,11 +247,20 @@ namespace Teknik.Areas.Blog.Controllers
[HttpPost] [HttpPost]
[AllowAnonymous] [AllowAnonymous]
public ActionResult GetPosts(int blogID, int startPostID, int count) public IActionResult GetPosts(int blogID, int startPostID, int count)
{ {
bool isAuth = User.IsInRole("Admin"); bool isAuth = User.IsInRole("Admin");
var posts = db.BlogPosts.Where(p => ((p.BlogId == blogID && !p.System) || (p.System && blogID == Config.BlogConfig.ServerBlogId)) && var posts = _dbContext.BlogPosts
(p.Published || p.Blog.User.Username == User.Identity.Name || isAuth)).OrderByDescending(p => p.DatePosted).Skip(startPostID).Take(count).ToList(); .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<PostViewModel> postViews = new List<PostViewModel>(); List<PostViewModel> postViews = new List<PostViewModel>();
if (posts != null) if (posts != null)
{ {
@ -207,16 +273,16 @@ namespace Teknik.Areas.Blog.Controllers
} }
[HttpPost] [HttpPost]
public ActionResult CreatePost(CreatePostViewModel data) public IActionResult CreatePost(CreatePostViewModel data)
{ {
BlogViewModel model = new BlogViewModel(); BlogViewModel model = new BlogViewModel();
if (ModelState.IsValid) if (ModelState.IsValid)
{ {
bool isAuth = User.IsInRole("Admin"); 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 (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 // Validate the fields
if (string.IsNullOrEmpty(data.Title)) if (string.IsNullOrEmpty(data.Title))
@ -233,16 +299,16 @@ namespace Teknik.Areas.Blog.Controllers
return View("~/Areas/Blog/Views/Blog/NewPost.cshtml", model); 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) 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) if (user != null)
{ {
data.BlogId = user.First().BlogId; data.BlogId = user.First().BlogId;
} }
} }
BlogPost post = db.BlogPosts.Create(); BlogPost post = new BlogPost();
post.BlogId = data.BlogId; post.BlogId = data.BlogId;
post.Title = data.Title; post.Title = data.Title;
post.Article = data.Article; post.Article = data.Article;
@ -251,8 +317,8 @@ namespace Teknik.Areas.Blog.Controllers
post.DatePublished = DateTime.Now; post.DatePublished = DateTime.Now;
post.DateEdited = DateTime.Now; post.DateEdited = DateTime.Now;
db.BlogPosts.Add(post); _dbContext.BlogPosts.Add(post);
db.SaveChanges(); _dbContext.SaveChanges();
return Redirect(Url.SubRouteUrl("blog", "Blog.Post", new { username = blog.User.Username, id = post.BlogPostId })); return Redirect(Url.SubRouteUrl("blog", "Blog.Post", new { username = blog.User.Username, id = post.BlogPostId }));
} }
model.Error = true; model.Error = true;
@ -269,12 +335,12 @@ namespace Teknik.Areas.Blog.Controllers
} }
[HttpPost] [HttpPost]
public ActionResult EditPost(EditPostViewModel data) public IActionResult EditPost(EditPostViewModel data)
{ {
PostViewModel model = new PostViewModel(); PostViewModel model = new PostViewModel();
if (ModelState.IsValid) 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) if (post != null)
{ {
model = new PostViewModel(post); model = new PostViewModel(post);
@ -298,8 +364,8 @@ namespace Teknik.Areas.Blog.Controllers
post.Title = data.Title; post.Title = data.Title;
post.Article = data.Article; post.Article = data.Article;
post.DateEdited = DateTime.Now; post.DateEdited = DateTime.Now;
db.Entry(post).State = EntityState.Modified; _dbContext.Entry(post).State = EntityState.Modified;
db.SaveChanges(); _dbContext.SaveChanges();
return Redirect(Url.SubRouteUrl("blog", "Blog.Post", new { username = post.Blog.User.Username, id = post.BlogPostId })); return Redirect(Url.SubRouteUrl("blog", "Blog.Post", new { username = post.Blog.User.Username, id = post.BlogPostId }));
} }
model.Error = true; model.Error = true;
@ -316,11 +382,11 @@ namespace Teknik.Areas.Blog.Controllers
} }
[HttpPost] [HttpPost]
public ActionResult PublishPost(int postID, bool publish) public IActionResult PublishPost(int postID, bool publish)
{ {
if (ModelState.IsValid) 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 (post != null)
{ {
if (User.IsInRole("Admin") || post.Blog.User.Username == User.Identity.Name) if (User.IsInRole("Admin") || post.Blog.User.Username == User.Identity.Name)
@ -328,8 +394,8 @@ namespace Teknik.Areas.Blog.Controllers
post.Published = publish; post.Published = publish;
if (publish) if (publish)
post.DatePublished = DateTime.Now; post.DatePublished = DateTime.Now;
db.Entry(post).State = EntityState.Modified; _dbContext.Entry(post).State = EntityState.Modified;
db.SaveChanges(); _dbContext.SaveChanges();
return Json(new { result = true }); return Json(new { result = true });
} }
return Json(new { error = "You are not authorized to publish this post" }); return Json(new { error = "You are not authorized to publish this post" });
@ -340,17 +406,17 @@ namespace Teknik.Areas.Blog.Controllers
} }
[HttpPost] [HttpPost]
public ActionResult DeletePost(int postID) public IActionResult DeletePost(int postID)
{ {
if (ModelState.IsValid) 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 (post != null)
{ {
if (User.IsInRole("Admin") || post.Blog.User.Username == User.Identity.Name) if (User.IsInRole("Admin") || post.Blog.User.Username == User.Identity.Name)
{ {
db.BlogPosts.Remove(post); _dbContext.BlogPosts.Remove(post);
db.SaveChanges(); _dbContext.SaveChanges();
return Json(new { result = true }); return Json(new { result = true });
} }
return Json(new { error = "You are not authorized to delete this post" }); return Json(new { error = "You are not authorized to delete this post" });
@ -364,9 +430,9 @@ namespace Teknik.Areas.Blog.Controllers
#region Comments #region Comments
[HttpPost] [HttpPost]
[AllowAnonymous] [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<CommentViewModel> commentViews = new List<CommentViewModel>(); List<CommentViewModel> commentViews = new List<CommentViewModel>();
if (comments != null) if (comments != null)
{ {
@ -380,9 +446,9 @@ namespace Teknik.Areas.Blog.Controllers
[HttpPost] [HttpPost]
[AllowAnonymous] [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) if (comment != null)
{ {
return Json(new { result = comment.Article }); return Json(new { result = comment.Article });
@ -391,21 +457,21 @@ namespace Teknik.Areas.Blog.Controllers
} }
[HttpPost] [HttpPost]
public ActionResult CreateComment(int postID, string article) public IActionResult CreateComment(int postID, string article)
{ {
if (ModelState.IsValid) 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.BlogPostId = postID;
comment.UserId = UserHelper.GetUser(db, User.Identity.Name).UserId; comment.UserId = UserHelper.GetUser(_dbContext, User.Identity.Name).UserId;
comment.Article = article; comment.Article = article;
comment.DatePosted = DateTime.Now; comment.DatePosted = DateTime.Now;
comment.DateEdited = DateTime.Now; comment.DateEdited = DateTime.Now;
db.BlogComments.Add(comment); _dbContext.BlogPostComments.Add(comment);
db.SaveChanges(); _dbContext.SaveChanges();
return Json(new { result = true }); return Json(new { result = true });
} }
return Json(new { error = "The post does not exist" }); return Json(new { error = "The post does not exist" });
@ -414,19 +480,19 @@ namespace Teknik.Areas.Blog.Controllers
} }
[HttpPost] [HttpPost]
public ActionResult EditComment(int commentID, string article) public IActionResult EditComment(int commentID, string article)
{ {
if (ModelState.IsValid) 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 != null)
{ {
if (comment.User.Username == User.Identity.Name || User.IsInRole("Admin")) if (comment.User.Username == User.Identity.Name || User.IsInRole("Admin"))
{ {
comment.Article = article; comment.Article = article;
comment.DateEdited = DateTime.Now; comment.DateEdited = DateTime.Now;
db.Entry(comment).State = EntityState.Modified; _dbContext.Entry(comment).State = EntityState.Modified;
db.SaveChanges(); _dbContext.SaveChanges();
return Json(new { result = true }); return Json(new { result = true });
} }
return Json(new { error = "You don't have permission to edit this comment" }); return Json(new { error = "You don't have permission to edit this comment" });
@ -437,17 +503,17 @@ namespace Teknik.Areas.Blog.Controllers
} }
[HttpPost] [HttpPost]
public ActionResult DeleteComment(int commentID) public IActionResult DeleteComment(int commentID)
{ {
if (ModelState.IsValid) 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 != null)
{ {
if (comment.User.Username == User.Identity.Name || User.IsInRole("Admin")) if (comment.User.Username == User.Identity.Name || User.IsInRole("Admin"))
{ {
db.BlogComments.Remove(comment); _dbContext.BlogPostComments.Remove(comment);
db.SaveChanges(); _dbContext.SaveChanges();
return Json(new { result = true }); return Json(new { result = true });
} }
return Json(new { error = "You don't have permission to delete this comment" }); return Json(new { error = "You don't have permission to delete this comment" });

View File

@ -26,7 +26,7 @@ namespace Teknik.Areas.Blog.Models
public string Article { get; set; } public string Article { get; set; }
public List<string> Tags { get; set; } public virtual ICollection<BlogPostTag> Tags { get; set; }
public virtual ICollection<BlogPostComment> Comments { get; set; } public virtual ICollection<BlogPostComment> Comments { get; set; }
} }

View File

@ -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; }
}
}

View File

@ -1,8 +1,4 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Teknik.Areas.Blog.Models; using Teknik.Areas.Blog.Models;
using Teknik.Areas.Users.Models; using Teknik.Areas.Users.Models;
using Teknik.ViewModels; using Teknik.ViewModels;
@ -21,7 +17,15 @@ namespace Teknik.Areas.Blog.ViewModels
public User User { get; set; } public User User { get; set; }
public bool HasPosts { get; set; } public bool HasPosts
{
get
{
return Posts != null && Posts.Count > 0;
}
}
public List<PostViewModel> Posts { get; set; }
public BlogViewModel() public BlogViewModel()
{ {
@ -35,7 +39,7 @@ namespace Teknik.Areas.Blog.ViewModels
Title = blog.User.BlogSettings.Title; Title = blog.User.BlogSettings.Title;
Description = blog.User.BlogSettings.Description; Description = blog.User.BlogSettings.Description;
User = blog.User; User = blog.User;
HasPosts = false; Posts = new List<PostViewModel>();
} }
} }
} }

View File

@ -1,7 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Teknik.Areas.Blog.Models; using Teknik.Areas.Blog.Models;
using Teknik.Areas.Users.Models; using Teknik.Areas.Users.Models;
using Teknik.ViewModels; using Teknik.ViewModels;

View File

@ -1,9 +1,4 @@
using System; using Teknik.ViewModels;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Teknik.ViewModels;
namespace Teknik.Areas.Blog.ViewModels namespace Teknik.Areas.Blog.ViewModels
{ {
@ -12,8 +7,7 @@ namespace Teknik.Areas.Blog.ViewModels
public int BlogId { get; set; } public int BlogId { get; set; }
public string Title { get; set; } public string Title { get; set; }
[AllowHtml]
public string Article { get; set; } public string Article { get; set; }
} }
} }

View File

@ -1,9 +1,4 @@
using System; using Teknik.ViewModels;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Teknik.ViewModels;
namespace Teknik.Areas.Blog.ViewModels namespace Teknik.Areas.Blog.ViewModels
{ {
@ -12,8 +7,7 @@ namespace Teknik.Areas.Blog.ViewModels
public int PostId { get; set; } public int PostId { get; set; }
public string Title { get; set; } public string Title { get; set; }
[AllowHtml]
public string Article { get; set; } public string Article { get; set; }
} }
} }

View File

@ -1,9 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Teknik.Areas.Blog.Models; using Teknik.Areas.Blog.Models;
using System.Security.Principal;
using System.Linq; using System.Linq;
using System.Web;
using Teknik.ViewModels; using Teknik.ViewModels;
namespace Teknik.Areas.Blog.ViewModels namespace Teknik.Areas.Blog.ViewModels
@ -30,7 +28,7 @@ namespace Teknik.Areas.Blog.ViewModels
public string Article { get; set; } public string Article { get; set; }
public List<string> Tags { get; set; } public List<BlogPostTag> Tags { get; set; }
public List<BlogPostComment> Comments { get; set; } public List<BlogPostComment> Comments { get; set; }
@ -50,7 +48,7 @@ namespace Teknik.Areas.Blog.ViewModels
DatePublished = post.DatePublished; DatePublished = post.DatePublished;
DateEdited = post.DateEdited; DateEdited = post.DateEdited;
Title = post.Title; Title = post.Title;
Tags = post.Tags; Tags = post.Tags.ToList();
Article = post.Article; Article = post.Article;
Comments = post.Comments.ToList(); Comments = post.Comments.ToList();
} }

View File

@ -1,8 +1,6 @@
@model Teknik.Areas.Blog.ViewModels.BlogViewModel @model Teknik.Areas.Blog.ViewModels.BlogViewModel
@using Teknik.Utilities <script>
<script nonce="@Context.Items[Constants.NONCE_KEY]">
// We need to define the action URLs for the script // We need to define the action URLs for the script
var uploadURL = '@Url.SubRouteUrl("upload", "Upload.Upload")'; var uploadURL = '@Url.SubRouteUrl("upload", "Upload.Upload")';
var helpURL = '@Url.SubRouteUrl("help", "Help.Markdown")'; var helpURL = '@Url.SubRouteUrl("help", "Help.Markdown")';
@ -18,8 +16,7 @@
var deleteCommentURL = '@Url.SubRouteUrl("blog", "Blog.Action", new { action = "DeleteComment" })'; var deleteCommentURL = '@Url.SubRouteUrl("blog", "Blog.Action", new { action = "DeleteComment" })';
</script> </script>
@Styles.Render("~/Content/blog") <bundle src="css/blog.min.css" append-version="true"></bundle>
@Scripts.Render("~/bundles/blog")
<div class="container"> <div class="container">
@if (!Model.Error) @if (!Model.Error)
@ -33,7 +30,7 @@
<div class="row"> <div class="row">
<div class="col-sm-12 text-center"> <div class="col-sm-12 text-center">
<p> <p>
<a href="@Url.SubRouteUrl("rss", "RSS.Blog", new { username = (Model.BlogId == Model.Config.BlogConfig.ServerBlogId) ? string.Empty : Model.User.Username })"><i class="fa fa-rss fa-2x fa-border"></i></a> <a href="@Url.SubRouteUrl("rss", "RSS.Blog", new { username = (Model.BlogId == Config.BlogConfig.ServerBlogId) ? string.Empty : Model.User.Username })"><i class="fa fa-rss fa-2x fa-border"></i></a>
</p> </p>
</div> </div>
</div> </div>
@ -46,14 +43,25 @@
</div> </div>
} }
<bundle src="js/blog.min.js" append-version="true"></bundle>
if (Model.HasPosts) if (Model.HasPosts)
{ {
<div class="blog-main" id="@Model.BlogId"></div> <div class="blog-main" id="@Model.BlogId">
<script nonce="@Context.Items[Constants.NONCE_KEY]"> @foreach (var post in Model.Posts)
var posts = @Model.Config.BlogConfig.PostsToLoad; {
var start_post = 0; @await Html.PartialAsync("Post", post)
loadMorePosts(start_post, posts); }
start_post = start_post + posts; </div>
<script>
var posts = @Config.BlogConfig.PostsToLoad;
var start_post = @Model.Posts.Count;
linkPostDelete('.delete_post');
linkPostPublish('.publish_post');
linkPostUnpublish('.unpublish_post');
$(window).bind('scroll', bindScrollPosts);
</script> </script>
} }
else else

View File

@ -1,7 +1,5 @@
@model Teknik.Areas.Blog.ViewModels.CommentViewModel @model Teknik.Areas.Blog.ViewModels.CommentViewModel
@using Teknik.Utilities
<hr> <hr>
<div class="row"> <div class="row">
<div class="col-sm-8 col-sm-offset-2"> <div class="col-sm-8 col-sm-offset-2">

View File

@ -2,5 +2,5 @@
@foreach (var comment in Model) @foreach (var comment in Model)
{ {
@Html.Partial("Comment", comment) @await Html.PartialAsync("Comment", comment)
} }

View File

@ -1,14 +1,11 @@
@model Teknik.Areas.Blog.ViewModels.PostViewModel @model Teknik.Areas.Blog.ViewModels.PostViewModel
@using Teknik.Utilities <script>
<script nonce="@Context.Items[Constants.NONCE_KEY]">
// We need to define the action URLs for the script // We need to define the action URLs for the script
var helpURL = '@Url.SubRouteUrl("help", "Help.Markdown")'; var helpURL = '@Url.SubRouteUrl("help", "Help.Markdown")';
</script> </script>
@Styles.Render("~/Content/blog") <bundle src="css/blog.min.css" append-version="true"></bundle>
@Scripts.Render("~/bundles/blog")
<div class="container"> <div class="container">
@if (Model.Error) @if (Model.Error)
@ -25,23 +22,33 @@
<h2>Edit Post</h2> <h2>Edit Post</h2>
</div> </div>
</div> </div>
<form class="form" action="@Url.SubRouteUrl("blog", "Blog.Action", new { action = "EditPost" })" method="post" id="newPost"> <!form class="form" action="@Url.SubRouteUrl("blog", "Blog.Action", new { action = "EditPost" })" method="post" id="newPost">
<input name="PostID" id="postID" type="hidden" value="@Model.PostId" /> <input name="PostID" id="postID" type="hidden" value="@Model.PostId" />
<div class="row"> <div class="row">
<div class="form-group col-sm-10 col-sm-offset-1"> <div class="col-sm-12">
<label for="title"><h4>Title</h4></label> <label for="title"><h4>Title</h4></label>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<input class="form-control" name="Title" id="title" placeholder="generic click bait" title="enter a title for your post." type="text" value="@Model.Title" /> <input class="form-control" name="Title" id="title" placeholder="generic click bait" title="enter a title for your post." type="text" value="@Model.Title" />
</div> </div>
</div> <div class="col-sm-1 col-sm-offset-1 pull-right">
<div class="row"> <button type="submit" class="btn btn-primary" id="submit">Save</button>
<div class="form-group col-sm-10 col-sm-offset-1">
<label for="article"><h4>Article</h4></label>
<div class="mdd_toolbar"></div>
<textarea class="form-control mdd_editor" name="Article" id="article" placeholder="I ate a burger today." title="enter any information you want to share with the world." data-provide="markdown" rows="10">@Model.Article</textarea>
</div> </div>
</div> </div>
<br />
<div class="row"> <div class="row">
<div class="col-sm-10 col-sm-offset-1"> <div class="col-sm-6">
<div class="panel panel-default">
<div class="panel-heading">Article</div>
<div class="panel-body">
<div class="mdd_toolbar"></div>
<textarea class="form-control mdd_editor" name="Article" id="article" placeholder="I ate a burger today." title="enter any information you want to share with the world." data-provide="markdown" rows="20">@Model.Article</textarea>
</div>
</div>
</div>
<div class="col-sm-6">
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading">Preview</div> <div class="panel-heading">Preview</div>
<div class="panel-body"> <div class="panel-body">
@ -50,10 +57,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="row"> </!form>
<div class="form-group col-sm-10 col-sm-offset-1">
<button type="submit" class="btn btn-primary" id="submit">Save</button>
</div>
</div>
</form>
</div> </div>
<bundle src="js/blog.min.js" append-version="true"></bundle>

View File

@ -1,14 +1,11 @@
@model Teknik.Areas.Blog.ViewModels.BlogViewModel @model Teknik.Areas.Blog.ViewModels.BlogViewModel
@using Teknik.Utilities <script>
<script nonce="@Context.Items[Constants.NONCE_KEY]">
// We need to define the action URLs for the script // We need to define the action URLs for the script
var helpURL = '@Url.SubRouteUrl("help", "Help.Markdown")'; var helpURL = '@Url.SubRouteUrl("help", "Help.Markdown")';
</script> </script>
@Styles.Render("~/Content/blog") <bundle src="css/blog.min.css" append-version="true"></bundle>
@Scripts.Render("~/bundles/blog")
<div class="container"> <div class="container">
@if (Model.Error) @if (Model.Error)
@ -25,23 +22,33 @@
<h2>Create a New Post</h2> <h2>Create a New Post</h2>
</div> </div>
</div> </div>
<form class="form" action="@Url.SubRouteUrl("blog", "Blog.Action", new { action = "CreatePost" })" method="post" id="newPost"> <!form class="form" action="@Url.SubRouteUrl("blog", "Blog.Action", new { action = "CreatePost" })" method="post" id="newPost">
<input name="BlogID" id="blogID" type="hidden" value="@Model.BlogId" /> <input name="BlogID" id="blogID" type="hidden" value="@Model.BlogId" />
<div class="row"> <div class="row">
<div class="form-group col-sm-10 col-sm-offset-1"> <div class="col-sm-12">
<label for="title"><h4>Title</h4></label> <label for="title"><h4>Title</h4></label>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<input class="form-control" name="Title" id="title" placeholder="generic click bait" title="enter a title for your post." type="text" /> <input class="form-control" name="Title" id="title" placeholder="generic click bait" title="enter a title for your post." type="text" />
</div> </div>
</div> <div class="col-sm-1 col-sm-offset-1 pull-right">
<div class="row"> <button type="submit" class="btn btn-primary" id="submit">Create Post</button>
<div class="form-group col-sm-10 col-sm-offset-1">
<label for="article"><h4>Article</h4></label>
<div class="mdd_toolbar"></div>
<textarea class="form-control mdd_editor" name="Article" id="article" placeholder="I ate a burger today." title="enter any information you want to share with the world." data-provide="markdown" rows="10"></textarea>
</div> </div>
</div> </div>
<br />
<div class="row"> <div class="row">
<div class="col-sm-10 col-sm-offset-1"> <div class="col-sm-6">
<div class="panel panel-default">
<div class="panel-heading">Article</div>
<div class="panel-body">
<div class="mdd_toolbar"></div>
<textarea class="form-control mdd_editor" name="Article" id="article" placeholder="I ate a burger today." title="enter any information you want to share with the world." data-provide="markdown" rows="20"></textarea>
</div>
</div>
</div>
<div class="col-sm-6">
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading">Preview</div> <div class="panel-heading">Preview</div>
<div class="panel-body"> <div class="panel-body">
@ -50,10 +57,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="row"> </!form>
<div class="form-group col-sm-10 col-sm-offset-1">
<button type="submit" class="btn btn-primary" id="submit">Create Post</button>
</div>
</div>
</form>
</div> </div>
<bundle src="js/blog.min.js" append-version="true"></bundle>

View File

@ -1,7 +1,5 @@
@model Teknik.Areas.Blog.ViewModels.PostViewModel @model Teknik.Areas.Blog.ViewModels.PostViewModel
@using Teknik.Utilities
<div class="row"> <div class="row">
<div class="col-sm-10 col-sm-offset-1"> <div class="col-sm-10 col-sm-offset-1">
<div class="blog-post"> <div class="blog-post">

View File

@ -2,5 +2,5 @@
@foreach (var post in Model) @foreach (var post in Model)
{ {
@Html.Partial("Post", post) @await Html.PartialAsync("Post", post)
} }

View File

@ -1,8 +1,6 @@
@model Teknik.Areas.Blog.ViewModels.PostViewModel @model Teknik.Areas.Blog.ViewModels.PostViewModel
@using Teknik.Utilities <script>
<script nonce="@Context.Items[Constants.NONCE_KEY]">
// We need to define the action URLs for the script // We need to define the action URLs for the script
var uploadURL = '@Url.SubRouteUrl("upload", "Upload.Upload")'; var uploadURL = '@Url.SubRouteUrl("upload", "Upload.Upload")';
var helpURL = '@Url.SubRouteUrl("help", "Help.Markdown")'; var helpURL = '@Url.SubRouteUrl("help", "Help.Markdown")';
@ -18,20 +16,20 @@
var deleteCommentURL = '@Url.SubRouteUrl("blog", "Blog.Action", new { action = "DeleteComment" })'; var deleteCommentURL = '@Url.SubRouteUrl("blog", "Blog.Action", new { action = "DeleteComment" })';
</script> </script>
@Styles.Render("~/Content/blog") <bundle src="css/blog.min.css" append-version="true"></bundle>
@Scripts.Render("~/bundles/blog") <bundle src="js/blog.min.js" append-version="true"></bundle>
<div class="container"> <div class="container">
@if (!Model.Error) @if (!Model.Error)
{ {
<ol class="breadcrumb"> <ol class="breadcrumb">
<li><a href="@Url.SubRouteUrl("blog", "Blog.Blog", new { username = (Model.System) ? string.Empty : Model.Blog.User.Username })">@((Model.System) ? Model.Config.BlogConfig.Title : (string.IsNullOrEmpty(Model.Blog.User.BlogSettings.Title) ? string.Format("{0}'s Blog", Model.Blog.User.Username) : Model.Blog.User.BlogSettings.Title))</a></li> <li><a href="@Url.SubRouteUrl("blog", "Blog.Blog", new { username = (Model.System) ? string.Empty : Model.Blog.User.Username })">@((Model.System) ? Config.BlogConfig.Title : (string.IsNullOrEmpty(Model.Blog.User.BlogSettings.Title) ? string.Format("{0}'s Blog", Model.Blog.User.Username) : Model.Blog.User.BlogSettings.Title))</a></li>
<li class="active"><a href="#">@Model.Title</a></li> <li class="active"><a href="#">@Model.Title</a></li>
</ol> </ol>
@Html.Partial("../../Areas/Blog/Views/Blog/Post", Model) @await Html.PartialAsync("../../Areas/Blog/Views/Blog/Post", Model)
if (Request.IsAuthenticated) if (User.Identity.IsAuthenticated)
{ {
<div class="row"> <div class="row">
<div class="col-sm-10 col-sm-offset-1"> <div class="col-sm-10 col-sm-offset-1">
@ -42,7 +40,7 @@
<div class="modal fade" id="newComment" tabindex="-1" role="dialog" aria-labelledby="newCommentLabel" aria-hidden="true"> <div class="modal fade" id="newComment" tabindex="-1" role="dialog" aria-labelledby="newCommentLabel" aria-hidden="true">
<div class="modal-dialog"> <div class="modal-dialog">
<div class="modal-content"> <div class="modal-content">
<form class="form" action="##" method="post" id="publishComment"> <!form class="form" action="##" method="post" id="publishComment">
<div class="modal-header"> <div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Cancel</span></button> <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Cancel</span></button>
<h4 class="modal-title" id="newCommentLabel">Add a New Comment</h4> <h4 class="modal-title" id="newCommentLabel">Add a New Comment</h4>
@ -60,14 +58,14 @@
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button> <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" id="comment_submit">Publish</button> <button type="button" class="btn btn-primary" id="comment_submit">Publish</button>
</div> </div>
</form> </!form>
</div> </div>
</div> </div>
</div> </div>
<div class="modal fade" id="editComment" tabindex="-1" role="dialog" aria-labelledby="editCommentLabel" aria-hidden="true"> <div class="modal fade" id="editComment" tabindex="-1" role="dialog" aria-labelledby="editCommentLabel" aria-hidden="true">
<div class="modal-dialog"> <div class="modal-dialog">
<div class="modal-content"> <div class="modal-content">
<form class="form" action="##" method="post" id="editCommentForm"> <!form class="form" action="##" method="post" id="editCommentForm">
<div class="modal-header"> <div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Cancel</span></button> <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Cancel</span></button>
<h4 class="modal-title" id="editCommentLabel">Edit Your Comment</h4> <h4 class="modal-title" id="editCommentLabel">Edit Your Comment</h4>
@ -85,19 +83,19 @@
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button> <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" id="edit_comment_submit">Save</button> <button type="button" class="btn btn-primary" id="edit_comment_submit">Save</button>
</div> </div>
</form> </!form>
</div> </div>
</div> </div>
</div> </div>
} }
<a name="replies"></a> <a name="replies"></a>
<div class="post-comments" id="@Model.PostId"></div> <div class="post-comments" id="@Model.PostId"></div>
<script nonce="@Context.Items[Constants.NONCE_KEY]"> <script>
linkPostDelete('.delete_post'); linkPostDelete('.delete_post');
linkPostPublish('.publish_post'); linkPostPublish('.publish_post');
linkPostUnpublish('.unpublish_post'); linkPostUnpublish('.unpublish_post');
var posts = @(Model.Config.BlogConfig.CommentsToLoad); var posts = @(Config.BlogConfig.CommentsToLoad);
var start_post = 0; var start_post = 0;
var view_post_id = @(Model.PostId); var view_post_id = @(Model.PostId);
loadMoreComments(start_post, posts); loadMoreComments(start_post, posts);

View File

@ -1,3 +0,0 @@
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}

View File

@ -1,36 +0,0 @@
<?xml version="1.0"?>
<configuration>
<configSections>
<sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
<section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
</sectionGroup>
</configSections>
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="Teknik.BaseViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="System.Web.Optimization" />
<add namespace="Teknik" />
</namespaces>
</pages>
</system.web.webPages.razor>
<appSettings>
<add key="webpages:Enabled" value="false" />
</appSettings>
<system.webServer>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" />
</handlers>
</system.webServer>
</configuration>

View File

@ -1,44 +0,0 @@
using System.Collections.Generic;
using System.Web.Mvc;
using System.Web.Optimization;
using Teknik.Configuration;
using Teknik.Utilities;
namespace Teknik.Areas.Contact
{
public class ContactAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "Contact";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
Config config = Config.Load();
context.MapSubdomainRoute(
"Contact.Index", // Route name
new List<string>() { "contact" }, // Subdomains
new List<string>() { config.Host }, // domains
"", // URL with parameters
new { controller = "Contact", action = "Index" }, // Parameter defaults
new[] { typeof(Controllers.ContactController).Namespace }
);
context.MapSubdomainRoute(
"Contact.Action", // Route name
new List<string>() { "contact" }, // Subdomains
new List<string>() { config.Host }, // domains
"{action}", // URL with parameters
new { controller = "Contact", action = "Index" }, // Parameter defaults
new[] { typeof(Controllers.ContactController).Namespace }
);
// Register Bundles
BundleTable.Bundles.Add(new CdnScriptBundle("~/bundles/contact", config.CdnHost).Include(
"~/Areas/Contact/Scripts/Contact.js"));
}
}
}

View File

@ -2,7 +2,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Web; using System.Web;
using System.Web.Mvc;
using System.Net.Mail; using System.Net.Mail;
using Teknik.Controllers; using Teknik.Controllers;
using Teknik.Areas.Contact.ViewModels; using Teknik.Areas.Contact.ViewModels;
@ -11,18 +10,26 @@ using Teknik.Models;
using System.Text; using System.Text;
using Teknik.Filters; using Teknik.Filters;
using Teknik.Attributes; using Teknik.Attributes;
using Microsoft.Extensions.Logging;
using Teknik.Configuration;
using Teknik.Data;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Teknik.Logging;
namespace Teknik.Areas.Contact.Controllers namespace Teknik.Areas.Contact.Controllers
{ {
[TeknikAuthorize] [TeknikAuthorize]
[Area("Contact")]
public class ContactController : DefaultController public class ContactController : DefaultController
{ {
// GET: Contact/Contact public ContactController(ILogger<Logger> logger, Config config, TeknikEntities dbContext) : base(logger, config, dbContext) { }
[TrackPageView] [TrackPageView]
[AllowAnonymous] [AllowAnonymous]
public ActionResult Index() public IActionResult Index()
{ {
ViewBag.Title = "Contact - " + Config.Title; ViewBag.Title = "Contact - " + _config.Title;
ViewBag.Description = "Contact Teknik Support"; ViewBag.Description = "Contact Teknik Support";
return View(new ContactViewModel()); return View(new ContactViewModel());
@ -30,39 +37,36 @@ namespace Teknik.Areas.Contact.Controllers
[HttpPost] [HttpPost]
[AllowAnonymous] [AllowAnonymous]
public ActionResult Submit(ContactViewModel model) public IActionResult Submit(ContactViewModel model)
{ {
if (ModelState.IsValid) if (ModelState.IsValid)
{ {
if (Config.ContactConfig.Enabled) if (_config.ContactConfig.Enabled)
{ {
try try
{ {
using (TeknikEntities db = new TeknikEntities()) // Insert the message into the DB
{ Models.Contact newContact = new Models.Contact();
// Insert the message into the DB newContact.Name = model.Name;
Models.Contact newContact = db.Contact.Create(); newContact.Email = model.Email;
newContact.Name = model.Name; newContact.Subject = model.Subject;
newContact.Email = model.Email; newContact.Message = model.Message;
newContact.Subject = model.Subject; newContact.DateAdded = DateTime.Now;
newContact.Message = model.Message; _dbContext.Contact.Add(newContact);
newContact.DateAdded = DateTime.Now; _dbContext.SaveChanges();
db.Contact.Add(newContact);
db.SaveChanges();
}
// Let's also email the message to support // Let's also email the message to support
SmtpClient client = new SmtpClient(); SmtpClient client = new SmtpClient();
client.Host = Config.ContactConfig.EmailAccount.Host; client.Host = _config.ContactConfig.EmailAccount.Host;
client.Port = Config.ContactConfig.EmailAccount.Port; client.Port = _config.ContactConfig.EmailAccount.Port;
client.EnableSsl = Config.ContactConfig.EmailAccount.SSL; client.EnableSsl = _config.ContactConfig.EmailAccount.SSL;
client.DeliveryMethod = SmtpDeliveryMethod.Network; client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.UseDefaultCredentials = true; client.UseDefaultCredentials = true;
client.Credentials = new System.Net.NetworkCredential(Config.ContactConfig.EmailAccount.Username, Config.ContactConfig.EmailAccount.Password); client.Credentials = new System.Net.NetworkCredential(_config.ContactConfig.EmailAccount.Username, _config.ContactConfig.EmailAccount.Password);
client.Timeout = 5000; client.Timeout = 5000;
MailMessage mail = new MailMessage(new MailAddress(model.Email, model.Name), new MailAddress(Config.SupportEmail, "Teknik Support")); MailMessage mail = new MailMessage(new MailAddress(model.Email, model.Name), new MailAddress(_config.SupportEmail, "Teknik Support"));
mail.Sender = new MailAddress(Config.ContactConfig.EmailAccount.EmailAddress); mail.Sender = new MailAddress(_config.ContactConfig.EmailAccount.EmailAddress);
mail.Subject = model.Subject; mail.Subject = model.Subject;
mail.Body = model.Message; mail.Body = model.Message;
mail.BodyEncoding = UTF8Encoding.UTF8; mail.BodyEncoding = UTF8Encoding.UTF8;

View File

@ -1,8 +1,5 @@
@model Teknik.Areas.Contact.ViewModels.ContactViewModel @model Teknik.Areas.Contact.ViewModels.ContactViewModel
@using Teknik.Utilities
@Scripts.Render("~/bundles/contact")
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-sm-12 col-lg-12"> <div class="col-sm-12 col-lg-12">
@ -16,7 +13,7 @@
<div class="row"> <div class="row">
<div class="col-md-8"> <div class="col-md-8">
<div class="well well-sm"> <div class="well well-sm">
<form role="form" id="contactForm" action="@Url.SubRouteUrl("contact", "Contact.Action", new { action = "Submit" })" method="post" accept-charset="UTF-8"> <!form role="form" id="contactForm" action="@Url.SubRouteUrl("contact", "Contact.Action", new { action = "Submit" })" method="post" accept-charset="UTF-8">
@Html.ValidationSummary(true, "Message send failed.") @Html.ValidationSummary(true, "Message send failed.")
<div class="row"> <div class="row">
<div class="col-md-6"> <div class="col-md-6">
@ -25,7 +22,7 @@
<label for="Name"> <label for="Name">
Name Name
</label> </label>
<input type="text" class="form-control" id="Name" name="Name" placeholder="Enter name" required="required" value="@((Request.IsAuthenticated) ? User.Identity.Name : string.Empty)" /> <input type="text" class="form-control" id="Name" name="Name" placeholder="Enter name" required="required" value="@((User.Identity.IsAuthenticated) ? User.Identity.Name : string.Empty)" />
</div> </div>
<div class="form-group"> <div class="form-group">
@Html.ValidationMessageFor(u => u.Email) @Html.ValidationMessageFor(u => u.Email)
@ -36,7 +33,7 @@
<span class="input-group-addon"> <span class="input-group-addon">
<span class="glyphicon glyphicon-envelope"></span> <span class="glyphicon glyphicon-envelope"></span>
</span> </span>
<input type="email" class="form-control" id="Email" name="Email" placeholder="Enter email" required="required" value="@((Request.IsAuthenticated) ? User.Identity.Name + "@" + Model.Config.Host : string.Empty)" /> <input type="email" class="form-control" id="Email" name="Email" placeholder="Enter email" required="required" value="@((User.Identity.IsAuthenticated) ? User.Identity.Name + "@" + Config.Host : string.Empty)" />
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
@ -63,24 +60,26 @@
</button> </button>
</div> </div>
</div> </div>
</form> </!form>
</div> </div>
<div class="row"> <div class="row">
<div class="col-sm-10 col-sm-offset-1"><p>If you want to report abuse, follow the instructions at the <a href="@Url.SubRouteUrl("abuse", "Abuse.Index")">Abuse Prevention</a> page.</p></div> <div class="col-sm-10 col-sm-offset-1"><p>If you want to report abuse, follow the instructions at the <a href="@Url.SubRouteUrl("abuse", "Abuse.Index")">Abuse Prevention</a> page.</p></div>
</div> </div>
</div> </div>
<div class="col-md-4"> <div class="col-md-4">
<form> <!form>
<legend><span class="glyphicon glyphicon-globe"></span> Where to find us</legend> <legend><span class="glyphicon glyphicon-globe"></span> Where to find us</legend>
<address> <address>
<strong>Customer Support</strong><br> <strong>Customer Support</strong><br>
<a href="mailto:@Model.Config.SupportEmail">@Model.Config.SupportEmail</a> <a href="mailto:@Config.SupportEmail">@Config.SupportEmail</a>
</address> </address>
<address> <address>
<strong>Teknik on Rizon IRC</strong><br> <strong>Teknik on Rizon IRC</strong><br>
#Teknik (<a href="irc://irc.rizon.net" target="_blank">irc.rizon.net</a>)<br> #Teknik (<a href="irc://irc.rizon.net" target="_blank">irc.rizon.net</a>)<br>
</address> </address>
</form> </!form>
</div> </div>
</div> </div>
</div> </div>
<bundle src="js/contact.min.js" append-version="true"></bundle>

View File

@ -1,3 +0,0 @@
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}

View File

@ -1,36 +0,0 @@
<?xml version="1.0"?>
<configuration>
<configSections>
<sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
<section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
</sectionGroup>
</configSections>
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="Teknik.BaseViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="System.Web.Optimization" />
<add namespace="Teknik" />
</namespaces>
</pages>
</system.web.webPages.razor>
<appSettings>
<add key="webpages:Enabled" value="false" />
</appSettings>
<system.webServer>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" />
</handlers>
</system.webServer>
</configuration>

View File

@ -1,22 +1,25 @@
using System; using Microsoft.AspNetCore.Authorization;
using System.Collections.Generic; using Microsoft.AspNetCore.Mvc;
using System.Linq; using Microsoft.Extensions.Logging;
using System.Web;
using System.Web.Mvc;
using Teknik.Attributes; using Teknik.Attributes;
using Teknik.Configuration;
using Teknik.Controllers; using Teknik.Controllers;
using Teknik.Data;
using Teknik.Filters; using Teknik.Filters;
using Teknik.Utilities; using Teknik.Utilities;
using Teknik.Logging;
namespace Teknik.Areas.Dev.Controllers namespace Teknik.Areas.Dev.Controllers
{ {
[TeknikAuthorize] [TeknikAuthorize]
[Area("Dev")]
public class DevController : DefaultController public class DevController : DefaultController
{ {
public DevController(ILogger<Logger> logger, Config config, TeknikEntities dbContext) : base(logger, config, dbContext) { }
[TrackPageView] [TrackPageView]
[AllowAnonymous] [AllowAnonymous]
// GET: Dev public IActionResult Index()
public ActionResult Index()
{ {
return Redirect(Url.SubRouteUrl("www", "Home.Index")); return Redirect(Url.SubRouteUrl("www", "Home.Index"));
} }

View File

@ -1,31 +0,0 @@
using System.Collections.Generic;
using System.Web.Mvc;
using Teknik.Areas.Home.Controllers;
using Teknik.Configuration;
namespace Teknik.Areas.Dev
{
public class DevAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "Dev";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
Config config = Config.Load();
context.MapSubdomainRoute(
"Dev.Index", // Route name
new List<string>() { "dev" }, // Subdomains
new List<string>() { config.Host }, // domains
"", // URL with parameters
new { controller = "Dev", action = "Index" }, // Parameter defaults
new[] { typeof(Controllers.DevController).Namespace }
);
}
}
}

View File

@ -1,3 +0,0 @@
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}

Some files were not shown because too many files have changed in this diff Show More