Skip to content

Commit

Permalink
Merge pull request #43 from devdanielsun/developer
Browse files Browse the repository at this point in the history
Developer
  • Loading branch information
devdanielsun authored Feb 11, 2024
2 parents 8a0c861 + 2df595a commit e13462f
Show file tree
Hide file tree
Showing 43 changed files with 1,393 additions and 173 deletions.
16 changes: 8 additions & 8 deletions database/migration.sql
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ CREATE TABLE [dbo].[users](
[first_name] [nvarchar](64) NULL,
[last_name] [nvarchar](64) NULL,
[role] [nvarchar](32) NULL DEFAULT 'Basic',
[created_at] [datetime] NOT NULL,
[created_at] [datetime2](7) NOT NULL,
CONSTRAINT PK_users PRIMARY KEY NONCLUSTERED (id),
CONSTRAINT UC_Users UNIQUE (id,emailaddress,username)
) ON [PRIMARY]
Expand All @@ -29,8 +29,8 @@ CREATE TABLE [dbo].[polls](
[id] [int] IDENTITY(1,1) NOT NULL,
[user_id] [int] NOT NULL,
[question] [nvarchar](512) NOT NULL,
[ending_date] [datetime] NOT NULL,
[created_at] [datetime] NOT NULL,
[ending_date] [datetime2](7) NOT NULL,
[created_at] [datetime2](7) NOT NULL,
CONSTRAINT PK_polls PRIMARY KEY NONCLUSTERED (id),
CONSTRAINT FK_poll_user FOREIGN KEY (user_id)
REFERENCES users (id)
Expand All @@ -45,7 +45,7 @@ CREATE TABLE [dbo].[answers](
[id] [int] IDENTITY(1,1) NOT NULL,
[poll_id] [int] NOT NULL,
[poll_answer] [nvarchar](256) NOT NULL,
[created_at] [datetime] NOT NULL,
[created_at] [datetime2](7) NOT NULL,
CONSTRAINT PK_answers PRIMARY KEY NONCLUSTERED (id),
CONSTRAINT FK_answer_poll FOREIGN KEY (poll_id)
REFERENCES polls (id)
Expand All @@ -57,11 +57,11 @@ GO
CREATE TABLE [dbo].[votes](
[id] [int] IDENTITY(1,1) NOT NULL,
[answer_id] [int] NOT NULL,
[ipv4_address] [varbinary](4) NULL,
[ipv6_address] [varbinary](16) NULL,
[ipv4_address] [varchar](15) NULL,
[ipv6_address] [varchar](45) NULL,
[mac_address] [char](12) NULL,
[voted_at] [datetime] NOT NULL,
[created_at] [datetime] NOT NULL,
[voted_at] [datetime2](7) NOT NULL,
[created_at] [datetime2](7) NOT NULL,
CONSTRAINT PK_votes PRIMARY KEY NONCLUSTERED (id),
CONSTRAINT FK_vote_answer FOREIGN KEY (answer_id)
REFERENCES answers (id)
Expand Down
88 changes: 49 additions & 39 deletions pollor.Server/Controllers/AuthController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,27 +37,28 @@ public IActionResult Register([FromBody] RegisterModel registerUser)
return BadRequest(new { message = "Password must be longer than 8 characters." });
}

bool isUsernameAvailable = new PollorDbContext().UserAuthModel.Where(u => u.username!.ToLower().Equals(registerUser.username!.ToLower())).IsNullOrEmpty();
if (isUsernameAvailable == false) {
return BadRequest(new { message = "Username is already taken, please login or use another username." });
}
try
{

bool isEmailAvailable = new PollorDbContext().UserAuthModel.Where(u => u.emailaddress!.ToLower().Equals(registerUser.emailaddress!.ToLower())).IsNullOrEmpty();
if (isEmailAvailable == false) {
return BadRequest(new { message = "Emailaddress is already taken, please login or use another emailaddress." });
}
bool isUsernameAvailable = new PollorDbContext().UserAuthModel.Where(u => u.username!.ToLower().Equals(registerUser.username!.ToLower())).IsNullOrEmpty();
if (isUsernameAvailable == false) {
return BadRequest(new { message = "Username is already taken, please login or use another username." });
}

var hasher = new PasswordHasher<RegisterModel>();
var hashedPass = hasher.HashPassword(registerUser, registerUser.password!);
UserAuthModel tempUser = new UserAuthModel() {
username = registerUser.username,
password = hashedPass,
emailaddress = registerUser.emailaddress,
created_at = DateTime.Now,
};
bool isEmailAvailable = new PollorDbContext().UserAuthModel.Where(u => u.emailaddress!.ToLower().Equals(registerUser.emailaddress!.ToLower())).IsNullOrEmpty();
if (isEmailAvailable == false) {
return BadRequest(new { message = "Emailaddress is already taken, please login or use another emailaddress." });
}

var hasher = new PasswordHasher<RegisterModel>();
var hashedPass = hasher.HashPassword(registerUser, registerUser.password!);
UserAuthModel tempUser = new UserAuthModel() {
username = registerUser.username,
password = hashedPass,
emailaddress = registerUser.emailaddress,
created_at = DateTime.Now,
};

try
{
using (var context = new PollorDbContext())
{
// Create new user
Expand Down Expand Up @@ -96,33 +97,42 @@ public IActionResult Login([FromBody] LoginModel loginUser)
return BadRequest(new { message = "Invalid client request" });
}

var authUser = new PollorDbContext().UserAuthModel.Where(u => u.username!.ToLower().Equals(loginUser.username!.ToLower())).FirstOrDefault();
if (authUser == null) {
return Unauthorized(new { message = "Username or password is wrong!" });
}

var hasher = new PasswordHasher<LoginModel>();
PasswordVerificationResult passwordIsOk = hasher.VerifyHashedPassword(loginUser, authUser.password!, loginUser.password!);
try
{
var authUser = new PollorDbContext().UserAuthModel.Where(u => u.username!.ToLower().Equals(loginUser.username!.ToLower())).FirstOrDefault();
if (authUser == null)
{
return Unauthorized(new { message = "Username or password is wrong!" });
}

if (passwordIsOk == PasswordVerificationResult.Failed) {
return Unauthorized(new { message = "Username or password is wrong!" });
}
var hasher = new PasswordHasher<LoginModel>();
PasswordVerificationResult passwordIsOk = hasher.VerifyHashedPassword(loginUser, authUser.password!, loginUser.password!);

if (authUser.username == loginUser.username && (passwordIsOk == PasswordVerificationResult.Success || passwordIsOk == PasswordVerificationResult.SuccessRehashNeeded))
{
if (passwordIsOk == PasswordVerificationResult.SuccessRehashNeeded) {
// rehash password and save to DB
_logger.LogError("Rehash password and save to DB");
if (passwordIsOk == PasswordVerificationResult.Failed)
{
return Unauthorized(new { message = "Username or password is wrong!" });
}

int tokenLongerValid = (bool)loginUser.tokenLongerValid ? 14 : 1;// true = 14, false = 1
var currentUser = new PollorDbContext().Users.Where(u => u.username!.ToLower().Equals(authUser.username!.ToLower())).FirstOrDefault();
var tokenOptions = GetJwtTokenOptions(tokenLongerValid, currentUser!);
var tokenString = new JwtSecurityTokenHandler().WriteToken(tokenOptions);
if (authUser.username == loginUser.username && (passwordIsOk == PasswordVerificationResult.Success || passwordIsOk == PasswordVerificationResult.SuccessRehashNeeded))
{
if (passwordIsOk == PasswordVerificationResult.SuccessRehashNeeded)
{
// rehash password and save to DB
_logger.LogError("Rehash password and save to DB");
}

return Ok(new AuthenticatedResponse { token = tokenString, user = currentUser});
}
int tokenLongerValid = (bool)loginUser.tokenLongerValid ? 14 : 1;// true = 14, false = 1
var currentUser = new PollorDbContext().Users.Where(u => u.username!.ToLower().Equals(authUser.username!.ToLower())).FirstOrDefault();
var tokenOptions = GetJwtTokenOptions(tokenLongerValid, currentUser!);
var tokenString = new JwtSecurityTokenHandler().WriteToken(tokenOptions);

return Ok(new AuthenticatedResponse { token = tokenString, user = currentUser });
}
} catch (Exception ex)
{
_logger.LogError(ex, ex.Message);
return Unauthorized(new { message = ex.Message });
}
return Unauthorized(new { message = "something went wrong" } );
}

Expand Down
23 changes: 22 additions & 1 deletion pollor.Server/Controllers/PollsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,28 @@ public IActionResult AddPoll(PollModel poll)
{
try {
using (var context = new PollorDbContext()) {
EntityEntry<PollModel> newPoll = context.Polls.Add(poll);
var userClaims = HttpContext.User;
var userId = userClaims.Claims.Where(e => e.Type.Equals("userId")).Select(e => e.Value).SingleOrDefault()!;

DateTime now = DateTime.Now;
List<AnswerModel> answers = new List<AnswerModel>();
foreach (var a in poll.Answers) {
answers.Add(new AnswerModel()
{
poll_answer = a.poll_answer,
created_at = now
});
}

EntityEntry<PollModel> newPoll = context.Polls
.Add(new PollModel()
{
user_id = int.Parse(userId),
question = poll.question,
Answers = answers,
ending_date = poll.ending_date,
created_at = now
});
context.SaveChanges();

if (newPoll == null) {
Expand Down
21 changes: 19 additions & 2 deletions pollor.Server/Controllers/VotesController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,29 @@ public IActionResult GetVoteById(int id)
}

[HttpPost("vote")]
[Authorize]
public IActionResult AddVote(VoteModel vote)
{
try {
using (var context = new PollorDbContext()) {
EntityEntry<VoteModel> newVote = context.Votes.Add(vote);
AnswerModel? answer = context.Answers
.Where(a => a.id.Equals(vote.answer_id))
.Where(a => a.Votes.Any(v => v.ipv4_address == vote.ipv4_address || v.ipv6_address == vote.ipv6_address))
.FirstOrDefault();
if (answer != null) {
return Conflict(new { message = "You have already voted on this poll" });
}
}

DateTime now = DateTime.Now;
using (var context = new PollorDbContext()) {
EntityEntry<VoteModel> newVote = context.Votes.Add(new VoteModel()
{
answer_id = vote.answer_id,
ipv4_address = vote.ipv4_address ?? null,
ipv6_address = vote.ipv6_address ?? null,
created_at = now,
voted_at = now
});
context.SaveChanges();

if (newVote == null) {
Expand Down
8 changes: 4 additions & 4 deletions pollor.Server/Models/VoteModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ namespace pollor.Server.Models
public partial class VoteModel : SuperModel
{
public int answer_id { get; set; }
[MaxLength(4)]
public byte[]? ipv4_address { get; set; }
[MaxLength(16)]
public byte[]? ipv6_address { get; set; }
[MaxLength(15)]
public string? ipv4_address { get; set; }
[MaxLength(45)]
public string? ipv6_address { get; set; }
[MaxLength(12)]
public char[]? mac_address { get; set; }
public DateTime voted_at { get; set; }
Expand Down
2 changes: 1 addition & 1 deletion pollor.Server/Properties/launchSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:5010",
"applicationUrl": "https://localhost:5010",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.SpaProxy"
Expand Down
2 changes: 1 addition & 1 deletion pollor.Server/pollor.Server.http
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@pollor.Server_HostAddress = http://localhost:5010
@pollor.Server_HostAddress = https://localhost:5010

GET {{pollor.Server_HostAddress}}/weatherforecast/
Accept: application/json
Expand Down
9 changes: 4 additions & 5 deletions pollor.client/angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,9 @@
"src/assets"
],
"styles": [
"src/styles.css",
"./node_modules/bootstrap/dist/css/bootstrap.min.css",
"./node_modules/bootstrap-icons/font/bootstrap-icons.css"

"./node_modules/bootstrap-icons/font/bootstrap-icons.css",
"src/styles.css"
],
"scripts": [
"./node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"
Expand Down Expand Up @@ -97,9 +96,9 @@
"src/assets"
],
"styles": [
"src/styles.css",
"node_modules/bootstrap/dist/css/bootstrap.min.css",
"./node_modules/bootstrap-icons/font/bootstrap-icons.css"
"./node_modules/bootstrap-icons/font/bootstrap-icons.css",
"src/styles.css"
],
"scripts": [
"./node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"
Expand Down
22 changes: 12 additions & 10 deletions pollor.client/src/app/_auth/auth.interceptor.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { HttpEvent, HttpHandler, HttpHeaders, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { AuthService } from './auth.service';
import { environment } from '../../environments/environment';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
private baseUrl = `${environment.API_URL}`;

constructor(private authService: AuthService) { }

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (this.authService.getToken()) {
const headers = {
'Content-Type': 'application/json; charset=utf-8',
'Accept': 'application/json',
'Authorization': `Bearer ${this.authService.getToken()}`,
if (req.url.includes(this.baseUrl)) {
let headers = new HttpHeaders();
headers = headers.set('Content-Type', 'application/json; charset=utf-8');

if (this.authService.getToken()) {
headers = headers.set('Accept', 'application/json');
headers = headers.set('Authorization', `Bearer ${this.authService.getToken()}`);
};

req = req.clone({
setHeaders: headers,
});

req = req.clone({ headers });
}

return next.handle(req);
Expand Down
2 changes: 1 addition & 1 deletion pollor.client/src/app/_auth/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export class AuthService {
}

public navigateDashboard(): void {
const dashboardRoute = this.getRole().toLowerCase() === 'admin' ? '/account/admin-profile' : '/account/profile';
const dashboardRoute = this.getRole().toLowerCase() === 'admin' ? '/account/adminpanel' : '/account';
this.router.navigate([dashboardRoute]);
console.log(`${this.getRole()} dashboard route`);
}
Expand Down
14 changes: 14 additions & 0 deletions pollor.client/src/app/_interfaces/answer.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { IPoll } from "./poll.interface";
import { IVote } from "./vote.interface";

export interface IAnswer {
id: number;
poll_id: IPoll;
poll_answer: string;
created_at: Date;
votes: IVote[];
}

export interface ICreateAnswer {
poll_answer: string;
}
10 changes: 0 additions & 10 deletions pollor.client/src/app/_interfaces/answers.interface.ts

This file was deleted.

16 changes: 16 additions & 0 deletions pollor.client/src/app/_interfaces/poll.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { IAnswer, ICreateAnswer } from "./answer.interface";

export interface IPoll {
id: string;
user_id: number;
question: number;
ending_date: Date;
created_at: Date;
answers: IAnswer[];
}

export interface ICreatePoll {
question: number;
ending_date: Date;
answers: ICreateAnswer[];
}
10 changes: 0 additions & 10 deletions pollor.client/src/app/_interfaces/polls.interface.ts

This file was deleted.

4 changes: 2 additions & 2 deletions pollor.client/src/app/_interfaces/user.interface.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { IPolls } from "./polls.interface";
import { IPoll } from "./poll.interface";

export interface IUser {
id: number;
Expand All @@ -8,7 +8,7 @@ export interface IUser {
last_name: string;
role: string;
created_at: Date;
polls: IPolls[];
polls: IPoll[];
}

export interface IUserChangePassword {
Expand Down
Loading

0 comments on commit e13462f

Please sign in to comment.