diff --git a/server/database/app.js b/server/database/app.js index f2517ed0355..81e08ea6567 100644 --- a/server/database/app.js +++ b/server/database/app.js @@ -1,39 +1,36 @@ +/* jshint esversion: 8 */ const express = require('express'); const mongoose = require('mongoose'); const fs = require('fs'); -const cors = require('cors') -const app = express() +const cors = require('cors'); +const app = express(); const port = 3030; -app.use(cors()) +app.use(cors()); app.use(require('body-parser').urlencoded({ extended: false })); const reviews_data = JSON.parse(fs.readFileSync("reviews.json", 'utf8')); const dealerships_data = JSON.parse(fs.readFileSync("dealerships.json", 'utf8')); -mongoose.connect("mongodb://mongo_db:27017/",{'dbName':'dealershipsDB'}); - +mongoose.connect("mongodb://mongo_db:27017/", { 'dbName': 'dealershipsDB' }); const Reviews = require('./review'); - const Dealerships = require('./dealership'); try { - Reviews.deleteMany({}).then(()=>{ - Reviews.insertMany(reviews_data['reviews']); + Reviews.deleteMany({}).then(() => { + Reviews.insertMany(reviews_data.reviews); }); - Dealerships.deleteMany({}).then(()=>{ - Dealerships.insertMany(dealerships_data['dealerships']); + Dealerships.deleteMany({}).then(() => { + Dealerships.insertMany(dealerships_data.dealerships); }); - } catch (error) { - res.status(500).json({ error: 'Error fetching documents' }); + console.error(error); } - // Express route to home app.get('/', async (req, res) => { - res.send("Welcome to the Mongoose API") + res.send("Welcome to the Mongoose API"); }); // Express route to fetch all reviews @@ -49,7 +46,7 @@ app.get('/fetchReviews', async (req, res) => { // Express route to fetch reviews by a particular dealer app.get('/fetchReviews/dealer/:id', async (req, res) => { try { - const documents = await Reviews.find({dealership: req.params.id}); + const documents = await Reviews.find({ dealership: req.params.id }); res.json(documents); } catch (error) { res.status(500).json({ error: 'Error fetching documents' }); @@ -58,7 +55,6 @@ app.get('/fetchReviews/dealer/:id', async (req, res) => { // Express route to fetch all dealerships app.get('/fetchDealers', async (req, res) => { - try { const documents = await Dealerships.find(); res.json(documents); @@ -69,7 +65,6 @@ app.get('/fetchDealers', async (req, res) => { // Express route to fetch Dealers by a particular state app.get('/fetchDealers/:state', async (req, res) => { - try { const documents = await Dealerships.find({ state: req.params.state }); res.json(documents); @@ -80,44 +75,40 @@ app.get('/fetchDealers/:state', async (req, res) => { // Express route to fetch dealer by a particular id app.get('/fetchDealer/:id', async (req, res) => { - try { - // We search using the custom numeric id field from your JSON file structure const document = await Dealerships.findOne({ id: req.params.id }); - if (!document) { return res.status(404).json({ error: 'Dealership not found' }); } - res.json(document); } catch (error) { res.status(500).json({ error: 'Error fetching dealership by id' }); } }); -//Express route to insert review +// Express route to insert review app.post('/insert_review', express.raw({ type: '*/*' }), async (req, res) => { - data = JSON.parse(req.body); - const documents = await Reviews.find().sort( { id: -1 } ) - let new_id = documents[0]['id']+1 + const data = JSON.parse(req.body); + const documents = await Reviews.find().sort({ id: -1 }); + let new_id = documents[0].id + 1; const review = new Reviews({ - "id": new_id, - "name": data['name'], - "dealership": data['dealership'], - "review": data['review'], - "purchase": data['purchase'], - "purchase_date": data['purchase_date'], - "car_make": data['car_make'], - "car_model": data['car_model'], - "car_year": data['car_year'], - }); + "id": new_id, + "name": data.name, + "dealership": data.dealership, + "review": data.review, + "purchase": data.purchase, + "purchase_date": data.purchase_date, + "car_make": data.car_make, + "car_model": data.car_model, + "car_year": data.car_year + }); try { const savedReview = await review.save(); res.json(savedReview); } catch (error) { - console.log(error); + console.log(error); res.status(500).json({ error: 'Error inserting review' }); } }); diff --git a/server/database/dealership.js b/server/database/dealership.js index b10d6b47304..0458592cebd 100644 --- a/server/database/dealership.js +++ b/server/database/dealership.js @@ -1,13 +1,14 @@ +/* jshint esversion: 6 */ const mongoose = require('mongoose'); const Schema = mongoose.Schema; const dealerships = new Schema({ - id: { + id: { type: Number, - required: true, - }, - city: { + required: true + }, + city: { type: String, required: true }, @@ -32,7 +33,7 @@ const dealerships = new Schema({ required: true }, short_name: { - type: String, + type: String }, full_name: { type: String, diff --git a/server/database/inventory.js b/server/database/inventory.js index 2c22fd092ce..85d93c8cbd5 100644 --- a/server/database/inventory.js +++ b/server/database/inventory.js @@ -1,30 +1,31 @@ +/* jshint esversion: 6 */ const { Int32 } = require('mongodb'); const mongoose = require('mongoose'); const Schema = mongoose.Schema; const cars = new Schema({ -dealer_id: { + dealer_id: { type: Number, required: true -}, -make: { + }, + make: { type: String, required: true }, -model: { + model: { type: String, required: true }, -bodyType: { + bodyType: { type: String, required: true }, -year: { + year: { type: Number, required: true }, -mileage: { + mileage: { type: Number, required: true } diff --git a/server/database/review.js b/server/database/review.js index 4759725a3a3..c516561604c 100644 --- a/server/database/review.js +++ b/server/database/review.js @@ -1,19 +1,20 @@ +/* jshint esversion: 6 */ const mongoose = require('mongoose'); const Schema = mongoose.Schema; const reviews = new Schema({ - id: { + id: { type: Number, - required: true, - }, - name: { + required: true + }, + name: { type: String, required: true }, dealership: { type: Number, - required: true, + required: true }, review: { type: String, @@ -38,7 +39,7 @@ const reviews = new Schema({ car_year: { type: Number, required: true - }, + } }); module.exports = mongoose.model('reviews', reviews); diff --git a/server/djangoapp/models.py b/server/djangoapp/models.py index 023e87c53bc..47e7d1ca3f2 100644 --- a/server/djangoapp/models.py +++ b/server/djangoapp/models.py @@ -1,5 +1,4 @@ from django.db import models -from django.utils.timezone import now from django.core.validators import MaxValueValidator, MinValueValidator @@ -14,27 +13,29 @@ def __str__(self): return self.name # Return the name as the string representation - # Create a Car Model model `class CarModel(models.Model):`: class CarModel(models.Model): - car_make = models.ForeignKey(CarMake, on_delete=models.CASCADE) # Many-to-One relationship - dealer_id = models.IntegerField() # <- instructions asked this missing field + # Many-to-One relationship + car_make = models.ForeignKey(CarMake, on_delete=models.CASCADE) + dealer_id = models.IntegerField() name = models.CharField(max_length=100) - + CAR_TYPES = [ ('SEDAN', 'Sedan'), ('SUV', 'SUV'), ('WAGON', 'Wagon'), ] type = models.CharField(max_length=10, choices=CAR_TYPES, default='SUV') - - # Updated default to 2026 and MaxValueValidator to 2026 to avoid validation errors - year = models.IntegerField(default=2026, + + # Updated default to 2026 to avoid validation errors + year = models.IntegerField( + default=2026, validators=[ MaxValueValidator(2026), MinValueValidator(2015) - ]) + ] + ) def __str__(self): - return self.car_make.name + " " + self.name # Returns full name (e.g. "Toyota Corolla") + return self.car_make.name + " " + self.name diff --git a/server/djangoapp/populate.py b/server/djangoapp/populate.py index 1720d075882..7a3ff2199af 100644 --- a/server/djangoapp/populate.py +++ b/server/djangoapp/populate.py @@ -1,15 +1,16 @@ from .models import CarMake, CarModel + def initiate(): # 1. Create CarMake instances makes = { - "NISSAN": "Japanese", "Mercedes": "German", + "NISSAN": "Japanese", "Mercedes": "German", "Audi": "German", "Kia": "Korean", "Toyota": "Japanese" } make_objs = {} for name, tech in makes.items(): make_objs[name] = CarMake.objects.create( - name=name, + name=name, description=f"Great cars. {tech} technology" ) @@ -34,6 +35,7 @@ def initiate(): for name, m_type, year, make in models: CarModel.objects.create( - name=name, type=m_type, year=year, + name=name, type=m_type, year=year, car_make=make, dealer_id=1 ) + diff --git a/server/djangoapp/restapis.py b/server/djangoapp/restapis.py index 11dd03ecb6a..e8303fb76b2 100644 --- a/server/djangoapp/restapis.py +++ b/server/djangoapp/restapis.py @@ -10,28 +10,28 @@ 'sentiment_analyzer_url', default="http://localhost:5050/") + # def get_request(endpoint, **kwargs): def get_request(endpoint, **kwargs): params = "" - if(kwargs): - for key,value in kwargs.items(): - params=params+key+"="+value+"&" + if kwargs: + for key, value in kwargs.items(): + params = params + key + "=" + value + "&" - request_url = backend_url+endpoint+"?"+params + request_url = backend_url + endpoint + "?" + params print("GET from {} ".format(request_url)) try: # Call get method of requests library with URL and parameters response = requests.get(request_url) return response.json() - except: - # If any error occurs - print("Network exception occurred") + except Exception as err: + print(f"Network exception occurred: {err}") # def analyze_review_sentiments(text): def analyze_review_sentiments(text): - request_url = sentiment_analyzer_url+"analyze/"+text + request_url = sentiment_analyzer_url + "analyze/" + text try: # Call get method of requests library with URL and parameters response = requests.get(request_url) @@ -42,11 +42,11 @@ def analyze_review_sentiments(text): def post_review(data_dict): - request_url = backend_url+"/insert_review" + request_url = backend_url + "/insert_review" try: - response = requests.post(request_url,json=data_dict) + response = requests.post(request_url, json=data_dict) print(response.json()) return response.json() - except: - print("Network exception occurred") + except Exception as err: + print(f"Network exception occurred: {err}") diff --git a/server/djangoapp/urls.py b/server/djangoapp/urls.py index 82dd9c6c412..aa18efae685 100644 --- a/server/djangoapp/urls.py +++ b/server/djangoapp/urls.py @@ -15,16 +15,32 @@ path(route='logout', view=views.logout_request, name='logout'), # path for get cars - path(route='get_cars', view=views.get_cars, name ='getcars'), + path(route='get_cars', view=views.get_cars, name='getcars'), # path for dealer reviews view - path(route='get_dealers', view=views.get_dealerships, name='get_dealers'), - path(route='get_dealers/', view=views.get_dealerships, name='get_dealers_by_state'), - - path(route='dealer/', view=views.get_dealer_details, name='dealer_details'), - path(route='reviews/dealer//', view=views.get_dealer_reviews, name='dealer_reviews'), + path( + route='get_dealers', + view=views.get_dealerships, + name='get_dealers' + ), + path( + route='get_dealers/', + view=views.get_dealerships, + name='get_dealers_by_state' + ), + + path( + route='dealer/', + view=views.get_dealer_details, + name='dealer_details' + ), + path( + route='reviews/dealer//', + view=views.get_dealer_reviews, + name='dealer_reviews' + ), # path for add a review view path(route='add_review', view=views.add_review, name='add_review'), - ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + diff --git a/server/djangoapp/views.py b/server/djangoapp/views.py index 5114a9daca0..565cf637534 100644 --- a/server/djangoapp/views.py +++ b/server/djangoapp/views.py @@ -1,17 +1,8 @@ -# Uncomment the required imports before adding the code - -from django.shortcuts import render -from django.http import HttpResponseRedirect, HttpResponse -from django.contrib.auth.models import User -from django.shortcuts import get_object_or_404, render, redirect -from django.contrib.auth import logout -from django.contrib import messages -from datetime import datetime - -from django.http import JsonResponse -from django.contrib.auth import login, authenticate import logging import json +from django.contrib.auth.models import User +from django.contrib.auth import logout, login, authenticate +from django.http import JsonResponse from django.views.decorators.csrf import csrf_exempt from .models import CarMake, CarModel @@ -19,7 +10,6 @@ from .restapis import get_request, analyze_review_sentiments, post_review - # Get an instance of a logger logger = logging.getLogger(__name__) @@ -42,18 +32,18 @@ def login_user(request): data = {"userName": username, "status": "Authenticated"} return JsonResponse(data) + # Create a `logout_request` view to handle sign out request def logout_request(request): logout(request) - data = {"userName" : "" } + data = {"userName": ""} return JsonResponse(data) + # Create a `registration` view to handle sign up request @csrf_exempt def registration(request): - context = {} - - # Load JSON data from the request body + # Load JSON data from the request body data = json.loads(request.body) username = data['userName'] password = data['password'] @@ -61,59 +51,65 @@ def registration(request): last_name = data['lastName'] email = data['email'] username_exist = False - email_exist = False try: # Check if user already exists User.objects.get(username=username) username_exist = True - except: + except Exception as err: # If not, simply log this is a new user - logger.debug("{} is new user".format(username)) + logger.debug(f"{username} is new user: {err}") # If it is a new user if not username_exist: # Create user in auth_user table - user = User.objects.create_user(username=username, first_name=first_name, last_name=last_name,password=password, email=email) + user = User.objects.create_user( + username=username, + first_name=first_name, + last_name=last_name, + password=password, + email=email + ) # Login the user and redirect to list page login(request, user) - data = {"userName":username,"status":"Authenticated"} + data = {"userName": username, "status": "Authenticated"} return JsonResponse(data) - else : - data = {"userName":username,"error":"Already Registered"} + else: + data = {"userName": username, "error": "Already Registered"} return JsonResponse(data) def get_cars(request): count = CarMake.objects.filter().count() print(count) - if(count == 0): + if count == 0: initiate() car_models = CarModel.objects.select_related('car_make') cars = [] for car_model in car_models: - cars.append({"CarModel": car_model.name, "CarMake": car_model.car_make.name}) - return JsonResponse({"CarModels":cars}) + cars.append({ + "CarModel": car_model.name, + "CarMake": car_model.car_make.name + }) + return JsonResponse({"CarModels": cars}) - -# # Update the `get_dealerships` view to render the index page with -# a list of dealerships -#Update the `get_dealerships` render list of dealerships all by default, particular state if state is passed +# Update the `get_dealerships` render list of dealerships all by default, +# particular state if state is passed def get_dealerships(request, state="All"): - if(state == "All"): + if state == "All": endpoint = "/fetchDealers" else: - endpoint = "/fetchDealers/"+state + endpoint = "/fetchDealers/" + state dealerships = get_request(endpoint) - return JsonResponse({"status":200,"dealers":dealerships}) + return JsonResponse({"status": 200, "dealers": dealerships}) # Create a `get_dealer_reviews` view to render the reviews of a dealer def get_dealer_reviews(request, dealer_id): - if(dealer_id): - endpoint = "/fetchReviews/dealer/"+str(dealer_id) + if dealer_id: + endpoint = "/fetchReviews/dealer/" + str(dealer_id) reviews = get_request(endpoint) - + # Safe check: Only run sentiment loop if reviews is a valid list if isinstance(reviews, list): for review_detail in reviews: @@ -123,35 +119,36 @@ def get_dealer_reviews(request, dealer_id): review_detail['sentiment'] = response['sentiment'] else: review_detail['sentiment'] = "neutral" - return JsonResponse({"status":200, "reviews": reviews}) + return JsonResponse({"status": 200, "reviews": reviews}) else: # If no reviews exist, return a safe empty array to React - return JsonResponse({"status":200, "reviews": []}) + return JsonResponse({"status": 200, "reviews": []}) else: - return JsonResponse({"status":400, "message": "Bad Request"}) + return JsonResponse({"status": 400, "message": "Bad Request"}) # Create a `get_dealer_details` view to render the dealer details def get_dealer_details(request, dealer_id): - if(dealer_id): - endpoint = "/fetchDealer/"+str(dealer_id) + if dealer_id: + endpoint = "/fetchDealer/" + str(dealer_id) dealership = get_request(endpoint) - return JsonResponse({"status":200,"dealer":dealership}) + return JsonResponse({"status": 200, "dealer": dealership}) else: - return JsonResponse({"status":400,"message":"Bad Request"}) + return JsonResponse({"status": 400, "message": "Bad Request"}) @csrf_exempt def add_review(request): - if(request.user.is_anonymous == False): + if not request.user.is_anonymous: data = json.loads(request.body) try: - response = post_review(data) - return JsonResponse({"status":200}) - except: - return JsonResponse({"status":401,"message":"Error in posting review"}) + post_review(data) + return JsonResponse({"status": 200}) + except Exception as err: + return JsonResponse({ + "status": 401, + "message": f"Error in posting review: {err}" + }) else: - return JsonResponse({"status":403,"message":"Unauthorized"}) - - + return JsonResponse({"status": 403, "message": "Unauthorized"}) diff --git a/server/djangoproj/settings.py b/server/djangoproj/settings.py index b6ec35f970e..ac8377719c9 100644 --- a/server/djangoproj/settings.py +++ b/server/djangoproj/settings.py @@ -22,20 +22,25 @@ # See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = "django-insecure-ccow$tz_=9%dxu4(0%^(z%nx32#s@(zt9$ih@)5l54yny)wm-0" +SECRET_KEY = ( + "django-insecure-ccow$tz_=9%dxu4(0%^(z%nx32#s@(zt9$ih@)5l54yny)wm-0" +) # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True ALLOWED_HOSTS = [ "localhost", - ".theiadockernext-1-labs-prod-theiak8s-4-tor01.proxy.cognitiveclass.ai", + ".theiadockernext-1-labs-prod-theiak8s-4-tor01.proxy.cognitiveclass.ai", ".theianext-1-labs-prod-misc-tools-us-east-0.proxy.cognitiveclass.ai", ] CSRF_TRUSTED_ORIGINS = [ - "https://rodcasio-8000.theiadockernext-1-labs-prod-theiak8s-4-tor01.proxy.cognitiveclass.ai", - "https://*.theiadockernext-1-labs-prod-theiak8s-4-tor01.proxy.cognitiveclass.ai", - "https://*.theianext-1-labs-prod-misc-tools-us-east-0.proxy.cognitiveclass.ai", + "https://rodcasio-8000.theiadockernext-1-labs-prod-theiak8s-4" + "-tor01.proxy.cognitiveclass.ai", + "https://*.theiadockernext-1-labs-prod-theiak8s-4-tor01.proxy" + ".cognitiveclass.ai", + "https://*.theianext-1-labs-prod-misc-tools-us-east-0.proxy" + ".cognitiveclass.ai", ] REST_FRAMEWORK = { @@ -100,16 +105,20 @@ AUTH_PASSWORD_VALIDATORS = [ { - "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", + "NAME": "django.contrib.auth.password_validation" + ".UserAttributeSimilarityValidator", }, { - "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", + "NAME": "django.contrib.auth.password_validation" + ".MinimumLengthValidator", }, { - "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", + "NAME": "django.contrib.auth.password_validation" + ".CommonPasswordValidator", }, { - "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", + "NAME": "django.contrib.auth.password_validation" + ".NumericPasswordValidator", }, ] diff --git a/server/djangoproj/urls.py b/server/djangoproj/urls.py index 4566f2d6c88..400ac05dfa0 100644 --- a/server/djangoproj/urls.py +++ b/server/djangoproj/urls.py @@ -29,7 +29,12 @@ path('login/', TemplateView.as_view(template_name="index.html")), path('register/', TemplateView.as_view(template_name="index.html")), path('dealers/', TemplateView.as_view(template_name="index.html")), - path('dealer/',TemplateView.as_view(template_name="index.html")), - path('postreview/',TemplateView.as_view(template_name="index.html")), - + path( + 'dealer/', + TemplateView.as_view(template_name="index.html") + ), + path( + 'postreview/', + TemplateView.as_view(template_name="index.html") + ), ] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)