Browse Source

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

tags/3.0.0^2
Teknikode 1 year ago
parent
commit
0f7c912390

+ 15
- 2
Configuration/PasteConfig.cs 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";
}
}

+ 19
- 22
Teknik/Areas/Paste/Controllers/PasteController.cs 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);
}

+ 6
- 0
Teknik/Areas/Paste/Models/Paste.cs 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; }

+ 52
- 17
Teknik/Areas/Paste/PasteHelper.cs 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 (!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))
{
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;
paste.HashedPassword = HashPassword(key, password);
keyBytes = AesCounterManaged.CreateKey(password, ivBytes, config.PasteConfig.KeySize);
}

paste.Content = content;
// 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();
}
}
}

+ 8
- 5
Teknik/Areas/Upload/Controllers/UploadController.cs 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)
{

+ 4
- 0
Teknik/Areas/Upload/Models/Upload.cs 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; }
}
}

+ 743
- 0
Teknik/Data/Migrations/20181121074110_PasteFiles.Designer.cs 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
}
}
}

+ 51
- 0
Teknik/Data/Migrations/20181121074110_PasteFiles.cs 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");
}
}
}

+ 11
- 1
Teknik/Data/Migrations/TeknikEntitiesModelSnapshot.cs 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")

Loading…
Cancel
Save