Skip to content

Commit

Permalink
feat: user add subs
Browse files Browse the repository at this point in the history
  • Loading branch information
haffi96 committed Sep 17, 2023
1 parent 320b663 commit 4ef1d0a
Show file tree
Hide file tree
Showing 15 changed files with 322 additions and 23 deletions.
22 changes: 21 additions & 1 deletion aws/backend/db/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ export type blogEntry = typeof allBlogs.$inferSelect;
export type newBlogPostEntry = typeof blogPosts.$inferInsert;

// Users table
export const upsertUserEntry = async (newUserParams: typeof users.$inferInsert) => {
return await db.insert(users).values(newUserParams).onConflictDoNothing({ target: [users.email] })
}

export const fetchUserById = async (userId: number) => {
return await db.select({ userUuid: users.user_uuid }).from(users).where(eq(users.id, userId))
}
Expand Down Expand Up @@ -51,7 +55,6 @@ export const fetchUserBlogsWithSubscriptionStatus = async (userEmail: string) =>
}



// AllBlogs table
export const createAllBlogsEntry = async (newBlogParams: newBlogEntry) => {
return await db.insert(allBlogs).values(newBlogParams)
Expand Down Expand Up @@ -147,6 +150,15 @@ export const fetchUsersForBlog = async (blogId: number | null) => {
return await db.select({ userId: userBlogs.user_id }).from(userBlogs).where(eq(userBlogs.blog_id, blogId!))
}

export const createUserBlogEntry = async (userEmail: string, blogId: number) => {
const userQuery = db.select({ userId: users.id }).from(users).where(eq(users.email, userEmail)).as("userQuery")

const result = await db.select({ userId: userQuery.userId }).from(userQuery)

const { userId } = result[0]

await db.insert(userBlogs).values({ user_id: userId, blog_id: blogId })
}

// UserPosts table
export const createUserPostEntry = async (userId: number, postId: number) => {
Expand Down Expand Up @@ -229,4 +241,12 @@ export const fetchTodaysUsersToNotify = async () => {

// fetchUserBlogsWithSubscriptionStatus("haffimazhar96@gmail.com").then((res) => {
// console.log(res)
// })

// upsertUserEntry({ email: "new@test.com" }).then((res) => {
// console.log(res)
// })

// createUserBlogEntry("new@test.com", 1).then((res) => {
// console.log(res)
// })
4 changes: 2 additions & 2 deletions aws/backend/db/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export const blogPosts = pgTable("blog_posts", {
titleHash: varchar("title_hash", { length: 256 }).notNull().unique(),
link: varchar("link", { length: 256 }),
author: varchar("author", { length: 256 }),
publishedDate: timestamp("published_date", { mode: "date"}),
publishedDate: timestamp("published_date", { mode: "date" }),
blog_id: integer("blog_id").references(() => allBlogs.id),
}, (blogPosts) => {
return {
Expand All @@ -63,7 +63,7 @@ export const userPosts = pgTable("user_posts", {
user_id: integer("user_id").references(() => users.id),
post_id: integer("post_id").references(() => blogPosts.id),
emailed: boolean("emailed").notNull().default(false),
notificationDate: timestamp("notification_date", { mode: "date"})
notificationDate: timestamp("notification_date", { mode: "date" })
.notNull()
.default(utcTimestampSql),
updatedAt: timestamp("updated_at"),
Expand Down
26 changes: 26 additions & 0 deletions aws/backend/lambda/addUserSubscription.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { APIGatewayProxyEvent, APIGatewayProxyResult } from "aws-lambda"
import { createUserBlogEntry } from "../db/query"

export const handler = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
const reqBody = event.body ? JSON.parse(event.body) : {}

const { email, blogId } = reqBody

try {
await createUserBlogEntry(email, blogId)
return {
statusCode: 200,
body: JSON.stringify({
reqBody
}),
}
} catch (err) {
console.log(err)
return {
statusCode: 500,
body: JSON.stringify({
message: "some error happened",
}),
}
}
}
26 changes: 26 additions & 0 deletions aws/backend/lambda/upsertUser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { APIGatewayProxyEvent, APIGatewayProxyResult } from "aws-lambda"
import { upsertUserEntry } from "../db/query"

export const handler = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
const reqBody = event.body ? JSON.parse(event.body) : {}

const { email, name } = reqBody

try {
await upsertUserEntry({ email, username: name })
return {
statusCode: 200,
body: JSON.stringify({
message: "success"
}),
}
} catch (err) {
console.log(err)
return {
statusCode: 500,
body: JSON.stringify({
message: "some error happened",
}),
}
}
}
70 changes: 70 additions & 0 deletions aws/events/addUserSub.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
{
"version": "2.0",
"routeKey": "$default",
"rawPath": "/path/to/resource",
"rawQueryString": "parameter1=value1&parameter1=value2&parameter2=value",
"cookies": [
"cookie1",
"cookie2"
],
"headers": {
"Header1": "value1",
"Header2": "value1,value2"
},
"queryStringParameters": {
"parameter1": "value1,value2",
"parameter2": "value"
},
"requestContext": {
"accountId": "123456789012",
"apiId": "api-id",
"authentication": {
"clientCert": {
"clientCertPem": "CERT_CONTENT",
"subjectDN": "www.example.com",
"issuerDN": "Example issuer",
"serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1",
"validity": {
"notBefore": "May 28 12:30:02 2019 GMT",
"notAfter": "Aug 5 09:36:04 2021 GMT"
}
}
},
"authorizer": {
"jwt": {
"claims": {
"claim1": "value1",
"claim2": "value2"
},
"scopes": [
"scope1",
"scope2"
]
}
},
"domainName": "id.execute-api.us-east-1.amazonaws.com",
"domainPrefix": "id",
"http": {
"method": "POST",
"path": "/path/to/resource",
"protocol": "HTTP/1.1",
"sourceIp": "192.168.0.1/32",
"userAgent": "agent"
},
"requestId": "id",
"routeKey": "$default",
"stage": "$default",
"time": "12/Mar/2020:19:03:58 +0000",
"timeEpoch": 1583348638390
},
"body": "{\"email\":\"new@test.com\", \"blogId\":\"5\"}",
"pathParameters": {
"parameter1": "value1"
},
"isBase64Encoded": true,
"stageVariables": {
"stageVariable1": "value1",
"stageVariable2": "value2"
}
}

69 changes: 69 additions & 0 deletions aws/events/upsertUser.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
{
"version": "2.0",
"routeKey": "$default",
"rawPath": "/path/to/resource",
"rawQueryString": "parameter1=value1&parameter1=value2&parameter2=value",
"cookies": [
"cookie1",
"cookie2"
],
"headers": {
"Header1": "value1",
"Header2": "value1,value2"
},
"queryStringParameters": {
"parameter1": "value1,value2",
"parameter2": "value"
},
"requestContext": {
"accountId": "123456789012",
"apiId": "api-id",
"authentication": {
"clientCert": {
"clientCertPem": "CERT_CONTENT",
"subjectDN": "www.example.com",
"issuerDN": "Example issuer",
"serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1",
"validity": {
"notBefore": "May 28 12:30:02 2019 GMT",
"notAfter": "Aug 5 09:36:04 2021 GMT"
}
}
},
"authorizer": {
"jwt": {
"claims": {
"claim1": "value1",
"claim2": "value2"
},
"scopes": [
"scope1",
"scope2"
]
}
},
"domainName": "id.execute-api.us-east-1.amazonaws.com",
"domainPrefix": "id",
"http": {
"method": "POST",
"path": "/path/to/resource",
"protocol": "HTTP/1.1",
"sourceIp": "192.168.0.1/32",
"userAgent": "agent"
},
"requestId": "id",
"routeKey": "$default",
"stage": "$default",
"time": "12/Mar/2020:19:03:58 +0000",
"timeEpoch": 1583348638390
},
"body": "{\"email\":\"foo@test.com\", \"name\":\"foo\"}",
"pathParameters": {
"parameter1": "value1"
},
"isBase64Encoded": true,
"stageVariables": {
"stageVariable1": "value1",
"stageVariable2": "value2"
}
}
7 changes: 6 additions & 1 deletion aws/lib/stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,13 +100,18 @@ export class TestStack extends cdk.Stack {
// API Lambdas
const postsLambda = new GenericLambda(this, "Posts")
const getSubscribedBlogsLambda = new GenericLambda(this, "GetSubscribedBlogs")
const upsertUserLambda = new GenericLambda(this, "upsertUser")
const addUserSubscriptionLambda = new GenericLambda(this, "addUserSubscription")


// API Routes
api.addIntegration("GET", "/posts", postsLambda)
api.addIntegration("GET", "/subscribed-blogs", getSubscribedBlogsLambda)
api.addIntegration("POST", "/user", upsertUserLambda)
api.addIntegration("POST", "/subscribe", addUserSubscriptionLambda)

// Create an SQS event source for NotifyUsers Lambda to process messages from the queue
const eventSource = new lambdaEventSources.SqsEventSource(queue, { batchSize: 1 } )
const eventSource = new lambdaEventSources.SqsEventSource(queue, { batchSize: 1 })
sendEmailLambda.addEventSource(eventSource)
}
}
2 changes: 1 addition & 1 deletion aws/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"migrate": "npx ts-node backend/db/migrate.ts",
"db-push": "npx drizzle-kit push:pg --config backend/db/config.ts",
"db-studio": "npx drizzle-kit studio --config backend/db/config.ts --port 5000",
"lint": "eslint ."
"lint": "eslint . --fix"
},
"devDependencies": {
"@types/aws-lambda": "^8.10.119",
Expand Down
28 changes: 19 additions & 9 deletions ui/src/components/SideNav.astro
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,26 @@ const userEmail = session?.user?.email || undefined;
const API_URL = import.meta.env.API_URL;
const baseUrl = userEmail
? `${API_URL}/subscribed-blogs?userEmail=${userEmail}`
: `${API_URL}/subscribed-blogs`;
async function fetchBlogs() {
const baseUrl = userEmail
? `${API_URL}/subscribed-blogs?userEmail=${userEmail}`
: `${API_URL}/subscribed-blogs`;
const res = await fetch(baseUrl, {
headers: {
"Content-Type": "application/json",
},
});
const subs: Subscription[] = await res.json();
const res = await fetch(baseUrl, {
headers: {
"Content-Type": "application/json",
},
});
return await res.json();
}
const subs: Subscription[] = await fetchBlogs();
// Sort by subscribed
subs.sort((a, b) =>
a.subscribed === b.subscribed ? 0 : a.subscribed ? -1 : 1,
);
const comingSoonEntry = {
blogId: 1000,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ import { useState } from "preact/hooks";
import type { Subscription } from "../types";

interface SubscribedBlogItemProps {
apiUrl: string;
userEmail?: string;
sub: Subscription;
removeSubAction: (blogId: number) => void;
}

export default function SubscribeActionButton({ userEmail, sub, removeSubAction }: SubscribedBlogItemProps) {
export default function SubscribeActionButton({ apiUrl, userEmail, sub, removeSubAction }: SubscribedBlogItemProps) {
const [unSubTrigger, setUnSubTrigger] = useState<boolean>(false);

const unSub = (blogId: number) => {
Expand All @@ -25,6 +26,20 @@ export default function SubscribeActionButton({ userEmail, sub, removeSubAction
window.location.href = `/login`;
}

async function addSubscriptionForUser(blogId: number) {
await fetch(`/api/addSub`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
userEmail,
blogId
}),
});
window.location.reload();
}

const iconRef = !sub.subscribed || userEmail === undefined ? "/add-outline.svg" : "/removeIcon.svg";

const LoggedOutSubscribeButton = () => {
Expand Down Expand Up @@ -53,7 +68,7 @@ export default function SubscribeActionButton({ userEmail, sub, removeSubAction
return (
<button
class="hover:bg-green-400 rounded-xl"
// onClick={() => unSubRequest(sub.blogId)}
onClick={() => addSubscriptionForUser(sub.blogId)}
>
<img src={iconRef} alt="Subscribe" />
</button>
Expand Down
3 changes: 2 additions & 1 deletion ui/src/components/allSubscriptions.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useState } from "preact/hooks";
import type { Subscription } from "../types";
import SubscribeActionButton from "./unSubscribeButton";
import SubscribeActionButton from "@components/SubscribeActionButton";

interface SubscribedBlogItemProps {
userEmail?: string;
Expand Down Expand Up @@ -29,6 +29,7 @@ export default function AllSubscriptionsList({ userEmail, apiUrl, subs }: Subscr
</a>
<div class="hidden md:block">
<SubscribeActionButton
apiUrl={apiUrl}
userEmail={userEmail}
sub={sub}
removeSubAction={removeSubAction}
Expand Down
Loading

0 comments on commit 4ef1d0a

Please sign in to comment.