diff --git a/client/src/app/app-routing.module.ts b/client/src/app/app-routing.module.ts index 4bae76e250156515cc188c99f976a4e50bdd2ef5..9de5dfda29e3799cb2ed1c1612af1a3cb090a210 100644 --- a/client/src/app/app-routing.module.ts +++ b/client/src/app/app-routing.module.ts @@ -6,6 +6,7 @@ import { PostListComponent } from './posts/post-list/post-list.component'; import { UserRegistrationFormComponent } from './users/user-registration-form/user-registration-form.component'; import { UserLoginFormComponent } from './users/user-login-form/user-login-form.component'; import { UserProfileComponent } from './users/user-profile/user-profile.component'; +import { UserLogoutComponent } from './users/user-logout/user-logout.component'; const routes: Routes = [ { path: 'annonse/ny', component: PostFormComponent }, @@ -15,7 +16,8 @@ const routes: Routes = [ { path: 'profile', component: UserProfileComponent }, { path: 'register', component: UserRegistrationFormComponent }, - { path: 'login', component: UserLoginFormComponent } + { path: 'login', component: UserLoginFormComponent }, + { path: 'logout', component: UserLogoutComponent } ]; @NgModule({ diff --git a/client/src/app/app.component.html b/client/src/app/app.component.html index 7c45da00f72626aa25250a412ee63294fad344ad..81cb33f0381e893897e1d0bb905e18e39f90985a 100644 --- a/client/src/app/app.component.html +++ b/client/src/app/app.component.html @@ -1,13 +1,12 @@ <div class="navbar"> - <a class="logo" href="/">SELLPOINT</a> + <span class="logo" (click)="navigate('/')">SellPoint</span> <nav> - <a href="/">/</a> - <a href="/annonse">/annonse</a> - <a href="/annonse/ny">/annonse/ny</a> - <a href="/register">/register</a> - <a href="/login">/login</a> - <a href="/profile">/profile</a> - <a href="/logout">/logout</a> + <span (click)="navigate('/annonse')">Annonser</span> + <span (click)="navigate('/annonse/ny')">Lag annonse</span> + <span *ngIf="!user" (click)="navigate('/register')">Registrer</span> + <span *ngIf="!user" (click)="navigate('/login')">Logg inn</span> + <span *ngIf="user" (click)="navigate('/profile')">Profil</span> + <span *ngIf="user" (click)="navigate('/logout')">Logg ut</span> </nav> </div> <div class="splash"> @@ -23,11 +22,10 @@ <h2>Lorem Ipsum</h2> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. <div class="buttons"> - <a href="/register" class="btn">Register deg!</a> - <a href="javascript:void(0)" class="btn pink">Les mer</a> + <button (click)="navigate('/register')" class="btn">Registrer deg!</button> + <button (click)="navigate('/')" class="btn pink">Les mer</button> </div> </div> - </div> </div> diff --git a/client/src/app/app.component.scss b/client/src/app/app.component.scss index 882c3fe9814051f453e801534144489b8abfcf6e..56ae8a30bdf418842d49d6276d871a9fc32043e5 100644 --- a/client/src/app/app.component.scss +++ b/client/src/app/app.component.scss @@ -1,21 +1,26 @@ div.navbar { - background-color: #666; + background-color: #fff; display: flex; justify-content: space-between; align-items: center; - height: 70px; + height: 62px; + font-family: 'Josefin Sans', sans-serif; + padding-top: 8px; - a.logo { + span.logo { padding: 10px; - background-color: white; width: 200px; margin-left: 10px; + font-size: 40px; + font-weight: bold; + cursor: pointer; } nav { - a{ + span{ padding: 10px; margin: 10px; - background-color: white; + cursor: pointer; + font-size: 25px; } } } @@ -31,13 +36,10 @@ div.splash { overflow: hidden; color: #ffffff; font-family: 'Inter', sans-serif; - a { + button { color: #ffffff; text-decoration: none; } - a:visited { - color: #ffffff; - } div { position: relative; } @@ -80,7 +82,7 @@ div.splash { text-align: center; justify-content: flex-end; } - a.btn { + button.btn { background: #13D05E; width: 200px; margin: 10px 0 10px 10px; @@ -88,8 +90,10 @@ div.splash { box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25), 0px 4px 4px rgba(0, 0, 0, 0.25); font-family: 'Josefin Sans', sans-serif; font-size: 20px; + border: none; + cursor: pointer; } - a.pink { + button.pink { background: #FFA1A1; } diff --git a/client/src/app/app.component.ts b/client/src/app/app.component.ts index cc061ccd82009ac4a6add0a0df0b8e701e1c8d42..83a949b0d973f839c2b3be21033fad1156793d22 100644 --- a/client/src/app/app.component.ts +++ b/client/src/app/app.component.ts @@ -1,10 +1,29 @@ -import { Component } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; +import { Router } from '@angular/router'; +import { Subscription } from 'rxjs'; +import { AuthService } from './authentication/auth.service'; +import { User } from './models/user.model'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'] }) -export class AppComponent { +export class AppComponent implements OnInit { title: string = 'client'; + user: User; + userSubscription: Subscription; + + constructor(private authService: AuthService, private router: Router){} + + ngOnInit() { + this.user = this.authService.getCurrentUser(); + this.userSubscription = this.authService.userObservable.subscribe(user => { + this.user = user; + }); + } + + navigate(url) { + this.router.navigateByUrl(url); + } } diff --git a/client/src/app/authentication/auth.service.ts b/client/src/app/authentication/auth.service.ts index cab69f3b5dea1554e09e0501f3922d7a09356a23..315b8980a9801ce60b64a6d6e0fc7779567f4bb6 100644 --- a/client/src/app/authentication/auth.service.ts +++ b/client/src/app/authentication/auth.service.ts @@ -1,8 +1,10 @@ -import { HttpClient, HttpEvent, HttpInterceptor, HttpResponse } from '@angular/common/http'; +import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { User } from '../models/user.model'; import { tap, shareReplay } from 'rxjs/operators'; import { Router } from '@angular/router'; +import { UserService } from '../users/user.service'; +import { Subject } from 'rxjs'; interface IUserLogin { username: string; @@ -16,7 +18,21 @@ export class AuthService { loginUrl = "api/auth/login"; registrationUrl = "api/auth/register"; - constructor(private http: HttpClient, private router: Router) { } + userObservable: Subject<User> = new Subject<User>(); + + constructor(private http: HttpClient, private router: Router, private userService: UserService) { } + + getCurrentUser(): User{ + // Check for token expiration + if (this.checkTokenExpiration()) { // redirects to "/" if token is expired + // Get user data from JWT token + const token = localStorage.getItem('token'); + const user_data = JSON.parse(atob(token.split(".")[1])).data[0]; + + return new User(user_data); + } + return null; + } /** * Logins an user, if given correct combination of username and password. @@ -41,13 +57,15 @@ export class AuthService { private login_user(body: IUserLogin) { // Pipes output to setSession function if a valid user is returned return this.http.post(this.loginUrl, body).pipe( - tap(res =>this.setSession(res)), - shareReplay()); + tap(res =>this.setSession(res)), + shareReplay() + ); } + // Set authentication token on localStorage if a valid user is received private setSession(authResult) { - console.log(authResult); localStorage.setItem('token', authResult.token); + this.userObservable.next(this.getCurrentUser()); } /** @@ -64,13 +82,13 @@ export class AuthService { // Expired token if (now < issued || now >= expires) { this.logout(); - this.router.navigateByUrl("/"); + this.router.navigateByUrl("/login"); return false } return true; } } - this.router.navigateByUrl("/") + this.router.navigateByUrl("/login") return false } @@ -79,7 +97,8 @@ export class AuthService { */ logout() { localStorage.removeItem("token"); - this.router.navigateByUrl("/") + this.router.navigateByUrl("/"); + this.userObservable.next(null); } /** diff --git a/client/src/app/models/post.model.ts b/client/src/app/models/post.model.ts index fcf5e849bd889d4fa77683b0569df936e20a88bd..7678903ebbae78fe5386c16add316bf655191fc5 100644 --- a/client/src/app/models/post.model.ts +++ b/client/src/app/models/post.model.ts @@ -6,7 +6,7 @@ export class Post implements Deserializable, Serializable { private title: string; private description: string; private timestamp: Date; - private owner: string; + private owner: number; private imageUrl: string; private price: number; private categoryid: number; @@ -83,7 +83,7 @@ export class Post implements Deserializable, Serializable { return this.owner; } - set setOwner(owner: string) { + set setOwner(owner: number) { this.owner = owner; } diff --git a/client/src/app/models/user.model.ts b/client/src/app/models/user.model.ts index 8bfe6639f25fa844f4ddaa3a1c504709421543b0..e4990d6ae007c9087ecd3eb4186eb3e9390c8267 100644 --- a/client/src/app/models/user.model.ts +++ b/client/src/app/models/user.model.ts @@ -22,7 +22,6 @@ export class User implements Deserializable, Serializable { deserialize(input: Object): this { Object.assign(this, input); - console.log(this); return this; } diff --git a/client/src/app/posts/post-details/post-details.component.html b/client/src/app/posts/post-details/post-details.component.html index ba284316a22ead9b04fbb999c8110b21f67c13aa..40857f7ce3a7ee7184384d6e93767369b387b482 100644 --- a/client/src/app/posts/post-details/post-details.component.html +++ b/client/src/app/posts/post-details/post-details.component.html @@ -7,5 +7,7 @@ <p>Publisert: {{post.getTimestamp}}</p> <p>Eier: {{post.getOwner}}</p> -<app-button text="Rediger annonse" (click)="editPost()"></app-button> -<app-button text="Slett annonse" (click)="deletePost()"></app-button> +<div *ngIf="userId == post.getOwner"> + <app-button text="Rediger annonse" (click)="editPost()"></app-button> + <app-button text="Slett annonse" (click)="deletePost()"></app-button> +</div> diff --git a/client/src/app/posts/post-details/post-details.component.ts b/client/src/app/posts/post-details/post-details.component.ts index 3de9e4d32cfdba4092e59ac8427030c074166eca..35099eb8fcef16eccf56cf7568781c35ca269620 100644 --- a/client/src/app/posts/post-details/post-details.component.ts +++ b/client/src/app/posts/post-details/post-details.component.ts @@ -2,6 +2,7 @@ import { Component, OnInit } from '@angular/core'; import { Post } from 'src/app/models/post.model'; import { PostService } from '../post.service'; import { ActivatedRoute, Router } from '@angular/router' +import { AuthService } from 'src/app/authentication/auth.service'; @Component({ selector: 'app-post-details', @@ -11,13 +12,17 @@ import { ActivatedRoute, Router } from '@angular/router' export class PostDetailsComponent implements OnInit { post: Post = new Post(); + userId: number = 0; - constructor(private postService: PostService, private activatedRoute: ActivatedRoute, private router: Router) { } + constructor(private postService: PostService, private activatedRoute: ActivatedRoute, private router: Router, private authService: AuthService) { } ngOnInit(): void { // Gets id parameter from URL const id = this.activatedRoute.snapshot.params["id"]; + // Gets ID from current user + this.userId = this.authService.getCurrentUser().getUserId; + // Gets Post with id from database this.postService.getPost(id).then(post => { this.post = post; @@ -25,6 +30,7 @@ export class PostDetailsComponent implements OnInit { console.log(error); }); } + /** * Moves to edit page */ @@ -36,11 +42,13 @@ export class PostDetailsComponent implements OnInit { * Deletes post in database and navigates to post list */ deletePost() { - this.postService.deletePost(this.post.getId).then(data => { - console.log("Successfully deleted post: " + this.post.getId); - this.router.navigateByUrl("/annonse"); - }).catch(error => { - console.log(error); - }); + if (this.userId == this.post.getOwner) { + this.postService.deletePost(this.post.getId).then(data => { + console.log("Successfully deleted post: " + this.post.getId); + this.router.navigateByUrl("/annonse"); + }).catch(error => { + console.log(error); + }); + } } } diff --git a/client/src/app/posts/post-form/post-form.component.ts b/client/src/app/posts/post-form/post-form.component.ts index 4fcf05a15115a372616c5ebe720264b1ff6620b7..3e9587e8ed8e3fe359dc6178250cf1634a319c7a 100644 --- a/client/src/app/posts/post-form/post-form.component.ts +++ b/client/src/app/posts/post-form/post-form.component.ts @@ -1,7 +1,9 @@ import { Component, OnInit } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; +import { AuthService } from 'src/app/authentication/auth.service'; import { Category } from 'src/app/models/category.model'; import { Post } from 'src/app/models/post.model'; +import { User } from 'src/app/models/user.model'; import { PostService } from '../post.service'; @Component({ @@ -24,9 +26,17 @@ export class PostFormComponent implements OnInit { categories: Array<Category>; - constructor(private postService: PostService, private router: Router, private activatedRoute: ActivatedRoute) { } + currentUser: User; + + constructor(private postService: PostService, private router: Router, private activatedRoute: ActivatedRoute, private authService: AuthService) { } ngOnInit() { + this.currentUser = this.authService.getCurrentUser(); + + if (!this.currentUser) { + this.router.navigateByUrl("/login"); + } + const id = this.activatedRoute.snapshot.params["id"]; if (id) { this.id = id; @@ -39,6 +49,10 @@ export class PostFormComponent implements OnInit { this.categoryid = post.getCategory; this.imageUrl = post.getImageUrl; + if (post.getOwner != this.currentUser.getUserId) { + this.router.navigateByUrl("/"); + } + this.showImage(this.imageUrl); }).catch(error => { console.log(error); @@ -91,7 +105,7 @@ export class PostFormComponent implements OnInit { title: this.title, description: this.description, timestamp: new Date(), - owner: "admin", + owner: this.currentUser.getUserId, imageUrl: this.imageUrl, price: this.price, categoryid: this.categoryid diff --git a/client/src/app/users/user-login-form/user-login-form.component.ts b/client/src/app/users/user-login-form/user-login-form.component.ts index 3f4cefddfdbaf340b8a983de899ed4a6b96b50cf..198c7d2e4e715ef2836899bc4b7680e3c9d2c1e9 100644 --- a/client/src/app/users/user-login-form/user-login-form.component.ts +++ b/client/src/app/users/user-login-form/user-login-form.component.ts @@ -49,7 +49,6 @@ export class UserLoginFormComponent implements OnInit { // Logins the user this.authService.login(request).then(status => { - console.log("User login1: " + JSON.stringify(status)); this.router.navigateByUrl("/"); }).catch(error => { console.log("Error user login: " + error); diff --git a/client/src/app/users/user-profile/user-profile.component.ts b/client/src/app/users/user-profile/user-profile.component.ts index ce10985b22048f6d0771c07ff0d54e02b6cde92d..5ba47faffcd241a344e888f5772820e7021fc541 100644 --- a/client/src/app/users/user-profile/user-profile.component.ts +++ b/client/src/app/users/user-profile/user-profile.component.ts @@ -13,22 +13,9 @@ import { UserService } from '../user.service'; export class UserProfileComponent implements OnInit { user: User = new User(); - constructor(private userService: UserService, private authService: AuthService, private router: Router) { } + constructor(private authService: AuthService, private router: Router) { } ngOnInit(): void { - // Check for token expiration - if (this.authService.checkTokenExpiration()) { // redirects to "/" if token is expired - // Get user data from JWT token - const token = localStorage.getItem('token'); - const user_data = JSON.parse(atob(token.split(".")[1])).data[0]; - - // Gets all user information and displays them in the component - this.userService.getUser(user_data.userId).then(user => { - this.user = user; - }).catch (error => { - console.log("Error getting user: " + error); - }); - } - + this.user = this.authService.getCurrentUser(); } } diff --git a/server/src/models/post.ts b/server/src/models/post.ts index ad301aa6174e8eda398dd9cbf3b4b539f52e060b..f4038f8b47f04fc9decbba8abff1f8d2c0188cdd 100644 --- a/server/src/models/post.ts +++ b/server/src/models/post.ts @@ -4,7 +4,7 @@ interface IPost { description: string; price: string; timestamp: number; - owner: string; + owner: number; categoryid: number; imageUrl: string; }