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

Feature/public event #287

Open
wants to merge 41 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
5ef6469
basic restoration of code from a deleted branch. includes- adding is_…
noam-y Feb 11, 2021
885a843
added 2 functions- one to send an adaptable email, with email body co…
noam-y Feb 11, 2021
1f4b084
added front end button to allow users to join event, not connected to…
noam-y Feb 11, 2021
8e0d1ee
adding testing fixtures
noam-y Feb 11, 2021
5a8adeb
adding working user and event fixture, adding is_public param to even…
noam-y Feb 11, 2021
59532d6
subtle changes for debugging add_user_to_event failing tests.
noam-y Feb 11, 2021
235c4b2
added something that prevents adding null event_id to userevent objects.
noam-y Feb 12, 2021
d32ca25
fixed a small bug that made one of the tests fail
noam-y Feb 12, 2021
ef0f679
added func that send email to participants given event id- there are …
noam-y Feb 12, 2021
c6477a5
email not working- last commit before rebuild
noam-y Feb 12, 2021
b7cc686
merged changes
noam-y Feb 12, 2021
540f1bf
merged with current changes + added one func that sends emails to all…
noam-y Feb 14, 2021
49ac8e7
improved documentation
noam-y Feb 14, 2021
e111110
adds feature that makes sure only the event owner can send email to a…
noam-y Feb 14, 2021
573cd2b
Merge branch 'develop' of https://github.com/PythonFreeCourse/calenda…
noam-y Feb 15, 2021
847eb09
merged changes w pulled code
noam-y Feb 15, 2021
b9d6016
Merge branch 'develop' into feature/public_event
yammesicka Feb 18, 2021
e715f4c
merging conflicts
noam-y Feb 18, 2021
14fc7e2
merge with code
noam-y Feb 18, 2021
f515361
trying to add is_public feature to telegram create event bot
noam-y Feb 18, 2021
e4f2ee0
creating more changes to enable public feature on create event func o…
noam-y Feb 18, 2021
9ffa3ea
last chance to add telegram feature- will be deleted soon...
noam-y Feb 18, 2021
e8571f1
reverting changes made on telegram
noam-y Feb 18, 2021
05c90a1
merging changes from pulled code
noam-y Feb 19, 2021
71ee772
changed email sending function to depend on send function so its more…
noam-y Feb 19, 2021
9cf15b1
moving user and event fixtures to conftest.py so we can use them glob…
noam-y Feb 20, 2021
70be019
changing mailing list sender to return the number of emails sent inst…
noam-y Feb 20, 2021
1bc712c
making test to assert failure of sending mailing list with no logged …
noam-y Feb 20, 2021
f371ce1
merging conflicts
noam-y Feb 20, 2021
05310b7
splitting mailing list send to 2 tests- one where no user is logged (…
noam-y Feb 20, 2021
c02ffd0
small pep changes
noam-y Feb 20, 2021
8a58f78
Merge branch 'develop' of https://github.com/PythonFreeCourse/calenda…
noam-y Feb 21, 2021
b6ff758
deleting some visual comments according to yam's commends + hooks
noam-y Feb 21, 2021
093881b
trying to add precommit hooks
noam-y Feb 23, 2021
7b4ee13
merge conflicts
noam-y Feb 25, 2021
986b43b
Merge branch 'feature/public_event' of https://github.com/noam-y/cale…
noam-y Feb 25, 2021
cf5b771
finally merged conflicts
noam-y Feb 26, 2021
76db81a
added guards and small changes
noam-y Feb 26, 2021
9bbed18
Merge branch 'develop' of https://github.com/PythonFreeCourse/calenda…
noam-y Feb 26, 2021
94c4a32
first try of adding koby's user system to event mailing list send
noam-y Feb 26, 2021
b08636e
moving user fixtures from conftest to user_fixtures.
noam-y Feb 26, 2021
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
2 changes: 2 additions & 0 deletions app/database/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class User(Base):
privacy = Column(String, default="Private", nullable=False)
is_manager = Column(Boolean, default=False)
language_id = Column(Integer, ForeignKey("languages.id"))
availability = Column(Boolean, default=True, nullable=False)
target_weight = Column(Float, nullable=True)

owned_events = relationship(
Expand Down Expand Up @@ -97,6 +98,7 @@ class Event(Base):
color = Column(String, nullable=True)
all_day = Column(Boolean, default=False)
invitees = Column(String)
is_public = Column(Boolean, default=False)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Event doesn't have "friends" option?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the meaning of friends is different- public event is meant to allow any user in the platform to join the event, just like the public events on facebook. so it means the owner's friends don't matter in this feature :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please explain what is the meaning of public/private event? is it like busy/free?
Thanks

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a pubic event is event anyone can join. it means you don't need to be invited directly from the owner, you can join the event by yourself by clicking a button on event page

privacy = Column(String, default=PrivacyKinds.Public.name, nullable=False)
emotion = Column(String, nullable=True)
availability = Column(Boolean, default=True, nullable=False)
Expand Down
44 changes: 40 additions & 4 deletions app/internal/email.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@

from app.config import (CALENDAR_HOME_PAGE, CALENDAR_REGISTRATION_PAGE,
CALENDAR_SITE_NAME, email_conf, templates)
from app.database.models import Event, User

from app.database.models import Event, User, UserEvent
from app.internal.utils import get_current_user
noam-y marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use Kobi's user system instead

mail = FastMail(email_conf)


def send(
session: Session, event_used: int, user_to_send: int,
title: str, background_tasks: BackgroundTasks = BackgroundTasks
title: str, content: str = "",
background_tasks: BackgroundTasks = BackgroundTasks
noam-y marked this conversation as resolved.
Show resolved Hide resolved
) -> bool:
"""This function is being used to send emails in the background.
It takes an event and a user and it sends the event to the user.
Expand Down Expand Up @@ -48,10 +49,45 @@ def send(
background_tasks.add_task(send_internal,
subject=subject,
recipients=recipients,
body=body)
body=body + content)
return True


def send_email_to_event_participants(
yammesicka marked this conversation as resolved.
Show resolved Hide resolved
session: Session, event_id: int,
title: str, content: str) -> int:
"""This function sends emails to a mailing list of all event participants.
it uses the function send above to do this and avoid double codes..
Args:
session(Session): The session to redirect to the database.
event_id (int): Id number of the event that is used.
title (str): Title of the email that is being sent.
content (str): body of email sent.
Returns:
int: Returns the number of emails sent
(number of valid emails in event's participants)
"""
event_owner = session.query(Event.owner).filter(id == event_id).first()
if event_owner != get_current_user(session):
return 0
# makes sure only event owner can send an email via this func.
mailing_list = session.query(User.id, User.email).join(
UserEvent, User.id == UserEvent.user_id
).filter(
event_id == event_id).all()
valid_mailing_list = list(filter(verify_email_pattern, mailing_list.email))
if not valid_mailing_list:
return 0
# making sure app doesn't crash if emails are invalid

event = session.query(Event).get(event_id)
subject = f"{event.title}: {title}"
for r in valid_mailing_list:
send(session, event, r.id, subject, content)
# sends the send email function parameters to send on the mailing list
return len(valid_mailing_list)


def send_email_invitation(sender_name: str,
recipient_name: str,
recipient_mail: str,
Expand Down
1 change: 1 addition & 0 deletions app/routers/email.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from app.internal.email import send as internal_send
from app.internal.email import send_email_invitation


router = APIRouter(
prefix="/email",
tags=["email"],
Expand Down
20 changes: 19 additions & 1 deletion app/routers/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from app.internal import comment as cmt
from app.internal.emotion import get_emotion
from app.internal.privacy import PrivacyKinds
from app.internal.utils import create_model, get_current_user
from app.internal.utils import create_model, save, get_current_user
noam-y marked this conversation as resolved.
Show resolved Hide resolved
from app.routers.categories import get_user_categories

EVENT_DATA = Tuple[Event, List[Dict[str, str]], str]
Expand Down Expand Up @@ -393,6 +393,7 @@ def create_event(
vc_link: str = None,
color: Optional[str] = None,
invitees: List[str] = None,
is_public: bool = False,
category_id: Optional[int] = None,
availability: bool = True,
is_google_event: bool = False,
Expand All @@ -416,6 +417,7 @@ def create_event(
color=color,
emotion=get_emotion(title, content),
invitees=invitees_concatenated,
is_public=is_public,
all_day=all_day,
category_id=category_id,
availability=availability,
Expand Down Expand Up @@ -516,6 +518,22 @@ def add_new_event(values: dict, db: Session) -> Optional[Event]:
return None


def add_user_to_event(session: Session, user_id: int, event_id: int):
user_already_connected = (
session.query(UserEvent)
.filter_by(event_id=event_id, user_id=user_id)
.all()
)
if not user_already_connected:
noam-y marked this conversation as resolved.
Show resolved Hide resolved
"""if user is not registered to the event, the system will add him"""
noam-y marked this conversation as resolved.
Show resolved Hide resolved
association = UserEvent(user_id=user_id, event_id=event_id)
save(session, association)
return True
# if the user has a connection to the event,
# the function will recognize the duplicate and return false.
return False


def get_template_to_share_event(
event_id: int,
user_name: str,
Expand Down
70 changes: 70 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import calendar
from datetime import datetime

import pytest
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

from app.config import PSQL_ENVIRONMENT
from app.database.models import Base
from app.routers.event import create_event
from app.routers.user import create_user

pytest_plugins = [
'tests.user_fixture',
Expand Down Expand Up @@ -80,3 +83,70 @@ def sqlite_engine():
@pytest.fixture
def Calendar():
return calendar.Calendar(0)


@pytest.fixture
def no_event_user(session):
"""a user made for testing who doesn't own any event."""
user = create_user(
session=session,
username='new_test_username',
password='new_test_password',
email='[email protected]',
language_id='english'
)

return user
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't create a new fixture, use one of the others.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i have to use several different users since i'm testing the use of the mailing list.



@pytest.fixture
def event_owning_user(session):
"""a user made for testing who already owns an event."""
user = create_user(
session=session,
username='new_test_username2',
password='new_test_password2',
email='[email protected]',
language_id='english'
)

data = {
'title': 'event_owning_user event',
'start': datetime.strptime('2021-05-05 14:59', '%Y-%m-%d %H:%M'),
'end': datetime.strptime('2021-05-05 15:01', '%Y-%m-%d %H:%M'),
'location': 'https://us02web.zoom.us/j/875384596',
'content': 'content',
'owner_id': user.id,
}

create_event(session, **data)

return user
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't create a new fixture, use one of the others. You can use a user fixture and an event fixture in your code to create this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i have to use several different users since i'm testing the use of the mailing list.

__



@pytest.fixture
def user1(session):
"""another user made for testing"""
user = create_user(
session=session,
username='user2user2',
password='verynicepass',
email='[email protected]',
language_id='english'
)
return user
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't create a new user fixture, use one of the others.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i have to use several different users since i'm testing mailing list.



@pytest.fixture
def event_example(session, event_owning_user):
data = {
'title': 'test event title',
'start': datetime.strptime('2021-05-05 14:59', '%Y-%m-%d %H:%M'),
'end': datetime.strptime('2021-05-05 15:01', '%Y-%m-%d %H:%M'),
'location': 'https://us02web.zoom.us/j/87538459r6',
'content': 'content',
'owner_id': event_owning_user.id,
}

event = create_event(session, **data)
return event
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't create a new event fixture, use one of the others.

53 changes: 50 additions & 3 deletions tests/test_email.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
from fastapi import BackgroundTasks, status
import pytest
from sqlalchemy.orm import Session
# from starlette.status import HTTP_302_FOUND

from app.database.models import User
from app.database.models import User, UserEvent
# from app.internal.security.dependancies import current_user
noam-y marked this conversation as resolved.
Show resolved Hide resolved
from app.internal.email import (mail, send, send_email_file,
send_email_invitation, verify_email_pattern)
from app.internal.utils import create_model, delete_instance
send_email_invitation,
send_email_to_event_participants,
verify_email_pattern)
noam-y marked this conversation as resolved.
Show resolved Hide resolved
from app.internal.utils import create_model, delete_instance, save


def test_email_send(client, user, event, smtpd):
Expand Down Expand Up @@ -240,3 +244,46 @@ def test_send(session, bad_user, event):
"test@mail-com"])
def test_verify_email_pattern(email):
assert not verify_email_pattern(email)


def test_sending_mailing_list_with_no_user(session, no_event_user,
event_owning_user,
user1,
event_example):
"""this test assures a wrong user won't be able to use the mailing list"""
association = UserEvent(
user_id=no_event_user.id,
event_id=event_example.id
)
save(session, association)

association2 = UserEvent(
user_id=user1.id,
event_id=event_example.id
)
save(session, association2)

num_emails_send = send_email_to_event_participants(
session, event_example.id, 'this mail example', 'booboo')
assert num_emails_send == 0


def test_sending_mailing_list_from_event_owner(session, no_event_user,
event_owning_user,
user1,
event_example, client,
security_test_client):
"""this test assures mailing list is sent successfuly from
the event owner. assiciations were created already at the test above."""
# logged_user_data = {'username': event_owning_user.username,
# 'password': event_owning_user.password}
pass
# res = security_test_client.post(
# security_test_client.app.url_path_for('login'),
# data=logged_user_data)
# TODO: log in event_owning_user to assure successful mailing list send

# if res.status_code == HTTP_302_FOUND:
# num_emails_send = send_email_to_event_participants(
# session, event_example.id, 'this mail example', 'booboo')
# assert num_emails_send == 2
33 changes: 32 additions & 1 deletion tests/test_event.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
from app.internal.utils import delete_instance
from app.main import app
from app.routers import event as evt
from app.routers.event import event_to_show
from app.routers.event import add_new_event, add_user_to_event, event_to_show
from app.routers.user import create_user

CORRECT_EVENT_FORM_DATA = {
"title": "test title",
Expand Down Expand Up @@ -140,6 +141,36 @@
]


@pytest.fixture
def new_event(session, new_user):
event = add_new_event(TestApp.event_test_data, session)
return event


@pytest.fixture
def new_user(session):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe you can use existing fixtures?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried but didn't really find a proper user fixture inside the file. ill try going over the code again

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are enough user fixtures, use one of the others.

user = create_user(
session=session,
username='new_test_username',
password='new_test_password',
email='[email protected]',
language_id='english'
)

return user


def test_joining_public_event(session, new_event, new_user):
"""test in order to make sure user is added the first time
he asks to join event, yet won't join the same user twice"""
first_join = add_user_to_event(
session, event_id=new_event.id, user_id=new_user.id)
assert first_join
second_join = add_user_to_event(
session, event_id=new_event.id, user_id=new_user.id)
assert not second_join


def test_get_events(event_test_client, session, event):
response = event_test_client.get("/event/")
assert response.ok
Expand Down
Loading