From a76ddeceadabd0f37a44793403604540baea02c9 Mon Sep 17 00:00:00 2001 From: Emanuel <101946589+Emanuel3queijos@users.noreply.github.com> Date: Mon, 29 Apr 2024 16:39:56 -0300 Subject: [PATCH] llogin com axios ok --- .../services/AdService.java | 43 ++++-- .../services/CrudInterface.java | 18 +++ ...ServiceInterface.java => UserService.java} | 5 +- frontend/package-lock.json | 56 +++++++- frontend/package.json | 1 + frontend/src/app/app.component.ts | 3 +- frontend/src/app/app.routes.ts | 2 + frontend/src/app/axios.service.spec.ts | 16 +++ frontend/src/app/axios.service.ts | 63 +++++++++ frontend/src/app/login/login.component.scss | 124 ++++++++++++++++++ frontend/src/app/login/login.component.ts | 78 +++++++++++ frontend/src/styles.scss | 44 +++---- 12 files changed, 411 insertions(+), 42 deletions(-) create mode 100644 backend/housing-location-project-backend/src/main/java/com/br/emanuelap/housinglocationprojectbackend/services/CrudInterface.java rename backend/housing-location-project-backend/src/main/java/com/br/emanuelap/housinglocationprojectbackend/services/{AdServiceInterface.java => UserService.java} (62%) create mode 100644 frontend/src/app/axios.service.spec.ts create mode 100644 frontend/src/app/axios.service.ts create mode 100644 frontend/src/app/login/login.component.scss create mode 100644 frontend/src/app/login/login.component.ts diff --git a/backend/housing-location-project-backend/src/main/java/com/br/emanuelap/housinglocationprojectbackend/services/AdService.java b/backend/housing-location-project-backend/src/main/java/com/br/emanuelap/housinglocationprojectbackend/services/AdService.java index a7ec120..321a69b 100644 --- a/backend/housing-location-project-backend/src/main/java/com/br/emanuelap/housinglocationprojectbackend/services/AdService.java +++ b/backend/housing-location-project-backend/src/main/java/com/br/emanuelap/housinglocationprojectbackend/services/AdService.java @@ -1,31 +1,50 @@ package com.br.emanuelap.housinglocationprojectbackend.services; import com.br.emanuelap.housinglocationprojectbackend.entities.Ad; +import com.br.emanuelap.housinglocationprojectbackend.exceptions.AppException; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; import com.br.emanuelap.housinglocationprojectbackend.repositories.AdRepository; +import java.util.List; +import java.util.Optional; + @RequiredArgsConstructor @Service -public class AdService { - - @Autowired - private AdRepository adRepository; -// public List findAll() {} +public class AdService implements CrudInterface { + private final AdRepository adRepository; + @Override public Ad save(Ad ad) { -// -// Optional optionalAd = adRepository.findByTitle(ad.getTitle()); -// if (optionalAd.isPresent()) { -// throw new AppException("Add with same tittle already exist", HttpStatus.CONFLICT); -// } -// - + Optional optionalAd = adRepository.findByTitle(ad.getTitle()); + if (optionalAd.isPresent()) { + throw new AppException("Add with same tittle already exist", HttpStatus.CONFLICT); + } return adRepository.save(ad); +} + + @Override + public List findAll() { + return List.of(); + } + + @Override + public Optional findById(Long id) { + return Optional.empty(); + } + + @Override + public Ad update(Object obj) { + return null; + } + + @Override + public void deleteById(Long id) { } } diff --git a/backend/housing-location-project-backend/src/main/java/com/br/emanuelap/housinglocationprojectbackend/services/CrudInterface.java b/backend/housing-location-project-backend/src/main/java/com/br/emanuelap/housinglocationprojectbackend/services/CrudInterface.java new file mode 100644 index 0000000..cef9868 --- /dev/null +++ b/backend/housing-location-project-backend/src/main/java/com/br/emanuelap/housinglocationprojectbackend/services/CrudInterface.java @@ -0,0 +1,18 @@ +package com.br.emanuelap.housinglocationprojectbackend.services; + +import java.util.List; +import java.util.Optional; + +public interface CrudInterface { + + T save(T obj); + + List findAll(); + + Optional findById(Long id); + + T update(Object obj); + + void deleteById(Long id); + +} diff --git a/backend/housing-location-project-backend/src/main/java/com/br/emanuelap/housinglocationprojectbackend/services/AdServiceInterface.java b/backend/housing-location-project-backend/src/main/java/com/br/emanuelap/housinglocationprojectbackend/services/UserService.java similarity index 62% rename from backend/housing-location-project-backend/src/main/java/com/br/emanuelap/housinglocationprojectbackend/services/AdServiceInterface.java rename to backend/housing-location-project-backend/src/main/java/com/br/emanuelap/housinglocationprojectbackend/services/UserService.java index c9eb993..5d242e9 100644 --- a/backend/housing-location-project-backend/src/main/java/com/br/emanuelap/housinglocationprojectbackend/services/AdServiceInterface.java +++ b/backend/housing-location-project-backend/src/main/java/com/br/emanuelap/housinglocationprojectbackend/services/UserService.java @@ -1,7 +1,4 @@ package com.br.emanuelap.housinglocationprojectbackend.services; -public interface AdServiceInterface { - - - +public class UserService { } diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 22af01c..9bedfed 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -25,6 +25,7 @@ "@fortawesome/free-solid-svg-icons": "^6.4.2", "@ng-bootstrap/ng-bootstrap": "^16.0.0", "@popperjs/core": "^2.11.8", + "axios": "^1.6.8", "bootstrap": "^5.3.2", "rxjs": "~7.8.0", "tslib": "^2.3.0", @@ -5109,6 +5110,11 @@ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", "dev": true }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, "node_modules/autoprefixer": { "version": "10.4.18", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.18.tgz", @@ -5146,6 +5152,16 @@ "postcss": "^8.1.0" } }, + "node_modules/axios": { + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", + "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/babel-loader": { "version": "9.1.3", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.1.3.tgz", @@ -5841,6 +5857,17 @@ "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", "dev": true }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -6393,6 +6420,14 @@ "node": ">=8" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -7173,7 +7208,6 @@ "version": "1.15.6", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", - "dev": true, "funding": [ { "type": "individual", @@ -7217,6 +7251,19 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -9069,7 +9116,6 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -9078,7 +9124,6 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "dependencies": { "mime-db": "1.52.0" }, @@ -10524,6 +10569,11 @@ "node": ">= 0.10" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", diff --git a/frontend/package.json b/frontend/package.json index 3529879..5eaf5fc 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -27,6 +27,7 @@ "@fortawesome/free-solid-svg-icons": "^6.4.2", "@ng-bootstrap/ng-bootstrap": "^16.0.0", "@popperjs/core": "^2.11.8", + "axios": "^1.6.8", "bootstrap": "^5.3.2", "rxjs": "~7.8.0", "tslib": "^2.3.0", diff --git a/frontend/src/app/app.component.ts b/frontend/src/app/app.component.ts index 1d06bec..2ac01d1 100644 --- a/frontend/src/app/app.component.ts +++ b/frontend/src/app/app.component.ts @@ -9,9 +9,10 @@ import { RouterModule } from '@angular/router'; standalone: true, imports: [RouterOutlet, HomeComponent, MatToolbarModule, RouterModule], template: ` -
+
+
{ + let service: AxiosService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(AxiosService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/frontend/src/app/axios.service.ts b/frontend/src/app/axios.service.ts new file mode 100644 index 0000000..6c13ec5 --- /dev/null +++ b/frontend/src/app/axios.service.ts @@ -0,0 +1,63 @@ +import { Injectable } from '@angular/core'; +import axios from 'axios'; +// import * as jwt from 'jsonwebtoken'; + +@Injectable({ + providedIn: 'root', +}) +export class AxiosService { + constructor() { + // axios.defaults.baseURL = 'http://localhost:8080'; + // axios.defaults.headers.post['Content-Type'] = 'application/json'; + } + + getAuthToken(): string | null { + return window.localStorage.getItem('auth_token'); + } + + getRole(): { username: string; role: string } | null { + const token = this.getAuthToken(); + if (token) { + const payload = token.split('.')[1]; + const decodedPayload = JSON.parse(atob(payload)); + return { + username: decodedPayload.nome, + role: decodedPayload.role, + }; + } + return null; + } + + setAuthToken(token: string | null): void { + if (token !== null) { + window.localStorage.setItem('auth_token', token); + } else { + window.localStorage.removeItem('auth_token'); + } + } + + isAuthenticated(): boolean { + const authToken = this.getAuthToken(); // Chame a função para obter o token JWT + return !!authToken; // Verifique se authToken existe e não é nulo + } + + logout(): void { + this.setAuthToken(null); + } + + request(method: string, url: string, data: any): Promise { + let headers: any = {}; + + if (this.getAuthToken() !== null) { + headers = { Authorization: 'Bearer ' + this.getAuthToken() }; + console.log('Token:', this.getAuthToken()); // Adicione esta linha para imprimir o token + } + + return axios({ + method: method, + url: url, + data: data, + headers: headers, + }); + } +} diff --git a/frontend/src/app/login/login.component.scss b/frontend/src/app/login/login.component.scss new file mode 100644 index 0000000..623e6a4 --- /dev/null +++ b/frontend/src/app/login/login.component.scss @@ -0,0 +1,124 @@ +a { + text-decoration: none; + color: #9796b7; + font-size: large; +} +a:hover { + text-decoration: none; + color: var(--accent-color); +} +button:hover { + background-color: var(--accent-color); +} + +input { + border: solid 2px #625fc9; + padding: 10px; + border-radius: 8px; + margin-right: 4px; + display: inline-block; + width: 30%; +} + +button { + padding: 10px; + border: solid 2px #625fc9; + background: #625fc9; + color: white; + border-radius: 8px; +} + +html, +body { + height: 100%; + overflow-x: hidden; +} + +a { + color: #4a6b83; + text-decoration: none; + font-size: x-small; +} +label { + font-size: large; + font-weight: 100; +} + +a:hover { + color: #000000; +} + +.navbar-collapse { + transition: height 0.5s ease-out; +} + +form { + width: 360px; + padding: 4% 0 0; + margin: auto; +} + +.form { + position: relative; + z-index: 1; + background-color: var(--pinkPurple-color); + max-width: 360px; + border-radius: 10%; + margin: 0 auto 50px; + padding: 45px; + text-align: center; +} + +.form input { + outline: 0; + background: #ffffff; + width: 100%; + border: 0; + border-radius: 7px; + margin: 0 0 15px; + padding: 15px; + box-sizing: border-box; + font-size: 14px; +} + +.form button { + font-family: "Roboto", sans-serif; + text-transform: uppercase; + outline: 0; + border-radius: 10px; + background: #625fc9; + width: 100%; + border: 0; + padding: 15px; + color: #ffffff; + font-size: 14px; + -webkit-transition: all 0.3 ease; + transition: all 0.3 ease; + cursor: pointer; +} + +.form button:hover, +.form button:active, +.form button:focus { + background: #9796b7; +} + +@media (max-width: 765px) { + .mobile { + display: block; + } +} + +@media (max-width: 768px) { + body { + background-attachment: scroll; + } +} + +@media (max-width: 700px) { + body { + background-attachment: scroll; + } +} + +@import url(https://fonts.googleapis.com/css?family=Roboto:300); diff --git a/frontend/src/app/login/login.component.ts b/frontend/src/app/login/login.component.ts new file mode 100644 index 0000000..ba9add0 --- /dev/null +++ b/frontend/src/app/login/login.component.ts @@ -0,0 +1,78 @@ +import { EventEmitter, Component, Output } from '@angular/core'; +import { AxiosService } from '../axios.service'; +import { FormsModule } from '@angular/forms'; +import { BrowserModule } from '@angular/platform-browser'; +import { MatToolbarModule } from '@angular/material/toolbar'; +import { NgbAlert } from '@ng-bootstrap/ng-bootstrap'; + +@Component({ + selector: 'app-login', + standalone: true, + imports: [FormsModule, MatToolbarModule, NgbAlert], + template: ` +
+ +
+ `, + styleUrls: ['./login.component.scss'], +}) +export class LoginComponent { + @Output() onSubmitLoginEvent = new EventEmitter(); + @Output() onSubmitRegisterEvent = new EventEmitter(); + constructor(private axiosService: AxiosService) {} + login: string = ''; + password: string = ''; + errorMsg: string = ''; + onSubmitLogin(): void { + this.axiosService + .request('POST', '/auth/login', { + login: this.login, + password: this.password, + }) + .then((response) => { + this.axiosService.setAuthToken(response.data.token); + console.log(response.data.token); + }) + .catch((error) => { + this.axiosService.setAuthToken(null); + this.errorMsg = 'Ocorreu um erro: ' + error.message; + }); + } +} diff --git a/frontend/src/styles.scss b/frontend/src/styles.scss index a6fbc72..6531dc8 100644 --- a/frontend/src/styles.scss +++ b/frontend/src/styles.scss @@ -1,5 +1,5 @@ /* You can add global styles to this file, and also import other style files */ -@use '@angular/material' as mat; +@use "@angular/material" as mat; @include mat.core(); @@ -7,34 +7,34 @@ $primary-color-palette: mat.define-palette(mat.$deep-purple-palette, 50); $secondary-color-palette: mat.define-palette(mat.$purple-palette, 100); $warn-color-palette: mat.define-palette(mat.$red-palette, 600); -$custom-theme: mat.define-light-theme(( +$custom-theme: mat.define-light-theme( + ( color: ( -primary: $primary-color-palette, -accent: $secondary-color-palette - + primary: $primary-color-palette, + accent: $secondary-color-palette, ), typography: mat.define-typography-config(), - density: 0, -) - + density: 0, + ) ); :root { - --primary-color: #605DC8; - --secondary-color: #8B89E6; - --accent-color: #e8e7fa; - --shadow-color: #E8E8E8; - } - + --primary-color: #605dc8; + --secondary-color: #8b89e6; + --accent-color: #e8e7fa; + --shadow-color: #e8e8e8; + --pinkPurple-color: #ede7f6ae; +} @include mat.all-component-themes($custom-theme); -html, body { height: 100%; } -body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; } -html, body { height: 100%; } -body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; } - -/* Importing Bootstrap SCSS file. */ -@import 'bootstrap/scss/bootstrap'; +html, +body { + height: 100%; +} +body { + margin: 0; + font-family: Roboto, "Helvetica Neue", sans-serif; +} /* Importing Bootstrap SCSS file. */ -@import 'bootstrap/scss/bootstrap'; +@import "bootstrap/scss/bootstrap";