Skip to content
This repository has been archived by the owner on May 11, 2023. It is now read-only.

Commit

Permalink
Week 2 (#5)
Browse files Browse the repository at this point in the history
* Lesson one work

* Initial commit for assignment security

* Worked on lesson 1 and a little on 2

* work on readme and made folder for main project

* Update README.md

Added table with requirements

* Moved files around

* Added developer page to Overkoepelend

* Improved developer page

* Databinding work and GDPR assignment

* Finished GDPR assignment

* Initial GDPR form added to Overkoepelend

* Week 2 added to ClientTech

* Update README.md

* GDPR now working alongside viewcounter. Missing only a few things now for week one client

* Removed unused functions and parameters from HomeController

* Starting work on developer page binding

* Lesson 2 ServerTech in class work

* Databinding done

* Changed gitignore

* Start work on contact page

* Required forms contact

* Work on updating readme and lesson assignment

* push readme for real this time

* made readme nicer and fixed one table

* Update README.md

* Work on class assignment

* Added back in

* Work on the fucking API

* POST finally posts

* Google API now gets a good response

* Work on finishing rest of the requirements

* Captcha function now properly checks

* Database connection working

* Lesson works + email sending now works

* Updates to page: loading bar, more verifications, prevent xss.

Moved keys to secret.json so can commit more frequently again

* Improved handling of errors and sending data to form. Form is pretty much finished

* Summaries and code improvements

* Using migrations on database now

* nosniff security

* Fix merge
  • Loading branch information
Labhatorian committed Feb 19, 2023
1 parent 54d6682 commit 45bef36
Show file tree
Hide file tree
Showing 63 changed files with 1,652 additions and 79 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ <h1>Contact</h1>

<div class="form-contactpagina__inputelement fx-col">
<label for="email">Email: </label>
<input type="email" name="email" id="email">
<input type="email" name="email" id="email" required minlength="8">
</div>

<div class="form-contactpagina__inputelement">
Expand All @@ -49,6 +49,14 @@ <h1>Contact</h1>

/*student uitwerking*/

<div class="form-contactpagina__inputelement fx-col">
<label for="number">Nummer: </label>
<input type="tel" name="number" id="number" required>
</div>

<div class="form-contactpagina__inputelement">
<input type="reset" value="Reset!">
</div>

</form>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
<span>Emailadres:</span>
<input type="email" name="email" id="email" required minlength="8">
<span class="error" aria-live="polite"></span>

<span>Naam:</span>
<input type="text" name="naam" id="naam" required>
<span class="error" aria-live="polite"></span>
</label>

<input type="submit" value="Verstuur!">
Expand Down
31 changes: 18 additions & 13 deletions ClientTech/week-2/les-1/form-versturen/studentversie/scripts/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,20 @@ const form = document.querySelector("form");
const email = document.getElementById("email");
const emailError = document.querySelector("#email + span.error");

email.addEventListener("input", (event) => {
// Each time the user types something, we check if the
// form fields are valid.
// email.addEventListener("input", (event) => {
// // Each time the user types something, we check if the
// // form fields are valid.

if (email.validity.valid) {
// In case there is an error message visible, if the field
// is valid, we remove the error message.
emailError.textContent = ""; // Reset the content of the message
emailError.className = "error"; // Reset the visual state of the message
} else {
// If there is still an error, show the correct error
showError();
}
});
// if (email.validity.valid) {
// // In case there is an error message visible, if the field
// // is valid, we remove the error message.
// emailError.textContent = ""; // Reset the content of the message
// emailError.className = "error"; // Reset the visual state of the message
// } else {
// // If there is still an error, show the correct error
// showError();
// }
// });

form.addEventListener("submit", (event) => {
// if the email field is valid, we let the form submit
Expand All @@ -24,6 +24,11 @@ form.addEventListener("submit", (event) => {
showError();
// Then we prevent the form from being sent by canceling the event
event.preventDefault();
} else {
// In case there is an error message visible, if the field
// is valid, we remove the error message.
emailError.textContent = ""; // Reset the content of the message
emailError.className = "error"; // Reset the visual state of the message
}

});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ app.post('/form', (req, res) => {

let naam = req.body.naam;
let email = req.body.email;
let pattern = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;

if(naam == null && email == null && email.match(pattern)){
res.send("VALIDATION ERROR!");
}

res.json({naam: naam, email: email});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@
requestPromises.push(fetch('http://localhost:3000/random'));
}

const responses = //Promises.all
const responses = await Promise.all(requestPromises);

//student uitwerking

let sum = 0;
for(const response of responses) {

const json = await response.json();
sum += json.random;
//student uitwerking

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.4.33103.184
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Setup", "Setup\Setup.csproj", "{AAF1C2AF-CF5C-41B9-BBF2-70C99FC1F68F}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Setup", "Setup\Setup.csproj", "{AAF1C2AF-CF5C-41B9-BBF2-70C99FC1F68F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down
115 changes: 115 additions & 0 deletions Overkoepelend/Setup/Setup/Controllers/DevContactController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
using Ganss.Xss;
using Mailjet.Client;
using Mailjet.Client.TransactionalEmails;
using Microsoft.AspNetCore.Mvc;
using Setup.Models;
using Setup.Models.DeveloperModels;

namespace Setup.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class DevContactController : ControllerBase
{
private readonly IConfiguration Configuration;
private readonly EmailContext db;

private readonly string GoogleCaptchaUrl = "https://www.google.com/recaptcha/api/siteverify";

private bool AcceptCaptcha = false;
private bool AcceptEmail = false;

/// <summary>
/// Constructor that gets <see cref="EmailContext"/> and <paramref name="configuration"/>.
/// </summary>
/// <param name="db"></param>
/// <param name="configuration"></param>
public DevContactController(EmailContext db, IConfiguration configuration)
{
this.db = db;
Configuration = configuration;
}

/// <summary>
/// When /api/DevContact/Contact gets posted, cast body data to <see cref="Email"/>
/// </summary>
/// <param name="email"></param>
/// <returns></returns>
[HttpPost("Contact")]
public IActionResult ContactDeveloper([FromBody] Email email)
{
if (email is null) return BadRequest();

//Prevent XSS
var sanitizer = new HtmlSanitizer();
if(email.Message is not null) email.Message = sanitizer.Sanitize(email.Message);
if (email.Subject is not null) email.Subject = sanitizer.Sanitize(email.Subject);

if (email.Response is not null)
{
Task captchatask = VerifyCaptcha(email.Response);
captchatask.Wait();
}

if (!AcceptCaptcha) return StatusCode(403, 0);

db.Add(email);
db.SaveChanges();

SendEmail(email).Wait();

if (!AcceptEmail) return StatusCode(403, 1);

return Ok("{\"Email\": \"" + email.EmailAddress + "\", \"Subject\": \"" + email.Subject + "\", \"Message\": \"" + email.Message + "\"}");
}

/// <summary>
/// Captcha will be done server side for better security
/// Verifies captcha from Google
/// </summary>
/// <param name="ResponseUser"></param>
/// <returns></returns>
private async Task VerifyCaptcha(string ResponseUser)
{
AcceptCaptcha = false;

using HttpClient client = new();
var req = new HttpRequestMessage(HttpMethod.Post, GoogleCaptchaUrl);
req.Headers.Add("Accept", "application/x-www-form-urlencoded");

req.Content = new FormUrlEncodedContent(new Dictionary<string, string>
{
{ "secret", Configuration["SecretKeys:CaptchaSecret"] },
{ "response", ResponseUser }
});

HttpResponseMessage resp = await client.SendAsync(req);
AcceptCaptcha = (bool)resp.IsSuccessStatusCode;
}

/// <summary>
/// Sends email with <see cref="MailjetClient"/>
/// </summary>
/// <param name="email"></param>
/// <returns></returns>
private async Task SendEmail(Email email)
{
AcceptEmail = false;

MailjetClient client = new(Configuration["PublicKeys:MailJetPublicKey"], Configuration["SecretKeys:MailJetSecret"]);

// construct your email with builder
var emailtosend = new TransactionalEmailBuilder()
.WithFrom(new SendContact("s1168716@student.windesheim.nl"))
.WithSubject(email.Subject)
.WithHtmlPart(email.Message + "<br><br>" + "Dit email is afkomstig van: " + email.EmailAddress)
.WithTo(new SendContact("s1168716@student.windesheim.nl"))
.Build();

// invoke API to send email
var response = await client.SendTransactionalEmailAsync(emailtosend);

AcceptEmail = response.Messages[0].Errors is null;
}
}
}
41 changes: 39 additions & 2 deletions Overkoepelend/Setup/Setup/Controllers/HomeController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,47 +6,84 @@ namespace Setup.Controllers
{
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;

public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}

private const string PageViews = "PageViews";
private DeveloperViewModel developer = new();
private readonly DeveloperViewModel developer = new();

/// <summary>
/// Main page, the index
/// </summary>
/// <returns></returns>
public IActionResult Index()
{
UpdatePageViewCookie();
return View();
}

/// <summary>
/// Privacy page but is empty for now
/// </summary>
/// <returns></returns>
public IActionResult Privacy()
{
UpdatePageViewCookie();
return View();
}

/// <summary>
/// Developer profile page
/// </summary>
/// <returns></returns>
public IActionResult Developer()
{
UpdatePageViewCookie();
return View(developer);
}

/// <summary>
/// Contact page
/// </summary>
/// <returns></returns>
public IActionResult Contact()
{
UpdatePageViewCookie();
return View(developer);
}

/// <summary>
/// Error page
/// </summary>
/// <returns></returns>
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
UpdatePageViewCookie();
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}

//TOdo dont do this when cookie not accepted
/// <summary>
/// Updates pageview cookie and checks for GDPR
/// </summary>
public void UpdatePageViewCookie()
{
var currentCookieValue = Request.Cookies[PageViews];
var acceptedGDRP = Request.Cookies["gdpr"];

if (acceptedGDRP is null || !acceptedGDRP.Equals("accept"))
{
//Delete cookie if it exists and return
Response.Cookies.Delete(PageViews);
return;
}
if (currentCookieValue == null)
{

Response.Cookies.Append(PageViews, "1");
}
else
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 45bef36

Please sign in to comment.