Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions app/database/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class User(Base):
avatar = Column(String, default="profile.png")
telegram_id = Column(String, unique=True)
is_active = Column(Boolean, default=False)
privacy = Column(String, default="Private", nullable=False)
Copy link
Contributor

Choose a reason for hiding this comment

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

If the only values you expect are "private" and "public", consider using boolean type - True ( for private) and Falsr (for public).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Originally the feature was planned to contain "friends" as a level of privacy.
This feature has yet to be approved or implemented but I think a room for this option and other levels of privacy can be allowed

Copy link
Contributor

Choose a reason for hiding this comment

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

So maybe use Enum?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As this is not a free text field but rather something from a set of closed options in a dropdown I don't think there is any reason to fear an incorrect value here
Also I am not sure whether in the setting here the solution would be Enum rather than another connecting table like they did in language. In any case I dont think that it is relevant in the situation here right now

Copy link
Contributor

Choose a reason for hiding this comment

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

I think that it's a good practice to add a validation also in backend and in db.
Also, I think that you can get better performance with this option (but I guess we are not worried about that..).

I agree that right now it's too much to add another table.

Please make sure that it's invalid to add a bad value, even if someone tries :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

where would you suggest doing this? I didn't see that anyone did something similar I think... It can't be in the models file obviously.. and as I mentioned no one can enter values I did not specify in the drropdown field, it's not a free text where anyone can enter what they want, just a set of options. Does that not qualify as verifying that only possible values can be entered?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

so anything? or can I resolve this? :)

is_manager = Column(Boolean, default=False)
language_id = Column(Integer, ForeignKey("languages.id"))

Expand Down
32 changes: 32 additions & 0 deletions app/internal/calendar_privacy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from app.dependencies import get_db
from app.database.models import User
# TODO switch to using this when the user system is merged
# from app.internal.security.dependancies import (
# current_user, CurrentUser)

from fastapi import Depends


# TODO add privacy as an attribute in current user
# in app.internal.security.dependancies
# when user system is merged
def can_show_calendar(
requested_user_username: str,
db: Depends(get_db),
current_user: User
# TODO to be added after user system is merged:
# CurrentUser = Depends(current_user)
) -> bool:
"""Check whether current user can show the requested calendar"""
requested_user = db.query(User).filter(
User.username == requested_user_username
).first()
privacy = current_user.privacy
is_current_user = current_user.username == requested_user.username
if privacy == 'Private' and is_current_user:
return True

elif privacy == 'Public':
return True

return False
17 changes: 17 additions & 0 deletions app/routers/profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,23 @@ async def update_telegram_id(
return RedirectResponse(url=url, status_code=HTTP_302_FOUND)


@router.post("/privacy")
async def update_calendar_privacy(
request: Request,
session=Depends(get_db)
):
user = session.query(User).filter_by(id=1).first()
data = await request.form()
new_privacy = data['privacy']

# Update database
Copy link
Contributor

Choose a reason for hiding this comment

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

you can delete the comment

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This comment appears in all the other forms so I just kept the same structure :) Unless a decision is made to remove the comments from all the file I think this should stay

user.privacy = new_privacy
session.commit()

url = router.url_path_for("profile")
return RedirectResponse(url=url, status_code=HTTP_302_FOUND)


@router.get("/holidays/import")
def import_holidays(request: Request):
return templates.TemplateResponse("import_holidays.html", {
Expand Down
4 changes: 4 additions & 0 deletions app/static/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,7 @@ p {
.subtitle {
font-size: 20px;
}

h2.modal-title {
font-size: 1.25rem;
}
44 changes: 37 additions & 7 deletions app/templates/profile.html
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@
Register telegram Id
</button>
</li>
<li class="list-group-item no-border">
<button type="button" class="btn text-secondary p-1 dropdown-item" data-bs-toggle="modal"
data-bs-target="#calendarPrivacyModal">
Update calendar privacy
</button>
</li>
</ul>
</div>

Expand All @@ -54,7 +60,7 @@
<div class="modal-dialog profile-modal-dialog profile-modal-fadeIn">
<div class="modal-content">
<div class="modal-header profile-modal-header">
<h5 class="modal-title">{{ gettext("Update name") }}</h5>
<h2 class="modal-title">{{ gettext("Update name") }}</h2>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
Expand All @@ -76,7 +82,7 @@ <h5 class="modal-title">{{ gettext("Update name") }}</h5>
<div class="modal-dialog profile-modal-dialog profile-modal-fadeIn">
<div class="modal-content">
<div class="modal-header profile-modal-header">
<h5 class="modal-title">{{ gettext("Update email") }}</h5>
<h2 class="modal-title">{{ gettext("Update email") }}</h2>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
Expand All @@ -99,7 +105,7 @@ <h5 class="modal-title">{{ gettext("Update email") }}</h5>
<div class="modal-dialog profile-modal-dialog profile-modal-fadeIn">
<div class="modal-content">
<div class="modal-header profile-modal-header">
<h5 class="modal-title">{{ gettext("Update description") }}</h5>
<h2 class="modal-title">{{ gettext("Update description") }}</h2>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
Expand All @@ -122,7 +128,7 @@ <h5 class="modal-title">{{ gettext("Update description") }}</h5>
<div class="modal-dialog profile-modal-dialog profile-modal-fadeIn">
<div class="modal-content">
<div class="modal-header profile-modal-header">
<h5 class="modal-title">{{ gettext("Update photo") }}</h5>
<h2 class="modal-title">{{ gettext("Update photo") }}</h2>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
Expand All @@ -145,7 +151,7 @@ <h5 class="modal-title">{{ gettext("Update photo") }}</h5>
<div class="modal-dialog profile-modal-dialog profile-modal-fadeIn">
<div class="modal-content">
<div class="modal-header profile-modal-header">
<h5 class="modal-title">My Telegram Id</h5>
<h2 class="modal-title">My Telegram Id</h2>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
Expand All @@ -161,6 +167,30 @@ <h5 class="modal-title">My Telegram Id</h5>
</div>
</div>
</div>

<!-- Calendar Privacy -->
<div class="modal modal-sm" id="calendarPrivacyModal" tabindex="-1" data-bs-backdrop="static"
aria-labelledby="updateCalendarPrivacyModalLabel" aria-hidden="true">
<div class="modal-dialog profile-modal-dialog profile-modal-fadeIn">
<div class="modal-content">
<div class="modal-header profile-modal-header">
<h2 class="modal-title">Set your calendar privacy</h2>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form action="update_calendar_privacy" method="post">
<select class="form-control-sm" name="privacy">
<option value="private">Private</option>
<option value="public">Public</option>
</select>
<div class="d-flex flex-row-reverse mt-4">
<button type="submit" class="btn btn-sm btn-success">Save changes</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<!-- End profile update menu -->

Expand Down Expand Up @@ -282,7 +312,7 @@ <h6 class="card-title text-center mb-1">{{ user.full_name }}</h6>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Update Event</h5>
<h2 class="modal-title">Update Event</h2>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
Expand Down Expand Up @@ -341,4 +371,4 @@ <h5 class="modal-title">Update Event</h5>
</div>
</div>
</div>
{% include "event/partials/text_editor_partial_body.html" %} {% endblock %}
{% include "event/partials/text_editor_partial_body.html" %} {% endblock %}
43 changes: 43 additions & 0 deletions tests/test_calendar_privacy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
from app.internal.calendar_privacy import can_show_calendar
# TODO after user system is merged:
# from app.internal.security.dependancies import CurrentUser
from app.routers.user import create_user


def test_can_show_calendar_public(session, user):
user.privacy = "Public"
# TODO to be replaced after user system is merged:
# current_user = CurrentUser(**user.__dict__)
current_user = user
result = can_show_calendar(
requested_user_username='test_username',
db=session, current_user=current_user
)
assert result is True
session.commit()


def test_can_show_calendar_private(session, user):
another_user = create_user(
session=session,
username='new_test_username2',
email='new_test.email2@gmail.com',
password='passpar_2',
language_id=1
)
current_user = user
# TODO to be replaced after user system is merged:
# current_user = CurrentUser(**user.__dict__)

result_a = can_show_calendar(
requested_user_username='new_test_username2',
db=session, current_user=current_user
)
result_b = can_show_calendar(
requested_user_username='test_username',
db=session, current_user=current_user
)
assert result_a is False
assert result_b is True
Copy link
Contributor

Choose a reason for hiding this comment

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

you can write it down as
assert result_b

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 got a previous comment saying to do the opposite haha ... let's just stay with this:)

session.delete(another_user)
session.commit()
17 changes: 17 additions & 0 deletions tests/test_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,20 @@ def test_upload_user_photo(profile_test_client):
new_avatar_path = os.path.join(MEDIA_PATH, 'fake_user.png')
assert Image.open(new_avatar_path).size == config.AVATAR_SIZE
os.remove(new_avatar_path)


def test_update_calendar_privacy(profile_test_client):
new_privacy = {
'privacy': "Public"
}
# Get profile page and initialize database
profile = profile_test_client.get('/profile')

# Post new data
profile = profile_test_client.post(
'/profile/privacy', data=new_privacy)
assert profile.status_code == status.HTTP_302_FOUND

# Get updated data
data = profile_test_client.get('/profile').content
assert b"Public" in data