-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Added new HTML templates for Admin - Added enum UserRole to User model - Fixed hashing in authorization routers - Location model changed to be flatter
- Loading branch information
Showing
37 changed files
with
374 additions
and
104 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{% if data | is_iter %} | ||
<ul> | ||
{% for value in data %} | ||
<li>{{ value }}</li> | ||
{% endfor %} | ||
</ul> | ||
{% else %} | ||
{{ "{} {} ".format(data["type"], data["coordinates"]) }} | ||
{% endif %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<div class="{% if error %}{{ field.error_class }}{% endif %}"> | ||
<div class="input-group"> | ||
<span class="input-group-text">Longitude</span> | ||
<input id="{{ field.id + '.longitude' }}" name="{{ field.id + '.longitude' }}" | ||
class="{{ field.class_ }} {% if error %}{{ field.error_class }}{% endif %}" | ||
value="{{ '' if data is none else data['coordinates'][0] }}" {{ field.input_params() | safe }} /> | ||
<span class="input-group-text">Latitude</span> | ||
<input id="{{ field.id + '.latitude' }}" name="{{ field.id + '.latitude' }}" | ||
class="{{ field.class_ }} {% if error %}{{ field.error_class }}{% endif %}" | ||
value="{{ '' if data is none else data['coordinates'][1] }}" {{ field.input_params() | safe }} /> | ||
</div> | ||
{% if field.help_text %} | ||
<small class="form-hint">{{ field.help_text }}</small> | ||
{% endif %} | ||
</div> | ||
{% include "forms/_error.html" %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{% extends "layout.html" %} | ||
{% block content %} | ||
<h2>Welcome to your Mongoengine admin panel</h2> | ||
{% endblock %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
from starlette.middleware import Middleware | ||
from starlette.middleware.sessions import SessionMiddleware | ||
from starlette_admin.contrib.mongoengine import Admin | ||
|
||
from admin.auth import AdminCredentialsProvider | ||
from admin.converter import MongoengineModelConverter | ||
from admin.views import EventView, ContactView, UserView | ||
from config import DATA_PATH | ||
from contacts.models import Contact | ||
from events.models import Event | ||
from users.models import User | ||
|
||
|
||
admin = Admin( | ||
templates_dir=str(DATA_PATH / "templates" / "admin"), | ||
auth_provider=AdminCredentialsProvider(), | ||
middlewares=[Middleware(SessionMiddleware, secret_key="ads1d21m21")] | ||
) | ||
|
||
admin.add_view(UserView(User, converter=MongoengineModelConverter(), icon="fa-solid fa-users")) | ||
admin.add_view(ContactView(Contact, converter=MongoengineModelConverter(), icon="fa-solid fa-people-arrows")) | ||
admin.add_view(EventView(Event, converter=MongoengineModelConverter(), icon="fa-solid fa-calendar-day"),) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
from fastapi import Request, Response | ||
|
||
|
||
from starlette_admin.auth import AuthProvider, AdminUser | ||
from starlette_admin.exceptions import FormValidationError, LoginFailed | ||
|
||
from authorization import service | ||
from authorization.phonenumber import validate_mobile_phone_number | ||
from users.enums import UserRole | ||
from users.models import User | ||
|
||
users = { | ||
"admin": { | ||
"name": "Admin", | ||
"avatar": "admin.png", | ||
"company_logo_url": "admin.png", | ||
"roles": ["read", "create", "edit", "delete", "action_make_published"], | ||
}, | ||
"johndoe": { | ||
"name": "John Doe", | ||
"avatar": None, # user avatar is optional | ||
"roles": ["read", "create", "edit", "action_make_published"], | ||
}, | ||
"viewer": {"name": "Viewer", "avatar": "guest.png", "roles": ["read"]}, | ||
} | ||
|
||
|
||
class AdminCredentialsProvider(AuthProvider): | ||
|
||
async def login( | ||
self, | ||
username: str, | ||
password: str, | ||
remember_me: bool, | ||
request: Request, | ||
response: Response, | ||
) -> Response: | ||
try: | ||
phone_number = validate_mobile_phone_number(username) | ||
except ValueError: | ||
raise FormValidationError({"username": "Incorrect format"}) | ||
|
||
user: User | None = service.get_user_by_phone_number(phone_number) | ||
if not user or not user.check_password(password): | ||
raise LoginFailed("Invalid phone number or password") | ||
|
||
if user.role not in UserRole.managers(): | ||
raise LoginFailed("Permission denied") | ||
|
||
if user.banned: | ||
raise LoginFailed("This user is banned") | ||
|
||
request.session.update(phone_number=user.phone_number) | ||
return response | ||
|
||
|
||
async def is_authenticated(self, request: Request) -> bool: | ||
phone_number: str = request.session.get("phone_number") | ||
if not phone_number: | ||
return False | ||
|
||
user: User | None = service.get_user_by_phone_number(phone_number) | ||
if not user or user.banned: | ||
return False | ||
|
||
request.state.user = user | ||
return True | ||
|
||
def get_admin_user(self, request: Request) -> AdminUser: | ||
user: User = request.state.user | ||
photo_url = user.photo_urls[0] if len(user.photo_urls) > 0 else None | ||
return AdminUser(username=user.phone_number, photo_url=photo_url) | ||
|
||
async def logout(self, request: Request, response: Response) -> Response: | ||
request.session.clear() | ||
return response |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
from mongoengine import PointField as MongoPointField, LazyReferenceField | ||
from starlette_admin import BaseField, StringField | ||
from starlette_admin.contrib.mongoengine.converters import ModelConverter | ||
from starlette_admin.converters import converts | ||
|
||
from admin.fields import PointField | ||
|
||
|
||
class MongoengineModelConverter(ModelConverter): | ||
|
||
@converts(MongoPointField) | ||
def conv_point_field(self, *args, **kwargs) -> BaseField: | ||
return PointField(**self._field_common(*args, **kwargs)) | ||
|
||
|
||
@converts(LazyReferenceField) | ||
def conv_lazy_reference_field(self, *args, **kwargs) -> BaseField: | ||
return StringField(**self._field_common(*args, **kwargs)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
from dataclasses import dataclass | ||
from typing import Any, Sequence | ||
|
||
from starlette.datastructures import FormData | ||
from starlette.requests import Request | ||
from starlette_admin import fields as admin_fields, RequestAction | ||
|
||
|
||
@dataclass | ||
class PointField(admin_fields.FloatField): | ||
form_template: str = "forms/geopoint.html" | ||
display_template: str = "displays/geopoint.html" | ||
|
||
async def parse_form_data( | ||
self, request: Request, form_data: FormData, action: RequestAction | ||
) -> Sequence[float] | None: | ||
try: | ||
longitude = float(form_data.get(self.id + ".longitude")) | ||
latitude = float(form_data.get(self.id + ".latitude")) | ||
except ValueError: | ||
return None | ||
|
||
return longitude, latitude | ||
|
||
async def serialize_value( | ||
self, request: Request, value: dict, action: RequestAction | ||
) -> Any: | ||
return dict(value) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
from fastapi import Request | ||
|
||
from starlette_admin import PhoneField | ||
from starlette_admin.contrib.mongoengine import ModelView | ||
|
||
from users.enums import UserRole | ||
|
||
|
||
class UserView(ModelView): | ||
fields = [ | ||
"id", | ||
PhoneField("phone_number"), | ||
"is_active", | ||
"banned", | ||
"photo_urls", | ||
"profile", | ||
"last_online", | ||
] | ||
exclude_fields_from_edit = ["phone_number", ] | ||
exclude_fields_from_list = ["profile.location", ] | ||
|
||
def can_create(self, request: Request) -> bool: | ||
return UserRole.ADMIN == request.state.user.role | ||
|
||
|
||
|
||
class EventView(ModelView): | ||
fields = [ | ||
"id", | ||
"title", | ||
"start_at", | ||
"city_id", | ||
"description", | ||
"location", | ||
"image_urls", | ||
] | ||
exclude_fields_from_list = ["location", "image_urls", "description"] | ||
|
||
|
||
|
||
|
||
class ContactView(ModelView): | ||
fields = [ | ||
"initiator", | ||
"respondent", | ||
"initiator_state", | ||
"respondent_state", | ||
"status", | ||
"messages" | ||
] | ||
|
||
exclude_fields_from_list = ["messages"] | ||
exclude_fields_from_edit = ["messages"] | ||
|
||
def can_create(self, request: Request) -> bool: | ||
return UserRole.ADMIN == request.state.user.role | ||
|
||
def can_edit(self, request: Request) -> bool: | ||
return UserRole.ADMIN == request.state.user.role | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.