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

Modified pastes to save content to encrypted files instead of saving to the DB.

This commit is contained in:
Uncled1023 2018-11-20 23:59:26 -08:00
parent 2799aac959
commit 0f7c912390
9 changed files with 910 additions and 48 deletions

View File

@ -1,19 +1,32 @@
namespace Teknik.Configuration using System.IO;
namespace Teknik.Configuration
{ {
public class PasteConfig public class PasteConfig
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int UrlLength { get; set; } public int UrlLength { get; set; }
public int DeleteKeyLength { get; set; }
public string SyntaxVisualStyle { get; set; }
// Location of the upload directory
public string PasteDirectory { get; set; }
// File Extension for saved files
public string FileExtension { get; set; }
public int KeySize { get; set; } public int KeySize { get; set; }
public int BlockSize { get; set; } public int BlockSize { get; set; }
public string SyntaxVisualStyle { get; set; } // The size of the chunk that the file will be encrypted/decrypted in (bytes)
public int ChunkSize { get; set; }
public PasteConfig() public PasteConfig()
{ {
Enabled = true; Enabled = true;
UrlLength = 5; UrlLength = 5;
DeleteKeyLength = 24;
KeySize = 256; KeySize = 256;
BlockSize = 128; BlockSize = 128;
ChunkSize = 1040;
PasteDirectory = Directory.GetCurrentDirectory();
FileExtension = "enc";
SyntaxVisualStyle = "vs"; SyntaxVisualStyle = "vs";
} }
} }

View File

@ -18,6 +18,8 @@ using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Teknik.Logging; using Teknik.Logging;
using System.IO;
using System.Threading.Tasks;
namespace Teknik.Areas.Paste.Controllers namespace Teknik.Areas.Paste.Controllers
{ {
@ -37,7 +39,7 @@ namespace Teknik.Areas.Paste.Controllers
} }
[AllowAnonymous] [AllowAnonymous]
public IActionResult ViewPaste(string type, string url, string password) public async Task<IActionResult> ViewPaste(string type, string url, string password)
{ {
Models.Paste paste = _dbContext.Pastes.Where(p => p.Url == url).FirstOrDefault(); Models.Paste paste = _dbContext.Pastes.Where(p => p.Url == url).FirstOrDefault();
if (paste != null) if (paste != null)
@ -59,13 +61,10 @@ namespace Teknik.Areas.Paste.Controllers
PasteViewModel model = new PasteViewModel(); PasteViewModel model = new PasteViewModel();
model.Url = url; model.Url = url;
model.Content = paste.Content;
model.Title = paste.Title; model.Title = paste.Title;
model.Syntax = paste.Syntax; model.Syntax = paste.Syntax;
model.DatePosted = paste.DatePosted; model.DatePosted = paste.DatePosted;
byte[] data = Encoding.UTF8.GetBytes(paste.Content);
if (User.Identity.IsAuthenticated && type.ToLower() == "full") if (User.Identity.IsAuthenticated && type.ToLower() == "full")
{ {
Users.Models.User user = UserHelper.GetUser(_dbContext, User.Identity.Name); Users.Models.User user = UserHelper.GetUser(_dbContext, User.Identity.Name);
@ -75,23 +74,17 @@ namespace Teknik.Areas.Paste.Controllers
} }
} }
byte[] ivBytes = Encoding.Unicode.GetBytes(paste.IV);
byte[] keyBytes = AesCounterManaged.CreateKey(paste.Key, ivBytes, paste.KeySize);
// The paste has a password set // The paste has a password set
if (!string.IsNullOrEmpty(paste.HashedPassword)) if (!string.IsNullOrEmpty(paste.HashedPassword))
{ {
string hash = string.Empty; string hash = string.Empty;
if (!string.IsNullOrEmpty(password)) if (!string.IsNullOrEmpty(password))
{ {
byte[] passBytes = SHA384.Hash(paste.Key, password); hash = PasteHelper.HashPassword(paste.Key, password);
hash = passBytes.ToHex(); keyBytes = AesCounterManaged.CreateKey(password, ivBytes, paste.KeySize);
// We need to convert old pastes to the new password scheme
//if (paste.Transfers.ToList().Exists(t => t.Type == TransferTypes.ASCIIPassword))
//{
// hash = Encoding.ASCII.GetString(passBytes);
// // Remove the transfer types
// paste.Transfers.Clear();
// _dbContext.Entry(paste).State = EntityState.Modified;
// _dbContext.SaveChanges();
//}
} }
if (string.IsNullOrEmpty(password) || hash != paste.HashedPassword) if (string.IsNullOrEmpty(password) || hash != paste.HashedPassword)
{ {
@ -108,13 +101,16 @@ namespace Teknik.Areas.Paste.Controllers
// Redirect them to the password request page // Redirect them to the password request page
return View("~/Areas/Paste/Views/Paste/PasswordNeeded.cshtml", passModel); return View("~/Areas/Paste/Views/Paste/PasswordNeeded.cshtml", passModel);
} }
}
data = Convert.FromBase64String(paste.Content); // Read in the file
// Now we decrypt the content string subDir = paste.FileName[0].ToString();
byte[] ivBytes = Encoding.Unicode.GetBytes(paste.IV); string filePath = Path.Combine(_config.PasteConfig.PasteDirectory, subDir, paste.FileName);
byte[] keyBytes = AesCounterManaged.CreateKey(password, ivBytes, paste.KeySize); using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
data = AesCounterManaged.Decrypt(data, keyBytes, ivBytes); using (AesCounterStream cs = new AesCounterStream(fs, false, keyBytes, ivBytes))
model.Content = Encoding.Unicode.GetString(data); using (StreamReader sr = new StreamReader(cs, Encoding.Unicode))
{
model.Content = await sr.ReadToEndAsync();
} }
switch (type.ToLower()) switch (type.ToLower())
@ -135,7 +131,8 @@ namespace Teknik.Areas.Paste.Controllers
Response.Headers.Add("Content-Disposition", cd.ToString()); Response.Headers.Add("Content-Disposition", cd.ToString());
return File(data, "application/octet-stream"); FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
return new BufferedFileStreamResult("application/octet-stream", async (response) => await ResponseHelper.StreamToOutput(response, true, new AesCounterStream(fs, false, keyBytes, ivBytes), (int)fs.Length, _config.PasteConfig.ChunkSize), false);
default: default:
return View("~/Areas/Paste/Views/Paste/Full.cshtml", model); return View("~/Areas/Paste/Views/Paste/Full.cshtml", model);
} }

View File

@ -24,6 +24,9 @@ namespace Teknik.Areas.Paste.Models
[CaseSensitive] [CaseSensitive]
public string Url { get; set; } public string Url { get; set; }
[CaseSensitive]
public string FileName { get; set; }
public string Content { get; set; } public string Content { get; set; }
public string Title { get; set; } public string Title { get; set; }
@ -45,6 +48,9 @@ namespace Teknik.Areas.Paste.Models
public int BlockSize { get; set; } public int BlockSize { get; set; }
[CaseSensitive]
public string DeleteKey { get; set; }
public bool Hide { get; set; } public bool Hide { get; set; }
public int MaxViews { get; set; } public int MaxViews { get; set; }

View File

@ -8,6 +8,7 @@ using Teknik.Utilities;
using Teknik.Models; using Teknik.Models;
using Teknik.Utilities.Cryptography; using Teknik.Utilities.Cryptography;
using Teknik.Data; using Teknik.Data;
using System.IO;
namespace Teknik.Areas.Paste namespace Teknik.Areas.Paste
{ {
@ -55,30 +56,49 @@ namespace Teknik.Areas.Paste
break; break;
} }
// Set the hashed password if one is provided and encrypt stuff if (!Directory.Exists(config.PasteConfig.PasteDirectory))
{
Directory.CreateDirectory(config.PasteConfig.PasteDirectory);
}
// Generate a unique file name that does not currently exist
string filePath = FileHelper.GenerateRandomFileName(config.PasteConfig.PasteDirectory, config.PasteConfig.FileExtension, 10);
string fileName = Path.GetFileName(filePath);
string key = GenerateKey(config.PasteConfig.KeySize);
string iv = GenerateIV(config.PasteConfig.BlockSize);
byte[] ivBytes = Encoding.Unicode.GetBytes(iv);
byte[] keyBytes = AesCounterManaged.CreateKey(key, ivBytes, config.PasteConfig.KeySize);
// Set the hashed password if one is provided and modify the key
if (!string.IsNullOrEmpty(password)) if (!string.IsNullOrEmpty(password))
{ {
string key = StringHelper.RandomString(config.PasteConfig.KeySize / 8); paste.HashedPassword = HashPassword(key, password);
string iv = StringHelper.RandomString(config.PasteConfig.BlockSize / 16); keyBytes = AesCounterManaged.CreateKey(password, ivBytes, config.PasteConfig.KeySize);
paste.HashedPassword = SHA384.Hash(key, password).ToHex(); }
// Encrypt Content // Encrypt Content
byte[] data = Encoding.Unicode.GetBytes(content); byte[] data = Encoding.Unicode.GetBytes(content);
byte[] ivBytes = Encoding.Unicode.GetBytes(iv); using (MemoryStream ms = new MemoryStream(data))
byte[] keyBytes = AesCounterManaged.CreateKey(password, ivBytes, config.PasteConfig.KeySize); {
byte[] encData = AesCounterManaged.Encrypt(data, keyBytes, ivBytes); AesCounterManaged.EncryptToFile(filePath, ms, config.PasteConfig.ChunkSize, keyBytes, ivBytes);
content = Convert.ToBase64String(encData); }
// Generate a deletion key
string delKey = StringHelper.RandomString(config.PasteConfig.DeleteKeyLength);
paste.Key = key; paste.Key = key;
paste.KeySize = config.PasteConfig.KeySize; paste.KeySize = config.PasteConfig.KeySize;
paste.IV = iv; paste.IV = iv;
paste.BlockSize = config.PasteConfig.BlockSize; paste.BlockSize = config.PasteConfig.BlockSize;
}
paste.Content = content; paste.FileName = fileName;
//paste.Content = content;
paste.Title = title; paste.Title = title;
paste.Syntax = syntax; paste.Syntax = syntax;
paste.Hide = hide; paste.Hide = hide;
paste.DeleteKey = delKey;
return paste; return paste;
} }
@ -92,5 +112,20 @@ namespace Teknik.Areas.Paste
return false; return false;
} }
public static string GenerateKey(int keySize)
{
return StringHelper.RandomString(keySize / 8);
}
public static string GenerateIV(int ivSize)
{
return StringHelper.RandomString(ivSize / 16);
}
public static string HashPassword(string key, string password)
{
return SHA384.Hash(key, password).ToHex();
}
} }
} }

View File

@ -64,11 +64,14 @@ namespace Teknik.Areas.Upload.Controllers
if (User.Identity.IsAuthenticated) if (User.Identity.IsAuthenticated)
{ {
maxUploadSize = _config.UploadConfig.MaxUploadSizeBasic; maxUploadSize = _config.UploadConfig.MaxUploadSizeBasic;
User user = UserHelper.GetUser(_dbContext, User.Identity.Name); if (User.Identity.IsAuthenticated)
//if (user.AccountType == AccountType.Premium) {
//{ IdentityUserInfo userInfo = await IdentityHelper.GetIdentityUserInfo(_config, User.Identity.Name);
// maxUploadSize = _config.UploadConfig.MaxUploadSizePremium; if (userInfo.AccountType == AccountType.Premium)
//} {
maxUploadSize = _config.UploadConfig.MaxUploadSizePremium;
}
}
} }
if (file.Length <= maxUploadSize) if (file.Length <= maxUploadSize)
{ {

View File

@ -42,6 +42,10 @@ namespace Teknik.Areas.Upload.Models
[CaseSensitive] [CaseSensitive]
public string DeleteKey { get; set; } public string DeleteKey { get; set; }
public DateTime? ExpireDate { get; set; }
public int MaxDownloads { get; set; }
public int Downloads { get; set; } public int Downloads { get; set; }
} }
} }

View File

@ -0,0 +1,743 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Teknik.Data;
namespace Teknik.Data.Migrations
{
[DbContext(typeof(TeknikEntities))]
[Migration("20181121074110_PasteFiles")]
partial class PasteFiles
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "2.2.0-preview3-35497")
.HasAnnotation("Relational:MaxIdentifierLength", 128)
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
modelBuilder.Entity("Teknik.Areas.Blog.Models.Blog", b =>
{
b.Property<int>("BlogId")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("UserId");
b.HasKey("BlogId");
b.HasIndex("UserId");
b.ToTable("Blogs");
});
modelBuilder.Entity("Teknik.Areas.Blog.Models.BlogPost", b =>
{
b.Property<int>("BlogPostId")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<string>("Article");
b.Property<int>("BlogId");
b.Property<DateTime>("DateEdited");
b.Property<DateTime>("DatePosted");
b.Property<DateTime>("DatePublished");
b.Property<bool>("Published");
b.Property<bool>("System");
b.Property<string>("Title");
b.HasKey("BlogPostId");
b.HasIndex("BlogId");
b.ToTable("BlogPosts");
});
modelBuilder.Entity("Teknik.Areas.Blog.Models.BlogPostComment", b =>
{
b.Property<int>("BlogPostCommentId")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<string>("Article");
b.Property<int>("BlogPostId");
b.Property<DateTime>("DateEdited");
b.Property<DateTime>("DatePosted");
b.Property<int?>("UserId");
b.HasKey("BlogPostCommentId");
b.HasIndex("BlogPostId");
b.HasIndex("UserId");
b.ToTable("BlogPostComments");
});
modelBuilder.Entity("Teknik.Areas.Blog.Models.BlogPostTag", b =>
{
b.Property<int>("BlogPostTagId")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("BlogPostId");
b.Property<string>("Description");
b.Property<string>("Name");
b.HasKey("BlogPostTagId");
b.HasIndex("BlogPostId");
b.ToTable("BlogPostTags");
});
modelBuilder.Entity("Teknik.Areas.Contact.Models.Contact", b =>
{
b.Property<int>("ContactId")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<DateTime>("DateAdded");
b.Property<string>("Email");
b.Property<string>("Message");
b.Property<string>("Name");
b.Property<string>("Subject");
b.HasKey("ContactId");
b.ToTable("Contact");
});
modelBuilder.Entity("Teknik.Areas.Paste.Models.Paste", b =>
{
b.Property<int>("PasteId")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("BlockSize");
b.Property<string>("Content");
b.Property<DateTime>("DatePosted");
b.Property<string>("DeleteKey")
.HasAnnotation("CaseSensitive", true);
b.Property<DateTime?>("ExpireDate");
b.Property<string>("FileName")
.HasAnnotation("CaseSensitive", true);
b.Property<string>("HashedPassword")
.HasAnnotation("CaseSensitive", true);
b.Property<bool>("Hide");
b.Property<string>("IV")
.HasAnnotation("CaseSensitive", true);
b.Property<string>("Key")
.HasAnnotation("CaseSensitive", true);
b.Property<int>("KeySize");
b.Property<int>("MaxViews");
b.Property<string>("Syntax");
b.Property<string>("Title");
b.Property<string>("Url")
.HasAnnotation("CaseSensitive", true);
b.Property<int?>("UserId");
b.Property<int>("Views");
b.HasKey("PasteId");
b.HasIndex("UserId");
b.ToTable("Pastes");
});
modelBuilder.Entity("Teknik.Areas.Podcast.Models.Podcast", b =>
{
b.Property<int>("PodcastId")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<DateTime>("DateEdited");
b.Property<DateTime>("DatePosted");
b.Property<DateTime>("DatePublished");
b.Property<string>("Description");
b.Property<int>("Episode");
b.Property<bool>("Published");
b.Property<string>("Title");
b.HasKey("PodcastId");
b.ToTable("Podcasts");
});
modelBuilder.Entity("Teknik.Areas.Podcast.Models.PodcastComment", b =>
{
b.Property<int>("PodcastCommentId")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<string>("Article");
b.Property<DateTime>("DateEdited");
b.Property<DateTime>("DatePosted");
b.Property<int>("PodcastId");
b.Property<int>("UserId");
b.HasKey("PodcastCommentId");
b.HasIndex("PodcastId");
b.HasIndex("UserId");
b.ToTable("PodcastComments");
});
modelBuilder.Entity("Teknik.Areas.Podcast.Models.PodcastFile", b =>
{
b.Property<int>("PodcastFileId")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<long>("ContentLength");
b.Property<string>("ContentType");
b.Property<string>("FileName");
b.Property<string>("Path");
b.Property<int>("PodcastId");
b.Property<int>("Size");
b.HasKey("PodcastFileId");
b.HasIndex("PodcastId");
b.ToTable("PodcastFiles");
});
modelBuilder.Entity("Teknik.Areas.Podcast.Models.PodcastTag", b =>
{
b.Property<int>("PodcastTagId")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<string>("Description");
b.Property<string>("Name");
b.Property<int>("PodcastId");
b.HasKey("PodcastTagId");
b.HasIndex("PodcastId");
b.ToTable("PodcastTags");
});
modelBuilder.Entity("Teknik.Areas.Shortener.Models.ShortenedUrl", b =>
{
b.Property<int>("ShortenedUrlId")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<DateTime>("DateAdded");
b.Property<string>("OriginalUrl");
b.Property<string>("ShortUrl")
.HasAnnotation("CaseSensitive", true);
b.Property<int?>("UserId");
b.Property<int>("Views");
b.HasKey("ShortenedUrlId");
b.HasIndex("UserId");
b.ToTable("ShortenedUrls");
});
modelBuilder.Entity("Teknik.Areas.Stats.Models.Takedown", b =>
{
b.Property<int>("TakedownId")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<string>("ActionTaken");
b.Property<DateTime>("DateActionTaken");
b.Property<DateTime>("DateRequested");
b.Property<string>("Reason");
b.Property<string>("Requester");
b.Property<string>("RequesterContact");
b.HasKey("TakedownId");
b.ToTable("Takedowns");
});
modelBuilder.Entity("Teknik.Areas.Stats.Models.Transaction", b =>
{
b.Property<int>("TransactionId")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<decimal>("Amount")
.HasColumnType("decimal(19, 5)");
b.Property<int>("Currency");
b.Property<DateTime>("DateSent");
b.Property<string>("Reason");
b.HasKey("TransactionId");
b.ToTable("Transactions");
});
modelBuilder.Entity("Teknik.Areas.Upload.Models.Upload", b =>
{
b.Property<int>("UploadId")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("BlockSize");
b.Property<long>("ContentLength");
b.Property<string>("ContentType");
b.Property<DateTime>("DateUploaded");
b.Property<string>("DeleteKey")
.HasAnnotation("CaseSensitive", true);
b.Property<int>("Downloads");
b.Property<DateTime?>("ExpireDate");
b.Property<string>("FileName")
.HasAnnotation("CaseSensitive", true);
b.Property<string>("IV")
.HasAnnotation("CaseSensitive", true);
b.Property<string>("Key")
.HasAnnotation("CaseSensitive", true);
b.Property<int>("KeySize");
b.Property<int>("MaxDownloads");
b.Property<int?>("Takedown_TakedownId");
b.Property<string>("Url")
.HasAnnotation("CaseSensitive", true);
b.Property<int?>("UserId");
b.HasKey("UploadId");
b.HasIndex("Takedown_TakedownId");
b.HasIndex("UserId");
b.ToTable("Uploads");
});
modelBuilder.Entity("Teknik.Areas.Users.Models.InviteCode", b =>
{
b.Property<int>("InviteCodeId")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<bool>("Active");
b.Property<int?>("ClaimedUserId");
b.Property<string>("Code")
.HasAnnotation("CaseSensitive", true);
b.Property<int?>("OwnerId");
b.HasKey("InviteCodeId");
b.HasIndex("ClaimedUserId")
.IsUnique()
.HasFilter("[ClaimedUserId] IS NOT NULL");
b.HasIndex("OwnerId");
b.ToTable("InviteCodes");
});
modelBuilder.Entity("Teknik.Areas.Users.Models.LoginInfo", b =>
{
b.Property<int>("LoginInfoId")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<string>("LoginProvider");
b.Property<string>("ProviderDisplayName");
b.Property<string>("ProviderKey");
b.Property<int>("UserId");
b.HasKey("LoginInfoId");
b.HasIndex("UserId");
b.ToTable("UserLogins");
});
modelBuilder.Entity("Teknik.Areas.Users.Models.User", b =>
{
b.Property<int>("UserId")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<string>("Username");
b.HasKey("UserId");
b.ToTable("Users");
});
modelBuilder.Entity("Teknik.Areas.Vault.Models.Vault", b =>
{
b.Property<int>("VaultId")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<DateTime>("DateCreated");
b.Property<DateTime>("DateEdited");
b.Property<string>("Description");
b.Property<string>("Title");
b.Property<string>("Url");
b.Property<int?>("UserId");
b.Property<int>("Views");
b.HasKey("VaultId");
b.HasIndex("UserId");
b.ToTable("Vaults");
});
modelBuilder.Entity("Teknik.Areas.Vault.Models.VaultItem", b =>
{
b.Property<int>("VaultItemId")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<DateTime>("DateAdded");
b.Property<string>("Description");
b.Property<string>("Discriminator")
.IsRequired();
b.Property<string>("Title");
b.Property<int>("VaultId");
b.HasKey("VaultItemId");
b.HasIndex("VaultId");
b.ToTable("VaultItems");
b.HasDiscriminator<string>("Discriminator").HasValue("VaultItem");
});
modelBuilder.Entity("Teknik.Areas.Vault.Models.PasteVaultItem", b =>
{
b.HasBaseType("Teknik.Areas.Vault.Models.VaultItem");
b.Property<int>("PasteId");
b.HasIndex("PasteId");
b.HasDiscriminator().HasValue("PasteVaultItem");
});
modelBuilder.Entity("Teknik.Areas.Vault.Models.UploadVaultItem", b =>
{
b.HasBaseType("Teknik.Areas.Vault.Models.VaultItem");
b.Property<int>("UploadId");
b.HasIndex("UploadId");
b.HasDiscriminator().HasValue("UploadVaultItem");
});
modelBuilder.Entity("Teknik.Areas.Blog.Models.Blog", b =>
{
b.HasOne("Teknik.Areas.Users.Models.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Teknik.Areas.Blog.Models.BlogPost", b =>
{
b.HasOne("Teknik.Areas.Blog.Models.Blog", "Blog")
.WithMany("BlogPosts")
.HasForeignKey("BlogId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Teknik.Areas.Blog.Models.BlogPostComment", b =>
{
b.HasOne("Teknik.Areas.Blog.Models.BlogPost", "BlogPost")
.WithMany("Comments")
.HasForeignKey("BlogPostId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("Teknik.Areas.Users.Models.User", "User")
.WithMany()
.HasForeignKey("UserId");
});
modelBuilder.Entity("Teknik.Areas.Blog.Models.BlogPostTag", b =>
{
b.HasOne("Teknik.Areas.Blog.Models.BlogPost", "BlogPost")
.WithMany("Tags")
.HasForeignKey("BlogPostId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Teknik.Areas.Paste.Models.Paste", b =>
{
b.HasOne("Teknik.Areas.Users.Models.User", "User")
.WithMany("Pastes")
.HasForeignKey("UserId");
});
modelBuilder.Entity("Teknik.Areas.Podcast.Models.PodcastComment", b =>
{
b.HasOne("Teknik.Areas.Podcast.Models.Podcast", "Podcast")
.WithMany("Comments")
.HasForeignKey("PodcastId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("Teknik.Areas.Users.Models.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Teknik.Areas.Podcast.Models.PodcastFile", b =>
{
b.HasOne("Teknik.Areas.Podcast.Models.Podcast", "Podcast")
.WithMany("Files")
.HasForeignKey("PodcastId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Teknik.Areas.Podcast.Models.PodcastTag", b =>
{
b.HasOne("Teknik.Areas.Podcast.Models.Podcast", "Podcast")
.WithMany("Tags")
.HasForeignKey("PodcastId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Teknik.Areas.Shortener.Models.ShortenedUrl", b =>
{
b.HasOne("Teknik.Areas.Users.Models.User", "User")
.WithMany("ShortenedUrls")
.HasForeignKey("UserId");
});
modelBuilder.Entity("Teknik.Areas.Upload.Models.Upload", b =>
{
b.HasOne("Teknik.Areas.Stats.Models.Takedown")
.WithMany("Attachments")
.HasForeignKey("Takedown_TakedownId");
b.HasOne("Teknik.Areas.Users.Models.User", "User")
.WithMany("Uploads")
.HasForeignKey("UserId");
});
modelBuilder.Entity("Teknik.Areas.Users.Models.InviteCode", b =>
{
b.HasOne("Teknik.Areas.Users.Models.User", "ClaimedUser")
.WithOne("ClaimedInviteCode")
.HasForeignKey("Teknik.Areas.Users.Models.InviteCode", "ClaimedUserId");
b.HasOne("Teknik.Areas.Users.Models.User", "Owner")
.WithMany("OwnedInviteCodes")
.HasForeignKey("OwnerId");
});
modelBuilder.Entity("Teknik.Areas.Users.Models.LoginInfo", b =>
{
b.HasOne("Teknik.Areas.Users.Models.User", "User")
.WithMany("Logins")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Teknik.Areas.Users.Models.User", b =>
{
b.OwnsOne("Teknik.Areas.Users.Models.BlogSettings", "BlogSettings", b1 =>
{
b1.Property<int>("UserId")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b1.Property<string>("Description")
.HasColumnName("Description");
b1.Property<string>("Title")
.HasColumnName("Title");
b1.HasKey("UserId");
b1.ToTable("Users");
b1.HasOne("Teknik.Areas.Users.Models.User")
.WithOne("BlogSettings")
.HasForeignKey("Teknik.Areas.Users.Models.BlogSettings", "UserId")
.OnDelete(DeleteBehavior.Cascade);
});
b.OwnsOne("Teknik.Areas.Users.Models.UploadSettings", "UploadSettings", b1 =>
{
b1.Property<int>("UserId")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b1.Property<bool>("Encrypt")
.HasColumnName("Encrypt");
b1.HasKey("UserId");
b1.ToTable("Users");
b1.HasOne("Teknik.Areas.Users.Models.User")
.WithOne("UploadSettings")
.HasForeignKey("Teknik.Areas.Users.Models.UploadSettings", "UserId")
.OnDelete(DeleteBehavior.Cascade);
});
b.OwnsOne("Teknik.Areas.Users.Models.UserSettings", "UserSettings", b1 =>
{
b1.Property<int>("UserId")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b1.Property<string>("About")
.HasColumnName("About");
b1.Property<string>("Quote")
.HasColumnName("Quote");
b1.Property<string>("Website")
.HasColumnName("Website");
b1.HasKey("UserId");
b1.ToTable("Users");
b1.HasOne("Teknik.Areas.Users.Models.User")
.WithOne("UserSettings")
.HasForeignKey("Teknik.Areas.Users.Models.UserSettings", "UserId")
.OnDelete(DeleteBehavior.Cascade);
});
});
modelBuilder.Entity("Teknik.Areas.Vault.Models.Vault", b =>
{
b.HasOne("Teknik.Areas.Users.Models.User", "User")
.WithMany("Vaults")
.HasForeignKey("UserId");
});
modelBuilder.Entity("Teknik.Areas.Vault.Models.VaultItem", b =>
{
b.HasOne("Teknik.Areas.Vault.Models.Vault", "Vault")
.WithMany("VaultItems")
.HasForeignKey("VaultId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Teknik.Areas.Vault.Models.PasteVaultItem", b =>
{
b.HasOne("Teknik.Areas.Paste.Models.Paste", "Paste")
.WithMany("PasteVaultItems")
.HasForeignKey("PasteId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Teknik.Areas.Vault.Models.UploadVaultItem", b =>
{
b.HasOne("Teknik.Areas.Upload.Models.Upload", "Upload")
.WithMany("UploadVaultItems")
.HasForeignKey("UploadId")
.OnDelete(DeleteBehavior.Cascade);
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,51 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace Teknik.Data.Migrations
{
public partial class PasteFiles : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<DateTime>(
name: "ExpireDate",
table: "Uploads",
nullable: true);
migrationBuilder.AddColumn<int>(
name: "MaxDownloads",
table: "Uploads",
nullable: false,
defaultValue: 0);
migrationBuilder.AddColumn<string>(
name: "DeleteKey",
table: "Pastes",
nullable: true);
migrationBuilder.AddColumn<string>(
name: "FileName",
table: "Pastes",
nullable: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "ExpireDate",
table: "Uploads");
migrationBuilder.DropColumn(
name: "MaxDownloads",
table: "Uploads");
migrationBuilder.DropColumn(
name: "DeleteKey",
table: "Pastes");
migrationBuilder.DropColumn(
name: "FileName",
table: "Pastes");
}
}
}

View File

@ -15,7 +15,7 @@ namespace Teknik.Data.Migrations
{ {
#pragma warning disable 612, 618 #pragma warning disable 612, 618
modelBuilder modelBuilder
.HasAnnotation("ProductVersion", "2.2.0-preview2-35157") .HasAnnotation("ProductVersion", "2.2.0-preview3-35497")
.HasAnnotation("Relational:MaxIdentifierLength", 128) .HasAnnotation("Relational:MaxIdentifierLength", 128)
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
@ -140,8 +140,14 @@ namespace Teknik.Data.Migrations
b.Property<DateTime>("DatePosted"); b.Property<DateTime>("DatePosted");
b.Property<string>("DeleteKey")
.HasAnnotation("CaseSensitive", true);
b.Property<DateTime?>("ExpireDate"); b.Property<DateTime?>("ExpireDate");
b.Property<string>("FileName")
.HasAnnotation("CaseSensitive", true);
b.Property<string>("HashedPassword") b.Property<string>("HashedPassword")
.HasAnnotation("CaseSensitive", true); .HasAnnotation("CaseSensitive", true);
@ -355,6 +361,8 @@ namespace Teknik.Data.Migrations
b.Property<int>("Downloads"); b.Property<int>("Downloads");
b.Property<DateTime?>("ExpireDate");
b.Property<string>("FileName") b.Property<string>("FileName")
.HasAnnotation("CaseSensitive", true); .HasAnnotation("CaseSensitive", true);
@ -366,6 +374,8 @@ namespace Teknik.Data.Migrations
b.Property<int>("KeySize"); b.Property<int>("KeySize");
b.Property<int>("MaxDownloads");
b.Property<int?>("Takedown_TakedownId"); b.Property<int?>("Takedown_TakedownId");
b.Property<string>("Url") b.Property<string>("Url")