public async Task <ActionResult <Thread> > CreatePost([FromBody] Thread newpost) { newpost.Id = 0; if (string.IsNullOrEmpty(newpost.Text)) { return(BadRequest("Text body is too short")); } if (newpost.IsCommentReply && newpost.ParentId == -1) { return(BadRequest("Expected a comment, got a parent")); } if (string.IsNullOrEmpty(newpost.Username)) { newpost.Username = "******"; } var passw = newpost.GeneratePassword; int passid = -1; if (!string.IsNullOrWhiteSpace(passw)) { (var hash, var salt) = Passworder.GenerateHash(passw, this.Config.SiteConfig.DefaultPassword); var newpass = new Password() { Hash = hash, Salt = salt }; this.Database.Passwords.Add(newpass); this.Database.SaveChanges(); passid = newpass.Id; } newpost.GeneratePassword = ""; newpost.PasswordId = passid; await this.Database.Threads.AddAsync(newpost); await this.Database.SaveChangesAsync(); //Run in background await Task.Run(async() => await Webhooker.SendContentToAllAsync(this.Database, newpost)); return(newpost); }
public ActionResult <bool> DeletePost([FromQuery] int postid = -1, [FromQuery] string pass = "") { var thread = this.Database.Threads.FirstOrDefault(x => x.Id == postid); if (thread != null) { var passwd = this.Database.Passwords.FirstOrDefault(x => x.Id == thread.PasswordId); if (passwd != null) { var passcorrect = Passworder.VerifyPassword(pass, passwd.Hash, passwd.Salt, this.Config.SiteConfig.DefaultPassword); if (passcorrect) { this.Database.Threads.Remove(thread); this.Database.SaveChanges(); return(Ok()); } } // failed, trying with master password var mpasswd = this.Database.Passwords.First(x => x.Id == -1); var mpasscorrect = Passworder.VerifyPassword(pass, mpasswd.Hash, mpasswd.Salt, this.Config.SiteConfig.DefaultPassword); if (mpasscorrect) { this.Database.Threads.Remove(thread); this.Database.SaveChanges(); return(Ok()); } return(BadRequest($"Received wrong password: {pass}")); } else { return(NotFound($"Thread with the ID '{postid}' was not found")); } }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { #region AspNetCoreRateLimit Stuff //Taken from https://github.com/stefanprodan/AspNetCoreRateLimit/wiki/IpRateLimitMiddleware#setup services.AddOptions(); services.AddMemoryCache(); services.Configure <IpRateLimitOptions>(Configuration.GetSection("IpRateLimiting")); services.Configure <IpRateLimitPolicies>(Configuration.GetSection("IpRateLimitPolicies")); services.AddSingleton <IIpPolicyStore, MemoryCacheIpPolicyStore>(); services.AddSingleton <IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>(); services.AddSingleton <IHttpContextAccessor, HttpContextAccessor>(); services.AddSingleton <IRateLimitConfiguration, RateLimitConfiguration>(); #endregion #region General Chandler Stuff services.AddSwaggerGen(x => { x.SwaggerDoc("v1", new OpenApiInfo() { Title = "CHANdler API Documentation", Version = "v1", License = new OpenApiLicense() { Name = "GNU General Public License v3.0", Url = new Uri("https://github.com/Naamloos/CHANdler/blob/master/LICENSE") }, }); x.IncludeXmlComments($"{AppContext.BaseDirectory}/{Assembly.GetExecutingAssembly().GetName().Name}.xml"); }); services.AddSingleton(_db); services.AddSingleton(_meta); services.AddSingleton(_config); services.AddCors(o => o.AddPolicy("publicpolicy", builder => { builder.AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader(); })); this._db.Database.EnsureCreated(); if (this._db.Boards.Count() == 0) { // insert debug thread data to database this._db.Boards.Add(new Board() { Name = "CHANdler", Tag = "c", Description = "CHANdler test board", ImageUrl = "/res/logo.jpg" }); this._db.Boards.Add(new Board() { Name = "Random", Tag = "r", Description = "Random shit", }); this._db.Boards.Add(new Board() { Name = "Memes", Tag = "m", ImageUrl = "/res/pepo.gif", Description = "haha cool and good dank memes", }); this._db.Boards.Add(new Board() { Name = "Meta", Tag = "meta", ImageUrl = "/res/wrench.png", Description = "About CHANdler itself, e.g. development talk.", }); (var hash, var salt) = Passworder.GenerateHash(this._config.SiteConfig.DefaultPassword, this._config.SiteConfig.DefaultPassword); this._db.Passwords.Add(new Password() { Id = -1, Hash = hash, Salt = salt }); this._db.SaveChanges(); } #region Auth and Forgery services.AddIdentity <ChandlerUser, IdentityRole>(x => { x.Password.RequiredLength = 8; x.Password.RequiredUniqueChars = 0; x.Password.RequireDigit = false; x.Password.RequireLowercase = false; x.Password.RequireNonAlphanumeric = false; x.Password.RequireUppercase = false; x.User.RequireUniqueEmail = true; x.Lockout.AllowedForNewUsers = true; x.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(15); x.Lockout.MaxFailedAccessAttempts = 5; x.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@_-+=?/!\\ "; }).AddEntityFrameworkStores <Database>() .AddDefaultTokenProviders() .AddUserManager <UserManager <ChandlerUser> >() .AddSignInManager <SignInManager <ChandlerUser> >(); if (this._config.DiscordOAuthSettings != null) { var clientid = this._config.DiscordOAuthSettings.ClientId.ToString(); var clientsecret = this._config.DiscordOAuthSettings.ClientSecret; using var crng = new RNGCryptoServiceProvider(); var arr = new byte[15]; crng.GetBytes(arr); var nonce = Convert.ToBase64String(arr); services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddDiscord(x => { x.SignInScheme = "Identity.External"; x.ClaimsIssuer = DiscordAuthenticationDefaults.Issuer; x.ReturnUrlParameter = "/"; x.AccessDeniedPath = "/"; x.ClientId = clientid; x.ClientSecret = clientsecret; x.TokenEndpoint = DiscordAuthenticationDefaults.TokenEndpoint; x.AuthorizationEndpoint = $"{DiscordAuthenticationDefaults.AuthorizationEndpoint}?response_type=code&client_id={clientid}&scope=identify&state={nonce}&redirect_uri={this._config.DiscordOAuthSettings.RedirectUri}"; x.UserInformationEndpoint = DiscordAuthenticationDefaults.UserInformationEndpoint; }); } else { services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme); } services.ConfigureApplicationCookie(x => { x.LoginPath = "/login"; x.LogoutPath = "/logout"; x.AccessDeniedPath = "/"; x.ExpireTimeSpan = TimeSpan.FromDays(1); x.SlidingExpiration = true; }); services.AddAntiforgery(x => { x.FormFieldName = "AntiForgeryToken"; x.HeaderName = "X-CRSF-TOKEN"; }); #endregion services.AddMvc(x => x.EnableEndpointRouting = false) .SetCompatibilityVersion(CompatibilityVersion.Version_3_0) .AddControllersAsServices(); services.AddTransient <AccountHelper>(); services.AddSingleton(new DbActionHelper(this._db)); #endregion }