Skip to content

Commit

Permalink
Merge pull request #16 from ucsb-cs156-f20/staff-channelList
Browse files Browse the repository at this point in the history
Staff channel list
  • Loading branch information
pconrad committed Nov 24, 2020
2 parents eb4624e + d1f0341 commit eb74930
Show file tree
Hide file tree
Showing 12 changed files with 506 additions and 1 deletion.
6 changes: 6 additions & 0 deletions .gitignore
@@ -1,3 +1,9 @@
# Emacs files

*~

# other files

HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
Expand Down
2 changes: 2 additions & 0 deletions javascript/src/main/App.js
Expand Up @@ -11,6 +11,7 @@ import PrivateRoute from "main/components/Auth/PrivateRoute";
import Admin from "main/pages/Admin/Admin";
import SlackUsers from "./pages/Admin/SlackUsers";
import AuthorizedRoute from "main/components/Nav/AuthorizedRoute";
import ChannelList from "main/pages/Channels/ChannelList";

function App() {
return (
Expand All @@ -20,6 +21,7 @@ function App() {
<Switch>
<AuthorizedRoute path="/admin" exact component={Admin} authorizedRoles={["admin"]} />
<AuthorizedRoute path="/admin/slackUsers" exact component={SlackUsers} authorizedRoles={["admin"]} />
<AuthorizedRoute path="/member/channels" exact component={ChannelList} authorizedRoles={["admin","member"]} />
<PrivateRoute path="/profile" component={Profile} />
<Route path="/about" component={About} />
<Route path="/" exact component={Home} />
Expand Down
21 changes: 21 additions & 0 deletions javascript/src/main/components/Channels/ChannelTable.js
@@ -0,0 +1,21 @@
import React from "react";
import BootstrapTable from 'react-bootstrap-table-next';

export default ({ channels }) => {

const columns = [{
dataField: 'name',
text: 'Name'
},{
dataField: 'purpose.value',
text: 'Purpose'
},{
dataField: 'topic.value',
text: 'Topic'
}
];

return (
<BootstrapTable keyField='id' data={channels} columns={columns} />
);
}
8 changes: 7 additions & 1 deletion javascript/src/main/components/Nav/AppNavbar.js
Expand Up @@ -15,19 +15,25 @@ function AppNavbar() {
fetchWithToken
);
const isAdmin = roleInfo && roleInfo.role.toLowerCase() === "admin";
const isMember = roleInfo && roleInfo.role.toLowerCase() === "member";

return (
<Navbar bg="dark" variant="dark">
<LinkContainer to={""}>
<Navbar.Brand data-testid="brand">Mapache Search</Navbar.Brand>
</LinkContainer>
<Nav>
{isAdmin &&
{ isAdmin &&
<NavDropdown title="Admin">
<NavDropdown.Item href="/admin">Maintain Admins</NavDropdown.Item>
<NavDropdown.Item href="/admin/slackUsers">Slack Users</NavDropdown.Item>
</NavDropdown>
}
{ (isMember || isAdmin) &&
<NavDropdown title="Channels">
<NavDropdown.Item href="/member/channels">List Channels</NavDropdown.Item>
</NavDropdown>
}
<LinkContainer to={"/about"}>
<Nav.Link>About</Nav.Link>
</LinkContainer>
Expand Down
18 changes: 18 additions & 0 deletions javascript/src/main/pages/Channels/ChannelList.js
@@ -0,0 +1,18 @@
import React from "react";
import { Jumbotron } from "react-bootstrap";
import {useAuth0} from "@auth0/auth0-react";
import { Redirect } from "react-router-dom";
import ChannelTable from "main/components/Channels/ChannelTable"
import useSWR from "swr";
import {fetchWithToken} from "main/utils/fetch";

const ChannelList = () => {
const { getAccessTokenSilently: getToken } = useAuth0();
const { data: channels } = useSWR(["/api/members/channels", getToken], fetchWithToken);

return (
<ChannelTable channels={channels || []} />
);
};

export default ChannelList;
6 changes: 6 additions & 0 deletions pom.xml
Expand Up @@ -96,6 +96,12 @@
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

<!-- https://mvnrepository.com/artifact/net.codebox/javabean-tester -->
<dependency>
<groupId>net.codebox</groupId>
<artifactId>javabean-tester</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>

<build>
Expand Down
61 changes: 61 additions & 0 deletions src/main/java/edu/ucsb/mapache/controllers/ChannelsController.java
@@ -0,0 +1,61 @@
package edu.ucsb.mapache.controllers;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import javax.validation.Valid;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import edu.ucsb.mapache.advice.AuthControllerAdvice;
import edu.ucsb.mapache.documents.Channel;
import edu.ucsb.mapache.documents.SlackUser;
import edu.ucsb.mapache.entities.Admin;
import edu.ucsb.mapache.entities.AppUser;
import edu.ucsb.mapache.repositories.AppUserRepository;
import edu.ucsb.mapache.repositories.ChannelRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/members")
public class ChannelsController {
private final Logger logger = LoggerFactory.getLogger(ChannelsController.class);

@Autowired
ChannelRepository channelRepository;

@Autowired
private AuthControllerAdvice authControllerAdvice;

private ObjectMapper mapper = new ObjectMapper();

private ResponseEntity<String> getUnauthorizedResponse(String roleRequired) throws JsonProcessingException {
Map<String, String> response = new HashMap<String, String>();
response.put("error", String.format("Unauthorized; only %s may access this resource.", roleRequired));
String body = mapper.writeValueAsString(response);
return new ResponseEntity<String>(body, HttpStatus.UNAUTHORIZED);
}

@GetMapping("/channels")
public ResponseEntity<String> getChannels(@RequestHeader("Authorization") String authorization)
throws JsonProcessingException {
if (!authControllerAdvice.getIsMember(authorization))
return getUnauthorizedResponse("member");

Iterable<Channel> channels = channelRepository.findAll();
String body = mapper.writeValueAsString(channels);

return ResponseEntity.ok().body(body);
}
}
182 changes: 182 additions & 0 deletions src/main/java/edu/ucsb/mapache/documents/Channel.java
@@ -0,0 +1,182 @@
package edu.ucsb.mapache.documents;

import java.util.List;
import java.util.Objects;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.springframework.data.mongodb.core.mapping.Document;

@Document(collection = "channels")
public class Channel {
private String id;
private String name;
private String creator;
private Boolean is_archived;
private Boolean is_general;
private List<String> members;
private ChannelTopic topic;
private ChannelPurpose purpose;

public Channel() {
}

public Channel(String id, String name, String creator, Boolean is_archived, Boolean is_general, List<String> members, ChannelTopic topic, ChannelPurpose purpose) {
this.id = id;
this.name = name;
this.creator = creator;
this.is_archived = is_archived;
this.is_general = is_general;
this.members = members;
this.topic = topic;
this.purpose = purpose;
}

public String getId() {
return this.id;
}

public void setId(String id) {
this.id = id;
}

public String getName() {
return this.name;
}

public void setName(String name) {
this.name = name;
}

public String getCreator() {
return this.creator;
}

public void setCreator(String creator) {
this.creator = creator;
}

public Boolean isIs_archived() {
return this.is_archived;
}

public Boolean getIs_archived() {
return this.is_archived;
}

public void setIs_archived(Boolean is_archived) {
this.is_archived = is_archived;
}

public Boolean isIs_general() {
return this.is_general;
}

public Boolean getIs_general() {
return this.is_general;
}

public void setIs_general(Boolean is_general) {
this.is_general = is_general;
}

public List<String> getMembers() {
return this.members;
}

public void setMembers(List<String> members) {
this.members = members;
}

public ChannelTopic getTopic() {
return this.topic;
}

public void setTopic(ChannelTopic topic) {
this.topic = topic;
}

public ChannelPurpose getPurpose() {
return this.purpose;
}

public void setPurpose(ChannelPurpose purpose) {
this.purpose = purpose;
}

@Override
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Channel)) {
return false;
}
Channel c = (Channel) o;
EqualsBuilder builder = new EqualsBuilder();
builder.append(name, c.getName());
return builder.build();
}

@Override
public int hashCode() {
return Objects.hash(name);
}

@Override
public String toString() {
return "{" +
" id='" + getId() + "'" +
", name='" + getName() + "'" +
", creator='" + getCreator() + "'" +
", is_archived='" + isIs_archived() + "'" +
", is_general='" + isIs_general() + "'" +
", members='" + getMembers() + "'" +
", topic='" + getTopic() + "'" +
", purpose='" + getPurpose() + "'" +
"}";
}


}

/*
Example of the JSON for a Channel document
{
"_id": {
"$oid": "5fb068cd0a8dccb8dbab0a82"
},
"id": "C016GMB0H5L",
"name": "section-6pm",
"created": {
"$numberInt": "1594143066"
},
"creator": "U017218J9B3",
"is_archived": false,
"is_general": false,
"members": [
"U017218J9B3",
"U0185QQSJBY",
"U018CH1NLPL",
"U018R1AULF3",
"U018XEKMRTM",
"U0192BC785N",
"U019B1Q0YHW"
],
"topic": {
"value": "",
"creator": "",
"last_set": {
"$numberInt": "0"
}
},
"purpose": {
"value": "",
"creator": "",
"last_set": {
"$numberInt": "0"
}
}
}
*/

0 comments on commit eb74930

Please sign in to comment.