#!/usr/bin/env python3 """ Paramecio2fm is a series of wrappers for Flask, mako and others and construct a simple headless cms. Copyright (C) 2023 Antonio de la Rosa Caballero This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . """ from paramecio2.libraries.db import corefields from paramecio2.libraries.db.coreforms import PasswordForm from paramecio2.libraries.i18n import I18n from paramecio2.libraries.keyutils import create_key_encrypt from paramecio2.libraries.i18n import I18n, PGetText # For tests outing the web framework try: from settings import config except: class config: pass framework='flask' if hasattr(config, 'framework'): framework=config.framework if framework=='flask': from flask import session, request, abort elif framework=='fastapi': from parameciofast.libraries.sessions import get_session pass # Need unittest """Functions and classes for process forms""" def pass_values_to_form(post, arr_form, yes_error=True, pass_values=True): """Function for pass a dict with form values for check using forms dict Values dict and Forms dict need have the same key. A forms dict is maked of a serie of paramecio2 forms elements, used for check the value. Args: post (dict): Dict composed by a series of values. The keys need to be equal to keys of arr_form dict. arr_form (dict): Dict composed by a series or forms objects. The keys need to be equal to keys of post dict. yes_error (bool): Show errors in txt_error form variables. pass_values (bool): Pass default values or values from post dict to arr_form dict items Returns: arr_form (dict): Return arr_form dict with checked values from post dict. """ if pass_values: def get_value(key): return post[key] else: def get_value(key): return arr_form[key].default_value for key, value in arr_form.items(): post[key]=post.get(key, '') #if arr_form[key].default_value=='': arr_form[key].default_value=get_value(key) if arr_form[key].field==None: arr_form[key].field=corefields.CharField(key, 255, required=False) # Recheck value if no set error field if arr_form[key].field.error == None: arr_form[key].field.check(post[key]) #arr_form[key].txt_error="" if arr_form[key].required==True and arr_form[key].field.error==True and yes_error==True: arr_form[key].txt_error=arr_form[key].field.txt_error # Reset error on field. arr_form[key].field.error=None return arr_form class CheckForm(): """Simple class for make similar check to pass_values_to_form. More simple. """ def __init__(self): self.error=0 def check(self, post, arr_form): """Simple method for pass a dict with form values for check using forms dict Values dict and Forms dict need have the same key. A forms dict is maked of a serie of paramecio2 forms elements, used for check the value. Args: post (dict): Dict composed by a series of values. The keys need to be equal to keys of arr_form dict. arr_form (dict): Dict composed by a series or forms objects. The keys need to be equal to keys of post dict. Returns: post (dict): Return post dict with values checked arr_form (dict): Return arr_form with errors and values. """ for k in arr_form.keys(): post[k]=post.get(k, '') if arr_form[k].field==None: arr_form[k].field=corefields.CharField(k, 255, required=False) post[k]=arr_form[k].field.check(post[k]) arr_form[k].txt_error=arr_form[k].field.txt_error if arr_form[k].field.error==True and arr_form[k].required==True: self.error+=1 return post, arr_form def check_form(post, arr_form, sufix_form='_error'): """Function for make check form, passing errors to extra dict called error_form. Also returns an bool variable setting error. Args: post (dict): Dict composed by a series of values. The keys need to be equal to keys of arr_form dict. arr_form (dict): Dict composed by a series or forms objects. The keys need to be equal to keys of post dict. sufix_form (str): Define the sufix of error_form keys Returns: error (bool): Return False if not errors in checking, if errors return True error_form (dict): A dict containing the errors in form fields. post (dict): Sanitized values arr_form (dict): arr_form with errors and values. """ error=0 error_form={} for k in arr_form.keys(): post[k]=post.get(k, '') if arr_form[k].field==None: arr_form[k].field=corefields.CharField(k, 255, required=False) post[k]=arr_form[k].field.check(post[k]) arr_form[k].txt_error=arr_form[k].field.txt_error if arr_form[k].field.error==True and arr_form[k].required==True: error_form['#'+k+sufix_form]=arr_form[k].txt_error error+=1 return error, error_form, post, arr_form def show_form(post, arr_form, t, yes_error=True, pass_values=True, modelform_tpl='forms/modelform.phtml'): """Function for generate a html form from a template Args: post (dict): Dict composed by a series of values. The keys need to be equal to keys of arr_form dict. arr_form (dict): Dict composed by a series or forms objects. The keys need to be equal to keys of post dict. t (PTemplate): Object used for load template for form yes_error (bool): Show errors in txt_error form variables. pass_values (bool): Pass default values or values from post dict to arr_form dict items modelform_tpl (str): Path for the template that generate the html form. By default is paramecio2/libraries/templates/forms/modelform.phtml Returns: template (str): An html string with the generated form. """ # Create csrf_token in session #generate_csrf() if pass_values==True: pass_values_to_form(post, arr_form, yes_error, pass_values) return t.load_template(modelform_tpl, forms=arr_form) def extract_post(post, fields): """Helper function for create a simple array from other using fields list for filter Args: post (dict): A dict with keys and values to filter. fields (list): A list with keys to validate. """ return {k:v for k,v in post.items() if k in fields} #Simple Function for add repeat_password form to user model def set_extra_forms_user(user_admin): """Helper function for add extraforms to UserModel form, not for general use Args: user_admin (UserModel): Instance of UserModel object for modify forms and fields """ user_admin.fields['password'].required=True user_admin.fields['email'].required=True user_admin.create_forms(['username', 'email', 'password']) user_admin.forms['repeat_password']=PasswordForm('repeat_password', '') user_admin.forms['repeat_password'].required=True user_admin.forms['repeat_password'].label=_('Repeat Password') def csrf_token(token_id='csrf_token'): """Function for generate a csrf token html hide form using flask sessions Args: token_id (str): Name of the html hide form Returns: html (str): Return html input hidden with csrf token saved in session """ #s=get_session() if not 'csrf_token' in session: session['csrf_token']=create_key_encrypt() return '' def generate_csrf(): """Function for generate a csrf token in a variable Returns: csrf_token (str): csrf token value """ if not 'csrf_token' in session: session['csrf_token']=create_key_encrypt() return session['csrf_token'] def check_csrf(name_csrf_token='csrf_token'): csrf_token=session.get('csrf_token', '') if csrf_token=='' or csrf_token!=request.form.get(name_csrf_token): abort(403)