book/line: berechtigungen für owner, beobachter, bearbeiter + tests
This commit is contained in:
parent
654e9d2ee7
commit
b9bb433c39
9 changed files with 584 additions and 3 deletions
15
book.py
15
book.py
|
@ -7,6 +7,7 @@ from trytond.model import Workflow, ModelView, ModelSQL, fields, Check
|
||||||
from trytond.pyson import Eval
|
from trytond.pyson import Eval
|
||||||
from trytond.exceptions import UserError
|
from trytond.exceptions import UserError
|
||||||
from trytond.i18n import gettext
|
from trytond.i18n import gettext
|
||||||
|
from trytond.transaction import Transaction
|
||||||
|
|
||||||
|
|
||||||
STATES = {
|
STATES = {
|
||||||
|
@ -30,6 +31,14 @@ class Book(Workflow, ModelSQL, ModelView):
|
||||||
btype = fields.Many2One(string='Type', required=True,
|
btype = fields.Many2One(string='Type', required=True,
|
||||||
model_name='cashbook.type', ondelete='RESTRICT',
|
model_name='cashbook.type', ondelete='RESTRICT',
|
||||||
states=STATES, depends=DEPENDS)
|
states=STATES, depends=DEPENDS)
|
||||||
|
owner = fields.Many2One(string='Owner', required=True, select=True,
|
||||||
|
model_name='res.user', ondelete='SET NULL')
|
||||||
|
reviewer = fields.Many2One(string='Reviewer', select=True,
|
||||||
|
help='Group of users who have write access to the cashbook.',
|
||||||
|
model_name='res.group', ondelete='SET NULL')
|
||||||
|
observer = fields.Many2One(string='Observer', select=True,
|
||||||
|
help='Group of users who have read-only access to the cashbook.',
|
||||||
|
model_name='res.group', ondelete='SET NULL')
|
||||||
lines = fields.One2Many(string='Lines', field='cashbook',
|
lines = fields.One2Many(string='Lines', field='cashbook',
|
||||||
model_name='cashbook.line',
|
model_name='cashbook.line',
|
||||||
states=STATES, depends=DEPENDS)
|
states=STATES, depends=DEPENDS)
|
||||||
|
@ -71,6 +80,12 @@ class Book(Workflow, ModelSQL, ModelView):
|
||||||
def default_state(cls):
|
def default_state(cls):
|
||||||
return 'open'
|
return 'open'
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def default_owner(cls):
|
||||||
|
""" default: current user
|
||||||
|
"""
|
||||||
|
return Transaction().user
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ModelView.button
|
@ModelView.button
|
||||||
@Workflow.transition('open')
|
@Workflow.transition('open')
|
||||||
|
|
44
book.xml
44
book.xml
|
@ -63,6 +63,50 @@ full copyright notices and license terms. -->
|
||||||
<field name="perm_delete" eval="False"/>
|
<field name="perm_delete" eval="False"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
<!-- permission by rule - admin -->
|
||||||
|
<record model="ir.rule.group" id="rg_book_write_adm">
|
||||||
|
<field name="model" search="[('model', '=', 'cashbook.book')]"/>
|
||||||
|
<field name="name">Administrators: Cashbook read/write</field>
|
||||||
|
<field name="global_p" eval="False"/>
|
||||||
|
<field name="default_p" eval="False"/>
|
||||||
|
<field name="perm_read" eval="True"/>
|
||||||
|
<field name="perm_write" eval="True"/>
|
||||||
|
<field name="perm_create" eval="True"/>
|
||||||
|
<field name="perm_delete" eval="True"/>
|
||||||
|
</record>
|
||||||
|
<record model="ir.rule" id="rg_book_write_adm-1">
|
||||||
|
<field name="domain" eval="[]" pyson="1"/>
|
||||||
|
<field name="rule_group" ref="rg_book_write_adm"/>
|
||||||
|
</record>
|
||||||
|
<record model="ir.rule.group-res.group" id="rg_book_write_adm-group_admin">
|
||||||
|
<field name="rule_group" ref="rg_book_write_adm"/>
|
||||||
|
<field name="group" ref="res.group_admin"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- permission by rule - read: owner, reviewer, observer -->
|
||||||
|
<record model="ir.rule.group" id="rg_book_read">
|
||||||
|
<field name="model" search="[('model', '=', 'cashbook.book')]"/>
|
||||||
|
<field name="name">Owners, observers and reviewers: Cashbook read</field>
|
||||||
|
<field name="global_p" eval="False"/>
|
||||||
|
<field name="default_p" eval="False"/>
|
||||||
|
<field name="perm_read" eval="True"/>
|
||||||
|
<field name="perm_write" eval="False"/>
|
||||||
|
<field name="perm_create" eval="False"/>
|
||||||
|
<field name="perm_delete" eval="False"/>
|
||||||
|
</record>
|
||||||
|
<record model="ir.rule" id="rg_book_read-1">
|
||||||
|
<field name="domain" eval="['OR',
|
||||||
|
('owner.id', '=', Eval('user', {}).get('id', -1)),
|
||||||
|
('observer.id', 'in', Eval('user', {}).get('groups', [])),
|
||||||
|
('reviewer.id', 'in', Eval('user', {}).get('groups', [])),
|
||||||
|
]" pyson="1"/>
|
||||||
|
<field name="rule_group" ref="rg_book_read"/>
|
||||||
|
</record>
|
||||||
|
<record model="ir.rule.group-res.group" id="rg_book_read-group_cashbook">
|
||||||
|
<field name="rule_group" ref="rg_book_read"/>
|
||||||
|
<field name="group" ref="group_cashbook"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
<!-- button - open -->
|
<!-- button - open -->
|
||||||
<record model="ir.model.button" id="book_wfopen_button">
|
<record model="ir.model.button" id="book_wfopen_button">
|
||||||
<field name="name">wfopen</field>
|
<field name="name">wfopen</field>
|
||||||
|
|
68
line.xml
68
line.xml
|
@ -72,7 +72,7 @@ full copyright notices and license terms. -->
|
||||||
<field name="perm_create" eval="True"/>
|
<field name="perm_create" eval="True"/>
|
||||||
<field name="perm_delete" eval="True"/>
|
<field name="perm_delete" eval="True"/>
|
||||||
</record>
|
</record>
|
||||||
<!-- cashbook: read -->
|
<!-- cashbook: read/write -->
|
||||||
<record model="ir.model.access" id="access_line-group_cashbook">
|
<record model="ir.model.access" id="access_line-group_cashbook">
|
||||||
<field name="model" search="[('model', '=', 'cashbook.line')]"/>
|
<field name="model" search="[('model', '=', 'cashbook.line')]"/>
|
||||||
<field name="group" ref="group_cashbook"/>
|
<field name="group" ref="group_cashbook"/>
|
||||||
|
@ -82,6 +82,72 @@ full copyright notices and license terms. -->
|
||||||
<field name="perm_delete" eval="True"/>
|
<field name="perm_delete" eval="True"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
<!-- permission by rule - admin -->
|
||||||
|
<record model="ir.rule.group" id="rg_line_write_adm">
|
||||||
|
<field name="model" search="[('model', '=', 'cashbook.line')]"/>
|
||||||
|
<field name="name">Administrators: Cashbook line read/write</field>
|
||||||
|
<field name="global_p" eval="False"/>
|
||||||
|
<field name="default_p" eval="False"/>
|
||||||
|
<field name="perm_read" eval="True"/>
|
||||||
|
<field name="perm_write" eval="True"/>
|
||||||
|
<field name="perm_create" eval="True"/>
|
||||||
|
<field name="perm_delete" eval="True"/>
|
||||||
|
</record>
|
||||||
|
<record model="ir.rule" id="rg_line_write_adm-1">
|
||||||
|
<field name="domain" eval="[]" pyson="1"/>
|
||||||
|
<field name="rule_group" ref="rg_line_write_adm"/>
|
||||||
|
</record>
|
||||||
|
<record model="ir.rule.group-res.group" id="rg_line_write_adm-group_admin">
|
||||||
|
<field name="rule_group" ref="rg_line_write_adm"/>
|
||||||
|
<field name="group" ref="res.group_admin"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- permission by rule - read/write: owner, reviewer -->
|
||||||
|
<record model="ir.rule.group" id="rg_line_write">
|
||||||
|
<field name="model" search="[('model', '=', 'cashbook.line')]"/>
|
||||||
|
<field name="name">Owners and reviewers: Cashbook line write</field>
|
||||||
|
<field name="global_p" eval="False"/>
|
||||||
|
<field name="default_p" eval="False"/>
|
||||||
|
<field name="perm_read" eval="True"/>
|
||||||
|
<field name="perm_write" eval="True"/>
|
||||||
|
<field name="perm_create" eval="True"/>
|
||||||
|
<field name="perm_delete" eval="True"/>
|
||||||
|
</record>
|
||||||
|
<record model="ir.rule" id="rg_line_write-1">
|
||||||
|
<field name="domain" eval="['OR',
|
||||||
|
('cashbook.owner.id', '=', Eval('user', {}).get('id', -1)),
|
||||||
|
('cashbook.reviewer.id', 'in', Eval('user', {}).get('groups', [])),
|
||||||
|
]" pyson="1"/>
|
||||||
|
<field name="rule_group" ref="rg_line_write"/>
|
||||||
|
</record>
|
||||||
|
<record model="ir.rule.group-res.group" id="rg_line_write-group_cashbook">
|
||||||
|
<field name="rule_group" ref="rg_line_write"/>
|
||||||
|
<field name="group" ref="group_cashbook"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- permission by rule - read: observer -->
|
||||||
|
<record model="ir.rule.group" id="rg_line_read">
|
||||||
|
<field name="model" search="[('model', '=', 'cashbook.line')]"/>
|
||||||
|
<field name="name">Observer: Cashbook line read</field>
|
||||||
|
<field name="global_p" eval="False"/>
|
||||||
|
<field name="default_p" eval="False"/>
|
||||||
|
<field name="perm_read" eval="True"/>
|
||||||
|
<field name="perm_write" eval="False"/>
|
||||||
|
<field name="perm_create" eval="False"/>
|
||||||
|
<field name="perm_delete" eval="False"/>
|
||||||
|
</record>
|
||||||
|
<record model="ir.rule" id="rg_line_read-1">
|
||||||
|
<field name="domain" eval="[
|
||||||
|
('cashbook.observer.id', 'in', Eval('user', {}).get('groups', [])),
|
||||||
|
]" pyson="1"/>
|
||||||
|
<field name="rule_group" ref="rg_line_read"/>
|
||||||
|
</record>
|
||||||
|
<record model="ir.rule.group-res.group" id="rg_line_read-group_cashbook">
|
||||||
|
<field name="rule_group" ref="rg_line_read"/>
|
||||||
|
<field name="group" ref="group_cashbook"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
|
||||||
<!-- button - edit -->
|
<!-- button - edit -->
|
||||||
<record model="ir.model.button" id="line_wfedit_button">
|
<record model="ir.model.button" id="line_wfedit_button">
|
||||||
<field name="name">wfedit</field>
|
<field name="name">wfedit</field>
|
||||||
|
|
49
locale/de.po
49
locale/de.po
|
@ -18,7 +18,6 @@ msgctxt "model:ir.message,text:msg_line_wrong_state_value"
|
||||||
msgid "Invalid value of the field 'Status', allowed: edit, check, done."
|
msgid "Invalid value of the field 'Status', allowed: edit, check, done."
|
||||||
msgstr "Ungültiger Wert des Feldes 'Status', erlaubt: edit, check, done."
|
msgstr "Ungültiger Wert des Feldes 'Status', erlaubt: edit, check, done."
|
||||||
|
|
||||||
|
|
||||||
msgctxt "model:ir.message,text:msg_book_wrong_state_value"
|
msgctxt "model:ir.message,text:msg_book_wrong_state_value"
|
||||||
msgid "Invalid value of the field 'Status', allowed: open, closed, archive."
|
msgid "Invalid value of the field 'Status', allowed: open, closed, archive."
|
||||||
msgstr "Ungültiger Wert des Feldes 'Status', erlaubt: open, closed, archive."
|
msgstr "Ungültiger Wert des Feldes 'Status', erlaubt: open, closed, archive."
|
||||||
|
@ -57,6 +56,30 @@ msgid "Cashbook - WF - Done"
|
||||||
msgstr "Kassenbuch - WF - Fertig"
|
msgstr "Kassenbuch - WF - Fertig"
|
||||||
|
|
||||||
|
|
||||||
|
#################
|
||||||
|
# ir.rule.group #
|
||||||
|
#################
|
||||||
|
msgctxt "model:ir.rule.group,name:rg_book_read"
|
||||||
|
msgid "Owners, observers and reviewers: Cashbook read"
|
||||||
|
msgstr "Eigentümer, Beobachter und Bearbeiter: Kassenbuch lesen"
|
||||||
|
|
||||||
|
msgctxt "model:ir.rule.group,name:rg_book_write_adm"
|
||||||
|
msgid "Administrators: Cashbook read/write"
|
||||||
|
msgstr "Administratoren: Kassenbuch bearbeiten"
|
||||||
|
|
||||||
|
msgctxt "model:ir.rule.group,name:rg_line_write_adm"
|
||||||
|
msgid "Administrators: Cashbook line read/write"
|
||||||
|
msgstr "Administratoren: Kassenbuchzeile bearbeiten"
|
||||||
|
|
||||||
|
msgctxt "model:ir.rule.group,name:rg_line_write"
|
||||||
|
msgid "Owners and reviewers: Cashbook line write"
|
||||||
|
msgstr "Eigentümer und Bearbeiter: Kassenbuchzeile bearbeiten"
|
||||||
|
|
||||||
|
msgctxt "model:ir.rule.group,name:rg_line_read"
|
||||||
|
msgid "Observer: Cashbook line read"
|
||||||
|
msgstr "Beobachter: Kassenbuchzeile lesen"
|
||||||
|
|
||||||
|
|
||||||
##############
|
##############
|
||||||
# ir.ui.menu #
|
# ir.ui.menu #
|
||||||
##############
|
##############
|
||||||
|
@ -136,6 +159,10 @@ msgctxt "model:cashbook.book,name:"
|
||||||
msgid "Cashbook"
|
msgid "Cashbook"
|
||||||
msgstr "Kassenbuch"
|
msgstr "Kassenbuch"
|
||||||
|
|
||||||
|
msgctxt "view:cashbook.book:"
|
||||||
|
msgid "Owner & Authorizeds"
|
||||||
|
msgstr "Eigentümer & Autorisierte"
|
||||||
|
|
||||||
msgctxt "field:cashbook.book,name:"
|
msgctxt "field:cashbook.book,name:"
|
||||||
msgid "Name"
|
msgid "Name"
|
||||||
msgstr "Name"
|
msgstr "Name"
|
||||||
|
@ -160,6 +187,26 @@ msgctxt "selection:cashbook.book,state:"
|
||||||
msgid "Archive"
|
msgid "Archive"
|
||||||
msgstr "Archiv"
|
msgstr "Archiv"
|
||||||
|
|
||||||
|
msgctxt "field:cashbook.book,owner:"
|
||||||
|
msgid "Owner"
|
||||||
|
msgstr "Eigentümer"
|
||||||
|
|
||||||
|
msgctxt "field:cashbook.book,reviewer:"
|
||||||
|
msgid "Reviewer"
|
||||||
|
msgstr "Bearbeiter"
|
||||||
|
|
||||||
|
msgctxt "help:cashbook.book,reviewer:"
|
||||||
|
msgid "Group of users who have write access to the cashbook."
|
||||||
|
msgstr "Gruppe von Benutzern, die Schreibzugriff auf das Kassenbuch haben."
|
||||||
|
|
||||||
|
msgctxt "field:cashbook.book,observer:"
|
||||||
|
msgid "Observer"
|
||||||
|
msgstr "Betrachter"
|
||||||
|
|
||||||
|
msgctxt "help:cashbook.book,observer:"
|
||||||
|
msgid "Group of users who have read-only access to the cashbook."
|
||||||
|
msgstr "Gruppe von Benutzern, die nur Lesezugriff auf das Kassenbuch haben."
|
||||||
|
|
||||||
|
|
||||||
#################
|
#################
|
||||||
# cashbook.line #
|
# cashbook.line #
|
||||||
|
|
|
@ -173,4 +173,173 @@ class BookTestCase(ModuleTestCase):
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@with_transaction()
|
||||||
|
def test_book_permission_owner(self):
|
||||||
|
""" create book + 2x users, add users to group, check access
|
||||||
|
"""
|
||||||
|
pool = Pool()
|
||||||
|
ResUser = pool.get('res.user')
|
||||||
|
ResGroup = pool.get('res.group')
|
||||||
|
Book = pool.get('cashbook.book')
|
||||||
|
Types = pool.get('cashbook.type')
|
||||||
|
|
||||||
|
types, = Types.search([('short', '=', 'CAS')])
|
||||||
|
grp_cashbook, = ResGroup.search([('name', '=', 'Cashbook')])
|
||||||
|
usr_lst = ResUser.create([{
|
||||||
|
'login': 'frida',
|
||||||
|
'name': 'Frida',
|
||||||
|
'groups': [('add', [grp_cashbook.id])],
|
||||||
|
}, {
|
||||||
|
'login': 'diego',
|
||||||
|
'name': 'Diego',
|
||||||
|
'groups': [('add', [grp_cashbook.id])],
|
||||||
|
}])
|
||||||
|
self.assertEqual(len(usr_lst), 2)
|
||||||
|
self.assertEqual(usr_lst[0].name, 'Frida')
|
||||||
|
self.assertEqual(usr_lst[1].name, 'Diego')
|
||||||
|
|
||||||
|
book, = Book.create([{
|
||||||
|
'name': 'Fridas book',
|
||||||
|
'owner': usr_lst[0].id,
|
||||||
|
'btype': types.id,
|
||||||
|
}])
|
||||||
|
self.assertEqual(book.rec_name, 'Fridas book'),
|
||||||
|
self.assertEqual(book.owner.rec_name, 'Frida'),
|
||||||
|
|
||||||
|
with Transaction().set_context({
|
||||||
|
'_check_access': True,
|
||||||
|
}):
|
||||||
|
# change to user 'diego' , try access
|
||||||
|
with Transaction().set_user(usr_lst[1].id):
|
||||||
|
books = Book.search([])
|
||||||
|
self.assertEqual(len(books), 0)
|
||||||
|
|
||||||
|
# change to user 'frida' read/write book
|
||||||
|
with Transaction().set_user(usr_lst[0].id):
|
||||||
|
books = Book.search([])
|
||||||
|
self.assertEqual(len(books), 1)
|
||||||
|
self.assertEqual(books[0].rec_name, 'Fridas book')
|
||||||
|
|
||||||
|
self.assertRaisesRegex(UserError,
|
||||||
|
'You are not allowed to access "Cashbook".',
|
||||||
|
Book.write,
|
||||||
|
*[
|
||||||
|
books,
|
||||||
|
{
|
||||||
|
'name': 'Book2',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
@with_transaction()
|
||||||
|
def test_book_permission_reviewer(self):
|
||||||
|
""" create book + 2x users + 1x reviewer-group, add users to group, check access
|
||||||
|
"""
|
||||||
|
pool = Pool()
|
||||||
|
ResUser = pool.get('res.user')
|
||||||
|
ResGroup = pool.get('res.group')
|
||||||
|
Book = pool.get('cashbook.book')
|
||||||
|
Types = pool.get('cashbook.type')
|
||||||
|
|
||||||
|
types, = Types.search([('short', '=', 'CAS')])
|
||||||
|
grp_cashbook, = ResGroup.search([('name', '=', 'Cashbook')])
|
||||||
|
grp_reviewer, = ResGroup.create([{
|
||||||
|
'name': 'Cashbook Reviewer',
|
||||||
|
}])
|
||||||
|
|
||||||
|
usr_lst = ResUser.create([{
|
||||||
|
'login': 'frida',
|
||||||
|
'name': 'Frida',
|
||||||
|
'groups': [('add', [grp_cashbook.id])],
|
||||||
|
}, {
|
||||||
|
'login': 'diego',
|
||||||
|
'name': 'Diego',
|
||||||
|
'groups': [('add', [grp_cashbook.id, grp_reviewer.id])],
|
||||||
|
}])
|
||||||
|
self.assertEqual(len(usr_lst), 2)
|
||||||
|
self.assertEqual(usr_lst[0].name, 'Frida')
|
||||||
|
self.assertEqual(usr_lst[1].name, 'Diego')
|
||||||
|
|
||||||
|
# create cashbook
|
||||||
|
# add reviewer-group to allow read for users in group
|
||||||
|
book, = Book.create([{
|
||||||
|
'name': 'Fridas book',
|
||||||
|
'owner': usr_lst[0].id,
|
||||||
|
'reviewer': grp_reviewer.id,
|
||||||
|
'btype': types.id,
|
||||||
|
}])
|
||||||
|
self.assertEqual(book.rec_name, 'Fridas book'),
|
||||||
|
self.assertEqual(book.owner.rec_name, 'Frida'),
|
||||||
|
|
||||||
|
with Transaction().set_context({
|
||||||
|
'_check_access': True,
|
||||||
|
}):
|
||||||
|
# change to user 'diego' , try access
|
||||||
|
with Transaction().set_user(usr_lst[1].id):
|
||||||
|
books = Book.search([])
|
||||||
|
self.assertEqual(len(books), 1)
|
||||||
|
self.assertEqual(len(books[0].reviewer.users), 1)
|
||||||
|
self.assertEqual(books[0].reviewer.users[0].rec_name, 'Diego')
|
||||||
|
|
||||||
|
# change to user 'frida' read/write book
|
||||||
|
with Transaction().set_user(usr_lst[0].id):
|
||||||
|
books = Book.search([])
|
||||||
|
self.assertEqual(len(books), 1)
|
||||||
|
self.assertEqual(books[0].rec_name, 'Fridas book')
|
||||||
|
|
||||||
|
@with_transaction()
|
||||||
|
def test_book_permission_observer(self):
|
||||||
|
""" create book + 2x users + 1x observer-group, add users to group, check access
|
||||||
|
"""
|
||||||
|
pool = Pool()
|
||||||
|
ResUser = pool.get('res.user')
|
||||||
|
ResGroup = pool.get('res.group')
|
||||||
|
Book = pool.get('cashbook.book')
|
||||||
|
Types = pool.get('cashbook.type')
|
||||||
|
|
||||||
|
types, = Types.search([('short', '=', 'CAS')])
|
||||||
|
grp_cashbook, = ResGroup.search([('name', '=', 'Cashbook')])
|
||||||
|
grp_observer, = ResGroup.create([{
|
||||||
|
'name': 'Cashbook Observer',
|
||||||
|
}])
|
||||||
|
|
||||||
|
usr_lst = ResUser.create([{
|
||||||
|
'login': 'frida',
|
||||||
|
'name': 'Frida',
|
||||||
|
'groups': [('add', [grp_cashbook.id])],
|
||||||
|
}, {
|
||||||
|
'login': 'diego',
|
||||||
|
'name': 'Diego',
|
||||||
|
'groups': [('add', [grp_cashbook.id, grp_observer.id])],
|
||||||
|
}])
|
||||||
|
self.assertEqual(len(usr_lst), 2)
|
||||||
|
self.assertEqual(usr_lst[0].name, 'Frida')
|
||||||
|
self.assertEqual(usr_lst[1].name, 'Diego')
|
||||||
|
|
||||||
|
# create cashbook
|
||||||
|
# add observer-group to allow read for users in group
|
||||||
|
book, = Book.create([{
|
||||||
|
'name': 'Fridas book',
|
||||||
|
'owner': usr_lst[0].id,
|
||||||
|
'observer': grp_observer.id,
|
||||||
|
'btype': types.id,
|
||||||
|
}])
|
||||||
|
self.assertEqual(book.rec_name, 'Fridas book'),
|
||||||
|
self.assertEqual(book.owner.rec_name, 'Frida'),
|
||||||
|
|
||||||
|
with Transaction().set_context({
|
||||||
|
'_check_access': True,
|
||||||
|
}):
|
||||||
|
# change to user 'diego' , try access
|
||||||
|
with Transaction().set_user(usr_lst[1].id):
|
||||||
|
books = Book.search([])
|
||||||
|
self.assertEqual(len(books), 1)
|
||||||
|
self.assertEqual(len(books[0].observer.users), 1)
|
||||||
|
self.assertEqual(books[0].observer.users[0].rec_name, 'Diego')
|
||||||
|
|
||||||
|
# change to user 'frida' read/write book
|
||||||
|
with Transaction().set_user(usr_lst[0].id):
|
||||||
|
books = Book.search([])
|
||||||
|
self.assertEqual(len(books), 1)
|
||||||
|
self.assertEqual(books[0].rec_name, 'Fridas book')
|
||||||
|
|
||||||
# end BookTestCase
|
# end BookTestCase
|
||||||
|
|
|
@ -150,4 +150,216 @@ class LineTestCase(ModuleTestCase):
|
||||||
Lines.delete,
|
Lines.delete,
|
||||||
[book.lines[0]])
|
[book.lines[0]])
|
||||||
|
|
||||||
# end BookTestCase
|
@with_transaction()
|
||||||
|
def test_line_permission_owner(self):
|
||||||
|
""" create book+line + 2x users, add users to group, check access
|
||||||
|
"""
|
||||||
|
pool = Pool()
|
||||||
|
ResUser = pool.get('res.user')
|
||||||
|
ResGroup = pool.get('res.group')
|
||||||
|
Book = pool.get('cashbook.book')
|
||||||
|
Line = pool.get('cashbook.line')
|
||||||
|
Types = pool.get('cashbook.type')
|
||||||
|
|
||||||
|
types, = Types.search([('short', '=', 'CAS')])
|
||||||
|
grp_cashbook, = ResGroup.search([('name', '=', 'Cashbook')])
|
||||||
|
usr_lst = ResUser.create([{
|
||||||
|
'login': 'frida',
|
||||||
|
'name': 'Frida',
|
||||||
|
'groups': [('add', [grp_cashbook.id])],
|
||||||
|
}, {
|
||||||
|
'login': 'diego',
|
||||||
|
'name': 'Diego',
|
||||||
|
'groups': [('add', [grp_cashbook.id])],
|
||||||
|
}])
|
||||||
|
self.assertEqual(len(usr_lst), 2)
|
||||||
|
self.assertEqual(usr_lst[0].name, 'Frida')
|
||||||
|
self.assertEqual(usr_lst[1].name, 'Diego')
|
||||||
|
|
||||||
|
book, = Book.create([{
|
||||||
|
'name': 'Fridas book',
|
||||||
|
'owner': usr_lst[0].id,
|
||||||
|
'btype': types.id,
|
||||||
|
'lines': [('create', [{
|
||||||
|
'date': date(2022, 5, 1),
|
||||||
|
'description': 'Test 1',
|
||||||
|
}])],
|
||||||
|
}])
|
||||||
|
self.assertEqual(book.rec_name, 'Fridas book'),
|
||||||
|
self.assertEqual(book.owner.rec_name, 'Frida'),
|
||||||
|
|
||||||
|
with Transaction().set_context({
|
||||||
|
'_check_access': True,
|
||||||
|
}):
|
||||||
|
# change to user 'diego' , try access
|
||||||
|
with Transaction().set_user(usr_lst[1].id):
|
||||||
|
lines = Line.search([])
|
||||||
|
self.assertEqual(len(lines), 0)
|
||||||
|
|
||||||
|
# change to user 'frida' read/write book
|
||||||
|
with Transaction().set_user(usr_lst[0].id):
|
||||||
|
lines = Line.search([])
|
||||||
|
self.assertEqual(len(lines), 1)
|
||||||
|
self.assertEqual(lines[0].cashbook.rec_name, 'Fridas book')
|
||||||
|
self.assertEqual(lines[0].rec_name, '05/01/2022 Test 1')
|
||||||
|
|
||||||
|
Line.write(*[
|
||||||
|
lines,
|
||||||
|
{
|
||||||
|
'description': 'Test 2',
|
||||||
|
}])
|
||||||
|
self.assertEqual(lines[0].rec_name, '05/01/2022 Test 2')
|
||||||
|
|
||||||
|
@with_transaction()
|
||||||
|
def test_line_permission_reviewer(self):
|
||||||
|
""" create book+line + 2x users + 1x reviewer-group, add users to group, check access
|
||||||
|
"""
|
||||||
|
pool = Pool()
|
||||||
|
ResUser = pool.get('res.user')
|
||||||
|
ResGroup = pool.get('res.group')
|
||||||
|
Book = pool.get('cashbook.book')
|
||||||
|
Line = pool.get('cashbook.line')
|
||||||
|
Types = pool.get('cashbook.type')
|
||||||
|
|
||||||
|
types, = Types.search([('short', '=', 'CAS')])
|
||||||
|
grp_cashbook, = ResGroup.search([('name', '=', 'Cashbook')])
|
||||||
|
grp_reviewer, = ResGroup.create([{
|
||||||
|
'name': 'Cashbook Reviewer',
|
||||||
|
}])
|
||||||
|
|
||||||
|
usr_lst = ResUser.create([{
|
||||||
|
'login': 'frida',
|
||||||
|
'name': 'Frida',
|
||||||
|
'groups': [('add', [grp_cashbook.id])],
|
||||||
|
}, {
|
||||||
|
'login': 'diego',
|
||||||
|
'name': 'Diego',
|
||||||
|
'groups': [('add', [grp_cashbook.id, grp_reviewer.id])],
|
||||||
|
}])
|
||||||
|
self.assertEqual(len(usr_lst), 2)
|
||||||
|
self.assertEqual(usr_lst[0].name, 'Frida')
|
||||||
|
self.assertEqual(usr_lst[1].name, 'Diego')
|
||||||
|
|
||||||
|
# create cashbook
|
||||||
|
# add reviewer-group to allow write for users in group
|
||||||
|
book, = Book.create([{
|
||||||
|
'name': 'Fridas book',
|
||||||
|
'owner': usr_lst[0].id,
|
||||||
|
'reviewer': grp_reviewer.id,
|
||||||
|
'btype': types.id,
|
||||||
|
'lines': [('create', [{
|
||||||
|
'date': date(2022, 5, 1),
|
||||||
|
'description': 'Test 1',
|
||||||
|
}])],
|
||||||
|
}])
|
||||||
|
self.assertEqual(book.rec_name, 'Fridas book'),
|
||||||
|
self.assertEqual(book.owner.rec_name, 'Frida'),
|
||||||
|
|
||||||
|
with Transaction().set_context({
|
||||||
|
'_check_access': True,
|
||||||
|
}):
|
||||||
|
# change to user 'diego' , try access
|
||||||
|
with Transaction().set_user(usr_lst[1].id):
|
||||||
|
lines = Line.search([])
|
||||||
|
self.assertEqual(len(lines), 1)
|
||||||
|
self.assertEqual(len(lines[0].cashbook.reviewer.users), 1)
|
||||||
|
self.assertEqual(lines[0].cashbook.reviewer.users[0].rec_name, 'Diego')
|
||||||
|
self.assertEqual(lines[0].rec_name, '05/01/2022 Test 1')
|
||||||
|
Line.write(*[
|
||||||
|
lines,
|
||||||
|
{
|
||||||
|
'description': 'Test 2',
|
||||||
|
}])
|
||||||
|
self.assertEqual(lines[0].rec_name, '05/01/2022 Test 2')
|
||||||
|
|
||||||
|
# change to user 'frida' read/write line
|
||||||
|
with Transaction().set_user(usr_lst[0].id):
|
||||||
|
lines = Line.search([])
|
||||||
|
self.assertEqual(len(lines), 1)
|
||||||
|
self.assertEqual(lines[0].rec_name, '05/01/2022 Test 2')
|
||||||
|
Line.write(*[
|
||||||
|
lines,
|
||||||
|
{
|
||||||
|
'description': 'Test 3',
|
||||||
|
}])
|
||||||
|
self.assertEqual(lines[0].rec_name, '05/01/2022 Test 3')
|
||||||
|
|
||||||
|
@with_transaction()
|
||||||
|
def test_line_permission_observer(self):
|
||||||
|
""" create book+line + 2x users + 1x observer-group, add users to group, check access
|
||||||
|
"""
|
||||||
|
pool = Pool()
|
||||||
|
ResUser = pool.get('res.user')
|
||||||
|
ResGroup = pool.get('res.group')
|
||||||
|
Book = pool.get('cashbook.book')
|
||||||
|
Line = pool.get('cashbook.line')
|
||||||
|
Types = pool.get('cashbook.type')
|
||||||
|
|
||||||
|
types, = Types.search([('short', '=', 'CAS')])
|
||||||
|
grp_cashbook, = ResGroup.search([('name', '=', 'Cashbook')])
|
||||||
|
grp_observer, = ResGroup.create([{
|
||||||
|
'name': 'Cashbook Observer',
|
||||||
|
}])
|
||||||
|
|
||||||
|
usr_lst = ResUser.create([{
|
||||||
|
'login': 'frida',
|
||||||
|
'name': 'Frida',
|
||||||
|
'groups': [('add', [grp_cashbook.id])],
|
||||||
|
}, {
|
||||||
|
'login': 'diego',
|
||||||
|
'name': 'Diego',
|
||||||
|
'groups': [('add', [grp_cashbook.id, grp_observer.id])],
|
||||||
|
}])
|
||||||
|
self.assertEqual(len(usr_lst), 2)
|
||||||
|
self.assertEqual(usr_lst[0].name, 'Frida')
|
||||||
|
self.assertEqual(usr_lst[1].name, 'Diego')
|
||||||
|
|
||||||
|
# create cashbook
|
||||||
|
# add reviewer-group to allow write for users in group
|
||||||
|
book, = Book.create([{
|
||||||
|
'name': 'Fridas book',
|
||||||
|
'owner': usr_lst[0].id,
|
||||||
|
'observer': grp_observer.id,
|
||||||
|
'btype': types.id,
|
||||||
|
'lines': [('create', [{
|
||||||
|
'date': date(2022, 5, 1),
|
||||||
|
'description': 'Test 1',
|
||||||
|
}])],
|
||||||
|
}])
|
||||||
|
self.assertEqual(book.rec_name, 'Fridas book'),
|
||||||
|
self.assertEqual(book.owner.rec_name, 'Frida'),
|
||||||
|
|
||||||
|
with Transaction().set_context({
|
||||||
|
'_check_access': True,
|
||||||
|
}):
|
||||||
|
# change to user 'diego' , try access
|
||||||
|
with Transaction().set_user(usr_lst[1].id):
|
||||||
|
lines = Line.search([])
|
||||||
|
self.assertEqual(len(lines), 1)
|
||||||
|
self.assertEqual(len(lines[0].cashbook.observer.users), 1)
|
||||||
|
self.assertEqual(lines[0].cashbook.observer.users[0].rec_name, 'Diego')
|
||||||
|
self.assertEqual(lines[0].rec_name, '05/01/2022 Test 1')
|
||||||
|
|
||||||
|
self.assertRaisesRegex(UserError,
|
||||||
|
'You are not allowed to write to records "[0-9]{1,}" of "Cashbook Line" because of at least one of these rules:\nOwners and reviewers: Cashbook line write - ',
|
||||||
|
Line.write,
|
||||||
|
*[
|
||||||
|
lines,
|
||||||
|
{
|
||||||
|
'description': 'Test 2',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
# change to user 'frida' read/write line
|
||||||
|
with Transaction().set_user(usr_lst[0].id):
|
||||||
|
lines = Line.search([])
|
||||||
|
self.assertEqual(len(lines), 1)
|
||||||
|
self.assertEqual(lines[0].rec_name, '05/01/2022 Test 1')
|
||||||
|
Line.write(*[
|
||||||
|
lines,
|
||||||
|
{
|
||||||
|
'description': 'Test 2',
|
||||||
|
}])
|
||||||
|
self.assertEqual(lines[0].rec_name, '05/01/2022 Test 2')
|
||||||
|
|
||||||
|
# end LineTestCase
|
||||||
|
|
|
@ -16,4 +16,14 @@ full copyright notices and license terms. -->
|
||||||
<button name="wfarchive"/>
|
<button name="wfarchive"/>
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
|
<separator id="sepperm" string="Owner and Authorizeds" colspan="4"/>
|
||||||
|
<label name="owner"/>
|
||||||
|
<field name="owner"/>
|
||||||
|
<newline/>
|
||||||
|
|
||||||
|
<label name="reviewer"/>
|
||||||
|
<field name="reviewer"/>
|
||||||
|
<label name="observer"/>
|
||||||
|
<field name="observer"/>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -5,6 +5,9 @@ full copyright notices and license terms. -->
|
||||||
<tree>
|
<tree>
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="btype"/>
|
<field name="btype"/>
|
||||||
|
<field name="owner"/>
|
||||||
|
<field name="reviewer"/>
|
||||||
|
<field name="observer"/>
|
||||||
<field name="state"/>
|
<field name="state"/>
|
||||||
<button name="wfopen"/>
|
<button name="wfopen"/>
|
||||||
<button name="wfclosed"/>
|
<button name="wfclosed"/>
|
||||||
|
|
|
@ -7,6 +7,7 @@ from trytond.model import ModelView, ModelSQL, fields
|
||||||
from trytond.pyson import PYSONEncoder
|
from trytond.pyson import PYSONEncoder
|
||||||
from trytond.wizard import Wizard, StateView, StateAction, Button
|
from trytond.wizard import Wizard, StateView, StateAction, Button
|
||||||
from trytond.i18n import gettext
|
from trytond.i18n import gettext
|
||||||
|
from trytond.pool import Pool
|
||||||
|
|
||||||
|
|
||||||
class OpenCashBookStart(ModelView):
|
class OpenCashBookStart(ModelView):
|
||||||
|
@ -42,6 +43,20 @@ class OpenCashBook(Wizard):
|
||||||
])
|
])
|
||||||
open_ = StateAction('cashbook.act_line_view')
|
open_ = StateAction('cashbook.act_line_view')
|
||||||
|
|
||||||
|
def default_start(self, fields):
|
||||||
|
""" setup form
|
||||||
|
"""
|
||||||
|
Book = Pool().get('cashbook.book')
|
||||||
|
|
||||||
|
result = {}
|
||||||
|
|
||||||
|
books = Book.search([])
|
||||||
|
print('\n## books:', books)
|
||||||
|
if len(books) == 1:
|
||||||
|
result['cashbook'] = books[0].id
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
def do_open_(self, action):
|
def do_open_(self, action):
|
||||||
action['pyson_context'] = PYSONEncoder().encode({
|
action['pyson_context'] = PYSONEncoder().encode({
|
||||||
'cashbook': self.start.cashbook.id,
|
'cashbook': self.start.cashbook.id,
|
||||||
|
|
Loading…
Reference in a new issue