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 bool Enabled { 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 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()
{
Enabled = true;
UrlLength = 5;
DeleteKeyLength = 24;
KeySize = 256;
BlockSize = 128;
ChunkSize = 1040;
PasteDirectory = Directory.GetCurrentDirectory();
FileExtension = "enc";
SyntaxVisualStyle = "vs";
}
}

View File

@ -18,6 +18,8 @@ using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Http;
using Teknik.Logging;
using System.IO;
using System.Threading.Tasks;
namespace Teknik.Areas.Paste.Controllers
{
@ -37,7 +39,7 @@ namespace Teknik.Areas.Paste.Controllers
}
[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();
if (paste != null)
@ -59,13 +61,10 @@ namespace Teknik.Areas.Paste.Controllers
PasteViewModel model = new PasteViewModel();
model.Url = url;
model.Content = paste.Content;
model.Title = paste.Title;
model.Syntax = paste.Syntax;
model.DatePosted = paste.DatePosted;
byte[] data = Encoding.UTF8.GetBytes(paste.Content);
if (User.Identity.IsAuthenticated && type.ToLower() == "full")
{
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
if (!string.IsNullOrEmpty(paste.HashedPassword))
{
string hash = string.Empty;
if (!string.IsNullOrEmpty(password))
{
byte[] passBytes = SHA384.Hash(paste.Key, password);
hash = passBytes.ToHex();
// 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();
//}
hash = PasteHelper.HashPassword(paste.Key, password);
keyBytes = AesCounterManaged.CreateKey(password, ivBytes, paste.KeySize);
}
if (string.IsNullOrEmpty(password) || hash != paste.HashedPassword)
{
@ -108,13 +101,16 @@ namespace Teknik.Areas.Paste.Controllers
// Redirect them to the password request page
return View("~/Areas/Paste/Views/Paste/PasswordNeeded.cshtml", passModel);
}
}
data = Convert.FromBase64String(paste.Content);
// Now we decrypt the content
byte[] ivBytes = Encoding.Unicode.GetBytes(paste.IV);
byte[] keyBytes = AesCounterManaged.CreateKey(password, ivBytes, paste.KeySize);
data = AesCounterManaged.Decrypt(data, keyBytes, ivBytes);
model.Content = Encoding.Unicode.GetString(data);
// Read in the file
string subDir = paste.FileName[0].ToString();
string filePath = Path.Combine(_config.PasteConfig.PasteDirectory, subDir, paste.FileName);
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
using (AesCounterStream cs = new AesCounterStream(fs, false, keyBytes, ivBytes))
using (StreamReader sr = new StreamReader(cs, Encoding.Unicode))
{
model.Content = await sr.ReadToEndAsync();
}
switch (type.ToLower())
@ -135,7 +131,8 @@ namespace Teknik.Areas.Paste.Controllers
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:
return View("~/Areas/Paste/Views/Paste/Full.cshtml", model);
}

View File

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

View File

@ -8,6 +8,7 @@ using Teknik.Utilities;
using Teknik.Models;
using Teknik.Utilities.Cryptography;
using Teknik.Data;
using System.IO;
namespace Teknik.Areas.Paste
{
@ -55,30 +56,49 @@ namespace Teknik.Areas.Paste
break;
}
// Set the hashed password if one is provided and encrypt stuff
if (!string.IsNullOrEmpty(password))
if (!Directory.Exists(config.PasteConfig.PasteDirectory))
{
string key = StringHelper.RandomString(config.PasteConfig.KeySize / 8);
string iv = StringHelper.RandomString(config.PasteConfig.BlockSize / 16);
paste.HashedPassword = SHA384.Hash(key, password).ToHex();
// Encrypt Content
byte[] data = Encoding.Unicode.GetBytes(content);
byte[] ivBytes = Encoding.Unicode.GetBytes(iv);
byte[] keyBytes = AesCounterManaged.CreateKey(password, ivBytes, config.PasteConfig.KeySize);
byte[] encData = AesCounterManaged.Encrypt(data, keyBytes, ivBytes);
content = Convert.ToBase64String(encData);
paste.Key = key;
paste.KeySize = config.PasteConfig.KeySize;
paste.IV = iv;
paste.BlockSize = config.PasteConfig.BlockSize;
Directory.CreateDirectory(config.PasteConfig.PasteDirectory);
}
paste.Content = content;
// 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))
{
paste.HashedPassword = HashPassword(key, password);
keyBytes = AesCounterManaged.CreateKey(password, ivBytes, config.PasteConfig.KeySize);
}
// Encrypt Content
byte[] data = Encoding.Unicode.GetBytes(content);
using (MemoryStream ms = new MemoryStream(data))
{
AesCounterManaged.EncryptToFile(filePath, ms, config.PasteConfig.ChunkSize, keyBytes, ivBytes);
}
// Generate a deletion key
string delKey = StringHelper.RandomString(config.PasteConfig.DeleteKeyLength);
paste.Key = key;
paste.KeySize = config.PasteConfig.KeySize;
paste.IV = iv;
paste.BlockSize = config.PasteConfig.BlockSize;
paste.FileName = fileName;
//paste.Content = content;
paste.Title = title;
paste.Syntax = syntax;
paste.Hide = hide;
paste.DeleteKey = delKey;
return paste;
}
@ -92,5 +112,20 @@ namespace Teknik.Areas.Paste
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)
{
maxUploadSize = _config.UploadConfig.MaxUploadSizeBasic;
User user = UserHelper.GetUser(_dbContext, User.Identity.Name);
//if (user.AccountType == AccountType.Premium)
//{
// maxUploadSize = _config.UploadConfig.MaxUploadSizePremium;
//}
if (User.Identity.IsAuthenticated)
{
IdentityUserInfo userInfo = await IdentityHelper.GetIdentityUserInfo(_config, User.Identity.Name);
if (userInfo.AccountType == AccountType.Premium)
{
maxUploadSize = _config.UploadConfig.MaxUploadSizePremium;
}
}
}
if (file.Length <= maxUploadSize)
{

View File

@ -42,6 +42,10 @@ namespace Teknik.Areas.Upload.Models
[CaseSensitive]
public string DeleteKey { get; set; }
public DateTime? ExpireDate { get; set; }
public int MaxDownloads { 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
modelBuilder
.HasAnnotation("ProductVersion", "2.2.0-preview2-35157")
.HasAnnotation("ProductVersion", "2.2.0-preview3-35497")
.HasAnnotation("Relational:MaxIdentifierLength", 128)
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
@ -140,8 +140,14 @@ namespace Teknik.Data.Migrations
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);
@ -355,6 +361,8 @@ namespace Teknik.Data.Migrations
b.Property<int>("Downloads");
b.Property<DateTime?>("ExpireDate");
b.Property<string>("FileName")
.HasAnnotation("CaseSensitive", true);
@ -366,6 +374,8 @@ namespace Teknik.Data.Migrations
b.Property<int>("KeySize");
b.Property<int>("MaxDownloads");
b.Property<int?>("Takedown_TakedownId");
b.Property<string>("Url")