Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Merge dev branch into staging branch #972

Merged
merged 64 commits into from
Aug 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
6b3075c
fix duplicate timezones
theijhay Aug 23, 2024
86ec9cd
Merge branch 'dev' into fix/duplicate-Time-Zone
theijhay Aug 24, 2024
75aa144
Add code for delete blog like endpoint
Aug 24, 2024
296892d
Add code for delete blog dislike endpoint
Aug 24, 2024
476a5a7
Merge branch 'hngprojects:dev' into fix/duplicate-Time-Zone
theijhay Aug 24, 2024
c12f3c1
made changes
theijhay Aug 24, 2024
9f24c4e
Add test for delete blog like endpoint
Aug 24, 2024
3742223
Add test for delete blog dislike endpoint
Aug 24, 2024
d7d3c46
Fix wrong reference in test delete blog like
Aug 24, 2024
5de8cb9
Merge branch 'dev' into fix/duplicate-Time-Zone
joboy-dev Aug 24, 2024
92a336e
Merge pull request #954 from theijhay/fix/duplicate-Time-Zone
johnson-oragui Aug 24, 2024
0e70092
Finish up delete blog like endpoint
Aug 24, 2024
6d61c37
Finish up delete blog dislike endpoint
Aug 24, 2024
274ca39
Merge branch 'dev' into feat/delete-blog-like
Aug 24, 2024
7c52ef9
Merge branch 'dev' into feat/delete-blog-dislike
Aug 24, 2024
6650ad4
Create regression-test.yml
DrInTech22 Aug 24, 2024
4fe2584
Fix else/if bug in services.blog.BlogService.delete_opposite_blog_lik…
Aug 24, 2024
ebc492f
fix: added conditionals to only send emails to new newsletter subscri…
Aug 24, 2024
2a7edc9
chore: updated with app dependencies
Aug 24, 2024
50d2f3f
Fix comment in services.blog.BlogService.delete_opposite_blog_like_or…
Aug 24, 2024
50c723c
Update regression workflow
DrInTech22 Aug 24, 2024
0abb5c7
Update .gitignore
DrInTech22 Aug 24, 2024
2d2fa96
Merge pull request #969 from hngprojects/DrInTech
Sarahligbe Aug 24, 2024
11e61f8
Merge branch 'dev' into fix/newsletter-sunscription
johnson-oragui Aug 24, 2024
c71f6dc
Merge pull request #970 from johnson-oragui/fix/newsletter-sunscription
trevorjob Aug 24, 2024
59eb5c8
Merge branch 'dev' into feat/delete-blog-dislike
chimeziriobioha Aug 24, 2024
00e7c3d
Merge branch 'dev' into feat/delete-blog-like
chimeziriobioha Aug 24, 2024
5178826
Merge pull request #968 from traderstechie/feat/delete-blog-dislike
johnson-oragui Aug 24, 2024
726df99
Merge branch 'dev' into feat/delete-blog-like
chimeziriobioha Aug 24, 2024
2661d52
Update regression workflow
DrInTech22 Aug 24, 2024
ac3005c
Merge branch 'dev' into DrInTech
DrInTech22 Aug 24, 2024
036354e
feat: implement search functionality on products dashboard
Nifilat Aug 24, 2024
a40f64e
feat: enhance endpoints for plan upgrade and downgrade
MikeSoft007 Aug 24, 2024
54e2e55
Merge remote-tracking branch 'origin/dev' into bugfix/google_auth
MikeSoft007 Aug 24, 2024
44defcd
Merge pull request #967 from traderstechie/feat/delete-blog-like
johnson-oragui Aug 24, 2024
1aa2f99
Merge branch 'dev' into DrInTech
DrInTech22 Aug 24, 2024
fcb2a11
Merge remote-tracking branch 'origin/dev' into bugfix/google_auth
MikeSoft007 Aug 24, 2024
9c44cfd
Merge pull request #973 from hngprojects/DrInTech
DrInTech22 Aug 24, 2024
a112f58
feat: implement product search on dashboard
Nifilat Aug 24, 2024
4df7127
feat: enhance endpoints for plan upgrade and downgrade
MikeSoft007 Aug 24, 2024
2020065
Merge remote-tracking branch 'origin/dev' into bugfix/google_auth
MikeSoft007 Aug 24, 2024
87ac768
feat: enhance endpoints for plan upgrade and downgrade
MikeSoft007 Aug 24, 2024
d1b99fc
feat:added test files to cover functionality
Nifilat Aug 24, 2024
82374e5
Merge remote-tracking branch 'upstream/dev' into dev
Nifilat Aug 24, 2024
6f447b2
Merge branch 'dev' into feat/product-search-on-dashboard
Nifilat Aug 24, 2024
c56fe40
Merge pull request #974 from MikeSoft007/bugfix/google_auth
johnson-oragui Aug 24, 2024
b4f1127
Merge remote-tracking branch 'upstream/dev' into dev
Nifilat Aug 24, 2024
358e9e3
Merge branch 'dev' into feat/product-search-on-dashboard
Nifilat Aug 24, 2024
7aa8a2b
Merge pull request #975 from Nifilat/feat/product-search-on-dashboard
joboy-dev Aug 24, 2024
5ad25dc
Update regression-test.yml
Sarahligbe Aug 24, 2024
69bb51d
fix: validate status code type
JoshuaOloton Aug 24, 2024
c20d01f
Merge branch 'dev' of https://github.com/hngprojects/hng_boilerplate_…
JoshuaOloton Aug 24, 2024
0d0c333
Merge pull request #976 from hngprojects/Sarahligbe-patch-7
DrInTech22 Aug 24, 2024
afefb45
Merge branch 'dev' into fix/status-page-script
joboy-dev Aug 24, 2024
6529035
fix: added email service to squeeze sign up
Aug 24, 2024
675963c
fix: added email service to squeeze sign up
Aug 24, 2024
0a10f7a
Merge remote-tracking branch 'origin/dev' into bugfix/squeeze_fix
Aug 24, 2024
36787b3
fix: added email service to squeeze sign up
Aug 24, 2024
f764b97
fix: added email service to squeeze sign up
Aug 24, 2024
dc8cc2a
Merge pull request #978 from SundayMba/bugfix/squeeze_fix
CodewithSegNet Aug 24, 2024
fca14ed
Merge branch 'dev' into fix/status-page-script
joboy-dev Aug 25, 2024
ef004ea
Merge pull request #977 from JoshuaOloton/fix/status-page-script
joboy-dev Aug 25, 2024
60c8150
Added send email template endpoint
theijhay Aug 25, 2024
d2ce65f
Merge pull request #979 from theijhay/feat/send-email-template
joboy-dev Aug 25, 2024
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
48 changes: 48 additions & 0 deletions .github/workflows/regression-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Run Regression Tests

on:
schedule:
- cron: '*/15 * * * *' # Runs every 15 minutes
workflow_dispatch:


jobs:
run-newman-test:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "20"

- name: Install Newman
run: |
npm install -g newman

- name: Run Newman Tests
run: |
newman run qa_tests/Boilerplate-status-page.postman_collection.json -r json --reporter-json-export=result.json --suppress-exit-code

- name: Copy result.json to server
uses: appleboy/[email protected]
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
password: ${{ secrets.PASSWORD }}
source: "result.json"
target: "/home/${{ secrets.USERNAME }}/hng_boilerplate_python_fastapi_web/staging"

- name: Deploy to Server
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
password: ${{ secrets.PASSWORD }}
script: |
cd hng_boilerplate_python_fastapi_web/staging
python3 update_api_status.py


2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ MANIFEST
test_case1.py
api/core/dependencies/mailjet.py
tests/v1/waitlist/waitlist_test.py

result.json
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
Expand Down
56 changes: 56 additions & 0 deletions api/core/dependencies/email/templates/squeeze.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{% extends 'base.html' %}

{% block title %}Welcome{% endblock %}

{% block content %}
<table role="presentation" width="100%" style="padding: 3.5rem;">
<tr>
<td>
<div style="text-align: center; margin-bottom: 1.5rem;">
<h1 style="font-size: 1.5rem; color: #0A0A0A; font-weight: 600;">Welcome to Boilerplate Squeeze</h1>
<p style="font-size: 1.125rem; color: rgba(0, 0, 0, 0.8); font-weight: 500;">Thanks for signing up</p>
</div>

<div>
<p style="color: #111; font-size: 1.125rem; font-weight: 600;">Hi {{name}}</p>
<p style="color: rgba(17, 17, 17, 0.9); font-weight: 400;">Experience quality and innovation
like never before. Our product is made to fit your needs and make your
life easier.</p>
</div>

<div style="margin-bottom: 1.75rem;">
<h3 style="color: #0A0A0A; font-weight: 600;">Here's what you can look forward to.</h3>
<div style="margin-bottom: 1.25rem;">
<ul>
<li>
<span style="font-weight: 600;">Exclusive Offers:</span> Enjoy special promotions and
discounts available only to our members.
</li>
<li>
<span style="font-weight: 600;">Exclusive Offers:</span> Enjoy special promotions and
discounts available only to our members.
</li>
<li>
<span style="font-weight: 600;">Exclusive Offers:</span> Enjoy special promotions and
discounts available only to our members.
</li>
</ul>
</div>
</div>

<a href="{{cta_link}}" style="display: block; width: fit-content; padding: 0.5rem 2.5rem; background-color: #F97316; color: white; text-decoration: none; border-radius: 0.5rem; margin: 0 auto; text-align: center;">
Learn more about us
</a>

<!-- <div style="margin-top: 2rem;">
<p style="color: #111; font-size: 0.875rem; font-weight: 500;">Thank you for joining Boilerplate</p>
</div> -->

<div style="margin-top: 2rem;">
<p>Regards,</p>
<p>Boilerplate</p>
</div>
</td>
</tr>
</table>
{% endblock %}
2 changes: 2 additions & 0 deletions api/v1/models/billing_plan.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# app/models/billing_plan.py
from sqlalchemy import Column, String, ARRAY, ForeignKey, Numeric, Boolean
from sqlalchemy.orm import relationship
from sqlalchemy import DateTime
from api.v1.models.base_model import BaseTableModel


Expand Down Expand Up @@ -34,3 +35,4 @@ class UserSubscription(BaseTableModel):
user = relationship("User", back_populates="subscriptions")
billing_plan = relationship("BillingPlan", back_populates="user_subscriptions")
organisation = relationship("Organisation", back_populates="user_subscriptions")
billing_cycle = Column(DateTime, nullable=True)
52 changes: 50 additions & 2 deletions api/v1/routes/blog.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from api.utils.pagination import paginated_response
from api.utils.success_response import success_response
from api.v1.models.user import User
from api.v1.models.blog import Blog, BlogDislike, BlogLike
from api.v1.models.blog import Blog
from api.v1.schemas.blog import (
BlogCreate,
BlogPostResponse,
Expand All @@ -20,7 +20,7 @@
CommentRequest,
CommentUpdateResponseModel
)
from api.v1.services.blog import BlogService
from api.v1.services.blog import BlogService, BlogDislikeService, BlogLikeService
from api.v1.services.user import user_service
from api.v1.schemas.comment import CommentCreate, CommentSuccessResponse
from api.v1.services.comment import comment_service
Expand Down Expand Up @@ -118,6 +118,7 @@ def like_blog_post(
current_user: User = Depends(user_service.get_current_user),
):
"""Endpoint to add `like` to a blog post.
Existing `dislike` by the `current_user` is automatically deleted.

args:
blog_id: `str` The ID of the blog post.
Expand All @@ -137,6 +138,9 @@ def like_blog_post(
# confirm current user has NOT liked before
blog_service.check_user_already_liked_blog(blog_p, current_user)

# check for BlogDislike by current user and delete it
blog_service.delete_opposite_blog_like_or_dislike(blog_p, current_user, "like")

# update likes
new_like = blog_service.create_blog_like(
db, blog_p.id, current_user.id, ip_address=get_ip_address(request))
Expand All @@ -160,6 +164,7 @@ def dislike_blog_post(
current_user: User = Depends(user_service.get_current_user),
):
"""Endpoint to add `dislike` to a blog post.
Existing `like` by the `current_user` is automatically deleted.

args:
blog_id: `str` The ID of the blog post.
Expand All @@ -179,6 +184,9 @@ def dislike_blog_post(
# confirm current user has NOT disliked before
blog_service.check_user_already_disliked_blog(blog_p, current_user)

# check for BlogLike by current user and delete it
blog_service.delete_opposite_blog_like_or_dislike(blog_p, current_user, "dislike")

# update disikes
new_dislike = blog_service.create_blog_dislike(
db, blog_p.id, current_user.id, ip_address=get_ip_address(request))
Expand Down Expand Up @@ -299,3 +307,43 @@ async def update_blog_comment(
status_code=200,
data=jsonable_encoder(updated_blog_comment)
)


@blog.delete("/likes/{blog_like_id}",
status_code=status.HTTP_204_NO_CONTENT)
async def delete_blog_like(
blog_like_id: str,
db: Session = Depends(get_db),
current_user: User = Depends(user_service.get_current_user),
):
"""Endpoint to delete `BlogLike`

args:
blog_like_id: `str` The ID of the BlogLike object.
request: `default` Request.
db: `default` Session.
"""
blog_like_service = BlogLikeService(db)

# delete blog like
return blog_like_service.delete(blog_like_id, current_user.id)


@blog.delete("/dislikes/{blog_dislike_id}",
status_code=status.HTTP_204_NO_CONTENT)
def delete_blog_dislike(
blog_dislike_id: str,
db: Session = Depends(get_db),
current_user: User = Depends(user_service.get_current_user),
):
"""Endpoint to delete `BlogDislike`

args:
blog_dislike_id: `str` The ID of the BlogDislike object.
request: `default` Request.
db: `default` Session.
"""
blog_dislike_service = BlogDislikeService(db)

# delete blog dislike
return blog_dislike_service.delete(blog_dislike_id, current_user.id)
23 changes: 22 additions & 1 deletion api/v1/routes/email_template.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from fastapi import APIRouter, Depends, status
from fastapi import APIRouter, Depends, status, HTTPException
from fastapi.encoders import jsonable_encoder
from sqlalchemy.orm import Session

Expand Down Expand Up @@ -92,3 +92,24 @@ async def delete_email_template(
"""Endpoint to delete a single template"""

email_template_service.delete(db, template_id=template_id)


@email_template.post("/{template_id}/send", response_model=success_response, status_code=200)
async def send_email_template(
template_id: str,
recipient_email: str,
db: Session = Depends(get_db),
current_user: User = Depends(user_service.get_current_super_admin),
):
"""Endpoint to send an email template to a recipient"""

send_result = email_template_service.send(db=db, template_id=template_id, recipient_email=recipient_email)

if send_result["status"] == "failure":
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=send_result["message"])

return success_response(
data=send_result,
message=f"Email sent successfully to {recipient_email}",
status_code=status.HTTP_200_OK,
)
27 changes: 15 additions & 12 deletions api/v1/routes/newsletter.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,23 @@ async def sub_newsletter(
# Save user to the database
NewsletterService.create(db, request)

link = "https://anchor-python.teams.hng.tech/"

# Send email in the background
background_tasks.add_task(
send_email,
recipient=request.email,
template_name="newsletter-subscription.html",
subject="Thank You for Subscribing to HNG Boilerplate Newsletters",
context={"link": link},
)
link = "https://anchor-python.teams.hng.tech/"

# Send email in the background
background_tasks.add_task(
send_email,
recipient=request.email,
template_name="newsletter-subscription.html",
subject="Thank You for Subscribing to HNG Boilerplate Newsletters",
context={"link": link},
)
message = "Thank you for subscribing to our newsletter."
else:
message = "You have already subscribed to our newsletter. Thank you."

return success_response(
message="Thank you for subscribing to our newsletter.",
status_code=status.HTTP_201_CREATED,
message=message,
status_code=status.HTTP_200_OK,
)


Expand Down
Loading
Loading