Browse Source
Merge branch '8.0' of https://github.com/oca/server-tools into 8.0-add-database_cleanup
pull/95/head
Merge branch '8.0' of https://github.com/oca/server-tools into 8.0-add-database_cleanup
pull/95/head
Anthony Muschang
10 years ago
203 changed files with 9920 additions and 0 deletions
-
56.gitignore
-
29.travis.yml
-
661LICENSE
-
12README.md
-
23__unported__/auth_admin_passkey/__init__.py
-
66__unported__/auth_admin_passkey/__openerp__.py
-
34__unported__/auth_admin_passkey/data/ir_config_parameter.xml
-
101__unported__/auth_admin_passkey/i18n/auth_admin_passkey.pot
-
120__unported__/auth_admin_passkey/i18n/fr.po
-
24__unported__/auth_admin_passkey/model/__init__.py
-
76__unported__/auth_admin_passkey/model/res_config.py
-
137__unported__/auth_admin_passkey/model/res_users.py
-
BIN__unported__/auth_admin_passkey/static/src/img/icon.png
-
23__unported__/auth_admin_passkey/tests/__init__.py
-
99__unported__/auth_admin_passkey/tests/test_auth_admin_passkey.py
-
47__unported__/auth_admin_passkey/view/res_config_view.xml
-
56__unported__/auth_from_http_basic/__init__.py
-
62__unported__/auth_from_http_basic/__openerp__.py
-
20__unported__/auth_from_http_basic_logout/__init__.py
-
57__unported__/auth_from_http_basic_logout/__openerp__.py
-
23__unported__/auth_from_http_basic_logout/i18n/auth_from_http_basic_logout.pot
-
27__unported__/auth_from_http_basic_logout/i18n/nl.po
-
BIN__unported__/auth_from_http_basic_logout/static/src/img/icon.png
-
48__unported__/auth_from_http_basic_logout/static/src/js/auth_from_http_basic_logout.js
-
24__unported__/base_external_dbsource/__init__.py
-
66__unported__/base_external_dbsource/__openerp__.py
-
175__unported__/base_external_dbsource/base_external_dbsource.py
-
15__unported__/base_external_dbsource/base_external_dbsource_demo.xml
-
54__unported__/base_external_dbsource/base_external_dbsource_view.xml
-
BIN__unported__/base_external_dbsource/images/screenshot01.png
-
2__unported__/base_external_dbsource/security/ir.model.access.csv
-
9__unported__/base_external_dbsource/test/dbsource_connect.yml
-
22__unported__/configuration_helper/__init__.py
-
82__unported__/configuration_helper/__openerp__.py
-
114__unported__/configuration_helper/config.py
-
1__unported__/email_template_template/__init__.py
-
105__unported__/email_template_template/__openerp__.py
-
16__unported__/email_template_template/i18n/email_template_template.pot
-
21__unported__/email_template_template/model/__init__.py
-
61__unported__/email_template_template/model/email_template.py
-
70__unported__/email_template_template/view/email_template.xml
-
25__unported__/fetchmail_attach_from_folder/__init__.py
-
46__unported__/fetchmail_attach_from_folder/__openerp__.py
-
26__unported__/fetchmail_attach_from_folder/match_algorithm/__init__.py
-
43__unported__/fetchmail_attach_from_folder/match_algorithm/base.py
-
45__unported__/fetchmail_attach_from_folder/match_algorithm/email_domain.py
-
57__unported__/fetchmail_attach_from_folder/match_algorithm/email_exact.py
-
58__unported__/fetchmail_attach_from_folder/match_algorithm/openerp_standard.py
-
24__unported__/fetchmail_attach_from_folder/model/__init__.py
-
278__unported__/fetchmail_attach_from_folder/model/fetchmail_server.py
-
131__unported__/fetchmail_attach_from_folder/model/fetchmail_server_folder.py
-
2__unported__/fetchmail_attach_from_folder/security/ir.model.access.csv
-
56__unported__/fetchmail_attach_from_folder/view/fetchmail_server.xml
-
23__unported__/fetchmail_attach_from_folder/wizard/__init__.py
-
129__unported__/fetchmail_attach_from_folder/wizard/attach_mail_manually.py
-
29__unported__/fetchmail_attach_from_folder/wizard/attach_mail_manually.xml
-
24__unported__/import_odbc/__init__.py
-
101__unported__/import_odbc/__openerp__.py
-
BIN__unported__/import_odbc/images/snapshot1.png
-
BIN__unported__/import_odbc/images/snapshot2.png
-
216__unported__/import_odbc/import_odbc.py
-
15__unported__/import_odbc/import_odbc_demo.xml
-
90__unported__/import_odbc/import_odbc_view.xml
-
2__unported__/import_odbc/security/ir.model.access.csv
-
0__unported__/ir_config_parameter_viewer/__init__.py
-
20__unported__/ir_config_parameter_viewer/__openerp__.py
-
16__unported__/ir_config_parameter_viewer/i18n/ir_config_parameter_viewer.pot
-
36__unported__/ir_config_parameter_viewer/ir_config_parameter_view.xml
-
1__unported__/mail_environment/__init__.py
-
68__unported__/mail_environment/__openerp__.py
-
225__unported__/mail_environment/env_mail.py
-
16__unported__/mail_environment/i18n/mail_environment.pot
-
27__unported__/mail_environment/mail_view.xml
-
1__unported__/security_protector/__init__.py
-
25__unported__/security_protector/__openerp__.py
-
8__unported__/security_protector/data.xml
-
16__unported__/security_protector/i18n/security_protector.pot
-
47__unported__/security_protector/security_protector.py
-
8__unported__/security_protector/security_view.xml
-
22__unported__/server_env_base_external_referentials/__init__.py
-
47__unported__/server_env_base_external_referentials/__openerp__.py
-
54__unported__/server_env_base_external_referentials/base_external_referentials.py
-
16__unported__/server_env_base_external_referentials/i18n/server_env_base_external_referentials.pot
-
1__unported__/super_calendar/AUTHORS.txt
-
21__unported__/super_calendar/__init__.py
-
88__unported__/super_calendar/__openerp__.py
-
15__unported__/super_calendar/cron_data.xml
-
212__unported__/super_calendar/i18n/it.po
-
211__unported__/super_calendar/i18n/ru.po
-
210__unported__/super_calendar/i18n/super_calendar.pot
-
4__unported__/super_calendar/security/ir.model.access.csv
-
163__unported__/super_calendar/super_calendar.py
-
144__unported__/super_calendar/super_calendar_view.xml
-
22__unported__/users_ldap_groups/__init__.py
-
61__unported__/users_ldap_groups/__openerp__.py
-
16__unported__/users_ldap_groups/i18n/users_ldap_groups.pot
-
2__unported__/users_ldap_groups/security/ir.model.access.csv
-
107__unported__/users_ldap_groups/users_ldap_groups.py
-
27__unported__/users_ldap_groups/users_ldap_groups.xml
-
47__unported__/users_ldap_groups/users_ldap_groups_operators.py
@ -0,0 +1,56 @@ |
|||
# Byte-compiled / optimized / DLL files |
|||
__pycache__/ |
|||
*.py[cod] |
|||
|
|||
# C extensions |
|||
*.so |
|||
|
|||
# Distribution / packaging |
|||
.Python |
|||
env/ |
|||
bin/ |
|||
build/ |
|||
develop-eggs/ |
|||
dist/ |
|||
eggs/ |
|||
lib/ |
|||
lib64/ |
|||
parts/ |
|||
sdist/ |
|||
var/ |
|||
*.egg-info/ |
|||
.installed.cfg |
|||
*.egg |
|||
|
|||
# Installer logs |
|||
pip-log.txt |
|||
pip-delete-this-directory.txt |
|||
|
|||
# Unit test / coverage reports |
|||
htmlcov/ |
|||
.tox/ |
|||
.coverage |
|||
.cache |
|||
nosetests.xml |
|||
coverage.xml |
|||
|
|||
# Translations |
|||
*.mo |
|||
|
|||
# Pycharm |
|||
.idea |
|||
|
|||
# Mr Developer |
|||
.mr.developer.cfg |
|||
.project |
|||
.pydevproject |
|||
|
|||
# Rope |
|||
.ropeproject |
|||
|
|||
# Sphinx documentation |
|||
docs/_build/ |
|||
|
|||
# Backup files |
|||
*~ |
|||
*.swp |
@ -0,0 +1,29 @@ |
|||
language: python |
|||
|
|||
python: |
|||
- "2.7" |
|||
|
|||
env: |
|||
- VERSION="8.0" ODOO_REPO="odoo/odoo" |
|||
- VERSION="8.0" ODOO_REPO="OCA/OCB" |
|||
- VERSION="8.0" UNIT_TEST="1" |
|||
|
|||
virtualenv: |
|||
system_site_packages: true |
|||
|
|||
env: |
|||
- VERSION="8.0" ODOO_REPO="odoo/odoo" |
|||
- VERSION="8.0" ODOO_REPO="OCA/OCB" |
|||
|
|||
install: |
|||
- git clone https://github.com/OCA/maintainer-quality-tools.git ${HOME}/maintainer-quality-tools |
|||
- export PATH=${HOME}/maintainer-quality-tools/travis:${PATH} |
|||
- travis_install_nightly |
|||
- sudo pip install python-ldap |
|||
- printf '[options]\n\nrunning_env = dev' > ${HOME}/.openerp_serverrc |
|||
- ln -s server_environment_files_sample ./server_environment_files |
|||
script: |
|||
- travis_run_tests |
|||
|
|||
after_success: |
|||
coveralls |
@ -0,0 +1,661 @@ |
|||
GNU AFFERO GENERAL PUBLIC LICENSE |
|||
Version 3, 19 November 2007 |
|||
|
|||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> |
|||
Everyone is permitted to copy and distribute verbatim copies |
|||
of this license document, but changing it is not allowed. |
|||
|
|||
Preamble |
|||
|
|||
The GNU Affero General Public License is a free, copyleft license for |
|||
software and other kinds of works, specifically designed to ensure |
|||
cooperation with the community in the case of network server software. |
|||
|
|||
The licenses for most software and other practical works are designed |
|||
to take away your freedom to share and change the works. By contrast, |
|||
our General Public Licenses are intended to guarantee your freedom to |
|||
share and change all versions of a program--to make sure it remains free |
|||
software for all its users. |
|||
|
|||
When we speak of free software, we are referring to freedom, not |
|||
price. Our General Public Licenses are designed to make sure that you |
|||
have the freedom to distribute copies of free software (and charge for |
|||
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 |
|||
free programs, and that you know you can do these things. |
|||
|
|||
Developers that use our General Public Licenses protect your rights |
|||
with two steps: (1) assert copyright on the software, and (2) offer |
|||
you this License which gives you legal permission to copy, distribute |
|||
and/or modify the software. |
|||
|
|||
A secondary benefit of defending all users' freedom is that |
|||
improvements made in alternate versions of the program, if they |
|||
receive widespread use, become available for other developers to |
|||
incorporate. Many developers of free software are heartened and |
|||
encouraged by the resulting cooperation. However, in the case of |
|||
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 |
|||
ensure that, in such cases, the modified source code becomes available |
|||
to the community. It requires the operator of a network server to |
|||
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 |
|||
published by Affero, was designed to accomplish similar goals. This is |
|||
a different license, not a version of the Affero GPL, but Affero has |
|||
released a new version of the Affero GPL which permits relicensing under |
|||
this license. |
|||
|
|||
The precise terms and conditions for copying, distribution and |
|||
modification follow. |
|||
|
|||
TERMS AND CONDITIONS |
|||
|
|||
0. Definitions. |
|||
|
|||
"This License" refers to version 3 of the GNU Affero General Public License. |
|||
|
|||
"Copyright" also means copyright-like laws that apply to other kinds of |
|||
works, such as semiconductor masks. |
|||
|
|||
"The Program" refers to any copyrightable work licensed under this |
|||
License. Each licensee is addressed as "you". "Licensees" and |
|||
"recipients" may be individuals or organizations. |
|||
|
|||
To "modify" a work means to copy from or adapt all or part of the work |
|||
in a fashion requiring copyright permission, other than the making of an |
|||
exact copy. The resulting work is called a "modified version" of the |
|||
earlier work or a work "based on" the earlier work. |
|||
|
|||
A "covered work" means either the unmodified Program or a work based |
|||
on the Program. |
|||
|
|||
To "propagate" a work means to do anything with it that, without |
|||
permission, would make you directly or secondarily liable for |
|||
infringement under applicable copyright law, except executing it on a |
|||
computer or modifying a private copy. Propagation includes copying, |
|||
distribution (with or without modification), making available to the |
|||
public, and in some countries other activities as well. |
|||
|
|||
To "convey" a work means any kind of propagation that enables other |
|||
parties to make or receive copies. Mere interaction with a user through |
|||
a computer network, with no transfer of a copy, is not conveying. |
|||
|
|||
An interactive user interface displays "Appropriate Legal Notices" |
|||
to the extent that it includes a convenient and prominently visible |
|||
feature that (1) displays an appropriate copyright notice, and (2) |
|||
tells the user that there is no warranty for the work (except to the |
|||
extent that warranties are provided), that licensees may convey the |
|||
work under this License, and how to view a copy of this License. If |
|||
the interface presents a list of user commands or options, such as a |
|||
menu, a prominent item in the list meets this criterion. |
|||
|
|||
1. Source Code. |
|||
|
|||
The "source code" for a work means the preferred form of the work |
|||
for making modifications to it. "Object code" means any non-source |
|||
form of a work. |
|||
|
|||
A "Standard Interface" means an interface that either is an official |
|||
standard defined by a recognized standards body, or, in the case of |
|||
interfaces specified for a particular programming language, one that |
|||
is widely used among developers working in that language. |
|||
|
|||
The "System Libraries" of an executable work include anything, other |
|||
than the work as a whole, that (a) is included in the normal form of |
|||
packaging a Major Component, but which is not part of that Major |
|||
Component, and (b) serves only to enable use of the work with that |
|||
Major Component, or to implement a Standard Interface for which an |
|||
implementation is available to the public in source code form. A |
|||
"Major Component", in this context, means a major essential component |
|||
(kernel, window system, and so on) of the specific operating system |
|||
(if any) on which the executable work runs, or a compiler used to |
|||
produce the work, or an object code interpreter used to run it. |
|||
|
|||
The "Corresponding Source" for a work in object code form means all |
|||
the source code needed to generate, install, and (for an executable |
|||
work) run the object code and to modify the work, including scripts to |
|||
control those activities. However, it does not include the work's |
|||
System Libraries, or general-purpose tools or generally available free |
|||
programs which are used unmodified in performing those activities but |
|||
which are not part of the work. For example, Corresponding Source |
|||
includes interface definition files associated with source files for |
|||
the work, and the source code for shared libraries and dynamically |
|||
linked subprograms that the work is specifically designed to require, |
|||
such as by intimate data communication or control flow between those |
|||
subprograms and other parts of the work. |
|||
|
|||
The Corresponding Source need not include anything that users |
|||
can regenerate automatically from other parts of the Corresponding |
|||
Source. |
|||
|
|||
The Corresponding Source for a work in source code form is that |
|||
same work. |
|||
|
|||
2. Basic Permissions. |
|||
|
|||
All rights granted under this License are granted for the term of |
|||
copyright on the Program, and are irrevocable provided the stated |
|||
conditions are met. This License explicitly affirms your unlimited |
|||
permission to run the unmodified Program. The output from running a |
|||
covered work is covered by this License only if the output, given its |
|||
content, constitutes a covered work. This License acknowledges your |
|||
rights of fair use or other equivalent, as provided by copyright law. |
|||
|
|||
You may make, run and propagate covered works that you do not |
|||
convey, without conditions so long as your license otherwise remains |
|||
in force. You may convey covered works to others for the sole purpose |
|||
of having them make modifications exclusively for you, or provide you |
|||
with facilities for running those works, provided that you comply with |
|||
the terms of this License in conveying all material for which you do |
|||
not control copyright. Those thus making or running the covered works |
|||
for you must do so exclusively on your behalf, under your direction |
|||
and control, on terms that prohibit them from making any copies of |
|||
your copyrighted material outside their relationship with you. |
|||
|
|||
Conveying under any other circumstances is permitted solely under |
|||
the conditions stated below. Sublicensing is not allowed; section 10 |
|||
makes it unnecessary. |
|||
|
|||
3. Protecting Users' Legal Rights From Anti-Circumvention Law. |
|||
|
|||
No covered work shall be deemed part of an effective technological |
|||
measure under any applicable law fulfilling obligations under article |
|||
11 of the WIPO copyright treaty adopted on 20 December 1996, or |
|||
similar laws prohibiting or restricting circumvention of such |
|||
measures. |
|||
|
|||
When you convey a covered work, you waive any legal power to forbid |
|||
circumvention of technological measures to the extent such circumvention |
|||
is effected by exercising rights under this License with respect to |
|||
the covered work, and you disclaim any intention to limit operation or |
|||
modification of the work as a means of enforcing, against the work's |
|||
users, your or third parties' legal rights to forbid circumvention of |
|||
technological measures. |
|||
|
|||
4. Conveying Verbatim Copies. |
|||
|
|||
You may convey verbatim copies of the Program's source code as you |
|||
receive it, in any medium, provided that you conspicuously and |
|||
appropriately publish on each copy an appropriate copyright notice; |
|||
keep intact all notices stating that this License and any |
|||
non-permissive terms added in accord with section 7 apply to the code; |
|||
keep intact all notices of the absence of any warranty; and give all |
|||
recipients a copy of this License along with the Program. |
|||
|
|||
You may charge any price or no price for each copy that you convey, |
|||
and you may offer support or warranty protection for a fee. |
|||
|
|||
5. Conveying Modified Source Versions. |
|||
|
|||
You may convey a work based on the Program, or the modifications to |
|||
produce it from the Program, in the form of source code under the |
|||
terms of section 4, provided that you also meet all of these conditions: |
|||
|
|||
a) The work must carry prominent notices stating that you modified |
|||
it, and giving a relevant date. |
|||
|
|||
b) The work must carry prominent notices stating that it is |
|||
released under this License and any conditions added under section |
|||
7. This requirement modifies the requirement in section 4 to |
|||
"keep intact all notices". |
|||
|
|||
c) You must license the entire work, as a whole, under this |
|||
License to anyone who comes into possession of a copy. This |
|||
License will therefore apply, along with any applicable section 7 |
|||
additional terms, to the whole of the work, and all its parts, |
|||
regardless of how they are packaged. This License gives no |
|||
permission to license the work in any other way, but it does not |
|||
invalidate such permission if you have separately received it. |
|||
|
|||
d) If the work has interactive user interfaces, each must display |
|||
Appropriate Legal Notices; however, if the Program has interactive |
|||
interfaces that do not display Appropriate Legal Notices, your |
|||
work need not make them do so. |
|||
|
|||
A compilation of a covered work with other separate and independent |
|||
works, which are not by their nature extensions of the covered work, |
|||
and which are not combined with it such as to form a larger program, |
|||
in or on a volume of a storage or distribution medium, is called an |
|||
"aggregate" if the compilation and its resulting copyright are not |
|||
used to limit the access or legal rights of the compilation's users |
|||
beyond what the individual works permit. Inclusion of a covered work |
|||
in an aggregate does not cause this License to apply to the other |
|||
parts of the aggregate. |
|||
|
|||
6. Conveying Non-Source Forms. |
|||
|
|||
You may convey a covered work in object code form under the terms |
|||
of sections 4 and 5, provided that you also convey the |
|||
machine-readable Corresponding Source under the terms of this License, |
|||
in one of these ways: |
|||
|
|||
a) Convey the object code in, or embodied in, a physical product |
|||
(including a physical distribution medium), accompanied by the |
|||
Corresponding Source fixed on a durable physical medium |
|||
customarily used for software interchange. |
|||
|
|||
b) Convey the object code in, or embodied in, a physical product |
|||
(including a physical distribution medium), accompanied by a |
|||
written offer, valid for at least three years and valid for as |
|||
long as you offer spare parts or customer support for that product |
|||
model, to give anyone who possesses the object code either (1) a |
|||
copy of the Corresponding Source for all the software in the |
|||
product that is covered by this License, on a durable physical |
|||
medium customarily used for software interchange, for a price no |
|||
more than your reasonable cost of physically performing this |
|||
conveying of source, or (2) access to copy the |
|||
Corresponding Source from a network server at no charge. |
|||
|
|||
c) Convey individual copies of the object code with a copy of the |
|||
written offer to provide the Corresponding Source. This |
|||
alternative is allowed only occasionally and noncommercially, and |
|||
only if you received the object code with such an offer, in accord |
|||
with subsection 6b. |
|||
|
|||
d) Convey the object code by offering access from a designated |
|||
place (gratis or for a charge), and offer equivalent access to the |
|||
Corresponding Source in the same way through the same place at no |
|||
further charge. You need not require recipients to copy the |
|||
Corresponding Source along with the object code. If the place to |
|||
copy the object code is a network server, the Corresponding Source |
|||
may be on a different server (operated by you or a third party) |
|||
that supports equivalent copying facilities, provided you maintain |
|||
clear directions next to the object code saying where to find the |
|||
Corresponding Source. Regardless of what server hosts the |
|||
Corresponding Source, you remain obligated to ensure that it is |
|||
available for as long as needed to satisfy these requirements. |
|||
|
|||
e) Convey the object code using peer-to-peer transmission, provided |
|||
you inform other peers where the object code and Corresponding |
|||
Source of the work are being offered to the general public at no |
|||
charge under subsection 6d. |
|||
|
|||
A separable portion of the object code, whose source code is excluded |
|||
from the Corresponding Source as a System Library, need not be |
|||
included in conveying the object code work. |
|||
|
|||
A "User Product" is either (1) a "consumer product", which means any |
|||
tangible personal property which is normally used for personal, family, |
|||
or household purposes, or (2) anything designed or sold for incorporation |
|||
into a dwelling. In determining whether a product is a consumer product, |
|||
doubtful cases shall be resolved in favor of coverage. For a particular |
|||
product received by a particular user, "normally used" refers to a |
|||
typical or common use of that class of product, regardless of the status |
|||
of the particular user or of the way in which the particular user |
|||
actually uses, or expects or is expected to use, the product. A product |
|||
is a consumer product regardless of whether the product has substantial |
|||
commercial, industrial or non-consumer uses, unless such uses represent |
|||
the only significant mode of use of the product. |
|||
|
|||
"Installation Information" for a User Product means any methods, |
|||
procedures, authorization keys, or other information required to install |
|||
and execute modified versions of a covered work in that User Product from |
|||
a modified version of its Corresponding Source. The information must |
|||
suffice to ensure that the continued functioning of the modified object |
|||
code is in no case prevented or interfered with solely because |
|||
modification has been made. |
|||
|
|||
If you convey an object code work under this section in, or with, or |
|||
specifically for use in, a User Product, and the conveying occurs as |
|||
part of a transaction in which the right of possession and use of the |
|||
User Product is transferred to the recipient in perpetuity or for a |
|||
fixed term (regardless of how the transaction is characterized), the |
|||
Corresponding Source conveyed under this section must be accompanied |
|||
by the Installation Information. But this requirement does not apply |
|||
if neither you nor any third party retains the ability to install |
|||
modified object code on the User Product (for example, the work has |
|||
been installed in ROM). |
|||
|
|||
The requirement to provide Installation Information does not include a |
|||
requirement to continue to provide support service, warranty, or updates |
|||
for a work that has been modified or installed by the recipient, or for |
|||
the User Product in which it has been modified or installed. Access to a |
|||
network may be denied when the modification itself materially and |
|||
adversely affects the operation of the network or violates the rules and |
|||
protocols for communication across the network. |
|||
|
|||
Corresponding Source conveyed, and Installation Information provided, |
|||
in accord with this section must be in a format that is publicly |
|||
documented (and with an implementation available to the public in |
|||
source code form), and must require no special password or key for |
|||
unpacking, reading or copying. |
|||
|
|||
7. Additional Terms. |
|||
|
|||
"Additional permissions" are terms that supplement the terms of this |
|||
License by making exceptions from one or more of its conditions. |
|||
Additional permissions that are applicable to the entire Program shall |
|||
be treated as though they were included in this License, to the extent |
|||
that they are valid under applicable law. If additional permissions |
|||
apply only to part of the Program, that part may be used separately |
|||
under those permissions, but the entire Program remains governed by |
|||
this License without regard to the additional permissions. |
|||
|
|||
When you convey a copy of a covered work, you may at your option |
|||
remove any additional permissions from that copy, or from any part of |
|||
it. (Additional permissions may be written to require their own |
|||
removal in certain cases when you modify the work.) You may place |
|||
additional permissions on material, added by you to a covered work, |
|||
for which you have or can give appropriate copyright permission. |
|||
|
|||
Notwithstanding any other provision of this License, for material you |
|||
add to a covered work, you may (if authorized by the copyright holders of |
|||
that material) supplement the terms of this License with terms: |
|||
|
|||
a) Disclaiming warranty or limiting liability differently from the |
|||
terms of sections 15 and 16 of this License; or |
|||
|
|||
b) Requiring preservation of specified reasonable legal notices or |
|||
author attributions in that material or in the Appropriate Legal |
|||
Notices displayed by works containing it; or |
|||
|
|||
c) Prohibiting misrepresentation of the origin of that material, or |
|||
requiring that modified versions of such material be marked in |
|||
reasonable ways as different from the original version; or |
|||
|
|||
d) Limiting the use for publicity purposes of names of licensors or |
|||
authors of the material; or |
|||
|
|||
e) Declining to grant rights under trademark law for use of some |
|||
trade names, trademarks, or service marks; or |
|||
|
|||
f) Requiring indemnification of licensors and authors of that |
|||
material by anyone who conveys the material (or modified versions of |
|||
it) with contractual assumptions of liability to the recipient, for |
|||
any liability that these contractual assumptions directly impose on |
|||
those licensors and authors. |
|||
|
|||
All other non-permissive additional terms are considered "further |
|||
restrictions" within the meaning of section 10. If the Program as you |
|||
received it, or any part of it, contains a notice stating that it is |
|||
governed by this License along with a term that is a further |
|||
restriction, you may remove that term. If a license document contains |
|||
a further restriction but permits relicensing or conveying under this |
|||
License, you may add to a covered work material governed by the terms |
|||
of that license document, provided that the further restriction does |
|||
not survive such relicensing or conveying. |
|||
|
|||
If you add terms to a covered work in accord with this section, you |
|||
must place, in the relevant source files, a statement of the |
|||
additional terms that apply to those files, or a notice indicating |
|||
where to find the applicable terms. |
|||
|
|||
Additional terms, permissive or non-permissive, may be stated in the |
|||
form of a separately written license, or stated as exceptions; |
|||
the above requirements apply either way. |
|||
|
|||
8. Termination. |
|||
|
|||
You may not propagate or modify a covered work except as expressly |
|||
provided under this License. Any attempt otherwise to propagate or |
|||
modify it is void, and will automatically terminate your rights under |
|||
this License (including any patent licenses granted under the third |
|||
paragraph of section 11). |
|||
|
|||
However, if you cease all violation of this License, then your |
|||
license from a particular copyright holder is reinstated (a) |
|||
provisionally, unless and until the copyright holder explicitly and |
|||
finally terminates your license, and (b) permanently, if the copyright |
|||
holder fails to notify you of the violation by some reasonable means |
|||
prior to 60 days after the cessation. |
|||
|
|||
Moreover, your license from a particular copyright holder is |
|||
reinstated permanently if the copyright holder notifies you of the |
|||
violation by some reasonable means, this is the first time you have |
|||
received notice of violation of this License (for any work) from that |
|||
copyright holder, and you cure the violation prior to 30 days after |
|||
your receipt of the notice. |
|||
|
|||
Termination of your rights under this section does not terminate the |
|||
licenses of parties who have received copies or rights from you under |
|||
this License. If your rights have been terminated and not permanently |
|||
reinstated, you do not qualify to receive new licenses for the same |
|||
material under section 10. |
|||
|
|||
9. Acceptance Not Required for Having Copies. |
|||
|
|||
You are not required to accept this License in order to receive or |
|||
run a copy of the Program. Ancillary propagation of a covered work |
|||
occurring solely as a consequence of using peer-to-peer transmission |
|||
to receive a copy likewise does not require acceptance. However, |
|||
nothing other than this License grants you permission to propagate or |
|||
modify any covered work. These actions infringe copyright if you do |
|||
not accept this License. Therefore, by modifying or propagating a |
|||
covered work, you indicate your acceptance of this License to do so. |
|||
|
|||
10. Automatic Licensing of Downstream Recipients. |
|||
|
|||
Each time you convey a covered work, the recipient automatically |
|||
receives a license from the original licensors, to run, modify and |
|||
propagate that work, subject to this License. You are not responsible |
|||
for enforcing compliance by third parties with this License. |
|||
|
|||
An "entity transaction" is a transaction transferring control of an |
|||
organization, or substantially all assets of one, or subdividing an |
|||
organization, or merging organizations. If propagation of a covered |
|||
work results from an entity transaction, each party to that |
|||
transaction who receives a copy of the work also receives whatever |
|||
licenses to the work the party's predecessor in interest had or could |
|||
give under the previous paragraph, plus a right to possession of the |
|||
Corresponding Source of the work from the predecessor in interest, if |
|||
the predecessor has it or can get it with reasonable efforts. |
|||
|
|||
You may not impose any further restrictions on the exercise of the |
|||
rights granted or affirmed under this License. For example, you may |
|||
not impose a license fee, royalty, or other charge for exercise of |
|||
rights granted under this License, and you may not initiate litigation |
|||
(including a cross-claim or counterclaim in a lawsuit) alleging that |
|||
any patent claim is infringed by making, using, selling, offering for |
|||
sale, or importing the Program or any portion of it. |
|||
|
|||
11. Patents. |
|||
|
|||
A "contributor" is a copyright holder who authorizes use under this |
|||
License of the Program or a work on which the Program is based. The |
|||
work thus licensed is called the contributor's "contributor version". |
|||
|
|||
A contributor's "essential patent claims" are all patent claims |
|||
owned or controlled by the contributor, whether already acquired or |
|||
hereafter acquired, that would be infringed by some manner, permitted |
|||
by this License, of making, using, or selling its contributor version, |
|||
but do not include claims that would be infringed only as a |
|||
consequence of further modification of the contributor version. For |
|||
purposes of this definition, "control" includes the right to grant |
|||
patent sublicenses in a manner consistent with the requirements of |
|||
this License. |
|||
|
|||
Each contributor grants you a non-exclusive, worldwide, royalty-free |
|||
patent license under the contributor's essential patent claims, to |
|||
make, use, sell, offer for sale, import and otherwise run, modify and |
|||
propagate the contents of its contributor version. |
|||
|
|||
In the following three paragraphs, a "patent license" is any express |
|||
agreement or commitment, however denominated, not to enforce a patent |
|||
(such as an express permission to practice a patent or covenant not to |
|||
sue for patent infringement). To "grant" such a patent license to a |
|||
party means to make such an agreement or commitment not to enforce a |
|||
patent against the party. |
|||
|
|||
If you convey a covered work, knowingly relying on a patent license, |
|||
and the Corresponding Source of the work is not available for anyone |
|||
to copy, free of charge and under the terms of this License, through a |
|||
publicly available network server or other readily accessible means, |
|||
then you must either (1) cause the Corresponding Source to be so |
|||
available, or (2) arrange to deprive yourself of the benefit of the |
|||
patent license for this particular work, or (3) arrange, in a manner |
|||
consistent with the requirements of this License, to extend the patent |
|||
license to downstream recipients. "Knowingly relying" means you have |
|||
actual knowledge that, but for the patent license, your conveying the |
|||
covered work in a country, or your recipient's use of the covered work |
|||
in a country, would infringe one or more identifiable patents in that |
|||
country that you have reason to believe are valid. |
|||
|
|||
If, pursuant to or in connection with a single transaction or |
|||
arrangement, you convey, or propagate by procuring conveyance of, a |
|||
covered work, and grant a patent license to some of the parties |
|||
receiving the covered work authorizing them to use, propagate, modify |
|||
or convey a specific copy of the covered work, then the patent license |
|||
you grant is automatically extended to all recipients of the covered |
|||
work and works based on it. |
|||
|
|||
A patent license is "discriminatory" if it does not include within |
|||
the scope of its coverage, prohibits the exercise of, or is |
|||
conditioned on the non-exercise of one or more of the rights that are |
|||
specifically granted under this License. You may not convey a covered |
|||
work if you are a party to an arrangement with a third party that is |
|||
in the business of distributing software, under which you make payment |
|||
to the third party based on the extent of your activity of conveying |
|||
the work, and under which the third party grants, to any of the |
|||
parties who would receive the covered work from you, a discriminatory |
|||
patent license (a) in connection with copies of the covered work |
|||
conveyed by you (or copies made from those copies), or (b) primarily |
|||
for and in connection with specific products or compilations that |
|||
contain the covered work, unless you entered into that arrangement, |
|||
or that patent license was granted, prior to 28 March 2007. |
|||
|
|||
Nothing in this License shall be construed as excluding or limiting |
|||
any implied license or other defenses to infringement that may |
|||
otherwise be available to you under applicable patent law. |
|||
|
|||
12. No Surrender of Others' Freedom. |
|||
|
|||
If conditions are imposed on you (whether by court order, agreement or |
|||
otherwise) that contradict the conditions of this License, they do not |
|||
excuse you from the conditions of this License. If you cannot convey a |
|||
covered work so as to satisfy simultaneously your obligations under this |
|||
License and any other pertinent obligations, then as a consequence you may |
|||
not convey it at all. For example, if you agree to terms that obligate you |
|||
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 |
|||
License would be to refrain entirely from conveying the Program. |
|||
|
|||
13. Remote Network Interaction; Use with the GNU 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 |
|||
permission to link or combine any covered work with a work licensed |
|||
under version 3 of the GNU General Public License into a single |
|||
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, |
|||
but the work with which it is combined will remain governed by version |
|||
3 of the GNU General Public License. |
|||
|
|||
14. Revised Versions of this License. |
|||
|
|||
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 |
|||
will be similar in spirit to the present version, but may differ in detail to |
|||
address new problems or concerns. |
|||
|
|||
Each version is given a distinguishing version number. If the |
|||
Program specifies that a certain numbered version of the GNU Affero General |
|||
Public License "or any later version" applies to it, you have the |
|||
option of following the terms and conditions either of that numbered |
|||
version or of any later version published by the Free Software |
|||
Foundation. If the Program does not specify a version number of the |
|||
GNU Affero General Public License, you may choose any version ever published |
|||
by the Free Software Foundation. |
|||
|
|||
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 |
|||
public statement of acceptance of a version permanently authorizes you |
|||
to choose that version for the Program. |
|||
|
|||
Later license versions may give you additional or different |
|||
permissions. However, no additional obligations are imposed on any |
|||
author or copyright holder as a result of your choosing to follow a |
|||
later version. |
|||
|
|||
15. Disclaimer of Warranty. |
|||
|
|||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY |
|||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT |
|||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY |
|||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, |
|||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM |
|||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF |
|||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION. |
|||
|
|||
16. Limitation of Liability. |
|||
|
|||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING |
|||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS |
|||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY |
|||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE |
|||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF |
|||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD |
|||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), |
|||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF |
|||
SUCH DAMAGES. |
|||
|
|||
17. Interpretation of Sections 15 and 16. |
|||
|
|||
If the disclaimer of warranty and limitation of liability provided |
|||
above cannot be given local legal effect according to their terms, |
|||
reviewing courts shall apply local law that most closely approximates |
|||
an absolute waiver of all civil liability in connection with the |
|||
Program, unless a warranty or assumption of liability accompanies a |
|||
copy of the Program in return for a fee. |
|||
|
|||
END OF TERMS AND CONDITIONS |
|||
|
|||
How to Apply These Terms to Your New Programs |
|||
|
|||
If you develop a new program, and you want it to be of the greatest |
|||
possible use to the public, the best way to achieve this is to make it |
|||
free software which everyone can redistribute and change under these terms. |
|||
|
|||
To do so, attach the following notices to the program. It is safest |
|||
to attach them to the start of each source file to most effectively |
|||
state the exclusion of warranty; and each file should have at least |
|||
the "copyright" line and a pointer to where the full notice is found. |
|||
|
|||
<one line to give the program's name and a brief idea of what it does.> |
|||
Copyright (C) <year> <name of author> |
|||
|
|||
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 <http://www.gnu.org/licenses/>. |
|||
|
|||
Also add information on how to contact you by electronic and paper mail. |
|||
|
|||
If your software can interact with users remotely through a computer |
|||
network, you should also make sure that it provides a way for users to |
|||
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 |
|||
of the code. There are many ways you could offer source, and different |
|||
solutions will be better for different programs; see section 13 for the |
|||
specific requirements. |
|||
|
|||
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. |
|||
For more information on this, and how to apply and follow the GNU AGPL, see |
|||
<http://www.gnu.org/licenses/>. |
@ -0,0 +1,12 @@ |
|||
[![Build Status](https://travis-ci.org/OCA/server-tools.svg?branch=8.0)](https://travis-ci.org/OCA/server-tools) |
|||
[![Coverage Status](https://coveralls.io/repos/OCA/server-tools/badge.png?branch=8.0)](https://coveralls.io/r/OCA/server-tools?branch=8.0) |
|||
|
|||
Server Environment And Tools |
|||
============================ |
|||
|
|||
This project aim to deal with modules related to manage Odoo server environment and provide useful tools. You'll find modules that: |
|||
|
|||
- Manage configuration depending on environment (devs, test, prod,..) |
|||
- Keep the security on update |
|||
- Manage email settings |
|||
-... |
@ -0,0 +1,23 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Admin Passkey module for OpenERP |
|||
# Copyright (C) 2013-2014 GRAP (http://www.grap.coop) |
|||
# @author Sylvain LE GAL (https://twitter.com/legalsylvain) |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
from . import model |
@ -0,0 +1,66 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Admin Passkey module for OpenERP |
|||
# Copyright (C) 2013-2014 GRAP (http://www.grap.coop) |
|||
# @author Sylvain LE GAL (https://twitter.com/legalsylvain) |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
{ |
|||
'name': 'Authentification - Admin Passkey', |
|||
'version': '2.1.1', |
|||
'category': 'base', |
|||
'description': """ |
|||
Admin password become a passkey for all active logins |
|||
===================================================== |
|||
|
|||
Functionality : |
|||
--------------- |
|||
* Administrator has now the possibility to login in with any login; |
|||
* By default, OpenERP will send a mail to user and admin to indicate them; |
|||
* If a user and the admin have the same password, admin will be informed; |
|||
|
|||
Technical information : |
|||
----------------------- |
|||
* Create two ir_config_parameter to enable / disable mail sending; |
|||
|
|||
Copyright, Author and Licence : |
|||
------------------------------- |
|||
* Copyright : 2014, Groupement Régional Alimentaire de Proximité; |
|||
* Author : Sylvain LE GAL (https://twitter.com/legalsylvain); |
|||
* Licence : AGPL-3 (http://www.gnu.org/licenses/) |
|||
""", |
|||
'author': 'GRAP', |
|||
'website': 'http://www.grap.coop', |
|||
'license': 'AGPL-3', |
|||
'depends': [ |
|||
'mail', |
|||
], |
|||
'data': [ |
|||
'data/ir_config_parameter.xml', |
|||
'view/res_config_view.xml', |
|||
], |
|||
'demo': [], |
|||
'js': [], |
|||
'css': [], |
|||
'qweb': [], |
|||
'images': [], |
|||
'post_load': '', |
|||
'application': False, |
|||
'installable': False, |
|||
'auto_install': False, |
|||
} |
@ -0,0 +1,34 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!-- ********************************************************************** --> |
|||
<!--Admin Passkey module for OpenERP --> |
|||
<!--Copyright (C) 2013-2014 GRAP (http://www.grap.coop) --> |
|||
<!--@author Sylvain LE GAL (https://twitter.com/legalsylvain) --> |
|||
|
|||
<!--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 <http://www.gnu.org/licenses/>. --> |
|||
<!-- ********************************************************************** --> |
|||
<openerp> |
|||
<data noupdate="1"> |
|||
|
|||
<record id="send_to_admin" model="ir.config_parameter"> |
|||
<field name="key">auth_admin_passkey.send_to_admin</field> |
|||
<field name="value">True</field> |
|||
</record> |
|||
|
|||
<record id="send_to_user" model="ir.config_parameter"> |
|||
<field name="key">auth_admin_passkey.send_to_user</field> |
|||
<field name="value">True</field> |
|||
</record> |
|||
|
|||
</data> |
|||
</openerp> |
@ -0,0 +1,101 @@ |
|||
############################################################################## |
|||
# |
|||
# Admin Passkey module for OpenERP |
|||
# Copyright (C) 2013-2014 GRAP (http://www.grap.coop) |
|||
# @author Sylvain LE GAL (https://twitter.com/legalsylvain) |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
# Translation of OpenERP Server. |
|||
# This file contains the translation of the following modules: |
|||
# * auth_admin_passkey |
|||
# |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: OpenERP Server 7.0\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2014-03-23 20:41+0000\n" |
|||
"PO-Revision-Date: 2014-03-23 20:41+0000\n" |
|||
"Last-Translator: <>\n" |
|||
"Language-Team: \n" |
|||
"MIME-Version: 1.0\n" |
|||
"Content-Type: text/plain; charset=UTF-8\n" |
|||
"Content-Transfer-Encoding: \n" |
|||
"Plural-Forms: \n" |
|||
|
|||
#. module: auth_admin_passkey |
|||
#: code:addons/auth_admin_passkey/model/res_users.py:66 |
|||
#, python-format |
|||
msgid "<pre>User with login '%s' has the same password as you.</pre>" |
|||
msgstr "" |
|||
|
|||
#. module: auth_admin_passkey |
|||
#: code:addons/auth_admin_passkey/model/res_users.py:44 |
|||
#, python-format |
|||
msgid "Admin user used his passkey to login with '%s'.\n" |
|||
"\n" |
|||
"\n" |
|||
"\n" |
|||
"Technicals informations belows : \n" |
|||
"\n" |
|||
"- Login date : %s\n" |
|||
"\n" |
|||
"" |
|||
msgstr "" |
|||
|
|||
#. module: auth_admin_passkey |
|||
#: view:base.config.settings:0 |
|||
msgid "Passkey" |
|||
msgstr "" |
|||
|
|||
#. module: auth_admin_passkey |
|||
#: code:addons/auth_admin_passkey/model/res_users.py:42 |
|||
#, python-format |
|||
msgid "Passkey used" |
|||
msgstr "" |
|||
|
|||
#. module: auth_admin_passkey |
|||
#: field:base.config.settings,auth_admin_passkey_send_to_admin:0 |
|||
msgid "Send email to admin user." |
|||
msgstr "" |
|||
|
|||
#. module: auth_admin_passkey |
|||
#: field:base.config.settings,auth_admin_passkey_send_to_user:0 |
|||
msgid "Send email to user." |
|||
msgstr "" |
|||
|
|||
#. module: auth_admin_passkey |
|||
#: code:_description:0 |
|||
#: model:ir.model,name:auth_admin_passkey.model_res_users |
|||
#, python-format |
|||
msgid "Users" |
|||
msgstr "" |
|||
|
|||
#. module: auth_admin_passkey |
|||
#: help:base.config.settings,auth_admin_passkey_send_to_user:0 |
|||
msgid "When the administrator use his password to login in with a different account, OpenERP will send an email to the account user." |
|||
msgstr "" |
|||
|
|||
#. module: auth_admin_passkey |
|||
#: help:base.config.settings,auth_admin_passkey_send_to_admin:0 |
|||
msgid "When the administrator use his password to login in with a different account, OpenERP will send an email to the admin user." |
|||
msgstr "" |
|||
|
|||
#. module: auth_admin_passkey |
|||
#: code:addons/auth_admin_passkey/model/res_users.py:64 |
|||
#, python-format |
|||
msgid "[WARNING] OpenERP Security Risk" |
|||
msgstr "" |
|||
|
@ -0,0 +1,120 @@ |
|||
############################################################################## |
|||
# |
|||
# Admin Passkey module for OpenERP |
|||
# Copyright (C) 2013-2014 GRAP (http://www.grap.coop) |
|||
# @author Sylvain LE GAL (https://twitter.com/legalsylvain) |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
# Translation of OpenERP Server. |
|||
# This file contains the translation of the following modules: |
|||
# * auth_admin_passkey |
|||
# |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: OpenERP Server 7.0\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2014-03-23 20:41+0000\n" |
|||
"PO-Revision-Date: 2014-04-08 09:24+0000\n" |
|||
"Last-Translator: Sylvain LE GAL (GRAP) <Unknown>\n" |
|||
"Language-Team: \n" |
|||
"MIME-Version: 1.0\n" |
|||
"Content-Type: text/plain; charset=UTF-8\n" |
|||
"Content-Transfer-Encoding: 8bit\n" |
|||
"X-Launchpad-Export-Date: 2014-05-24 06:46+0000\n" |
|||
"X-Generator: Launchpad (build 17017)\n" |
|||
|
|||
#. module: auth_admin_passkey |
|||
#: code:addons/auth_admin_passkey/model/res_users.py:66 |
|||
#, python-format |
|||
msgid "<pre>User with login '%s' has the same password as you.</pre>" |
|||
msgstr "" |
|||
"<pre>L'utilisateur dont l'identifiant est '%s' a le même mot de passe que " |
|||
"vous.</pre>" |
|||
|
|||
#. module: auth_admin_passkey |
|||
#: code:addons/auth_admin_passkey/model/res_users.py:44 |
|||
#, python-format |
|||
msgid "" |
|||
"Admin user used his passkey to login with '%s'.\n" |
|||
"\n" |
|||
"\n" |
|||
"\n" |
|||
"Technicals informations belows : \n" |
|||
"\n" |
|||
"- Login date : %s\n" |
|||
"\n" |
|||
msgstr "" |
|||
"L'administrateur a utilisé son mot de passe \"bris de glace\" pour " |
|||
"s'identifier avec l'identifiant '%s'.\n" |
|||
"\n" |
|||
"\n" |
|||
"\n" |
|||
"Informations techniques ci-dessous : \n" |
|||
"\n" |
|||
"- Date d'authentification : %s\n" |
|||
"\n" |
|||
|
|||
#. module: auth_admin_passkey |
|||
#: view:base.config.settings:0 |
|||
msgid "Passkey" |
|||
msgstr "Mot de passe \"bris de glace\"" |
|||
|
|||
#. module: auth_admin_passkey |
|||
#: code:addons/auth_admin_passkey/model/res_users.py:42 |
|||
#, python-format |
|||
msgid "Passkey used" |
|||
msgstr "Mot de passe \"bris de glace\" utilisé" |
|||
|
|||
#. module: auth_admin_passkey |
|||
#: field:base.config.settings,auth_admin_passkey_send_to_admin:0 |
|||
msgid "Send email to admin user." |
|||
msgstr "Envoyer un email à l'administrateur." |
|||
|
|||
#. module: auth_admin_passkey |
|||
#: field:base.config.settings,auth_admin_passkey_send_to_user:0 |
|||
msgid "Send email to user." |
|||
msgstr "Envoyer un email à l'utilisateur." |
|||
|
|||
#. module: auth_admin_passkey |
|||
#: code:_description:0 |
|||
#: model:ir.model,name:auth_admin_passkey.model_res_users |
|||
#, python-format |
|||
msgid "Users" |
|||
msgstr "Utilisateurs" |
|||
|
|||
#. module: auth_admin_passkey |
|||
#: help:base.config.settings,auth_admin_passkey_send_to_user:0 |
|||
msgid "" |
|||
"When the administrator use his password to login in with a different " |
|||
"account, OpenERP will send an email to the account user." |
|||
msgstr "" |
|||
"Quand l'administrateur utilise son mot de passe pour s'authentifier avec un " |
|||
"compte différent, OpenERP lui enverra un mail." |
|||
|
|||
#. module: auth_admin_passkey |
|||
#: help:base.config.settings,auth_admin_passkey_send_to_admin:0 |
|||
msgid "" |
|||
"When the administrator use his password to login in with a different " |
|||
"account, OpenERP will send an email to the admin user." |
|||
msgstr "" |
|||
"Quand l'administrateur utilise son mot de passe pour s'authentifier avec un " |
|||
"compte différent, OpenERP enverra un mail à l'utilisateur." |
|||
|
|||
#. module: auth_admin_passkey |
|||
#: code:addons/auth_admin_passkey/model/res_users.py:64 |
|||
#, python-format |
|||
msgid "[WARNING] OpenERP Security Risk" |
|||
msgstr "[WARNING] Faille de sécurité sur OpenERP" |
@ -0,0 +1,24 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Admin Passkey module for OpenERP |
|||
# Copyright (C) 2013-2014 GRAP (http://www.grap.coop) |
|||
# @author Sylvain LE GAL (https://twitter.com/legalsylvain) |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
from . import res_config |
|||
from . import res_users |
@ -0,0 +1,76 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Admin Passkey module for OpenERP |
|||
# Copyright (C) 2013-2014 GRAP (http://www.grap.coop) |
|||
# @author Sylvain LE GAL (https://twitter.com/legalsylvain) |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
from openerp.osv import fields |
|||
from openerp.osv.orm import TransientModel |
|||
from openerp.tools.safe_eval import safe_eval |
|||
|
|||
|
|||
class base_config_settings(TransientModel): |
|||
_inherit = 'base.config.settings' |
|||
|
|||
# Getter / Setter Section |
|||
def get_default_auth_admin_passkey_send_to_admin( |
|||
self, cr, uid, ids, context=None): |
|||
icp = self.pool['ir.config_parameter'] |
|||
return { |
|||
'auth_admin_passkey_send_to_admin': safe_eval(icp.get_param( |
|||
cr, uid, 'auth_admin_passkey.send_to_admin', 'True')), |
|||
} |
|||
|
|||
def set_auth_admin_passkey_send_to_admin(self, cr, uid, ids, context=None): |
|||
config = self.browse(cr, uid, ids[0], context=context) |
|||
icp = self.pool['ir.config_parameter'] |
|||
icp.set_param( |
|||
cr, uid, 'auth_admin_passkey.send_to_admin', |
|||
repr(config.auth_admin_passkey_send_to_admin)) |
|||
|
|||
def get_default_auth_admin_passkey_send_to_user( |
|||
self, cr, uid, ids, context=None): |
|||
icp = self.pool['ir.config_parameter'] |
|||
return { |
|||
'auth_admin_passkey_send_to_user': safe_eval(icp.get_param( |
|||
cr, uid, 'auth_admin_passkey.send_to_user', 'True')), |
|||
} |
|||
|
|||
def set_auth_admin_passkey_send_to_user(self, cr, uid, ids, context=None): |
|||
config = self.browse(cr, uid, ids[0], context=context) |
|||
icp = self.pool['ir.config_parameter'] |
|||
icp.set_param( |
|||
cr, uid, 'auth_admin_passkey.send_to_user', |
|||
repr(config.auth_admin_passkey_send_to_user)) |
|||
|
|||
# Columns Section |
|||
_columns = { |
|||
'auth_admin_passkey_send_to_admin': fields.boolean( |
|||
'Send email to admin user.', |
|||
help="""When the administrator use his password to login in """ |
|||
"""with a different account, OpenERP will send an email """ |
|||
"""to the admin user.""", |
|||
), |
|||
'auth_admin_passkey_send_to_user': fields.boolean( |
|||
string='Send email to user.', |
|||
help="""When the administrator use his password to login in """ |
|||
"""with a different account, OpenERP will send an email """ |
|||
"""to the account user.""", |
|||
), |
|||
} |
@ -0,0 +1,137 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Admin Passkey module for OpenERP |
|||
# Copyright (C) 2013-2014 GRAP (http://www.grap.coop) |
|||
# @author Sylvain LE GAL (https://twitter.com/legalsylvain) |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
import datetime |
|||
|
|||
from openerp import SUPERUSER_ID |
|||
from openerp import pooler |
|||
from openerp import exceptions |
|||
from openerp.osv.orm import Model |
|||
from openerp.tools.translate import _ |
|||
from openerp.tools.safe_eval import safe_eval |
|||
|
|||
|
|||
class res_users(Model): |
|||
_inherit = "res.users" |
|||
|
|||
# Private Function section |
|||
def _get_translation(self, cr, lang, text): |
|||
context = {'lang': lang} # noqa: _() checks page for locals |
|||
return _(text) |
|||
|
|||
def _send_email_passkey(self, cr, user_id, user_agent_env): |
|||
""" Send a email to the admin of the system and / or the user |
|||
to inform passkey use.""" |
|||
mails = [] |
|||
mail_obj = self.pool['mail.mail'] |
|||
icp_obj = self.pool['ir.config_parameter'] |
|||
admin_user = self.browse(cr, SUPERUSER_ID, SUPERUSER_ID) |
|||
login_user = self.browse(cr, SUPERUSER_ID, user_id) |
|||
send_to_admin = safe_eval(icp_obj.get_param( |
|||
cr, SUPERUSER_ID, 'auth_admin_passkey.send_to_admin', 'True')) |
|||
send_to_user = safe_eval(icp_obj.get_param( |
|||
cr, SUPERUSER_ID, 'auth_admin_passkey.send_to_user', 'True')) |
|||
|
|||
if send_to_admin and admin_user.email: |
|||
mails.append({'email': admin_user.email, 'lang': admin_user.lang}) |
|||
if send_to_user and login_user.email: |
|||
mails.append({'email': login_user.email, 'lang': login_user.lang}) |
|||
|
|||
for mail in mails: |
|||
subject = self._get_translation( |
|||
cr, mail['lang'], _('Passkey used')) |
|||
body = self._get_translation( |
|||
cr, mail['lang'], |
|||
_("""Admin user used his passkey to login with '%s'.\n\n""" |
|||
"""\n\nTechnicals informations belows : \n\n""" |
|||
"""- Login date : %s\n\n""")) % ( |
|||
login_user.login, |
|||
datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")) |
|||
for k, v in user_agent_env.iteritems(): |
|||
body += ("- %s : %s\n\n") % (k, v) |
|||
mail_obj.create( |
|||
cr, SUPERUSER_ID, { |
|||
'email_to': mail['email'], |
|||
'subject': subject, |
|||
'body_html': '<pre>%s</pre>' % body}) |
|||
|
|||
def _send_email_same_password(self, cr, login_user): |
|||
""" Send a email to the admin user to inform that another user has the |
|||
same password as him.""" |
|||
mail_obj = self.pool['mail.mail'] |
|||
admin_user = self.browse(cr, SUPERUSER_ID, SUPERUSER_ID) |
|||
if admin_user.email: |
|||
mail_obj.create(cr, SUPERUSER_ID, { |
|||
'email_to': admin_user.email, |
|||
'subject': self._get_translation( |
|||
cr, admin_user.lang, _('[WARNING] OpenERP Security Risk')), |
|||
'body_html': self._get_translation( |
|||
cr, admin_user.lang, _( |
|||
"""<pre>User with login '%s' has the same """ |
|||
"""password as you.</pre>""")) % (login_user), |
|||
}) |
|||
|
|||
# Overload Section |
|||
def authenticate(self, db, login, password, user_agent_env): |
|||
""" Authenticate the user 'login' is password is ok or if |
|||
is admin password. In the second case, send mail to user and admin.""" |
|||
user_id = super(res_users, self).authenticate( |
|||
db, login, password, user_agent_env) |
|||
if user_id and (user_id != SUPERUSER_ID): |
|||
same_password = False |
|||
cr = pooler.get_db(db).cursor() |
|||
try: |
|||
# directly use parent 'check_credentials' function |
|||
# to really know if credentials are ok |
|||
# or if it was admin password |
|||
super(res_users, self).check_credentials( |
|||
cr, SUPERUSER_ID, password) |
|||
try: |
|||
# Test now if the user has the same password as admin user |
|||
super(res_users, self).check_credentials( |
|||
cr, user_id, password) |
|||
same_password = True |
|||
except exceptions.AccessDenied: |
|||
pass |
|||
if not same_password: |
|||
self._send_email_passkey(cr, user_id, user_agent_env) |
|||
else: |
|||
self._send_email_same_password(cr, login) |
|||
cr.commit() |
|||
except exceptions.AccessDenied: |
|||
pass |
|||
finally: |
|||
cr.close() |
|||
return user_id |
|||
|
|||
def check_credentials(self, cr, uid, password): |
|||
""" Return now True if credentials are good OR if password is admin |
|||
password.""" |
|||
if uid != SUPERUSER_ID: |
|||
try: |
|||
super(res_users, self).check_credentials( |
|||
cr, uid, password) |
|||
return True |
|||
except exceptions.AccessDenied: |
|||
return self.check_credentials(cr, SUPERUSER_ID, password) |
|||
else: |
|||
return super(res_users, self).check_credentials(cr, uid, password) |
After Width: 128 | Height: 128 | Size: 4.0 KiB |
@ -0,0 +1,23 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Admin Passkey module for OpenERP |
|||
# Copyright (C) 2013-2014 GRAP (http://www.grap.coop) |
|||
# @author Sylvain LE GAL (https://twitter.com/legalsylvain) |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
from . import test_auth_admin_passkey |
@ -0,0 +1,99 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Admin Passkey module for OpenERP |
|||
# Copyright (C) 2013-2014 GRAP (http://www.grap.coop) |
|||
# @author Sylvain LE GAL (https://twitter.com/legalsylvain) |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
import threading |
|||
|
|||
from openerp.tests.common import TransactionCase |
|||
|
|||
|
|||
class TestAuthAdminPasskey(TransactionCase): |
|||
"""Tests for 'Auth Admin Passkey' Module""" |
|||
|
|||
# Overload Section |
|||
def setUp(self): |
|||
super(TestAuthAdminPasskey, self).setUp() |
|||
|
|||
# Get Registries |
|||
self.imd_obj = self.registry('ir.model.data') |
|||
self.ru_obj = self.registry('res.users') |
|||
|
|||
# Get Database name |
|||
self.db = threading.current_thread().dbname |
|||
|
|||
# Get ids from xml_ids |
|||
self.admin_user_id = self.imd_obj.get_object_reference( |
|||
self.cr, self.uid, 'base', 'user_root')[1] |
|||
self.demo_user_id = self.imd_obj.get_object_reference( |
|||
self.cr, self.uid, 'base', 'user_demo')[1] |
|||
|
|||
# Test Section |
|||
def test_01_normal_login_admin_succeed(self): |
|||
"""[Regression Test] |
|||
Test the succeed of login with 'admin' / 'admin'""" |
|||
res = self.ru_obj.authenticate(self.db, 'admin', 'admin', {}) |
|||
self.assertEqual( |
|||
res, self.admin_user_id, |
|||
"'admin' / 'admin' login must succeed.") |
|||
|
|||
def test_02_normal_login_admin_fail(self): |
|||
"""[Regression Test] |
|||
Test the fail of login with 'admin' / 'bad_password'""" |
|||
res = self.ru_obj.authenticate(self.db, 'admin', 'bad_password', {}) |
|||
self.assertEqual( |
|||
res, False, |
|||
"'admin' / 'bad_password' login must fail.") |
|||
|
|||
def test_03_normal_login_demo_succeed(self): |
|||
"""[Regression Test] |
|||
Test the succeed of login with 'demo' / 'demo'""" |
|||
res = self.ru_obj.authenticate(self.db, 'demo', 'demo', {}) |
|||
self.assertEqual( |
|||
res, self.demo_user_id, |
|||
"'demo' / 'demo' login must succeed.") |
|||
|
|||
def test_04_normal_login_demo_fail(self): |
|||
"""[Regression Test] |
|||
Test the fail of login with 'demo' / 'bad_password'""" |
|||
res = self.ru_obj.authenticate(self.db, 'demo', 'bad_password', {}) |
|||
self.assertEqual( |
|||
res, False, |
|||
"'demo' / 'bad_password' login must fail.") |
|||
|
|||
def test_05_passkey_login_demo_succeed(self): |
|||
"""[New Feature] |
|||
Test the succeed of login with 'demo' / 'admin'""" |
|||
res = self.ru_obj.authenticate(self.db, 'demo', 'admin', {}) |
|||
self.assertEqual( |
|||
res, self.demo_user_id, |
|||
"'demo' / 'admin' login must succeed.") |
|||
|
|||
def test_06_passkey_login_demo_succeed(self): |
|||
"""[Bug #1319391] |
|||
Test the correct behaviour of login with 'bad_login' / 'admin'""" |
|||
exception_raised = False |
|||
try: |
|||
self.ru_obj.authenticate(self.db, 'bad_login', 'admin', {}) |
|||
except: |
|||
exception_raised = True |
|||
self.assertEqual( |
|||
exception_raised, False, |
|||
"'bad_login' / 'admin' musn't raise Error.") |
@ -0,0 +1,47 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!-- ********************************************************************** --> |
|||
<!--Admin Passkey module for OpenERP --> |
|||
<!--Copyright (C) 2013-2014 GRAP (http://www.grap.coop) --> |
|||
<!--@author Sylvain LE GAL (https://twitter.com/legalsylvain) --> |
|||
|
|||
<!--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 <http://www.gnu.org/licenses/>. --> |
|||
<!-- ********************************************************************** --> |
|||
<openerp> |
|||
<data> |
|||
|
|||
<record id="view_res_config_settings" model="ir.ui.view"> |
|||
<field name="name">base.config.settings.view</field> |
|||
<field name="model">base.config.settings</field> |
|||
<field name="inherit_id" ref="base_setup.view_general_configuration"/> |
|||
<field name="arch" type="xml"> |
|||
<xpath expr="//label[@string='Email']/.." position='after'> |
|||
<group> |
|||
<label for="id" string="Passkey"/> |
|||
<div> |
|||
<div> |
|||
<field name="auth_admin_passkey_send_to_admin" class="oe_inline"/> |
|||
<label for="auth_admin_passkey_send_to_admin"/> |
|||
</div> |
|||
<div> |
|||
<field name="auth_admin_passkey_send_to_user" class="oe_inline"/> |
|||
<label for="auth_admin_passkey_send_to_user"/> |
|||
</div> |
|||
</div> |
|||
</group> |
|||
</xpath> |
|||
</field> |
|||
</record> |
|||
|
|||
</data> |
|||
</openerp> |
@ -0,0 +1,56 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# This module copyright (C) 2014 Therp BV (<http://therp.nl>). |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
from openerp.addons.web.http import WebRequest, JsonRequest |
|||
from openerp.addons.web.controllers import main as web_main |
|||
|
|||
old_init = WebRequest.init |
|||
|
|||
|
|||
def init(self, params): |
|||
old_init(self, params) |
|||
if self.httprequest.authorization and not self.session._login: |
|||
dbs = web_main.db_list(self) |
|||
self.session.authenticate( |
|||
dbs and dbs[0], |
|||
self.httprequest.authorization.username, |
|||
self.httprequest.authorization.password, |
|||
dict( |
|||
base_location=self.httprequest.url_root.rstrip('/'), |
|||
HTTP_HOST=self.httprequest.environ['HTTP_HOST'], |
|||
REMOTE_ADDR=self.httprequest.environ['REMOTE_ADDR'] |
|||
) |
|||
) |
|||
|
|||
WebRequest.init = init |
|||
|
|||
old_dispatch = JsonRequest.dispatch |
|||
|
|||
|
|||
def dispatch(self, method): |
|||
response = old_dispatch(self, method) |
|||
if method.im_func == web_main.Session.destroy.im_func: |
|||
response.status = '301 logout' |
|||
response.headers.add( |
|||
'Location', |
|||
self.httprequest.url.replace('://', '://logout@')) |
|||
return response |
|||
|
|||
JsonRequest.dispatch = dispatch |
@ -0,0 +1,62 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# This module copyright (C) 2014 Therp BV (<http://therp.nl>). |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
{ |
|||
"name": "Authenticate via HTTP basic authentication", |
|||
"version": "1.0", |
|||
"author": "Therp BV", |
|||
"complexity": "expert", |
|||
"description": """ |
|||
In an environment where several web applications authenticate against the same |
|||
source, the simplest way to attain single sign on would be to have the |
|||
webserver handle authentication and pass the login information via HTTP headers |
|||
to the application it proxies. |
|||
|
|||
This addon allows for this setup. Technically, it picks up the HTTP |
|||
Authorization header, extracts a username and a password and tries to login |
|||
into the first database found in the database list. |
|||
|
|||
If you have to set a specific database, possibly depending on the login |
|||
provided, use the addon dbfilter_from_header. |
|||
|
|||
The addon has to be loaded as server-wide module. |
|||
|
|||
|
|||
Funders: |
|||
|
|||
Open2bizz software & consultancy |
|||
""", |
|||
"category": "", |
|||
"depends": [ |
|||
], |
|||
"data": [ |
|||
], |
|||
"js": [ |
|||
], |
|||
"css": [ |
|||
], |
|||
"qweb": [ |
|||
], |
|||
"auto_install": False, |
|||
"installable": True, |
|||
"external_dependencies": { |
|||
'python': [], |
|||
}, |
|||
} |
@ -0,0 +1,20 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# This module copyright (C) 2014 Therp BV (<http://therp.nl>). |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
@ -0,0 +1,57 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# This module copyright (C) 2014 Therp BV (<http://therp.nl>). |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
{ |
|||
"name": "Authenticate via HTTP basic authentication (logout helper)", |
|||
"version": "1.0", |
|||
"author": "Therp BV", |
|||
"complexity": "expert", |
|||
"description": """ |
|||
With auth_from_http_basic, the logout procedure has to be bent a bit to provide |
|||
a good user experience. As the former has to be a server wide module, this is |
|||
the clientside complement which provides the javascript part. |
|||
|
|||
The addon has to be installed in the database in use. |
|||
|
|||
|
|||
Funders: |
|||
|
|||
Open2bizz software & consultancy |
|||
""", |
|||
"category": "", |
|||
"depends": [ |
|||
'web', |
|||
'auth_from_http_basic', |
|||
], |
|||
"data": [ |
|||
], |
|||
"js": [ |
|||
'static/src/js/auth_from_http_basic_logout.js', |
|||
], |
|||
"css": [ |
|||
], |
|||
"qweb": [ |
|||
], |
|||
"auto_install": False, |
|||
"installable": True, |
|||
"external_dependencies": { |
|||
'python': [], |
|||
}, |
|||
} |
@ -0,0 +1,23 @@ |
|||
# Translation of OpenERP Server. |
|||
# This file contains the translation of the following modules: |
|||
# |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: OpenERP Server 7.0\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2014-01-18 16:31+0000\n" |
|||
"PO-Revision-Date: 2014-01-18 16:31+0000\n" |
|||
"Last-Translator: <>\n" |
|||
"Language-Team: \n" |
|||
"MIME-Version: 1.0\n" |
|||
"Content-Type: text/plain; charset=UTF-8\n" |
|||
"Content-Transfer-Encoding: \n" |
|||
"Plural-Forms: \n" |
|||
|
|||
#. module: auth_from_http_basic_logout |
|||
#. openerp-web |
|||
#: code:addons/auth_from_http_basic_logout/static/src/js/auth_from_http_basic_logout.js:37 |
|||
#, python-format |
|||
msgid "<p style=\"background: white\">You have been logged out successfully. <a href=\"#\">Click here to log in again.</a></p>" |
|||
msgstr "" |
|||
|
@ -0,0 +1,27 @@ |
|||
# Translation of OpenERP Server. |
|||
# This file contains the translation of the following modules: |
|||
# |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: OpenERP Server 7.0\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2014-01-18 16:31+0000\n" |
|||
"PO-Revision-Date: 2014-04-03 05:38+0000\n" |
|||
"Last-Translator: Holger Brunn (Therp) <hbrunn@therp.nl>\n" |
|||
"Language-Team: \n" |
|||
"MIME-Version: 1.0\n" |
|||
"Content-Type: text/plain; charset=UTF-8\n" |
|||
"Content-Transfer-Encoding: 8bit\n" |
|||
"X-Launchpad-Export-Date: 2014-05-24 06:46+0000\n" |
|||
"X-Generator: Launchpad (build 17017)\n" |
|||
|
|||
#. module: auth_from_http_basic_logout |
|||
#. openerp-web |
|||
#: code:addons/auth_from_http_basic_logout/static/src/js/auth_from_http_basic_logout.js:37 |
|||
#, python-format |
|||
msgid "" |
|||
"<p style=\"background: white\">You have been logged out successfully. <a " |
|||
"href=\"#\">Click here to log in again.</a></p>" |
|||
msgstr "" |
|||
"<p style=\"background: white\">U bent afgemeld. <a href=\"#\">Klik hier om " |
|||
"weer in te loggen.</a></p>" |
After Width: 80 | Height: 80 | Size: 7.8 KiB |
@ -0,0 +1,48 @@ |
|||
//-*- coding: utf-8 -*-
|
|||
//############################################################################
|
|||
//
|
|||
// OpenERP, Open Source Management Solution
|
|||
// This module copyright (C) 2014 Therp BV (<http://therp.nl>).
|
|||
//
|
|||
// 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 <http://www.gnu.org/licenses/>.
|
|||
//
|
|||
//############################################################################
|
|||
|
|||
openerp.auth_from_http_basic_logout = function(openerp) |
|||
{ |
|||
openerp.web.Session.include({ |
|||
session_logout: function() |
|||
{ |
|||
var deferred = this._super(this, arguments); |
|||
deferred.fail(function(error, ev) |
|||
{ |
|||
ev.preventDefault(); |
|||
openerp.web.blockUI(); |
|||
jQuery('.openerp_webclient_container').remove(); |
|||
jQuery('.oe_blockui_spin_container') |
|||
.empty() |
|||
.html( |
|||
_.string.sprintf( |
|||
openerp.web._t( |
|||
'<p style="background: white">You have been logged out successfully. <a href="#">Click here to log in again.</a></p>') |
|||
)) |
|||
.click(function() |
|||
{ |
|||
window.location.reload(); |
|||
}); |
|||
}); |
|||
return deferred; |
|||
} |
|||
}); |
|||
} |
@ -0,0 +1,24 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Daniel Reis |
|||
# 2011 |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
from . import base_external_dbsource |
|||
|
|||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
@ -0,0 +1,66 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Daniel Reis, 2011 |
|||
# Additional contributions by Maxime Chambreuil, Savoir-faire Linux |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
{ |
|||
'name': 'External Database Sources', |
|||
'version': '1.3', |
|||
'category': 'Tools', |
|||
'description': """ |
|||
This module allows you to define connections to foreign databases using ODBC, |
|||
Oracle Client or SQLAlchemy. |
|||
|
|||
Database sources can be configured in Settings > Configuration -> Data sources. |
|||
|
|||
Depending on the database, you need: |
|||
* to install unixodbc and python-pyodbc packages to use ODBC connections. |
|||
* to install FreeTDS driver (tdsodbc package) and configure it through ODBC to |
|||
connect to Microsoft SQL Server. |
|||
* to install and configure Oracle Instant Client and cx_Oracle python library |
|||
to connect to Oracle. |
|||
|
|||
Contributors |
|||
============ |
|||
|
|||
* Maxime Chambreuil <maxime.chambreuil@savoirfairelinux.com> |
|||
""", |
|||
'author': 'Daniel Reis', |
|||
'website': 'http://launchpad.net/addons-tko', |
|||
'images': [ |
|||
'images/screenshot01.png', |
|||
], |
|||
'depends': [ |
|||
'base', |
|||
], |
|||
'data': [ |
|||
'base_external_dbsource_view.xml', |
|||
'security/ir.model.access.csv', |
|||
], |
|||
'demo': [ |
|||
'base_external_dbsource_demo.xml', |
|||
], |
|||
'test': [ |
|||
'test/dbsource_connect.yml', |
|||
], |
|||
'installable': False, |
|||
'active': False, |
|||
} |
|||
|
|||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
@ -0,0 +1,175 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Daniel Reis |
|||
# 2011 |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
import os |
|||
import logging |
|||
from openerp.osv import orm, fields |
|||
from openerp.tools.translate import _ |
|||
import openerp.tools as tools |
|||
_logger = logging.getLogger(__name__) |
|||
|
|||
CONNECTORS = [] |
|||
|
|||
try: |
|||
import sqlalchemy |
|||
CONNECTORS.append(('sqlite', 'SQLite')) |
|||
try: |
|||
import pymssql |
|||
CONNECTORS.append(('mssql', 'Microsoft SQL Server')) |
|||
assert pymssql |
|||
except (ImportError, AssertionError): |
|||
_logger.info('MS SQL Server not available. Please install "pymssql"\ |
|||
python package.') |
|||
try: |
|||
import MySQLdb |
|||
CONNECTORS.append(('mysql', 'MySQL')) |
|||
assert MySQLdb |
|||
except (ImportError, AssertionError): |
|||
_logger.info('MySQL not available. Please install "mysqldb"\ |
|||
python package.') |
|||
except: |
|||
_logger.info('SQL Alchemy not available. Please install "slqalchemy"\ |
|||
python package.') |
|||
try: |
|||
import pyodbc |
|||
CONNECTORS.append(('pyodbc', 'ODBC')) |
|||
except: |
|||
_logger.info('ODBC libraries not available. Please install "unixodbc"\ |
|||
and "python-pyodbc" packages.') |
|||
|
|||
try: |
|||
import cx_Oracle |
|||
CONNECTORS.append(('cx_Oracle', 'Oracle')) |
|||
except: |
|||
_logger.info('Oracle libraries not available. Please install "cx_Oracle"\ |
|||
python package.') |
|||
|
|||
import psycopg2 |
|||
CONNECTORS.append(('postgresql', 'PostgreSQL')) |
|||
|
|||
|
|||
class base_external_dbsource(orm.Model): |
|||
_name = "base.external.dbsource" |
|||
_description = 'External Database Sources' |
|||
_columns = { |
|||
'name': fields.char('Datasource name', required=True, size=64), |
|||
'conn_string': fields.text('Connection string', help=""" |
|||
Sample connection strings: |
|||
- Microsoft SQL Server: |
|||
mssql+pymssql://username:%s@server:port/dbname?charset=utf8 |
|||
- MySQL: mysql://user:%s@server:port/dbname |
|||
- ODBC: DRIVER={FreeTDS};SERVER=server.address;Database=mydb;UID=sa |
|||
- ORACLE: username/%s@//server.address:port/instance |
|||
- PostgreSQL: |
|||
dbname='template1' user='dbuser' host='localhost' port='5432' password=%s |
|||
- SQLite: sqlite:///test.db |
|||
"""), |
|||
'password': fields.char('Password', size=40), |
|||
'connector': fields.selection(CONNECTORS, 'Connector', |
|||
required=True, |
|||
help="If a connector is missing from the\ |
|||
list, check the server log to confirm\ |
|||
that the required components were\ |
|||
detected."), |
|||
} |
|||
|
|||
def conn_open(self, cr, uid, id1): |
|||
# Get dbsource record |
|||
data = self.browse(cr, uid, id1) |
|||
# Build the full connection string |
|||
connStr = data.conn_string |
|||
if data.password: |
|||
if '%s' not in data.conn_string: |
|||
connStr += ';PWD=%s' |
|||
connStr = connStr % data.password |
|||
# Try to connect |
|||
if data.connector == 'cx_Oracle': |
|||
os.environ['NLS_LANG'] = 'AMERICAN_AMERICA.UTF8' |
|||
conn = cx_Oracle.connect(connStr) |
|||
elif data.connector == 'pyodbc': |
|||
conn = pyodbc.connect(connStr) |
|||
elif data.connector in ('sqlite', 'mysql', 'mssql'): |
|||
conn = sqlalchemy.create_engine(connStr).connect() |
|||
elif data.connector == 'postgresql': |
|||
conn = psycopg2.connect(connStr) |
|||
|
|||
return conn |
|||
|
|||
def execute(self, cr, uid, ids, sqlquery, sqlparams=None, metadata=False, |
|||
context=None): |
|||
"""Executes SQL and returns a list of rows. |
|||
|
|||
"sqlparams" can be a dict of values, that can be referenced in |
|||
the SQL statement using "%(key)s" or, in the case of Oracle, |
|||
":key". |
|||
Example: |
|||
sqlquery = "select * from mytable where city = %(city)s and |
|||
date > %(dt)s" |
|||
params = {'city': 'Lisbon', |
|||
'dt': datetime.datetime(2000, 12, 31)} |
|||
|
|||
If metadata=True, it will instead return a dict containing the |
|||
rows list and the columns list, in the format: |
|||
{ 'cols': [ 'col_a', 'col_b', ...] |
|||
, 'rows': [ (a0, b0, ...), (a1, b1, ...), ...] } |
|||
""" |
|||
data = self.browse(cr, uid, ids) |
|||
rows, cols = list(), list() |
|||
for obj in data: |
|||
conn = self.conn_open(cr, uid, obj.id) |
|||
if obj.connector in ["sqlite", "mysql", "mssql"]: |
|||
# using sqlalchemy |
|||
cur = conn.execute(sqlquery, sqlparams) |
|||
if metadata: |
|||
cols = cur.keys() |
|||
rows = [r for r in cur] |
|||
else: |
|||
# using other db connectors |
|||
cur = conn.cursor() |
|||
cur.execute(sqlquery, sqlparams) |
|||
if metadata: |
|||
cols = [d[0] for d in cur.description] |
|||
rows = cur.fetchall() |
|||
conn.close() |
|||
if metadata: |
|||
return{'cols': cols, 'rows': rows} |
|||
else: |
|||
return rows |
|||
|
|||
def connection_test(self, cr, uid, ids, context=None): |
|||
for obj in self.browse(cr, uid, ids, context): |
|||
conn = False |
|||
try: |
|||
conn = self.conn_open(cr, uid, obj.id) |
|||
except Exception as e: |
|||
raise orm.except_orm(_("Connection test failed!"), |
|||
_("Here is what we got instead:\n %s") |
|||
% tools.ustr(e)) |
|||
finally: |
|||
try: |
|||
if conn: |
|||
conn.close() |
|||
except Exception: |
|||
# ignored, just a consequence of the previous exception |
|||
pass |
|||
# TODO: if OK a (wizard) message box should be displayed |
|||
raise orm.except_orm(_("Connection test succeeded!"), |
|||
_("Everything seems properly set up!")) |
@ -0,0 +1,15 @@ |
|||
<?xml version="1.0"?> |
|||
<openerp> |
|||
<data> |
|||
|
|||
<record model="base.external.dbsource" id="demo_postgre"> |
|||
<field name="name">PostgreSQL local</field> |
|||
<field name="conn_string">dbname='postgres' password=%s</field> |
|||
<field name="password">postgresql</field> |
|||
<field name="connector">postgresql</field> |
|||
</record> |
|||
|
|||
</data> |
|||
</openerp> |
|||
|
|||
|
@ -0,0 +1,54 @@ |
|||
<?xml version="1.0"?> |
|||
<openerp> |
|||
<data> |
|||
|
|||
<!-- DBSource --> |
|||
|
|||
<record model="ir.ui.view" id="view_dbsource_tree"> |
|||
<field name="name">base.external.dbsource.tree</field> |
|||
<field name="model">base.external.dbsource</field> |
|||
<field name="type">tree</field> |
|||
<field name="arch" type="xml"> |
|||
<tree string="External DB Sources"> |
|||
<field name="name"/> |
|||
<field name="connector"/> |
|||
<field name="conn_string"/> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.ui.view" id="view_dbsource_form"> |
|||
<field name="name">base.external.dbsource.form</field> |
|||
<field name="model">base.external.dbsource</field> |
|||
<field name="type">form</field> |
|||
<field name="arch" type="xml"> |
|||
<form string="External DB Source"> |
|||
<field name="name"/> |
|||
<field name="password" password="True"/> |
|||
<newline/> |
|||
<field name="connector" colspan="2"/> |
|||
<newline/> |
|||
<field name="conn_string" colspan="4"/> |
|||
<newline/> |
|||
<button name="connection_test" string="Test Connection" type="object" icon="gtk-network" colspan="4"/> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.actions.act_window" id="action_dbsource"> |
|||
<field name="name">External Database Sources</field> |
|||
<field name="res_model">base.external.dbsource</field> |
|||
<field name="view_type">form</field> |
|||
<field name="view_mode">tree,form</field> |
|||
<field name="view_id" ref="view_dbsource_tree"/> |
|||
</record> |
|||
|
|||
<menuitem name="Database Sources" |
|||
id="menu_dbsource" |
|||
parent="base.next_id_9" |
|||
action="action_dbsource"/> |
|||
|
|||
</data> |
|||
</openerp> |
|||
|
|||
|
After Width: 960 | Height: 281 | Size: 31 KiB |
@ -0,0 +1,2 @@ |
|||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink |
|||
access_base_external_dbsource_group_system,bae_external_dbsource_group_system,model_base_external_dbsource,base.group_system,1,1,1,1 |
@ -0,0 +1,9 @@ |
|||
- |
|||
Connect to local Postgres. |
|||
- |
|||
!python {model: base.external.dbsource}: | |
|||
from openerp.osv.orm import except_orm |
|||
try: |
|||
self.connection_test(cr, uid, [ref("demo_postgre")]) |
|||
except except_orm as e: |
|||
assert e.value == u'Everything seems properly set up!' |
@ -0,0 +1,22 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Author: David BEAL |
|||
# Copyright 2014 Akretion |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
from . import config # noqa |
@ -0,0 +1,82 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Author: David BEAL |
|||
# Copyright 2014 Akretion |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
{ |
|||
'name': 'Configuration Helper', |
|||
'version': '0.8', |
|||
'author': 'Akretion', |
|||
'maintainer': 'Akretion', |
|||
'category': 'server', |
|||
'complexity': 'normal', |
|||
'depends': ['base'], |
|||
'description': """ |
|||
Configuration Helper |
|||
==================== |
|||
|
|||
*This module is intended for developer only. It does nothing used alone.* |
|||
|
|||
This module : |
|||
|
|||
* create automatically related fields in 'whatiwant.config.settings' |
|||
using those defined in 'res.company' : it avoid duplicated field definitions. |
|||
* company_id field with default value is created |
|||
* onchange_company_id is defined to update all related fields |
|||
* supported fields: char, text, integer, float, datetime, date, boolean, m2o |
|||
|
|||
|
|||
How to use |
|||
---------- |
|||
|
|||
.. code-block:: python |
|||
|
|||
from . company import ResCompany |
|||
|
|||
class WhatiwantClassSettings(orm.TransientModel): |
|||
_inherit = ['res.config.settings', 'abstract.config.settings'] |
|||
_name = 'whatiwant.config.settings' |
|||
# fields must be defined in ResCompany class |
|||
# related fields are automatically generated from previous definitions |
|||
_companyObject = ResCompany |
|||
|
|||
|
|||
Roadmap |
|||
------- |
|||
* support (or check support) for these field types : o2m, m2m, reference, property, selection |
|||
* automatically generate a default view for 'whatiwant.config.settings' (in --debug ?) |
|||
|
|||
|
|||
Contributors |
|||
------------ |
|||
|
|||
* David BEAL <david.beal@akretion.com> |
|||
* Sébastien BEAU <sebastien.beau@akretion.com> |
|||
* Yannick Vaucher, Camptocamp, (code refactoring from his module 'delivery_carrier_label_postlogistics') |
|||
|
|||
""", |
|||
'website': 'http://www.akretion.com/', |
|||
'data': [ |
|||
], |
|||
'tests': [], |
|||
'installable': False, |
|||
'auto_install': False, |
|||
'license': 'AGPL-3', |
|||
'application': True, |
|||
} |
@ -0,0 +1,114 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Author: David BEAL, Copyright 2014 Akretion |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
import re |
|||
|
|||
from openerp.osv import orm, fields |
|||
|
|||
|
|||
class AbstractConfigSettings(orm.AbstractModel): |
|||
_name = 'abstract.config.settings' |
|||
_description = 'Abstract configuration settings' |
|||
# prefix field name to differentiate fields in company with those in config |
|||
_prefix = 'setting_' |
|||
# this is the class name to import in your module |
|||
# (it should be ResCompany or res_company, depends of your code) |
|||
_companyObject = None |
|||
|
|||
def _filter_field(self, field_key): |
|||
"""Inherit in your module to define for which company field |
|||
you don't want have a matching related field""" |
|||
return True |
|||
|
|||
def __init__(self, pool, cr): |
|||
super(AbstractConfigSettings, self).__init__(pool, cr) |
|||
if self._companyObject: |
|||
for field_key in self._companyObject._columns: |
|||
# allows to exclude some field |
|||
if self._filter_field(field_key): |
|||
args = ('company_id', field_key) |
|||
kwargs = { |
|||
'string': self._companyObject._columns[field_key].string, |
|||
'help': self._companyObject._columns[field_key].help, |
|||
'type': self._companyObject._columns[field_key]._type, |
|||
} |
|||
if '_obj' in self._companyObject._columns[field_key].__dict__.keys(): |
|||
kwargs['relation'] = \ |
|||
self._companyObject._columns[field_key]._obj |
|||
if '_domain' in \ |
|||
self._companyObject._columns[field_key].__dict__.keys(): |
|||
kwargs['domain'] = \ |
|||
self._companyObject._columns[field_key]._domain |
|||
field_key = re.sub('^' + self._prefix, '', field_key) |
|||
self._columns[field_key] = \ |
|||
fields.related(*args, **kwargs) |
|||
|
|||
_columns = { |
|||
'company_id': fields.many2one( |
|||
'res.company', |
|||
'Company', |
|||
required=True), |
|||
} |
|||
|
|||
def _default_company(self, cr, uid, context=None): |
|||
user = self.pool['res.users'].browse(cr, uid, uid, context=context) |
|||
return user.company_id.id |
|||
|
|||
_defaults = { |
|||
'company_id': _default_company, |
|||
} |
|||
|
|||
def field_to_populate_as_related(self, cr, uid, field, company_cols, context=None): |
|||
"""Only fields which comes from company with the right prefix |
|||
must be defined as related""" |
|||
if self._prefix + field in company_cols: |
|||
return True |
|||
return False |
|||
|
|||
def onchange_company_id(self, cr, uid, ids, company_id, context=None): |
|||
" update related fields " |
|||
values = {} |
|||
values['currency_id'] = False |
|||
if not company_id: |
|||
return {'value': values} |
|||
company_m = self.pool['res.company'] |
|||
company = company_m.browse( |
|||
cr, uid, company_id, context=context) |
|||
company_cols = company_m._columns.keys() |
|||
for field in self._columns: |
|||
if self.field_to_populate_as_related( |
|||
cr, uid, field, company_cols, context=context): |
|||
cpny_field = self._columns[field].arg[-1] |
|||
if self._columns[field]._type == 'many2one': |
|||
values[field] = company[cpny_field]['id'] or False |
|||
else: |
|||
values[field] = company[cpny_field] |
|||
return {'value': values} |
|||
|
|||
def create(self, cr, uid, values, context=None): |
|||
id = super(AbstractConfigSettings, self).create( |
|||
cr, uid, values, context=context) |
|||
# Hack: to avoid some nasty bug, related fields are not written |
|||
# upon record creation. Hence we write on those fields here. |
|||
vals = {} |
|||
for fname, field in self._columns.iteritems(): |
|||
if isinstance(field, fields.related) and fname in values: |
|||
vals[fname] = values[fname] |
|||
self.write(cr, uid, [id], vals, context) |
|||
return id |
@ -0,0 +1 @@ |
|||
import model |
@ -0,0 +1,105 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# This module copyright (C) 2013 Therp BV (<http://therp.nl>). |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
{ |
|||
"name": "Templates for email templates", |
|||
"version": "1.0", |
|||
"author": "Therp BV", |
|||
"category": 'Tools', |
|||
'complexity': "expert", |
|||
"description": """If an organisation's email layout is a bit more |
|||
complicated, changes can be tedious when having to do that across several email |
|||
templates. So this addon allows to define templates for mails that is referenced |
|||
by other mail templates. |
|||
This way we can put the layout parts into the template template and only content |
|||
in the other templates. Changing the layout is then only a matter of changing |
|||
the template template. |
|||
|
|||
----- |
|||
Usage |
|||
----- |
|||
Create an email template with the related document model 'Email Templates'. Now |
|||
most of the fields gray out and you can only edit body_text and body_html. Be |
|||
sure to use ${body_text} and ${body_html} respectively in your template |
|||
template. |
|||
|
|||
Then select this newly created template templates in one of your actual |
|||
templates. |
|||
|
|||
For example, create a template template |
|||
|
|||
:: |
|||
|
|||
Example Corp logo |
|||
Example Corp header |
|||
${object.body_text} <- this gets evaluated to the body_text of a template using this template template |
|||
Example Corp |
|||
Example street 42 |
|||
Example city |
|||
Example Corp footer |
|||
|
|||
Then in your template you write |
|||
|
|||
:: |
|||
|
|||
Dear ${object.partner_id.name}, |
|||
|
|||
Your order has been booked on date ${object.date} for a total amount of ${object.sum}. |
|||
|
|||
And it will be evaluated to |
|||
|
|||
:: |
|||
|
|||
Example Corp logo |
|||
Example Corp header |
|||
Dear Jane Doe, |
|||
|
|||
Your order has been booked on date 04/17/2013 for a total amount of 42. |
|||
Example Corp |
|||
Example street 42 |
|||
Example city |
|||
Example Corp footer |
|||
|
|||
Given the way evaluation works internally (body_text of the template template |
|||
is evaluated two times, first with the instance of email.template of your own |
|||
template, then with the object your template refers to), you can do some |
|||
trickery if you know that a template template is always used with the same |
|||
kind of model (that is, models that have the same field name): |
|||
|
|||
In your template template: |
|||
|
|||
:: |
|||
|
|||
Dear ${'${object.name}'}, <-- gets evaluated to "${object.name}" in the |
|||
first step, then to the content of object.name |
|||
${object.body_html} |
|||
Best, |
|||
Example Corp |
|||
""", |
|||
'website': 'http://therp.nl', |
|||
'images': [], |
|||
'depends': ['email_template'], |
|||
'data': [ |
|||
'view/email_template.xml', |
|||
], |
|||
"license": 'AGPL-3', |
|||
'installable': False, |
|||
} |
|||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
@ -0,0 +1,16 @@ |
|||
# Translation of OpenERP Server. |
|||
# This file contains the translation of the following modules: |
|||
# |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: OpenERP Server 7.0\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2014-03-14 17:41+0000\n" |
|||
"PO-Revision-Date: 2014-03-14 17:41+0000\n" |
|||
"Last-Translator: <>\n" |
|||
"Language-Team: \n" |
|||
"MIME-Version: 1.0\n" |
|||
"Content-Type: text/plain; charset=UTF-8\n" |
|||
"Content-Transfer-Encoding: \n" |
|||
"Plural-Forms: \n" |
|||
|
@ -0,0 +1,21 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# This module copyright (C) 2013 Therp BV (<http://therp.nl>). |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
import email_template |
@ -0,0 +1,61 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# This module copyright (C) 2013 Therp BV (<http://therp.nl>). |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
from openerp.osv.orm import Model |
|||
from openerp.osv import fields |
|||
from openerp.addons.email_template.email_template import mako_template_env |
|||
|
|||
|
|||
class email_template(Model): |
|||
_inherit = 'email.template' |
|||
|
|||
def _get_is_template_template(self, cr, uid, ids, fields_name, arg, |
|||
context=None): |
|||
cr.execute('''select |
|||
id, (select count(*) > 0 from email_template e |
|||
where email_template_id=email_template.id) |
|||
from email_template |
|||
where id in %s''', (tuple(ids),)) |
|||
return dict(cr.fetchall()) |
|||
|
|||
_columns = { |
|||
'email_template_id': fields.many2one('email.template', 'Template'), |
|||
'is_template_template': fields.function( |
|||
_get_is_template_template, type='boolean', |
|||
string='Is a template template'), |
|||
} |
|||
|
|||
def get_email_template(self, cr, uid, template_id=False, record_id=None, |
|||
context=None): |
|||
this = super(email_template, self).get_email_template( |
|||
cr, uid, template_id, record_id, context) |
|||
|
|||
if this.email_template_id and not this.is_template_template: |
|||
for field in ['body_html']: |
|||
if this[field] and this.email_template_id[field]: |
|||
try: |
|||
mako_template_env.autoescape = False |
|||
this._data[this.id][field] = self.render_template( |
|||
cr, uid, this.email_template_id[field], |
|||
this.email_template_id.model, |
|||
this.id, this._context) |
|||
finally: |
|||
mako_template_env.autoescape = True |
|||
return this |
@ -0,0 +1,70 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<openerp> |
|||
<data> |
|||
<record id="email_template_form" model="ir.ui.view"> |
|||
<field name="name">email.template.form</field> |
|||
<field name="model">email.template</field> |
|||
<field name="inherit_id" ref="email_template.email_template_form" /> |
|||
<field name="arch" type="xml"> |
|||
<data> |
|||
<field name="name" position="after"> |
|||
<field name="is_template_template" invisible="1" /> |
|||
<field name="email_template_id" domain="[('email_template_id', '=', False), ('model_id', '=', %(email_template.model_email_template)s)]" |
|||
attrs="{'readonly': [('is_template_template','=',True), ('email_template_id','=',False)]}" |
|||
context="{'default_model_id': %(email_template.model_email_template)s}" |
|||
/> |
|||
|
|||
</field> |
|||
<field name="model_id" position="attributes"> |
|||
<attribute name="attrs"> |
|||
{'readonly': [('is_template_template','=',True)]} |
|||
</attribute> |
|||
</field> |
|||
<field name="email_from" position="attributes"> |
|||
<attribute name="required">0</attribute> |
|||
<attribute name="attrs"> |
|||
{'readonly': ['|',('is_template_template','=',True),('model_id', '=', %(email_template.model_email_template)s)]} |
|||
</attribute> |
|||
</field> |
|||
<field name="email_to" position="attributes"> |
|||
<attribute name="required">0</attribute> |
|||
<attribute name="attrs"> |
|||
{'readonly': ['|',('is_template_template','=',True),('model_id', '=', %(email_template.model_email_template)s)]} |
|||
</attribute> |
|||
</field> |
|||
<field name="email_cc" position="attributes"> |
|||
<attribute name="attrs"> |
|||
{'readonly': ['|',('is_template_template','=',True),('model_id', '=', %(email_template.model_email_template)s)]} |
|||
</attribute> |
|||
</field> |
|||
<field name="email_recipients" position="attributes"> |
|||
<attribute name="attrs"> |
|||
{'readonly': ['|',('is_template_template','=',True),('model_id', '=', %(email_template.model_email_template)s)]} |
|||
</attribute> |
|||
</field> |
|||
<field name="reply_to" position="attributes"> |
|||
<attribute name="attrs"> |
|||
{'readonly': ['|',('is_template_template','=',True),('model_id', '=', %(email_template.model_email_template)s)]} |
|||
</attribute> |
|||
</field> |
|||
<field name="lang" position="attributes"> |
|||
<attribute name="attrs"> |
|||
{'readonly': ['|',('is_template_template','=',True),('model_id', '=', %(email_template.model_email_template)s)]} |
|||
</attribute> |
|||
</field> |
|||
<field name="user_signature" position="attributes"> |
|||
<attribute name="attrs"> |
|||
{'readonly': ['|',('is_template_template','=',True),('model_id', '=', %(email_template.model_email_template)s)]} |
|||
</attribute> |
|||
</field> |
|||
<field name="subject" position="attributes"> |
|||
<attribute name="required">0</attribute> |
|||
<attribute name="attrs"> |
|||
{'readonly': ['|',('is_template_template','=',True),('model_id', '=', %(email_template.model_email_template)s)]} |
|||
</attribute> |
|||
</field> |
|||
</data> |
|||
</field> |
|||
</record> |
|||
</data> |
|||
</openerp> |
@ -0,0 +1,25 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# This module copyright (C) 2013 Therp BV (<http://therp.nl>) |
|||
# All Rights Reserved |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
import match_algorithm |
|||
import model |
|||
import wizard |
@ -0,0 +1,46 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# This module copyright (C) 2013 Therp BV (<http://therp.nl>) |
|||
# All Rights Reserved |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
{ |
|||
'name': 'Attach mails in an IMAP folder to existing objects', |
|||
'version': '1.0', |
|||
'description': """ |
|||
Adds the possibility to attach emails from a certain IMAP folder to objects, |
|||
ie partners. Matching is done via several algorithms, ie email address. |
|||
|
|||
This gives a simple possibility to archive emails in OpenERP without a mail |
|||
client integration. |
|||
""", |
|||
'author': 'Therp BV', |
|||
'website': 'http://www.therp.nl', |
|||
"category": "Tools", |
|||
"depends": ['fetchmail'], |
|||
'data': [ |
|||
'view/fetchmail_server.xml', |
|||
'wizard/attach_mail_manually.xml', |
|||
'security/ir.model.access.csv', |
|||
], |
|||
'js': [], |
|||
'installable': False, |
|||
'active': False, |
|||
'certificate': '', |
|||
} |
@ -0,0 +1,26 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# This module copyright (C) 2013 Therp BV (<http://therp.nl>) |
|||
# All Rights Reserved |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
import base |
|||
import email_exact |
|||
import email_domain |
|||
import openerp_standard |
@ -0,0 +1,43 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# This module copyright (C) 2013 Therp BV (<http://therp.nl>) |
|||
# All Rights Reserved |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
|
|||
class base(object): |
|||
name = None |
|||
'''Name shown to the user''' |
|||
|
|||
required_fields = [] |
|||
'''Fields on fetchmail_server folder that are required for this algorithm''' |
|||
|
|||
readonly_fields = [] |
|||
'''Fields on fetchmail_server folder that are readonly for this algorithm''' |
|||
|
|||
def search_matches(self, cr, uid, conf, mail_message, mail_message_org): |
|||
'''Returns ids found for model with mail_message''' |
|||
return [] |
|||
|
|||
def handle_match( |
|||
self, cr, uid, connection, object_id, folder, |
|||
mail_message, mail_message_org, msgid, context=None): |
|||
'''Do whatever it takes to handle a match''' |
|||
return folder.server_id.attach_mail(connection, object_id, folder, |
|||
mail_message, msgid) |
@ -0,0 +1,45 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# This module copyright (C) 2013 Therp BV (<http://therp.nl>) |
|||
# All Rights Reserved |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
from email_exact import email_exact |
|||
|
|||
|
|||
class email_domain(email_exact): |
|||
'''Search objects by domain name of email address. |
|||
Beware of match_first here, this is most likely to get it wrong (gmail)''' |
|||
name = 'Domain of email address' |
|||
|
|||
def search_matches(self, cr, uid, conf, mail_message, mail_message_org): |
|||
ids = super(email_domain, self).search_matches( |
|||
cr, uid, conf, mail_message, mail_message_org) |
|||
if not ids: |
|||
domains = [] |
|||
for addr in self._get_mailaddresses(conf, mail_message): |
|||
domains.append(addr.split('@')[-1]) |
|||
ids = conf.pool.get(conf.model_id.model).search( |
|||
cr, uid, |
|||
self._get_mailaddress_search_domain( |
|||
conf, mail_message, |
|||
operator='like', |
|||
values=['%@'+domain for domain in set(domains)]), |
|||
order=conf.model_order) |
|||
return ids |
@ -0,0 +1,57 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# This module copyright (C) 2013 Therp BV (<http://therp.nl>) |
|||
# All Rights Reserved |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
from base import base |
|||
from openerp.tools.safe_eval import safe_eval |
|||
from openerp.tools.mail import email_split |
|||
|
|||
|
|||
class email_exact(base): |
|||
'''Search for exactly the mailadress as noted in the email''' |
|||
|
|||
name = 'Exact mailadress' |
|||
required_fields = ['model_field', 'mail_field'] |
|||
|
|||
def _get_mailaddresses(self, conf, mail_message): |
|||
mailaddresses = [] |
|||
fields = conf.mail_field.split(',') |
|||
for field in fields: |
|||
if field in mail_message: |
|||
mailaddresses += email_split(mail_message[field]) |
|||
return [addr.lower() for addr in mailaddresses] |
|||
|
|||
def _get_mailaddress_search_domain( |
|||
self, conf, mail_message, operator='=', values=None): |
|||
mailaddresses = values or self._get_mailaddresses( |
|||
conf, mail_message) |
|||
if not mailaddresses: |
|||
return [(0, '=', 1)] |
|||
search_domain = ((['|'] * (len(mailaddresses) - 1)) + [ |
|||
(conf.model_field, operator, addr) for addr in mailaddresses] + |
|||
safe_eval(conf.domain or '[]')) |
|||
return search_domain |
|||
|
|||
def search_matches(self, cr, uid, conf, mail_message, mail_message_org): |
|||
conf_model = conf.pool.get(conf.model_id.model) |
|||
search_domain = self._get_mailaddress_search_domain(conf, mail_message) |
|||
return conf_model.search( |
|||
cr, uid, search_domain, order=conf.model_order) |
@ -0,0 +1,58 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# This module copyright (C) 2013 Therp BV (<http://therp.nl>) |
|||
# All Rights Reserved |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
from base import base |
|||
|
|||
|
|||
class openerp_standard(base): |
|||
'''No search at all. Use OpenERP's standard mechanism to attach mails to |
|||
mail.thread objects. Note that this algorithm always matches.''' |
|||
|
|||
name = 'OpenERP standard' |
|||
readonly_fields = [ |
|||
'model_field', |
|||
'mail_field', |
|||
'match_first', |
|||
'domain', |
|||
'model_order', |
|||
'flag_nonmatching', |
|||
] |
|||
|
|||
def search_matches(self, cr, uid, conf, mail_message, mail_message_org): |
|||
'''Always match. Duplicates will be fished out by message_id''' |
|||
return [True] |
|||
|
|||
def handle_match( |
|||
self, cr, uid, connection, object_id, folder, |
|||
mail_message, mail_message_org, msgid, context): |
|||
result = folder.pool.get('mail.thread').message_process( |
|||
cr, uid, |
|||
folder.model_id.model, mail_message_org, |
|||
save_original=folder.server_id.original, |
|||
strip_attachments=(not folder.server_id.attach), |
|||
context=context |
|||
) |
|||
|
|||
if folder.delete_matching: |
|||
connection.store(msgid, '+FLAGS', '\\DELETED') |
|||
|
|||
return [result] |
@ -0,0 +1,24 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# This module copyright (C) 2013 Therp BV (<http://therp.nl>) |
|||
# All Rights Reserved |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
import fetchmail_server |
|||
import fetchmail_server_folder |
@ -0,0 +1,278 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# This module copyright (C) 2013 Therp BV (<http://therp.nl>) |
|||
# All Rights Reserved |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
import base64 |
|||
import simplejson |
|||
from lxml import etree |
|||
from openerp.osv.orm import Model, except_orm |
|||
from openerp.tools.translate import _ |
|||
from openerp.osv import fields |
|||
from openerp.addons.fetchmail.fetchmail import _logger as logger |
|||
from openerp.tools.misc import UnquoteEvalContext |
|||
|
|||
|
|||
class fetchmail_server(Model): |
|||
_inherit = 'fetchmail.server' |
|||
|
|||
_columns = { |
|||
'folder_ids': fields.one2many( |
|||
'fetchmail.server.folder', 'server_id', 'Folders'), |
|||
} |
|||
|
|||
_defaults = { |
|||
'type': 'imap', |
|||
} |
|||
|
|||
def __init__(self, pool, cr): |
|||
self._columns['object_id'].required = False |
|||
return super(fetchmail_server, self).__init__(pool, cr) |
|||
|
|||
def onchange_server_type( |
|||
self, cr, uid, ids, server_type=False, ssl=False, |
|||
object_id=False): |
|||
retval = super( |
|||
fetchmail_server, self).onchange_server_type(cr, uid, |
|||
ids, server_type, ssl, |
|||
object_id) |
|||
retval['value']['state'] = 'draft' |
|||
return retval |
|||
|
|||
def fetch_mail(self, cr, uid, ids, context=None): |
|||
if context is None: |
|||
context = {} |
|||
|
|||
check_original = [] |
|||
|
|||
for this in self.browse(cr, uid, ids, context): |
|||
if this.object_id: |
|||
check_original.append(this.id) |
|||
|
|||
context.update( |
|||
{ |
|||
'fetchmail_server_id': this.id, |
|||
'server_type': this.type |
|||
}) |
|||
|
|||
connection = this.connect() |
|||
for folder in this.folder_ids: |
|||
this.handle_folder(connection, folder) |
|||
|
|||
connection.close() |
|||
|
|||
return super(fetchmail_server, self).fetch_mail( |
|||
cr, uid, check_original, context) |
|||
|
|||
def handle_folder(self, cr, uid, ids, connection, folder, context=None): |
|||
'''Return ids of objects matched''' |
|||
|
|||
matched_object_ids = [] |
|||
|
|||
for this in self.browse(cr, uid, ids, context=context): |
|||
logger.info('start checking for emails in %s server %s', |
|||
folder.path, this.name) |
|||
|
|||
match_algorithm = folder.get_algorithm() |
|||
|
|||
if connection.select(folder.path)[0] != 'OK': |
|||
logger.error( |
|||
'Could not open mailbox %s on %s' % (folder.path, this.server)) |
|||
connection.select() |
|||
continue |
|||
result, msgids = this.get_msgids(connection) |
|||
if result != 'OK': |
|||
logger.error( |
|||
'Could not search mailbox %s on %s' % ( |
|||
folder.path, this.server)) |
|||
continue |
|||
|
|||
for msgid in msgids[0].split(): |
|||
matched_object_ids += this.apply_matching( |
|||
connection, folder, msgid, match_algorithm) |
|||
|
|||
logger.info('finished checking for emails in %s server %s', |
|||
folder.path, this.name) |
|||
|
|||
return matched_object_ids |
|||
|
|||
def get_msgids(self, cr, uid, ids, connection, context=None): |
|||
'''Return imap ids of messages to process''' |
|||
return connection.search(None, 'UNDELETED') |
|||
|
|||
def apply_matching(self, cr, uid, ids, connection, folder, msgid, |
|||
match_algorithm, context=None): |
|||
'''Return ids of objects matched''' |
|||
|
|||
matched_object_ids = [] |
|||
|
|||
for this in self.browse(cr, uid, ids, context=context): |
|||
result, msgdata = connection.fetch(msgid, '(RFC822)') |
|||
|
|||
if result != 'OK': |
|||
logger.error( |
|||
'Could not fetch %s in %s on %s' % (msgid, folder.path, this.server)) |
|||
continue |
|||
|
|||
mail_message = self.pool.get('mail.thread').message_parse( |
|||
cr, uid, msgdata[0][1], save_original=this.original, |
|||
context=context) |
|||
|
|||
if self.pool.get('mail.message').search( |
|||
cr, uid, [ |
|||
('message_id', '=', mail_message['message_id'])]): |
|||
continue |
|||
|
|||
found_ids = match_algorithm.search_matches( |
|||
cr, uid, folder, |
|||
mail_message, msgdata[0][1]) |
|||
|
|||
if found_ids and (len(found_ids) == 1 or |
|||
folder.match_first): |
|||
try: |
|||
cr.execute('savepoint apply_matching') |
|||
match_algorithm.handle_match( |
|||
cr, uid, connection, |
|||
found_ids[0], folder, mail_message, |
|||
msgdata[0][1], msgid, context) |
|||
cr.execute('release savepoint apply_matching') |
|||
matched_object_ids += found_ids[:1] |
|||
except Exception: |
|||
cr.execute('rollback to savepoint apply_matching') |
|||
logger.exception( |
|||
"Failed to fetch mail %s from %s", |
|||
msgid, this.name) |
|||
elif folder.flag_nonmatching: |
|||
connection.store(msgid, '+FLAGS', '\\FLAGGED') |
|||
|
|||
return matched_object_ids |
|||
|
|||
def attach_mail( |
|||
self, cr, uid, ids, connection, object_id, folder, |
|||
mail_message, msgid, context=None): |
|||
'''Return ids of messages created''' |
|||
|
|||
mail_message_ids = [] |
|||
|
|||
for this in self.browse(cr, uid, ids, context): |
|||
partner_id = None |
|||
if folder.model_id.model == 'res.partner': |
|||
partner_id = object_id |
|||
if 'partner_id' in self.pool.get(folder.model_id.model)._columns: |
|||
partner_id = self.pool.get( |
|||
folder.model_id.model).browse( |
|||
cr, uid, object_id, context |
|||
).partner_id.id |
|||
|
|||
attachments = [] |
|||
if this.attach and mail_message.get('attachments'): |
|||
for attachment in mail_message['attachments']: |
|||
fname, fcontent = attachment |
|||
if isinstance(fcontent, unicode): |
|||
fcontent = fcontent.encode('utf-8') |
|||
data_attach = { |
|||
'name': fname, |
|||
'datas': base64.b64encode(str(fcontent)), |
|||
'datas_fname': fname, |
|||
'description': _('Mail attachment'), |
|||
'res_model': folder.model_id.model, |
|||
'res_id': object_id, |
|||
} |
|||
attachments.append( |
|||
self.pool.get('ir.attachment').create( |
|||
cr, uid, data_attach, context=context)) |
|||
|
|||
mail_message_ids.append( |
|||
self.pool.get('mail.message').create( |
|||
cr, uid, |
|||
{ |
|||
'author_id': partner_id, |
|||
'model': folder.model_id.model, |
|||
'res_id': object_id, |
|||
'type': 'email', |
|||
'body': mail_message.get('body'), |
|||
'subject': mail_message.get('subject'), |
|||
'email_from': mail_message.get('from'), |
|||
'date': mail_message.get('date'), |
|||
'message_id': mail_message.get('message_id'), |
|||
'attachment_ids': [(6, 0, attachments)], |
|||
}, |
|||
context)) |
|||
|
|||
if folder.delete_matching: |
|||
connection.store(msgid, '+FLAGS', '\\DELETED') |
|||
return mail_message_ids |
|||
|
|||
def button_confirm_login(self, cr, uid, ids, context=None): |
|||
retval = super(fetchmail_server, self).button_confirm_login(cr, uid, |
|||
ids, |
|||
context) |
|||
|
|||
for this in self.browse(cr, uid, ids, context): |
|||
this.write({'state': 'draft'}) |
|||
connection = this.connect() |
|||
connection.select() |
|||
for folder in this.folder_ids: |
|||
if connection.select(folder.path)[0] != 'OK': |
|||
raise except_orm( |
|||
_('Error'), _('Mailbox %s not found!') % |
|||
folder.path) |
|||
connection.close() |
|||
this.write({'state': 'done'}) |
|||
|
|||
return retval |
|||
|
|||
def fields_view_get(self, cr, user, view_id=None, view_type='form', |
|||
context=None, toolbar=False, submenu=False): |
|||
result = super(fetchmail_server, self).fields_view_get( |
|||
cr, user, view_id, view_type, context, toolbar, submenu) |
|||
|
|||
if view_type == 'form': |
|||
view = etree.fromstring( |
|||
result['fields']['folder_ids']['views']['form']['arch']) |
|||
modifiers = {} |
|||
docstr = '' |
|||
for algorithm in self.pool.get('fetchmail.server.folder')\ |
|||
._get_match_algorithms().itervalues(): |
|||
for modifier in ['required', 'readonly']: |
|||
for field in getattr(algorithm, modifier + '_fields'): |
|||
modifiers.setdefault(field, {}) |
|||
modifiers[field].setdefault(modifier, []) |
|||
if modifiers[field][modifier]: |
|||
modifiers[field][modifier].insert(0, '|') |
|||
modifiers[field][modifier].append( |
|||
("match_algorithm", "==", algorithm.__name__)) |
|||
docstr += _(algorithm.name) + '\n' + _(algorithm.__doc__) + \ |
|||
'\n\n' |
|||
|
|||
for field in view: |
|||
if field.tag == 'field' and field.get('name') in modifiers: |
|||
field.set('modifiers', simplejson.dumps( |
|||
dict( |
|||
eval(field.attrib['modifiers'], |
|||
UnquoteEvalContext({})), |
|||
**modifiers[field.attrib['name']]))) |
|||
if (field.tag == 'field' and |
|||
field.get('name') == 'match_algorithm'): |
|||
field.set('help', docstr) |
|||
result['fields']['folder_ids']['views']['form']['arch'] = \ |
|||
etree.tostring(view) |
|||
|
|||
return result |
@ -0,0 +1,131 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# This module copyright (C) 2013 Therp BV (<http://therp.nl>) |
|||
# All Rights Reserved |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
######################################################################## |
|||
|
|||
from openerp.osv import fields |
|||
from openerp.osv.orm import Model |
|||
from .. import match_algorithm |
|||
|
|||
|
|||
class fetchmail_server_folder(Model): |
|||
_name = 'fetchmail.server.folder' |
|||
_rec_name = 'path' |
|||
|
|||
def _get_match_algorithms(self): |
|||
def get_all_subclasses(cls): |
|||
return cls.__subclasses__() + [subsub |
|||
for sub in cls.__subclasses__() |
|||
for subsub in get_all_subclasses(sub)] |
|||
return dict([(cls.__name__, cls) for cls in get_all_subclasses( |
|||
match_algorithm.base.base)]) |
|||
|
|||
def _get_match_algorithms_sel(self, cr, uid, context=None): |
|||
algorithms = [] |
|||
for cls in self._get_match_algorithms().itervalues(): |
|||
algorithms.append((cls.__name__, cls.name)) |
|||
algorithms.sort() |
|||
return algorithms |
|||
|
|||
_columns = { |
|||
'sequence': fields.integer('Sequence'), |
|||
'path': fields.char( |
|||
'Path', size=256, help='The path to your mail ' |
|||
"folder. Typically would be something like 'INBOX.myfolder'", |
|||
required=True |
|||
), |
|||
'model_id': fields.many2one( |
|||
'ir.model', 'Model', required=True, |
|||
help='The model to attach emails to' |
|||
), |
|||
'model_field': fields.char( |
|||
'Field (model)', size=128, |
|||
help='The field in your model that contains the field to match ' |
|||
'against.\n' |
|||
'Examples:\n' |
|||
"'email' if your model is res.partner, or " |
|||
"'partner_id.email' if you're matching sale orders" |
|||
), |
|||
'model_order': fields.char( |
|||
'Order (model)', size=128, |
|||
help='Fields to order by, this mostly useful in conjunction ' |
|||
"with 'Use 1st match'" |
|||
), |
|||
'match_algorithm': fields.selection( |
|||
_get_match_algorithms_sel, |
|||
'Match algorithm', required=True, translate=True, |
|||
help='The algorithm used to determine which object an email ' |
|||
'matches.' |
|||
), |
|||
'mail_field': fields.char( |
|||
'Field (email)', size=128, |
|||
help='The field in the email used for matching. Typically ' |
|||
"this is 'to' or 'from'" |
|||
), |
|||
'server_id': fields.many2one('fetchmail.server', 'Server'), |
|||
'delete_matching': fields.boolean( |
|||
'Delete matches', |
|||
help='Delete matched emails from server' |
|||
), |
|||
'flag_nonmatching': fields.boolean( |
|||
'Flag nonmatching', |
|||
help="Flag emails in the server that don't match any object " |
|||
'in OpenERP' |
|||
), |
|||
'match_first': fields.boolean( |
|||
'Use 1st match', |
|||
help='If there are multiple matches, use the first one. If ' |
|||
'not checked, multiple matches count as no match at all' |
|||
), |
|||
'domain': fields.char( |
|||
'Domain', size=128, help='Fill in a search ' |
|||
'filter to narrow down objects to match' |
|||
), |
|||
'msg_state': fields.selection( |
|||
[ |
|||
('sent', 'Sent'), |
|||
('received', 'Received'), |
|||
], |
|||
'Message state', |
|||
help='The state messages fetched from this folder should be ' |
|||
'assigned in OpenERP' |
|||
), |
|||
} |
|||
|
|||
_defaults = { |
|||
'flag_nonmatching': True, |
|||
'msg_state': 'received', |
|||
} |
|||
|
|||
def get_algorithm(self, cr, uid, ids, context=None): |
|||
for this in self.browse(cr, uid, ids, context): |
|||
return self._get_match_algorithms()[this.match_algorithm]() |
|||
|
|||
def button_attach_mail_manually(self, cr, uid, ids, context=None): |
|||
for this in self.browse(cr, uid, ids, context): |
|||
context.update({'default_folder_id': this.id}) |
|||
return { |
|||
'type': 'ir.actions.act_window', |
|||
'res_model': 'fetchmail.attach.mail.manually', |
|||
'target': 'new', |
|||
'context': context, |
|||
'view_type': 'form', |
|||
'view_mode': 'form', |
|||
} |
@ -0,0 +1,2 @@ |
|||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink |
|||
access_model_fetchmail_server_folder,fetchmail.server.folder,model_fetchmail_server_folder,base.group_system,1,1,1,1 |
@ -0,0 +1,56 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<openerp> |
|||
<data> |
|||
<record model="ir.ui.view" id="view_email_server_form"> |
|||
<field name="name">fetchmail.server.form</field> |
|||
<field name="model">fetchmail.server</field> |
|||
<field name="inherit_id" ref="fetchmail.view_email_server_form" /> |
|||
<field name="arch" type="xml"> |
|||
<data> |
|||
<field name="object_id" position="attributes"> |
|||
<attribute name="attrs">{'required': [('type', '!=', 'imap')]}</attribute> |
|||
</field> |
|||
<xpath expr="//page[@string='Server & Login']/group/group[3]" position="after"> |
|||
<group attrs="{'invisible': [('type','!=','imap')]}" string="Folders to monitor"> |
|||
<field |
|||
name="folder_ids" |
|||
nolabel="1" |
|||
on_change="onchange_server_type(type, is_ssl, object_id)"> |
|||
<tree> |
|||
<field name="sequence" invisible="1" /> |
|||
<field name="path" /> |
|||
<field name="model_id" /> |
|||
<field name="model_field" /> |
|||
<field name="match_algorithm" /> |
|||
<field name="mail_field" /> |
|||
</tree> |
|||
<form version="7.0"> |
|||
<header> |
|||
<button type="object" name="button_attach_mail_manually" string="Attach mail manually" icon="gtk-redo" /> |
|||
</header> |
|||
<group> |
|||
<group> |
|||
<field name="path" /> |
|||
<field name="model_id" /> |
|||
<field name="model_field" /> |
|||
<field name="match_algorithm" /> |
|||
<field name="mail_field" /> |
|||
</group> |
|||
<group> |
|||
<field name="delete_matching" /> |
|||
<field name="flag_nonmatching" /> |
|||
<field name="match_first" /> |
|||
<field name="msg_state" /> |
|||
<field name="model_order" attrs="{'readonly': [('match_first','==',False)], 'required': [('match_first','==',True)]}" /> |
|||
<field name="domain" /> |
|||
</group> |
|||
</group> |
|||
</form> |
|||
</field> |
|||
</group> |
|||
</xpath> |
|||
</data> |
|||
</field> |
|||
</record> |
|||
</data> |
|||
</openerp> |
@ -0,0 +1,23 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# This module copyright (C) 2013 Therp BV (<http://therp.nl>) |
|||
# All Rights Reserved |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
import attach_mail_manually |
@ -0,0 +1,129 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# This module copyright (C) 2013 Therp BV (<http://therp.nl>) |
|||
# All Rights Reserved |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
from openerp.osv import fields |
|||
from openerp.osv.orm import TransientModel |
|||
import logging |
|||
logger = logging.getLogger(__name__) |
|||
|
|||
|
|||
class attach_mail_manually(TransientModel): |
|||
_name = 'fetchmail.attach.mail.manually' |
|||
|
|||
_columns = { |
|||
'folder_id': fields.many2one('fetchmail.server.folder', 'Folder', |
|||
readonly=True), |
|||
'mail_ids': fields.one2many( |
|||
'fetchmail.attach.mail.manually.mail', 'wizard_id', 'Emails'), |
|||
} |
|||
|
|||
def default_get(self, cr, uid, fields_list, context=None): |
|||
if context is None: |
|||
context = {} |
|||
|
|||
defaults = super(attach_mail_manually, self).default_get( |
|||
cr, uid, fields_list, context |
|||
) |
|||
|
|||
for folder in self.pool.get('fetchmail.server.folder').browse( |
|||
cr, uid, |
|||
[context.get('default_folder_id')], context): |
|||
defaults['mail_ids'] = [] |
|||
connection = folder.server_id.connect() |
|||
connection.select(folder.path) |
|||
result, msgids = connection.search( |
|||
None, |
|||
'FLAGGED' if folder.flag_nonmatching else 'UNDELETED') |
|||
if result != 'OK': |
|||
logger.error('Could not search mailbox %s on %s' % ( |
|||
folder.path, folder.server_id.name)) |
|||
continue |
|||
attach_mail_manually_mail._columns['object_id'].selection = [ |
|||
(folder.model_id.model, folder.model_id.name)] |
|||
for msgid in msgids[0].split(): |
|||
result, msgdata = connection.fetch(msgid, '(RFC822)') |
|||
if result != 'OK': |
|||
logger.error('Could not fetch %s in %s on %s' % ( |
|||
msgid, folder.path, folder.server_id.name)) |
|||
continue |
|||
mail_message = self.pool.get('mail.thread').message_parse( |
|||
cr, uid, msgdata[0][1], |
|||
save_original=folder.server_id.original, |
|||
context=context |
|||
) |
|||
defaults['mail_ids'].append((0, 0, { |
|||
'msgid': msgid, |
|||
'subject': mail_message.get('subject', ''), |
|||
'date': mail_message.get('date', ''), |
|||
'object_id': folder.model_id.model+',False' |
|||
})) |
|||
connection.close() |
|||
|
|||
return defaults |
|||
|
|||
def attach_mails(self, cr, uid, ids, context=None): |
|||
for this in self.browse(cr, uid, ids, context): |
|||
for mail in this.mail_ids: |
|||
connection = this.folder_id.server_id.connect() |
|||
connection.select(this.folder_id.path) |
|||
result, msgdata = connection.fetch(mail.msgid, '(RFC822)') |
|||
if result != 'OK': |
|||
logger.error('Could not fetch %s in %s on %s' % ( |
|||
mail.msgid, this.folder_id.path, this.server)) |
|||
continue |
|||
|
|||
mail_message = self.pool.get('mail.thread').message_parse( |
|||
cr, uid, msgdata[0][1], |
|||
save_original=this.folder_id.server_id.original, |
|||
context=context) |
|||
|
|||
this.folder_id.server_id.attach_mail( |
|||
connection, |
|||
mail.object_id.id, this.folder_id, mail_message, |
|||
mail.msgid |
|||
) |
|||
connection.close() |
|||
return {'type': 'ir.actions.act_window_close'} |
|||
|
|||
|
|||
class attach_mail_manually_mail(TransientModel): |
|||
_name = 'fetchmail.attach.mail.manually.mail' |
|||
|
|||
_columns = { |
|||
'wizard_id': fields.many2one('fetchmail.attach.mail.manually', |
|||
readonly=True), |
|||
'msgid': fields.char('Message id', size=16, readonly=True), |
|||
'subject': fields.char('Subject', size=128, readonly=True), |
|||
'date': fields.datetime('Date', readonly=True), |
|||
'object_id': fields.reference( |
|||
'Object', |
|||
selection=lambda self, cr, uid, context: [ |
|||
(m.model, m.name) |
|||
for m in self.pool.get('ir.model').browse( |
|||
cr, uid, |
|||
self.pool.get('ir.model').search(cr, uid, []), |
|||
context |
|||
) |
|||
], |
|||
size=128, |
|||
), |
|||
} |
@ -0,0 +1,29 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<openerp> |
|||
<data> |
|||
<record model="ir.ui.view" id="view_attach_mail_manually"> |
|||
<field name="name">fetchmail.attach.mail.manually</field> |
|||
<field name="model">fetchmail.attach.mail.manually</field> |
|||
<field name="arch" type="xml"> |
|||
<form col="4" version="7.0" string="Attach mail manually"> |
|||
<sheet> |
|||
<group> |
|||
<field name="folder_id" /> |
|||
<field name="mail_ids" nolabel="1" colspan="4"> |
|||
<tree editable="top" create="0"> |
|||
<field name="subject" /> |
|||
<field name="date" /> |
|||
<field name="object_id" /> |
|||
</tree> |
|||
</field> |
|||
</group> |
|||
</sheet> |
|||
<footer> |
|||
<button string="Save" type="object" name="attach_mails" icon="gtk-ok" /> |
|||
<button special="cancel" string="Cancel" icon="gtk-cancel" /> |
|||
</footer> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
</data> |
|||
</openerp> |
@ -0,0 +1,24 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Daniel Reis |
|||
# 2011 |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
from . import import_odbc |
|||
|
|||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
@ -0,0 +1,101 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Daniel Reis |
|||
# 2011 |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
{ |
|||
'name': 'Import data from SQL and ODBC data sources.', |
|||
'version': '1.3', |
|||
'category': 'Tools', |
|||
'description': """ |
|||
Import data directly from other databases. |
|||
|
|||
Installed in the Administration module, menu Configuration -> Import from SQL. |
|||
|
|||
Features: |
|||
* Fetched data from the databases are used to build lines equivalent to |
|||
regular import files. These are imported using the standard "import_data()" |
|||
ORM method, benefiting from all its features, including xml_ids. |
|||
* Each table import is defined by an SQL statement, used to build the |
|||
equivalent for an import file. Each column's name should match the column |
|||
names you would use in an import file. The first column must provide an |
|||
unique identifier for the record, and will be used to build its xml_id. |
|||
* SQL columns named "none" are ignored. This can be used for the first column |
|||
of the SQL, so that it's used to build the XML Id but it's not imported to |
|||
any OpenERP field. |
|||
* The last sync date is the last successfull execution can be used in the SQL |
|||
using "%(sync)s", or ":sync" in the case of Oracle. |
|||
* When errors are found, only the record with the error fails import. The |
|||
other correct records are commited. However, the "last sync date" will only |
|||
be automaticaly updated when no errors are found. |
|||
* The import execution can be scheduled to run automatically. |
|||
|
|||
Examples: |
|||
* Importing suppliers to res.partner: |
|||
SELECT distinct |
|||
[SUPPLIER_CODE] as "ref" |
|||
, [SUPPLIER_NAME] as "name" |
|||
, 1 as "is_supplier" |
|||
, [INFO] as "comment" |
|||
FROM T_SUPPLIERS |
|||
WHERE INACTIVE_DATE IS NULL and DATE_CHANGED >= %(sync)s |
|||
|
|||
* Importing products to product.product: |
|||
SELECT PRODUCT_CODE as "ref" |
|||
, PRODUCT_NAME as "name" |
|||
, 'res_partner_id_'+SUPPLIER_ID as "partner_id/id" |
|||
FROM T_PRODUCTS |
|||
WHERE DATE_CHANGED >= %(sync)s |
|||
|
|||
Improvements ideas waiting for a contributor: |
|||
* Allow to import many2one fields (currently not supported). Done by adding a |
|||
second SQL sentence to get child record list? |
|||
* Allow "import sets" that can be executed at different time intervals using |
|||
different scheduler jobs. |
|||
* Allow to inactivate/delete OpenERP records when not present in an SQL |
|||
result set. |
|||
|
|||
Contributors |
|||
============ |
|||
|
|||
* Maxime Chambreuil <maxime.chambreuil@savoirfairelinux.com> |
|||
""", |
|||
'author': 'Daniel Reis', |
|||
'website': 'http://launchpad.net/addons-tko', |
|||
'images': [ |
|||
'images/snapshot1.png', |
|||
'images/snapshot2.png', |
|||
], |
|||
'depends': [ |
|||
'base', |
|||
'base_external_dbsource', |
|||
], |
|||
'data': [ |
|||
'import_odbc_view.xml', |
|||
'security/ir.model.access.csv', |
|||
], |
|||
'demo': [ |
|||
'import_odbc_demo.xml', |
|||
], |
|||
'test': [], |
|||
'installable': False, |
|||
'active': False, |
|||
} |
|||
|
|||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
After Width: 699 | Height: 475 | Size: 19 KiB |
After Width: 943 | Height: 348 | Size: 24 KiB |
@ -0,0 +1,216 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Daniel Reis |
|||
# 2011 |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
import sys |
|||
from datetime import datetime |
|||
from openerp.osv import orm, fields |
|||
import logging |
|||
_logger = logging.getLogger(__name__) |
|||
_loglvl = _logger.getEffectiveLevel() |
|||
SEP = '|' |
|||
|
|||
|
|||
class import_odbc_dbtable(orm.Model): |
|||
_name = "import.odbc.dbtable" |
|||
_description = 'Import Table Data' |
|||
_order = 'exec_order' |
|||
_columns = { |
|||
'name': fields.char('Datasource name', required=True, size=64), |
|||
'enabled': fields.boolean('Execution enabled'), |
|||
'dbsource_id': fields.many2one('base.external.dbsource', 'Database source', required=True), |
|||
'sql_source': fields.text('SQL', required=True, help='Column names must be valid "import_data" columns.'), |
|||
'model_target': fields.many2one('ir.model', 'Target object'), |
|||
'noupdate': fields.boolean('No updates', help="Only create new records; disable updates to existing records."), |
|||
'exec_order': fields.integer('Execution order', help="Defines the order to perform the import"), |
|||
'last_sync': fields.datetime('Last sync date', |
|||
help="Datetime for the last succesfull sync." |
|||
"\nLater changes on the source may not be replicated on the destination"), |
|||
'start_run': fields.datetime('Time started', readonly=True), |
|||
'last_run': fields.datetime('Time ended', readonly=True), |
|||
'last_record_count': fields.integer('Last record count', readonly=True), |
|||
'last_error_count': fields.integer('Last error count', readonly=True), |
|||
'last_warn_count': fields.integer('Last warning count', readonly=True), |
|||
'last_log': fields.text('Last run log', readonly=True), |
|||
'ignore_rel_errors': fields.boolean('Ignore relationship errors', |
|||
help="On error try to reimport rows ignoring relationships."), |
|||
'raise_import_errors': fields.boolean('Raise import errors', |
|||
help="Import errors not handled, intended for debugging purposes." |
|||
"\nAlso forces debug messages to be written to the server log."), |
|||
} |
|||
_defaults = { |
|||
'enabled': True, |
|||
'exec_order': 10, |
|||
} |
|||
|
|||
def _import_data(self, cr, uid, flds, data, model_obj, table_obj, log): |
|||
"""Import data and returns error msg or empty string""" |
|||
|
|||
def find_m2o(field_list): |
|||
""""Find index of first column with a one2many field""" |
|||
for i, x in enumerate(field_list): |
|||
if len(x) > 3 and x[-3:] == ':id' or x[-3:] == '/id': |
|||
return i |
|||
return -1 |
|||
|
|||
def append_to_log(log, level, obj_id='', msg='', rel_id=''): |
|||
if '_id_' in obj_id: |
|||
obj_id = '.'.join(obj_id.split('_')[:-2]) + ': ' + obj_id.split('_')[-1] |
|||
if ': .' in msg and not rel_id: |
|||
rel_id = msg[msg.find(': .')+3:] |
|||
if '_id_' in rel_id: |
|||
rel_id = '.'.join(rel_id.split('_')[:-2]) + ': ' + rel_id.split('_')[-1] |
|||
msg = msg[:msg.find(': .')] |
|||
log['last_log'].append('%s|%s\t|%s\t|%s' % (level.ljust(5), obj_id, rel_id, msg)) |
|||
_logger.debug(data) |
|||
cols = list(flds) # copy to avoid side effects |
|||
errmsg = str() |
|||
if table_obj.raise_import_errors: |
|||
model_obj.import_data(cr, uid, cols, [data], noupdate=table_obj.noupdate) |
|||
else: |
|||
try: |
|||
model_obj.import_data(cr, uid, cols, [data], noupdate=table_obj.noupdate) |
|||
except: |
|||
errmsg = str(sys.exc_info()[1]) |
|||
if errmsg and not table_obj.ignore_rel_errors: |
|||
# Fail |
|||
append_to_log(log, 'ERROR', data, errmsg) |
|||
log['last_error_count'] += 1 |
|||
return False |
|||
if errmsg and table_obj.ignore_rel_errors: |
|||
# Warn and retry ignoring many2one fields... |
|||
append_to_log(log, 'WARN', data, errmsg) |
|||
log['last_warn_count'] += 1 |
|||
# Try ignoring each many2one (tip: in the SQL sentence select more problematic FKs first) |
|||
i = find_m2o(cols) |
|||
if i >= 0: |
|||
# Try again without the [i] column |
|||
del cols[i] |
|||
del data[i] |
|||
self._import_data(cr, uid, cols, data, model_obj, table_obj, log) |
|||
else: |
|||
# Fail |
|||
append_to_log(log, 'ERROR', data, 'Removed all m2o keys and still fails.') |
|||
log['last_error_count'] += 1 |
|||
return False |
|||
return True |
|||
|
|||
def import_run(self, cr, uid, ids=None, context=None): |
|||
db_model = self.pool.get('base.external.dbsource') |
|||
actions = self.read(cr, uid, ids, ['id', 'exec_order']) |
|||
actions.sort(key=lambda x: (x['exec_order'], x['id'])) |
|||
|
|||
# Consider each dbtable: |
|||
for action_ref in actions: |
|||
obj = self.browse(cr, uid, action_ref['id']) |
|||
if not obj.enabled: |
|||
continue # skip |
|||
|
|||
_logger.setLevel(obj.raise_import_errors and logging.DEBUG or _loglvl) |
|||
_logger.debug('Importing %s...' % obj.name) |
|||
|
|||
# now() microseconds are stripped to avoid problem with SQL smalldate |
|||
# TODO: convert UTC Now to local timezone |
|||
# http://stackoverflow.com/questions/4770297/python-convert-utc-datetime-string-to-local-datetime |
|||
model_name = obj.model_target.model |
|||
model_obj = self.pool.get(model_name) |
|||
xml_prefix = model_name.replace('.', '_') + "_id_" |
|||
log = {'start_run': datetime.now().replace(microsecond=0), |
|||
'last_run': None, |
|||
'last_record_count': 0, |
|||
'last_error_count': 0, |
|||
'last_warn_count': 0, |
|||
'last_log': list()} |
|||
self.write(cr, uid, [obj.id], log) |
|||
|
|||
# Prepare SQL sentence; replace "%s" with the last_sync date |
|||
if obj.last_sync: |
|||
sync = datetime.strptime(obj.last_sync, "%Y-%m-%d %H:%M:%S") |
|||
else: |
|||
sync = datetime.datetime(1900, 1, 1, 0, 0, 0) |
|||
params = {'sync': sync} |
|||
res = db_model.execute(cr, uid, [obj.dbsource_id.id], |
|||
obj.sql_source, params, metadata=True) |
|||
|
|||
# Exclude columns titled "None"; add (xml_)"id" column |
|||
cidx = [i for i, x in enumerate(res['cols']) if x.upper() != 'NONE'] |
|||
cols = [x for i, x in enumerate(res['cols']) if x.upper() != 'NONE'] + ['id'] |
|||
|
|||
# Import each row: |
|||
for row in res['rows']: |
|||
# Build data row; import only columns present in the "cols" list |
|||
data = list() |
|||
for i in cidx: |
|||
# TODO: Handle imported datetimes properly - convert from localtime to UTC! |
|||
v = row[i] |
|||
if isinstance(v, str): |
|||
v = v.strip() |
|||
data.append(v) |
|||
data.append(xml_prefix + str(row[0]).strip()) |
|||
|
|||
# Import the row; on error, write line to the log |
|||
log['last_record_count'] += 1 |
|||
self._import_data(cr, uid, cols, data, model_obj, obj, log) |
|||
if log['last_record_count'] % 500 == 0: |
|||
_logger.info('...%s rows processed...' % (log['last_record_count'])) |
|||
|
|||
# Finished importing all rows |
|||
# If no errors, write new sync date |
|||
if not (log['last_error_count'] or log['last_warn_count']): |
|||
log['last_sync'] = log['start_run'] |
|||
level = logging.DEBUG |
|||
if log['last_warn_count']: |
|||
level = logging.WARN |
|||
if log['last_error_count']: |
|||
level = logging.ERROR |
|||
_logger.log(level, 'Imported %s , %d rows, %d errors, %d warnings.' % ( |
|||
model_name, log['last_record_count'], log['last_error_count'], |
|||
log['last_warn_count'])) |
|||
# Write run log, either if the table import is active or inactive |
|||
if log['last_log']: |
|||
log['last_log'].insert(0, 'LEVEL|== Line == |== Relationship ==|== Message ==') |
|||
log.update({'last_log': '\n'.join(log['last_log'])}) |
|||
log.update({'last_run': datetime.now().replace(microsecond=0)}) |
|||
self.write(cr, uid, [obj.id], log) |
|||
|
|||
# Finished |
|||
_logger.debug('Import job FINISHED.') |
|||
return True |
|||
|
|||
def import_schedule(self, cr, uid, ids, context=None): |
|||
cron_obj = self.pool.get('ir.cron') |
|||
new_create_id = cron_obj.create(cr, uid, { |
|||
'name': 'Import ODBC tables', |
|||
'interval_type': 'hours', |
|||
'interval_number': 1, |
|||
'numbercall': -1, |
|||
'model': 'import.odbc.dbtable', |
|||
'function': 'import_run', |
|||
'doall': False, |
|||
'active': True |
|||
}) |
|||
return { |
|||
'name': 'Import ODBC tables', |
|||
'view_type': 'form', |
|||
'view_mode': 'form,tree', |
|||
'res_model': 'ir.cron', |
|||
'res_id': new_create_id, |
|||
'type': 'ir.actions.act_window', |
|||
} |
@ -0,0 +1,15 @@ |
|||
<?xml version="1.0"?> |
|||
<openerp> |
|||
<data> |
|||
|
|||
<record model="import.odbc.dbtable" id="demo_postgresql_users"> |
|||
<field name="name">Users from PostgreSQL </field> |
|||
<field name="dbsource_id" ref="base_external_dbsource.demo_postgre"/> |
|||
<field name="sql_source">select usename as "login", usename as "name" from pg_catalog.pg_user</field> |
|||
<field name="model_target" ref="base.model_res_users"/> |
|||
</record> |
|||
|
|||
</data> |
|||
</openerp> |
|||
|
|||
|
@ -0,0 +1,90 @@ |
|||
<?xml version="1.0"?> |
|||
<openerp> |
|||
<data> |
|||
|
|||
<!-- Table form --> |
|||
|
|||
<record model="ir.ui.view" id="view_import_dbtable_form"> |
|||
<field name="name">import.odbc.dbtable.form</field> |
|||
<field name="model">import.odbc.dbtable</field> |
|||
<field name="type">form</field> |
|||
<field name="arch" type="xml"> |
|||
<form string="Table"> |
|||
<field name="name" search="1"/> |
|||
<field name="exec_order"/> |
|||
<field name="model_target"/> |
|||
<field name="dbsource_id" search="1"/> |
|||
<field name="noupdate"/> |
|||
<field name="enabled"/> |
|||
<field name="ignore_rel_errors"/> |
|||
<field name="raise_import_errors"/> |
|||
<field name="last_sync"/> |
|||
<group colspan="2"> |
|||
<button name="import_run" string="Run Import" type="object" icon="gtk-execute"/> |
|||
<button name="import_schedule" string="Schedule Import" type="object" icon="gtk-paste"/> |
|||
</group> |
|||
<field name="sql_source" colspan="4"/> |
|||
<separator string="Last execution" colspan="4"/> |
|||
<field name="last_record_count"/> |
|||
<field name="start_run"/> |
|||
<field name="last_warn_count"/> |
|||
<field name="last_run"/> |
|||
<field name="last_error_count"/> |
|||
<field name="last_log" colspan="4"/> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
|
|||
<!-- Table Tree --> |
|||
|
|||
<record id="view_import_dbtable_tree" model="ir.ui.view"> |
|||
<field name="name">import.odbc.dbtable.tree</field> |
|||
<field name="model">import.odbc.dbtable</field> |
|||
<field name="type">tree</field> |
|||
<field name="arch" type="xml"> |
|||
<tree string="Tables" colors="grey: enabled==False; red:last_error_count>0; blue:last_warn_count>0"> |
|||
<field name="exec_order"/> |
|||
<field name="name"/> |
|||
<field name="model_target"/> |
|||
<field name="dbsource_id"/> |
|||
<field name="enabled"/> |
|||
<field name="last_run"/> |
|||
<field name="last_sync"/> |
|||
<field name="last_record_count"/> |
|||
<field name="last_error_count"/> |
|||
<field name="last_warn_count"/> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
|
|||
<!-- Tree Search --> |
|||
<record id="view_import_dbtable_filter" model="ir.ui.view"> |
|||
<field name="name">import.odbc.dbtable.filter</field> |
|||
<field name="model">import.odbc.dbtable</field> |
|||
<field name="type">search</field> |
|||
<field name="arch" type="xml"> |
|||
<search string="Search ODBC Imports"> |
|||
<field name="name"/> |
|||
<field name="dbsource_id"/> |
|||
<field name="model_target"/> |
|||
</search> |
|||
</field> |
|||
</record> |
|||
|
|||
<!--Menu--> |
|||
<record model="ir.actions.act_window" id="action_import_dbtable"> |
|||
<field name="name">Import from SQL</field> |
|||
<field name="res_model">import.odbc.dbtable</field> |
|||
<field name="view_type">form</field> |
|||
</record> |
|||
|
|||
<menuitem name="Import from SQL" |
|||
id="menu_import_dbtable" |
|||
parent="base.next_id_9" |
|||
action="action_import_dbtable"/> |
|||
|
|||
</data> |
|||
</openerp> |
|||
|
|||
|
|||
|
@ -0,0 +1,2 @@ |
|||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink |
|||
access_import_odbc_dbsource_group_system,import_odbc_dbtable_group_system,model_import_odbc_dbtable,base.group_system,1,1,1,1 |
@ -0,0 +1,20 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Author Nicolas Bessi. Copyright Camptocamp SA |
|||
############################################################################## |
|||
{'name': 'Ir.config_parameter view', |
|||
'version': '0.1', |
|||
'category': 'Tools', |
|||
'description': """ |
|||
Create view to inspect/change technical parameters |
|||
""", |
|||
'author': 'Camptocamp', |
|||
'website': 'http://openerp.camptocamp.com', |
|||
'depends': ['base'], |
|||
'init_xml': [], |
|||
'update_xml': ['ir_config_parameter_view.xml'], |
|||
'demo_xml': [], |
|||
'installable': False, |
|||
'auto_install': False} |
|||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
@ -0,0 +1,16 @@ |
|||
# Translation of OpenERP Server. |
|||
# This file contains the translation of the following modules: |
|||
# |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: OpenERP Server 7.0\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2014-03-14 17:41+0000\n" |
|||
"PO-Revision-Date: 2014-03-14 17:41+0000\n" |
|||
"Last-Translator: <>\n" |
|||
"Language-Team: \n" |
|||
"MIME-Version: 1.0\n" |
|||
"Content-Type: text/plain; charset=UTF-8\n" |
|||
"Content-Transfer-Encoding: \n" |
|||
"Plural-Forms: \n" |
|||
|
@ -0,0 +1,36 @@ |
|||
<openerp> |
|||
<data> |
|||
<record model="ir.ui.view" id="view_config_list"> |
|||
<field name="name">ir.config_parameter.list</field> |
|||
<field name="model">ir.config_parameter</field> |
|||
<field name="priority" eval="6"/> |
|||
<field name="arch" type="xml"> |
|||
<tree string="Technical configuration parameters"> |
|||
<field name="key" select="1"/> |
|||
<field name="value" select="1" /> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
<record model="ir.ui.view" id="view_config_form"> |
|||
<field name="name">ir.config_parameter.form</field> |
|||
<field name="model">ir.config_parameter</field> |
|||
<field name="priority" eval="6"/> |
|||
<field name="arch" type="xml"> |
|||
<form string="Technical configuration parameters"> |
|||
<field name="key" select="1"/> |
|||
<field name="value" select="1" /> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
<record id="view_config_action" model="ir.actions.act_window"> |
|||
<field name="name">Technical config parameters</field> |
|||
<field name="type">ir.actions.act_window</field> |
|||
<field name="res_model">ir.config_parameter</field> |
|||
<field name="view_type">form</field> |
|||
<field name="view_id" ref="view_config_list"/> |
|||
</record> |
|||
|
|||
<menuitem name="Technical config parameters" id="technical_config_parameters" |
|||
parent="base.next_id_15" action="view_config_action" groups="base.group_extended"/> |
|||
</data> |
|||
</openerp> |
@ -0,0 +1 @@ |
|||
from . import env_mail |
@ -0,0 +1,68 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Author: Nicolas Bessi |
|||
# Copyright 2012 Camptocamp SA |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
{ |
|||
'name': 'Server env config for mail + fetchmail', |
|||
'version': '0.1', |
|||
'category': 'Tools', |
|||
'description': """ |
|||
Extend mail and fetch mail with server environment module. |
|||
|
|||
In config files, sections outgoint_mail and incoming_mails are default values |
|||
for all Outgoing Mail Servers and Fetchmail Servers. |
|||
For each server, you can (re)define values with a section named |
|||
"outgoing_mail.resource_name" where resource_name is the name of your server. |
|||
|
|||
Exemple of config file : |
|||
|
|||
[outgoing_mail] |
|||
smtp_host = smtp.myserver.com |
|||
smtp_port = 587 |
|||
smtp_user = |
|||
smtp_pass = |
|||
smtp_encryption = ssl |
|||
|
|||
[outgoing_mail.openerp_smtp_server1] |
|||
smtp_user = openerp |
|||
smtp_pass = openerp |
|||
|
|||
[incoming_mail.openerp_pop_mail1] |
|||
server = mail.myserver.com |
|||
port = 110 |
|||
type = pop |
|||
is_ssl = 0 |
|||
attach = 0 |
|||
original = 0 |
|||
user = openerp@myserver.com |
|||
password = openerp |
|||
|
|||
|
|||
""", |
|||
'author': 'Camptocamp', |
|||
'license': 'AGPL-3', |
|||
'website': 'http://openerp.camptocamp.com', |
|||
'depends': ['mail', 'fetchmail', 'server_environment', 'server_environment_files', 'crm'], |
|||
'init_xml': [], |
|||
'update_xml': ['mail_view.xml'], |
|||
'demo_xml': [], |
|||
'installable': False, |
|||
'active': False, |
|||
} |
@ -0,0 +1,225 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Author: Nicolas Bessi |
|||
# Copyright 2012 Camptocamp SA |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
from osv import fields |
|||
from osv import osv |
|||
|
|||
from server_environment import serv_config |
|||
|
|||
|
|||
class IrMail(osv.osv): |
|||
_inherit = "ir.mail_server" |
|||
|
|||
def _get_smtp_conf(self, cursor, uid, ids, name, args, context=None): |
|||
""" |
|||
Return configuration |
|||
""" |
|||
res = {} |
|||
for mail_server in self.browse(cursor, uid, ids): |
|||
global_section_name = 'outgoing_mail' |
|||
|
|||
# default vals |
|||
config_vals = {'smtp_port': 587} |
|||
if serv_config.has_section(global_section_name): |
|||
config_vals.update((serv_config.items(global_section_name))) |
|||
|
|||
custom_section_name = '.'.join((global_section_name, mail_server.name)) |
|||
if serv_config.has_section(custom_section_name): |
|||
config_vals.update(serv_config.items(custom_section_name)) |
|||
|
|||
if config_vals.get('smtp_port'): |
|||
config_vals['smtp_port'] = int(config_vals['smtp_port']) |
|||
|
|||
res[mail_server.id] = config_vals |
|||
return res |
|||
|
|||
_columns = { |
|||
'smtp_host': fields.function( |
|||
_get_smtp_conf, |
|||
method=True, |
|||
string='SMTP Server', |
|||
type="char", |
|||
multi='outgoing_mail_config', |
|||
size=128), |
|||
'smtp_port': fields.function( |
|||
_get_smtp_conf, |
|||
method=True, |
|||
string='SMTP Port', |
|||
type="integer", |
|||
multi='outgoing_mail_config', |
|||
help="SMTP Port. Usually 465 for SSL, and 25 or 587 for other cases.", |
|||
size=5), |
|||
'smtp_user': fields.function( |
|||
_get_smtp_conf, |
|||
method=True, |
|||
string='Username', |
|||
type="char", |
|||
multi='outgoing_mail_config', |
|||
help="Optional username for SMTP authentication", |
|||
size=64), |
|||
'smtp_pass': fields.function( |
|||
_get_smtp_conf, |
|||
method=True, |
|||
string='Password', |
|||
type="char", |
|||
multi='outgoing_mail_config', |
|||
help="Optional password for SMTP authentication", |
|||
size=64), |
|||
'smtp_encryption': fields.function( |
|||
_get_smtp_conf, |
|||
method=True, |
|||
string='smtp_encryption', |
|||
type="char", |
|||
multi='outgoing_mail_config', |
|||
help="Choose the connection encryption scheme:\n" |
|||
"- none: SMTP sessions are done in cleartext.\n" |
|||
"- starttls: TLS encryption is requested at start of SMTP session (Recommended)\n" |
|||
"- ssl: SMTP sessions are encrypted with SSL/TLS through a dedicated port (default: 465)", |
|||
size=64)} |
|||
|
|||
IrMail() |
|||
|
|||
|
|||
class FetchmailServer(osv.osv): |
|||
"""Incoming POP/IMAP mail server account""" |
|||
_inherit = 'fetchmail.server' |
|||
|
|||
def _get_incom_conf(self, cursor, uid, ids, name, args, context=None): |
|||
""" |
|||
Return configuration |
|||
""" |
|||
res = {} |
|||
for fetchmail in self.browse(cursor, uid, ids): |
|||
global_section_name = 'incoming_mail' |
|||
|
|||
key_types = {'port': int, |
|||
'is_ssl': lambda a: bool(int(a)), |
|||
'attach': lambda a: bool(int(a)), |
|||
'original': lambda a: bool(int(a)), |
|||
} |
|||
|
|||
# default vals |
|||
config_vals = {'port': 993, |
|||
'is_ssl': 0, |
|||
'attach': 0, |
|||
'original': 0, |
|||
} |
|||
if serv_config.has_section(global_section_name): |
|||
config_vals.update(serv_config.items(global_section_name)) |
|||
|
|||
custom_section_name = '.'.join((global_section_name, fetchmail.name)) |
|||
if serv_config.has_section(custom_section_name): |
|||
config_vals.update(serv_config.items(custom_section_name)) |
|||
|
|||
for key, to_type in key_types.iteritems(): |
|||
if config_vals.get(key): |
|||
config_vals[key] = to_type(config_vals[key]) |
|||
res[fetchmail.id] = config_vals |
|||
return res |
|||
|
|||
def _type_search(self, cr, uid, obj, name, args, context={}): |
|||
result_ids = [] |
|||
# read all incomming servers values |
|||
all_ids = self.search(cr, uid, [], context=context) |
|||
results = self.read(cr, uid, all_ids, ['id', 'type'], context=context) |
|||
args = args[:] |
|||
i = 0 |
|||
while i < len(args): |
|||
operator = args[i][1] |
|||
if operator == '=': |
|||
for res in results: |
|||
if (res['type'] == args[i][2]) and (res['id'] not in result_ids): |
|||
result_ids.append(res['id']) |
|||
elif operator == 'in': |
|||
for search_vals in args[i][2]: |
|||
for res in results: |
|||
if (res['type'] == search_vals) and (res['id'] not in result_ids): |
|||
result_ids.append(res['id']) |
|||
else: |
|||
continue |
|||
i += 1 |
|||
return [('id', 'in', result_ids)] |
|||
|
|||
_columns = { |
|||
'server': fields.function( |
|||
_get_incom_conf, |
|||
method=True, |
|||
string='Server', |
|||
type="char", |
|||
multi='income_mail_config', |
|||
size=256, help="Hostname or IP of the mail server"), |
|||
'port': fields.function( |
|||
_get_incom_conf, |
|||
method=True, |
|||
string='Port', |
|||
type="integer", |
|||
multi='income_mail_config', |
|||
help="Hostname or IP of the mail server"), |
|||
'type': fields.function( |
|||
_get_incom_conf, |
|||
method=True, |
|||
string='Type', |
|||
type="char", |
|||
multi='income_mail_config', |
|||
fnct_search=_type_search, |
|||
size=64, |
|||
help="pop, imap, local"), |
|||
'is_ssl': fields.function( |
|||
_get_incom_conf, |
|||
method=True, |
|||
string='Is SSL', |
|||
type="boolean", |
|||
multi='income_mail_config', |
|||
help='Connections are encrypted with SSL/TLS through' |
|||
' a dedicated port (default: IMAPS=993, POP3S=995)'), |
|||
'attach': fields.function( |
|||
_get_incom_conf, |
|||
method=True, |
|||
string='Keep Attachments', |
|||
type="boolean", |
|||
multi='income_mail_config', |
|||
help="Whether attachments should be downloaded. " |
|||
"If not enabled, incoming emails will be stripped of any " |
|||
"attachments before being processed"), |
|||
'original': fields.function( |
|||
_get_incom_conf, |
|||
method=True, |
|||
string='Keep Original', |
|||
type="boolean", |
|||
multi='income_mail_config', |
|||
help="Whether a full original copy of each email should be kept " |
|||
"for reference and attached to each processed message. This " |
|||
"will usually double the size of your message database."), |
|||
'user': fields.function( |
|||
_get_incom_conf, |
|||
method=True, |
|||
string='Username', |
|||
type="char", |
|||
multi='income_mail_config', |
|||
size=64), |
|||
'password': fields.function( |
|||
_get_incom_conf, |
|||
method=True, |
|||
string='password', |
|||
type="char", |
|||
multi='income_mail_config', |
|||
size=64)} |
|||
FetchmailServer() |
@ -0,0 +1,16 @@ |
|||
# Translation of OpenERP Server. |
|||
# This file contains the translation of the following modules: |
|||
# |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: OpenERP Server 7.0\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2014-03-14 17:41+0000\n" |
|||
"PO-Revision-Date: 2014-03-14 17:41+0000\n" |
|||
"Last-Translator: <>\n" |
|||
"Language-Team: \n" |
|||
"MIME-Version: 1.0\n" |
|||
"Content-Type: text/plain; charset=UTF-8\n" |
|||
"Content-Transfer-Encoding: \n" |
|||
"Plural-Forms: \n" |
|||
|
@ -0,0 +1,27 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<openerp> |
|||
<data> |
|||
<record model="ir.ui.view" id="inherit_fetchmail"> |
|||
<!-- must be unique in this module. --> |
|||
<field name="name">inherit_fetchmail_for_env_support</field> |
|||
<field name="model">fetchmail.server</field> |
|||
<!--parent python entity --> |
|||
<field name="inherit_id" ref="fetchmail.view_email_server_form"/> |
|||
<!-- modulename.view --> |
|||
<field name="arch" type="xml"> |
|||
<field name="server" attrs="{'required' : [('type', '!=', 'local')]}" position="replace"> |
|||
<field name="server" /> |
|||
</field> |
|||
<field name="port" attrs="{'required' : [('type', '!=', 'local')]}" position="replace"> |
|||
<field name="port" /> |
|||
</field> |
|||
<field name="user" attrs="{'required' : [('type', '!=', 'local')]}" position="replace"> |
|||
<field name="user" /> |
|||
</field> |
|||
<field name="password" attrs="{'required' : [('type', '!=', 'local')]}" position="replace"> |
|||
<field name="password" /> |
|||
</field> |
|||
</field> |
|||
</record> |
|||
</data> |
|||
</openerp> |
@ -0,0 +1 @@ |
|||
from . import security_protector |
@ -0,0 +1,25 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Author Nicolas Bessi. Copyright Camptocamp SA |
|||
############################################################################## |
|||
{'name': 'Security protector', |
|||
'version': '0.1', |
|||
'category': 'Tools', |
|||
'description': """ |
|||
Prevent security to be changed when module is updated |
|||
This module overwrite ir model acces write delete function. |
|||
Only acces edited trough the UI or with manual_security_override in context set to True will be altered. |
|||
When you try to delete a acces write it simply set all perms to false |
|||
you can deactivate this behavior in ir.config_parameter by chanching the protect_security? key to 0 |
|||
""", |
|||
'author': 'Camptocamp', |
|||
'website': 'http://openerp.camptocamp.com', |
|||
'depends': ['base'], |
|||
'init_xml': ['data.xml'], |
|||
'update_xml': ['security_view.xml'], |
|||
'demo_xml': [], |
|||
'installable': False, |
|||
'auto_install': False, |
|||
} |
|||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
@ -0,0 +1,8 @@ |
|||
<openerp> |
|||
<data noupdate="1"> |
|||
<record id="security_protector_config_param" model="ir.config_parameter"> |
|||
<field name="key">protect_security?</field> |
|||
<field name="value">1</field> |
|||
</record> |
|||
</data> |
|||
</openerp> |
@ -0,0 +1,16 @@ |
|||
# Translation of OpenERP Server. |
|||
# This file contains the translation of the following modules: |
|||
# |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: OpenERP Server 7.0\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2014-03-14 17:41+0000\n" |
|||
"PO-Revision-Date: 2014-03-14 17:41+0000\n" |
|||
"Last-Translator: <>\n" |
|||
"Language-Team: \n" |
|||
"MIME-Version: 1.0\n" |
|||
"Content-Type: text/plain; charset=UTF-8\n" |
|||
"Content-Transfer-Encoding: \n" |
|||
"Plural-Forms: \n" |
|||
|
@ -0,0 +1,47 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Author Nicolas Bessi. Copyright Camptocamp SA |
|||
############################################################################## |
|||
from osv import fields, osv |
|||
|
|||
class IrModelAccess(osv.osv): |
|||
"We inherit ir model access to add specific write unlink and copy behavior" |
|||
_name = 'ir.model.access' |
|||
_inherit = "ir.model.access" |
|||
|
|||
def _acces_can_be_modified(self, cr, uid, context=None): |
|||
context = context or {} |
|||
on = self.pool.get('ir.config_parameter').get_param(cr, uid, 'protect_security?', default=False, context=context) |
|||
if on in (1, "1", "YES", True): |
|||
if context.get('manual_security_override', False): |
|||
return True |
|||
return False |
|||
|
|||
else: |
|||
return True |
|||
|
|||
def write(self, cr, uid, ids, vals, context=None): |
|||
res =True |
|||
context = context or {} |
|||
if self._acces_can_be_modified(cr, uid, context=context): |
|||
res = super(IrModelAccess, self).write(cr, uid, ids, vals, context=context) |
|||
return res |
|||
|
|||
|
|||
def unlink(self, cr, uid, ids, context=None): |
|||
res = True |
|||
context = context or {} |
|||
# I'm note sur about this one maybe we should do nothing |
|||
if self._acces_can_be_modified(cr, uid, context=context): |
|||
vals = {'perm_read':False, |
|||
'perm_write': False, |
|||
'perm_unlink': False, |
|||
'perm_create': False} |
|||
super(IrModelAccess, self).write(cr, uid, ids, vals, context=context) |
|||
else: |
|||
res = super(IrModelAccess, self).unlink(cr, uid, ids, context=context) |
|||
|
|||
return res |
|||
|
|||
IrModelAccess() |
@ -0,0 +1,8 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<openerp> |
|||
<data> |
|||
<record id="base.ir_access_act" model="ir.actions.act_window"> |
|||
<field name="context">{'manual_security_override': 1}</field> |
|||
</record> |
|||
</data> |
|||
</openerp> |
@ -0,0 +1,22 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Author: Guewen Baconnier |
|||
# Copyright 2012 Camptocamp SA |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
import base_external_referentials |
@ -0,0 +1,47 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Author: Guewen Baconnier |
|||
# Copyright 2011-2012 Camptocamp SA |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
{ |
|||
"name": "Server environment for base_external_referential", |
|||
"version": "1.0", |
|||
"depends": ["base", 'server_environment', 'base_external_referentials'], |
|||
"author": "Camptocamp", |
|||
'license': 'AGPL-3', |
|||
"description": """This module is based on the server_environment module to use files for configuration. |
|||
Thus we can have a different file for each environment (dev, test, staging, prod). |
|||
This module define the config variables for the base_external_referential module. |
|||
In the configuration file, you can configure the url, login and password of the referentials |
|||
|
|||
Exemple of the section to put in the configuration file : |
|||
|
|||
[external_referential.name_of_my_external_referential] |
|||
location = http://localhost/magento/ |
|||
apiusername = my_api_login |
|||
apipass = my_api_password |
|||
""", |
|||
"website": "http://www.camptocamp.com", |
|||
"category": "Tools", |
|||
"init_xml": [], |
|||
"demo_xml": [], |
|||
"update_xml": [], |
|||
"installable": False, |
|||
"active": False, |
|||
} |
@ -0,0 +1,54 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Author: Guewen Baconnier |
|||
# Copyright 2011-2012 Camptocamp SA |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
from osv import fields, osv |
|||
from server_environment import serv_config |
|||
import logging |
|||
|
|||
|
|||
|
|||
class external_referential(osv.osv): |
|||
_inherit = 'external.referential' |
|||
|
|||
def _get_environment_config_by_name(self, cr, uid, ids, field_names, arg, context): |
|||
values = {} |
|||
for referential in self.browse(cr, uid, ids, context): |
|||
values[referential.id] = {} |
|||
for field_name in field_names: |
|||
section_name = '.'.join((self._name.replace('.', '_'), referential.name)) |
|||
try: |
|||
value = serv_config.get(section_name, field_name) |
|||
values[referential.id].update({field_name: value}) |
|||
except: |
|||
logger = logging.getLogger(__name__) |
|||
logger.exception('error trying to read field %s in section %s', field_name, section_name) |
|||
return values |
|||
|
|||
_columns = { |
|||
'location': fields.function(_get_environment_config_by_name, type='char', size=200, |
|||
method=True, string='Location', multi='connection_config'), |
|||
'apiusername': fields.function(_get_environment_config_by_name, type='char', size=64, |
|||
method=True, string='User Name', multi='connection_config'), |
|||
'apipass': fields.function(_get_environment_config_by_name, type='char', size=64, |
|||
method=True, string='Password', multi='connection_config'), |
|||
} |
|||
|
|||
external_referential() |
@ -0,0 +1,16 @@ |
|||
# Translation of OpenERP Server. |
|||
# This file contains the translation of the following modules: |
|||
# |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: OpenERP Server 7.0\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2014-03-14 17:41+0000\n" |
|||
"PO-Revision-Date: 2014-03-14 17:41+0000\n" |
|||
"Last-Translator: <>\n" |
|||
"Language-Team: \n" |
|||
"MIME-Version: 1.0\n" |
|||
"Content-Type: text/plain; charset=UTF-8\n" |
|||
"Content-Transfer-Encoding: \n" |
|||
"Plural-Forms: \n" |
|||
|
@ -0,0 +1 @@ |
|||
Lorenzo Battistini <lorenzo.battistini@agilebg.com> |
@ -0,0 +1,21 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Copyright (C) 2012 Agile Business Group sagl (<http://www.agilebg.com>) |
|||
# Copyright (C) 2012 Domsense srl (<http://www.domsense.com>) |
|||
# |
|||
# 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 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
import super_calendar |
@ -0,0 +1,88 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Copyright (C) 2012 Agile Business Group sagl (<http://www.agilebg.com>) |
|||
# Copyright (C) 2012 Domsense srl (<http://www.domsense.com>) |
|||
# |
|||
# 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 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
{ |
|||
'name': "Super Calendar", |
|||
'version': '0.1', |
|||
'category': 'Generic Modules/Others', |
|||
'summary': 'This module allows to create configurable calendars.', |
|||
'description': """ |
|||
This module allows to create configurable calendars. |
|||
|
|||
Through the 'calendar configurator' object, you can specify which models have |
|||
to be merged in the super calendar. For each model, you have to define the |
|||
'description' and 'date_start' fields at least. Then you can define 'duration' |
|||
and the 'user_id' fields. |
|||
|
|||
The 'super.calendar' object contains the the merged calendars. The |
|||
'super.calendar' can be updated by 'ir.cron' or manually. |
|||
|
|||
Configuration |
|||
============= |
|||
|
|||
After installing the module you can go to |
|||
|
|||
Super calendar → Configuration → Configurators |
|||
|
|||
and create a new configurator. For instance, if you want to see meetings and |
|||
phone calls, you can create the following lines |
|||
|
|||
.. image:: http://planet.domsense.com/wp-content/uploads/2012/04/meetings.png |
|||
:width: 400 px |
|||
|
|||
.. image:: http://planet.domsense.com/wp-content/uploads/2012/04/phone_calls.png |
|||
:width: 400 px |
|||
|
|||
Then, you can use the ‘Generate Calendar’ button or wait for the scheduled |
|||
action (‘Generate Calendar Records’) to be run. |
|||
|
|||
When the calendar is generated, you can visualize it by the ‘super calendar’ main menu. |
|||
|
|||
Here is a sample monthly calendar: |
|||
|
|||
.. image:: http://planet.domsense.com/wp-content/uploads/2012/04/month_calendar.png |
|||
:width: 400 px |
|||
|
|||
And here is the weekly one: |
|||
|
|||
.. image:: http://planet.domsense.com/wp-content/uploads/2012/04/week_calendar.png |
|||
:width: 400 px |
|||
|
|||
As you can see, several filters are available. A typical usage consists in |
|||
filtering by ‘Configurator’ (if you have several configurators, |
|||
‘Scheduled calls and meetings’ can be one of them) and by your user. |
|||
Once you filtered, you can save the filter as ‘Advanced filter’ or even |
|||
add it to a dashboard. |
|||
""", |
|||
'author': 'Agile Business Group', |
|||
'website': 'http://www.agilebg.com', |
|||
'license': 'AGPL-3', |
|||
'depends': ['base'], |
|||
"data": [ |
|||
'super_calendar_view.xml', |
|||
'cron_data.xml', |
|||
'security/ir.model.access.csv', |
|||
], |
|||
'demo': [], |
|||
'test': [], |
|||
'installable': False, |
|||
'application': True, |
|||
'auto_install': False, |
|||
} |
@ -0,0 +1,15 @@ |
|||
<?xml version="1.0"?> |
|||
<openerp> |
|||
<data noupdate="1"> |
|||
<record model="ir.cron" id="generate_calendar_records_cron"> |
|||
<field name="name">Generate Calendar Records</field> |
|||
<field name="interval_number">10</field> |
|||
<field name="interval_type">minutes</field> |
|||
<field name="numbercall">-1</field> |
|||
<field name="doall" eval="False"></field> |
|||
<field eval="'super.calendar.configurator'" name="model"/> |
|||
<field eval="'generate_calendar_records'" name="function"/> |
|||
<field eval="'[[],{}]'" name="args"/> |
|||
</record> |
|||
</data> |
|||
</openerp> |
@ -0,0 +1,212 @@ |
|||
# Translation of OpenERP Server. |
|||
# This file contains the translation of the following modules: |
|||
# * super_calendar |
|||
# |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: OpenERP Server 7.0\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2014-03-14 17:41+0000\n" |
|||
"PO-Revision-Date: 2014-03-17 10:57+0000\n" |
|||
"Last-Translator: michele <michelemilidoni@gmail.com>\n" |
|||
"Language-Team: \n" |
|||
"MIME-Version: 1.0\n" |
|||
"Content-Type: text/plain; charset=UTF-8\n" |
|||
"Content-Transfer-Encoding: 8bit\n" |
|||
"X-Launchpad-Export-Date: 2014-05-24 06:46+0000\n" |
|||
"X-Generator: Launchpad (build 17017)\n" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar.configurator.line,duration_field_id:0 |
|||
msgid "Duration field" |
|||
msgstr "Campo durata" |
|||
|
|||
#. module: super_calendar |
|||
#: view:super.calendar.configurator:0 |
|||
msgid "Generate Calendar" |
|||
msgstr "Generazione calendario" |
|||
|
|||
#. module: super_calendar |
|||
#: selection:super.calendar.configurator.line,description_type:0 |
|||
msgid "Field" |
|||
msgstr "Campo" |
|||
|
|||
#. module: super_calendar |
|||
#: code:addons/super_calendar/super_calendar.py:61 |
|||
#, python-format |
|||
msgid "The 'User' field of record %s (%s) does not refer to res.users" |
|||
msgstr "Il campo 'Utente' del record %s (%s) non si riferisce a res.users" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar,date_start:0 |
|||
msgid "Start date" |
|||
msgstr "Data inizio" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar.configurator.line,user_field_id:0 |
|||
msgid "User field" |
|||
msgstr "Campo Utente" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar.configurator.line,description_type:0 |
|||
msgid "Description Type" |
|||
msgstr "Tipo di descrizione" |
|||
|
|||
#. module: super_calendar |
|||
#: model:_description:0 |
|||
#: model:ir.model,name:super_calendar.model_super_calendar_configurator |
|||
msgid "super.calendar.configurator" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar,name:0 |
|||
#: view:super.calendar.configurator:0 |
|||
#: field:super.calendar.configurator.line,description:0 |
|||
msgid "Description" |
|||
msgstr "Descrizione" |
|||
|
|||
#. module: super_calendar |
|||
#: model:ir.actions.act_window,name:super_calendar.super_calendar_configurator |
|||
msgid "Calendar Configurators" |
|||
msgstr "Configuratori Calendario" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar,model_description:0 |
|||
msgid "Model Description" |
|||
msgstr "Descrizione Modello" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar.configurator.line,date_start_field_id:0 |
|||
msgid "Start date field" |
|||
msgstr "Data inizio" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar,user_id:0 |
|||
msgid "User" |
|||
msgstr "Utente" |
|||
|
|||
#. module: super_calendar |
|||
#: model:ir.actions.act_window,name:super_calendar.super_calendar_action |
|||
#: model:ir.ui.menu,name:super_calendar.super_calendar_menu |
|||
msgid "Super Calendar" |
|||
msgstr "Super Calendario" |
|||
|
|||
#. module: super_calendar |
|||
#: view:super.calendar.configurator:0 |
|||
msgid "Line" |
|||
msgstr "Riga" |
|||
|
|||
#. module: super_calendar |
|||
#: view:super.calendar:0 |
|||
msgid "Extended Filters..." |
|||
msgstr "Filtri estesi..." |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar,res_id:0 |
|||
msgid "Resource" |
|||
msgstr "Risorsa" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar.configurator,name:0 |
|||
msgid "Name" |
|||
msgstr "Nome" |
|||
|
|||
#. module: super_calendar |
|||
#: model:ir.ui.menu,name:super_calendar.super_calendar_configurators |
|||
#: view:super.calendar.configurator:0 |
|||
msgid "Configurators" |
|||
msgstr "Configuratori" |
|||
|
|||
#. module: super_calendar |
|||
#: view:super.calendar.configurator:0 |
|||
#: field:super.calendar.configurator,line_ids:0 |
|||
msgid "Lines" |
|||
msgstr "Righe" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar.configurator.line,description_code:0 |
|||
#: field:super.calendar.configurator.line,description_field_id:0 |
|||
msgid "Description field" |
|||
msgstr "Campo descrizione" |
|||
|
|||
#. module: super_calendar |
|||
#: view:super.calendar.configurator:0 |
|||
#: help:super.calendar.configurator.line,description_code:0 |
|||
msgid "" |
|||
"Use '${o}' to refer to the involved object. E.g.: '${o.project_id.name}'" |
|||
msgstr "" |
|||
"Usare '${o}' per richiamare l'oggetto scelto. Esempio: '${o.project_id.name}'" |
|||
|
|||
#. module: super_calendar |
|||
#: code:addons/super_calendar/super_calendar.py:60 |
|||
#, python-format |
|||
msgid "Error" |
|||
msgstr "Errore" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar,model_id:0 |
|||
#: field:super.calendar.configurator.line,name:0 |
|||
msgid "Model" |
|||
msgstr "Modello" |
|||
|
|||
#. module: super_calendar |
|||
#: view:super.calendar:0 |
|||
#: field:super.calendar,configurator_id:0 |
|||
#: view:super.calendar.configurator:0 |
|||
#: field:super.calendar.configurator.line,configurator_id:0 |
|||
msgid "Configurator" |
|||
msgstr "Configuratore" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar.configurator.line,domain:0 |
|||
msgid "Domain" |
|||
msgstr "Domain" |
|||
|
|||
#. module: super_calendar |
|||
#: selection:super.calendar.configurator.line,description_type:0 |
|||
msgid "Code" |
|||
msgstr "Codice" |
|||
|
|||
#. module: super_calendar |
|||
#: model:_description:0 |
|||
#: model:ir.model,name:super_calendar.model_super_calendar_configurator_line |
|||
msgid "super.calendar.configurator.line" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: model:ir.ui.menu,name:super_calendar.super_calendar_configuration |
|||
msgid "Configuration" |
|||
msgstr "Configurazione" |
|||
|
|||
#. module: super_calendar |
|||
#: view:super.calendar:0 |
|||
msgid "My Items" |
|||
msgstr "I miei oggetti" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar.configurator.line,date_stop_field_id:0 |
|||
msgid "End date field" |
|||
msgstr "Campo data fine" |
|||
|
|||
#. module: super_calendar |
|||
#: model:_description:0 |
|||
#: model:ir.model,name:super_calendar.model_super_calendar |
|||
msgid "super.calendar" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: view:super.calendar:0 |
|||
msgid "Search Calendar" |
|||
msgstr "Ricerca Calendario" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar,duration:0 |
|||
msgid "Duration" |
|||
msgstr "Durata" |
|||
|
|||
#. module: super_calendar |
|||
#: model:ir.ui.menu,name:super_calendar.super_calendar_calendar |
|||
#: model:ir.ui.menu,name:super_calendar.super_calendar_calendar_calendar |
|||
#: view:super.calendar:0 |
|||
msgid "Calendar" |
|||
msgstr "Calendario" |
@ -0,0 +1,211 @@ |
|||
# Translation of OpenERP Server. |
|||
# This file contains the translation of the following modules: |
|||
# * super_calendar |
|||
# |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: OpenERP Server 7.0\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2014-03-14 17:41+0000\n" |
|||
"PO-Revision-Date: 2014-03-17 10:57+0000\n" |
|||
"Last-Translator: michele <michelemilidoni@gmail.com>\n" |
|||
"Language-Team: \n" |
|||
"MIME-Version: 1.0\n" |
|||
"Content-Type: text/plain; charset=UTF-8\n" |
|||
"Content-Transfer-Encoding: 8bit\n" |
|||
"X-Launchpad-Export-Date: 2014-05-24 06:46+0000\n" |
|||
"X-Generator: Launchpad (build 17017)\n" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar.configurator.line,duration_field_id:0 |
|||
msgid "Duration field" |
|||
msgstr "Поле длительности" |
|||
|
|||
#. module: super_calendar |
|||
#: view:super.calendar.configurator:0 |
|||
msgid "Generate Calendar" |
|||
msgstr "Обновить календарь" |
|||
|
|||
#. module: super_calendar |
|||
#: selection:super.calendar.configurator.line,description_type:0 |
|||
msgid "Field" |
|||
msgstr "Поле" |
|||
|
|||
#. module: super_calendar |
|||
#: code:addons/super_calendar/super_calendar.py:61 |
|||
#, python-format |
|||
msgid "The 'User' field of record %s (%s) does not refer to res.users" |
|||
msgstr "Поле 'User' записи %s (%s) не ссылается на res.users" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar,date_start:0 |
|||
msgid "Start date" |
|||
msgstr "Дата начала" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar.configurator.line,user_field_id:0 |
|||
msgid "User field" |
|||
msgstr "Поле пользователя" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar.configurator.line,description_type:0 |
|||
msgid "Description Type" |
|||
msgstr "Тип описания" |
|||
|
|||
#. module: super_calendar |
|||
#: model:_description:0 |
|||
#: model:ir.model,name:super_calendar.model_super_calendar_configurator |
|||
msgid "super.calendar.configurator" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar,name:0 |
|||
#: view:super.calendar.configurator:0 |
|||
#: field:super.calendar.configurator.line,description:0 |
|||
msgid "Description" |
|||
msgstr "Описание" |
|||
|
|||
#. module: super_calendar |
|||
#: model:ir.actions.act_window,name:super_calendar.super_calendar_configurator |
|||
msgid "Calendar Configurators" |
|||
msgstr "Настройки календаря" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar,model_description:0 |
|||
msgid "Model Description" |
|||
msgstr "Описание" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar.configurator.line,date_start_field_id:0 |
|||
msgid "Start date field" |
|||
msgstr "Поле даты начала" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar,user_id:0 |
|||
msgid "User" |
|||
msgstr "Пользователь" |
|||
|
|||
#. module: super_calendar |
|||
#: model:ir.actions.act_window,name:super_calendar.super_calendar_action |
|||
#: model:ir.ui.menu,name:super_calendar.super_calendar_menu |
|||
msgid "Super Calendar" |
|||
msgstr "Календарь" |
|||
|
|||
#. module: super_calendar |
|||
#: view:super.calendar.configurator:0 |
|||
msgid "Line" |
|||
msgstr "Строка" |
|||
|
|||
#. module: super_calendar |
|||
#: view:super.calendar:0 |
|||
msgid "Extended Filters..." |
|||
msgstr "Расширенные фильтры..." |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar,res_id:0 |
|||
msgid "Resource" |
|||
msgstr "Ресурс" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar.configurator,name:0 |
|||
msgid "Name" |
|||
msgstr "Название" |
|||
|
|||
#. module: super_calendar |
|||
#: model:ir.ui.menu,name:super_calendar.super_calendar_configurators |
|||
#: view:super.calendar.configurator:0 |
|||
msgid "Configurators" |
|||
msgstr "Настройки" |
|||
|
|||
#. module: super_calendar |
|||
#: view:super.calendar.configurator:0 |
|||
#: field:super.calendar.configurator,line_ids:0 |
|||
msgid "Lines" |
|||
msgstr "Строки" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar.configurator.line,description_code:0 |
|||
#: field:super.calendar.configurator.line,description_field_id:0 |
|||
msgid "Description field" |
|||
msgstr "Поле описания" |
|||
|
|||
#. module: super_calendar |
|||
#: view:super.calendar.configurator:0 |
|||
#: help:super.calendar.configurator.line,description_code:0 |
|||
msgid "" |
|||
"Use '${o}' to refer to the involved object. E.g.: '${o.project_id.name}'" |
|||
msgstr "Используйте '${o}' для ссылки на объект: '${o.project_id.name}'" |
|||
|
|||
#. module: super_calendar |
|||
#: code:addons/super_calendar/super_calendar.py:60 |
|||
#, python-format |
|||
msgid "Error" |
|||
msgstr "Ошибка" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar,model_id:0 |
|||
#: field:super.calendar.configurator.line,name:0 |
|||
msgid "Model" |
|||
msgstr "Модель" |
|||
|
|||
#. module: super_calendar |
|||
#: view:super.calendar:0 |
|||
#: field:super.calendar,configurator_id:0 |
|||
#: view:super.calendar.configurator:0 |
|||
#: field:super.calendar.configurator.line,configurator_id:0 |
|||
msgid "Configurator" |
|||
msgstr "Настройки" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar.configurator.line,domain:0 |
|||
msgid "Domain" |
|||
msgstr "Домен" |
|||
|
|||
#. module: super_calendar |
|||
#: selection:super.calendar.configurator.line,description_type:0 |
|||
msgid "Code" |
|||
msgstr "Код" |
|||
|
|||
#. module: super_calendar |
|||
#: model:_description:0 |
|||
#: model:ir.model,name:super_calendar.model_super_calendar_configurator_line |
|||
msgid "super.calendar.configurator.line" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: model:ir.ui.menu,name:super_calendar.super_calendar_configuration |
|||
msgid "Configuration" |
|||
msgstr "Настройки" |
|||
|
|||
#. module: super_calendar |
|||
#: view:super.calendar:0 |
|||
msgid "My Items" |
|||
msgstr "Мои события" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar.configurator.line,date_stop_field_id:0 |
|||
msgid "End date field" |
|||
msgstr "Поле даты окончания" |
|||
|
|||
#. module: super_calendar |
|||
#: model:_description:0 |
|||
#: model:ir.model,name:super_calendar.model_super_calendar |
|||
msgid "super.calendar" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: view:super.calendar:0 |
|||
msgid "Search Calendar" |
|||
msgstr "Поиск календаря" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar,duration:0 |
|||
msgid "Duration" |
|||
msgstr "Продолжительность" |
|||
|
|||
#. module: super_calendar |
|||
#: model:ir.ui.menu,name:super_calendar.super_calendar_calendar |
|||
#: model:ir.ui.menu,name:super_calendar.super_calendar_calendar_calendar |
|||
#: view:super.calendar:0 |
|||
msgid "Calendar" |
|||
msgstr "Календарь" |
@ -0,0 +1,210 @@ |
|||
# Translation of OpenERP Server. |
|||
# This file contains the translation of the following modules: |
|||
# * super_calendar |
|||
# |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: OpenERP Server 7.0\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2014-03-14 17:41+0000\n" |
|||
"PO-Revision-Date: 2014-03-14 17:41+0000\n" |
|||
"Last-Translator: <>\n" |
|||
"Language-Team: \n" |
|||
"MIME-Version: 1.0\n" |
|||
"Content-Type: text/plain; charset=UTF-8\n" |
|||
"Content-Transfer-Encoding: \n" |
|||
"Plural-Forms: \n" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar.configurator.line,duration_field_id:0 |
|||
msgid "Duration field" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: view:super.calendar.configurator:0 |
|||
msgid "Generate Calendar" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: selection:super.calendar.configurator.line,description_type:0 |
|||
msgid "Field" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: code:addons/super_calendar/super_calendar.py:61 |
|||
#, python-format |
|||
msgid "The 'User' field of record %s (%s) does not refer to res.users" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar,date_start:0 |
|||
msgid "Start date" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar.configurator.line,user_field_id:0 |
|||
msgid "User field" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar.configurator.line,description_type:0 |
|||
msgid "Description Type" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: model:_description:0 |
|||
#: model:ir.model,name:super_calendar.model_super_calendar_configurator |
|||
msgid "super.calendar.configurator" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar,name:0 |
|||
#: view:super.calendar.configurator:0 |
|||
#: field:super.calendar.configurator.line,description:0 |
|||
msgid "Description" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: model:ir.actions.act_window,name:super_calendar.super_calendar_configurator |
|||
msgid "Calendar Configurators" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar,model_description:0 |
|||
msgid "Model Description" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar.configurator.line,date_start_field_id:0 |
|||
msgid "Start date field" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar,user_id:0 |
|||
msgid "User" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: model:ir.actions.act_window,name:super_calendar.super_calendar_action |
|||
#: model:ir.ui.menu,name:super_calendar.super_calendar_menu |
|||
msgid "Super Calendar" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: view:super.calendar.configurator:0 |
|||
msgid "Line" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: view:super.calendar:0 |
|||
msgid "Extended Filters..." |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar,res_id:0 |
|||
msgid "Resource" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar.configurator,name:0 |
|||
msgid "Name" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: model:ir.ui.menu,name:super_calendar.super_calendar_configurators |
|||
#: view:super.calendar.configurator:0 |
|||
msgid "Configurators" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: view:super.calendar.configurator:0 |
|||
#: field:super.calendar.configurator,line_ids:0 |
|||
msgid "Lines" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar.configurator.line,description_code:0 |
|||
#: field:super.calendar.configurator.line,description_field_id:0 |
|||
msgid "Description field" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: view:super.calendar.configurator:0 |
|||
#: help:super.calendar.configurator.line,description_code:0 |
|||
msgid "Use '${o}' to refer to the involved object. E.g.: '${o.project_id.name}'" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: code:addons/super_calendar/super_calendar.py:60 |
|||
#, python-format |
|||
msgid "Error" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar,model_id:0 |
|||
#: field:super.calendar.configurator.line,name:0 |
|||
msgid "Model" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: view:super.calendar:0 |
|||
#: field:super.calendar,configurator_id:0 |
|||
#: view:super.calendar.configurator:0 |
|||
#: field:super.calendar.configurator.line,configurator_id:0 |
|||
msgid "Configurator" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar.configurator.line,domain:0 |
|||
msgid "Domain" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: selection:super.calendar.configurator.line,description_type:0 |
|||
msgid "Code" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: model:_description:0 |
|||
#: model:ir.model,name:super_calendar.model_super_calendar_configurator_line |
|||
msgid "super.calendar.configurator.line" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: model:ir.ui.menu,name:super_calendar.super_calendar_configuration |
|||
msgid "Configuration" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: view:super.calendar:0 |
|||
msgid "My Items" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar.configurator.line,date_stop_field_id:0 |
|||
msgid "End date field" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: model:_description:0 |
|||
#: model:ir.model,name:super_calendar.model_super_calendar |
|||
msgid "super.calendar" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: view:super.calendar:0 |
|||
msgid "Search Calendar" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: field:super.calendar,duration:0 |
|||
msgid "Duration" |
|||
msgstr "" |
|||
|
|||
#. module: super_calendar |
|||
#: model:ir.ui.menu,name:super_calendar.super_calendar_calendar |
|||
#: model:ir.ui.menu,name:super_calendar.super_calendar_calendar_calendar |
|||
#: view:super.calendar:0 |
|||
msgid "Calendar" |
|||
msgstr "" |
|||
|
@ -0,0 +1,4 @@ |
|||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink |
|||
access_model_super_calendar_configurator,access_model_super_calendar_configurator,model_super_calendar_configurator,base.group_system,1,1,1,1 |
|||
access_model_super_calendar_configurator_line,access_model_super_calendar_configurator_line,model_super_calendar_configurator_line,base.group_system,1,1,1,1 |
|||
access_model_super_calendar,access_model_super_calendar,model_super_calendar,base.group_user,1,0,0,0 |
@ -0,0 +1,163 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Copyright (C) 2012 Agile Business Group sagl (<http://www.agilebg.com>) |
|||
# Copyright (C) 2012 Domsense srl (<http://www.domsense.com>) |
|||
# |
|||
# 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 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
from openerp.osv import fields, orm |
|||
from openerp.tools.translate import _ |
|||
import logging |
|||
from mako.template import Template |
|||
from datetime import datetime |
|||
from openerp import tools |
|||
from openerp.tools.safe_eval import safe_eval |
|||
|
|||
|
|||
def _models_get(self, cr, uid, context=None): |
|||
obj = self.pool.get('ir.model') |
|||
ids = obj.search(cr, uid, []) |
|||
res = obj.read(cr, uid, ids, ['model', 'name'], context) |
|||
return [(r['model'], r['name']) for r in res] |
|||
|
|||
|
|||
class super_calendar_configurator(orm.Model): |
|||
_logger = logging.getLogger('super.calendar') |
|||
_name = 'super.calendar.configurator' |
|||
_columns = { |
|||
'name': fields.char('Name', size=64, required=True), |
|||
'line_ids': fields.one2many('super.calendar.configurator.line', 'configurator_id', 'Lines'), |
|||
} |
|||
|
|||
def generate_calendar_records(self, cr, uid, ids, context=None): |
|||
configurator_ids = self.search(cr, uid, []) |
|||
super_calendar_pool = self.pool.get('super.calendar') |
|||
|
|||
# removing old records |
|||
super_calendar_ids = super_calendar_pool.search(cr, uid, [], context=context) |
|||
super_calendar_pool.unlink(cr, uid, super_calendar_ids, context=context) |
|||
|
|||
for configurator in self.browse(cr, uid, configurator_ids, context): |
|||
for line in configurator.line_ids: |
|||
current_pool = self.pool.get(line.name.model) |
|||
current_record_ids = current_pool.search( |
|||
cr, |
|||
uid, |
|||
line.domain and safe_eval(line.domain) or [], |
|||
context=context) |
|||
|
|||
for current_record_id in current_record_ids: |
|||
current_record = current_pool.browse(cr, uid, current_record_id, context=context) |
|||
if (line.user_field_id and |
|||
current_record[line.user_field_id.name] and |
|||
current_record[line.user_field_id.name]._table_name != 'res.users'): |
|||
raise orm.except_orm( |
|||
_('Error'), |
|||
_("The 'User' field of record %s (%s) does not refer to res.users") |
|||
% (current_record[line.description_field_id.name], line.name.model)) |
|||
if (((line.description_field_id and current_record[line.description_field_id.name]) or |
|||
line.description_code) and |
|||
current_record[line.date_start_field_id.name]): |
|||
duration = False |
|||
if (not line.duration_field_id and |
|||
line.date_stop_field_id and |
|||
current_record[line.date_start_field_id.name] and |
|||
current_record[line.date_stop_field_id.name]): |
|||
date_start = datetime.strptime( |
|||
current_record[line.date_start_field_id.name], |
|||
tools.DEFAULT_SERVER_DATETIME_FORMAT |
|||
) |
|||
date_stop = datetime.strptime( |
|||
current_record[line.date_stop_field_id.name], |
|||
tools.DEFAULT_SERVER_DATETIME_FORMAT |
|||
) |
|||
duration = (date_stop - date_start).total_seconds() / 3600 |
|||
elif line.duration_field_id: |
|||
duration = current_record[line.duration_field_id.name] |
|||
if line.description_type != 'code': |
|||
name = current_record[line.description_field_id.name] |
|||
else: |
|||
parse_dict = {'o': current_record} |
|||
mytemplate = Template(line.description_code) |
|||
name = mytemplate.render(**parse_dict) |
|||
super_calendar_values = { |
|||
'name': name, |
|||
'model_description': line.description, |
|||
'date_start': current_record[line.date_start_field_id.name], |
|||
'duration': duration, |
|||
'user_id': ( |
|||
line.user_field_id and |
|||
current_record[line.user_field_id.name] and |
|||
current_record[line.user_field_id.name].id or |
|||
False |
|||
), |
|||
'configurator_id': configurator.id, |
|||
'res_id': line.name.model+','+str(current_record['id']), |
|||
'model_id': line.name.id, |
|||
} |
|||
super_calendar_pool.create(cr, uid, super_calendar_values, context=context) |
|||
self._logger.info('Calendar generated') |
|||
return True |
|||
|
|||
|
|||
class super_calendar_configurator_line(orm.Model): |
|||
_name = 'super.calendar.configurator.line' |
|||
_columns = { |
|||
'name': fields.many2one('ir.model', 'Model', required=True), |
|||
'description': fields.char('Description', size=128, required=True), |
|||
'domain': fields.char('Domain', size=512), |
|||
'configurator_id': fields.many2one('super.calendar.configurator', 'Configurator'), |
|||
'description_type': fields.selection([ |
|||
('field', 'Field'), |
|||
('code', 'Code'), |
|||
], string="Description Type"), |
|||
'description_field_id': fields.many2one( |
|||
'ir.model.fields', 'Description field', |
|||
domain="[('model_id', '=', name),('ttype', '=', 'char')]"), |
|||
'description_code': fields.text( |
|||
'Description field', |
|||
help="Use '${o}' to refer to the involved object. E.g.: '${o.project_id.name}'" |
|||
), |
|||
'date_start_field_id': fields.many2one( |
|||
'ir.model.fields', 'Start date field', |
|||
domain="['&','|',('ttype', '=', 'datetime'),('ttype', '=', 'date'),('model_id', '=', name)]", |
|||
required=True), |
|||
'date_stop_field_id': fields.many2one( |
|||
'ir.model.fields', 'End date field', |
|||
domain="['&',('ttype', '=', 'datetime'),('model_id', '=', name)]" |
|||
), |
|||
'duration_field_id': fields.many2one( |
|||
'ir.model.fields', 'Duration field', |
|||
domain="['&',('ttype', '=', 'float'),('model_id', '=', name)]"), |
|||
'user_field_id': fields.many2one( |
|||
'ir.model.fields', 'User field', |
|||
domain="['&',('ttype', '=', 'many2one'),('model_id', '=', name)]"), |
|||
} |
|||
|
|||
|
|||
class super_calendar(orm.Model): |
|||
_name = 'super.calendar' |
|||
_columns = { |
|||
'name': fields.char('Description', size=512, required=True), |
|||
'model_description': fields.char('Model Description', size=128, required=True), |
|||
'date_start': fields.datetime('Start date', required=True), |
|||
'duration': fields.float('Duration'), |
|||
'user_id': fields.many2one('res.users', 'User'), |
|||
'configurator_id': fields.many2one('super.calendar.configurator', 'Configurator'), |
|||
'res_id': fields.reference('Resource', selection=_models_get, size=128), |
|||
'model_id': fields.many2one('ir.model', 'Model'), |
|||
} |
@ -0,0 +1,144 @@ |
|||
<?xml version="1.0"?> |
|||
<openerp> |
|||
<data> |
|||
|
|||
<!-- configurator --> |
|||
|
|||
<record model="ir.ui.view" id="super_calendar_configurator_tree"> |
|||
<field name="name">super_calendar_configurator_tree</field> |
|||
<field name="model">super.calendar.configurator</field> |
|||
<field name="arch" type="xml"> |
|||
<tree string="Configurators"> |
|||
<field name="name"/> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.ui.view" id="super_calendar_configurator_form"> |
|||
<field name="name">super_calendar_configurator_form</field> |
|||
<field name="model">super.calendar.configurator</field> |
|||
<field name="arch" type="xml"> |
|||
<form string="Configurator"> |
|||
<field name="name" select="1" colspan="2"/> |
|||
<newline/> |
|||
<field name="line_ids" nolabel="1" colspan="4"> |
|||
<tree string="Lines"> |
|||
<field name="name"/> |
|||
<field name="domain"/> |
|||
</tree> |
|||
<form string="Line"> |
|||
<field name="name"/> |
|||
<field name="description"/> |
|||
<field name="domain"/> |
|||
<field name="date_start_field_id"/> |
|||
<field name="duration_field_id"/> |
|||
<field name="date_stop_field_id" attrs="{'readonly':[('duration_field_id','!=',False)]}"/> |
|||
<field name="user_field_id"/> |
|||
<separator string="Description" colspan="4" /> |
|||
<field name="description_type"/> |
|||
<newline/> |
|||
<field name="description_field_id" attrs="{'required':[('description_type','!=','code')], 'invisible':[('description_type','==','code')]}"/> |
|||
<group colspan="4" col="1" attrs="{'invisible':[('description_type','!=','code')]}"> |
|||
<label string="Use '${o}' to refer to the involved object. E.g.: '${o.project_id.name}'" /> |
|||
<field name="description_code" nolabel="1" attrs="{'required':[('description_type','==','code')]}"/> |
|||
</group> |
|||
</form> |
|||
</field> |
|||
<newline/> |
|||
<button name="generate_calendar_records" string="Generate Calendar" type="object" icon="gtk-go-forward" colspan="2"/> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.actions.act_window" id="super_calendar_configurator"> |
|||
<field name="name">Calendar Configurators</field> |
|||
<field name="res_model">super.calendar.configurator</field> |
|||
<field name="view_type">form</field> |
|||
<field name="view_mode">tree,form</field> |
|||
<field name="view_id" ref="super_calendar_configurator_tree"/> |
|||
</record> |
|||
|
|||
<!-- calendar --> |
|||
|
|||
<record model="ir.ui.view" id="super_calendar_tree"> |
|||
<field name="name">super_calendar_tree</field> |
|||
<field name="model">super.calendar</field> |
|||
<field name="arch" type="xml"> |
|||
<tree string="Calendar"> |
|||
<field name="name"/> |
|||
<field name="date_start"/> |
|||
<!--<field name="date_stop"/>--> |
|||
<field name="duration"/> |
|||
<field name="user_id"/> |
|||
<field name="configurator_id"/> |
|||
<field name="model_id"/> |
|||
<field name="model_description"/> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.ui.view" id="super_calendar_form"> |
|||
<field name="name">super_calendar_form</field> |
|||
<field name="model">super.calendar</field> |
|||
<field name="arch" type="xml"> |
|||
<form string="Configurator"> |
|||
<field name="name" readonly="1"/> |
|||
<field name="date_start" readonly="1"/> |
|||
<!--<field name="date_stop" readonly="1"/>--> |
|||
<field name="duration" readonly="1"/> |
|||
<field name="user_id" readonly="1"/> |
|||
<field name="configurator_id" readonly="1"/> |
|||
<field name="model_id" readonly="1"/> |
|||
<field name="model_description" readonly="1"/> |
|||
<field name="res_id"/> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.ui.view" id="super_calendar"> |
|||
<field name="name">super_calendar</field> |
|||
<field name="model">super.calendar</field> |
|||
<field name="arch" type="xml"> |
|||
<calendar string="Calendar" color="model_description" date_start="date_start" date_delay="duration"> |
|||
<field name="name"/> |
|||
</calendar> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.ui.view" id="super_calendar_search"> |
|||
<field name="name">super_calendar_search</field> |
|||
<field name="model">super.calendar</field> |
|||
<field name="arch" type="xml"> |
|||
<search string="Search Calendar" > |
|||
<field name="name"/> |
|||
<field name="configurator_id" select="1"/> |
|||
<field name="model_id" select="1"/> |
|||
<field name="model_description" select="1"/> |
|||
<field name="user_id" widget="selection" > |
|||
<filter domain="[('user_id','=',uid)]" help="My Items" icon="terp-personal"/> |
|||
</field> |
|||
<newline/> |
|||
<group expand="0" string="Extended Filters..." colspan="4" col="8"> |
|||
<field name="date_start" /> |
|||
<!--<field name="date_stop" />--> |
|||
<field name="duration" /> |
|||
</group> |
|||
</search> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.actions.act_window" id="super_calendar_action"> |
|||
<field name="name">Super Calendar</field> |
|||
<field name="res_model">super.calendar</field> |
|||
<field name="view_type">form</field> |
|||
<field name="view_mode">calendar,tree,form</field> |
|||
<field name="view_id" ref="super_calendar"/> |
|||
</record> |
|||
|
|||
<menuitem id="super_calendar_menu" name="Super Calendar" action="super_calendar_action"/> |
|||
<menuitem id="super_calendar_calendar" name="Calendar" parent="super_calendar_menu" /> |
|||
<menuitem id="super_calendar_calendar_calendar" name="Calendar" parent="super_calendar_calendar" action="super_calendar_action"/> |
|||
<menuitem id="super_calendar_configuration" name="Configuration" parent="super_calendar_menu" /> |
|||
<menuitem id="super_calendar_configurators" name="Configurators" parent="super_calendar_configuration" action="super_calendar_configurator"/> |
|||
</data> |
|||
</openerp> |
@ -0,0 +1,22 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# This module copyright (C) 2012 Therp BV (<http://therp.nl>). |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
import users_ldap_groups |
@ -0,0 +1,61 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# This module copyright (C) 2012 Therp BV (<http://therp.nl>). |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
{ |
|||
"name": "Groups assignment", |
|||
"version": "1.2", |
|||
"depends": ["auth_ldap"], |
|||
"author": "Therp BV", |
|||
"description": """ |
|||
Adds user accounts to groups based on rules defined by the administrator. |
|||
|
|||
Usage: |
|||
|
|||
Define mappings in Settings->Companies->[your company]->tab configuration->[your |
|||
ldap server]. |
|||
|
|||
Decide whether you want only groups mapped from ldap (Only ldap groups=y) or a |
|||
mix of manually set groups and ldap groups (Only ldap groups=n). Setting this to |
|||
'no' will result in users never losing privileges when you remove them from a |
|||
ldap group, so that's a potential security issue. It is still the default to |
|||
prevent losing group information by accident. |
|||
|
|||
For active directory, use LDAP attribute 'memberOf' and operator 'contains'. |
|||
Fill in the DN of the windows group as value and choose an OpenERP group users |
|||
with this windows group are to be assigned to. |
|||
|
|||
For posix accounts, use operator 'query' and a value like |
|||
(&(cn=bzr)(objectClass=posixGroup)(memberUid=$uid)) |
|||
|
|||
The operator query matches if the filter in value returns something, and value |
|||
can contain $[attribute] which will be replaced by the first value of the |
|||
user's ldap record's attribute named [attribute]. |
|||
""", |
|||
"category": "Tools", |
|||
"data": [ |
|||
'users_ldap_groups.xml', |
|||
'security/ir.model.access.csv', |
|||
], |
|||
"installable": True, |
|||
"external_dependencies": { |
|||
'python': ['ldap'], |
|||
}, |
|||
} |
@ -0,0 +1,16 @@ |
|||
# Translation of OpenERP Server. |
|||
# This file contains the translation of the following modules: |
|||
# |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: OpenERP Server 7.0\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2014-03-14 17:41+0000\n" |
|||
"PO-Revision-Date: 2014-03-14 17:41+0000\n" |
|||
"Last-Translator: <>\n" |
|||
"Language-Team: \n" |
|||
"MIME-Version: 1.0\n" |
|||
"Content-Type: text/plain; charset=UTF-8\n" |
|||
"Content-Transfer-Encoding: \n" |
|||
"Plural-Forms: \n" |
|||
|
@ -0,0 +1,2 @@ |
|||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink |
|||
access_res_company_ldap_groups,res_company_ldap_groups,model_res_company_ldap_group_mapping,base.group_system,1,1,1,1 |
@ -0,0 +1,107 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# This module copyright (C) 2012 Therp BV (<http://therp.nl>). |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
from openerp.osv import fields, orm |
|||
import logging |
|||
import users_ldap_groups_operators |
|||
import inspect |
|||
|
|||
|
|||
class CompanyLDAPGroupMapping(orm.Model): |
|||
_name = 'res.company.ldap.group_mapping' |
|||
_rec_name = 'ldap_attribute' |
|||
_order = 'ldap_attribute' |
|||
|
|||
def _get_operators(self, cr, uid, context=None): |
|||
operators = [] |
|||
members = inspect.getmembers( |
|||
users_ldap_groups_operators, |
|||
lambda cls: inspect.isclass(cls) |
|||
and cls != users_ldap_groups_operators.LDAPOperator) |
|||
for name, operator in members: |
|||
operators.append((name, name)) |
|||
return tuple(operators) |
|||
|
|||
_columns = { |
|||
'ldap_id': fields.many2one('res.company.ldap', 'LDAP server', required=True), |
|||
'ldap_attribute': fields.char( |
|||
'LDAP attribute', size=64, |
|||
help='The LDAP attribute to check.\n' |
|||
'For active directory, use memberOf.'), |
|||
'operator': fields.selection( |
|||
_get_operators, 'Operator', |
|||
help='The operator to check the attribute against the value\n' |
|||
'For active directory, use \'contains\'', required=True), |
|||
'value': fields.char( |
|||
'Value', size=1024, |
|||
help='The value to check the attribute against.\n' |
|||
'For active directory, use the dn of the desired group', |
|||
required=True), |
|||
'group': fields.many2one( |
|||
'res.groups', 'OpenERP group', |
|||
help='The OpenERP group to assign', required=True), |
|||
} |
|||
|
|||
|
|||
class CompanyLDAP(orm.Model): |
|||
_inherit = 'res.company.ldap' |
|||
|
|||
_columns = { |
|||
'group_mappings': fields.one2many( |
|||
'res.company.ldap.group_mapping', |
|||
'ldap_id', 'Group mappings', |
|||
help='Define how OpenERP groups are assigned to ldap users'), |
|||
'only_ldap_groups': fields.boolean( |
|||
'Only ldap groups', |
|||
help='If this is checked, manual changes to group membership are ' |
|||
'undone on every login (so OpenERP groups are always synchronous ' |
|||
'with LDAP groups). If not, manually added groups are preserved.') |
|||
} |
|||
|
|||
_default = { |
|||
'only_ldap_groups': False, |
|||
} |
|||
|
|||
def get_or_create_user(self, cr, uid, conf, login, ldap_entry, context=None): |
|||
user_id = super(CompanyLDAP, self).get_or_create_user(cr, uid, conf, login, |
|||
ldap_entry, context) |
|||
if not user_id: |
|||
return user_id |
|||
logger = logging.getLogger('users_ldap_groups') |
|||
mappingobj = self.pool.get('res.company.ldap.group_mapping') |
|||
userobj = self.pool.get('res.users') |
|||
conf_all = self.read(cr, uid, conf['id'], ['only_ldap_groups']) |
|||
if(conf_all['only_ldap_groups']): |
|||
logger.debug('deleting all groups from user %d' % user_id) |
|||
userobj.write(cr, uid, [user_id], {'groups_id': [(5, )]}, context=context) |
|||
|
|||
for mapping in mappingobj.read(cr, uid, mappingobj.search( |
|||
cr, uid, [('ldap_id', '=', conf['id'])]), []): |
|||
operator = getattr(users_ldap_groups_operators, mapping['operator'])() |
|||
logger.debug('checking mapping %s' % mapping) |
|||
if operator.check_value(ldap_entry, mapping['ldap_attribute'], |
|||
mapping['value'], conf, self, logger): |
|||
logger.debug('adding user %d to group %s' % |
|||
(user_id, mapping['group'][1])) |
|||
userobj.write(cr, uid, [user_id], |
|||
{'groups_id': [(4, mapping['group'][0])]}, |
|||
context=context) |
|||
return user_id |
@ -0,0 +1,27 @@ |
|||
<?xml version="1.0"?> |
|||
<openerp> |
|||
<data> |
|||
<record model="ir.ui.view" id="company_form_view"> |
|||
<field name="name">res.company.form.inherit.users_ldap_groups</field> |
|||
<field name="model">res.company</field> |
|||
<field name="inherit_id" ref="auth_ldap.company_form_view"/> |
|||
<field name="arch" type="xml"> |
|||
|
|||
<xpath expr="//form[@string='LDAP Configuration']" position="inside"> |
|||
<group string="Map User Groups" > |
|||
<field name="only_ldap_groups" /> |
|||
<field name="group_mappings" colspan="4" nolabel="1"> |
|||
<tree editable="top"> |
|||
<field name="ldap_attribute" attrs="{'required': [('operator','not in',['query'])], 'readonly': [('operator','in',['query'])]}" /> |
|||
<field name="operator" /> |
|||
<field name="value" /> |
|||
<field name="group" /> |
|||
</tree> |
|||
</field> |
|||
</group> |
|||
</xpath> |
|||
|
|||
</field> |
|||
</record> |
|||
</data> |
|||
</openerp> |
@ -0,0 +1,47 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# This module copyright (C) 2012 Therp BV (<http://therp.nl>). |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
from string import Template |
|||
|
|||
|
|||
class LDAPOperator: |
|||
pass |
|||
|
|||
|
|||
class contains(LDAPOperator): |
|||
def check_value(self, ldap_entry, attribute, value, ldap_config, company, logger): |
|||
return (attribute in ldap_entry[1]) and (value in ldap_entry[1][attribute]) |
|||
|
|||
|
|||
class equals(LDAPOperator): |
|||
def check_value(self, ldap_entry, attribute, value, ldap_config, company, logger): |
|||
return attribute in ldap_entry[1] and unicode(value) == unicode(ldap_entry[1][attribute]) |
|||
|
|||
|
|||
class query(LDAPOperator): |
|||
def check_value(self, ldap_entry, attribute, value, ldap_config, company, logger): |
|||
query_string = Template(value).safe_substitute(dict( |
|||
[(attr, ldap_entry[1][attribute][0]) for attr in ldap_entry[1]] |
|||
) |
|||
) |
|||
logger.debug('evaluating query group mapping, filter: %s' % query_string) |
|||
results = company.query(ldap_config, query_string) |
|||
logger.debug(results) |
|||
return bool(results) |
Some files were not shown because too many files changed in this diff
Write
Preview
Loading…
Cancel
Save
Reference in new issue