Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
116 commits
Select commit Hold shift + click to select a range
a6415ae
Auth 0 setup
Frank-cntrl Jul 31, 2025
f7f9727
Merge pull request #5 from team8ttpr/context/auth-provider
Frank-cntrl Jul 31, 2025
e3fad3e
Cors update backend
Frank-cntrl Jul 31, 2025
c5cc9a0
feat: added posts model
WebbneyVallon99 Jul 31, 2025
a44842e
feat: added follows model
WebbneyVallon99 Jul 31, 2025
adeb205
will undo this
Frank-cntrl Jul 31, 2025
a0c247d
refactor: fixed typo
WebbneyVallon99 Jul 31, 2025
a4202dd
.
Frank-cntrl Jul 31, 2025
7d53b9a
g
Frank-cntrl Jul 31, 2025
a9c449f
g
Frank-cntrl Jul 31, 2025
f6311f0
g
Frank-cntrl Jul 31, 2025
5004509
undid
Frank-cntrl Jul 31, 2025
1b5a016
Merge pull request #6 from team8ttpr/model/posts-model
Micksterious Aug 1, 2025
b6bff00
Delete database/posts.js
Micksterious Aug 1, 2025
3002014
Merge branch 'main' of https://github.com/team8ttpr/Capstone-2-Backen…
Micksterious Aug 1, 2025
f52422f
Restored posts.js to resolve merge conflict
Micksterious Aug 1, 2025
0d44453
Merge pull request #11 from team8ttpr/model/follows-model
Micksterious Aug 1, 2025
50fb32f
added spotify login
Frank-cntrl Aug 1, 2025
115f195
Merge branch 'main' into feature-spotify/login
Frank-cntrl Aug 1, 2025
54aa66f
Merge pull request #16 from team8ttpr/feature-spotify/login
Frank-cntrl Aug 1, 2025
bb84c2d
new backend
Frank-cntrl Aug 1, 2025
bbc6dda
Merge pull request #17 from team8ttpr/feature-spotify/login
Frank-cntrl Aug 1, 2025
36a814f
edited databases/posts.js, added dummy data for post to test, added r…
Micksterious Aug 1, 2025
740b44b
Merge branch 'main' into api/posts
Micksterious Aug 1, 2025
2c165df
WOrk?
Frank-cntrl Aug 1, 2025
bf9f1ce
Merge pull request #20 from team8ttpr/feature-spotify/login
Frank-cntrl Aug 1, 2025
ba58351
Merge branch 'main' into api/posts
Micksterious Aug 4, 2025
4d70612
Routes for user data
Frank-cntrl Aug 4, 2025
7562330
Merge pull request #28 from team8ttpr/feature/top-artist
Frank-cntrl Aug 4, 2025
5bd356a
added routes for /GET feed and myPost
Micksterious Aug 4, 2025
8fd2079
Added models AvatarURL and removed 'if published !== deleted TEMP
Micksterious Aug 5, 2025
9e0ea50
Merge pull request #18 from team8ttpr/api/posts
Frank-cntrl Aug 5, 2025
bda1eff
Syntax
Frank-cntrl Aug 5, 2025
8e76997
fix: updated Post model to accept type + id for Spotify item
tran2106 Aug 5, 2025
2a8c627
feat: add a post/save draft endpoint
tran2106 Aug 5, 2025
14bb9fd
feat: Patch routes
tran2106 Aug 6, 2025
aecf402
fix: mounted route
tran2106 Aug 6, 2025
8fce0d5
added search component and fixed minidrawer responsiveness
Frank-cntrl Aug 6, 2025
f9ae100
Merge pull request #33 from team8ttpr/api/draft-endpoints
Frank-cntrl Aug 6, 2025
e5a14ec
Update search.js
Frank-cntrl Aug 6, 2025
e361f15
Merge pull request #34 from team8ttpr/feature/search-bar
Frank-cntrl Aug 6, 2025
fe3abb1
Merge branch 'api/posts' of https://github.com/team8ttpr/Capstone-2-B…
Micksterious Aug 6, 2025
d3514d8
Merge branch 'main' into api/posts
Micksterious Aug 6, 2025
9e49f44
Merge branch 'main' into api/posts
Micksterious Aug 6, 2025
47f89be
bug fixes
Micksterious Aug 6, 2025
30e2011
Merge branch 'api/posts' of https://github.com/team8ttpr/Capstone-2-B…
Micksterious Aug 6, 2025
a21edf1
fixed bug issues
Micksterious Aug 6, 2025
be26183
routes to get post by status either draft or published
Micksterious Aug 6, 2025
eeb16c2
added spotify fields to post model and edited seed to include spotify…
Micksterious Aug 7, 2025
5c1bfeb
fixed patch route to check if status is published to prevent editting
Micksterious Aug 7, 2025
71c55b7
Merge pull request #35 from team8ttpr/api/posts
Frank-cntrl Aug 7, 2025
adf1ed3
added attributes so when its passed to postcard it shows username
Micksterious Aug 7, 2025
ff18184
Merge branch 'main' into api/posts
Micksterious Aug 7, 2025
45724ee
merge profile page backend
Frank-cntrl Aug 7, 2025
7049735
Merge branch 'main' into api/posts
Micksterious Aug 7, 2025
ecd7c90
refactor
Frank-cntrl Aug 7, 2025
9eab848
Deleted seed.js
Micksterious Aug 7, 2025
7f7ff8b
f
Frank-cntrl Aug 7, 2025
e82cdf6
Create post
Frank-cntrl Aug 7, 2025
c9de44b
Merge pull request #37 from team8ttpr/feature/create-post
Frank-cntrl Aug 7, 2025
075333d
feat: add theme attribute to models/add new endpoints (GET/PUT /api/p…
tran2106 Aug 8, 2025
e5c8376
fix: removed put route
tran2106 Aug 8, 2025
0a42506
updated model to accept any theme string instead of a fixed set
tran2106 Aug 8, 2025
7ee3f1c
some refactored route changes
Micksterious Aug 8, 2025
c6d77a7
updated
Micksterious Aug 8, 2025
39dfb23
refactored routes and added GET draft/:id
Micksterious Aug 8, 2025
cffc520
Merge pull request #50 from team8ttpr/api/profile-theme
Micksterious Aug 8, 2025
840c77f
Merge pull request #51 from team8ttpr/api/posts
Micksterious Aug 8, 2025
e781328
feat: added sticker and user profile sticker table
tran2106 Aug 8, 2025
9fbac2b
edited seed to included sample follow realtions as well worked testin…
Micksterious Aug 8, 2025
82012c9
feat: Cloudinary condig + get preset sticker routes + update Sticker …
tran2106 Aug 10, 2025
4a605ac
test
tran2106 Aug 10, 2025
bd9847e
feat: added route to get user's custom stickers
tran2106 Aug 10, 2025
c7b4c46
refactor: file name change
tran2106 Aug 10, 2025
9997061
feat: added upload + upload with ai removal routes + delete mock rout…
tran2106 Aug 10, 2025
9fd08b2
feat: updated delete route -> post route for the functionality, updat…
tran2106 Aug 10, 2025
d35544c
feat: added route for spotify item + update profile routes + model up…
tran2106 Aug 11, 2025
56b6bcd
Merge pull request #52 from team8ttpr/feature/api/models/sticker-profile
tran2106 Aug 11, 2025
f901d97
Merge branch 'main' into api/posts
Micksterious Aug 11, 2025
1d81ae4
Added created follow.js and routes for following and followers
Micksterious Aug 11, 2025
165ae88
small changes
Micksterious Aug 11, 2025
f5ebf37
Created routes and a table for likes
Frank-cntrl Aug 11, 2025
e67c03b
Merge pull request #53 from team8ttpr/feature-post-like
Frank-cntrl Aug 11, 2025
6dc79b0
added /GET all profile routes
Micksterious Aug 12, 2025
ab0dc00
working get route for all
Micksterious Aug 12, 2025
d43d4bf
minor changes
Micksterious Aug 12, 2025
d9a0f83
Merge branch 'main' into api/posts
Micksterious Aug 12, 2025
da19f0d
Merge pull request #55 from team8ttpr/api/posts
Micksterious Aug 12, 2025
171f94d
feat: updated user model for visibility and images profile setting/ u…
tran2106 Aug 13, 2025
3d44e14
comments are succesful (#56)
Frank-cntrl Aug 13, 2025
17cba2e
Feature fork (#57)
Frank-cntrl Aug 13, 2025
5814558
cors
Frank-cntrl Aug 13, 2025
0deef28
added route for following-status
Micksterious Aug 14, 2025
d4de0e9
Merge pull request #58 from team8ttpr/api/posts
Micksterious Aug 14, 2025
19ab096
Revert "added route for following-status" (#59)
Frank-cntrl Aug 14, 2025
b47bad1
temp
Micksterious Aug 14, 2025
1152124
fixed my post filtering, drafting and publishing
Frank-cntrl Aug 14, 2025
6340e94
Merge branch 'main' into api/posts
Micksterious Aug 14, 2025
e6bac31
added route for following
Micksterious Aug 14, 2025
1b448f2
Merge pull request #60 from team8ttpr/api/posts
Micksterious Aug 14, 2025
8d0fe6e
Fixed search componenet, now returns user saved playlist instead of r…
Frank-cntrl Aug 14, 2025
5dba4f5
feat added endoint to fetch user listening history and top genres + a…
tran2106 Aug 15, 2025
ec8d758
Merge pull request #62 from team8ttpr/api/analutics-history
tran2106 Aug 15, 2025
a559d0b
expansion of following system (#63)
Frank-cntrl Aug 15, 2025
7147e92
mabye sockets
Micksterious Aug 15, 2025
1b2d350
updated
Micksterious Aug 15, 2025
e426046
Merge branch 'main' into api/posts
Micksterious Aug 15, 2025
69e286f
Merge pull request #64 from team8ttpr/api/posts
Micksterious Aug 15, 2025
b05d164
updated
Micksterious Aug 15, 2025
813db46
Merge pull request #65 from team8ttpr/api/posts
Micksterious Aug 15, 2025
9e3775a
refactored file structure
Micksterious Aug 15, 2025
c87a0cc
Merge pull request #66 from team8ttpr/api/posts
Micksterious Aug 15, 2025
c1df74e
updates (#67)
Frank-cntrl Aug 15, 2025
fe1fdb3
Feature messages (#68)
Frank-cntrl Aug 15, 2025
c2cc47a
added middleware for checking spotify users
Micksterious Aug 15, 2025
069d6a9
Merge branch 'main' into api/posts
Micksterious Aug 15, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .env.example

This file was deleted.

85 changes: 85 additions & 0 deletions api/comments.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
const express = require("express");
const router = express.Router();
const { Comments, User } = require("../database");
const { authenticateJWT } = require("../auth");

// get the comments of a specific post
router.get("/posts/:postId/comments", async (req, res) => {
try {
const { postId } = req.params;

const comments = await Comments.findAll({
where: { post_id: postId },
include: [
{
model: User,
as: "author",
attributes: ["id", "username", "spotifyDisplayName", "profileImage", "avatarURL"]
}
],
order: [["created_at", "DESC"]]
});

res.json(comments);
} catch (error) {
console.error('Error fetching comments:', error);
res.status(500).json({ error: 'Failed to fetch comments' });
}
});

// post comments to a specific post
router.post("/posts/:postId/comments", authenticateJWT, async (req, res) => {
try {
const { postId } = req.params;
const { content, parentId } = req.body;
const userId = req.user.id;

const comment = await Comments.create({
post_id: postId,
user_id: userId,
content,
parent_id: parentId || null
});

const createdComment = await Comments.findByPk(comment.id, {
include: [
{
model: User,
as: "author",
attributes: ["id", "username", "spotifyDisplayName", "profileImage", "avatarURL"]
}
]
});

res.json(createdComment);
} catch (error) {
console.error('Error creating comment:', error);
res.status(500).json({ error: 'Failed to create comment' });
}
});

// delete comments of a specific post
router.delete("/:id", authenticateJWT, async (req, res) => {
try {
const commentId = req.params.id;
const userId = req.user.id;

const deleted = await Comments.destroy({
where: {
id: commentId,
user_id: userId
}
});

if (deleted === 0) {
return res.status(404).json({ error: "Comment not found or unauthorized" });
}

res.status(204).end();
} catch (error) {
console.error('Error deleting comment:', error);
res.status(500).json({ error: 'Failed to delete comment' });
}
});

module.exports = router;
245 changes: 245 additions & 0 deletions api/follow.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
const express = require("express");
const router = express.Router();
const { User, Posts, Follows } = require("../database");
const { authenticateJWT } = require("../auth");
const { Op } = require("sequelize");

router.get("/me/followers", authenticateJWT, async (req, res) => {
try {
const user = await User.findByPk(req.user.id);

if (!user) {
return res.status(404).json({ error: "User not found" });
}

const followers = await Follows.findAll({
where: { followingId: user.id },
include: [
{
model: User,
as: "follower",
attributes: [
"id",
"username",
"firstName",
"lastName",
"profileImage",
"spotifyProfileImage",
"avatarURL",
],
},
],
order: [["createdAt", "DESC"]],
limit: 50,
});

res.json(followers.map((follow) => follow.follower));
} catch (error) {
console.error("Error fetching my followers:", error);
res.status(500).json({ error: "Failed to fetch followers" });
}
});

// Get *my* following
router.get("/me/following", authenticateJWT, async (req, res) => {
try {
const user = await User.findByPk(req.user.id);

if (!user) {
return res.status(404).json({ error: "User not found" });
}

const following = await Follows.findAll({
where: { followerId: user.id },
include: [
{
model: User,
as: "following",
attributes: [
"id",
"username",
"firstName",
"lastName",
"profileImage",
"spotifyProfileImage",
"avatarURL",
],
},
],
order: [["createdAt", "DESC"]],
limit: 50,
});

res.json(following.map((follow) => follow.following));
} catch (error) {
console.error("Error fetching my following:", error);
res.status(500).json({ error: "Failed to fetch following" });
}
});

// Check if current user is following another user
router.get("/:username/following-status", authenticateJWT, async (req, res) => {
try {
const userToCheck = await User.findOne({
where: { username: req.params.username },
});

if (!userToCheck) {
return res.status(404).json({ error: "User not found" });
}

const isFollowing = await Follows.findOne({
where: {
followerId: req.user.id,
followingId: userToCheck.id,
},
});

res.json({ following: !!isFollowing });
} catch (error) {
console.error("Error checking following status:", error);
res.status(500).json({ error: "Failed to check following status" });
}
});

// Get user's followers
router.get("/:username/followers", async (req, res) => {
try {
const user = await User.findOne({
where: { username: req.params.username },
});

if (!user) {
return res.status(404).json({ error: "User not found" });
}

const followers = await Follows.findAll({
where: { followingId: user.id },
include: [
{
model: User,
as: "follower",
attributes: [
"id",
"username",
"firstName",
"lastName",
"profileImage",
"spotifyProfileImage",
"avatarURL",
],
},
],
order: [["createdAt", "DESC"]],
limit: 50,
});

res.json(followers.map((follow) => follow.follower));
} catch (error) {
console.error("Error fetching followers:", error);
res.status(500).json({ error: "Failed to fetch followers" });
}
});

// Get user's following
router.get("/:username/following", async (req, res) => {
try {
const user = await User.findOne({
where: { username: req.params.username },
});

if (!user) {
return res.status(404).json({ error: "User not found" });
}

const following = await Follows.findAll({
where: { followerId: user.id },
include: [
{
model: User,
as: "following",
attributes: [
"id",
"username",
"firstName",
"lastName",
"profileImage",
"spotifyProfileImage",
"avatarURL",
],
},
],
order: [["createdAt", "DESC"]],
limit: 50,
});

res.json(following.map((follow) => follow.following));
} catch (error) {
console.error("Error fetching following:", error);
res.status(500).json({ error: "Failed to fetch following" });
}
});

//get all users who are following one another
router.get("/:username/friends", authenticateJWT, async (req, res) => {
try {
const user = await User.findByPk(req.user.id);

if (!user) {
return res.status(404).json({ error: "User not found" });
}

const followers = await user.getFollowers();
const following = await user.getFollowing();

const friends = followers.filter((follower) =>
following.some((followed) => followed.id === follower.id)
);

res.json(friends);
} catch (error) {
console.error("Error fetching mutual friends:", error);
res.status(500).json({ error: "Failed to fetch mutual friends" });
}
});

//get all users with follow status
router.get("/all-with-follow-status", authenticateJWT, async (req, res) => {
try {
const meId = req.user.id;

// Get all users except me
const users = await User.findAll({
where: { id: { [Op.ne]: meId } },
attributes: [
"id",
"username",
"firstName",
"lastName",
"profileImage",
"spotifyProfileImage",
"avatarURL",
],
});

// Get IDs of users I’m following
const following = await Follows.findAll({
where: { followerId: meId },
attributes: ["followingId"],
});
const followingIds = new Set(following.map((f) => f.followingId));

// Attach isFollowing flag to each user
const result = users.map((u) => ({
...u.toJSON(),
isFollowing: followingIds.has(u.id),
}));

res.json(result);
} catch (error) {
console.error("Error fetching users with follow status:", error);
res.status(500).json({ error: "Failed to fetch follow data" });
}
});

module.exports = router;
14 changes: 14 additions & 0 deletions api/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
const express = require("express");
const router = express.Router();

const testDbRouter = require("./test-db");
const searchRouter = require("./search");
const postsRouter = require("./posts");
const profileRouter = require("./profile");
const stickersRouter = require("./stickers");
const followRouter = require("./follow");
const commentsRouter = require('./comments');


router.use("/test-db", testDbRouter);
router.use("/search-songs", searchRouter);
router.use("/posts", postsRouter);
router.use("/profile", profileRouter);
router.use("/follow", followRouter);
router.use("/stickers", stickersRouter);
router.use('/', commentsRouter);

module.exports = router;
Loading