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

Merged utilities separation with Master

This commit is contained in:
Uncled1023 2017-01-09 19:59:14 -08:00
commit 078523f1f5
18 changed files with 287 additions and 78 deletions

9
.editorconfig Normal file
View File

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

View File

@ -5,7 +5,7 @@ Teknik is a suite of services with attractive and functional interfaces.
## Features
* File Upload w/ encryption
* Pastebin
* Url Shortening
* URL Shortening
* Blogs
* Git Repositories
* Podcasts
@ -17,27 +17,27 @@ You can see a live demo [here](https://www.teknik.io).
## Requirements
In order to run Teknik on your server, you'll need:
* IIS 7+ with URL Rewrite module or Apache with mod_rewrite enabled (Requires conversion of web.config files)
* IIS 7+ with URL Rewrite module or Apache with `mod_rewrite` enabled (Requires conversion of `web.config` files)
* ASP.NET MVC 5
* .NET Framework 4.5.2
* MS SQL Server
* hMailServer (If running email as well)
* Web Mail Client (If you would like to have webmail)
* Gogs Service (If you want to have git integration)
* Gogs Service (If you want to have Git integration)
## Installation
* Clone the Teknik repository to your web root directory, or anywhere else you want to run Teknik from.
* Clone the Teknik repository to your web root directory, or anywhere else you want to run Teknik from
```
```nohighlight
cd /var/www
git clone https://git.teknik.io/Teknikode/Teknik
```
* Open the Teknik.sln file to build the project.
* Copy the build files to your wwwroot directory.
* Create a **ConnectionStrings.config** file in the **App_Data** directory and fill it with the following template and put in your sql server conenction details
* Open the `Teknik.sln` file to build the project
* Copy the build files to your `wwwroot` directory
* Create a `ConnectionStrings.config` file in the `App_Data` directory and fill it with the following template and put in your SQL server connection details
```
```nohighlight
<connectionStrings>
<add name="TeknikEntities"
providerName="System.Data.SqlClient"
@ -45,23 +45,22 @@ git clone https://git.teknik.io/Teknikode/Teknik
</connectionStrings>
```
* After first run, a **Config.json** file will be created in the **App_Data** directory. This will need to be edited with your configuration options.
* After the first run, a `Config.json` file will be created in the `App_Data` directory. This will need to be edited with your configuration options.
**That's it**, installation complete! If you're having problems, let us know through the [Contact](https://contact.teknik.io/) page.
That's it, installation complete! If you're having problems, let us know through the [Contact](https://contact.teknik.io/) page.
## Authors and contributors
* [Chris Woodward](https://www.teknik.io) (Creator, developer)
* [Chris Woodward](https://www.teknik.io) (Creator, Developer)
* [dronedaddy](https://www.behance.net/dronedaddy) (Logo Designer)
## License
[BSD 3-Clause license](http://opensource.org/licenses/BSD-3-Clause)
## Development
You can view Teknik's [Development Branch](https://dev.teknik.io/) to see the current new features. (It may not work, as it is a development branch)
You can view Teknik's [Development Branch](https://dev.teknik.io/) to see the current new features (It may not work, as it is a development branch).
## Contributing
If you are a developer, we need your help. Teknik is a young project and we have lot's of stuff to do. Some developers are contributing with new features, others with bug fixes. Any help you can give would be greatly appreciated!
If you are a developer, we need your help. Teknik is a young project and we have lots of stuff to do. Some developers are contributing with new features, others with bug fixes. Any help you can give would be greatly appreciated!
## Further information
If you want to know more about the features of Teknik, check the [Help](https://help.teknik.io/) page. Also, if you're having problems with Teknik, let us know through the [Contact](https://contact.teknik.io/) page. Don't forget to give feedback and suggest new features! :)

View File

@ -7,6 +7,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Teknik", "Teknik\Teknik.csp
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{725ABF52-FD44-4682-81BB-D93598787643}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
GitVersionConfig.yaml = GitVersionConfig.yaml
README.md = README.md
EndProjectSection

View File

@ -0,0 +1,2 @@
User-agent: *
Disallow: /

View File

@ -14,7 +14,7 @@ using System.Text;
using Teknik.Areas.Shortener.Models;
using nClam;
using Teknik.Filters;
using Teknik.Utilities;
using Teknik.Areas.API.Models;
namespace Teknik.Areas.API.Controllers
{
@ -31,22 +31,21 @@ namespace Teknik.Areas.API.Controllers
[HttpPost]
[AllowAnonymous]
[TrackPageView]
public ActionResult Upload(HttpPostedFileWrapper file, string contentType = null, bool encrypt = true, bool saveKey = true, string key = null, int keySize = 0, string iv = null, int blockSize = 0, bool genDeletionKey = false, bool doNotTrack = false)
public ActionResult Upload(APIv1UploadModel model)
{
try
{
ViewBag.Title = "Upload";
if (file != null)
if (model.file != null)
{
if (file.ContentLength <= Config.UploadConfig.MaxUploadSize)
if (model.file.ContentLength <= Config.UploadConfig.MaxUploadSize)
{
// convert file to bytes
byte[] fileData = null;
string fileExt = Path.GetExtension(file.FileName);
int contentLength = file.ContentLength;
using (var binaryReader = new BinaryReader(file.InputStream))
string fileExt = Path.GetExtension(model.file.FileName);
int contentLength = model.file.ContentLength;
using (var binaryReader = new BinaryReader(model.file.InputStream))
{
fileData = binaryReader.ReadBytes(file.ContentLength);
fileData = binaryReader.ReadBytes(model.file.ContentLength);
}
// Scan the file to detect a virus
@ -54,13 +53,13 @@ namespace Teknik.Areas.API.Controllers
{
byte[] scanData = fileData;
// If it was encrypted client side, decrypt it
if (!encrypt && key != null)
if (!model.encrypt && model.key != null)
{
// If the IV is set, and Key is set, then decrypt it
if (!string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(iv))
if (!string.IsNullOrEmpty(model.key) && !string.IsNullOrEmpty(model.iv))
{
// Decrypt the data
scanData = AES.Decrypt(scanData, key, iv);
scanData = AES.Decrypt(scanData, model.key, model.iv);
}
}
ClamClient clam = new ClamClient(Config.UploadConfig.ClamServer, Config.UploadConfig.ClamPort);
@ -81,32 +80,32 @@ namespace Teknik.Areas.API.Controllers
}
// Need to grab the contentType if it's empty
if (string.IsNullOrEmpty(contentType))
if (string.IsNullOrEmpty(model.contentType))
{
contentType = (string.IsNullOrEmpty(file.ContentType)) ? "application/octet-stream" : file.ContentType;
model.contentType = (string.IsNullOrEmpty(model.file.ContentType)) ? "application/octet-stream" : model.file.ContentType;
}
// Initialize the key size and block size if empty
if (keySize <= 0)
keySize = Config.UploadConfig.KeySize;
if (blockSize <= 0)
blockSize = Config.UploadConfig.BlockSize;
if (model.keySize <= 0)
model.keySize = Config.UploadConfig.KeySize;
if (model.blockSize <= 0)
model.blockSize = Config.UploadConfig.BlockSize;
byte[] data = null;
// If they want us to encrypt the file first, do that here
if (encrypt)
if (model.encrypt)
{
// Generate key and iv if empty
if (string.IsNullOrEmpty(key))
if (string.IsNullOrEmpty(model.key))
{
key = StringHelper.RandomString(keySize / 8);
model.key = Utility.RandomString(model.keySize / 8);
}
if (string.IsNullOrEmpty(iv))
if (string.IsNullOrEmpty(model.iv))
{
iv = StringHelper.RandomString(blockSize / 8);
model.iv = Utility.RandomString(model.blockSize / 8);
}
data = AES.Encrypt(fileData, key, iv);
data = AES.Encrypt(fileData, model.key, model.iv);
if (data == null || data.Length <= 0)
{
return Json(new { error = new { message = "Unable to encrypt file" } });
@ -114,14 +113,14 @@ namespace Teknik.Areas.API.Controllers
}
// Save the file data
Upload.Models.Upload upload = Uploader.SaveFile(db, Config, (encrypt) ? data : fileData, contentType, contentLength, fileExt, iv, (saveKey) ? key : null, keySize, blockSize);
Upload.Models.Upload upload = Uploader.SaveFile(db, Config, (model.encrypt) ? data : fileData, model.contentType, contentLength, fileExt, model.iv, (model.saveKey) ? model.key : null, model.keySize, model.blockSize);
if (upload != null)
{
// Generate delete key if asked to
if (genDeletionKey)
if (model.genDeletionKey)
{
string delKey = StringHelper.RandomString(Config.UploadConfig.DeleteKeyLength);
string delKey = Utility.RandomString(Config.UploadConfig.DeleteKeyLength);
upload.DeleteKey = delKey;
db.Entry(upload).State = EntityState.Modified;
db.SaveChanges();
@ -131,14 +130,14 @@ namespace Teknik.Areas.API.Controllers
string fullUrl = Url.SubRouteUrl("upload", "Upload.Download", new { file = upload.Url });
var returnData = new
{
url = (saveKey || string.IsNullOrEmpty(key)) ? fullUrl : fullUrl + "#" + key,
url = (model.saveKey || string.IsNullOrEmpty(model.key)) ? fullUrl : fullUrl + "#" + model.key,
fileName = upload.Url,
contentType = contentType,
contentType = model.contentType,
contentLength = contentLength,
key = key,
keySize = keySize,
iv = iv,
blockSize = blockSize,
key = model.key,
keySize = model.keySize,
iv = model.iv,
blockSize = model.blockSize,
deletionKey = upload.DeleteKey
};
@ -151,7 +150,6 @@ namespace Teknik.Areas.API.Controllers
return Json(new { error = new { message = "File Too Large" } });
}
}
return Json(new { error = new { message = "Invalid Upload Request" } });
}
catch(Exception ex)
@ -163,28 +161,31 @@ namespace Teknik.Areas.API.Controllers
[HttpPost]
[AllowAnonymous]
[TrackPageView]
public ActionResult Paste(string code, string title = "", string syntax = "text", string expireUnit = "never", int expireLength = 1, string password = "", bool hide = false, bool doNotTrack = false)
public ActionResult Paste(APIv1PasteModel model)
{
try
{
ViewBag.Title = "Paste";
Paste.Models.Paste paste = PasteHelper.CreatePaste(code, title, syntax, expireUnit, expireLength, password, hide);
db.Pastes.Add(paste);
db.SaveChanges();
return Json(new
if (model != null && model.code != null)
{
result = new
Paste.Models.Paste paste = PasteHelper.CreatePaste(model.code, model.title, model.syntax, model.expireUnit, model.expireLength, model.password, model.hide);
db.Pastes.Add(paste);
db.SaveChanges();
return Json(new
{
id = paste.Url,
url = Url.SubRouteUrl("paste", "Paste.View", new { type = "Full", url = paste.Url, password = password }),
title = paste.Title,
syntax = paste.Syntax,
expiration = paste.ExpireDate,
password = password
}
});
result = new
{
id = paste.Url,
url = Url.SubRouteUrl("paste", "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" } });
}
catch (Exception ex)
{
@ -195,14 +196,13 @@ namespace Teknik.Areas.API.Controllers
[HttpPost]
[AllowAnonymous]
[TrackPageView]
public ActionResult Shorten(string url, bool doNotTrack = false)
public ActionResult Shorten(APIv1ShortenModel model)
{
try
{
ViewBag.Title = "Shorten";
if (url.IsValidUrl())
if (model.url.IsValidUrl())
{
ShortenedUrl newUrl = Shortener.Shortener.ShortenUrl(url, Config.ShortenerConfig.UrlLength);
ShortenedUrl newUrl = Shortener.Shortener.ShortenUrl(model.url, Config.ShortenerConfig.UrlLength);
db.ShortenedUrls.Add(newUrl);
db.SaveChanges();
@ -218,7 +218,7 @@ namespace Teknik.Areas.API.Controllers
result = new
{
shortUrl = shortUrl,
originalUrl = url
originalUrl = model.url
}
});
}

View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace Teknik.Areas.API.Models
{
public class APIv1BaseModel
{
public bool doNotTrack { get; set; }
public APIv1BaseModel()
{
doNotTrack = false;
}
}
}

View File

@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace Teknik.Areas.API.Models
{
public class APIv1PasteModel : APIv1BaseModel
{
[AllowHtml]
public string code { get; set; }
public string title { get; set; }
public string syntax { get; set; }
public string expireUnit { get; set; }
public int expireLength { get; set; }
public string password { get; set; }
public bool hide { get; set; }
public APIv1PasteModel()
{
code = null;
title = string.Empty;
syntax = "text";
expireUnit = "never";
expireLength = 1;
password = string.Empty;
hide = false;
}
}
}

View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace Teknik.Areas.API.Models
{
public class APIv1ShortenModel : APIv1BaseModel
{
public string url { get; set; }
public APIv1ShortenModel()
{
url = string.Empty;
}
}
}

View File

@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace Teknik.Areas.API.Models
{
public class APIv1UploadModel : APIv1BaseModel
{
public HttpPostedFileWrapper file { get; set; }
public string contentType { get; set; }
public bool encrypt { get; set; }
public bool saveKey { get; set; }
public string key { get; set; }
public int keySize { get; set; }
public string iv { get; set; }
public int blockSize { get; set; }
public bool genDeletionKey { get; set; }
public APIv1UploadModel()
{
file = null;
contentType = null;
encrypt = true;
saveKey = true;
key = null;
keySize = 0;
iv = null;
blockSize = 0;
genDeletionKey = false;
}
}
}

View File

@ -1,11 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Mail;
using System.Text;
using System.Web;
using System.Web.Mvc;
using Teknik.Areas.Error.ViewModels;
using Teknik.Controllers;
using Teknik.Filters;
using Teknik.Helpers;
namespace Teknik.Areas.Error.Controllers
{
@ -24,6 +27,11 @@ namespace Teknik.Areas.Error.Controllers
Response.TrySkipIisCustomErrors = true;
}
if (exception != null)
{
SendErrorEmail(exception);
}
ErrorViewModel model = new ErrorViewModel();
model.Exception = exception;
@ -43,6 +51,11 @@ namespace Teknik.Areas.Error.Controllers
Response.TrySkipIisCustomErrors = true;
}
if (exception != null)
{
SendErrorEmail(exception);
}
ErrorViewModel model = new ErrorViewModel();
model.Description = exception.Message;
model.Exception = exception;
@ -62,6 +75,11 @@ namespace Teknik.Areas.Error.Controllers
Response.TrySkipIisCustomErrors = true;
}
if (exception != null)
{
SendErrorEmail(exception);
}
ErrorViewModel model = new ErrorViewModel();
model.Exception = exception;
@ -99,10 +117,45 @@ namespace Teknik.Areas.Error.Controllers
Response.TrySkipIisCustomErrors = true;
}
if (exception != null)
{
SendErrorEmail(exception);
}
ErrorViewModel model = new ErrorViewModel();
model.Exception = exception;
return View("/Areas/Error/Views/Error/Http500.cshtml", model);
}
private void SendErrorEmail(Exception ex)
{
try
{
// Let's also email the message to support
SmtpClient client = new SmtpClient();
client.Host = Config.ContactConfig.Host;
client.Port = Config.ContactConfig.Port;
client.EnableSsl = Config.ContactConfig.SSL;
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.UseDefaultCredentials = true;
client.Credentials = new System.Net.NetworkCredential(Config.ContactConfig.Username, Config.ContactConfig.Password);
client.Timeout = 5000;
MailMessage mail = new MailMessage(Config.SupportEmail, Config.SupportEmail);
mail.Subject = string.Format("Exception Occured on: {0}", Request.Url.AbsoluteUri);
mail.Body = string.Format(@"
Message: {0}
Source: {1}
Stack Trace: {2}", ex.GetFullMessage(true), ex.Source, ex.StackTrace);
mail.BodyEncoding = UTF8Encoding.UTF8;
mail.DeliveryNotificationOptions = DeliveryNotificationOptions.Never;
client.Send(mail);
}
catch (Exception) { /* don't handle something in the handler */ }
}
}
}

View File

@ -1,5 +1,7 @@
@model Teknik.Areas.Error.ViewModels.ErrorViewModel
@using Teknik.Helpers
<div class="container">
<div class="row">
<div class="col-md-12">
@ -14,7 +16,7 @@
{
<div class="text-left">
<p>
<b>Exception:</b> @Model.Exception.Message
<b>Exception:</b> @Model.Exception.GetFullMessage(true)
<br />
<b>Source:</b> @Model.Exception.Source
</p>

View File

@ -6,7 +6,7 @@
<hr>
<h3>Authorization</h3>
<p>
To login into your git account, you will initially need to initially use your teknik email address to login using the web interface. Once you have done so at least once, you can from then on use your teknik username.
To login into your Git account, you will initially need to use your Teknik email address to login using the web interface. Once you have done so at least once, you can from then on use your Teknik username.
</p>
</div>
</div>

View File

@ -18,19 +18,21 @@
<h3 class="text-center">Help Topics</h3>
<dl class="dl-horizontal">
<dt><a href="@Url.SubRouteUrl("help", "Help.API")">API</a></dt>
<dd>Open API available to interact with the difference services.</dd>
<dd>Open API available to interact with the different services.</dd>
<dt><a href="@Url.SubRouteUrl("help", "Help.Blog")">Blogging</a></dt>
<dd>Blogging platform available to the users and visible to the public.</dd>
<dt><a href="@Url.SubRouteUrl("help", "Help.Git")">Git Repositories</a></dt>
<dd>Unlimited public and private git repositories.</dd>
<dd>Unlimited public and private Git repositories.</dd>
<dt><a href="@Url.SubRouteUrl("help", "Help.IRC")">IRC Network</a></dt>
<dd>IRC network that uses the Teknik userbase for nickname authentication.</dd>
<dt><a href="@Url.SubRouteUrl("help", "Help.Mail")">Mail Server</a></dt>
<dd>Mail service with IMAP and POP3 support with <b>1 GB</b> storage.</dd>
<dd>Mail service featuring IMAP and POP3 support with <b>1 GB</b> storage.</dd>
<dt><a href="@Url.SubRouteUrl("help", "Help.Markdown")">Markdown</a></dt>
<dd>Markdown syntax used throughout the site.</dd>
<dt><a href="@Url.SubRouteUrl("help", "Help.Mumble")">Mumble Chat Server</a></dt>
<dd>The public Mumble server and configuration settings needed.</dd>
<dt><a href="@Url.SubRouteUrl("help", "Help.RSS")">RSS Feeds</a></dt>
<dd>Built-in RSS support for content updates.</dd>
<dt><a href="@Url.SubRouteUrl("help", "Help.Tools")">Tools</a></dt>
<dd>Internal and 3rd Party Tools for interfacing with our services.</dd>
<dt><a href="@Url.SubRouteUrl("help", "Help.Upload")">Uploads</a></dt>

View File

@ -42,6 +42,16 @@ namespace Teknik.Areas.Home
new[] { typeof(DefaultController).Namespace }
);
// Handle robots.txt file requests
context.MapSubdomainRoute(
"Default.Robots", // Route name
new List<string>() { "*" }, // Subdomains
new List<string>() { config.Host, config.ShortenerConfig.ShortenerHost }, // domains
"robots.txt", // URL with parameters
new { controller = "Default", action = "Robots" }, // Parameter defaults
new[] { typeof(DefaultController).Namespace }
);
// Register fallback for all bad requests
context.MapSubdomainRoute(
"Default.NotFound", // Route name

View File

@ -68,6 +68,16 @@ namespace Teknik.Controllers
return File(imageFile, "image/svg+xml");
}
// Get the Logo
[HttpGet]
[AllowAnonymous]
public ActionResult Robots()
{
// Get favicon
string file = Server.MapPath(Constants.ROBOTS_PATH);
return File(file, "text/plain");
}
[HttpGet]
[AllowAnonymous]
public ActionResult NotFound()

View File

@ -108,8 +108,10 @@ namespace Teknik
protected void Application_Error(object sender, EventArgs e)
{
// Get the last exception
Exception exception = Server.GetLastError();
// Clear the response
Response.Clear();
HttpException httpException = exception as HttpException;

View File

@ -13,5 +13,6 @@ namespace Teknik.Helpers
public const string TRUSTEDDEVICECOOKIE = "TeknikTrustedDevice";
public const string LOGO_PATH = "~/Images/logo-black.svg";
public const string FAVICON_PATH = "~/Images/favicon.ico";
public const string ROBOTS_PATH = "~/App_Data/robots.txt";
}
}

View File

@ -192,6 +192,10 @@
<Compile Include="Areas\API\APIAreaRegistration.cs" />
<Compile Include="Areas\API\Controllers\APIController.cs" />
<Compile Include="Areas\API\Controllers\APIv1Controller.cs" />
<Compile Include="Areas\API\Models\APIv1BaseModel.cs" />
<Compile Include="Areas\API\Models\APIv1PasteModel.cs" />
<Compile Include="Areas\API\Models\APIv1ShortenModel.cs" />
<Compile Include="Areas\API\Models\APIv1UploadModel.cs" />
<Compile Include="Areas\Blog\BlogAreaRegistration.cs" />
<Compile Include="Areas\Blog\Models\BlogPostComment.cs" />
<Compile Include="Areas\Blog\ViewModels\BlogViewModel.cs" />
@ -345,6 +349,9 @@
<Content Include="App_Data\reservedUsernames.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="App_Data\robots.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Areas\Admin\Scripts\Search.js" />
<Content Include="Areas\Blog\Content\Blog.css" />
<Content Include="Areas\Blog\Scripts\Blog.js" />
@ -665,7 +672,6 @@
<Folder Include="Areas\About\Views\Shared\" />
<Folder Include="Areas\Admin\Models\" />
<Folder Include="Areas\Admin\Views\Shared\" />
<Folder Include="Areas\API\Models\" />
<Folder Include="Areas\API\Views\APIv1\" />
<Folder Include="Areas\API\Views\API\" />
<Folder Include="Areas\API\Views\Shared\" />