Skip to content

Commit

Permalink
Merge pull request #41 from DhafinFK/rollback-branch
Browse files Browse the repository at this point in the history
fix: returned admin feature
  • Loading branch information
DhafinFK authored Aug 3, 2024
2 parents 5b1644e + 4c914bf commit 8b36800
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 1 deletion.
2 changes: 2 additions & 0 deletions app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from app.views.auth import router_auth
from app.views.main import router_main
from app.views.review import router_review
from app.views.admin import router_admin
from app.cron import cron
from uploader.views import router_uploader

Expand Down Expand Up @@ -86,6 +87,7 @@
app.register_blueprint(router_main, url_prefix=app.config["BASE_PATH"])
app.register_blueprint(router_uploader, url_prefix=app.config["BASE_PATH"])
app.register_blueprint(router_review, url_prefix=app.config["BASE_PATH"])
app.register_blueprint(router_admin, url_prefix=app.config["BASE_PATH"])
app.register_blueprint(cron)

CORS(app)
Expand Down
12 changes: 12 additions & 0 deletions app/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,16 @@ def decorated_func(*args, **kwargs):
'message': 'There is no token/token is not valid'
}), 401)
return func(*args, **kwargs)
return decorated_func


def require_admin_jwt(func):
@functools.wraps(func)
def decorated_func(*args, **kwargs):
data = extract_header_data(request.headers)
if(data['credentials'] == os.environ.get("ADMIN_CREDENTIAL_VERIFICATION")):
return func(*args, **kwargs)
return (jsonify({
'message': 'Unauthorized access'
}), 403)
return decorated_func
9 changes: 8 additions & 1 deletion app/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,11 @@ def process_sso_profile(sso_profile):


def get_app_config(varname):
return app.config.get(varname)
return app.config.get(varname)


def generate_admin_jwt():
token = encode_token({
'credentials': os.environ.get("ADMIN_CREDENTIAL_VERIFICATION")
})
return token
145 changes: 145 additions & 0 deletions app/views/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import html
from flask import (
Blueprint,
jsonify,
request
)

from datetime import datetime
from app.decorators import require_jwt_token, require_admin_jwt
from app.jwt_utils import decode_token
from models.admin import Admin
from models.review import Review
from app.utils import generate_admin_jwt

router_admin = Blueprint('router_admin', __name__)

@router_admin.route('/admin', methods=['GET'])
@require_jwt_token
@require_admin_jwt
def admin_test():
return (jsonify({
"Message": "Admin api accessed."
}), 200)


@router_admin.route("/admin/login", methods=['POST'])
def admin_login():
data = request.json
username = data.get('username')
password = data.get('password')

admin = Admin.objects(username=username).first()

if(admin and admin.check_password(password)):
token = generate_admin_jwt()
return (jsonify({
'token': token
}), 200)

return (jsonify({
'message': 'Invalid credentials.'
}), 401)



@router_admin.route("admin/reviews-overview", methods=['GET'])
@require_jwt_token
@require_admin_jwt
def admin_review_overview():
total_reviews = Review.objects.count()
if total_reviews == 0:
return jsonify({
'average_rating': 0,
'rating_counts': {str(i): 0 for i in range(1, 6)}
}), 200

total_rating = Review.objects.sum('rating')
average_rating = total_rating / total_reviews

rating_counts = {str(i): Review.objects(rating=i).count() for i in range(1, 6)}

return jsonify({
'average_rating': average_rating,
'rating_counts': rating_counts
}), 200


@router_admin.route("/admin/reviews/list", methods=['GET'])
@require_jwt_token
@require_admin_jwt
def admin_review_list():
try:
page = int(request.args.get('page', 1))
except ValueError:
return (jsonify({
'message': 'Invalid page number.'
}), 400)

if page <= 0:
return (jsonify({
'message': 'Page must be a positive integer.'
}), 400)

data = request.json if request.json else {}
per_page = data.get('per_page', 10)

try:
per_page = int(per_page)
if per_page <= 0:
raise ValueError
except ValueError:
return jsonify({'message': 'per_page must be a positive integer.'}), 400

skip = (page - 1) * per_page

reviews = Review.objects.order_by('-created_at').skip(skip).limit(per_page)
total_reviews = Review.objects.count()
total_pages = (total_reviews + per_page - 1) // per_page

serialized_reviews = [review.serialize() for review in reviews]

return jsonify({
'page': page,
'total_page': total_pages,
'per_page': per_page,
'total_reviews': total_reviews,
'reviews': serialized_reviews
}), 200


@router_admin.route("admin/review/status/<review_id>", methods=['PATCH'])
@require_jwt_token
@require_admin_jwt
def admin_edit_review_status(review_id):
data = request.json
new_status = data.get("reviewed")

if new_status is None:
return jsonify({'message': 'Missing reviewed status.'}), 400

try:
review = Review.objects.get(id=review_id)
except Review.DoesNotExist:
return jsonify({'message': 'Review not found.'}), 404

review.reviewed = new_status
review.save()

return jsonify({
'id': str(review.id),
'reviewed': review.reviewed
}), 200


@router_admin.route("/admin/review/delete/<review_id>", methods=['DELETE'])
@require_jwt_token
@require_admin_jwt
def admin_delete_review(review_id):
try:
review = Review.objects.get(id=review_id)
except Review.DoesNotExist:
return jsonify({'message': 'Review not found.'}), 404

review.delete()
return jsonify({'message': 'Review deleted successfully.'}), 200
10 changes: 10 additions & 0 deletions models/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import mongoengine as mongo
from werkzeug.security import check_password_hash


class Admin(mongo.Document):
username = mongo.StringField(max_length=256, required=True)
password = mongo.StringField(max_length=256, required=True)

def check_password(self, password):
return check_password_hash(self.password, password)

0 comments on commit 8b36800

Please sign in to comment.