Compare commits
No commits in common. "master" and "dark_theme" have entirely different histories.
master
...
dark_theme
110 changed files with 844 additions and 3138 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -47,7 +47,7 @@ coverage.xml
|
||||||
.hypothesis/
|
.hypothesis/
|
||||||
|
|
||||||
# Translations
|
# Translations
|
||||||
#*.mo
|
*.mo
|
||||||
*.pot
|
*.pot
|
||||||
|
|
||||||
# Django stuff:
|
# Django stuff:
|
||||||
|
|
|
||||||
3
.gitmodules
vendored
3
.gitmodules
vendored
|
|
@ -1,3 +0,0 @@
|
||||||
[submodule "paramecio2/modules/admin/media/js/jsutils"]
|
|
||||||
path = paramecio2/modules/admin/media/js/jsutils
|
|
||||||
url = https://git.cuchulu.com/paramecio/jsutils.git
|
|
||||||
148
LICENSE.txt
148
LICENSE.txt
|
|
@ -1,21 +1,23 @@
|
||||||
GNU AFFERO GENERAL PUBLIC LICENSE
|
GNU GENERAL PUBLIC LICENSE
|
||||||
Version 3, 19 November 2007
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
of this license document, but changing it is not allowed.
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
Preamble
|
Preamble
|
||||||
|
|
||||||
The GNU Affero General Public License is a free, copyleft license for
|
The GNU General Public License is a free, copyleft license for
|
||||||
software and other kinds of works, specifically designed to ensure
|
software and other kinds of works.
|
||||||
cooperation with the community in the case of network server software.
|
|
||||||
|
|
||||||
The licenses for most software and other practical works are designed
|
The licenses for most software and other practical works are designed
|
||||||
to take away your freedom to share and change the works. By contrast,
|
to take away your freedom to share and change the works. By contrast,
|
||||||
our General Public Licenses are intended to guarantee your freedom to
|
the GNU General Public License is intended to guarantee your freedom to
|
||||||
share and change all versions of a program--to make sure it remains free
|
share and change all versions of a program--to make sure it remains free
|
||||||
software for all its users.
|
software for all its users. We, the Free Software Foundation, use the
|
||||||
|
GNU General Public License for most of our software; it applies also to
|
||||||
|
any other work released this way by its authors. You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
When we speak of free software, we are referring to freedom, not
|
When we speak of free software, we are referring to freedom, not
|
||||||
price. Our General Public Licenses are designed to make sure that you
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
|
@ -24,34 +26,44 @@ them if you wish), that you receive source code or can get it if you
|
||||||
want it, that you can change the software or use pieces of it in new
|
want it, that you can change the software or use pieces of it in new
|
||||||
free programs, and that you know you can do these things.
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
Developers that use our General Public Licenses protect your rights
|
To protect your rights, we need to prevent others from denying you
|
||||||
with two steps: (1) assert copyright on the software, and (2) offer
|
these rights or asking you to surrender the rights. Therefore, you have
|
||||||
you this License which gives you legal permission to copy, distribute
|
certain responsibilities if you distribute copies of the software, or if
|
||||||
and/or modify the software.
|
you modify it: responsibilities to respect the freedom of others.
|
||||||
|
|
||||||
A secondary benefit of defending all users' freedom is that
|
For example, if you distribute copies of such a program, whether
|
||||||
improvements made in alternate versions of the program, if they
|
gratis or for a fee, you must pass on to the recipients the same
|
||||||
receive widespread use, become available for other developers to
|
freedoms that you received. You must make sure that they, too, receive
|
||||||
incorporate. Many developers of free software are heartened and
|
or can get the source code. And you must show them these terms so they
|
||||||
encouraged by the resulting cooperation. However, in the case of
|
know their rights.
|
||||||
software used on network servers, this result may fail to come about.
|
|
||||||
The GNU General Public License permits making a modified version and
|
|
||||||
letting the public access it on a server without ever releasing its
|
|
||||||
source code to the public.
|
|
||||||
|
|
||||||
The GNU Affero General Public License is designed specifically to
|
Developers that use the GNU GPL protect your rights with two steps:
|
||||||
ensure that, in such cases, the modified source code becomes available
|
(1) assert copyright on the software, and (2) offer you this License
|
||||||
to the community. It requires the operator of a network server to
|
giving you legal permission to copy, distribute and/or modify it.
|
||||||
provide the source code of the modified version running there to the
|
|
||||||
users of that server. Therefore, public use of a modified version, on
|
|
||||||
a publicly accessible server, gives the public access to the source
|
|
||||||
code of the modified version.
|
|
||||||
|
|
||||||
An older license, called the Affero General Public License and
|
For the developers' and authors' protection, the GPL clearly explains
|
||||||
published by Affero, was designed to accomplish similar goals. This is
|
that there is no warranty for this free software. For both users' and
|
||||||
a different license, not a version of the Affero GPL, but Affero has
|
authors' sake, the GPL requires that modified versions be marked as
|
||||||
released a new version of the Affero GPL which permits relicensing under
|
changed, so that their problems will not be attributed erroneously to
|
||||||
this license.
|
authors of previous versions.
|
||||||
|
|
||||||
|
Some devices are designed to deny users access to install or run
|
||||||
|
modified versions of the software inside them, although the manufacturer
|
||||||
|
can do so. This is fundamentally incompatible with the aim of
|
||||||
|
protecting users' freedom to change the software. The systematic
|
||||||
|
pattern of such abuse occurs in the area of products for individuals to
|
||||||
|
use, which is precisely where it is most unacceptable. Therefore, we
|
||||||
|
have designed this version of the GPL to prohibit the practice for those
|
||||||
|
products. If such problems arise substantially in other domains, we
|
||||||
|
stand ready to extend this provision to those domains in future versions
|
||||||
|
of the GPL, as needed to protect the freedom of users.
|
||||||
|
|
||||||
|
Finally, every program is threatened constantly by software patents.
|
||||||
|
States should not allow patents to restrict development and use of
|
||||||
|
software on general-purpose computers, but in those that do, we wish to
|
||||||
|
avoid the special danger that patents applied to a free program could
|
||||||
|
make it effectively proprietary. To prevent this, the GPL assures that
|
||||||
|
patents cannot be used to render the program non-free.
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and
|
The precise terms and conditions for copying, distribution and
|
||||||
modification follow.
|
modification follow.
|
||||||
|
|
@ -60,7 +72,7 @@ modification follow.
|
||||||
|
|
||||||
0. Definitions.
|
0. Definitions.
|
||||||
|
|
||||||
"This License" refers to version 3 of the GNU Affero General Public License.
|
"This License" refers to version 3 of the GNU General Public License.
|
||||||
|
|
||||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
works, such as semiconductor masks.
|
works, such as semiconductor masks.
|
||||||
|
|
@ -537,45 +549,35 @@ to collect a royalty for further conveying from those to whom you convey
|
||||||
the Program, the only way you could satisfy both those terms and this
|
the Program, the only way you could satisfy both those terms and this
|
||||||
License would be to refrain entirely from conveying the Program.
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
13. Remote Network Interaction; Use with the GNU General Public License.
|
13. Use with the GNU Affero General Public License.
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, if you modify the
|
|
||||||
Program, your modified version must prominently offer all users
|
|
||||||
interacting with it remotely through a computer network (if your version
|
|
||||||
supports such interaction) an opportunity to receive the Corresponding
|
|
||||||
Source of your version by providing access to the Corresponding Source
|
|
||||||
from a network server at no charge, through some standard or customary
|
|
||||||
means of facilitating copying of software. This Corresponding Source
|
|
||||||
shall include the Corresponding Source for any work covered by version 3
|
|
||||||
of the GNU General Public License that is incorporated pursuant to the
|
|
||||||
following paragraph.
|
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, you have
|
Notwithstanding any other provision of this License, you have
|
||||||
permission to link or combine any covered work with a work licensed
|
permission to link or combine any covered work with a work licensed
|
||||||
under version 3 of the GNU General Public License into a single
|
under version 3 of the GNU Affero General Public License into a single
|
||||||
combined work, and to convey the resulting work. The terms of this
|
combined work, and to convey the resulting work. The terms of this
|
||||||
License will continue to apply to the part which is the covered work,
|
License will continue to apply to the part which is the covered work,
|
||||||
but the work with which it is combined will remain governed by version
|
but the special requirements of the GNU Affero General Public License,
|
||||||
3 of the GNU General Public License.
|
section 13, concerning interaction through a network will apply to the
|
||||||
|
combination as such.
|
||||||
|
|
||||||
14. Revised Versions of this License.
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
The Free Software Foundation may publish revised and/or new versions of
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
the GNU Affero General Public License from time to time. Such new versions
|
the GNU General Public License from time to time. Such new versions will
|
||||||
will be similar in spirit to the present version, but may differ in detail to
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
address new problems or concerns.
|
address new problems or concerns.
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the
|
Each version is given a distinguishing version number. If the
|
||||||
Program specifies that a certain numbered version of the GNU Affero General
|
Program specifies that a certain numbered version of the GNU General
|
||||||
Public License "or any later version" applies to it, you have the
|
Public License "or any later version" applies to it, you have the
|
||||||
option of following the terms and conditions either of that numbered
|
option of following the terms and conditions either of that numbered
|
||||||
version or of any later version published by the Free Software
|
version or of any later version published by the Free Software
|
||||||
Foundation. If the Program does not specify a version number of the
|
Foundation. If the Program does not specify a version number of the
|
||||||
GNU Affero General Public License, you may choose any version ever published
|
GNU General Public License, you may choose any version ever published
|
||||||
by the Free Software Foundation.
|
by the Free Software Foundation.
|
||||||
|
|
||||||
If the Program specifies that a proxy can decide which future
|
If the Program specifies that a proxy can decide which future
|
||||||
versions of the GNU Affero General Public License can be used, that proxy's
|
versions of the GNU General Public License can be used, that proxy's
|
||||||
public statement of acceptance of a version permanently authorizes you
|
public statement of acceptance of a version permanently authorizes you
|
||||||
to choose that version for the Program.
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
|
@ -633,29 +635,41 @@ the "copyright" line and a pointer to where the full notice is found.
|
||||||
Copyright (C) <year> <name of author>
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU Affero General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
If your software can interact with users remotely through a computer
|
If the program does terminal interaction, make it output a short
|
||||||
network, you should also make sure that it provides a way for users to
|
notice like this when it starts in an interactive mode:
|
||||||
get its source. For example, if your program is a web application, its
|
|
||||||
interface could display a "Source" link that leads users to an archive
|
<program> Copyright (C) <year> <name of author>
|
||||||
of the code. There are many ways you could offer source, and different
|
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
solutions will be better for different programs; see section 13 for the
|
This is free software, and you are welcome to redistribute it
|
||||||
specific requirements.
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, your program's commands
|
||||||
|
might be different; for a GUI interface, you would use an "about box".
|
||||||
|
|
||||||
You should also get your employer (if you work as a programmer) or school,
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
For more information on this, and how to apply and follow the GNU AGPL, see
|
For more information on this, and how to apply and follow the GNU GPL, see
|
||||||
<https://www.gnu.org/licenses/>.
|
<http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
The GNU General Public License does not permit incorporating your program
|
||||||
|
into proprietary programs. If your program is a subroutine library, you
|
||||||
|
may consider it more useful to permit linking proprietary applications with
|
||||||
|
the library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License. But first, please read
|
||||||
|
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ Also, you need the next software installed in your os:
|
||||||
|
|
||||||
### Python 3.10 or later.
|
### Python 3.10 or later.
|
||||||
|
|
||||||
Paramecio should work fine in 3.5-3.9 but is tested in 3.10, 3.11 and 3.12 python 3 versions actually.
|
Paramecio should work fine in 3.5-3.9 but is tested in 3.10 and 3.11 python 3 versions actually.
|
||||||
|
|
||||||
In Debian and Ubuntu you can install Python 3 using the next command: `apt-get install python3`.
|
In Debian and Ubuntu you can install Python 3 using the next command: `apt-get install python3`.
|
||||||
|
|
||||||
|
|
@ -20,7 +20,7 @@ In Fedora and other Red Hat derived distros you can use `yum install python3`. I
|
||||||
|
|
||||||
### MySQL or MariaDB database servers.
|
### MySQL or MariaDB database servers.
|
||||||
|
|
||||||
MariaDB 10.6 and later are recommended but is compatible with previous versions.
|
MariaDB 10.6 and later are recommended but is compatible with MariaDB 10.
|
||||||
|
|
||||||
In Debian and Ubuntu you can install MariaDB using the next command: `apt-get install mariadb-server`.
|
In Debian and Ubuntu you can install MariaDB using the next command: `apt-get install mariadb-server`.
|
||||||
|
|
||||||
|
|
@ -53,7 +53,7 @@ You can install the framework using the next command in your server:
|
||||||
|
|
||||||
or if you want development version:
|
or if you want development version:
|
||||||
|
|
||||||
`pip3 install git+https://git.cuchulu.com/paramecio/paramecio2fm.git`
|
`pip3 install git+https://git.cuchulu.com/absurdo/paramecio2fm.git`
|
||||||
|
|
||||||
This command will install in your server paramecio framework with its dependencies.
|
This command will install in your server paramecio framework with its dependencies.
|
||||||
|
|
||||||
|
|
@ -67,6 +67,3 @@ If you get an error in your installation of dependencies how MarkupSafe or SqlAl
|
||||||
|
|
||||||
`apt-get install python3-mako python3-sqlalchemy` and try pip3 command again.
|
`apt-get install python3-mako python3-sqlalchemy` and try pip3 command again.
|
||||||
|
|
||||||
## Documentation
|
|
||||||
|
|
||||||
You can find paramecio2 documentation in this [site](https://docs.cuchulu.com/paramecio2/)
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
==========================================================
|
==========================================================
|
||||||
Paramecio is a simple framework based in flask and mako.
|
Paramecio is a simple framework based in bottle and mako.
|
||||||
==========================================================
|
==========================================================
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
"""
|
|
||||||
Paramecio2fm is a series of wrappers for Flask, mako and others and construct a simple headless cms.
|
|
||||||
|
|
||||||
Copyright (C) 2025 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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
@ -1,22 +1,3 @@
|
||||||
"""
|
|
||||||
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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from flask import Flask, session, url_for, request, send_file, abort
|
from flask import Flask, session, url_for, request, send_file, abort
|
||||||
from settings import config
|
from settings import config
|
||||||
from importlib import import_module
|
from importlib import import_module
|
||||||
|
|
@ -24,28 +5,6 @@ import os
|
||||||
import sys
|
import sys
|
||||||
import inspect
|
import inspect
|
||||||
from paramecio2.libraries.datetime import set_timezone
|
from paramecio2.libraries.datetime import set_timezone
|
||||||
try:
|
|
||||||
import ujson as json
|
|
||||||
except:
|
|
||||||
import json
|
|
||||||
|
|
||||||
flask_session=False
|
|
||||||
|
|
||||||
if hasattr(config, 'flask_session'):
|
|
||||||
|
|
||||||
flask_session=config.flask_session
|
|
||||||
|
|
||||||
if flask_session:
|
|
||||||
|
|
||||||
from flask_session import Session
|
|
||||||
from redis import Redis
|
|
||||||
SESSION_TYPE='redis'
|
|
||||||
SESSION_REDIS=Redis(host='localhost', port=6379)
|
|
||||||
|
|
||||||
swagger_app=False
|
|
||||||
|
|
||||||
if hasattr(config, 'swagger_app'):
|
|
||||||
swagger_app=config.swagger_app
|
|
||||||
|
|
||||||
def start_app():
|
def start_app():
|
||||||
|
|
||||||
|
|
@ -88,13 +47,7 @@ def start_app():
|
||||||
workdir=os.getcwd()
|
workdir=os.getcwd()
|
||||||
arr_module_path={}
|
arr_module_path={}
|
||||||
|
|
||||||
# Load blueprints from json file (for installed modules using paramecio2 utilities)
|
# Load blueprints
|
||||||
|
|
||||||
if os.path.isfile('./settings/modules.json'):
|
|
||||||
|
|
||||||
with open('./settings/modules.json') as f:
|
|
||||||
json_apps=json.loads(f.read())
|
|
||||||
config.apps=json_apps | config.apps
|
|
||||||
|
|
||||||
for key_app, added_app in config.apps.items():
|
for key_app, added_app in config.apps.items():
|
||||||
|
|
||||||
|
|
@ -106,14 +59,9 @@ def start_app():
|
||||||
|
|
||||||
app_name=getattr(controller_path, added_app[1])
|
app_name=getattr(controller_path, added_app[1])
|
||||||
|
|
||||||
#print(os.path.dirname(sys.modules[added_app[0]].__file__))
|
|
||||||
#print(key_app)
|
|
||||||
|
|
||||||
arr_module_path[key_app]=os.path.dirname(sys.modules[added_app[0]].__file__)
|
|
||||||
|
|
||||||
for controller in dir_controllers:
|
for controller in dir_controllers:
|
||||||
|
|
||||||
if controller.find('.py')!=-1 and not controller.startswith('__'):
|
if controller.find('.py')!=-1 and controller.find('__init__')==-1:
|
||||||
|
|
||||||
controller_py=controller.replace('.py', '')
|
controller_py=controller.replace('.py', '')
|
||||||
|
|
||||||
|
|
@ -121,8 +69,7 @@ def start_app():
|
||||||
|
|
||||||
a=import_module(module_app)
|
a=import_module(module_app)
|
||||||
|
|
||||||
#arr_module_path[key_app]=os.path.dirname(sys.modules[module_app].__file__)
|
arr_module_path[key_app]=os.path.dirname(sys.modules[module_app].__file__)
|
||||||
|
|
||||||
if config.application_root=='/':
|
if config.application_root=='/':
|
||||||
app.register_blueprint(app_name, url_prefix=added_app[2])
|
app.register_blueprint(app_name, url_prefix=added_app[2])
|
||||||
else:
|
else:
|
||||||
|
|
@ -148,10 +95,6 @@ def start_app():
|
||||||
|
|
||||||
if not os.path.isfile(file_path):
|
if not os.path.isfile(file_path):
|
||||||
#file_path=workdir+'/modules/'+module+'/media/'+media_file
|
#file_path=workdir+'/modules/'+module+'/media/'+media_file
|
||||||
|
|
||||||
if not module in arr_module_path:
|
|
||||||
abort(404)
|
|
||||||
|
|
||||||
file_path=arr_module_path[module]+'/media/'+media_file
|
file_path=arr_module_path[module]+'/media/'+media_file
|
||||||
|
|
||||||
if not os.path.isfile(file_path):
|
if not os.path.isfile(file_path):
|
||||||
|
|
@ -159,12 +102,4 @@ def start_app():
|
||||||
|
|
||||||
return send_file(file_path)
|
return send_file(file_path)
|
||||||
|
|
||||||
if swagger_app:
|
|
||||||
from flasgger import Swagger
|
|
||||||
swagger=Swagger(app)
|
|
||||||
|
|
||||||
if flask_session:
|
|
||||||
app.config.from_object(__name__)
|
|
||||||
Session(app)
|
|
||||||
|
|
||||||
return app
|
return app
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
from paramecio2.libraries.db.webmodel import WebModel
|
from paramecio2.libraries.db.webmodel import WebModel
|
||||||
from paramecio2.libraries.load_apps import load_extra_modules
|
|
||||||
|
|
||||||
secret_key="im smoking fool"
|
secret_key="im smoking fool"
|
||||||
|
|
||||||
|
|
@ -11,8 +10,6 @@ static_url_path='/media/default'
|
||||||
|
|
||||||
apps={'welcome': ['paramecio2.modules.welcome', 'welcome_app', '/']}
|
apps={'welcome': ['paramecio2.modules.welcome', 'welcome_app', '/']}
|
||||||
|
|
||||||
apps=load_extra_modules(apps)
|
|
||||||
|
|
||||||
default_module='welcome'
|
default_module='welcome'
|
||||||
|
|
||||||
theme="default"
|
theme="default"
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,5 @@
|
||||||
#!/usr/bin/env python3
|
#!/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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
|
|
@ -41,7 +22,7 @@ def start():
|
||||||
|
|
||||||
parser.add_argument('--symlink', help='Set if create direct symlink to paramecio in new site', action='store_true')
|
parser.add_argument('--symlink', help='Set if create direct symlink to paramecio in new site', action='store_true')
|
||||||
|
|
||||||
#parser.add_argument('--tests', help='Create a symlink to tests for check into paramecio site', action='store_true')
|
parser.add_argument('--tests', help='Create a symlink to tests for check into paramecio site', action='store_true')
|
||||||
|
|
||||||
# Options for deploy
|
# Options for deploy
|
||||||
|
|
||||||
|
|
@ -49,9 +30,9 @@ def start():
|
||||||
|
|
||||||
parser.add_argument('--folder', help='If you deploy in a subdirectory, set it, without beggining and ending slashes', required=False)
|
parser.add_argument('--folder', help='If you deploy in a subdirectory, set it, without beggining and ending slashes', required=False)
|
||||||
|
|
||||||
#parser.add_argument('--host', help='The host ip or domain where the app is binded', required=False)
|
parser.add_argument('--host', help='The host ip or domain where the app is binded', required=False)
|
||||||
|
|
||||||
#parser.add_argument('--port', help='Change the default port 8080 to other number. Use 80 is not recommended, use 80 for the proxy server how nginx or apache', required=False)
|
parser.add_argument('--port', help='Change the default port 8080 to other number. Use 80 is not recommended, use 80 for the proxy server how nginx or apache', required=False)
|
||||||
|
|
||||||
args=parser.parse_args()
|
args=parser.parse_args()
|
||||||
|
|
||||||
|
|
@ -107,14 +88,12 @@ def start():
|
||||||
except:
|
except:
|
||||||
print('Error: cannot symlink paramecio in new site')
|
print('Error: cannot symlink paramecio in new site')
|
||||||
|
|
||||||
"""
|
|
||||||
if args.tests==True:
|
if args.tests==True:
|
||||||
try:
|
try:
|
||||||
os.symlink(workdir, args.path+'/paramecio2/', True)
|
os.symlink(workdir, args.path+'/paramecio2/', True)
|
||||||
|
|
||||||
except:
|
except:
|
||||||
print('Error: cannot symlink paramecio2 in new site')
|
print('Error: cannot symlink paramecio2 in new site')
|
||||||
"""
|
|
||||||
|
|
||||||
with open(path_settings+'/config.py', 'r') as f:
|
with open(path_settings+'/config.py', 'r') as f:
|
||||||
conf=f.read()
|
conf=f.read()
|
||||||
|
|
@ -372,7 +351,7 @@ def start():
|
||||||
|
|
||||||
models_files=os.listdir(models_path)
|
models_files=os.listdir(models_path)
|
||||||
|
|
||||||
m=re.compile(r".*\.py$")
|
m=re.compile(".*\.py$")
|
||||||
|
|
||||||
underscore=re.compile("^__.*")
|
underscore=re.compile("^__.*")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,3 @@
|
||||||
"""
|
|
||||||
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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from paramecio2.app import start_app
|
from paramecio2.app import start_app
|
||||||
|
|
||||||
app=start_app()
|
app=start_app()
|
||||||
|
|
||||||
application=app
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,3 @@
|
||||||
"""
|
|
||||||
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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from paramecio2.app import start_app
|
from paramecio2.app import start_app
|
||||||
|
|
||||||
app=start_app()
|
app=start_app()
|
||||||
|
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
"""
|
|
||||||
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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
@ -1,24 +1,5 @@
|
||||||
#!/usr/bin/env python3
|
#!/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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import os, sys
|
import os, sys
|
||||||
|
|
||||||
|
|
@ -28,7 +9,6 @@ import re
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from importlib import import_module
|
from importlib import import_module
|
||||||
from paramecio2.libraries.i18n import I18n
|
from paramecio2.libraries.i18n import I18n
|
||||||
from paramecio2.libraries.slugify import slugify
|
|
||||||
try:
|
try:
|
||||||
from settings import config
|
from settings import config
|
||||||
except:
|
except:
|
||||||
|
|
@ -39,18 +19,12 @@ except:
|
||||||
"""Command line utility for extract I18n.lang strings from html templates and .py files
|
"""Command line utility for extract I18n.lang strings from html templates and .py files
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pattern=re.compile(r'^\w+\.(py|html|phtml|js)$')
|
pattern=re.compile('^\w+\.(py|html|phtml|js)$')
|
||||||
|
|
||||||
ignored=re.compile(r'^[__|\.].*$')
|
ignored=re.compile('^[__|\.].*$')
|
||||||
|
|
||||||
lang_p=re.compile(r"I18n\.lang\('(.*?)',\s+'(.*?)',\s+'(.*?)'\)")
|
lang_p=re.compile("I18n\.lang\('(.*?)',\s+'(.*?)',\s+'(.*?)'\)")
|
||||||
lang_t=re.compile(r"\${lang\('(.*?)',\s+'(.*?)',\s+'(.*?)'\)\}")
|
lang_t=re.compile("\${lang\('(.*?)',\s+'(.*?)',\s+'(.*?)'\)\}")
|
||||||
|
|
||||||
lang_s=re.compile(r"i18n\.slang\('(.*?)',\s+'(.*?)'\)")
|
|
||||||
lang_ts=re.compile(r"\${slang\('(.*?)',\s+'(.*?)'\)\}")
|
|
||||||
|
|
||||||
lang_tl=re.compile(r"i18n\.tlang\('(.*?)'\)")
|
|
||||||
lang_ttl=re.compile(r"\${tlang\('(.*?)'\)\}")
|
|
||||||
|
|
||||||
tmp_lang={}
|
tmp_lang={}
|
||||||
|
|
||||||
|
|
@ -60,16 +34,12 @@ def start():
|
||||||
|
|
||||||
global lang_p
|
global lang_p
|
||||||
global lang_t
|
global lang_t
|
||||||
global lang_s
|
|
||||||
global lang_tl
|
|
||||||
global lang_ts
|
|
||||||
global lang_ttl
|
|
||||||
|
|
||||||
# Module to search a file where save the file.
|
# Module to search a file where save the file.
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description='A tool for create python language files')
|
parser = argparse.ArgumentParser(description='A tool for create python language files')
|
||||||
|
|
||||||
parser.add_argument('--module', help='The module where search lang files', required=True)
|
parser.add_argument('--module', help='The module where search lang files', required=False)
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
|
@ -87,9 +57,9 @@ def start():
|
||||||
|
|
||||||
module_base=os.path.basename(args.module)
|
module_base=os.path.basename(args.module)
|
||||||
|
|
||||||
lang_p=re.compile(r"I18n\.lang\('("+module_base+r"?)',\s+'(.*?)',\s+'(.*?)'\)")
|
lang_p=re.compile("I18n\.lang\('("+module_base+"?)',\s+'(.*?)',\s+'(.*?)'\)")
|
||||||
#lang_t=re.compile("\${lang\('("+module_base+"?)',\s+'(.*?)',\s+'(.*?)'\)\}")
|
#lang_t=re.compile("\${lang\('("+module_base+"?)',\s+'(.*?)',\s+'(.*?)'\)\}")
|
||||||
lang_t=re.compile(r"lang\('("+module_base+r"?)',\s+'(.*?)',\s+'(.*?)'\)")
|
lang_t=re.compile("lang\('("+module_base+"?)',\s+'(.*?)',\s+'(.*?)'\)")
|
||||||
|
|
||||||
if not os.path.isdir(path):
|
if not os.path.isdir(path):
|
||||||
|
|
||||||
|
|
@ -97,7 +67,7 @@ def start():
|
||||||
|
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
scandir(path, path_save, module_base)
|
scandir(path, path_save)
|
||||||
|
|
||||||
#Save the files
|
#Save the files
|
||||||
|
|
||||||
|
|
@ -166,7 +136,7 @@ def start():
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def scandir(path, module_search='', module_base=None):
|
def scandir(path, module_search=''):
|
||||||
|
|
||||||
list=os.listdir(path)
|
list=os.listdir(path)
|
||||||
|
|
||||||
|
|
@ -188,19 +158,6 @@ def scandir(path, module_search='', module_base=None):
|
||||||
match_p=lang_p.findall(line)
|
match_p=lang_p.findall(line)
|
||||||
match_t=lang_t.findall(line)
|
match_t=lang_t.findall(line)
|
||||||
|
|
||||||
match_s=lang_s.findall(line)
|
|
||||||
match_ts=lang_ts.findall(line)
|
|
||||||
|
|
||||||
match_tl=lang_tl.findall(line)
|
|
||||||
match_ttl=lang_ttl.findall(line)
|
|
||||||
|
|
||||||
"""
|
|
||||||
global lang_s
|
|
||||||
global lang_tl
|
|
||||||
global lang_ts
|
|
||||||
global lang_ttl
|
|
||||||
"""
|
|
||||||
|
|
||||||
if match_p!=None:
|
if match_p!=None:
|
||||||
|
|
||||||
for m in match_p:
|
for m in match_p:
|
||||||
|
|
@ -232,44 +189,6 @@ def scandir(path, module_search='', module_base=None):
|
||||||
|
|
||||||
tmp_lang[module][symbol]=tmp_lang[module].get(symbol, text_default)
|
tmp_lang[module][symbol]=tmp_lang[module].get(symbol, text_default)
|
||||||
|
|
||||||
if module_base:
|
|
||||||
|
|
||||||
if match_s!=None:
|
|
||||||
|
|
||||||
for m in match_s:
|
|
||||||
module=base_module
|
|
||||||
symbol=m[0]
|
|
||||||
text_default=m[1]
|
|
||||||
|
|
||||||
tmp_lang[module]=tmp_lang.get(module, {})
|
|
||||||
tmp_lang[module][symbol]=tmp_lang[module].get(symbol, text_default)
|
|
||||||
|
|
||||||
for m in match_ts:
|
|
||||||
module=base_module
|
|
||||||
symbol=m[0]
|
|
||||||
text_default=m[1]
|
|
||||||
|
|
||||||
tmp_lang[module]=tmp_lang.get(module, {})
|
|
||||||
tmp_lang[module][symbol]=tmp_lang[module].get(symbol, text_default)
|
|
||||||
|
|
||||||
|
|
||||||
for m in match_tl:
|
|
||||||
module=base_module
|
|
||||||
symbol=slugify(m[0])
|
|
||||||
text_default=m[0]
|
|
||||||
|
|
||||||
tmp_lang[module]=tmp_lang.get(module, {})
|
|
||||||
tmp_lang[module][symbol]=tmp_lang[module].get(symbol, text_default)
|
|
||||||
|
|
||||||
for m in match_ttl:
|
|
||||||
module=base_module
|
|
||||||
symbol=slugify(m[0][:40])
|
|
||||||
text_default=m[0]
|
|
||||||
|
|
||||||
tmp_lang[module]=tmp_lang.get(module, {})
|
|
||||||
tmp_lang[module][symbol]=tmp_lang[module].get(symbol, text_default)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,3 @@
|
||||||
"""
|
|
||||||
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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Variable base for admin modules
|
# Variable base for admin modules
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,3 @@
|
||||||
"""
|
|
||||||
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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import time
|
import time
|
||||||
from datetime import date, datetime, tzinfo
|
from datetime import date, datetime, tzinfo
|
||||||
import arrow
|
import arrow
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,7 @@
|
||||||
"""
|
|
||||||
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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from paramecio2.libraries.db.webmodel import PhangoField
|
from paramecio2.libraries.db.webmodel import PhangoField
|
||||||
from paramecio2.libraries.db import coreforms
|
from paramecio2.libraries.db import coreforms
|
||||||
from paramecio2.libraries.i18n import I18n
|
from paramecio2.libraries.i18n import I18n
|
||||||
#from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
import bleach
|
|
||||||
|
|
||||||
class IntegerField(PhangoField):
|
class IntegerField(PhangoField):
|
||||||
|
|
||||||
|
|
@ -38,12 +18,6 @@ class IntegerField(PhangoField):
|
||||||
|
|
||||||
super(IntegerField, self).__init__(name, size, required)
|
super(IntegerField, self).__init__(name, size, required)
|
||||||
self.default_value=0
|
self.default_value=0
|
||||||
self.type_sql='int({})'.format(self.size)
|
|
||||||
|
|
||||||
self.default_value=0
|
|
||||||
self.jtype='integer'
|
|
||||||
self.jformat='int64'
|
|
||||||
self.jexample='1'
|
|
||||||
|
|
||||||
def check(self, value):
|
def check(self, value):
|
||||||
|
|
||||||
|
|
@ -88,11 +62,6 @@ class BigIntegerField(IntegerField):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, name, size=11, required=False):
|
|
||||||
|
|
||||||
super().__init__(name, size, required)
|
|
||||||
self.type_sql='bigint({})'.format(self.size)
|
|
||||||
|
|
||||||
def get_type_sql(self):
|
def get_type_sql(self):
|
||||||
|
|
||||||
"""Method for return the sql code for this type
|
"""Method for return the sql code for this type
|
||||||
|
|
@ -118,10 +87,6 @@ class FloatField(PhangoField):
|
||||||
|
|
||||||
self.error_default="The value is zero"
|
self.error_default="The value is zero"
|
||||||
self.default_value=0
|
self.default_value=0
|
||||||
self.type_sql='float'.format(self.size)
|
|
||||||
|
|
||||||
self.jtype='number'
|
|
||||||
self.jformat='float'
|
|
||||||
|
|
||||||
def check(self, value):
|
def check(self, value):
|
||||||
|
|
||||||
|
|
@ -162,13 +127,6 @@ class FloatField(PhangoField):
|
||||||
class DecimalField(FloatField):
|
class DecimalField(FloatField):
|
||||||
"""PhangoField field for Decimals fields."""
|
"""PhangoField field for Decimals fields."""
|
||||||
|
|
||||||
def __init__(self, name, size=11, required=False):
|
|
||||||
|
|
||||||
super().__init__(name, size, required)
|
|
||||||
self.type_sql='decimal(20,2)'
|
|
||||||
|
|
||||||
self.jtype='number'
|
|
||||||
|
|
||||||
def get_type_sql(self):
|
def get_type_sql(self):
|
||||||
|
|
||||||
return 'DECIMAL(20, 2) NOT NULL DEFAULT "0"'
|
return 'DECIMAL(20, 2) NOT NULL DEFAULT "0"'
|
||||||
|
|
@ -176,14 +134,6 @@ class DecimalField(FloatField):
|
||||||
class DoubleField(FloatField):
|
class DoubleField(FloatField):
|
||||||
"""PhangoField field for Double fields."""
|
"""PhangoField field for Double fields."""
|
||||||
|
|
||||||
def __init__(self, name, size=11, required=False):
|
|
||||||
|
|
||||||
super().__init__(name, size, required)
|
|
||||||
self.type_sql='double'
|
|
||||||
|
|
||||||
self.jtype='number'
|
|
||||||
self.jformat='double'
|
|
||||||
|
|
||||||
def get_type_sql(self):
|
def get_type_sql(self):
|
||||||
|
|
||||||
return 'DOUBLE NOT NULL DEFAULT "0"'
|
return 'DOUBLE NOT NULL DEFAULT "0"'
|
||||||
|
|
@ -212,8 +162,6 @@ class TextField(PhangoField):
|
||||||
|
|
||||||
super().__init__(name, 11, required)
|
super().__init__(name, 11, required)
|
||||||
|
|
||||||
self.type_sql='text'
|
|
||||||
|
|
||||||
self.set_default='NOT NULL'
|
self.set_default='NOT NULL'
|
||||||
|
|
||||||
def get_type_sql(self):
|
def get_type_sql(self):
|
||||||
|
|
@ -230,20 +178,6 @@ class LongTextField(TextField):
|
||||||
Class used for text fields, use LONGTEXT sql type for the this field.
|
Class used for text fields, use LONGTEXT sql type for the this field.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, name, required=False):
|
|
||||||
"""Init TextField class different to standard PhangoField
|
|
||||||
|
|
||||||
Args:
|
|
||||||
name (str): The name of new field
|
|
||||||
required (bool): Boolean for define if field is required or not
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
set_default (str): Set if the value es NOT NULL or not
|
|
||||||
"""
|
|
||||||
|
|
||||||
super().__init__(name, required)
|
|
||||||
self.type_sql='longtext'
|
|
||||||
|
|
||||||
def get_type_sql(self):
|
def get_type_sql(self):
|
||||||
|
|
||||||
"""Method for return the sql code for this type
|
"""Method for return the sql code for this type
|
||||||
|
|
@ -270,7 +204,7 @@ class HTMLField(TextField):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
super().__init__(name, required)
|
super().__init__(name, required)
|
||||||
self.trusted_tags=['b', 'strong']
|
self.trusted_tags=[]
|
||||||
|
|
||||||
def check(self, value):
|
def check(self, value):
|
||||||
"""Check method for html values
|
"""Check method for html values
|
||||||
|
|
@ -278,12 +212,9 @@ class HTMLField(TextField):
|
||||||
This check method use beautifulsoap for clean and format html code
|
This check method use beautifulsoap for clean and format html code
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# leach.clean('<p>"trial"</p><script></script>', tags=('p'))
|
|
||||||
"""
|
|
||||||
soup=BeautifulSoup(value, features='html.parser')
|
soup=BeautifulSoup(value, features='html.parser')
|
||||||
|
|
||||||
for tag in soup.findAll(True):
|
for tag in soup.findAll(True):
|
||||||
|
|
||||||
if tag.name not in self.trusted_tags:
|
if tag.name not in self.trusted_tags:
|
||||||
tag.hidden=True
|
tag.hidden=True
|
||||||
|
|
||||||
|
|
@ -296,17 +227,6 @@ class HTMLField(TextField):
|
||||||
|
|
||||||
return value
|
return value
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
value=bleach.clean(value, tags=self.trusted_tags)
|
|
||||||
|
|
||||||
if self.escape:
|
|
||||||
|
|
||||||
return value.replace('"', '"')
|
|
||||||
else:
|
|
||||||
|
|
||||||
return value
|
|
||||||
|
|
||||||
|
|
||||||
class ForeignKeyField(IntegerField):
|
class ForeignKeyField(IntegerField):
|
||||||
"""Subclass of IntegerField for create Foreign keys
|
"""Subclass of IntegerField for create Foreign keys
|
||||||
|
|
@ -385,12 +305,6 @@ class BooleanField(IntegerField):
|
||||||
self.default_error="Need 0 or 1 value"
|
self.default_error="Need 0 or 1 value"
|
||||||
self.default_value=0
|
self.default_value=0
|
||||||
|
|
||||||
self.type_sql='tinyint(1)'
|
|
||||||
|
|
||||||
self.jtype='boolean'
|
|
||||||
#self.jformat='0'
|
|
||||||
self.jexample='0'
|
|
||||||
|
|
||||||
def check(self, value):
|
def check(self, value):
|
||||||
|
|
||||||
self.error=False
|
self.error=False
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,5 @@
|
||||||
#!/usr/bin/env python3
|
#!/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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from html import escape
|
from html import escape
|
||||||
|
|
||||||
|
|
@ -263,8 +244,7 @@ class SelectModelForm(SelectForm):
|
||||||
|
|
||||||
arr_son[arr_value[self.field_parent]]=[]
|
arr_son[arr_value[self.field_parent]]=[]
|
||||||
|
|
||||||
if arr_value[self.field_value]!=self.model.model_id:
|
arr_son[arr_value[self.field_parent]].append([arr_value[self.field_value], arr_value[self.field_name]])
|
||||||
arr_son[arr_value[self.field_parent]].append([arr_value[self.field_value], self.model.fields[self.field_name].show_formatted(arr_value[self.field_name])])
|
|
||||||
|
|
||||||
self.create_son(0, arr_son)
|
self.create_son(0, arr_son)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,5 @@
|
||||||
#!/usr/bin/env python3
|
#!/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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import os,traceback
|
import os,traceback
|
||||||
import sys, inspect
|
import sys, inspect
|
||||||
|
|
@ -130,32 +111,6 @@ def start():
|
||||||
|
|
||||||
new_tables=[x for x in tables if x not in table_exists]
|
new_tables=[x for x in tables if x not in table_exists]
|
||||||
|
|
||||||
# Get foreignkeys
|
|
||||||
|
|
||||||
# SELECT * FROM information_schema.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA='catalogdev_db' AND information_schema.TABLE_CONSTRAINTS.CONSTRAINT_TYPE = 'FOREIGN KEY' ;
|
|
||||||
|
|
||||||
foreignkey_fields={}
|
|
||||||
|
|
||||||
#| CONSTRAINT_CATALOG | CONSTRAINT_SCHEMA | CONSTRAINT_NAME | TABLE_SCHEMA | TABLE_NAME | CONSTRAINT_TYPE |
|
|
||||||
#+--------------------+-------------------+-----------------------------------------+---------------+-------------------+-----------------+
|
|
||||||
#| def | catalogdev_db | product_id_attributesIDX | catalogdev_db | attributes | FOREIGN KEY |
|
|
||||||
|
|
||||||
|
|
||||||
#WebModel.connections
|
|
||||||
|
|
||||||
db_name=WebModel.connections['default']['db']
|
|
||||||
|
|
||||||
with connection.query('SELECT * FROM information_schema.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA=%s AND information_schema.TABLE_CONSTRAINTS.CONSTRAINT_TYPE = %s', [db_name, 'FOREIGN KEY']) as cursor:
|
|
||||||
|
|
||||||
for row in cursor:
|
|
||||||
if not row['TABLE_NAME'] in foreignkey_fields:
|
|
||||||
foreignkey_fields[row['TABLE_NAME']]=[]
|
|
||||||
|
|
||||||
foreignkey_fields[row['TABLE_NAME']]=row['CONSTRAINT_NAME'].replace('_{}IDX'.format(row['TABLE_NAME']), '')
|
|
||||||
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
#If don't want order
|
#If don't want order
|
||||||
#new_tables=set(tables)-set(table_exists)
|
#new_tables=set(tables)-set(table_exists)
|
||||||
|
|
||||||
|
|
@ -213,23 +168,6 @@ def start():
|
||||||
print(Style.BRIGHT+"Checking old versions of model for find changes...")
|
print(Style.BRIGHT+"Checking old versions of model for find changes...")
|
||||||
|
|
||||||
for table in tables:
|
for table in tables:
|
||||||
|
|
||||||
#print(table)
|
|
||||||
|
|
||||||
table_fields={table: {}}
|
|
||||||
|
|
||||||
# Field | Type | Null | Key | Default | Extra |
|
|
||||||
#| id | int(11) | NO | PRI | NULL | auto_increment |
|
|
||||||
|
|
||||||
with connection.query('describe %s' % table) as cursor:
|
|
||||||
#all_fields=cursor.fetchall()
|
|
||||||
#print(all_fields)
|
|
||||||
|
|
||||||
for row in cursor:
|
|
||||||
table_fields[table][row['Field']]={'type': row['Type'], 'key': row['Key']}
|
|
||||||
pass
|
|
||||||
#print(table_fields)
|
|
||||||
|
|
||||||
#connection.query("")
|
#connection.query("")
|
||||||
#Check if new table
|
#Check if new table
|
||||||
|
|
||||||
|
|
@ -252,8 +190,7 @@ def start():
|
||||||
|
|
||||||
for f, v in WebModel.model[table].fields.items():
|
for f, v in WebModel.model[table].fields.items():
|
||||||
|
|
||||||
#if not f in WebModel.model[old_table].fields:
|
if not f in WebModel.model[old_table].fields:
|
||||||
if not f in table_fields[table]:
|
|
||||||
|
|
||||||
fields_to_add.append(f)
|
fields_to_add.append(f)
|
||||||
|
|
||||||
|
|
@ -297,15 +234,13 @@ def start():
|
||||||
|
|
||||||
#Add index
|
#Add index
|
||||||
|
|
||||||
#if v.indexed==True and v_old.indexed==False:
|
if v.indexed==True and v_old.indexed==False:
|
||||||
if v.indexed==True and table_fields[table][f]['key']!='MUL':
|
|
||||||
|
|
||||||
fields_to_add_index.append(f)
|
fields_to_add_index.append(f)
|
||||||
|
|
||||||
changes+=1
|
changes+=1
|
||||||
|
|
||||||
#if v.indexed==False and v_old.indexed==True:
|
if v.indexed==False and v_old.indexed==True:
|
||||||
if v.indexed==False and table_fields[table][f]['key']=='MUL' and v.foreignkey==False:
|
|
||||||
|
|
||||||
fields_to_delete_index.append(f)
|
fields_to_delete_index.append(f)
|
||||||
|
|
||||||
|
|
@ -313,15 +248,13 @@ def start():
|
||||||
|
|
||||||
#Add unique
|
#Add unique
|
||||||
|
|
||||||
#if v.unique==True and v_old.unique==False:
|
if v.unique==True and v_old.unique==False:
|
||||||
if v.unique==True and table_fields[table][f]['key']!='UNI':
|
|
||||||
|
|
||||||
fields_to_add_unique.append(f)
|
fields_to_add_unique.append(f)
|
||||||
|
|
||||||
changes+=1
|
changes+=1
|
||||||
|
|
||||||
#if v.unique==False and v_old.unique==True:
|
if v.unique==False and v_old.unique==True:
|
||||||
if v.unique==False and table_fields[table][f]['key']=='UNI':
|
|
||||||
|
|
||||||
fields_to_delete_unique.append(f)
|
fields_to_delete_unique.append(f)
|
||||||
|
|
||||||
|
|
@ -329,43 +262,29 @@ def start():
|
||||||
|
|
||||||
#Add constraint
|
#Add constraint
|
||||||
|
|
||||||
#if v.foreignkey==True and v_old.foreignkey==False:
|
if v.foreignkey==True and v_old.foreignkey==False:
|
||||||
if v.foreignkey==True and table_fields[table][f]['key']!='MUL':
|
|
||||||
|
|
||||||
fields_to_add_constraint.append(f)
|
fields_to_add_constraint.append(f)
|
||||||
|
|
||||||
changes+=1
|
changes+=1
|
||||||
|
|
||||||
#if v.foreignkey==False and v_old.foreignkey==True:
|
if v.foreignkey==False and v_old.foreignkey==True:
|
||||||
if v.foreignkey==False and table_fields[table][f]['key']=='MUL':
|
|
||||||
|
|
||||||
if table in foreignkey_fields:
|
fields_to_delete_constraint.append(f)
|
||||||
|
|
||||||
if f in foreignkey_fields[table]:
|
changes+=1
|
||||||
|
|
||||||
fields_to_delete_constraint.append(f)
|
for f, v in WebModel.model[old_table].fields.items():
|
||||||
|
|
||||||
changes+=1
|
|
||||||
|
|
||||||
# Clean fields
|
|
||||||
|
|
||||||
#for f, v in WebModel.model[old_table].fields.items():
|
|
||||||
|
|
||||||
for f, v in table_fields[table].items():
|
|
||||||
|
|
||||||
if not f in WebModel.model[table].fields:
|
if not f in WebModel.model[table].fields:
|
||||||
|
|
||||||
#Add constraint
|
#Add constraint
|
||||||
|
|
||||||
#if v.foreignkey==True:
|
if v.foreignkey==True:
|
||||||
|
|
||||||
if table in foreignkey_fields:
|
fields_to_delete_constraint.append(f)
|
||||||
|
|
||||||
if f in foreignkey_fields[table]:
|
changes+=1
|
||||||
|
|
||||||
fields_to_delete_constraint.append(f)
|
|
||||||
|
|
||||||
changes+=1
|
|
||||||
|
|
||||||
fields_to_delete.append(f)
|
fields_to_delete.append(f)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
"""
|
|
||||||
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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
@ -1,22 +1,3 @@
|
||||||
"""
|
|
||||||
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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from paramecio2.libraries.db.webmodel import PhangoField,WebModel
|
from paramecio2.libraries.db.webmodel import PhangoField,WebModel
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
|
@ -39,12 +20,6 @@ class ArrayField(PhangoField):
|
||||||
|
|
||||||
self.set_default='NOT NULL'
|
self.set_default='NOT NULL'
|
||||||
|
|
||||||
self.type_sql='text'
|
|
||||||
|
|
||||||
self.jtype='array'
|
|
||||||
|
|
||||||
self.default_value='[]'
|
|
||||||
|
|
||||||
def check(self, value):
|
def check(self, value):
|
||||||
|
|
||||||
if type(value).__name__=='str':
|
if type(value).__name__=='str':
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,3 @@
|
||||||
"""
|
|
||||||
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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from paramecio2.libraries.db.corefields import IntegerField
|
from paramecio2.libraries.db.corefields import IntegerField
|
||||||
try:
|
try:
|
||||||
from paramecio2.libraries.db.extraforms.colorform import ColorForm
|
from paramecio2.libraries.db.extraforms.colorform import ColorForm
|
||||||
|
|
@ -31,8 +12,6 @@ class ColorField(IntegerField):
|
||||||
super().__init__(name, size, required)
|
super().__init__(name, size, required)
|
||||||
|
|
||||||
self.name_form=ColorForm
|
self.name_form=ColorForm
|
||||||
self.jtype='string'
|
|
||||||
self.jexample='#f0f0f0'
|
|
||||||
|
|
||||||
def check(self, value):
|
def check(self, value):
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,3 @@
|
||||||
"""
|
|
||||||
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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from paramecio2.libraries.db.corefields import PhangoField
|
from paramecio2.libraries.db.corefields import PhangoField
|
||||||
from paramecio2.libraries import datetime
|
from paramecio2.libraries import datetime
|
||||||
try:
|
try:
|
||||||
|
|
@ -39,9 +20,6 @@ class DateField(PhangoField):
|
||||||
|
|
||||||
self.error_default='Error: Date format invalid'
|
self.error_default='Error: Date format invalid'
|
||||||
|
|
||||||
self.jtype='string'
|
|
||||||
self.jformat='date-time'
|
|
||||||
|
|
||||||
def check(self, value):
|
def check(self, value):
|
||||||
|
|
||||||
if self.utc:
|
if self.utc:
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,3 @@
|
||||||
"""
|
|
||||||
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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from paramecio2.libraries.db.corefields import PhangoField
|
from paramecio2.libraries.db.corefields import PhangoField
|
||||||
from paramecio2.libraries import datetime
|
from paramecio2.libraries import datetime
|
||||||
try:
|
try:
|
||||||
|
|
@ -38,12 +19,6 @@ class DateTimeField(PhangoField):
|
||||||
|
|
||||||
self.error_default='Error: Date format invalid'
|
self.error_default='Error: Date format invalid'
|
||||||
|
|
||||||
self.type_sql='datetime'
|
|
||||||
|
|
||||||
self.jformat='date-time'
|
|
||||||
self.jtype='string'
|
|
||||||
self.jexample='2022-12-01 12:24:11'
|
|
||||||
|
|
||||||
def check(self, value):
|
def check(self, value):
|
||||||
|
|
||||||
if self.utc:
|
if self.utc:
|
||||||
|
|
@ -77,7 +52,6 @@ class DateTimeField(PhangoField):
|
||||||
def show_formatted(self, value):
|
def show_formatted(self, value):
|
||||||
|
|
||||||
# Convert to paramecio value
|
# Convert to paramecio value
|
||||||
|
|
||||||
value=str(value)
|
value=str(value)
|
||||||
value=value.replace('-', '').replace(':', '').replace(' ', '')
|
value=value.replace('-', '').replace(':', '').replace(' ', '')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,3 @@
|
||||||
"""
|
|
||||||
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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from paramecio2.libraries.db.webmodel import WebModel, PhangoField
|
from paramecio2.libraries.db.webmodel import WebModel, PhangoField
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
|
@ -39,12 +20,6 @@ class DictField(PhangoField):
|
||||||
|
|
||||||
self.set_default='NOT NULL'
|
self.set_default='NOT NULL'
|
||||||
|
|
||||||
self.type_sql='longtext'
|
|
||||||
|
|
||||||
self.jtype='object'
|
|
||||||
|
|
||||||
self.default_value='{}'
|
|
||||||
|
|
||||||
def check(self, value):
|
def check(self, value):
|
||||||
|
|
||||||
if type(value).__name__=='str':
|
if type(value).__name__=='str':
|
||||||
|
|
@ -79,7 +54,7 @@ class DictField(PhangoField):
|
||||||
|
|
||||||
def get_type_sql(self):
|
def get_type_sql(self):
|
||||||
|
|
||||||
return 'JSON '+self.set_default
|
return 'TEXT '+self.set_default
|
||||||
|
|
||||||
def show_formatted(self, value):
|
def show_formatted(self, value):
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,7 @@
|
||||||
"""
|
|
||||||
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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from paramecio2.libraries.db.corefields import CharField
|
from paramecio2.libraries.db.corefields import CharField
|
||||||
import re
|
import re
|
||||||
|
|
||||||
mail_pattern=re.compile(r"\w[\w\.-]*@\w[\w\.-]+\.\w+")
|
mail_pattern=re.compile("\w[\w\.-]*@\w[\w\.-]+\.\w+")
|
||||||
|
|
||||||
class EmailField(CharField):
|
class EmailField(CharField):
|
||||||
"""Field for save and check email addreses"""
|
"""Field for save and check email addreses"""
|
||||||
|
|
@ -31,8 +12,6 @@ class EmailField(CharField):
|
||||||
|
|
||||||
self.error_default='Error: No valid format'
|
self.error_default='Error: No valid format'
|
||||||
|
|
||||||
self.jformat='email'
|
|
||||||
|
|
||||||
def check(self, value):
|
def check(self, value):
|
||||||
|
|
||||||
value=super().check(value)
|
value=super().check(value)
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,3 @@
|
||||||
"""
|
|
||||||
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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,5 @@
|
||||||
#!/usr/bin/env python3
|
#!/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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import json
|
import json
|
||||||
from paramecio2.libraries.db.webmodel import PhangoField
|
from paramecio2.libraries.db.webmodel import PhangoField
|
||||||
from paramecio2.libraries.db.coreforms import BaseForm
|
from paramecio2.libraries.db.coreforms import BaseForm
|
||||||
|
|
@ -51,8 +32,6 @@ class I18nField(PhangoField):
|
||||||
arr_i18n={i:'' for i in I18n.dict_i18n}
|
arr_i18n={i:'' for i in I18n.dict_i18n}
|
||||||
self.default_value=json.dumps(arr_i18n)
|
self.default_value=json.dumps(arr_i18n)
|
||||||
|
|
||||||
self.type_sql='longtext'
|
|
||||||
|
|
||||||
def change_form(self, form):
|
def change_form(self, form):
|
||||||
self.extra_parameters=[form]
|
self.extra_parameters=[form]
|
||||||
|
|
||||||
|
|
@ -111,7 +90,7 @@ class I18nField(PhangoField):
|
||||||
|
|
||||||
def get_type_sql(self):
|
def get_type_sql(self):
|
||||||
|
|
||||||
return 'JSON NOT NULL'
|
return 'TEXT NOT NULL'
|
||||||
|
|
||||||
def obtain_lang_value(self, lang, value):
|
def obtain_lang_value(self, lang, value):
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,3 @@
|
||||||
"""
|
|
||||||
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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
@ -132,14 +113,9 @@ class ImageField(CharField):
|
||||||
return self.save_folder+'/'+value
|
return self.save_folder+'/'+value
|
||||||
else:
|
else:
|
||||||
|
|
||||||
self.txt_error='Field is empty'
|
value=os.path.basename(value)
|
||||||
self.error=True
|
|
||||||
|
|
||||||
return ''
|
return self.save_folder+'/'+value
|
||||||
|
|
||||||
#value=os.path.basename(value)
|
|
||||||
|
|
||||||
#return self.save_folder+'/'+value
|
|
||||||
|
|
||||||
# Load image file
|
# Load image file
|
||||||
|
|
||||||
|
|
@ -204,7 +180,7 @@ class ImageField(CharField):
|
||||||
if format_image!='JPEG' and format_image!='GIF' and format_image!='PNG':
|
if format_image!='JPEG' and format_image!='GIF' and format_image!='PNG':
|
||||||
|
|
||||||
self.error=True
|
self.error=True
|
||||||
self.txt_error='Format is wrong. Requires GIF, JPEG or PNG formats'
|
self.txt_error='Format is wrong. Requires JPEG or PNG formats'
|
||||||
im.close()
|
im.close()
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
@ -222,6 +198,24 @@ class ImageField(CharField):
|
||||||
|
|
||||||
save_file=self.save_folder+'/'+filename
|
save_file=self.save_folder+'/'+filename
|
||||||
|
|
||||||
|
if self.yes_thumbnail:
|
||||||
|
|
||||||
|
for name, width_t in self.thumbnail.items():
|
||||||
|
|
||||||
|
im_thumb=im.copy()
|
||||||
|
|
||||||
|
ratio=(real_width/width_t)
|
||||||
|
height_t=round(real_height/ratio)
|
||||||
|
|
||||||
|
size=(width_t, height_t)
|
||||||
|
|
||||||
|
save_file_thumb=self.save_folder+'/'+name+filename
|
||||||
|
|
||||||
|
im_thumb.thumbnail(size, Image.ANTIALIAS)
|
||||||
|
im_thumb.save(save_file_thumb, "JPEG", quality=self.default_quality_thumb)
|
||||||
|
|
||||||
|
im_thumb.close()
|
||||||
|
|
||||||
# Save file
|
# Save file
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
@ -251,26 +245,6 @@ class ImageField(CharField):
|
||||||
|
|
||||||
os.remove(save_file)
|
os.remove(save_file)
|
||||||
|
|
||||||
# Save thumbnails
|
|
||||||
|
|
||||||
if self.yes_thumbnail:
|
|
||||||
|
|
||||||
for name, width_t in self.thumbnail.items():
|
|
||||||
|
|
||||||
im_thumb=im.copy()
|
|
||||||
|
|
||||||
ratio=(real_width/width_t)
|
|
||||||
height_t=round(real_height/ratio)
|
|
||||||
|
|
||||||
size=(width_t, height_t)
|
|
||||||
|
|
||||||
save_file_thumb=self.save_folder+'/'+name+filename
|
|
||||||
|
|
||||||
im_thumb.thumbnail(size, Image.LANCZOS)
|
|
||||||
im_thumb.save(save_file_thumb, "JPEG", quality=self.default_quality_thumb)
|
|
||||||
|
|
||||||
im_thumb.close()
|
|
||||||
|
|
||||||
im.save(save_file)
|
im.save(save_file)
|
||||||
|
|
||||||
# Delete old files
|
# Delete old files
|
||||||
|
|
@ -295,23 +269,10 @@ class ImageField(CharField):
|
||||||
|
|
||||||
os.remove(arr_image[self.name])
|
os.remove(arr_image[self.name])
|
||||||
|
|
||||||
if self.yes_thumbnail:
|
|
||||||
|
|
||||||
for tname, width_t in self.thumbnail.items():
|
|
||||||
|
|
||||||
old_dir_name=os.path.dirname(arr_image[self.name])
|
|
||||||
old_base_name=os.path.basename(arr_image[self.name])
|
|
||||||
|
|
||||||
old_thumb_name=old_dir_name+'/'+tname+old_base_name
|
|
||||||
|
|
||||||
if os.path.isfile(old_thumb_name):
|
|
||||||
os.remove(old_thumb_name)
|
|
||||||
|
|
||||||
|
|
||||||
self.model.yes_reset_conditions=old_reset
|
self.model.yes_reset_conditions=old_reset
|
||||||
|
|
||||||
|
|
||||||
#self.model.conditions=old_conditions
|
#self.model.conditions=old_conditions
|
||||||
|
|
||||||
im.close()
|
im.close()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,34 +1,9 @@
|
||||||
"""
|
|
||||||
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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from paramecio2.libraries.db.corefields import CharField
|
from paramecio2.libraries.db.corefields import CharField
|
||||||
import ipaddress
|
import ipaddress
|
||||||
|
|
||||||
class IpField(CharField):
|
class IpField(CharField):
|
||||||
"""Field for save ip internet address values in db"""
|
"""Field for save ip internet address values in db"""
|
||||||
|
|
||||||
def __init__(self, name, size=1024, required=False):
|
|
||||||
|
|
||||||
super().__init__(name, size, required)
|
|
||||||
|
|
||||||
self.jformat='ipV4'
|
|
||||||
|
|
||||||
def check(self, value):
|
def check(self, value):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,3 @@
|
||||||
"""
|
|
||||||
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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from paramecio2.libraries.db.webmodel import WebModel, PhangoField
|
from paramecio2.libraries.db.webmodel import WebModel, PhangoField
|
||||||
import sys
|
import sys
|
||||||
try:
|
try:
|
||||||
|
|
@ -44,10 +25,6 @@ class JsonField(PhangoField):
|
||||||
|
|
||||||
self.set_default='NOT NULL'
|
self.set_default='NOT NULL'
|
||||||
|
|
||||||
self.type_sql='longtext'
|
|
||||||
|
|
||||||
self.jtype='object'
|
|
||||||
|
|
||||||
def check(self, value):
|
def check(self, value):
|
||||||
|
|
||||||
if type(value).__name__=='str':
|
if type(value).__name__=='str':
|
||||||
|
|
@ -79,7 +56,7 @@ class JsonField(PhangoField):
|
||||||
|
|
||||||
def get_type_sql(self):
|
def get_type_sql(self):
|
||||||
|
|
||||||
return 'JSON '+self.set_default
|
return 'LONGTEXT '+self.set_default
|
||||||
|
|
||||||
def show_formatted(self, value):
|
def show_formatted(self, value):
|
||||||
|
|
||||||
|
|
@ -104,12 +81,10 @@ class JsonValueField(PhangoField):
|
||||||
return 'JSON'
|
return 'JSON'
|
||||||
|
|
||||||
def check(self, value):
|
def check(self, value):
|
||||||
#print(value)
|
|
||||||
try:
|
try:
|
||||||
final_value=json.dumps(value)
|
final_value=json.dumps(value)
|
||||||
|
|
||||||
final_value=value
|
|
||||||
|
|
||||||
except json.JSONDecodeError:
|
except json.JSONDecodeError:
|
||||||
|
|
||||||
final_value='{}'
|
final_value='{}'
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,5 @@
|
||||||
#!/usr/bin/env python3
|
#!/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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from paramecio2.libraries.db.corefields import CharField
|
from paramecio2.libraries.db.corefields import CharField
|
||||||
from paramecio2.libraries.db import coreforms
|
from paramecio2.libraries.db import coreforms
|
||||||
from paramecio2.libraries.i18n import I18n
|
from paramecio2.libraries.i18n import I18n
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,3 @@
|
||||||
"""
|
|
||||||
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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from paramecio2.libraries.db.corefields import DecimalField
|
from paramecio2.libraries.db.corefields import DecimalField
|
||||||
from decimal import Decimal, getcontext
|
from decimal import Decimal, getcontext
|
||||||
from locale import format_string
|
from locale import format_string
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,5 @@
|
||||||
#!/usr/bin/env python3
|
#!/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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
#from paramecio2.libraries.db.webmodel import PhangoField
|
#from paramecio2.libraries.db.webmodel import PhangoField
|
||||||
from paramecio2.libraries.db.corefields import IntegerField
|
from paramecio2.libraries.db.corefields import IntegerField
|
||||||
from paramecio2.libraries.db.coreforms import SelectModelForm
|
from paramecio2.libraries.db.coreforms import SelectModelForm
|
||||||
|
|
|
||||||
|
|
@ -1,32 +1,7 @@
|
||||||
"""
|
|
||||||
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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from paramecio2.libraries.db.corefields import PhangoField
|
from paramecio2.libraries.db.corefields import PhangoField
|
||||||
from paramecio2.libraries.db.coreforms import PasswordForm
|
from paramecio2.libraries.db.coreforms import PasswordForm
|
||||||
from hmac import compare_digest as compare_hash
|
from hmac import compare_digest as compare_hash
|
||||||
#try:
|
import crypt
|
||||||
# import crypt
|
|
||||||
#except:
|
|
||||||
# pass
|
|
||||||
|
|
||||||
#import bcrypt
|
|
||||||
from argon2 import PasswordHasher
|
|
||||||
|
|
||||||
class PasswordField(PhangoField):
|
class PasswordField(PhangoField):
|
||||||
"""Field for check and save passwords"""
|
"""Field for check and save passwords"""
|
||||||
|
|
@ -38,7 +13,6 @@ class PasswordField(PhangoField):
|
||||||
self.name_form=PasswordForm
|
self.name_form=PasswordForm
|
||||||
self.default_value=''
|
self.default_value=''
|
||||||
self.encrypt_password=True
|
self.encrypt_password=True
|
||||||
self.jformat='password'
|
|
||||||
|
|
||||||
def check(self, value):
|
def check(self, value):
|
||||||
|
|
||||||
|
|
@ -70,10 +44,7 @@ class PasswordField(PhangoField):
|
||||||
|
|
||||||
#salt=crypt.mksalt(crypt.METHOD_SHA512)
|
#salt=crypt.mksalt(crypt.METHOD_SHA512)
|
||||||
if self.encrypt_password:
|
if self.encrypt_password:
|
||||||
#value=crypt.crypt(value)
|
value=crypt.crypt(value)
|
||||||
ph=PasswordHasher()
|
|
||||||
final_value=ph.hash(value)
|
|
||||||
return final_value
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
else:
|
else:
|
||||||
|
|
@ -89,12 +60,7 @@ class PasswordField(PhangoField):
|
||||||
def verify( password, h):
|
def verify( password, h):
|
||||||
"""Static method used for verify a password save using PasswordField"""
|
"""Static method used for verify a password save using PasswordField"""
|
||||||
#return bcrypt_sha256.verify(password, h)
|
#return bcrypt_sha256.verify(password, h)
|
||||||
#return compare_hash(h, crypt.crypt(password, h))
|
return compare_hash(h, crypt.crypt(password, h))
|
||||||
ph=PasswordHasher()
|
|
||||||
try:
|
|
||||||
return ph.verify(h, password)
|
|
||||||
except:
|
|
||||||
return False
|
|
||||||
|
|
||||||
# Old function bcrypt
|
# Old function bcrypt
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,6 @@
|
||||||
"""
|
from paramecio2.libraries.db.corefields import IntegerField
|
||||||
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
|
class PercentField(IntegerField):
|
||||||
|
|
||||||
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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from paramecio2.libraries.db.corefields import DecimalField
|
|
||||||
|
|
||||||
class PercentField(DecimalField):
|
|
||||||
"""Field used for save percent values from 0 to 100."""
|
"""Field used for save percent values from 0 to 100."""
|
||||||
|
|
||||||
def __init__(self, name, required=False):
|
def __init__(self, name, required=False):
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,5 @@
|
||||||
#!/usr/bin/env python3
|
#!/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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from paramecio2.libraries.db.corefields import CharField
|
from paramecio2.libraries.db.corefields import CharField
|
||||||
from slugify import slugify
|
from slugify import slugify
|
||||||
from paramecio2.libraries.db.coreforms import HiddenForm
|
from paramecio2.libraries.db.coreforms import HiddenForm
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,3 @@
|
||||||
"""
|
|
||||||
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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from paramecio2.libraries.db.corefields import CharField
|
from paramecio2.libraries.db.corefields import CharField
|
||||||
import re
|
import re
|
||||||
import ipaddress
|
import ipaddress
|
||||||
|
|
@ -32,11 +13,6 @@ check_url = re.compile(
|
||||||
class UrlField(CharField):
|
class UrlField(CharField):
|
||||||
"""Field for check and save strings in url format"""
|
"""Field for check and save strings in url format"""
|
||||||
|
|
||||||
def __init__(self, name, size=1024, required=False):
|
|
||||||
|
|
||||||
super().__init__(name, size, required)
|
|
||||||
self.jformat='url'
|
|
||||||
|
|
||||||
def check(self, value):
|
def check(self, value):
|
||||||
|
|
||||||
self.error=False
|
self.error=False
|
||||||
|
|
@ -50,7 +26,7 @@ class UrlField(CharField):
|
||||||
|
|
||||||
return value
|
return value
|
||||||
|
|
||||||
check_domain=re.compile(r'^(([a-zA-Z]{1})|([a-zA-Z]{1}[a-zA-Z]{1})|([a-zA-Z]{1}[0-9]{1})|([0-9]{1}[a-zA-Z]{1})|([a-zA-Z0-9][a-zA-Z0-9-_]{1,61}[a-zA-Z0-9]))\.([a-zA-Z]{2,6}|[a-zA-Z0-9-]{2,30}\.[a-zA-Z]{2,3})$')
|
check_domain=re.compile('^(([a-zA-Z]{1})|([a-zA-Z]{1}[a-zA-Z]{1})|([a-zA-Z]{1}[0-9]{1})|([0-9]{1}[a-zA-Z]{1})|([a-zA-Z0-9][a-zA-Z0-9-_]{1,61}[a-zA-Z0-9]))\.([a-zA-Z]{2,6}|[a-zA-Z0-9-]{2,30}\.[a-zA-Z]{2,3})$')
|
||||||
|
|
||||||
class DomainField(CharField):
|
class DomainField(CharField):
|
||||||
"""Field for check and save strings in domain internet format"""
|
"""Field for check and save strings in domain internet format"""
|
||||||
|
|
@ -77,7 +53,7 @@ class DomainField(CharField):
|
||||||
|
|
||||||
#^(https|ssh):\/\/([a-zA-Z0-9\-_]+@)?[a-zA-Z0-9\-_]+(\.[a-zA-Z0-9\-_]+)*(:[0-9]+)?\/[a-zA-Z0-9\-_]+(\/[a-zA-Z0-9\-_]+)*(\.git)?$
|
#^(https|ssh):\/\/([a-zA-Z0-9\-_]+@)?[a-zA-Z0-9\-_]+(\.[a-zA-Z0-9\-_]+)*(:[0-9]+)?\/[a-zA-Z0-9\-_]+(\/[a-zA-Z0-9\-_]+)*(\.git)?$
|
||||||
|
|
||||||
check_git_url=re.compile(r'^(https|ssh):\/\/([a-zA-Z0-9\-_]+@)?[a-zA-Z0-9\-_]+(\.[a-zA-Z0-9\-_]+)*(:[a-zA-Z0-9\-_]+)?\/[a-zA-Z0-9\-_]+(\/[a-zA-Z0-9\-_]+)*(\.git)?$')
|
check_git_url=re.compile('^(https|ssh):\/\/([a-zA-Z0-9\-_]+@)?[a-zA-Z0-9\-_]+(\.[a-zA-Z0-9\-_]+)*(:[a-zA-Z0-9\-_]+)?\/[a-zA-Z0-9\-_]+(\/[a-zA-Z0-9\-_]+)*(\.git)?$')
|
||||||
|
|
||||||
class GitUrlField(CharField):
|
class GitUrlField(CharField):
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,7 @@
|
||||||
"""
|
|
||||||
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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from paramecio2.libraries.db.corefields import PhangoField
|
from paramecio2.libraries.db.corefields import PhangoField
|
||||||
from paramecio2.libraries.db.coreforms import PasswordForm
|
from paramecio2.libraries.db.coreforms import PasswordForm
|
||||||
from hmac import compare_digest as compare_hash
|
from hmac import compare_digest as compare_hash
|
||||||
#import crypt
|
import crypt
|
||||||
import re
|
import re
|
||||||
|
|
||||||
class UserNameField(PhangoField):
|
class UserNameField(PhangoField):
|
||||||
|
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
"""
|
|
||||||
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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
@ -1,24 +1,5 @@
|
||||||
#!/usr/bin/env python3
|
#!/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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from paramecio2.libraries.db.coreforms import BaseForm
|
from paramecio2.libraries.db.coreforms import BaseForm
|
||||||
|
|
||||||
class CheckForm(BaseForm):
|
class CheckForm(BaseForm):
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,5 @@
|
||||||
#!/usr/bin/env python3
|
#!/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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from paramecio2.libraries.db.coreforms import BaseForm
|
from paramecio2.libraries.db.coreforms import BaseForm
|
||||||
from paramecio2.libraries.mtemplates import standard_t
|
from paramecio2.libraries.mtemplates import standard_t
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,5 @@
|
||||||
#!/usr/bin/env python3
|
#!/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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from paramecio2.libraries.db.coreforms import BaseForm
|
from paramecio2.libraries.db.coreforms import BaseForm
|
||||||
from paramecio2.libraries.mtemplates import standard_t
|
from paramecio2.libraries.mtemplates import standard_t
|
||||||
from paramecio2.libraries.datetime import format_timedata
|
from paramecio2.libraries.datetime import format_timedata
|
||||||
|
|
@ -30,41 +11,28 @@ class DateForm(BaseForm):
|
||||||
|
|
||||||
super().__init__(name, value)
|
super().__init__(name, value)
|
||||||
|
|
||||||
self.yes_time=True
|
self.yes_time=False
|
||||||
self.t=standard_t
|
self.t=standard_t
|
||||||
|
|
||||||
def form(self):
|
def form(self):
|
||||||
|
|
||||||
if type(self.default_value).__name__!='datetime':
|
y=''
|
||||||
|
m=''
|
||||||
|
d=''
|
||||||
|
h=''
|
||||||
|
min=''
|
||||||
|
s=''
|
||||||
|
min_time=''
|
||||||
|
|
||||||
y=''
|
time=format_timedata(self.default_value)
|
||||||
m=''
|
|
||||||
d=''
|
|
||||||
h=''
|
|
||||||
min=''
|
|
||||||
s=''
|
|
||||||
min_time=''
|
|
||||||
|
|
||||||
time=format_timedata(self.default_value)
|
if time[0]:
|
||||||
|
y=int(time[0])
|
||||||
if time[0]:
|
m=int(time[1])
|
||||||
y=int(time[0])
|
d=int(time[2])
|
||||||
m=int(time[1])
|
h=int(time[3])
|
||||||
d=int(time[2])
|
min_time=int(time[4])
|
||||||
h=int(time[3])
|
s=int(time[5])
|
||||||
min_time=int(time[4])
|
|
||||||
s='00' #int(time[5])
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
y=self.default_value.year #"{:>10}".format(s)
|
|
||||||
m="{:02d}".format(self.default_value.month)
|
|
||||||
d="{:02d}".format(self.default_value.day)
|
|
||||||
h="{:02d}".format(self.default_value.hour)
|
|
||||||
min_time="{:02d}".format(self.default_value.minute)
|
|
||||||
s='00'
|
|
||||||
|
|
||||||
pass
|
|
||||||
|
|
||||||
return self.t.load_template('forms/dateform.phtml', yes_time=self.yes_time, form=self.name, y=y, m=m, d=d, h=h, min=min_time, s=s)
|
return self.t.load_template('forms/dateform.phtml', yes_time=self.yes_time, form=self.name, y=y, m=m, d=d, h=h, min=min_time, s=s)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,5 @@
|
||||||
#!/usr/bin/env python3
|
#!/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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from paramecio2.libraries.db.coreforms import BaseForm
|
from paramecio2.libraries.db.coreforms import BaseForm
|
||||||
from paramecio2.libraries.mtemplates import env_theme, PTemplate
|
from paramecio2.libraries.mtemplates import env_theme, PTemplate
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,5 @@
|
||||||
#!/usr/bin/env python3
|
#!/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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from paramecio2.libraries.db.coreforms import BaseForm
|
from paramecio2.libraries.db.coreforms import BaseForm
|
||||||
from paramecio2.libraries.i18n import I18n
|
from paramecio2.libraries.i18n import I18n
|
||||||
from paramecio2.libraries.mtemplates import standard_t
|
from paramecio2.libraries.mtemplates import standard_t
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,3 @@
|
||||||
"""
|
|
||||||
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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from paramecio2.libraries.db.coreforms import BaseForm
|
from paramecio2.libraries.db.coreforms import BaseForm
|
||||||
from paramecio2.libraries.mtemplates import env_theme, PTemplate
|
from paramecio2.libraries.mtemplates import env_theme, PTemplate
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,3 @@
|
||||||
"""
|
|
||||||
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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from paramecio2.libraries.db.coreforms import BaseForm
|
from paramecio2.libraries.db.coreforms import BaseForm
|
||||||
from paramecio2.libraries.mtemplates import env_theme, PTemplate
|
from paramecio2.libraries.mtemplates import env_theme, PTemplate
|
||||||
|
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
|
|
||||||
# A more simple set for make queries
|
|
||||||
|
|
||||||
def insert(model, db, dict_values):
|
|
||||||
|
|
||||||
final_values={}
|
|
||||||
|
|
||||||
for k in model.fields.keys():
|
|
||||||
final_values[k]=model.fields[k].check(dict_values.get(k, ''))
|
|
||||||
|
|
||||||
del final_values[model.name_field_id]
|
|
||||||
|
|
||||||
str_fields="`"+"`, `".join(final_values.keys())+"`"
|
|
||||||
|
|
||||||
str_query='insert into {} ({}) VALUES ({})'.format(model.name, str_fields, ", ".join(['%s']*len(final_values)))
|
|
||||||
|
|
||||||
success=False
|
|
||||||
|
|
||||||
with db.query(str_query, list(final_values.values())) as cursor:
|
|
||||||
|
|
||||||
if cursor.rowcount>0:
|
|
||||||
|
|
||||||
model.last_id=cursor.lastrowid
|
|
||||||
success=True
|
|
||||||
|
|
||||||
return success
|
|
||||||
|
|
||||||
|
|
||||||
def select(model, db, dict_fields=[], where_sql='', limit='', dict_values=[]):
|
|
||||||
|
|
||||||
if len(dict_fields)==0:
|
|
||||||
dict_fields=['`'+field+'`' for field in model.fields.keys()]
|
|
||||||
|
|
||||||
str_fields=", ".join(dict_fields)
|
|
||||||
|
|
||||||
str_query='select {} from {} {} limit 1'.format(str_fields, model.name, where_sql)
|
|
||||||
|
|
||||||
arr_result=[]
|
|
||||||
|
|
||||||
with db.query(str_query, dict_values) as cursor:
|
|
||||||
|
|
||||||
arr_result=cursor.fetchall()
|
|
||||||
|
|
||||||
return arr_result
|
|
||||||
|
|
@ -46,7 +46,6 @@ class SqlClass:
|
||||||
self.conn=None
|
self.conn=None
|
||||||
self.connected=False
|
self.connected=False
|
||||||
self.pool_recycle=3600
|
self.pool_recycle=3600
|
||||||
self.last_query=''
|
|
||||||
self.connect()
|
self.connect()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -74,9 +73,6 @@ class SqlClass:
|
||||||
|
|
||||||
engine=create_engine("mysql+%s://%s:%s@%s/%s?charset=utf8mb4" % (self.connection['db_type'], self.connection['user'], self.connection['password'], self.connection['host'], self.connection['db']), pool_recycle=self.pool_recycle, echo_pool=True, pool_size=self.pool_size, pool_pre_ping=True)
|
engine=create_engine("mysql+%s://%s:%s@%s/%s?charset=utf8mb4" % (self.connection['db_type'], self.connection['user'], self.connection['password'], self.connection['host'], self.connection['db']), pool_recycle=self.pool_recycle, echo_pool=True, pool_size=self.pool_size, pool_pre_ping=True)
|
||||||
|
|
||||||
#Postgre
|
|
||||||
#engine = create_engine("postgresql+psycopg2://scott:tiger@localhost:5432/mydatabase")
|
|
||||||
|
|
||||||
except:
|
except:
|
||||||
e = sys.exc_info()[0]
|
e = sys.exc_info()[0]
|
||||||
v = sys.exc_info()[1]
|
v = sys.exc_info()[1]
|
||||||
|
|
@ -174,20 +170,16 @@ class SqlClass:
|
||||||
|
|
||||||
cursor.execute(sql_query, arguments)
|
cursor.execute(sql_query, arguments)
|
||||||
self.conn.commit()
|
self.conn.commit()
|
||||||
|
|
||||||
#if hasattr(cursor, '_executed'):
|
|
||||||
# self.last_query=cursor._executed
|
|
||||||
|
|
||||||
return cursor
|
return cursor
|
||||||
|
|
||||||
except:
|
except:
|
||||||
e = sys.exc_info()[0]
|
e = sys.exc_info()[0]
|
||||||
v = sys.exc_info()[1]
|
v = sys.exc_info()[1]
|
||||||
|
|
||||||
#if hasattr(cursor, '_executed'):
|
if hasattr(cursor, '_last_executed'):
|
||||||
# self.last_query=cursor._executed
|
sql_query=cursor._last_executed
|
||||||
|
|
||||||
self.error_connection="Error in query ||%s||Values: %s" % (self.last_query, str(arguments))
|
self.error_connection="Error in query ||%s||Values: %s" % (sql_query, str(arguments))
|
||||||
|
|
||||||
self.conn.close()
|
self.conn.close()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
from paramecio2.libraries.db.webmodel import WebModel
|
from paramecio2.libraries.db.webmodel import WebModel
|
||||||
from paramecio2.libraries.db.coreforms import PasswordForm
|
from paramecio2.libraries.db.coreforms import PasswordForm
|
||||||
from paramecio2.libraries.i18n import I18n
|
from paramecio2.libraries.i18n import I18n
|
||||||
from flask import request, session
|
from flask import request
|
||||||
|
|
||||||
class UserModel(WebModel):
|
class UserModel(WebModel):
|
||||||
"""Model used with basic things for users login and signup
|
"""Model used with basic things for users login and signup
|
||||||
|
|
@ -46,7 +46,7 @@ class UserModel(WebModel):
|
||||||
|
|
||||||
repeat_password.required=1
|
repeat_password.required=1
|
||||||
|
|
||||||
repeat_password.label=_('Repeat Password')
|
repeat_password.label=I18n.lang('common', 'repeat_password', 'Repeat Password')
|
||||||
|
|
||||||
repeat_password.field=self.fields[self.password_field]
|
repeat_password.field=self.fields[self.password_field]
|
||||||
|
|
||||||
|
|
@ -99,7 +99,7 @@ class UserModel(WebModel):
|
||||||
if dict_values['repeat_password']!=dict_values[self.password_field]:
|
if dict_values['repeat_password']!=dict_values[self.password_field]:
|
||||||
|
|
||||||
self.fields[self.password_field].error=True
|
self.fields[self.password_field].error=True
|
||||||
self.fields[self.password_field].txt_error=_('Error: passwords doesn\'t match')
|
self.fields[self.password_field].txt_error=I18n.lang('common', 'error_passwords_no_match', 'Error: passwords doesn\'t match')
|
||||||
|
|
||||||
error+=1
|
error+=1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,6 @@ class PhangoField:
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
name (str): The name of the field
|
name (str): The name of the field
|
||||||
jtype(Python type): The type of value in python
|
|
||||||
label (str): A label or generic name for use in text labels used for representate the field
|
label (str): A label or generic name for use in text labels used for representate the field
|
||||||
required (bool): If the field is required or not.
|
required (bool): If the field is required or not.
|
||||||
size (int): The size of sql field.
|
size (int): The size of sql field.
|
||||||
|
|
@ -55,10 +54,6 @@ class PhangoField:
|
||||||
|
|
||||||
self.name=name
|
self.name=name
|
||||||
|
|
||||||
# The type of the field in javascript. Util for api documentation
|
|
||||||
|
|
||||||
self.jtype='string'
|
|
||||||
|
|
||||||
# The label for the Field
|
# The label for the Field
|
||||||
|
|
||||||
self.label=name.replace('_', ' ').title()
|
self.label=name.replace('_', ' ').title()
|
||||||
|
|
@ -151,10 +146,6 @@ class PhangoField:
|
||||||
|
|
||||||
self.help=''
|
self.help=''
|
||||||
|
|
||||||
self.type_sql='varchar({})'.format(self.size)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_type_sql(self):
|
def get_type_sql(self):
|
||||||
"""This method is used for describe the new field in a sql language format."""
|
"""This method is used for describe the new field in a sql language format."""
|
||||||
|
|
||||||
|
|
@ -231,7 +222,6 @@ class PrimaryKeyField(PhangoField):
|
||||||
self.name_form=HiddenForm
|
self.name_form=HiddenForm
|
||||||
self.required=False
|
self.required=False
|
||||||
self.error_default="The value is zero"
|
self.error_default="The value is zero"
|
||||||
self.type_sql='int({})'.format(self.size)
|
|
||||||
|
|
||||||
def check(self, value):
|
def check(self, value):
|
||||||
|
|
||||||
|
|
@ -362,7 +352,6 @@ class WebModel:
|
||||||
sqlclass (SqlClass): A sql_class used for connect to db.
|
sqlclass (SqlClass): A sql_class used for connect to db.
|
||||||
show_formatted (bool): If True, by default all fields are showed with formatted value using show_formatted method of PhangoField classes and children in select method. If False, raw value is showed.
|
show_formatted (bool): If True, by default all fields are showed with formatted value using show_formatted method of PhangoField classes and children in select method. If False, raw value is showed.
|
||||||
enctype (bool): If True, forms generated using this model are prepared for enctype=multipart/form-data A.K.A. upload files.
|
enctype (bool): If True, forms generated using this model are prepared for enctype=multipart/form-data A.K.A. upload files.
|
||||||
model_id (int): Variable where the actual row from model selected can be saved for different things.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.cached=WebModel.global_cached
|
self.cached=WebModel.global_cached
|
||||||
|
|
@ -467,8 +456,6 @@ class WebModel:
|
||||||
|
|
||||||
self.enctype=False
|
self.enctype=False
|
||||||
|
|
||||||
self.model_id=0
|
|
||||||
|
|
||||||
self.dummy=0
|
self.dummy=0
|
||||||
|
|
||||||
# A method for add the connection
|
# A method for add the connection
|
||||||
|
|
@ -1140,9 +1127,7 @@ class WebModel:
|
||||||
|
|
||||||
#Need delete rows from other related tables save in self.related_models_deleted
|
#Need delete rows from other related tables save in self.related_models_deleted
|
||||||
|
|
||||||
#+' '+self.order_by+' '+self.limit
|
sql=("delete from `"+self.name+"` "+self.conditions[0]+' '+self.order_by+' '+self.limit).strip()
|
||||||
|
|
||||||
sql=("delete from `"+self.name+"` "+self.conditions[0]).strip()
|
|
||||||
|
|
||||||
result=self.query(sql, self.conditions[1], self.connection_id)
|
result=self.query(sql, self.conditions[1], self.connection_id)
|
||||||
|
|
||||||
|
|
@ -1305,7 +1290,7 @@ class WebModel:
|
||||||
|
|
||||||
self.arr_sql_set_index[self.name][field]='ALTER TABLE `'+self.name+'` ADD CONSTRAINT `'+field+'_'+self.name+'IDX` FOREIGN KEY ( `'+field+'` ) REFERENCES `'+table_related+'` (`'+id_table_related+'`) ON DELETE CASCADE ON UPDATE CASCADE;'
|
self.arr_sql_set_index[self.name][field]='ALTER TABLE `'+self.name+'` ADD CONSTRAINT `'+field+'_'+self.name+'IDX` FOREIGN KEY ( `'+field+'` ) REFERENCES `'+table_related+'` (`'+id_table_related+'`) ON DELETE CASCADE ON UPDATE CASCADE;'
|
||||||
|
|
||||||
return "create table `"+self.name+"` (\n"+",\n".join(table_fields)+"\n) DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;";
|
return "create table `"+self.name+"` (\n"+",\n".join(table_fields)+"\n) DEFAULT CHARSET=utf8;";
|
||||||
|
|
||||||
def update_table(self, fields_to_add, fields_to_modify, fields_to_add_index, fields_to_add_constraint, fields_to_add_unique, fields_to_delete_index, fields_to_delete_unique, fields_to_delete_constraint, fields_to_delete):
|
def update_table(self, fields_to_add, fields_to_modify, fields_to_add_index, fields_to_add_constraint, fields_to_add_unique, fields_to_delete_index, fields_to_delete_unique, fields_to_delete_constraint, fields_to_delete):
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,48 +1,10 @@
|
||||||
#!/usr/bin/env python3
|
#!/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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from paramecio2.libraries.db import corefields
|
from paramecio2.libraries.db import corefields
|
||||||
from paramecio2.libraries.db.coreforms import PasswordForm
|
from paramecio2.libraries.db.coreforms import PasswordForm
|
||||||
from paramecio2.libraries.i18n import I18n
|
from paramecio2.libraries.i18n import I18n
|
||||||
|
from flask import session, request, abort
|
||||||
from paramecio2.libraries.keyutils import create_key_encrypt
|
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
|
# Need unittest
|
||||||
"""Functions and classes for process forms"""
|
"""Functions and classes for process forms"""
|
||||||
|
|
@ -189,24 +151,13 @@ def show_form(post, arr_form, t, yes_error=True, pass_values=True, modelform_tpl
|
||||||
|
|
||||||
# Create csrf_token in session
|
# Create csrf_token in session
|
||||||
|
|
||||||
#generate_csrf()
|
generate_csrf()
|
||||||
|
|
||||||
if pass_values==True:
|
if pass_values==True:
|
||||||
pass_values_to_form(post, arr_form, yes_error, pass_values)
|
pass_values_to_form(post, arr_form, yes_error, pass_values)
|
||||||
|
|
||||||
return t.load_template(modelform_tpl, forms=arr_form)
|
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
|
#Simple Function for add repeat_password form to user model
|
||||||
|
|
||||||
def set_extra_forms_user(user_admin):
|
def set_extra_forms_user(user_admin):
|
||||||
|
|
@ -227,7 +178,7 @@ def set_extra_forms_user(user_admin):
|
||||||
|
|
||||||
user_admin.forms['repeat_password'].required=True
|
user_admin.forms['repeat_password'].required=True
|
||||||
|
|
||||||
user_admin.forms['repeat_password'].label=_('Repeat Password')
|
user_admin.forms['repeat_password'].label=I18n.lang('common', 'repeat_password', 'Repeat Password')
|
||||||
|
|
||||||
def csrf_token(token_id='csrf_token'):
|
def csrf_token(token_id='csrf_token'):
|
||||||
|
|
||||||
|
|
@ -265,6 +216,6 @@ def check_csrf(name_csrf_token='csrf_token'):
|
||||||
csrf_token=session.get('csrf_token', '')
|
csrf_token=session.get('csrf_token', '')
|
||||||
|
|
||||||
if csrf_token=='' or csrf_token!=request.form.get(name_csrf_token):
|
if csrf_token=='' or csrf_token!=request.form.get(name_csrf_token):
|
||||||
abort(403)
|
abort(404)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,44 +1,16 @@
|
||||||
"""
|
|
||||||
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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from paramecio2.libraries.lists import SimpleList
|
from paramecio2.libraries.lists import SimpleList
|
||||||
from flask import request, redirect, flash
|
from flask import request, redirect, flash
|
||||||
from paramecio2.libraries.urls import add_get_parameters
|
from paramecio2.libraries.urls import add_get_parameters
|
||||||
#from paramecio.citoplasma.mtemplates import set_flash_message
|
#from paramecio.citoplasma.mtemplates import set_flash_message
|
||||||
from paramecio2.libraries.formsutils import show_form
|
from paramecio2.libraries.formsutils import show_form
|
||||||
from paramecio2.libraries.mtemplates import env_theme, PTemplate
|
from paramecio2.libraries.i18n import I18n
|
||||||
from paramecio2.libraries.i18n import I18n, PGetText
|
|
||||||
from paramecio2.libraries.formsutils import check_csrf
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
pgettext=PGetText(__file__)
|
|
||||||
_=pgettext.gettext
|
|
||||||
|
|
||||||
#env=env_theme(__file__)
|
|
||||||
|
|
||||||
#t=PTemplate(env)
|
|
||||||
|
|
||||||
class GenerateAdminClass:
|
class GenerateAdminClass:
|
||||||
"""Class for insert, update and list items of a model
|
"""Class for insert, update and list items of a model
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, model, url, t=None, query_args=None, request_post=None):
|
def __init__(self, model, url, t):
|
||||||
"""A class for generate forms, insert and update items from a database model
|
"""A class for generate forms, insert and update items from a database model
|
||||||
|
|
||||||
For an easy and fast access to database data, you can use this class for get a simple database model of paramecio and get list of items, add forms, edit forms and more.
|
For an easy and fast access to database data, you can use this class for get a simple database model of paramecio and get list of items, add forms, edit forms and more.
|
||||||
|
|
@ -66,20 +38,9 @@ class GenerateAdminClass:
|
||||||
|
|
||||||
self.model=model
|
self.model=model
|
||||||
|
|
||||||
if t:
|
self.t=t
|
||||||
|
|
||||||
self.t=t
|
self.list=SimpleList(model, url, t)
|
||||||
else:
|
|
||||||
|
|
||||||
env=env_theme(__file__)
|
|
||||||
|
|
||||||
self.t=PTemplate(env)
|
|
||||||
|
|
||||||
#self.t.l=pgettext
|
|
||||||
|
|
||||||
#self.t.add_filter(self.t._)
|
|
||||||
|
|
||||||
self.list=SimpleList(model, url, self.t)
|
|
||||||
|
|
||||||
self.arr_fields_edit=list(model.fields.keys())
|
self.arr_fields_edit=list(model.fields.keys())
|
||||||
|
|
||||||
|
|
@ -115,11 +76,7 @@ class GenerateAdminClass:
|
||||||
|
|
||||||
self.post_update=None
|
self.post_update=None
|
||||||
|
|
||||||
self.text_home=_('Home')
|
self.text_home=I18n.lang('common', 'home', 'Home')
|
||||||
|
|
||||||
self.query_args=None
|
|
||||||
|
|
||||||
self.request_post=None
|
|
||||||
|
|
||||||
def show(self):
|
def show(self):
|
||||||
""" Method for show the admin model
|
""" Method for show the admin model
|
||||||
|
|
@ -130,13 +87,9 @@ class GenerateAdminClass:
|
||||||
html (str): The html content of the admin page, can be, items list, forms for create items, etc...
|
html (str): The html content of the admin page, can be, items list, forms for create items, etc...
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not self.query_args:
|
op_admin=request.args.get('op_admin', '0')
|
||||||
op_admin=request.args.get('op_admin', '0')
|
|
||||||
item_id=request.args.get('id', '0')
|
|
||||||
|
|
||||||
else:
|
item_id=request.args.get('id', '0')
|
||||||
op_admin=self.query_args.get('op_admin', '0')
|
|
||||||
item_id=self.query_args.get('id', '0')
|
|
||||||
|
|
||||||
if len(self.model.forms)==0:
|
if len(self.model.forms)==0:
|
||||||
|
|
||||||
|
|
@ -153,26 +106,21 @@ class GenerateAdminClass:
|
||||||
|
|
||||||
post=None
|
post=None
|
||||||
|
|
||||||
title_edit=_('Add new item')
|
title_edit=I18n.lang('common', 'add_new_item', 'Add new item')
|
||||||
|
|
||||||
pass_value=False
|
pass_value=False
|
||||||
|
|
||||||
if item_id!='0':
|
if item_id!='0':
|
||||||
post=self.model.select_a_row(item_id, [], True)
|
post=self.model.select_a_row(item_id, [], True)
|
||||||
title_edit=_('Edit item')
|
title_edit=I18n.lang('common', 'edit_new_item', 'Edit item')
|
||||||
pass_value=True
|
pass_value=True
|
||||||
|
|
||||||
if post==None or post==False:
|
if post==None or post==False:
|
||||||
|
|
||||||
if item_id=='0':
|
if item_id=='0':
|
||||||
|
|
||||||
self.model.model_id=0
|
|
||||||
|
|
||||||
post={}
|
post={}
|
||||||
else:
|
else:
|
||||||
return ""
|
return ""
|
||||||
else:
|
|
||||||
self.model.model_id=int(item_id)
|
|
||||||
|
|
||||||
url_action=add_get_parameters(self.url, op_admin=2, id=item_id)
|
url_action=add_get_parameters(self.url, op_admin=2, id=item_id)
|
||||||
|
|
||||||
|
|
@ -182,8 +130,6 @@ class GenerateAdminClass:
|
||||||
|
|
||||||
elif op_admin=='2':
|
elif op_admin=='2':
|
||||||
|
|
||||||
check_csrf()
|
|
||||||
|
|
||||||
self.model.reset_conditions()
|
self.model.reset_conditions()
|
||||||
|
|
||||||
insert_row=self.model.insert
|
insert_row=self.model.insert
|
||||||
|
|
@ -197,34 +143,26 @@ class GenerateAdminClass:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
||||||
if not self.query_args:
|
item_id=str(int(request.args.get('id', '0')))
|
||||||
|
|
||||||
item_id=str(int(request.args.get('id', '0')))
|
|
||||||
else:
|
|
||||||
item_id=str(int(self.query_args.get('id', '0')))
|
|
||||||
|
|
||||||
except:
|
except:
|
||||||
|
|
||||||
item_id='0'
|
item_id='0'
|
||||||
|
|
||||||
title_edit=_('Add new item')
|
title_edit=I18n.lang('common', 'add_new_item', 'Add new item')
|
||||||
|
|
||||||
|
|
||||||
if item_id!='0':
|
if item_id!='0':
|
||||||
insert_row=self.model.update
|
insert_row=self.model.update
|
||||||
title_edit=_('Edit item')
|
title_edit=I18n.lang('common', 'edit_new_item', 'Edit item')
|
||||||
self.model.conditions=['WHERE `'+self.model.name+'`.`'+self.model.name_field_id+'`=%s', [item_id]]
|
self.model.conditions=['WHERE `'+self.model.name+'`.`'+self.model.name_field_id+'`=%s', [item_id]]
|
||||||
|
|
||||||
if not self.request_post:
|
post=dict(request.form)
|
||||||
|
|
||||||
post=dict(request.form)
|
|
||||||
else:
|
|
||||||
post=self.request_post
|
|
||||||
print(post)
|
|
||||||
if pre_update_ret:
|
if pre_update_ret:
|
||||||
|
|
||||||
if insert_row(post):
|
if insert_row(post):
|
||||||
flash(_('Task successful'))
|
flash(I18n.lang('common', 'task_successful', 'Task successful'))
|
||||||
|
|
||||||
if self.post_update:
|
if self.post_update:
|
||||||
if item_id=='0':
|
if item_id=='0':
|
||||||
|
|
@ -237,10 +175,7 @@ class GenerateAdminClass:
|
||||||
|
|
||||||
url_action=add_get_parameters(self.url, op_admin=2, id=item_id)
|
url_action=add_get_parameters(self.url, op_admin=2, id=item_id)
|
||||||
|
|
||||||
if not self.request_post:
|
post=dict(request.form)
|
||||||
post=dict(request.form)
|
|
||||||
else:
|
|
||||||
post=self.request_post
|
|
||||||
|
|
||||||
form=show_form(post, edit_forms, self.t, True)
|
form=show_form(post, edit_forms, self.t, True)
|
||||||
|
|
||||||
|
|
@ -250,7 +185,7 @@ class GenerateAdminClass:
|
||||||
else:
|
else:
|
||||||
url_action=add_get_parameters(self.url, op_admin=2, id=item_id)
|
url_action=add_get_parameters(self.url, op_admin=2, id=item_id)
|
||||||
|
|
||||||
#post=dict(request.form)
|
post=dict(request.form)
|
||||||
|
|
||||||
form=show_form(post, edit_forms, self.t, True)
|
form=show_form(post, edit_forms, self.t, True)
|
||||||
|
|
||||||
|
|
@ -261,20 +196,14 @@ class GenerateAdminClass:
|
||||||
|
|
||||||
elif op_admin=='3':
|
elif op_admin=='3':
|
||||||
|
|
||||||
if not self.query_args:
|
verified=request.args.get('verified', '0')
|
||||||
|
|
||||||
verified=request.args.get('verified', '0')
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
verified=self.query_args.get('verified', '0')
|
|
||||||
|
|
||||||
if verified=='1':
|
if verified=='1':
|
||||||
|
|
||||||
if item_id!='0':
|
if item_id!='0':
|
||||||
self.model.conditions=['WHERE `'+self.model.name+'`.`'+self.model.name_field_id+'`=%s', [item_id]]
|
self.model.conditions=['WHERE `'+self.model.name+'`.`'+self.model.name_field_id+'`=%s', [item_id]]
|
||||||
self.model.delete()
|
self.model.delete()
|
||||||
flash(_('Task successful'))
|
flash(I18n.lang('common', 'task_successful', 'Task successful'))
|
||||||
return redirect(self.url_redirect)
|
return redirect(self.url_redirect)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
@ -353,11 +282,7 @@ class GenerateConfigClass:
|
||||||
|
|
||||||
self.post_update=None
|
self.post_update=None
|
||||||
|
|
||||||
self.text_home=_('Home')
|
self.text_home=I18n.lang('common', 'home', 'Home')
|
||||||
|
|
||||||
self.query_args=None
|
|
||||||
|
|
||||||
self.request_post=None
|
|
||||||
|
|
||||||
def show(self):
|
def show(self):
|
||||||
|
|
||||||
|
|
@ -367,17 +292,13 @@ class GenerateConfigClass:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
#op_config=request.args.get('op_config', '0')
|
op_config=request.args.get('op_config', '0')
|
||||||
if not self.query_args:
|
|
||||||
op_config=request.args.get('op_config', '0')
|
|
||||||
else:
|
|
||||||
op_config=self.query_args.get('op_config', '0')
|
|
||||||
|
|
||||||
if len(self.model.forms)==0:
|
if len(self.model.forms)==0:
|
||||||
|
|
||||||
self.model.create_forms()
|
self.model.create_forms()
|
||||||
|
|
||||||
title_edit=_('Edit')+' '+self.title_name
|
title_edit=I18n.lang('common', 'edit', 'Edit')+' '+self.title_name
|
||||||
|
|
||||||
edit_forms=OrderedDict()
|
edit_forms=OrderedDict()
|
||||||
|
|
||||||
|
|
@ -399,32 +320,21 @@ class GenerateConfigClass:
|
||||||
if c:
|
if c:
|
||||||
insert_model=self.model.update
|
insert_model=self.model.update
|
||||||
|
|
||||||
#post=dict(request.form)
|
post=dict(request.form)
|
||||||
if not self.request_post:
|
|
||||||
|
|
||||||
post=dict(request.form)
|
|
||||||
else:
|
|
||||||
post=self.request_post
|
|
||||||
|
|
||||||
|
|
||||||
if insert_model(post):
|
if insert_model(post):
|
||||||
flash(_('Task successful'))
|
set_flash_message(I18n.lang('common', 'task_successful', 'Task successful'))
|
||||||
self.model.yes_reset_conditions=True
|
self.model.yes_reset_conditions=True
|
||||||
|
|
||||||
if self.post_update:
|
if self.post_update:
|
||||||
self.post_update(self)
|
self.post_update(self)
|
||||||
|
|
||||||
return redirect(self.url_redirect)
|
redirect(self.url_redirect)
|
||||||
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
#post=dict(request.form)
|
post=dict(request.form)
|
||||||
if not self.request_post:
|
|
||||||
post=dict(request.form)
|
|
||||||
else:
|
|
||||||
post=self.request_post
|
|
||||||
|
|
||||||
|
|
||||||
form=show_form(post, edit_forms, self.t, True)
|
form=show_form(post, edit_forms, self.t, True)
|
||||||
self.model.yes_reset_conditions=True
|
self.model.yes_reset_conditions=True
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,3 @@
|
||||||
"""
|
|
||||||
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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from flask import request
|
from flask import request
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,145 +0,0 @@
|
||||||
#/usr/bin/env python3
|
|
||||||
|
|
||||||
#from paramecio.citoplasma.urls import add_get_parameters
|
|
||||||
from paramecio2.libraries.urls import add_get_parameters
|
|
||||||
|
|
||||||
class HierarchyLinks:
|
|
||||||
|
|
||||||
def __init__(arr_links, t=None):
|
|
||||||
|
|
||||||
self.arr_links=arr_links
|
|
||||||
|
|
||||||
self.arr_indexes={}
|
|
||||||
|
|
||||||
def update_links(self, link_father, link_son, text):
|
|
||||||
|
|
||||||
self.arr_links[link_father][link_son]=text
|
|
||||||
|
|
||||||
|
|
||||||
def calculate_indexes():
|
|
||||||
|
|
||||||
#oreach(self.arr_links as $father_link => $arr_child_links)
|
|
||||||
for father_link, arr_child_links in self.arr_links.items():
|
|
||||||
|
|
||||||
#foreach($arr_child_links as $link => $text)
|
|
||||||
for link, text in self.arr_child_links.items():
|
|
||||||
|
|
||||||
self.arr_indexes[link]=father_link
|
|
||||||
|
|
||||||
|
|
||||||
def result(last_link, arr_result=[], yes_last_link=0):
|
|
||||||
|
|
||||||
self.calculate_indexes()
|
|
||||||
|
|
||||||
if last_link in self.arr_indexes:
|
|
||||||
|
|
||||||
father=self.arr_indexes[last_link]
|
|
||||||
|
|
||||||
arr_last_link[0]=self.no_link
|
|
||||||
|
|
||||||
arr_last_link[1]=self.yes_link
|
|
||||||
|
|
||||||
yes_link_func=arr_last_link[yes_last_link]
|
|
||||||
|
|
||||||
if father!='':
|
|
||||||
|
|
||||||
arr_result.append(self.yes_link_func(last_link, self.arr_links[father][last_link]))
|
|
||||||
|
|
||||||
yes_last_link=1
|
|
||||||
|
|
||||||
arr_result=self.result(father, arr_result, yes_last_link)
|
|
||||||
|
|
||||||
return arr_result
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
arr_result.append(self.yes_link_func(last_link, self.arr_links[father][last_link]))
|
|
||||||
|
|
||||||
return arr_result
|
|
||||||
|
|
||||||
return arr_result
|
|
||||||
|
|
||||||
|
|
||||||
def show(link, separator='>>', class_link=''):
|
|
||||||
|
|
||||||
arr_result=self.result(link)
|
|
||||||
|
|
||||||
arr_result=array_reverse(arr_result)
|
|
||||||
|
|
||||||
return ' '+separator+' '.join(arr_result)
|
|
||||||
|
|
||||||
def yes_link(link, text):
|
|
||||||
|
|
||||||
return '<a href="'+link+'">'+text+'</a>'
|
|
||||||
|
|
||||||
|
|
||||||
def no_link(link, text):
|
|
||||||
|
|
||||||
return text
|
|
||||||
|
|
||||||
class HierarchyModelLinks:
|
|
||||||
|
|
||||||
def __init__(self, model, first_element_title, field_name, field_parent, base_url):
|
|
||||||
|
|
||||||
self.model=model
|
|
||||||
self.field_parent=field_parent
|
|
||||||
self.field_name=field_name
|
|
||||||
self.base_url=base_url
|
|
||||||
self.arr_parent={}
|
|
||||||
self.arr_son=[]
|
|
||||||
self.first_element_title=first_element_title
|
|
||||||
|
|
||||||
def prepare(self):
|
|
||||||
|
|
||||||
conditions=self.model.conditions
|
|
||||||
|
|
||||||
with self.model.set_conditions('', []).select([self.model.name_field_id, self.field_name, self.field_parent]) as cur:
|
|
||||||
for arr_model in cur:
|
|
||||||
if self.field_parent not in self.arr_parent:
|
|
||||||
self.arr_parent[arr_model[self.model.name_field_id]]=[]
|
|
||||||
|
|
||||||
self.arr_parent[arr_model[self.model.name_field_id]]=[self.model.fields[self.field_name].show_formatted(arr_model[self.field_name]), arr_model[self.field_parent]]
|
|
||||||
|
|
||||||
self.model.conditions=conditions
|
|
||||||
|
|
||||||
def parents(self, son_id, url_func):
|
|
||||||
|
|
||||||
if son_id not in self.arr_parent or son_id==0:
|
|
||||||
return
|
|
||||||
|
|
||||||
self.arr_son.insert(0, url_func(son_id, self.arr_parent[son_id][0]))
|
|
||||||
|
|
||||||
self.parents(self.arr_parent[son_id][1], self.url)
|
|
||||||
|
|
||||||
|
|
||||||
def no_url(self, son_id, title):
|
|
||||||
return title
|
|
||||||
|
|
||||||
def url(self, son_id, title):
|
|
||||||
|
|
||||||
args={}
|
|
||||||
|
|
||||||
args[self.field_parent]=str(son_id)
|
|
||||||
|
|
||||||
return '<a href="%s">%s</a>' % (add_get_parameters(self.base_url, **args), title)
|
|
||||||
|
|
||||||
def show(self, son_id, separator=' >> '):
|
|
||||||
|
|
||||||
try:
|
|
||||||
son_id=int(son_id)
|
|
||||||
except:
|
|
||||||
son_id=0
|
|
||||||
|
|
||||||
self.prepare()
|
|
||||||
|
|
||||||
self.parents(son_id, self.no_url)
|
|
||||||
|
|
||||||
self.arr_son.insert(0, self.url(0, self.first_element_title))
|
|
||||||
|
|
||||||
return separator.join(self.arr_son)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,30 +1,9 @@
|
||||||
#!/usr/bin/env python3
|
#!/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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from importlib import import_module
|
from importlib import import_module
|
||||||
import gettext
|
|
||||||
#from paramecio.citoplasma.sessions import get_session
|
#from paramecio.citoplasma.sessions import get_session
|
||||||
import json
|
import json
|
||||||
from flask import session, has_request_context
|
from flask import session, has_request_context
|
||||||
import os
|
|
||||||
|
|
||||||
yes_session=False
|
yes_session=False
|
||||||
|
|
||||||
|
|
@ -49,44 +28,6 @@ def load_lang(*args):
|
||||||
|
|
||||||
# here load the language
|
# here load the language
|
||||||
|
|
||||||
class PGetText:
|
|
||||||
|
|
||||||
# Dict where all gettext domain are saved -> domain=name, example, admin, libraries, pastafari2, etc...
|
|
||||||
|
|
||||||
l={}
|
|
||||||
|
|
||||||
def __init__(self, module_file):
|
|
||||||
|
|
||||||
module_dir=os.path.dirname(os.path.realpath(module_file))
|
|
||||||
|
|
||||||
module_name=os.path.basename(module_dir)
|
|
||||||
|
|
||||||
if module_name not in PGetText.l:
|
|
||||||
|
|
||||||
PGetText.l[module_name]={}
|
|
||||||
|
|
||||||
for i in I18n.dict_i18n:
|
|
||||||
|
|
||||||
if i not in PGetText.l[module_name]:
|
|
||||||
|
|
||||||
PGetText.l[module_name][i]=gettext.translation(module_name, module_dir+'/languages/', languages=[i], fallback=True)
|
|
||||||
PGetText.l[module_name][i].install()
|
|
||||||
|
|
||||||
self.module=module_name
|
|
||||||
|
|
||||||
def gettext(self, text):
|
|
||||||
|
|
||||||
return PGetText.l[self.module][I18n.get_default_lang()].gettext(text)
|
|
||||||
|
|
||||||
def pgettext(module_file):
|
|
||||||
|
|
||||||
module=os.path.dirname(os.path.realpath(module_file))
|
|
||||||
|
|
||||||
base_name=os.path.dirname(os.path.realpath(module))
|
|
||||||
|
|
||||||
l=gettext.translation(os.path.basename(base_name), module+'/languages/', languages=I18n.get_default_lang(), fallback=True)
|
|
||||||
|
|
||||||
return l.gettext
|
|
||||||
|
|
||||||
class I18n:
|
class I18n:
|
||||||
"""Class for i18n tasks
|
"""Class for i18n tasks
|
||||||
|
|
@ -105,64 +46,9 @@ class I18n:
|
||||||
|
|
||||||
l={}
|
l={}
|
||||||
|
|
||||||
def __init__(self, module):
|
|
||||||
|
|
||||||
self.module=module
|
|
||||||
|
|
||||||
def slang(self, symbol, text_default, lang=None):
|
|
||||||
"""Method for get a string from selected language but object oriented
|
|
||||||
|
|
||||||
Method for get a string from selected language but object oriented
|
|
||||||
|
|
||||||
Args:
|
|
||||||
symbol (str): The symbol used for identify the text string.
|
|
||||||
text_default (str): The text default used. You have use how base for translations.
|
|
||||||
"""
|
|
||||||
return I18n.lang(self.module, symbol, text_default, lang)
|
|
||||||
|
|
||||||
def tlang(self, text_default, lang=None):
|
|
||||||
"""Method for get a string from selected language but object oriented and using module and symbol by default
|
|
||||||
|
|
||||||
Method for get a string from selected language but object oriented and using module and symbol by default
|
|
||||||
|
|
||||||
Args:
|
|
||||||
text_default (str): The text default used. You have use how base for translations.
|
|
||||||
"""
|
|
||||||
|
|
||||||
symbol=text_default[:60]
|
|
||||||
|
|
||||||
return I18n.lang(self.module, symbol, text_default, lang)
|
|
||||||
|
|
||||||
#@staticmethod
|
#@staticmethod
|
||||||
#def set_lang(code_lang):
|
#def set_lang(code_lang):
|
||||||
# if default_lang
|
# if default_lang
|
||||||
def __init__(self, module):
|
|
||||||
|
|
||||||
self.module=module
|
|
||||||
|
|
||||||
def slang(self, symbol, text_default, lang=None):
|
|
||||||
"""Method for get a string from selected language but object oriented
|
|
||||||
|
|
||||||
Method for get a string from selected language but object oriented
|
|
||||||
|
|
||||||
Args:
|
|
||||||
symbol (str): The symbol used for identify the text string.
|
|
||||||
text_default (str): The text default used. You have use how base for translations.
|
|
||||||
"""
|
|
||||||
return I18n.lang(self.module, symbol, text_default)
|
|
||||||
|
|
||||||
def tlang(self, text_default, lang=None):
|
|
||||||
"""Method for get a string from selected language but object oriented and using module and symbol by default
|
|
||||||
|
|
||||||
Method for get a string from selected language but object oriented and using module and symbol by default
|
|
||||||
|
|
||||||
Args:
|
|
||||||
text_default (str): The text default used. You have use how base for translations.
|
|
||||||
"""
|
|
||||||
|
|
||||||
symbol=text_default[:60]
|
|
||||||
|
|
||||||
return I18n.lang(self.module, symbol, text_default)
|
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
@ -244,4 +130,3 @@ class I18n:
|
||||||
|
|
||||||
return json.dumps(arr_final)
|
return json.dumps(arr_final)
|
||||||
|
|
||||||
common_pgettext=PGetText(__file__)
|
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,3 @@
|
||||||
"""
|
|
||||||
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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from hashlib import sha512, sha256
|
from hashlib import sha512, sha256
|
||||||
from base64 import b64encode
|
from base64 import b64encode
|
||||||
from os import urandom
|
from os import urandom
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -1,59 +0,0 @@
|
||||||
# SOME DESCRIPTIVE TITLE.
|
|
||||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
|
||||||
# This file is distributed under the same license as the PACKAGE package.
|
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
|
||||||
#
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: \n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2023-12-18 23:51+0100\n"
|
|
||||||
"PO-Revision-Date: 2023-12-19 00:01+0100\n"
|
|
||||||
"Last-Translator: \n"
|
|
||||||
"Language-Team: \n"
|
|
||||||
"Language: es\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"X-Generator: Poedit 3.4.1\n"
|
|
||||||
|
|
||||||
#: formsutils.py:183
|
|
||||||
msgid "Repeat Password"
|
|
||||||
msgstr "Repetir contraseña"
|
|
||||||
|
|
||||||
#: lists.py:113
|
|
||||||
msgid "Options"
|
|
||||||
msgstr "Opciones"
|
|
||||||
|
|
||||||
#: lists.py:222 generate_admin_class.py:304
|
|
||||||
msgid "Edit"
|
|
||||||
msgstr "Editar"
|
|
||||||
|
|
||||||
#: lists.py:223
|
|
||||||
msgid "Delete"
|
|
||||||
msgstr "Borrar"
|
|
||||||
|
|
||||||
#: lists.py:395 templates/utils/list.phtml:133
|
|
||||||
msgid "Pages"
|
|
||||||
msgstr "Páginas"
|
|
||||||
|
|
||||||
#: generate_admin_class.py:82 generate_admin_class.py:288
|
|
||||||
msgid "Home"
|
|
||||||
msgstr "Inicio"
|
|
||||||
|
|
||||||
#: generate_admin_class.py:112 generate_admin_class.py:155
|
|
||||||
msgid "Add new item"
|
|
||||||
msgstr "Añadir nuevo elemento"
|
|
||||||
|
|
||||||
#: generate_admin_class.py:118 generate_admin_class.py:160
|
|
||||||
msgid "Edit item"
|
|
||||||
msgstr "Editar elemento"
|
|
||||||
|
|
||||||
#: generate_admin_class.py:168 generate_admin_class.py:209
|
|
||||||
#: generate_admin_class.py:329
|
|
||||||
msgid "Task successful"
|
|
||||||
msgstr "Tarea exitosa"
|
|
||||||
|
|
||||||
#: templates/utils/list.phtml:14
|
|
||||||
msgid "Search"
|
|
||||||
msgstr "Buscar"
|
|
||||||
Binary file not shown.
|
|
@ -1,59 +0,0 @@
|
||||||
# SOME DESCRIPTIVE TITLE.
|
|
||||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
|
||||||
# This file is distributed under the same license as the PACKAGE package.
|
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
|
||||||
#
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: \n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2023-12-18 23:51+0100\n"
|
|
||||||
"PO-Revision-Date: 2023-12-19 00:01+0100\n"
|
|
||||||
"Last-Translator: \n"
|
|
||||||
"Language-Team: \n"
|
|
||||||
"Language: es\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"X-Generator: Poedit 3.4.1\n"
|
|
||||||
|
|
||||||
#: formsutils.py:183
|
|
||||||
msgid "Repeat Password"
|
|
||||||
msgstr "Repetir contraseña"
|
|
||||||
|
|
||||||
#: lists.py:113
|
|
||||||
msgid "Options"
|
|
||||||
msgstr "Opciones"
|
|
||||||
|
|
||||||
#: lists.py:222 generate_admin_class.py:304
|
|
||||||
msgid "Edit"
|
|
||||||
msgstr "Editar"
|
|
||||||
|
|
||||||
#: lists.py:223
|
|
||||||
msgid "Delete"
|
|
||||||
msgstr "Borrar"
|
|
||||||
|
|
||||||
#: lists.py:395 templates/utils/list.phtml:133
|
|
||||||
msgid "Pages"
|
|
||||||
msgstr "Páginas"
|
|
||||||
|
|
||||||
#: generate_admin_class.py:82 generate_admin_class.py:288
|
|
||||||
msgid "Home"
|
|
||||||
msgstr "Inicio"
|
|
||||||
|
|
||||||
#: generate_admin_class.py:112 generate_admin_class.py:155
|
|
||||||
msgid "Add new item"
|
|
||||||
msgstr "Añadir nuevo elemento"
|
|
||||||
|
|
||||||
#: generate_admin_class.py:118 generate_admin_class.py:160
|
|
||||||
msgid "Edit item"
|
|
||||||
msgstr "Editar elemento"
|
|
||||||
|
|
||||||
#: generate_admin_class.py:168 generate_admin_class.py:209
|
|
||||||
#: generate_admin_class.py:329
|
|
||||||
msgid "Task successful"
|
|
||||||
msgstr "Tarea exitosa"
|
|
||||||
|
|
||||||
#: templates/utils/list.phtml:14
|
|
||||||
msgid "Search"
|
|
||||||
msgstr "Buscar"
|
|
||||||
|
|
@ -1,35 +1,13 @@
|
||||||
"""
|
|
||||||
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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
#By default id is not showed
|
#By default id is not showed
|
||||||
|
|
||||||
from paramecio2.libraries.pages import Pages
|
from paramecio2.libraries.pages import Pages
|
||||||
from paramecio2.libraries.urls import add_get_parameters
|
from paramecio2.libraries.urls import add_get_parameters
|
||||||
from paramecio2.libraries.i18n import I18n, PGetText
|
from paramecio2.libraries.i18n import I18n
|
||||||
#from flask import request, session
|
#from flask import request, session
|
||||||
from paramecio2.libraries.get_data import get_query_args
|
from paramecio2.libraries.get_data import get_query_args
|
||||||
import sys
|
import sys
|
||||||
import re
|
import re
|
||||||
|
|
||||||
pgettext=PGetText(__file__)
|
|
||||||
_=pgettext.gettext
|
|
||||||
|
|
||||||
class SimpleList:
|
class SimpleList:
|
||||||
"""Class for create item list from a model table
|
"""Class for create item list from a model table
|
||||||
"""
|
"""
|
||||||
|
|
@ -129,7 +107,7 @@ class SimpleList:
|
||||||
|
|
||||||
#self.yes_options=True
|
#self.yes_options=True
|
||||||
|
|
||||||
self.arr_extra_fields=[_('Options')]
|
self.arr_extra_fields=[I18n.lang('common', 'options', 'Options')]
|
||||||
|
|
||||||
self.arr_extra_options=[SimpleList.standard_options]
|
self.arr_extra_options=[SimpleList.standard_options]
|
||||||
|
|
||||||
|
|
@ -238,8 +216,8 @@ class SimpleList:
|
||||||
options (list): Return a list of basic options for items row
|
options (list): Return a list of basic options for items row
|
||||||
"""
|
"""
|
||||||
options=[]
|
options=[]
|
||||||
options.append('<a href="'+add_get_parameters(url, op_admin=1, id=id)+'">'+_('Edit')+'</a>')
|
options.append('<a href="'+add_get_parameters(url, op_admin=1, id=id)+'">'+I18n.lang('common', 'edit', 'Edit')+'</a>')
|
||||||
options.append('<a href="'+add_get_parameters(url, op_admin=3, id=id)+'">'+_('Delete')+'</a>')
|
options.append('<a href="'+add_get_parameters(url, op_admin=3, id=id)+'">'+I18n.lang('common', 'delete', 'Delete')+'</a>')
|
||||||
return options
|
return options
|
||||||
|
|
||||||
def show(self):
|
def show(self):
|
||||||
|
|
@ -308,7 +286,7 @@ class AjaxList(SimpleList):
|
||||||
"""Class for make a list from a table based in Ajax
|
"""Class for make a list from a table based in Ajax
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Fields example: [['Hostname', True], ['IP', True], ['Options', False]]
|
# Fields example: [[I18n.lang('cuchulu', 'hostname', 'Hostname'), True], ['IP', True], [I18n.lang('cuchulu', 'options', 'Options'), False]]
|
||||||
|
|
||||||
# arr_order_fields=['server.hostname', 'server.ip']
|
# arr_order_fields=['server.hostname', 'server.ip']
|
||||||
|
|
||||||
|
|
@ -411,7 +389,7 @@ class AjaxList(SimpleList):
|
||||||
|
|
||||||
pages=Pages()
|
pages=Pages()
|
||||||
|
|
||||||
html_pages=_('Pages')+': '+pages.show( begin_page, total_elements, limit, '#' ,initial_num_pages=self.initial_num_pages, variable='begin_page', label='', func_jscript='')
|
html_pages=I18n.lang('cuchulu', 'pages', 'Pages')+': '+pages.show( begin_page, total_elements, limit, '#' ,initial_num_pages=self.initial_num_pages, variable='begin_page', label='', func_jscript='')
|
||||||
|
|
||||||
with self.db.query(str_query, params) as cursor:
|
with self.db.query(str_query, params) as cursor:
|
||||||
for row in cursor:
|
for row in cursor:
|
||||||
|
|
@ -433,7 +411,5 @@ class AjaxList(SimpleList):
|
||||||
return {'fields': self.fields, 'rows': rows, 'html_pages': html_pages}
|
return {'fields': self.fields, 'rows': rows, 'html_pages': html_pages}
|
||||||
|
|
||||||
|
|
||||||
class SimpleAjaxList():
|
|
||||||
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,3 @@
|
||||||
"""
|
|
||||||
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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import csv
|
import csv
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,8 @@
|
||||||
"""
|
|
||||||
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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Template frontend from mako.
|
# Template frontend from mako.
|
||||||
|
|
||||||
#import gettext
|
import gettext
|
||||||
from mako.template import Template
|
from mako.template import Template
|
||||||
from flask import url_for as url_for_flask
|
from flask import session, url_for
|
||||||
from mako.lookup import TemplateLookup
|
from mako.lookup import TemplateLookup
|
||||||
from os import path
|
from os import path
|
||||||
try:
|
try:
|
||||||
|
|
@ -31,24 +12,12 @@ except:
|
||||||
theme='default'
|
theme='default'
|
||||||
reloader=False
|
reloader=False
|
||||||
|
|
||||||
#import gettext
|
import gettext
|
||||||
import sys
|
import sys
|
||||||
from paramecio2.libraries.i18n import I18n, PGetText
|
from paramecio2.libraries.i18n import I18n
|
||||||
from paramecio2.libraries.urls import make_url, make_media_url, add_get_parameters
|
from paramecio2.libraries.urls import make_url, make_media_url, add_get_parameters
|
||||||
from paramecio2.libraries.formsutils import csrf_token
|
from paramecio2.libraries.formsutils import csrf_token
|
||||||
|
|
||||||
framework='flask'
|
|
||||||
|
|
||||||
if hasattr(config, 'framework'):
|
|
||||||
framework=config.framework
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
|
||||||
def _(text):
|
|
||||||
|
|
||||||
return gettext.gettext(text)
|
|
||||||
"""
|
|
||||||
|
|
||||||
def env_theme(module, cache_enabled=True, cache_impl='', cache_args={}, module_directory="./tmp/modules"):
|
def env_theme(module, cache_enabled=True, cache_impl='', cache_args={}, module_directory="./tmp/modules"):
|
||||||
"""Function for create an environment for mako templates
|
"""Function for create an environment for mako templates
|
||||||
|
|
||||||
|
|
@ -74,8 +43,6 @@ def env_theme(module, cache_enabled=True, cache_impl='', cache_args={}, module_d
|
||||||
|
|
||||||
standard_templates=path.dirname(__file__)+'/templates'
|
standard_templates=path.dirname(__file__)+'/templates'
|
||||||
|
|
||||||
standard_languages=path.dirname(__file__)+'/languages'
|
|
||||||
|
|
||||||
module_directory+='/'+module
|
module_directory+='/'+module
|
||||||
|
|
||||||
module_templates=module+'/templates'
|
module_templates=module+'/templates'
|
||||||
|
|
@ -97,7 +64,7 @@ class PTemplate:
|
||||||
|
|
||||||
templates_loaded={}
|
templates_loaded={}
|
||||||
|
|
||||||
def __init__(self, environment, url_for_function=None):
|
def __init__(self, environment):
|
||||||
"""A class used how shortcuts for Mako template functions.
|
"""A class used how shortcuts for Mako template functions.
|
||||||
|
|
||||||
This class is used to have a set of shortcuts and hooks to Mako templates functions and methods over a series of default options.
|
This class is used to have a set of shortcuts and hooks to Mako templates functions and methods over a series of default options.
|
||||||
|
|
@ -123,22 +90,15 @@ class PTemplate:
|
||||||
|
|
||||||
self.add_filter(I18n.lang)
|
self.add_filter(I18n.lang)
|
||||||
|
|
||||||
self.add_filter(make_url)
|
_=gettext.gettext
|
||||||
|
|
||||||
|
self.add_filter(_)
|
||||||
|
|
||||||
|
#self.add_filter(make_url)
|
||||||
|
|
||||||
self.add_filter(make_media_url)
|
self.add_filter(make_media_url)
|
||||||
|
|
||||||
if not url_for_function:
|
self.add_filter(url_for)
|
||||||
|
|
||||||
url_for=url_for_flask
|
|
||||||
|
|
||||||
self.add_filter(url_for)
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
url_for=url_for_function
|
|
||||||
|
|
||||||
self.add_filter(url_for)
|
|
||||||
|
|
||||||
|
|
||||||
self.add_filter(csrf_token)
|
self.add_filter(csrf_token)
|
||||||
|
|
||||||
|
|
@ -148,30 +108,6 @@ class PTemplate:
|
||||||
|
|
||||||
self.add_filter(self.load_js)
|
self.add_filter(self.load_js)
|
||||||
|
|
||||||
# Loading language domain for gettext in templates
|
|
||||||
|
|
||||||
base_name=path.dirname(path.realpath(__file__))
|
|
||||||
|
|
||||||
module_env=self.env.directories[1].replace('/templates', '')
|
|
||||||
|
|
||||||
#print(path.basename(module_env)+' '+base_name+'/languages/')
|
|
||||||
|
|
||||||
self.l=PGetText(module_env+'/app.py')
|
|
||||||
|
|
||||||
self.i18n=I18n(module_env)
|
|
||||||
|
|
||||||
self.add_filter(self._)
|
|
||||||
|
|
||||||
self.i18n=I18n(base_name)
|
|
||||||
|
|
||||||
self.add_filter(self.i18n.slang)
|
|
||||||
|
|
||||||
self.add_filter(self.i18n.tlang)
|
|
||||||
|
|
||||||
def _(self, text):
|
|
||||||
|
|
||||||
return self.l.gettext(text)
|
|
||||||
|
|
||||||
def add_js(self, js, module=''):
|
def add_js(self, js, module=''):
|
||||||
"""Function for add js to self.js attribute
|
"""Function for add js to self.js attribute
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,5 @@
|
||||||
#!/usr/bin/env python3
|
#!/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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from math import ceil, floor
|
from math import ceil, floor
|
||||||
from paramecio2.libraries.urls import add_get_parameters
|
from paramecio2.libraries.urls import add_get_parameters
|
||||||
from paramecio2.libraries.i18n import I18n
|
from paramecio2.libraries.i18n import I18n
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,3 @@
|
||||||
"""
|
|
||||||
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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from flask import g, session, redirect, url_for
|
from flask import g, session, redirect, url_for
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
from paramecio2.libraries.db.webmodel import WebModel
|
from paramecio2.libraries.db.webmodel import WebModel
|
||||||
|
|
@ -32,7 +13,7 @@ def db(f):
|
||||||
|
|
||||||
"""Wrapper function for add db connection to your flask function
|
"""Wrapper function for add db connection to your flask function
|
||||||
|
|
||||||
Wrapper function for add db connection to your flask function. Also close the connection if error or function exception is finished.
|
Wrapper function for add db connection to your flask function. Also close the connection if error or function exection is finished.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
*args (mixed): The args of function
|
*args (mixed): The args of function
|
||||||
|
|
@ -42,8 +23,7 @@ def db(f):
|
||||||
wrapper (function): Return the wrapper.
|
wrapper (function): Return the wrapper.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not hasattr(g, 'connection'):
|
g.connection=WebModel.connection()
|
||||||
g.connection=WebModel.connection()
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
from paramecio2.libraries.db import corefields
|
|
||||||
from paramecio2.libraries.db.extrafields.jsonfield import JsonField
|
|
||||||
from paramecio2.libraries.db.extrafields.dictfield import DictField
|
|
||||||
try:
|
|
||||||
import ujson as json
|
|
||||||
except:
|
|
||||||
import json
|
|
||||||
|
|
||||||
"""A class for list objects with data fields
|
|
||||||
"""
|
|
||||||
|
|
||||||
class ListItem:
|
|
||||||
pass
|
|
||||||
|
|
||||||
"""Typical item """
|
|
||||||
|
|
||||||
class Items(ListItem):
|
|
||||||
|
|
||||||
name=corefields.CharField('name')
|
|
||||||
|
|
||||||
|
|
||||||
class StandardResponse:
|
|
||||||
|
|
||||||
error=corefields.BooleanField('error')
|
|
||||||
message=corefields.CharField('message')
|
|
||||||
code_error=corefields.IntegerField('code_error')
|
|
||||||
error_form=DictField('error_form', corefields.CharField('error_form'))
|
|
||||||
#items=JsonField('items', corefields.CharField)
|
|
||||||
|
|
||||||
def __init__(self, error=0, message='', code_error=0):
|
|
||||||
|
|
||||||
self.error=error
|
|
||||||
self.message=message
|
|
||||||
self.code_error=code_error
|
|
||||||
|
|
||||||
def toDict(self):
|
|
||||||
|
|
||||||
return self.__dict__
|
|
||||||
|
|
||||||
def toJSON(self):
|
|
||||||
return json.dumps( self, default=lambda o: o.__dict__, sort_keys=True, indent=4 )
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class ResponseItems(StandardResponse):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
@ -1,24 +1,4 @@
|
||||||
#!/usr/bin/env python3
|
#!/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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import smtplib
|
import smtplib
|
||||||
import mimetypes
|
import mimetypes
|
||||||
|
|
@ -29,7 +9,6 @@ from email.mime.base import MIMEBase
|
||||||
from email.mime.image import MIMEImage
|
from email.mime.image import MIMEImage
|
||||||
from email.mime.multipart import MIMEMultipart
|
from email.mime.multipart import MIMEMultipart
|
||||||
from email.mime.text import MIMEText
|
from email.mime.text import MIMEText
|
||||||
from email.utils import formataddr, formatdate
|
|
||||||
import ssl as ssl_module
|
import ssl as ssl_module
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
@ -130,7 +109,7 @@ class SendMail:
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def send(self, from_address, to_address: list, subject, message, content_type='plain', attachments=[], reply_to=()):
|
def send(self, from_address, to_address: list, subject, message, content_type='plain', attachments=[]):
|
||||||
""" Method that send email
|
""" Method that send email
|
||||||
|
|
||||||
With this method you can send email to multiple address, html, and add attachments to email
|
With this method you can send email to multiple address, html, and add attachments to email
|
||||||
|
|
@ -148,10 +127,6 @@ class SendMail:
|
||||||
if not self.connect():
|
if not self.connect():
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if len(reply_to)==0:
|
|
||||||
reply_to=(from_address, from_address)
|
|
||||||
|
|
||||||
|
|
||||||
COMMASPACE=', '
|
COMMASPACE=', '
|
||||||
|
|
||||||
if len(attachments)==0:
|
if len(attachments)==0:
|
||||||
|
|
@ -159,9 +134,6 @@ class SendMail:
|
||||||
msg=MIMEText(message, content_type)
|
msg=MIMEText(message, content_type)
|
||||||
|
|
||||||
msg['Subject']=subject
|
msg['Subject']=subject
|
||||||
|
|
||||||
msg['Reply-To']=formataddr(reply_to)
|
|
||||||
|
|
||||||
msg['From']=from_address
|
msg['From']=from_address
|
||||||
|
|
||||||
msg['To']=COMMASPACE.join(to_address)
|
msg['To']=COMMASPACE.join(to_address)
|
||||||
|
|
@ -177,15 +149,10 @@ class SendMail:
|
||||||
outer=MIMEMultipart()
|
outer=MIMEMultipart()
|
||||||
|
|
||||||
outer['Subject']=subject
|
outer['Subject']=subject
|
||||||
|
|
||||||
msg['Reply-To']=formataddr(reply_to)
|
|
||||||
|
|
||||||
outer['From']=from_address
|
outer['From']=from_address
|
||||||
|
|
||||||
outer['To']=COMMASPACE.join(to_address)
|
outer['To']=COMMASPACE.join(to_address)
|
||||||
|
|
||||||
#outer['Date']=formatdate()
|
|
||||||
|
|
||||||
# Attach message text
|
# Attach message text
|
||||||
|
|
||||||
msg=MIMEText(message, content_type)
|
msg=MIMEText(message, content_type)
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,3 @@
|
||||||
"""
|
|
||||||
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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from slugify import slugify as slugify_func
|
from slugify import slugify as slugify_func
|
||||||
|
|
||||||
def slugify(slug, *args, **wargs):
|
def slugify(slug, *args, **wargs):
|
||||||
|
|
|
||||||
|
|
@ -1,54 +1,38 @@
|
||||||
${add_js('jquery.min.js', 'admin')}
|
${add_js('jquery.min.js', 'admin')}
|
||||||
|
|
||||||
<!--<input type="number" min="1" max="31" name="${form}_day" id="time_${form}_day" class="form_day" value="${d}" size="2" maxlength="2"/>
|
<input type="number" min="1" max="31" name="${form}_day" id="time_${form}_day" class="form_day" value="${d}" size="2" maxlength="2"/>
|
||||||
<input type="number" min="1" max="12" name="${form}_month" id="time_${form}_month" class="form_month" value="${m}" size="2" maxlength="2"/>
|
<input type="number" min="1" max="12" name="${form}_month" id="time_${form}_month" class="form_month" value="${m}" size="2" maxlength="2"/>
|
||||||
<input type="number" name="${form}_year" id="time_${form}_year" class="form_year" value="${y}" size="4" maxlength="4"/>-->
|
<input type="number" name="${form}_year" id="time_${form}_year" class="form_year" value="${y}" size="4" maxlength="4"/>
|
||||||
<%
|
|
||||||
|
|
||||||
date=''
|
|
||||||
|
|
||||||
if d!='':
|
|
||||||
date='-'.join((str(y), str(m), str(d)))
|
|
||||||
|
|
||||||
time=''
|
|
||||||
|
|
||||||
if h!='':
|
|
||||||
time=':'.join((str(h), str(min)))
|
|
||||||
|
|
||||||
%>
|
|
||||||
<input type="date" value="${date}" name="${form}_date" id="${form}_date" />
|
|
||||||
% if yes_time==True:
|
% if yes_time==True:
|
||||||
<!--<input type="number" min="0" max="23" name="${form}_hour" id="time_${form}_hour" class="form_hour" value="${h}" size="2" maxlength="2"/>
|
<input type="text" min="0" max="23" name="${form}_hour" id="time_${form}_hour" class="form_hour" value="${h}" size="2" maxlength="2"/>
|
||||||
<input type="number" min="0" max="60" name="${form}_minute" id="time_${form}_minute" class="form_minute" value="${min}" size="2" maxlength="2"/>
|
<input type="text" min="0" max="60" name="${form}_minute" id="time_${form}_minute" class="form_minute" value="${min}" size="2" maxlength="2"/>
|
||||||
<input type="number" min="0" max="60" name="${form}_second" id="time_${form}_second" class="form_second" value="${s}" size="2" maxlength="2"/>-->
|
<input type="text" min="0" max="60" name="${form}_second" id="time_${form}_second" class="form_second" value="${s}" size="2" maxlength="2"/>
|
||||||
<input type="time" value="${time}" name="${form}_time" id="${form}_time" />
|
|
||||||
% endif
|
% endif
|
||||||
<input type="hidden" name="${form}" id="time_${form}" value="" />
|
<input type="hidden" name="${form}" id="time_${form}" value="" />
|
||||||
|
|
||||||
<script language="javascript">
|
<script language="javascript">
|
||||||
$(document).submit(function () {
|
$(document).submit(function () {
|
||||||
|
|
||||||
/*year=$("#time_${form}_year").val().toString();
|
year=$("#time_${form}_year").val().toString();
|
||||||
month=$("#time_${form}_month").val().toString();
|
month=$("#time_${form}_month").val().toString();
|
||||||
day=$("#time_${form}_day").val().toString();
|
day=$("#time_${form}_day").val().toString();
|
||||||
|
|
||||||
year=add_extra_length(year, 4);
|
year=add_extra_length(year, 4);
|
||||||
month=add_extra_length(month, 2);
|
month=add_extra_length(month, 2);
|
||||||
day=add_extra_length(day, 2); */
|
day=add_extra_length(day, 2);
|
||||||
|
|
||||||
//final_time=year+month+day
|
final_time=year+month+day
|
||||||
final_time=$('#${form}_date').val().replace(/-/g, '');
|
|
||||||
|
|
||||||
% if yes_time==True:
|
% if yes_time==True:
|
||||||
/*hour=$("#time_${form}_hour").val().toString();
|
hour=$("#time_${form}_hour").val().toString();
|
||||||
minute=$("#time_${form}_minute").val().toString();
|
minute=$("#time_${form}_minute").val().toString();
|
||||||
second=$("#time_${form}_second").val().toString();
|
second=$("#time_${form}_second").val().toString();
|
||||||
|
|
||||||
hour=add_extra_length(hour, 2);
|
hour=add_extra_length(hour, 2);
|
||||||
minute=add_extra_length(minute, 2);
|
minute=add_extra_length(minute, 2);
|
||||||
second=add_extra_length(second, 2); */
|
second=add_extra_length(second, 2);
|
||||||
|
|
||||||
final_time+=$('#${form}_time').val().replace(':', '')+'00';
|
final_time+=final_time;
|
||||||
|
|
||||||
% else:
|
% else:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
choose=''
|
choose=''
|
||||||
|
|
||||||
%>
|
%>
|
||||||
<span id="${name_form}_languages_form" style="display:inline-block;">
|
<div id="languages_form">
|
||||||
<%def name="select_lang(i18n, lang_selected)">
|
<%def name="select_lang(i18n, lang_selected)">
|
||||||
% if i18n==lang_selected:
|
% if i18n==lang_selected:
|
||||||
<%
|
<%
|
||||||
|
|
@ -28,23 +28,10 @@ choose=''
|
||||||
<%
|
<%
|
||||||
form.default_value=default_value[i18n]
|
form.default_value=default_value[i18n]
|
||||||
%>
|
%>
|
||||||
<span id="${name_form}_${i18n}_switch" class="${name_form}_i18n_form">${form.form()|n}</span> <a class="choose_flag ${name_form}_i18n_flag lang_form" id="${name_form}_${i18n}_element" href="#"><img src="${make_media_url('images/languages/'+i18n+'.png', 'admin')}" alt="${name_form}_${i18n}"></a>
|
<span id="${name_form}_${i18n}_switch" class="${name_form}_i18n_form">${form.form()|n}</span> <a class="choose_flag ${name_form}_i18n_flag lang_form" id="${name_form}_${i18n}_element" href="#"><img src="${make_media_url('images/languages/'+i18n+'.png', 'admin')}" alt="${name_form}_${i18n}"/></a>
|
||||||
|
|
||||||
% endfor
|
% endfor
|
||||||
<i class="fa fa-globe all_languages tooltip" aria-hidden="true" style="display:none;cursor:pointer;" data-tooltip-content="#tooltip_${name_form}_content"></i>
|
|
||||||
<div class="tooltip_templates" style="display:none;"><div id="tooltip_${name_form}_content">${_('All lenguages activated, if you change to multilanguage, the default language will be ')}${lang_selected}</div></div>
|
|
||||||
% endif
|
% endif
|
||||||
% if len(arr_i18n)==1:
|
</div>
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
$("#${name_form}_languages_form").find('.${name_form}_i18n_flag').hide();
|
|
||||||
$("#${name_form}_languages_form").find('.all_languages').show();
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
% endif
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
<!--<h1>${admin.title}</h1>-->
|
<!--<h1>${admin.title}</h1>-->
|
||||||
<p><a href="${add_get_parameters(admin.url, op_admin='1')}">${_('Add new item')}</a></p>
|
<p><a href="${add_get_parameters(admin.url, op_admin='1')}">${lang('common', 'add_item', 'Add new item')}</a></p>
|
||||||
${admin.list.show()|n}
|
${admin.list.show()|n}
|
||||||
|
|
|
||||||
|
|
@ -11,13 +11,13 @@
|
||||||
% if simplelist.yes_search:
|
% if simplelist.yes_search:
|
||||||
<div class="form">
|
<div class="form">
|
||||||
<form method="get" action="${simplelist.url}">
|
<form method="get" action="${simplelist.url}">
|
||||||
${_('Search')}: <input type="text" name="search_text" value="${simplelist.search_text|n}">
|
${lang('common','search', 'Search')}: <input type="text" name="search_text" value="${simplelist.search_text|n}">
|
||||||
<select name="search_field">
|
<select name="search_field">
|
||||||
% for field in simplelist.search_fields:
|
% for field in simplelist.search_fields:
|
||||||
<option value="${simplelist.model.fields[field].name}" ${select_field(field)}>${simplelist.model.fields[field].label}</option>
|
<option value="${simplelist.model.fields[field].name}" ${select_field(field)}>${simplelist.model.fields[field].label}</option>
|
||||||
% endfor
|
% endfor
|
||||||
</select>
|
</select>
|
||||||
<input type="submit" value="${_('Search')}" />
|
<input type="submit" value="${lang('common', 'search', 'Search')}" />
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
% endif
|
% endif
|
||||||
|
|
@ -130,6 +130,6 @@ size_td=round(100/(len(simplelist.fields_showed)+len(simplelist.arr_extra_option
|
||||||
% endif
|
% endif
|
||||||
<p>
|
<p>
|
||||||
% if pages!='':
|
% if pages!='':
|
||||||
${_('Pages')}: ${pages|n}
|
${lang('common', 'pages', 'Pages')}: ${pages|n}
|
||||||
% endif
|
% endif
|
||||||
</p>
|
</p>
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,6 @@
|
||||||
<!-- <input type="hidden" name="id" value="${item_id}">
|
<!-- <input type="hidden" name="id" value="${item_id}">
|
||||||
<input type="hidden" name="op_admin" value="${op_admin}">
|
<input type="hidden" name="op_admin" value="${op_admin}">
|
||||||
<input type="hidden" name="verified" value="${verified}">-->
|
<input type="hidden" name="verified" value="${verified}">-->
|
||||||
<input type="submit" value="${_('Are you sure for delete this item?')}" />
|
<input type="submit" value="${lang('common', 'delete_item_you_sure', 'Are you sure for delete this item?')}" />
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,3 @@
|
||||||
"""
|
|
||||||
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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from settings import config
|
from settings import config
|
||||||
except:
|
except:
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,10 @@ try:
|
||||||
|
|
||||||
admin_app=Blueprint('admin_app', __name__, static_folder='static')
|
admin_app=Blueprint('admin_app', __name__, static_folder='static')
|
||||||
|
|
||||||
|
|
||||||
env=env_theme(__file__)
|
env=env_theme(__file__)
|
||||||
|
|
||||||
t=PTemplate(env)
|
t=PTemplate(env)
|
||||||
|
|
||||||
wsgi_module=True
|
|
||||||
|
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,13 @@
|
||||||
from settings import config
|
from settings import config
|
||||||
from flask import g, url_for, session
|
from flask import g, url_for
|
||||||
from paramecio2.modules.admin.models.admin import UserAdmin
|
from paramecio2.modules.admin.models.admin import UserAdmin
|
||||||
from paramecio2.libraries.generate_admin_class import GenerateAdminClass
|
from paramecio2.libraries.generate_admin_class import GenerateAdminClass
|
||||||
from paramecio2.libraries.i18n import I18n, PGetText
|
from paramecio2.libraries.i18n import I18n
|
||||||
from paramecio2.libraries.db.coreforms import SelectForm
|
from paramecio2.libraries.db.coreforms import SelectForm
|
||||||
from paramecio2.libraries.db.coreforms import HiddenForm
|
from paramecio2.libraries.db.coreforms import HiddenForm
|
||||||
import copy
|
import copy
|
||||||
from paramecio2.modules.admin import admin_app, t as admin_t
|
from paramecio2.modules.admin import admin_app, t as admin_t
|
||||||
|
|
||||||
pgettext=PGetText(__file__+'/../')
|
|
||||||
|
|
||||||
_=pgettext.gettext
|
|
||||||
|
|
||||||
t=copy.copy(admin_t)
|
t=copy.copy(admin_t)
|
||||||
|
|
||||||
@admin_app.route('/admin/ausers/', methods=['GET', 'POST'])
|
@admin_app.route('/admin/ausers/', methods=['GET', 'POST'])
|
||||||
|
|
@ -31,47 +27,37 @@ def ausers():
|
||||||
|
|
||||||
user_admin.fields['dark_theme'].name_form=SelectForm
|
user_admin.fields['dark_theme'].name_form=SelectForm
|
||||||
|
|
||||||
user_admin.create_forms(['username', 'password', 'email', 'privileges', 'lang', 'dark_theme', 'disabled', 'double_auth', 'last_login', 'privileges'])
|
user_admin.create_forms(['username', 'password', 'email', 'privileges', 'lang', 'dark_theme', 'disabled', 'double_auth', 'last_login'])
|
||||||
|
|
||||||
user_admin.forms['privileges'].arr_select={0: _('Without privileges'), 1: _('Selected privileges'), 2: _('Administrator')}
|
user_admin.forms['privileges'].arr_select={0: I18n.lang('admin', 'without_privileges', 'Without privileges'), 1: I18n.lang('admin', 'selected_privileges', 'Selected privileges'), 2: I18n.lang('admin', 'administrator', 'Administrator')}
|
||||||
|
|
||||||
user_admin.forms['disabled'].arr_select={0: _('User enabled'), 1: _('User disabled')}
|
user_admin.forms['disabled'].arr_select={0: I18n.lang('admin', 'user_enabled', 'User enabled'), 1: I18n.lang('admin', 'user_disabled', 'User disabled')}
|
||||||
|
|
||||||
user_admin.forms['double_auth'].arr_select={0: _('No'), 1: _('Yes')}
|
user_admin.forms['double_auth'].arr_select={0: I18n.lang('admin', 'no', 'No'), 1: I18n.lang('admin', 'yes', 'Yes')}
|
||||||
|
|
||||||
user_admin.fields['password'].protected=False
|
user_admin.fields['password'].protected=False
|
||||||
|
|
||||||
user_admin.forms['dark_theme'].arr_select={0: _('Light theme'), 1: _('Dark theme')}
|
user_admin.forms['dark_theme'].arr_select={0: I18n.lang('admin', 'light_theme', 'Light theme'), 1: I18n.lang('admin', 'dark_theme', 'Dark theme')}
|
||||||
|
|
||||||
user_admin.check_user=False
|
user_admin.check_user=False
|
||||||
user_admin.check_email=False
|
user_admin.check_email=False
|
||||||
|
|
||||||
url=url_for('admin_app.ausers')
|
url=url_for('admin_app.ausers')
|
||||||
|
|
||||||
admin=GenerateAdminClass(user_admin, url)
|
admin=GenerateAdminClass(user_admin, url, t)
|
||||||
|
|
||||||
admin.list.fields_showed=['username']
|
admin.list.fields_showed=['username']
|
||||||
|
|
||||||
admin.list.search_fields=['username']
|
admin.list.search_fields=['username']
|
||||||
|
|
||||||
admin.arr_fields_edit=['username', 'password', 'repeat_password', 'email', 'lang', 'dark_theme', 'double_auth', 'disabled', 'last_login', 'privileges']
|
admin.arr_fields_edit=['username', 'password', 'repeat_password', 'email', 'lang', 'dark_theme', 'double_auth', 'disabled', 'last_login']
|
||||||
|
|
||||||
admin.post_update=update_lang
|
|
||||||
|
|
||||||
form_admin=admin.show()
|
form_admin=admin.show()
|
||||||
|
|
||||||
if type(form_admin).__name__=='str':
|
if type(form_admin).__name__=='str':
|
||||||
|
|
||||||
return t.load_template('content.phtml', title=_('Users edit'), contents=form_admin, path_module='admin_app.ausers')
|
return t.load_template('content.phtml', title=I18n.lang('admin', 'users_edit', 'Users edit'), contents=form_admin, path_module='admin_app.ausers')
|
||||||
else:
|
else:
|
||||||
|
|
||||||
return form_admin
|
return form_admin
|
||||||
|
|
||||||
|
|
||||||
def update_lang(admin, item_id):
|
|
||||||
|
|
||||||
arr_row=admin.model.select_a_row(item_id)
|
|
||||||
|
|
||||||
session['lang']=arr_row.get('lang', I18n.get_default_lang())
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
from flask import Blueprint, redirect, session, url_for, request, g, make_response, abort
|
from flask import Blueprint, redirect, session, url_for, request, g, make_response, abort
|
||||||
from settings import config
|
from settings import config
|
||||||
from paramecio2.libraries.i18n import I18n, PGetText
|
from paramecio2.libraries.i18n import I18n
|
||||||
from paramecio2.libraries.datetime import now, format_local_strtime, timestamp_to_datetime, obtain_timestamp
|
from paramecio2.libraries.datetime import now, format_local_strtime, timestamp_to_datetime, obtain_timestamp
|
||||||
from paramecio2.libraries.formsutils import show_form, generate_csrf, set_extra_forms_user, pass_values_to_form
|
from paramecio2.libraries.formsutils import show_form, generate_csrf, set_extra_forms_user, pass_values_to_form
|
||||||
from paramecio2.libraries.db.webmodel import WebModel
|
from paramecio2.libraries.db.webmodel import WebModel
|
||||||
|
|
@ -15,27 +15,6 @@ from os import path
|
||||||
from paramecio2.modules.admin import admin_app, t
|
from paramecio2.modules.admin import admin_app, t
|
||||||
from paramecio2.libraries.sendmail import SendMail
|
from paramecio2.libraries.sendmail import SendMail
|
||||||
from paramecio2.libraries.formsutils import check_csrf
|
from paramecio2.libraries.formsutils import check_csrf
|
||||||
from hmac import compare_digest as compare_hash
|
|
||||||
from paramecio2.modules.admin.libraries.admin_auth import admin_prepare, admin_finished, modules_access
|
|
||||||
try:
|
|
||||||
import ujson as json
|
|
||||||
except:
|
|
||||||
import json
|
|
||||||
|
|
||||||
try:
|
|
||||||
import crypt
|
|
||||||
crypt_pass=True
|
|
||||||
except:
|
|
||||||
crypt_pass=False
|
|
||||||
|
|
||||||
login_tries=5
|
|
||||||
|
|
||||||
if hasattr(config, 'login_tries'):
|
|
||||||
login_tries=config.login_tries
|
|
||||||
|
|
||||||
gtext=PGetText(__file__)
|
|
||||||
|
|
||||||
_=gtext.gettext
|
|
||||||
|
|
||||||
yes_recovery_login=False
|
yes_recovery_login=False
|
||||||
email_address='localhost'
|
email_address='localhost'
|
||||||
|
|
@ -47,9 +26,62 @@ if hasattr(config, 'email_address'):
|
||||||
email_address=config.email_address
|
email_address=config.email_address
|
||||||
|
|
||||||
|
|
||||||
admin_prepare=admin_app.before_request(admin_prepare)
|
#admin_app=Blueprint('admin_app', __name__, static_folder='static')
|
||||||
|
|
||||||
admin_finished=admin_app.after_request(admin_finished)
|
@admin_app.before_request
|
||||||
|
def admin_prepare():
|
||||||
|
|
||||||
|
g.connection=WebModel.connection()
|
||||||
|
|
||||||
|
if request.endpoint!='admin_app.login' and request.endpoint!='admin_app.signup' and request.endpoint!='admin_app.need_auth' and request.endpoint!='admin_app.auth_check':
|
||||||
|
|
||||||
|
if 'login_admin' not in session:
|
||||||
|
|
||||||
|
if 'remember_login_admin' in request.cookies:
|
||||||
|
|
||||||
|
with g.connection.query('select count(id) as count_id from useradmin where token_login=%s', [request.cookies['remember_login_admin']]) as cursor:
|
||||||
|
|
||||||
|
arr_count=cursor.fetchone()
|
||||||
|
|
||||||
|
if arr_count['count_id']==0:
|
||||||
|
|
||||||
|
url_redirect=config.domain_url+url_for('admin_app.login', _external=False)
|
||||||
|
|
||||||
|
return redirect(url_redirect)
|
||||||
|
else:
|
||||||
|
|
||||||
|
session['login_admin']=True
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
url_redirect=config.domain_url+url_for('admin_app.login', _external=False)
|
||||||
|
|
||||||
|
return redirect(url_redirect)
|
||||||
|
else:
|
||||||
|
|
||||||
|
#print(session['verify_auth'])
|
||||||
|
if request.endpoint!='admin_app.logout':
|
||||||
|
|
||||||
|
if not session.get('verify_auth', True):
|
||||||
|
|
||||||
|
url_redirect=config.domain_url+url_for('admin_app.need_auth', _external=False)
|
||||||
|
|
||||||
|
return redirect(url_redirect)
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
if request.method=='POST':
|
||||||
|
check_csrf()
|
||||||
|
"""
|
||||||
|
|
||||||
|
@admin_app.after_request
|
||||||
|
def admin_finished(response):
|
||||||
|
|
||||||
|
#print('pepe')
|
||||||
|
|
||||||
|
g.connection.close()
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
# Load modules from admin
|
# Load modules from admin
|
||||||
|
|
||||||
|
|
@ -64,24 +96,67 @@ for app in config.apps:
|
||||||
|
|
||||||
a=import_module(config_path)
|
a=import_module(config_path)
|
||||||
|
|
||||||
|
|
||||||
arr_modules_admin={}
|
arr_modules_admin={}
|
||||||
|
|
||||||
for app_load in config_admin:
|
for app_load in config_admin:
|
||||||
|
|
||||||
|
#print(app)
|
||||||
|
|
||||||
if len(app_load)==3:
|
if len(app_load)==3:
|
||||||
|
|
||||||
arr_modules_admin[app_load[2]+'/']=import_module(app_load[1])
|
arr_modules_admin[app_load[2]+'/']=import_module(app_load[1])
|
||||||
|
#arr_modules_admin[app_load[2]+'/'].admin=admin_app.route(arr_modules_admin[app_load[2]+'/'])(arr_modules_admin[app_load[2]+'/'].admin)
|
||||||
|
#print(app_load[1])
|
||||||
elif len(app_load)==4:
|
elif len(app_load)==4:
|
||||||
|
|
||||||
arr_modules_admin[app_load[2]+'/'+app_load[3]]=import_module(app_load[1])
|
arr_modules_admin[app_load[2]+'/'+app_load[3]]=import_module(app_load[1])
|
||||||
|
|
||||||
|
#print(app_load[1])
|
||||||
|
|
||||||
@admin_app.route('/admin/')
|
@admin_app.route('/admin/')
|
||||||
def admin():
|
def admin():
|
||||||
|
|
||||||
return t.load_template('home.phtml', title=_('Admin'))
|
return t.load_template('home.phtml', title=I18n.lang('admin', 'admin', 'Admin'))
|
||||||
|
|
||||||
|
"""
|
||||||
|
@admin_app.route('/admin/')
|
||||||
|
@admin_app.route('/admin/<module>', methods=['GET', 'POST'])
|
||||||
|
@admin_app.route('/admin/<module>/<submodule>', methods=['GET', 'POST'])
|
||||||
|
def admin(module='', submodule=''):
|
||||||
|
|
||||||
|
if module=='':
|
||||||
|
|
||||||
|
return t.load_template('home.phtml', title=I18n.lang('admin', 'paramecio_admin', 'Paramecio admin'))
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
path_module=module+'/'+submodule
|
||||||
|
|
||||||
|
if path_module in arr_modules_admin:
|
||||||
|
|
||||||
|
t_mod=copy.copy(t)
|
||||||
|
|
||||||
|
templates_path=path.dirname(arr_modules_admin[module+'/'+submodule].__file__).replace('/admin', '')+'/templates'
|
||||||
|
|
||||||
|
try:
|
||||||
|
index_value = t_mod.env.directories.index(templates_path)
|
||||||
|
except ValueError:
|
||||||
|
t_mod.env.directories.insert(0, templates_path)
|
||||||
|
|
||||||
|
content=arr_modules_admin[path_module].admin(t=t)
|
||||||
|
|
||||||
|
if type(content).__name__=='str':
|
||||||
|
|
||||||
|
return t.load_template('content.phtml', title=I18n.lang('admin', 'paramecio_admin', 'Paramecio admin'), contents=content, path_module=path_module)
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
return content
|
||||||
|
|
||||||
|
else:
|
||||||
|
abort(404)
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
@admin_app.route('/admin/logout/')
|
@admin_app.route('/admin/logout/')
|
||||||
def logout():
|
def logout():
|
||||||
|
|
@ -102,7 +177,7 @@ def logout():
|
||||||
@admin_app.route('/admin/login/', methods=['GET', 'POST'])
|
@admin_app.route('/admin/login/', methods=['GET', 'POST'])
|
||||||
def login():
|
def login():
|
||||||
|
|
||||||
new_crypt=False
|
#connection=WebModel.connection()
|
||||||
|
|
||||||
user_admin=UserAdmin(g.connection)
|
user_admin=UserAdmin(g.connection)
|
||||||
|
|
||||||
|
|
@ -129,25 +204,9 @@ def login():
|
||||||
|
|
||||||
arr_user=user_admin.set_conditions('WHERE username=%s', [username]).select_a_row_where()
|
arr_user=user_admin.set_conditions('WHERE username=%s', [username]).select_a_row_where()
|
||||||
|
|
||||||
if arr_user and not check_login_tries():
|
if arr_user:
|
||||||
|
|
||||||
# Layer compatibility with old crypt password
|
if user_admin.fields['password'].verify(password, arr_user['password']):
|
||||||
|
|
||||||
check_pass=user_admin.fields['password'].verify(password, arr_user['password'])
|
|
||||||
|
|
||||||
if not check_pass:
|
|
||||||
|
|
||||||
try:
|
|
||||||
check_pass=compare_hash(arr_user['password'], crypt.crypt(password, arr_user['password']))
|
|
||||||
new_crypt=True
|
|
||||||
except:
|
|
||||||
|
|
||||||
print('Warning: python developers deleting unix crypt module support, you cannot use sha512 passwords.')
|
|
||||||
|
|
||||||
check_pass=False
|
|
||||||
pass
|
|
||||||
|
|
||||||
if check_pass:
|
|
||||||
|
|
||||||
if not arr_user['disabled']:
|
if not arr_user['disabled']:
|
||||||
|
|
||||||
|
|
@ -172,15 +231,15 @@ def login():
|
||||||
|
|
||||||
timestamp=int(time())+315360000
|
timestamp=int(time())+315360000
|
||||||
|
|
||||||
user_admin.fields['token_login'].protected=False
|
resp.set_cookie('remember_login_admin', value=remember_key, max_age=315360000, expires=timestamp, path=config.application_root)
|
||||||
|
|
||||||
resp.set_cookie('remember_login_admin', value=json.dumps((arr_user['id'], remember_key)), max_age=315360000, expires=timestamp, path=config.application_root)
|
|
||||||
|
|
||||||
if arr_user['double_auth']:
|
if arr_user['double_auth']:
|
||||||
|
|
||||||
token_auth=create_key(8)
|
token_auth=create_key(8)
|
||||||
session['verify_auth']=False
|
session['verify_auth']=False
|
||||||
|
|
||||||
|
#user_admin.set_conditions('WHERE id=%s', [arr_user['id']]).update({'token_auth': token_auth})
|
||||||
|
|
||||||
user_admin.fields['token_auth'].protected=False
|
user_admin.fields['token_auth'].protected=False
|
||||||
|
|
||||||
arr_update['token_auth']=token_auth
|
arr_update['token_auth']=token_auth
|
||||||
|
|
@ -189,7 +248,9 @@ def login():
|
||||||
|
|
||||||
sendmail=SendMail(ssl=True)
|
sendmail=SendMail(ssl=True)
|
||||||
|
|
||||||
sendmail.send(config.portal_email, [arr_user['email']], _('Code for complete login'), _('We send to you a code for activate your account using double authentication:')+"\n"+token_auth, content_type='plain', attachments=[])
|
# def send(self, from_address, to_address: list, subject, message, content_type='plain', attachments=[]):
|
||||||
|
|
||||||
|
sendmail.send(config.portal_email, [arr_user['email']], I18n.lang('admin', 'code_for_complete_login', 'Code for complete login'), I18n.lang('admin', 'code_for_complete_login_explain', 'We send to you a code for activate your account using double authentication:')+"\n"+token_auth, content_type='plain', attachments=[])
|
||||||
|
|
||||||
if arr_user['dark_theme']:
|
if arr_user['dark_theme']:
|
||||||
session['theme']='1'
|
session['theme']='1'
|
||||||
|
|
@ -198,17 +259,8 @@ def login():
|
||||||
|
|
||||||
arr_update['last_login']=now()
|
arr_update['last_login']=now()
|
||||||
|
|
||||||
session['lang']=arr_user.get('lang', I18n.default_lang)
|
|
||||||
|
|
||||||
if len(arr_update)>0:
|
if len(arr_update)>0:
|
||||||
|
|
||||||
if new_crypt:
|
|
||||||
print('Changing password for %s to argon2' % arr_user['username'])
|
|
||||||
|
|
||||||
user_admin.fields['password'].protected=False
|
|
||||||
|
|
||||||
arr_update['password']=password
|
|
||||||
|
|
||||||
user_admin.set_conditions('WHERE id=%s', [arr_user['id']]).update(arr_update)
|
user_admin.set_conditions('WHERE id=%s', [arr_user['id']]).update(arr_update)
|
||||||
|
|
||||||
return resp
|
return resp
|
||||||
|
|
@ -231,6 +283,8 @@ def login():
|
||||||
|
|
||||||
return {'error': 1, 'you_cannot_login': you_cannot_login}
|
return {'error': 1, 'you_cannot_login': you_cannot_login}
|
||||||
|
|
||||||
|
#if
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
forms=show_form(post, user_admin.forms, t, yes_error=False)
|
forms=show_form(post, user_admin.forms, t, yes_error=False)
|
||||||
|
|
@ -348,19 +402,21 @@ def auth_check():
|
||||||
@admin_app.route('/admin/change_theme/')
|
@admin_app.route('/admin/change_theme/')
|
||||||
def change_theme():
|
def change_theme():
|
||||||
|
|
||||||
db=g.connection
|
|
||||||
|
|
||||||
theme_selected=str(request.args.get('theme', '0'))
|
theme_selected=str(request.args.get('theme', '0'))
|
||||||
|
|
||||||
session['theme']=theme_selected
|
session['theme']=theme_selected
|
||||||
|
|
||||||
if not db.query('update useradmin set dark_theme=%s WHERE id=%s', [session['theme'], session['user_id']]):
|
|
||||||
error=1
|
|
||||||
|
|
||||||
error=0
|
error=0
|
||||||
|
|
||||||
return {'error': error}
|
return {'error': error}
|
||||||
|
|
||||||
|
"""
|
||||||
|
@admin_app.route('/admin/recovery_password/')
|
||||||
|
def recovery_password():
|
||||||
|
|
||||||
|
return ""
|
||||||
|
"""
|
||||||
|
|
||||||
def check_login_tries():
|
def check_login_tries():
|
||||||
|
|
||||||
logintries=LoginTries(g.connection)
|
logintries=LoginTries(g.connection)
|
||||||
|
|
@ -385,7 +441,7 @@ def check_login_tries():
|
||||||
|
|
||||||
if arr_try:
|
if arr_try:
|
||||||
|
|
||||||
if arr_try['num_tries']<login_tries:
|
if arr_try['num_tries']<5:
|
||||||
|
|
||||||
logintries.query('update logintries set num_tries=num_tries+1, last_login=%s WHERE ip=%s', [date_now, ip])
|
logintries.query('update logintries set num_tries=num_tries+1, last_login=%s WHERE ip=%s', [date_now, ip])
|
||||||
|
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -1,132 +0,0 @@
|
||||||
# SOME DESCRIPTIVE TITLE.
|
|
||||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
|
||||||
# This file is distributed under the same license as the PACKAGE package.
|
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
|
||||||
#
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: \n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2023-12-19 15:30+0100\n"
|
|
||||||
"PO-Revision-Date: 2023-12-19 15:32+0100\n"
|
|
||||||
"Last-Translator: \n"
|
|
||||||
"Language-Team: \n"
|
|
||||||
"Language: es\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"X-Generator: Poedit 3.4.1\n"
|
|
||||||
|
|
||||||
#: admin/modules.py:51
|
|
||||||
msgid "Error: git url wrong"
|
|
||||||
msgstr "Error: Url git equivocada"
|
|
||||||
|
|
||||||
#: admin/modules.py:58
|
|
||||||
msgid "Error: cannot install the module, view the error in wsgi server log"
|
|
||||||
msgstr "Error: no puedo instalar el módulo, ver el error en el servidor wsgi"
|
|
||||||
|
|
||||||
#: admin/ausers.py:36
|
|
||||||
msgid "Without privileges"
|
|
||||||
msgstr "Sin privilegios"
|
|
||||||
|
|
||||||
#: admin/ausers.py:36
|
|
||||||
msgid "Selected privileges"
|
|
||||||
msgstr "Privilegios seleccionados"
|
|
||||||
|
|
||||||
#: admin/ausers.py:36
|
|
||||||
msgid "Administrator"
|
|
||||||
msgstr "Administrador"
|
|
||||||
|
|
||||||
#: admin/ausers.py:38
|
|
||||||
msgid "User enabled"
|
|
||||||
msgstr "Usuario activado"
|
|
||||||
|
|
||||||
#: admin/ausers.py:38
|
|
||||||
msgid "User disabled"
|
|
||||||
msgstr "Usuario desactivado"
|
|
||||||
|
|
||||||
#: admin/ausers.py:40
|
|
||||||
msgid "No"
|
|
||||||
msgstr "No"
|
|
||||||
|
|
||||||
#: admin/ausers.py:40
|
|
||||||
msgid "Yes"
|
|
||||||
msgstr "Sí"
|
|
||||||
|
|
||||||
#: admin/ausers.py:44
|
|
||||||
msgid "Light theme"
|
|
||||||
msgstr "Tema claro"
|
|
||||||
|
|
||||||
#: admin/ausers.py:44 templates/dashboard.phtml:110
|
|
||||||
msgid "Dark theme"
|
|
||||||
msgstr "Tema oscuro"
|
|
||||||
|
|
||||||
#: admin/ausers.py:63 settings/config_admin.py:11
|
|
||||||
msgid "Users edit"
|
|
||||||
msgstr "Editar usuarios"
|
|
||||||
|
|
||||||
#: app.py:126
|
|
||||||
msgid "Admin"
|
|
||||||
msgstr "Admin"
|
|
||||||
|
|
||||||
#: app.py:260
|
|
||||||
msgid "Code for complete login"
|
|
||||||
msgstr "Código para completar login"
|
|
||||||
|
|
||||||
#: app.py:260
|
|
||||||
msgid ""
|
|
||||||
"We send to you a code for activate your account using double authentication:"
|
|
||||||
msgstr ""
|
|
||||||
"Te enviaremos un código para activr tu cuenta usando doble autenticación"
|
|
||||||
|
|
||||||
#: settings/config_admin.py:9
|
|
||||||
msgid "Users"
|
|
||||||
msgstr "Usuarios"
|
|
||||||
|
|
||||||
#: templates/modules.phtml:3
|
|
||||||
msgid "Add new module"
|
|
||||||
msgstr "Añadir nuevo módulo"
|
|
||||||
|
|
||||||
#: templates/home.phtml:4 templates/users.phtml:4
|
|
||||||
msgid "Welcome to Paramecio Admin"
|
|
||||||
msgstr "Bienvenido a Paramecio Admin"
|
|
||||||
|
|
||||||
#: templates/home.phtml:7 templates/users.phtml:7
|
|
||||||
msgid "From here you can admin your site"
|
|
||||||
msgstr "Desde aquí puedes administrar tu sitio"
|
|
||||||
|
|
||||||
#: templates/login.phtml:4 templates/login.phtml:99 templates/need_auth.phtml:2
|
|
||||||
#: templates/need_auth.phtml:6
|
|
||||||
msgid "Paramecio Login"
|
|
||||||
msgstr "Paramecio login"
|
|
||||||
|
|
||||||
#: templates/login.phtml:103
|
|
||||||
msgid "Remember login?"
|
|
||||||
msgstr "¿Recordar login?"
|
|
||||||
|
|
||||||
#: templates/login.phtml:110
|
|
||||||
msgid "Recovery password?"
|
|
||||||
msgstr "¿Recuperar contraseña?"
|
|
||||||
|
|
||||||
#: templates/login.phtml:112
|
|
||||||
msgid "Remember that only have 3 attempts"
|
|
||||||
msgstr "Recuera que sólo tienes 3 intentos"
|
|
||||||
|
|
||||||
#: templates/register.phtml:51 templates/register.phtml:55
|
|
||||||
msgid "Paramecio Sign up"
|
|
||||||
msgstr "Paramecio Registro"
|
|
||||||
|
|
||||||
#: templates/dashboard.phtml:66
|
|
||||||
msgid "Applications"
|
|
||||||
msgstr "Aplicaciones"
|
|
||||||
|
|
||||||
#: templates/need_auth.phtml:9
|
|
||||||
msgid ""
|
|
||||||
"Check your email for get instructions for complete login with double auth or"
|
|
||||||
msgstr ""
|
|
||||||
"Mira tu email para obtener instrucciones para completar el login con doble "
|
|
||||||
"autenticación o"
|
|
||||||
|
|
||||||
#: templates/need_auth.phtml:10
|
|
||||||
msgid "Code"
|
|
||||||
msgstr "Código"
|
|
||||||
|
|
@ -1,89 +0,0 @@
|
||||||
from flask import g, request, redirect, session, url_for
|
|
||||||
from paramecio2.libraries.db.webmodel import WebModel
|
|
||||||
from settings import config
|
|
||||||
from paramecio2.libraries.db.extrafields.passwordfield import PasswordField
|
|
||||||
from paramecio2.libraries.i18n import I18n, PGetText
|
|
||||||
|
|
||||||
try:
|
|
||||||
import ujson as json
|
|
||||||
except:
|
|
||||||
import json
|
|
||||||
|
|
||||||
modules_access=[]
|
|
||||||
|
|
||||||
def admin_prepare():
|
|
||||||
|
|
||||||
g.connection=WebModel.connection()
|
|
||||||
|
|
||||||
if request.endpoint!='admin_app.login' and request.endpoint!='admin_app.signup' and request.endpoint!='admin_app.need_auth' and request.endpoint!='admin_app.auth_check':
|
|
||||||
|
|
||||||
if 'login_admin' not in session:
|
|
||||||
|
|
||||||
if 'remember_login_admin' in request.cookies:
|
|
||||||
|
|
||||||
try:
|
|
||||||
|
|
||||||
arr_cookie=json.loads(request.cookies['remember_login_admin'])
|
|
||||||
|
|
||||||
except:
|
|
||||||
|
|
||||||
arr_cookie=(0, '')
|
|
||||||
|
|
||||||
#print(arr_cookie)
|
|
||||||
#with g.connection.query('select count(id) as count_id from useradmin where token_login=%s', [request.cookies['remember_login_admin']]) as cursor:
|
|
||||||
with g.connection.query('select id, token_login, dark_theme from useradmin where id=%s', [arr_cookie[0]]) as cursor:
|
|
||||||
|
|
||||||
arr_user=cursor.fetchone()
|
|
||||||
|
|
||||||
if arr_user:
|
|
||||||
|
|
||||||
passfield=PasswordField('token_login')
|
|
||||||
|
|
||||||
if passfield.verify(arr_cookie[1], arr_user['token_login']):
|
|
||||||
|
|
||||||
session['login_admin']=True
|
|
||||||
session['user_id']=arr_user['id']
|
|
||||||
|
|
||||||
if arr_user['dark_theme']:
|
|
||||||
session['theme']='1'
|
|
||||||
else:
|
|
||||||
session['theme']='0'
|
|
||||||
|
|
||||||
session['lang']=arr_user.get('lang', I18n.default_lang)
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
session.clear()
|
|
||||||
|
|
||||||
url_redirect=config.domain_url+url_for('admin_app.login', _external=False)
|
|
||||||
|
|
||||||
return redirect(url_redirect)
|
|
||||||
else:
|
|
||||||
|
|
||||||
session.clear()
|
|
||||||
|
|
||||||
url_redirect=config.domain_url+url_for('admin_app.login', _external=False)
|
|
||||||
|
|
||||||
return redirect(url_redirect)
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
url_redirect=config.domain_url+url_for('admin_app.login', _external=False)
|
|
||||||
|
|
||||||
return redirect(url_redirect)
|
|
||||||
else:
|
|
||||||
|
|
||||||
|
|
||||||
if request.endpoint!='admin_app.logout':
|
|
||||||
|
|
||||||
if not session.get('verify_auth', True):
|
|
||||||
|
|
||||||
url_redirect=config.domain_url+url_for('admin_app.need_auth', _external=False)
|
|
||||||
|
|
||||||
return redirect(url_redirect)
|
|
||||||
|
|
||||||
def admin_finished(response):
|
|
||||||
|
|
||||||
g.connection.close()
|
|
||||||
|
|
||||||
return response
|
|
||||||
|
|
@ -1,75 +0,0 @@
|
||||||
from paramecio2.libraries.i18n import I18n, PGetText
|
|
||||||
from paramecio2.libraries.mtemplates import env_theme, PTemplate
|
|
||||||
from paramecio2.modules.admin.models.admin import UserAdmin, LoginTries
|
|
||||||
from paramecio2.libraries.db.webmodel import WebModel
|
|
||||||
from paramecio2.libraries.db import simplequery
|
|
||||||
from settings import config
|
|
||||||
from paramecio2.libraries.datetime import now, format_local_strtime, timestamp_to_datetime, obtain_timestamp
|
|
||||||
from paramecio2.libraries.keyutils import create_key_encrypt, create_key
|
|
||||||
from time import time
|
|
||||||
#from paramecio2.wsgiapp import app
|
|
||||||
#from paramecio2.modules.admin2 import admin_app
|
|
||||||
#from bottle import request, redirect, Bottle, response
|
|
||||||
from flask import request, redirect
|
|
||||||
#from paramecio2.modules.admin.libraries.loginplugin import check_login
|
|
||||||
#from paramecio2.libraries.sessionplugin import SessionPlugin
|
|
||||||
#from paramecio2.libraries.httputils import GetPostFiles
|
|
||||||
from paramecio2.libraries.formsutils import check_form, csrf_token
|
|
||||||
from paramecio2.libraries.db.coreforms import PasswordForm
|
|
||||||
from paramecio2.libraries.sendmail import SendMail
|
|
||||||
#from paramecio2.modules.admin.libraries.config import modules_admin
|
|
||||||
|
|
||||||
login_tries=5
|
|
||||||
|
|
||||||
if hasattr(config, 'login_tries'):
|
|
||||||
login_tries=config.login_tries
|
|
||||||
|
|
||||||
seconds_login=300
|
|
||||||
|
|
||||||
if hasattr(config, 'seconds_login'):
|
|
||||||
seconds_login=config.seconds_login
|
|
||||||
|
|
||||||
|
|
||||||
def check_login_tries(request, db):
|
|
||||||
|
|
||||||
logintries=LoginTries(db)
|
|
||||||
|
|
||||||
logintries.safe_query()
|
|
||||||
|
|
||||||
ip=request.environ.get('HTTP_X_FORWARDED_FOR') or request.environ.get('REMOTE_ADDR')
|
|
||||||
|
|
||||||
"""
|
|
||||||
if 'x-real-ip' in request.headers:
|
|
||||||
ip=request.headers['x-real-ip']
|
|
||||||
elif 'x-forwarded-for' in request.headers:
|
|
||||||
ip=request.headers['x-forwarded-for']
|
|
||||||
else:
|
|
||||||
ip=request.client.host
|
|
||||||
"""
|
|
||||||
|
|
||||||
you_cannot_login=0
|
|
||||||
|
|
||||||
now_str=now()
|
|
||||||
date_now=format_local_strtime('YYYY-MM-DD HH:mm:ss', now_str)
|
|
||||||
|
|
||||||
date_check=format_local_strtime('YYYY-MM-DD HH:mm:ss', timestamp_to_datetime(obtain_timestamp(now_str)-seconds_login))
|
|
||||||
|
|
||||||
logintries.query('delete from logintries where last_login<%s', [date_check])
|
|
||||||
|
|
||||||
arr_try=logintries.set_conditions('WHERE ip=%s', [ip]).select_a_row_where()
|
|
||||||
|
|
||||||
if arr_try:
|
|
||||||
|
|
||||||
if arr_try['num_tries']<login_tries:
|
|
||||||
|
|
||||||
logintries.query('update logintries set num_tries=num_tries+1, last_login=%s WHERE ip=%s', [date_now, ip])
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
you_cannot_login=1
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
logintries.query('insert into logintries (`ip`, `num_tries`, `last_login`) VALUES (%s, %s, %s)', [ip, 1, date_now])
|
|
||||||
|
|
||||||
return you_cannot_login
|
|
||||||
|
|
@ -11,7 +11,7 @@ body
|
||||||
|
|
||||||
margin:0px;
|
margin:0px;
|
||||||
background-color:#f4f6f9;
|
background-color:#f4f6f9;
|
||||||
font-family: sans, sans-serif, serif;
|
font-family: "Roboto", sans, sans-serif, serif;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
/*-webkit-transition: all 0.5s ease-in-out;
|
/*-webkit-transition: all 0.5s ease-in-out;
|
||||||
transition: all 0.5s ease-in-out;
|
transition: all 0.5s ease-in-out;
|
||||||
|
|
@ -409,13 +409,6 @@ p {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark .form textarea {
|
|
||||||
|
|
||||||
background-color: #1e202a;
|
|
||||||
color: #fbfbfb;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.form label {
|
.form label {
|
||||||
display: block;
|
display: block;
|
||||||
/*width: 150px;*/
|
/*width: 150px;*/
|
||||||
|
|
@ -1002,7 +995,7 @@ a.form_button_tab:hover
|
||||||
|
|
||||||
#layer_loading {
|
#layer_loading {
|
||||||
|
|
||||||
z-index:99999;
|
z-index:50000;
|
||||||
/*background-color:rgba(0,0,0,0.4);*/
|
/*background-color:rgba(0,0,0,0.4);*/
|
||||||
/*opacity:0.5;*/
|
/*opacity:0.5;*/
|
||||||
position:absolute;
|
position:absolute;
|
||||||
|
|
@ -1036,7 +1029,6 @@ a.form_button_tab:hover
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
/* border: solid #fff 1px;*/
|
/* border: solid #fff 1px;*/
|
||||||
float:left;
|
float:left;
|
||||||
overflow:hidden;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1046,7 +1038,6 @@ a.form_button_tab:hover
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
/* border: solid #fff 1px;*/
|
/* border: solid #fff 1px;*/
|
||||||
float:left;
|
float:left;
|
||||||
overflow:hidden;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1057,7 +1048,6 @@ a.form_button_tab:hover
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
/*border: solid #f00 1px;*/
|
/*border: solid #f00 1px;*/
|
||||||
float:left;
|
float:left;
|
||||||
overflow:hidden;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1067,7 +1057,6 @@ a.form_button_tab:hover
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
/*border: solid #f00 1px;*/
|
/*border: solid #f00 1px;*/
|
||||||
float:left;
|
float:left;
|
||||||
overflow:hidden;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ body {
|
||||||
|
|
||||||
margin:0px;
|
margin:0px;
|
||||||
background: #fbfbfb;
|
background: #fbfbfb;
|
||||||
font-family: sans , sans-serif;
|
font-family: 'Open Sans', sans-serif;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit 353a80d8437aaf449ecdd7e459c1fcf7575f41bc
|
|
||||||
|
|
@ -82,7 +82,7 @@ class UserAdmin(UserModel):
|
||||||
|
|
||||||
self.register(corefields.CharField('token_recovery'))
|
self.register(corefields.CharField('token_recovery'))
|
||||||
|
|
||||||
self.register(PasswordField('token_login'))
|
self.register(corefields.CharField('token_login'))
|
||||||
|
|
||||||
self.register(PasswordField('token_auth'))
|
self.register(PasswordField('token_auth'))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,8 @@
|
||||||
from paramecio2.libraries.config_admin import config_admin
|
from paramecio2.libraries.config_admin import config_admin
|
||||||
from paramecio2.libraries.i18n import I18n, PGetText
|
from paramecio2.libraries.i18n import I18n
|
||||||
|
|
||||||
#modules_admin=[[I18n.lang('admin', 'users_admin', 'User\'s Admin'), 'paramecio.modules.admin.admin.ausers', 'ausers']]
|
#modules_admin=[[I18n.lang('admin', 'users_admin', 'User\'s Admin'), 'paramecio.modules.admin.admin.ausers', 'ausers']]
|
||||||
|
|
||||||
pgettext=PGetText(__file__+'/../')
|
config_admin.append([I18n.lang('admin', 'users', 'Users')])
|
||||||
_=pgettext.gettext
|
|
||||||
|
|
||||||
def users_text():
|
config_admin.append([I18n.lang('admin', 'users_edit', 'Users edit'), 'paramecio2.modules.admin.admin.ausers', 'admin_app.ausers', 'fa-user'])
|
||||||
|
|
||||||
return _('Backend Users')
|
|
||||||
|
|
||||||
def users_edit():
|
|
||||||
|
|
||||||
return _('Backend users edit')
|
|
||||||
|
|
||||||
config_admin.append([users_text])
|
|
||||||
|
|
||||||
config_admin.append([users_edit, 'paramecio2.modules.admin.admin.ausers', 'admin_app.ausers', '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640" width="24" style="fill: currentColor;display: inline-block;vertical-align: -.130em;position:relative;left:-6px;top:2px;"><!--!Font Awesome Free v7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M320 312C386.3 312 440 258.3 440 192C440 125.7 386.3 72 320 72C253.7 72 200 125.7 200 192C200 258.3 253.7 312 320 312zM290.3 368C191.8 368 112 447.8 112 546.3C112 562.7 125.3 576 141.7 576L498.3 576C514.7 576 528 562.7 528 546.3C528 447.8 448.2 368 349.7 368L290.3 368z"/></svg>'])
|
|
||||||
|
|
||||||
#config_admin.append([I18n.lang('admin', 'modules', 'Modules')])
|
|
||||||
|
|
||||||
#config_admin.append([I18n.lang('admin', 'edit_module', 'Edit modules'), 'paramecio2.modules.admin.admin.modules', 'admin_app.amodules', 'fa-dropbox'])
|
|
||||||
|
|
|
||||||
|
|
@ -17,11 +17,11 @@ if session.get('theme', '0')=='1':
|
||||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
|
||||||
<title>${title}</title>
|
<title>${title}</title>
|
||||||
<link href="${make_media_url('css/font-awesome.min.css', 'admin')}" rel="stylesheet" />
|
|
||||||
<link href="${make_media_url('css/admin.css', 'admin')}" rel="stylesheet" />
|
<link href="${make_media_url('css/admin.css', 'admin')}" rel="stylesheet" />
|
||||||
|
<link href="${make_media_url('css/font-awesome.min.css', 'admin')}" rel="stylesheet" />
|
||||||
<link href="${make_media_url('css/responsive-nav.css', 'admin')}" rel="stylesheet" />
|
<link href="${make_media_url('css/responsive-nav.css', 'admin')}" rel="stylesheet" />
|
||||||
<link href="${make_media_url('css/tooltipster.bundle.min.css', 'admin')}" rel="stylesheet" />
|
<link href="${make_media_url('css/tooltipster.bundle.min.css', 'admin')}" rel="stylesheet" />
|
||||||
<!--<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet"> -->
|
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
|
||||||
<%block name="extra_css">
|
<%block name="extra_css">
|
||||||
</%block>
|
</%block>
|
||||||
<script language="Javascript" src="${make_media_url('js/jquery.min.js', 'admin')}"></script>
|
<script language="Javascript" src="${make_media_url('js/jquery.min.js', 'admin')}"></script>
|
||||||
|
|
@ -34,11 +34,11 @@ ${load_js()|n}
|
||||||
</%block>
|
</%block>
|
||||||
</head>
|
</head>
|
||||||
<body class="${dark_css}">
|
<body class="${dark_css}">
|
||||||
<div id="layer_loading"><div id="container_loading"><div class="lds-dual-ring"></div></div></div>
|
<div id="layer_loading" style="display:none;"><div id="container_loading"><div class="lds-dual-ring"></div></div></div>
|
||||||
<div id="languages_general">
|
<div id="languages_general">
|
||||||
</div>
|
</div>
|
||||||
<div id="logout">
|
<div id="logout">
|
||||||
<%block name="logout"><a href="${url_for('admin_app.logout')}"><i class="fa fa-power-off" aria-hidden="true"></i> Logout</a></%block>
|
<%block name="logout"><a href="${url_for('.logout')}"><i class="fa fa-power-off" aria-hidden="true"></i> Logout</a></%block>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="center_body">
|
<div id="center_body">
|
||||||
|
|
@ -63,9 +63,7 @@ ${load_js()|n}
|
||||||
|
|
||||||
<nav id="menu" class="nav-collapse">
|
<nav id="menu" class="nav-collapse">
|
||||||
<ul>
|
<ul>
|
||||||
<li class="menu_title"><%block name="applications"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640" width="22" style="fill: currentColor;display: inline-block;vertical-align: -.130em;position:relative;left:-3px;top:2px;">
|
<li class="menu_title"><%block name="applications"><i class="fa fa-gear" aria-hidden="true"></i>${lang('admin', 'applications', 'Applications')}</li></%block>
|
||||||
<!--!Font Awesome Free v7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
|
|
||||||
<path d="M259.1 73.5C262.1 58.7 275.2 48 290.4 48L350.2 48C365.4 48 378.5 58.7 381.5 73.5L396 143.5C410.1 149.5 423.3 157.2 435.3 166.3L503.1 143.8C517.5 139 533.3 145 540.9 158.2L570.8 210C578.4 223.2 575.7 239.8 564.3 249.9L511 297.3C511.9 304.7 512.3 312.3 512.3 320C512.3 327.7 511.8 335.3 511 342.7L564.4 390.2C575.8 400.3 578.4 417 570.9 430.1L541 481.9C533.4 495 517.6 501.1 503.2 496.3L435.4 473.8C423.3 482.9 410.1 490.5 396.1 496.6L381.7 566.5C378.6 581.4 365.5 592 350.4 592L290.6 592C275.4 592 262.3 581.3 259.3 566.5L244.9 496.6C230.8 490.6 217.7 482.9 205.6 473.8L137.5 496.3C123.1 501.1 107.3 495.1 99.7 481.9L69.8 430.1C62.2 416.9 64.9 400.3 76.3 390.2L129.7 342.7C128.8 335.3 128.4 327.7 128.4 320C128.4 312.3 128.9 304.7 129.7 297.3L76.3 249.8C64.9 239.7 62.3 223 69.8 209.9L99.7 158.1C107.3 144.9 123.1 138.9 137.5 143.7L205.3 166.2C217.4 157.1 230.6 149.5 244.6 143.4L259.1 73.5zM320.3 400C364.5 399.8 400.2 363.9 400 319.7C399.8 275.5 363.9 239.8 319.7 240C275.5 240.2 239.8 276.1 240 320.3C240.2 364.5 276.1 400.2 320.3 400z"/></svg>${_('Applications')}</li></%block>
|
|
||||||
<%block name="menu_list">
|
<%block name="menu_list">
|
||||||
<%
|
<%
|
||||||
|
|
||||||
|
|
@ -77,7 +75,6 @@ ${load_js()|n}
|
||||||
<%
|
<%
|
||||||
|
|
||||||
class_selected=''
|
class_selected=''
|
||||||
link_text=''
|
|
||||||
|
|
||||||
%>
|
%>
|
||||||
|
|
||||||
|
|
@ -92,33 +89,13 @@ ${load_js()|n}
|
||||||
if len(admin)>3:
|
if len(admin)>3:
|
||||||
icon_module=admin[3]
|
icon_module=admin[3]
|
||||||
|
|
||||||
if type(admin[0]).__name__=='function':
|
|
||||||
link_text=admin[0]()
|
|
||||||
else:
|
|
||||||
link_text=admin[0]
|
|
||||||
|
|
||||||
%>
|
%>
|
||||||
|
|
||||||
|
<li><a href="${url_for(admin[2])}" class="${class_selected}"> <i class="fa ${icon_module}" aria-hidden="true"></i>${admin[0]}</a></li>
|
||||||
<li><a href="${url_for(admin[2])}" class="${class_selected}">
|
|
||||||
% if icon_module.startswith('fa-'):
|
|
||||||
<i class="fa ${icon_module}" aria-hidden="true"></i>
|
|
||||||
%else:
|
|
||||||
${icon_module|n}
|
|
||||||
% endif
|
|
||||||
${link_text}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
% elif len(admin)==1:
|
% elif len(admin)==1:
|
||||||
<%
|
|
||||||
if type(admin[0]).__name__=='function':
|
|
||||||
link_text=admin[0]()
|
|
||||||
else:
|
|
||||||
link_text=admin[0]
|
|
||||||
%>
|
|
||||||
|
|
||||||
<li><div class="father_admin">${link_text}</div></li>
|
<li><div class="father_admin">${admin[0]}</div></li>
|
||||||
|
|
||||||
% endif
|
% endif
|
||||||
|
|
||||||
|
|
@ -130,7 +107,7 @@ ${load_js()|n}
|
||||||
<h1>${title}</h1>
|
<h1>${title}</h1>
|
||||||
<div class="switch-btn">
|
<div class="switch-btn">
|
||||||
<div class="switch-text">
|
<div class="switch-text">
|
||||||
${_('Dark theme')}
|
Dark Mode
|
||||||
</div>
|
</div>
|
||||||
<div class="switch-slider">
|
<div class="switch-slider">
|
||||||
<label class="switch">
|
<label class="switch">
|
||||||
|
|
@ -219,12 +196,6 @@ ${load_js()|n}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$(document).ready(function () {
|
|
||||||
|
|
||||||
$('#layer_loading').hide();
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<%block name="jscript_block">
|
<%block name="jscript_block">
|
||||||
</%block>
|
</%block>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
<%inherit file="dashboard.phtml"/>
|
<%inherit file="dashboard.phtml"/>
|
||||||
<%block name="content">
|
<%block name="content">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
${_('Welcome to Paramecio Admin')}
|
Welcome to Paramecio Admin
|
||||||
</div>
|
</div>
|
||||||
<div class="cont">
|
<div class="cont">
|
||||||
${_('From here you can admin your site')}
|
From here you can admin your site
|
||||||
</div>
|
</div>
|
||||||
</%block>
|
</%block>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
<%inherit file="home.html"/>
|
<%inherit file="home.html"/>
|
||||||
<%block name="content">
|
<%block name="content">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
${_('Welcome to Admin dashboard')}
|
${lang('admin', 'welcome_to_admin_dashboard', 'Welcome to Admin dashboard')}
|
||||||
</div>
|
</div>
|
||||||
<div class="cont">
|
<div class="cont">
|
||||||
${_('From here you can configure your site')}.
|
${lang('admin', 'from_here_you_can_configure_your_site', 'From here you can configure your site')}.
|
||||||
</div>
|
</div>
|
||||||
</%block>
|
</%block>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title><%block name="title">${_('Paramecio Login')}</%block></title>
|
<title><%block name="title">${lang('admin', 'login', 'Paramecio Login')}</%block></title>
|
||||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||||
<!--<link href='https://fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css'>-->
|
<link href='https://fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css'>
|
||||||
<link href="${make_media_url('css/login.css', 'admin')}" rel='stylesheet' type='text/css'>
|
<link href="${make_media_url('css/login.css', 'admin')}" rel='stylesheet' type='text/css'>
|
||||||
<link href="${make_media_url('css/font-awesome.min.css', 'admin')}" rel='stylesheet' type='text/css'>
|
<link href="${make_media_url('css/font-awesome.min.css', 'admin')}" rel='stylesheet' type='text/css'>
|
||||||
<%block name="extra_css">
|
<%block name="extra_css">
|
||||||
|
|
@ -58,25 +58,25 @@
|
||||||
|
|
||||||
if(data.hasOwnProperty('disable')) {
|
if(data.hasOwnProperty('disable')) {
|
||||||
|
|
||||||
$('#username_error').html("${_('Error, your user is disabled, you need support of web administration')}");
|
$('#username_error').html("${lang('common', 'error_disabled', 'Error, your user is disabled, you need support of web administration')}");
|
||||||
|
|
||||||
} if(data.hasOwnProperty('you_cannot_login')) {
|
} if(data.hasOwnProperty('you_cannot_login')) {
|
||||||
|
|
||||||
if(data.you_cannot_login) {
|
if(data.you_cannot_login) {
|
||||||
|
|
||||||
$('#username_error').html("${_('Error, excessive tries, wait some minutes for login again')}");
|
$('#username_error').html("${lang('common', 'error_tries_disabled', 'Error, excessive tries, wait some minutes for login again')}");
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
$('#username_error').html("${_('Error, wrong username or password')}");
|
$('#username_error').html("${lang('common', 'error_login', 'Error, wrong username or password')}");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
$('#username_error').html("${_('Error, wrong username or password')}");
|
$('#username_error').html("${lang('common', 'error_login', 'Error, wrong username or password')}");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -96,21 +96,20 @@
|
||||||
<%block name="content">
|
<%block name="content">
|
||||||
<form id="login">
|
<form id="login">
|
||||||
<div id="title">
|
<div id="title">
|
||||||
${_('Paramecio Login')}
|
${lang('admin', 'login', 'Paramecio Login')}
|
||||||
</div>
|
</div>
|
||||||
${forms|n}
|
${forms|n}
|
||||||
${csrf_token()|n}
|
|
||||||
<div class="form">
|
<div class="form">
|
||||||
${_('Remember login?')} <input type="checkbox" id="remember_login" name="remember_login" value="1">
|
${lang('admin', 'remember_login', 'Remember login?')} <input type="checkbox" id="remember_login" name="remember_login" value="1">
|
||||||
</div>
|
</div>
|
||||||
<div id="submit_block">
|
<div id="submit_block">
|
||||||
<input type="submit" value="${_('Login')}" class="submit" id="login_submit"/>
|
<input type="submit" value="${lang('common', 'login', 'Login')}" class="submit" id="login_submit"/>
|
||||||
<span id="loading"> </span>
|
<span id="loading"> </span>
|
||||||
</div>
|
</div>
|
||||||
% if yes_recovery_login:
|
% if yes_recovery_login:
|
||||||
<div class="form"><a href="${url_for('.recovery_password')}">${_('Recovery password?')}</a></div>
|
<div class="form"><a href="${url_for('.recovery_password')}">${lang('admin', 'recovery_password', 'Recovery password?')}</a></div>
|
||||||
% endif
|
% endif
|
||||||
<!--<div class="form">${_('Remember that only have 3 attempts')}</div>-->
|
<div class="form">${lang('admin', 'remember_tries', 'Remember that only have 3 attempts')}</div>
|
||||||
</form>
|
</form>
|
||||||
</%block>
|
</%block>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,17 @@
|
||||||
<%inherit file="login.phtml"/>
|
<%inherit file="login.phtml"/>
|
||||||
<%block name="title">${_('Paramecio Login')}</%block>
|
<%block name="title">${lang('admin', 'login', 'Paramecio Login')}</%block>
|
||||||
<%block name="content">
|
<%block name="content">
|
||||||
<form id="login">
|
<form id="login">
|
||||||
<div id="title">
|
<div id="title">
|
||||||
${_('Paramecio Login')}
|
${lang('admin', 'login', 'Paramecio Login')}
|
||||||
</div>
|
</div>
|
||||||
<div class="form">
|
<div class="form">
|
||||||
<p align="center">${_('Check your email for get instructions for complete login with double auth or')} <a href="${url_for('.logout')}">logout</a> and login again with other user</p>
|
<p align="center">${lang('admin', 'check_your_email', 'Check your email for get instructions for complete login with double auth or')} <a href="${url_for('.logout')}">logout</a> and login again with other user</p>
|
||||||
<p><label>${_('Code')} *</label><input type="text" class="" name="code" id="code_form" value="" /> <span class="error" id="code_error"></span></p>
|
<p><label>${lang('admin', 'code', 'Code')} *</label><input type="text" class="" name="code" id="code_form" value="" /> <span class="error" id="code_error"></span></p>
|
||||||
${csrf_token()|n}
|
${csrf_token()|n}
|
||||||
</div>
|
</div>
|
||||||
<div id="submit_block">
|
<div id="submit_block">
|
||||||
<input type="submit" value="${_('Send code')}" class="submit" id="code_submit"/>
|
<input type="submit" value="${lang('common', 'send_code', 'Send code')}" class="submit" id="code_submit"/>
|
||||||
<span id="loading"> </span>
|
<span id="loading"> </span>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
@ -60,17 +60,17 @@
|
||||||
|
|
||||||
if(data.hasOwnProperty('disable')) {
|
if(data.hasOwnProperty('disable')) {
|
||||||
|
|
||||||
$('#code_error').html("${_('Error, your user is disabled, you need support of web administration')}");
|
$('#code_error').html("${lang('common', 'error_disabled', 'Error, your user is disabled, you need support of web administration')}");
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
$('#code_error').html("${_('Error, wrong code')}");
|
$('#code_error').html("${lang('common', 'error_wrong_code', 'Error, wrong code')}");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(data.you_cannot_login) {
|
if(data.you_cannot_login) {
|
||||||
|
|
||||||
$('#code_error').html("${_('Error, excessive tries, wait some minutes for login again')}");
|
$('#code_error').html("${lang('common', 'error_tries_disabled', 'Error, excessive tries, wait some minutes for login again')}");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,17 +48,16 @@
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</%block>
|
</%block>
|
||||||
<%block name="title">${_('Paramecio Sign up')}</%block>
|
<%block name="title">${lang('admin', 'sign_up', 'Paramecio Sign up')}</%block>
|
||||||
<%block name="content">
|
<%block name="content">
|
||||||
<form id="login">
|
<form id="login">
|
||||||
<div id="title">
|
<div id="title">
|
||||||
${_('Paramecio Sign up')}
|
${lang('admin', 'sign_up', 'Paramecio Sign up')}
|
||||||
</div>
|
</div>
|
||||||
${forms|n}
|
${forms|n}
|
||||||
${csrf_token()|n}
|
|
||||||
<div id="result_register"></div>
|
<div id="result_register"></div>
|
||||||
<div id="submit_block">
|
<div id="submit_block">
|
||||||
<input type="submit" value="${_('Sign up')}" class="submit" id="register_submit"/>
|
<input type="submit" value="${lang('common', 'sign_up', 'Sign up')}" class="submit" id="register_submit"/>
|
||||||
<span id="loading"> </span>
|
<span id="loading"> </span>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
<%inherit file="dashboard.phtml"/>
|
<%inherit file="dashboard.phtml"/>
|
||||||
<%block name="content">
|
<%block name="content">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
${_('Welcome to Paramecio Admin')}
|
Welcome to Paramecio Admin
|
||||||
</div>
|
</div>
|
||||||
<div class="cont">
|
<div class="cont">
|
||||||
${_('From here you can admin your site')}
|
From here you can admin your site
|
||||||
</div>
|
</div>
|
||||||
</%block>
|
</%block>
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,6 @@
|
||||||
from settings import config
|
from settings import config
|
||||||
from paramecio2.libraries.mtemplates import PTemplate, env_theme
|
from paramecio2.libraries.mtemplates import PTemplate, env_theme
|
||||||
from paramecio2.modules.welcome import welcome_app
|
from paramecio2.modules.welcome import welcome_app
|
||||||
from paramecio2.libraries.i18n import PGetText
|
|
||||||
|
|
||||||
pgettext=PGetText(__file__)
|
|
||||||
|
|
||||||
_=pgettext.gettext
|
|
||||||
|
|
||||||
env=env_theme(__file__)
|
env=env_theme(__file__)
|
||||||
|
|
||||||
|
|
@ -15,7 +10,7 @@ t=PTemplate(env)
|
||||||
@welcome_app.route('/welcome')
|
@welcome_app.route('/welcome')
|
||||||
def home():
|
def home():
|
||||||
|
|
||||||
return t.load_template('welcome.phtml', title=_("Welcome"), content=_('Welcome to the real world'))
|
return t.load_template('welcome.phtml', title="Welcome", content='Welcome to the real world')
|
||||||
|
|
||||||
#return render_template('welcome.html', title="Welcome")
|
#return render_template('welcome.html', title="Welcome")
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -1,30 +0,0 @@
|
||||||
# SOME DESCRIPTIVE TITLE.
|
|
||||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
|
||||||
# This file is distributed under the same license as the PACKAGE package.
|
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
|
||||||
#
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: \n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2023-12-18 22:13+0100\n"
|
|
||||||
"PO-Revision-Date: 2023-12-18 22:13+0100\n"
|
|
||||||
"Last-Translator: \n"
|
|
||||||
"Language-Team: \n"
|
|
||||||
"Language: es\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"X-Generator: Poedit 3.4.1\n"
|
|
||||||
|
|
||||||
#: app.py:13
|
|
||||||
msgid "Welcome"
|
|
||||||
msgstr "Bienvenido"
|
|
||||||
|
|
||||||
#: app.py:13
|
|
||||||
msgid "Welcome to the real world"
|
|
||||||
msgstr "Bienvenido al mundo real"
|
|
||||||
|
|
||||||
#: templates/welcome.phtml:75
|
|
||||||
msgid "Paramecio, a system created for create webapps"
|
|
||||||
msgstr "Paramecio, un sistema creado para crear webapps"
|
|
||||||
|
|
@ -72,7 +72,7 @@
|
||||||
${content}
|
${content}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="footer">${_('Paramecio, a system created for create webapps')}</div>
|
<div class="footer">Paramecio, a system created for create webapps</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
|
||||||
|
|
@ -1,151 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
import traceback
|
|
||||||
import argparse
|
|
||||||
import os,sys
|
|
||||||
import shutil
|
|
||||||
import getpass
|
|
||||||
from pathlib import Path
|
|
||||||
from importlib import import_module
|
|
||||||
from paramecio2.libraries.slugify import slugify
|
|
||||||
import json
|
|
||||||
|
|
||||||
sys.path.insert(0, os.path.realpath('.'))
|
|
||||||
|
|
||||||
try:
|
|
||||||
|
|
||||||
from settings import config
|
|
||||||
|
|
||||||
except:
|
|
||||||
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def start():
|
|
||||||
"""Module for create new modules for paramecio
|
|
||||||
"""
|
|
||||||
|
|
||||||
parser=argparse.ArgumentParser(description='A tool for create new modules for paramecio')
|
|
||||||
|
|
||||||
parser.add_argument('--folder', help='The folder where the new paramecio module is located', required=True)
|
|
||||||
|
|
||||||
args=parser.parse_args()
|
|
||||||
|
|
||||||
workdir=os.path.dirname(os.path.abspath(__file__))
|
|
||||||
|
|
||||||
# Create directory
|
|
||||||
|
|
||||||
real_path=os.path.basename(slugify(args.folder))
|
|
||||||
|
|
||||||
path=Path('modules/'+real_path)
|
|
||||||
|
|
||||||
|
|
||||||
path.mkdir(0o755, True)
|
|
||||||
|
|
||||||
#open('modules/'+args.path+'/__init__.py', 'a').close()
|
|
||||||
with open('modules/'+real_path+'/__init__.py', 'a') as f:
|
|
||||||
f.write("from flask import Blueprint\n\n")
|
|
||||||
f.write("{}_app=Blueprint('{}_app', __name__)\n\n".format(real_path, real_path))
|
|
||||||
f.write("@{}_app.route('/{}')\n".format(real_path, real_path))
|
|
||||||
f.write("def {}_home():\n".format(real_path))
|
|
||||||
f.write(" return {'hello': 'world'}")
|
|
||||||
|
|
||||||
modules_json={}
|
|
||||||
|
|
||||||
if os.path.isfile('settings/modules.json'):
|
|
||||||
|
|
||||||
with open('settings/modules.json') as f:
|
|
||||||
|
|
||||||
#apps={'monit2': ['modules.monit2', 'monit2_app', '/'], 'welcome': ['paramecio2.modules.welcome', 'welcome_app', '/'], 'pastafari2': ['modules.pastafari2', 'pastafari_app', '/'], 'apache': ['modules.apache', 'apache_app', '/'], 'mariadb': ['modules.mariadb', 'mariadb_app', '/'], 'apiv1': ['modules.apiv1', 'apiv1_app', '/'], 'admin': ['paramecio2.modules.admin', 'admin_app', '/']}
|
|
||||||
|
|
||||||
json_text=f.read()
|
|
||||||
|
|
||||||
if json_text!='':
|
|
||||||
modules_json=json.loads(json_text)
|
|
||||||
|
|
||||||
with open('settings/modules.json', 'w+') as f:
|
|
||||||
modules_json[real_path]=['modules.'+real_path, real_path+'_app', '/']
|
|
||||||
|
|
||||||
f.write(json.dumps(modules_json, indent=4))
|
|
||||||
|
|
||||||
print('Created the new module. Please, reload the WSGI server and go to url /'+real_path)
|
|
||||||
|
|
||||||
"""
|
|
||||||
except:
|
|
||||||
|
|
||||||
print('Error: cannot create the directory. Check if exists and if you have permissions')
|
|
||||||
exit(1)
|
|
||||||
"""
|
|
||||||
#Create base controller file
|
|
||||||
|
|
||||||
#f=open('modules/'+args.path+'/index.py', 'w')
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
shutil.copy(workdir+'/examples/app.py', 'modules/'+args.path+'/__init__.py')
|
|
||||||
|
|
||||||
except:
|
|
||||||
|
|
||||||
print('Error: cannot copy controller example. Check if you have permissions')
|
|
||||||
exit(1)
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Regenerate modules
|
|
||||||
|
|
||||||
#regenerate_modules_config()
|
|
||||||
"""
|
|
||||||
def regenerate_modules_config():
|
|
||||||
|
|
||||||
print("Regenerating modules configuration...")
|
|
||||||
|
|
||||||
modules=[]
|
|
||||||
|
|
||||||
modules.append("#!/usr/bin/env python3\n\n")
|
|
||||||
modules.append("list_modules=[]\n\n")
|
|
||||||
|
|
||||||
for module in config.modules:
|
|
||||||
|
|
||||||
try:
|
|
||||||
|
|
||||||
controller_path=import_module(module)
|
|
||||||
|
|
||||||
controller_base=os.path.dirname(controller_path.__file__)
|
|
||||||
|
|
||||||
base_module=module.split('.')[-1]
|
|
||||||
|
|
||||||
dir_controllers=os.listdir(controller_base)
|
|
||||||
|
|
||||||
modules.append('from '+module+' import ')
|
|
||||||
|
|
||||||
arr_controllers=[]
|
|
||||||
|
|
||||||
for controller in dir_controllers:
|
|
||||||
|
|
||||||
if controller.find('.py')!=-1 and controller.find('__init__')==-1:
|
|
||||||
|
|
||||||
controller_py=controller.replace('.py', '')
|
|
||||||
|
|
||||||
arr_controllers.append(controller_py)
|
|
||||||
|
|
||||||
#load(module+'.'+controller_py)
|
|
||||||
|
|
||||||
|
|
||||||
modules.append(", ".join(arr_controllers))
|
|
||||||
|
|
||||||
modules.append("\n\n")
|
|
||||||
|
|
||||||
#add_func_static_module(controller_base)
|
|
||||||
|
|
||||||
except:
|
|
||||||
|
|
||||||
print("Exception in user code:")
|
|
||||||
print("-"*60)
|
|
||||||
traceback.print_exc(file=sys.stdout)
|
|
||||||
print("-"*60)
|
|
||||||
exit(1)
|
|
||||||
|
|
||||||
with open('./settings/modules.py', 'w') as f:
|
|
||||||
f.write("".join(modules))
|
|
||||||
"""
|
|
||||||
|
|
||||||
if __name__=="__main__":
|
|
||||||
start()
|
|
||||||
|
|
@ -1,115 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
import traceback
|
|
||||||
import argparse
|
|
||||||
import os,sys
|
|
||||||
import shutil
|
|
||||||
import getpass
|
|
||||||
from pathlib import Path
|
|
||||||
from importlib import import_module
|
|
||||||
from paramecio2.libraries.slugify import slugify
|
|
||||||
import json
|
|
||||||
import subprocess
|
|
||||||
#from colorama import init, Fore, Back, Style
|
|
||||||
import colorama
|
|
||||||
|
|
||||||
sys.path.insert(0, os.path.realpath('.'))
|
|
||||||
|
|
||||||
try:
|
|
||||||
|
|
||||||
from settings import config
|
|
||||||
|
|
||||||
except:
|
|
||||||
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def start():
|
|
||||||
"""Module for create new modules for paramecio
|
|
||||||
"""
|
|
||||||
|
|
||||||
parser=argparse.ArgumentParser(description='A tool for add modules for paramecio from git url')
|
|
||||||
|
|
||||||
parser.add_argument('--git_url', help='The git url for clone the module.', required=True)
|
|
||||||
|
|
||||||
args=parser.parse_args()
|
|
||||||
|
|
||||||
colorama.init()
|
|
||||||
|
|
||||||
workdir='.'
|
|
||||||
|
|
||||||
os.chdir('./modules/')
|
|
||||||
|
|
||||||
if subprocess.call("git clone {}".format(args.git_url), shell=True) > 0:
|
|
||||||
print('Error, cannot install the git module. Do you have installed git?. Is a correct url?')
|
|
||||||
exit(1)
|
|
||||||
|
|
||||||
real_path=''
|
|
||||||
|
|
||||||
with os.scandir('.') as d:
|
|
||||||
for e in d:
|
|
||||||
#print(e.name)
|
|
||||||
if not e.name in config.apps:
|
|
||||||
#print(e.name)
|
|
||||||
if args.git_url.find(e.name)!=-1:
|
|
||||||
real_path=os.path.basename(e.name)
|
|
||||||
|
|
||||||
# Add dependencies using pip
|
|
||||||
|
|
||||||
os.chdir('../')
|
|
||||||
|
|
||||||
dependencies_file='./modules/{}/dependencies.json'.format(real_path)
|
|
||||||
|
|
||||||
if os.path.isfile(dependencies_file):
|
|
||||||
|
|
||||||
dep_json=[]
|
|
||||||
|
|
||||||
with open(dependencies_file) as f:
|
|
||||||
|
|
||||||
content=f.read()
|
|
||||||
|
|
||||||
try:
|
|
||||||
dep_json=json.loads(content)
|
|
||||||
except:
|
|
||||||
dep_json=[]
|
|
||||||
print('Error: cannot install dependencies for the package. Malformed json {}'.format(content))
|
|
||||||
|
|
||||||
if len(dep_json)>0:
|
|
||||||
if 'packages' in dep_json:
|
|
||||||
print('Install dependencies for the module...')
|
|
||||||
arr_packages=" ".join(dep_json['packages'])
|
|
||||||
if subprocess.call("pip install {}".format(arr_packages), shell=True) > 0:
|
|
||||||
print('Error, cannot install the pip libraries. Do you have installed pip?.')
|
|
||||||
|
|
||||||
if 'models' in dep_json:
|
|
||||||
print('Creating database tables from models in module...')
|
|
||||||
for model in dep_json['models']:
|
|
||||||
if subprocess.call("paramecio2db --model modules/{}/models/{}.py".format(real_path, model), shell=True) > 0:
|
|
||||||
|
|
||||||
print('Error, cannot install the model {}.'.format(model))
|
|
||||||
|
|
||||||
# Add to json configuration.
|
|
||||||
|
|
||||||
if real_path!='':
|
|
||||||
|
|
||||||
if os.path.isfile('settings/modules.json'):
|
|
||||||
|
|
||||||
modules_json={}
|
|
||||||
|
|
||||||
with open('settings/modules.json') as f:
|
|
||||||
print('Inserting new module in modules.json...')
|
|
||||||
|
|
||||||
json_text=f.read()
|
|
||||||
|
|
||||||
if json_text!='':
|
|
||||||
modules_json=json.loads(json_text)
|
|
||||||
|
|
||||||
with open('settings/modules.json', 'w+') as f:
|
|
||||||
modules_json[real_path]=['modules.'+real_path, real_path+'_app', '/']
|
|
||||||
|
|
||||||
f.write(json.dumps(modules_json, indent=4))
|
|
||||||
|
|
||||||
print('Please, reload your wsgi application for access to your new module')
|
|
||||||
|
|
||||||
if __name__=="__main__":
|
|
||||||
start()
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue