Skip to content
Snippets Groups Projects
Commit 4eaf78b0 authored by Sarthak Shrivastava's avatar Sarthak Shrivastava
Browse files

Added 404 support, build end points for roster, added buttons for org view page.

parent c26c2fe3
No related branches found
No related tags found
No related merge requests found
Showing
with 354 additions and 8 deletions
......@@ -16,6 +16,8 @@ import useToken from "./components/useToken";
import AccountInformation from "./components/user/AccountInformation";
import PrivateRoutes from "./routes/PrivateRoutes";
import MyOrganizations from "./components/myorg/MyOrganizations";
import OrganizationDetails from "./components/myorg/OrganizationDetails";
import NotFound from "./components/error/NotFound";
function App() {
// const [token, setToken] = useState();
......@@ -49,6 +51,13 @@ function App() {
<Route element={<PrivateRoutes token={token} />}>
<Route path="/myorganizations" element={<MyOrganizations token={token}/>} />
</Route>
<Route element={<PrivateRoutes token={token} />}>
<Route path="/organizations/:orgId" element={<OrganizationDetails token={token}/> } />
</Route>
<Route path='*' element={<NotFound />}/>
<Route path='/404' element={<NotFound />}/>
{/*<Route path="/organizations/:orgId" element={<OrganizationDetails token={token}/>}>*/}
{/*</Route>*/}
<Route
path="/listallorganizations"
element={<ListAllOrganizations />}
......
.not-found-container {
text-align: center;
margin-top: 50px;
}
h1 {
font-size: 24px;
}
p {
font-size: 16px;
margin-bottom: 20px;
}
/* Change Link to a for proper styling */
a {
display: block;
margin-bottom: 10px;
font-size: 18px;
text-decoration: none;
color: #3498db; /* Change color to your preference */
}
a:hover {
text-decoration: underline;
}
import { Link } from "react-router-dom";
import './NotFound.css'
export default function NotFound() {
return (
<div className="not-found-container">
<h1>Oops! You seem to be lost.</h1>
<p>Here are some helpful links:</p>
<Link to='/'>Home</Link>
<Link to='/login'>Login</Link>
<Link to='/register'>Register</Link>
</div>
)
}
\ No newline at end of file
......@@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react';
import Axios from 'axios';
import './MyOrganization.css'
import PropTypes from "prop-types";
import {Link} from "react-router-dom";
const MyOrganizations = ({ token }) => {
const [organizations, setOrganizations] = useState([]);
......@@ -32,9 +33,9 @@ const MyOrganizations = ({ token }) => {
<ul>
{organizations.map((org) => (
<li key={org.orgId} className="organization-item">
{/*<Link to={`/organization/${org.orgId}`}>*/}
<Link to={`/organizations/${org.orgId}`}>
<h3>{org.name}</h3>
{/*</Link>*/}
</Link>
<p>Category: {org.category}</p>
<p>Members: {org.memberCount}</p>
{/* Add more information as needed */}
......
.organization-details {
text-align: center;
margin-top: 50px;
}
h2 {
font-size: 24px;
margin-bottom: 20px;
}
p {
font-size: 16px;
margin-bottom: 10px;
}
/* Center organization information */
.organization-info {
max-width: 600px;
margin: 0 auto;
}
.button-container {
display: flex;
justify-content: center;
margin-top: 20px;
}
.blue-button {
background-color: #3498db;
color: #fff;
border: 1px solid #2980b9;
padding: 8px 16px; /* Adjusted padding for smaller buttons */
margin: 0 10px; /* Adjusted margin */
font-size: 14px; /* Adjusted font size */
cursor: pointer;
max-width: 10%;
}
.blue-button:hover {
background-color: #2980b9;
}
import React, { useState, useEffect } from 'react';
import {useParams, Navigate, useNavigate } from 'react-router-dom';
import Axios from 'axios';
import './OrganizationDetails.css'
const OrganizationDetails = ({token}) => {
const { orgId } = useParams();
const [organization, setOrganization] = useState(null);
const navigate = useNavigate();
useEffect(() => {
const fetchOrganizationDetails = async () => {
try {
console.log(token);
const response = await Axios.post(`http://localhost:8080/myorg/user/org`, {
jwt: token.jwt,
orgId: orgId
});
if (response.data.result === 'success') {
setOrganization(response.data.data);
} else {
console.error('Error fetching organization details');
navigate('/404');
}
} catch (error) {
console.error('Error fetching organization details:', error);
navigate('/404');
}
};
fetchOrganizationDetails();
}, [orgId]);
if (!organization) {
return <div>Loading...</div>;
}
return (
<div className="organization-details">
<div className="organization-info">
<h2>{organization.name}</h2>
<p>Email: {organization.email}</p>
<p>Owner Email: {organization.ownerEmail}</p>
<p>Description: {organization.description}</p>
<p>Member Count: {organization.memberCount}</p>
</div>
{/* Buttons at the bottom */}
<div className="button-container">
<button className="blue-button">Roster</button>
<button className="blue-button">Requests</button>
<button className="blue-button">Items</button>
<button className="blue-button">Listings</button>
</div>
</div>
);
};
export default OrganizationDetails;
......@@ -53,6 +53,24 @@ INSERT INTO ORGANIZATION_ROSTER (user_email, organization_id, type)
SELECT owner_email, organization_id, 'OWNER'
FROM ORGANIZATION;
INSERT INTO ORGANIZATION_ROSTER (user_email, organization_id, type)
VALUES
('johnsmith@example.com', 2, 'MEMBER'),
('johnsmith@example.com', 4, 'MANAGER'),
('alicedoe@example.com', 5, 'MEMBER'),
('emilyjohnson@example.com', 2, 'MEMBER');
UPDATE ORGANIZATION o
SET member_count = (
SELECT COUNT(DISTINCT user_email)
FROM ORGANIZATION_ROSTER
WHERE organization_id = o.organization_id
)
WHERE member_count != o.member_count
;
SELECT * FROM ORGANIZATION_ROSTER WHERE ORGANIZATION_ROSTER.user_email LIKE 'emilyjohnson@example.com';
SELECT DISTINCT o.*
FROM ORGANIZATION o
......
......@@ -64,7 +64,7 @@ public class MainController {
}
@PostMapping(path = "/user")
public @ResponseBody User getUser(@RequestBody Map<String, String> json)
public @ResponseBody User getUser(@RequestBody Map<String, Object> json)
{
User found = new User();
AuthController au = new AuthController();
......@@ -85,7 +85,7 @@ public class MainController {
@PostMapping(path = "/delete")
@ResponseBody
public User deleteUser(@RequestBody Map<String, String> json)
public User deleteUser(@RequestBody Map<String, Object> json)
{
User found = new User();
AuthController au = new AuthController();
......
......@@ -61,13 +61,13 @@ public class AuthController {
//also create a verification end point to verify their access to this one org.
@PostMapping(path="/verify")
public @ResponseBody Map<String, String> verify(@RequestBody Map<String, String> json)
public @ResponseBody Map<String, String> verify(@RequestBody Map<String, Object> json)
{
Map<String, String> res = new HashMap<String, String>();
System.out.println(json.entrySet());
if (json.containsKey("jwt"))
{
Claims claim = JWT.decodeJWT(json.get("jwt"));
Claims claim = JWT.decodeJWT((String) json.get("jwt")); //this will be a string
if (claim != null)
{
res.put("user", claim.getSubject());
......
......@@ -9,7 +9,9 @@ import jakarta.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@Repository
......@@ -32,6 +34,50 @@ public class MyOrgRosterRepository implements OrgRosterRepository{
return organizations;
}
@Transactional
public Map<String, Object> findUserOrg(String userEmail, Integer orgId )
{
Map<String, Object> result = new HashMap<>();
try {
String nativeQuery = "SELECT r.type, o.* " +
"FROM ORGANIZATION_ROSTER r " +
"JOIN ORGANIZATION o ON r.organization_id = o.organization_id " +
"WHERE r.user_email = :userEmail AND r.organization_id = :orgId";
OrgUserType queryResult = (OrgUserType) entityManager.createNativeQuery(nativeQuery, OrgUserType.class)
.setParameter("userEmail", userEmail)
.setParameter("orgId", orgId)
.getSingleResult();
if (queryResult != null) {
result.put("result", "success");
result.put("type", queryResult.getType());
result.put("orgId", orgId);
result.put("data", queryResult);
return result;
}
result.put("result", "failure");
}
catch (Exception e)
{
result.put("result", "failure");
//result.put("exception", e.getStackTrace());
}
return result;
}
@Transactional
public List<Object> getRoster(Integer orgId)
{
String nativeQuery = "SELECT u.fname, u.lname, r.type" +
" FROM ORGANIZATION_ROSTER r" +
" JOIN USER u ON r.user_email=u.email" +
" WHERE r.organization_id = :orgId";
return(entityManager.createNativeQuery(nativeQuery)
.setParameter("orgId", orgId)
.getResultList());
}
@Override
public <S extends OrganizationRoster> S save(S entity) {
......
......@@ -3,11 +3,14 @@ package com.example.accessingdatamysql.myorg;
import com.example.accessingdatamysql.User;
import com.example.accessingdatamysql.UserRepository;
import com.example.accessingdatamysql.auth.AuthController;
import com.example.accessingdatamysql.auth.JWT;
import com.example.accessingdatamysql.org.Organization;
import jakarta.persistence.criteria.CriteriaBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
......@@ -32,7 +35,7 @@ public class OrgRosterController {
}
@PostMapping(path="/user")
public @ResponseBody Map<String, Object> getUsersOrgs(@RequestBody Map<String, String> json)
public @ResponseBody Map<String, Object> getUsersOrgs(@RequestBody Map<String, Object> json)
{
Map<String, Object> response = new HashMap<>();
User found = new User();
......@@ -53,5 +56,53 @@ public class OrgRosterController {
response.put("data", myOrgRosterRepository.findUserOrgs(res.get("user")));
return response;
}
@PostMapping(path="/user/org")
public @ResponseBody Map<String, Object> getUserOrg(@RequestBody Map<String, Object> json)
{
Map<String, Object> response = new HashMap<>();
System.out.println(json.get("orgId"));
if (!json.containsKey("orgId"))
{
response.put("result", "failed = no orgId provided bad request");
return response;
}
User found = new User();
AuthController au = new AuthController();
Map<String, String> res = au.verify(json); // if the jwt token could not be verified
if (res.containsKey("login") && res.get("login").equals("failed"))
{
response.put("result", "failed = bad token or bad request");
return response;
}
Optional<User> usr = userRepository.findById(res.get("user"));
if (!usr.isPresent())
{
response.put("result", "failed = user not found");
return response;
}
if (json.get("orgId") instanceof Integer)
return myOrgRosterRepository.findUserOrg(usr.get().getEmail(), (Integer) json.get("orgId"));
return myOrgRosterRepository.findUserOrg(usr.get().getEmail(), Integer.parseInt((String) json.get("orgId")));
}
@PostMapping(path="/user/roster")
public @ResponseBody Map<String, Object> getRoster(@RequestBody Map<String, Object> json)
{
Map<String, Object> map = getUserOrg(json);
Map<String, Object> result = new HashMap<>();
//above, verify that this user is even supposed to see this information
if (map.get("result").equals("success"))
{
result.put("result", "success");
result.put("type", map.get("type")); //tell the client what type this user is so they can render buttons for the roster
System.out.println(map.get("orgId"));
result.put("roster", myOrgRosterRepository.getRoster((Integer) json.get("orgId")));
return result;
}
result.put("result", "failure");
return result;
}
}
package com.example.accessingdatamysql.myorg;
import com.example.accessingdatamysql.org.Organization;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.Id;
@Entity
public class OrgUserType {
@Id
private String ownerEmail;
@Enumerated(EnumType.STRING)
private Organization.Category category;
private Integer memberCount;
private String name;
private String email;
private String description;
@Enumerated(EnumType.STRING)
private OrganizationRoster.Type type;
public String getOwnerEmail() {
return ownerEmail;
}
public void setOwnerEmail(String ownerEmail) {
this.ownerEmail = ownerEmail;
}
public Organization.Category getCategory() {
return category;
}
public void setCategory(Organization.Category category) {
this.category = category;
}
public Integer getMemberCount() {
return memberCount;
}
public void setMemberCount(Integer memberCount) {
this.memberCount = memberCount;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public OrganizationRoster.Type getType() {
return type;
}
public void setType(OrganizationRoster.Type type) {
this.type = type;
}
}
......@@ -7,7 +7,7 @@ import jakarta.persistence.*;
@Table(name = "ORGANIZATION")
public class Organization {
enum Category {
public enum Category {
ACADEMIC,
RECREATION,
TECHNOLOGY,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment