Skip to content

Commit

Permalink
Update README and connection revisions (#204)
Browse files Browse the repository at this point in the history
### changes
- add README
- handle image posts from webwizards
- don't call inbox when sending comments to webwizards, seems like they
don't support it based on their API
- comment likes changes
  • Loading branch information
rmgutierrez authored Dec 8, 2023
2 parents bb96490 + 9a9bf88 commit 6ae5105
Show file tree
Hide file tree
Showing 12 changed files with 188 additions and 46 deletions.
75 changes: 73 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,84 @@ CMPUT 404 Project: Social Distribution

Contributors / Licensing
========================

Authors:

* Kaye Ena Crayzhel Misay
* Kaustubh Mukherjee
* Nhat Minh Luu
* Raphael Gutierrez
* Mehsheed Ahmed Syed Abdul

Generally, everything is LICENSE'D under the Apache 2 license by 404_Team_not_found.

User Stories
========================
- [x] As an author I want to make public posts.
- [x] As an author I want to edit public posts.
- [x] As an author, posts I create can link to images.
- [x] As an author, posts I create can be images.
- [x] As a server admin, images can be hosted on my server.
- [x] As an author, posts I create can be private to another author
- [x] As an author, posts I create can be private to my friends
- [x] As an author, I can share other author’s public posts
- [x] As an author, I can re-share other author’s friend posts to my friends
- [x] As an author, posts I make can be in simple plain text
- [x] As an author, posts I make can be in CommonMark
- [x] As an author, I want a consistent identity per server
- [x] As a server admin, I want to host multiple authors on my server
- [x] As a server admin, I want to share public images with users on other servers.
- [x] As an author, I want to pull in my github activity to my “stream”
- [x] As an author, I want to post posts to my “stream”
- [x] As an author, I want to delete my own public posts.
- [x] As an author, I want to befriend local authors
- [x] As an author, I want to befriend remote authors
- [x] As an author, I want to feel safe about sharing images and posts with my friends – images shared to friends should only be visible to friends. [public images are public]
- [x] As an author, when someone sends me a friends only-post I want to see the likes.
- [x] As an author, comments on friend posts are private only to me the original author.
- [x] As an author, I want un-befriend local and remote authors
- Done for local. Unfollowing Code Monkey's author works.
- Some teams have implemented their `DELETE` `/followers` request in local-only mode, so we aren't able to "Unfollow" their author.
- [x] As an author, I want to be able to use my web-browser to manage my profile
- [x] As an author, I want to be able to use my web-browser to manage/author my posts
- [x] As a server admin, I want to be able to add, modify, and remove authors.
- [x] As a server admin, I want to OPTIONALLY be able to allow users to sign up but require my OK to finally be on my server
- [x] As a server admin, I don’t want to do heavy setup to get the posts of my author’s friends.
- [x] As a server admin, I want a restful interface for most operations
- [x] As an author, other authors cannot modify my public post
- [x] As an author, other authors cannot modify my shared to friends post.
- [x] As an author, I want to comment on posts that I can access
- [x] As an author, I want to like posts that I can access
- [x] As an author, my server will know about my friends
- [x] As an author, When I befriend someone it follows them, only when the other authors befriends me do I count as a real friend.
- [x] As an author, I want to know if I have friend requests.
- [x] As an author I should be able to browse the public posts of everyone
- [x] As a server admin, I want to be able to add nodes to share with
- [x] As a server admin, I want to be able to remove nodes and stop sharing with them.
- [x] As a server admin, I can limit nodes connecting to me via authentication.
- [x] As a server admin, node to node connections can be authenticated with HTTP Basic Auth
- [x] As a server admin, I can disable the node to node interfaces for connections that are not authenticated!
- [x] As an author, I want to be able to make posts that are unlisted, that are publicly shareable by URI alone (or for embedding images)

Connections
========================
- Code Monkeys
- website url: https://chimp-chat-1e0cca1cc8ce.herokuapp.com/
- username: node-404-team-not-found
- password: chimpchatapi
- full connection
- Web Wizards
- website url: https://uofa-cmput404.github.io/404f23project-web-wizards/
- username: node-404-team-not-found
- password: socialpassword
- full connection
- Note: At the time of writing, Web Wizards doesn't support visibility = "Private". We are attempting to send it to them, in case it changes.
- Triet
- website url: https://fakebook-frontend-f922a5dc4574.herokuapp.com/
- username: 404-not-found
- password: 1
- partial connection
- Note: At the time of writing, Triet's database resets every day, so node and author registrations need to be done manually by Triet.
- Net Ninjas
- website url: https://netninjas-58669f3bc849.herokuapp.com
- credentials: should be able to create on their website
- partial connection
- Note: At the time of writing, their API is currently returning an OperationalError. Net ninjas mentioned that it's something related to their database.
25 changes: 24 additions & 1 deletion client/src/components/Profilepage/ProfilePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
import HeadBar from "../template/AppBar";
import { Author } from "../../interfaces/interfaces";
import EditIcon from "@mui/icons-material/Edit";
import { ApiPaths, ImageLink, ShareType, ToastMessages, Username } from "../../enums/enums";
import { ApiPaths, Hosts, ImageLink, ShareType, ToastMessages, Username } from "../../enums/enums";
import { useParams, useLocation } from "react-router-dom";
import MakePostModal from "../post/MakePostModal";
import LeftNavBar from "../template/LeftNavBar";
Expand Down Expand Up @@ -186,6 +186,29 @@ const ProfilePage = () => {
post.visibility === ShareType.PUBLIC);
}

// webwizards has a different way of getting images...
// we have to call /images to get the base64
if (otherAuthorObject.host === Hosts.WEBWIZARDS) {
for (const post of publicPosts) {
if (post.has_image !== undefined && post.has_image) {
try {
const url = `${post.id}/image`
const imageResponse = await axios.get(url, {
auth: {
username: Username.NOTFOUND,
password: codes[Hosts.WEBWIZARDS],
},
});

// Update the specific post in publicPosts with updated data
post.contentType = imageResponse.data["image_type"];
post.description = post.content;
post.content = imageResponse.data["image"];
} catch (error) {
}
}
}
}
setPosts(publicPosts);
}
} catch (error) {
Expand Down
26 changes: 25 additions & 1 deletion client/src/components/feed/HomePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import { toast } from "react-toastify";
import HeadBar from "../template/AppBar";
import LeftNavBar from "../template/LeftNavBar";
import Loading from "../ui/Loading";
import { Hosts, Username } from "../../enums/enums";
import { codes } from "../../objects/objects";

const APP_URI = process.env.REACT_APP_URI;

Expand Down Expand Up @@ -50,9 +52,31 @@ export default function HomePage() {
},
});

const inboxPosts = inboxresponse.data.items.filter(
let inboxPosts = inboxresponse.data.items.filter(
(item: any) => item && item.type === "post"
);

// webwizards has a different way of getting images...
// we have to call /images to get the base64
for (const post of inboxPosts) {
if (post.author.host === Hosts.WEBWIZARDS && post.has_image !== undefined && post.has_image) {
try {
const url = `${post.id}/image`
const imageResponse = await axios.get(url, {
auth: {
username: Username.NOTFOUND,
password: codes[Hosts.WEBWIZARDS],
},
});

// Update the specific post in publicPosts with updated data
post.contentType = imageResponse.data["image_type"];
post.description = post.content;
post.content = imageResponse.data["image"];
} catch (error) {
}
}
}

const validPosts = response.data.filter((item: any) => item !== null);

Expand Down
12 changes: 10 additions & 2 deletions client/src/components/post/MakeCommentModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ const MakeCommentModal = ({
toast.error(ToastMessages.NOUSERCREDS);
}
} else {
if (post.author.host === Hosts.CODEMONKEYS) {
if (post.author.host === Hosts.CODEMONKEYS || post.author.host === Hosts.TRIET) {
data = {
...data,
id: `${post.id}/comments/${uuidv4()}`,
Expand All @@ -213,7 +213,11 @@ const MakeCommentModal = ({

post.count = post.count + 1;
await fetchComments();
await sendCommentToInbox(comment, contentType, response.data["id"], response.data["published"]);
// from their API, it seems like creating a comment already sends it to their inbox
// we don't need to do this, and they don't allow sending type=comment to their inbox (based from their API)
if (post.author.host !== Hosts.WEBWIZARDS) {
await sendCommentToInbox(comment, contentType, response.data["id"], response.data["published"]);
}
}

handleClear();
Expand Down Expand Up @@ -258,6 +262,10 @@ const MakeCommentModal = ({
if (post.author.host === Hosts.TRIET) {
data = {
...data,
"author": {
...data.author,
"id": `${data.author.id}/`,
},
"id": `${data.id}/`,
}
}
Expand Down
12 changes: 12 additions & 0 deletions client/src/components/post/MakePostModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,10 @@ const MakePostModal = ({
// triet requires / at the end for ids
postData = {
...postData,
"author": {
...postData.author,
"id": `${postData.author.id}/`,
},
"id": `${postData.id}/`
}
}
Expand Down Expand Up @@ -279,6 +283,10 @@ const MakePostModal = ({
// triet requires / at the end for ids
postData = {
...postData,
"author": {
...postData.author,
"id": `${postData.author.id}/`,
},
"id": `${postData.id}/`
}
}
Expand Down Expand Up @@ -309,6 +317,10 @@ const MakePostModal = ({
// triet requires / at the end for ids
postData = {
...postData,
"author": {
...postData.author,
"id": `${postData.author.id}/`,
},
"id": `${postData.id}/`
}
}
Expand Down
41 changes: 19 additions & 22 deletions client/src/components/post/like/CommentLikes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import { Button, Typography } from "@mui/material";
import axios from "axios";
import { Like, LikePostRequest } from "../../../interfaces/interfaces";
import {
getAuthorUrlFromIdUrl,
getCodeFromObjectId,
isApiPathNoSlash,
isHostLocal,
isApiPathNoSlash, isObjectFromTriet,
isUrlIdLocal,
} from "../../../utils/responseUtils";
import { toast } from "react-toastify";
import FavoriteBorderIcon from "@mui/icons-material/FavoriteBorder";
Expand All @@ -15,9 +16,6 @@ import Tooltip from "@mui/material/Tooltip";
import { Comment } from "../../../interfaces/interfaces";
import { ApiPaths, Hosts, Links, ToastMessages, Username } from "../../../enums/enums";
import { codes } from "../../../objects/objects";
import { extractEndpointSegmentFromCommentId } from "../../../utils/requestUtils";

const APP_URI = process.env.REACT_APP_URI;

const CommentLikes = ({
comment,
Expand All @@ -28,9 +26,7 @@ const CommentLikes = ({
}) => {
const [commentLikes, setCommentLikes] = useState<Like[]>([]);
const [isUserLiked, setIsUserLiked] = useState<boolean>(false);
// have to check the author of the comment instead of the comment.id
// since a local author can comment in a remote post, and vice-versa
const isLocal = isHostLocal(comment.author.host);
const isLocal = isUrlIdLocal(comment.id);
const userData = getUserData();

const handleLike = async () => {
Expand All @@ -40,11 +36,12 @@ const CommentLikes = ({
"object": comment.id,
"summary": `${userData.displayName} Likes your post`
}
const authorUrl = getAuthorUrlFromIdUrl(comment.id);

try {
if (isLocal) {
const userCredentials = getUserCredentials();
const url = `${comment.author.id}/inbox/`;
const url = `${authorUrl}/inbox/`;

if (userCredentials.username && userCredentials.password) {
const response = await axios.post(url, data, {
Expand All @@ -59,13 +56,17 @@ const CommentLikes = ({
toast.error(ToastMessages.NOUSERCREDS);
}
} else {
const url = isApiPathNoSlash(comment.author.host, ApiPaths.INBOX) ?
`${comment.author.id}/inbox` :
`${comment.author.id}/inbox/`;
const url = isApiPathNoSlash(authorUrl, ApiPaths.INBOX) ?
`${authorUrl}/inbox` :
`${authorUrl}/inbox/`;

if (comment.author.host === Hosts.TRIET) {
if (isObjectFromTriet(authorUrl)) {
data = {
...data,
"author": {
...data.author,
"id": `${data.author.id}/`,
},
"@context": Links.LIKECONTEXT,
"object": `${data.object}/`,
}
Expand All @@ -79,7 +80,7 @@ const CommentLikes = ({
const response = await axios.post(url, data, {
auth: {
username: Username.NOTFOUND,
password: codes[comment.author.host],
password: getCodeFromObjectId(authorUrl),
},
});

Expand All @@ -93,13 +94,10 @@ const CommentLikes = ({

useEffect(() => {
const fetchLikes = async () => {
const endpoint = extractEndpointSegmentFromCommentId(comment.id);


try {
if (isLocal) {
const userCredentials = getUserCredentials();
const url = `${APP_URI}authors/${endpoint}/likes/`;
const url = `${comment.id}/likes/`;

if (userCredentials.username && userCredentials.password) {
const response = await axios.get(url, {
Expand All @@ -120,10 +118,9 @@ const CommentLikes = ({
} else {
// TODO: currently not working as comment.id is not well-formed from webwizards,
// should automatically work when they fix it, but should double check
let url = `${comment.author.host}authors/${endpoint}`
url = isApiPathNoSlash(comment.id, ApiPaths.COMMENTLIKES) ?
`${url}/likes`:
`${url}/likes/`;
const url = isApiPathNoSlash(comment.id, ApiPaths.COMMENTLIKES) ?
`${comment.id}/likes`:
`${comment.id}/likes/`;

const response = await axios.get(url, {
auth: {
Expand Down
4 changes: 4 additions & 0 deletions client/src/components/post/like/PostLikes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ const PostLikes = ({
if (post.author.host === Hosts.TRIET) {
data = {
...data,
"author": {
...data.author,
"id": `${data.author.id}/`,
},
"@context": Links.LIKECONTEXT,
"object": `${data.object}/`,
}
Expand Down
10 changes: 8 additions & 2 deletions client/src/components/post/post-item/PostPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ const PostPage = () => {
toast.error(ToastMessages.NOUSERCREDS);
}
} else {
if (post.author.host === Hosts.CODEMONKEYS) {
if (post.author.host === Hosts.CODEMONKEYS || post.author.host === Hosts.TRIET) {
data = {
...data,
id: `${post.id}/comments/${uuidv4()}`,
Expand All @@ -269,7 +269,9 @@ const PostPage = () => {

post.count = post.count + 1;
await fetchComments(post.id, post.author.host);
await sendCommentToInbox(comment, contentType, response.data["id"], post.author.id, response.data["published"]);
if (post.author.host !== Hosts.WEBWIZARDS) {
await sendCommentToInbox(comment, contentType, response.data["id"], post.author.id, response.data["published"]);
}
}

handleClear();
Expand Down Expand Up @@ -316,6 +318,10 @@ const PostPage = () => {
if (postHost === Hosts.TRIET) {
data = {
...data,
"author": {
...data.author,
"id": `${data.author.id}/`,
},
"id": `${data.id}/`,
}
}
Expand Down
1 change: 1 addition & 0 deletions client/src/interfaces/interfaces.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export interface Post {
contentType: ContentType;
content_type?: ContentType;
description: string;
has_image?: boolean;
title: string;
source: string;
origin: string;
Expand Down
1 change: 1 addition & 0 deletions client/src/lists/lists.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export const remoteAuthorHosts: string[] = [
export const webWizardsNoSlashApiPath: string[] = [
ApiPaths.FOLLOWER,
ApiPaths.FOLLOWERS,
ApiPaths.IMAGE,
ApiPaths.INBOX,
ApiPaths.POSTLIKES,
ApiPaths.POST,
Expand Down
Loading

0 comments on commit 6ae5105

Please sign in to comment.