Enhance CSRF protection and logging in various components

- Added CSRF token handling in BaseView and CSRFSchema.
- Updated routes to include CSRF flag for user actions.
- Improved logging for CSRF token and request parameters in DataTables.
- Refactored templates to support CSRF token integration.
1 parent b8c3dea9
......@@ -14,7 +14,7 @@ from pyramid.config import Configurator
from pyramid.events import NewRequest, BeforeRender, subscriber
from pyramid_mailer import mailer_factory_from_settings
from sqlalchemy import engine_from_config
from pyramid.csrf import get_csrf_token
from opensipkd.tools import get_settings, DefaultTimeZone, dmy, dmyhms, get_ext
from .security import MySecurityPolicy, get_user
from .models.base import DBSession
......@@ -100,7 +100,7 @@ def add_cors_headers_response_callback(event):
# _logging.debug(f"Headers: {headers}")
response.headers.update(headers)
_logging.warning(response.headers)
_logging.debug(response.headers)
event.request.add_response_callback(cors_headers)
......@@ -246,8 +246,11 @@ def get_config(settings):
config = Configurator(settings=settings,
root_factory='opensipkd.base.models.users.RootFactory',
session_factory=session_factory)
config.set_default_csrf_options(require_csrf=False)
require_csrf = settings.get("csrf")
require_csrf = require_csrf and str(require_csrf).lower() in ['1', 'true', 'yes'] or False
config.set_default_csrf_options(require_csrf=require_csrf)
config.set_security_policy(MySecurityPolicy(settings["session.secret"]))
config.add_subscriber(add_cors_headers_response_callback, NewRequest)
config.add_request_method(get_app_name, 'app_name', reify=True)
config.add_request_method(get_menus, 'menus', reify=True)
......@@ -275,7 +278,7 @@ def get_config(settings):
# reify=True)
# config.add_request_method(_get_ini, 'get_ini', reify=True)
# config.add_request_method(get_params, 'get_params', reify=True)
# config.add_request_method(get_csrf_token, 'get_csrf_token', reify=True)
config.add_request_method(get_csrf_token, 'get_csrf_token', reify=True)
# # Penambahan Module Auto Generate Menu
# # config.add_request_method(get_module_menus, 'get_module_menus', reify=True)
......@@ -372,6 +375,7 @@ def _add_route(config, route):
def _add_view_config(config, paket, route):
_logging.debug(f"Add View Config for Route: {route}")
_add_route(config, route)
if not route.get("func_name"):
func_name = "".join(route.get("kode").split('-')[-1:])
......@@ -415,7 +419,7 @@ def _add_view_config(config, paket, route):
if route.get("permission"):
params["permission"] = route.get("permission")
if route.get("crsf"):
if route.get("csrf"):
params["require_csrf"] = True
if route.get("request_method"):
params["request_method"] = route.get("request_method")
......@@ -424,6 +428,7 @@ def _add_view_config(config, paket, route):
params.pop("renderer", None)
config.add_view(views.as_view(), **params)
else:
# _logging.debug(f"Add View Config : {params}")
config.add_view(views, **params)
except Exception as e:
......@@ -646,6 +651,7 @@ def add_global(event):
event['has_modules'] = has_modules
event['get_params'] = get_params_
# event['urlencode'] = urlencode
# event['quote_plus'] = quote_plus
# event['quote'] = quote
......
......@@ -10,11 +10,11 @@ base-register,/register,base,register,,view_register,,,,Register,1,0,,0,form8.pt
base-recreate-api-key,/recreate-api-key,base,register,ViewPassword,recreate-api-key,,,,Get Api Key,1,0,,0,recreate-api-key.pt,
base-admin,#,base,,,,,view,,Administrator,1,0,,1,,
base-user,/user,base,user,,view_list,,user-view,base-admin,User,1,0,,1,form.pt,
base-user-act,/user/{act}/act,base,user,,,,user-view,base-user,User Action,1,0,,,json,
base-user-add,/user/add,base,user,,,,user-edit,base-user,User Add,1,0,,,form6.pt,
base-user-edit,/user/{id}/edit,base,user,,,,user-edit,base-user,User Edit,1,0,,,form6.pt,
base-user-view,/user/{id}/view,base,user,,,,user-view,base-user,User View,1,0,,,form6.pt,
base-user-delete,/user/{id}/delete,base,user,,,,user-edit,base-user,User Delete,1,0,,,form6.pt,
base-user-act,/user/{act}/act,base,user,,,,user-view,base-user,User Action,1,0,,,json,1
base-user-add,/user/add,base,user,,,,user-edit,base-user,User Add,1,0,,,form6.pt,1
base-user-edit,/user/{id}/edit,base,user,,,,user-edit,base-user,User Edit,1,0,,,form6.pt,1
base-user-view,/user/{id}/view,base,user,,,,user-view,base-user,User View,1,0,,,form6.pt,1
base-user-delete,/user/{id}/delete,base,user,,,,user-edit,base-user,User Delete,1,0,,,form6.pt,1
base-partner,/partner,base,partner,,view_list,,admin,base-admin,Partner,1,0,,1,form.pt,
base-partner-act,/partner/{act}/act,base,partner,,,,admin,base-partner,Partner Action,1,0,,,json,
base-partner-add,/partner/add,base,partner,,,,admin,base-partner,Partner Add,1,0,,,form6.pt,
......
......@@ -10,7 +10,7 @@ from pyramid.view import view_config
from opensipkd.base import get_params, get_home
from pyramid.renderers import render_to_response
#, get_urls
from .base_views import BaseView
from .base_views import BaseView, CSRFSchema
#, DataTables
from datetime import timedelta
from opensipkd.detable import *
......
......@@ -49,7 +49,8 @@ class CSRFSchema(colander.Schema):
self["csrf_token"] = colander.SchemaNode(
colander.String(), widget=widget.HiddenWidget(),
default=csrf_token
default=csrf_token,
missing=colander.drop
)
......@@ -440,6 +441,7 @@ class BaseView(object):
scroll_y=scroll_y,
scroll_x=scroll_x,
html_buttons=html_buttons,
csrf_token=get_csrf_token(self.req),
**kwargs
)
resources = table.get_widget_resources()
......@@ -541,7 +543,10 @@ class BaseView(object):
# log.debug(str(columns))
# qry = query.add_columns(*[c.sqla_expr for c in columns])
# log.debug(str(qry))
row_table = DataTables(self.req.GET, query, columns)
if self.req.POST:
row_table = DataTables(self.req.POST, query, columns)
else:
row_table = DataTables(self.req.GET, query, columns)
result = row_table.output_result()
data = result and result.get("data") or {}
for res in data:
......
......@@ -45,6 +45,7 @@ class DataTables(BaseDataTables):
def output_result(self):
"""Output results in the format needed by DataTables."""
output = {}
log.debug(self.params)
output['draw'] = str(int(self.params['draw']))
output['recordsTotal'] = str(self.cardinality)
output['recordsFiltered'] = str(self.cardinality_filtered)
......
......@@ -9,7 +9,7 @@ from pyramid.view import view_config
from sqlalchemy import (func, )
from ziggurat_foundations.models.services.user import UserService
from . import BaseView
from . import BaseView, CSRFSchema
# from .company import company_widget
from .user_login import (
regenerate_security_code, send_email_security_code, generate_api_key, )
......@@ -296,7 +296,7 @@ def save_user(values, user, row=None):
return row
class AddSchema(colander.Schema):
class AddSchema(CSRFSchema):
email = colander.SchemaNode(
colander.String(), title=_('Email'),
validator=email_validator)
......@@ -314,6 +314,8 @@ class AddSchema(colander.Schema):
# colander.Integer(), widget=company_widget,
# title="Company",
# missing=colander.drop)
def after_bind(self, schema, kwargs):
super().after_bind(schema, kwargs)
class EditSchema(AddSchema):
......
......@@ -67,12 +67,6 @@ class Login(CSRFSchema):
def after_bind(self, schema, kwargs):
super().after_bind(schema, kwargs)
request = kwargs["request"]
# csrf_token = new_csrf_token(request)
# log.debug(csrf_token)
# self["csrf_token"] = colander.SchemaNode(
# colander.String(), widget=widget.HiddenWidget(),
# default=csrf_token
# )
if BASE_CLASS.login_captcha:
self["captcha"] = colander.SchemaNode(
colander.String(),
......
......@@ -138,6 +138,7 @@ class DeTable(field.Field):
self.filter_columns = filter_columns
self.scroll_x = json.dumps(scroll_x)
self.scroll_y = json.dumps(scroll_y)
self.csrf_token = kw.get("csrf_token", "")
# self.widget = None
# Button yang dikirim sebagai tambahan
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!