Commit e7f38f23 authored by Xiyang Lu's avatar Xiyang Lu

[AFP-36] Joe MoveGradleToMaven, finished afp 36 both frontend and backend

parent 1fb4a1bd
No preview for this file type
package com.nisum.ecomservice.controller; package com.nisum.ecomservice.controller;
//import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier;
//import com.google.api.client.http.javanet.NetHttpTransport;
//import com.google.api.client.json.gson.GsonFactory;
import com.nisum.ecomservice.model.User; import com.nisum.ecomservice.model.User;
import com.nisum.ecomservice.repository.UserRepository; import com.nisum.ecomservice.model.UserRequestBody;
import com.nisum.ecomservice.service.UserService; import com.nisum.ecomservice.service.UserService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.util.Collections;
@RestController @RestController
@RequestMapping("/api/users") @RequestMapping("/api/users")
...@@ -14,8 +22,18 @@ public class UsersController { ...@@ -14,8 +22,18 @@ public class UsersController {
@Autowired @Autowired
private UserService userService; private UserService userService;
@Autowired // @Value("${google.client_id}")
private UserRepository userRepository; // private String CLIENT_ID;
// NetHttpTransport transport = new NetHttpTransport();
// GsonFactory jsonFactory = new GsonFactory().getDefaultInstance();
//
// GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(transport, jsonFactory)
// // Specify the CLIENT_ID of the app that accesses the backend:
// .setAudience(Collections.singletonList(CLIENT_ID))
// // Or, if multiple clients access the backend:
// //.setAudience(Arrays.asList(CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3))
// .build();
@GetMapping() @GetMapping()
private Flux<User> getUsers(){ private Flux<User> getUsers(){
...@@ -25,4 +43,47 @@ public class UsersController { ...@@ -25,4 +43,47 @@ public class UsersController {
return userService.getUsers(); return userService.getUsers();
} }
@PostMapping()
public ResponseEntity<Mono<User>> createUser(@RequestBody UserRequestBody requestBody) {
// GoogleIdToken idToken = verifier.verify(idTokenString);
// if (idToken != null) {
// Payload payload = idToken.getPayload();
// String userId = payload.getSubject();
//// System.out.println("User ID: " + userId);
// // Get profile information from payload
// String email = payload.getEmail();
// boolean emailVerified = Boolean.valueOf(payload.getEmailVerified());
// String lastName = (String) payload.get("family_name");
// String firstName = (String) payload.get("given_name");
//
// User newUser = null;
// newUser.setUserId(userId);
// newUser.setEmail(email);
// newUser.setFirstName(firstName);
// newUser.setLastName(lastName);
// newUser.setAccessToken(accessTokenString);
//
// return ResponseEntity.ok(userService.getUserbyEmail(email).switchIfEmpty(userService.createUser(newUser)));
// } else {
// return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
// }
String idTokenString = requestBody.getIdToken();
User newUser = new User(requestBody.getUserId(), requestBody.getEmail(), requestBody.getFirstName(), requestBody.getLastName(), requestBody.getAccessToken());
Mono<Boolean> response = userService.verifyToken(idTokenString);
Mono<User> newUserMono = response.flatMap(res-> {
if(res){
return userService.createUser(newUser);
}else{
return Mono.empty();
}
});
return ResponseEntity.ok(newUserMono);
}
} }
package com.nisum.ecomservice.model;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@AllArgsConstructor
public class UserRequestBody {
String idToken;
String userId;
String email;
String firstName;
String lastName;
String accessToken;
}
package com.nisum.ecomservice.repository; package com.nisum.ecomservice.repository;
import com.nisum.ecomservice.model.User; import com.nisum.ecomservice.model.User;
import org.springframework.data.mongodb.repository.Query;
import org.springframework.data.mongodb.repository.ReactiveMongoRepository; import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import reactor.core.publisher.Mono;
public interface UserRepository extends ReactiveMongoRepository<User, String> { public interface UserRepository extends ReactiveMongoRepository<User, String> {
@Query("SELECT u from User u where u.email= $email")
Mono<User> findUserbyEmail(String email);
} }
...@@ -3,18 +3,45 @@ package com.nisum.ecomservice.service; ...@@ -3,18 +3,45 @@ package com.nisum.ecomservice.service;
import com.nisum.ecomservice.model.User; import com.nisum.ecomservice.model.User;
import com.nisum.ecomservice.repository.UserRepository; import com.nisum.ecomservice.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@Service @Service
public class UserService { public class UserService {
private WebClient webClient;
@Autowired @Autowired
private UserRepository userRepository; private UserRepository userRepository;
public Flux<User> getUsers() { public Flux<User> getUsers() {
return userRepository.findAll(); return userRepository.findAll();
} }
public Mono<User> createUser(User user) {
return userRepository.save(user);
}
public Mono<User> getUserbyEmail(String email){
return userRepository.findUserbyEmail(email);
}
public Mono<Boolean> verifyToken(String token){
return WebClient
.builder()
.build()
.get()
.uri("https://www.googleapis.com/oauth2/v3/tokeninfo?id_token={token}", token)
.exchangeToMono(clientResponse -> {
if(clientResponse.statusCode().is2xxSuccessful()){
return Mono.just(Boolean.TRUE);
}else {
return Mono.just(Boolean.FALSE);
}
});
}
} }
REACT_APP_GOOGLE_CLIENT_ID=925243198137-vco98nrjenavrk0n00dvloblpe205vst
REACT_APP_GOOGLE_SERCRET=hnQt949bODSsvriMfi2lDKdm
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -8,9 +8,12 @@ ...@@ -8,9 +8,12 @@
"@testing-library/user-event": "^12.1.10", "@testing-library/user-event": "^12.1.10",
"animate.css": "^4.1.1", "animate.css": "^4.1.1",
"axios": "^0.21.1", "axios": "^0.21.1",
"bootstrap": "^5.0.0",
"jquery": "^3.6.0", "jquery": "^3.6.0",
"react": "^17.0.2", "react": "^17.0.2",
"react-bootstrap": "^1.5.2",
"react-dom": "^17.0.2", "react-dom": "^17.0.2",
"react-google-login": "^5.2.2",
"react-redux": "^7.2.4", "react-redux": "^7.2.4",
"react-router-dom": "^5.2.0", "react-router-dom": "^5.2.0",
"react-scripts": "4.0.3", "react-scripts": "4.0.3",
......
// import {postUser} from '../util/session-api-util'
export const SET_CURRENT_USER = "SET_CURRENT_USER"
export const LOGOUT_USER = "LOGOUT_USER"
export const setCurrentUser = () => {
return {type: SET_CURRENT_USER}
}
export const logoutUser = () => {
return {type: LOGOUT_USER}
}
// export const login = (user) => dispatch => {
// return postUser(user).then((response)=>
// dispatch(setCurrentUser(response))
// )
// }
export const login = () => {
return (dispatch) => {
return dispatch(setCurrentUser());
};
};
export const logOut = () => {
return (dispatch) => {
return dispatch(logoutUser());
};
};
\ No newline at end of file
import { connect } from 'react-redux';
import Header from './header';
const mSTP = state => ({
});
const mDTP = dispatch => ({
});
export default connect(mSTP, mDTP)(Header);
\ No newline at end of file
import React, { Component } from 'react'
import Nav from 'react-bootstrap/Nav'
import Navbar from 'react-bootstrap/Navbar'
import NavDropdown from 'react-bootstrap/NavDropdown'
import Session from '../session/session-container'
export default class Header extends Component {
constructor(props) {
super(props)
this.state = {}
}
render() {
return (
<div>
<Navbar collapseOnSelect expand="lg" bg="primary" variant="dark">
<Navbar.Brand href="#home">Ascend Ecommerce</Navbar.Brand>
<Navbar.Toggle aria-controls="responsive-navbar-nav" />
<Navbar.Collapse id="responsive-navbar-nav">
<Nav >
<Navbar.Text>
Hello Guest!
</Navbar.Text>
</Nav>
<Nav className="ms-auto">
<Session />
<Nav.Link>
Cart
</Nav.Link>
</Nav>
</Navbar.Collapse>
</Navbar>
</div>
)
}
}
import '../../resources/stylesheets/product-market.css'; import '../../resources/stylesheets/product-market.css';
import React, { Component } from 'react' import React, { Component } from 'react'
import Header from '../Header/header-container'
export default class ProductMarket extends Component { export default class ProductMarket extends Component {
constructor(props) { constructor(props) {
...@@ -16,6 +17,7 @@ export default class ProductMarket extends Component { ...@@ -16,6 +17,7 @@ export default class ProductMarket extends Component {
render() { render() {
return ( return (
<div> <div>
<Header />
{this.props.products.map(prod => { {this.props.products.map(prod => {
return ( return (
<div key={ prod.sku }> <div key={ prod.sku }>
......
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import Session from './session'; import Session from './session';
import {login, logOut} from '../../actions/session_actions'
const mSTP = state => ({ const mSTP = state => ({
currentUser: state.user
}); });
const mDTP = dispatch => ({ const mDTP = dispatch => ({
login: () => dispatch(login()),
logOut: () => dispatch(logOut())
}); });
export default connect(mSTP, mDTP)(Session); export default connect(mSTP, mDTP)(Session);
\ No newline at end of file
import React, { Component } from 'react' import React, { Component } from 'react'
import { GoogleLogin, GoogleLogout } from 'react-google-login';
const clientId = `${process.env.REACT_APP_GOOGLE_CLIENT_ID}.apps.googleusercontent.com`;
export default class Session extends Component { export default class Session extends Component {
constructor(props) { constructor(props) {
super(props) super(props)
this.state = {} this.loginSuccess = this.loginSuccess.bind(this)
this.loginFailed = this.loginFailed.bind(this)
this.logOutSuccess = this.logOutSuccess.bind(this)
}
loginSuccess = (response) => {
console.log('Login Success: currentUser:', response);
this.props.login()
}
loginFailed = (response) => {
console.log('Login failed: res:', response);
}
logOutSuccess = (response) => {
console.log('Logout made successfully');
this.props.logOut()
} }
render() { render() {
return ( return (
<div> <div>
This is the Session component {this.props.currentUser === null ?
<GoogleLogin
clientId={clientId}
buttonText="Login"
onSuccess={this.loginSuccess}
onFailure={this.loginFailed}
cookiePolicy={'single_host_origin'}
/> : <GoogleLogout
clientId={clientId}
buttonText="Logout"
onLogoutSuccess={this.logOutSuccess}
></GoogleLogout>
}
</div> </div>
) )
} }
......
...@@ -2,6 +2,7 @@ import React from 'react'; ...@@ -2,6 +2,7 @@ import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import configureStore from './store/store' import configureStore from './store/store'
import Root from './components/root' import Root from './components/root'
import 'bootstrap/dist/css/bootstrap.css'
document.addEventListener("DOMContentLoaded", () => { document.addEventListener("DOMContentLoaded", () => {
let store = configureStore(); let store = configureStore();
......
import { combineReducers } from 'redux'; import { combineReducers } from 'redux';
import productsReducer from './products_reducer'; import productsReducer from './products_reducer';
import userReducer from './user_reducer'
const rootReducer = combineReducers({ const rootReducer = combineReducers({
market: productsReducer market: productsReducer,
user: userReducer,
}); });
export default rootReducer; export default rootReducer;
\ No newline at end of file
import {SET_CURRENT_USER, LOGOUT_USER} from '../actions/session_actions'
const initialState = {currentUser: null}
const userReducer = (state = initialState, action) => {
Object.freeze(state);
let newState = Object.assign({}, state);
switch (action.type) {
case SET_CURRENT_USER:
return newState.currentUser = { emailAddress: 'fakeEmail@123'};
case LOGOUT_USER:
return newState.currentUser = null;
default:
return state;
}
}
export default userReducer;
import axios from 'axios';
// export const postUser = (user) => {
// return currentUser
// }
// export const postLogOutUser = (user) => {
// return axios.post("/api/user", user)
// }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment