Added acl.grant and acl.revoke functions.
[py-rsbac] / rsbac / transaction.py
1 # -*- coding:utf-8 -*-
2
3 # py-rsbac - RSBAC Python bindings
4 # Copyright (C) 2006  Frederic Jolliton <pyrsbac@tuxee.net>
5
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
20 __all__ = [ 'CurrentTransaction' , 'Transaction' ,
21             'withCurrentTransaction' , 'withTransaction' ]
22
23 # Duplicated in um.py
24 g_NO_USER = -3
25 g_ALL_USERS = -4
26 g_NO_GROUP = -3
27 g_ALL_GROUPS = -4
28
29 from ctypes import byref
30
31 from rsbac import headers, lib
32 from rsbac.errors import raiseIfError
33 from rsbac._utils import intToTtl, ttlToInt, unlimitedTtl
34
35 # Minimal transaction support. FIXME: Integrate transactions into the
36 # rest of the modules. For example, as a global (g_transaction
37 # imported from a common module) then used everywhere a transaction is
38 # needed. See Python 2.5 'with' statement that could help to run a
39 # transaction and finish it cleanly. (Emulating Common Lisp special
40 # variable.) -> Update: see _t below.
41
42 # The current transaction
43 _t = 0
44
45 # With Python 2.5 or above:
46 #     ...
47 #     with CurrentTransaction( n ) :
48 #         BLOCK
49 #     ...
50 class CurrentTransaction( object ) :
51     __slots__ = ( '_t' , '_old' )
52     def __init__( self , transaction ) :
53         self._t = transaction
54         self._old = None
55     def __enter__( self ) :
56         global _t
57         self._old = _t
58         _t = self._t
59     def __exit__( self , a , b , c ) :
60         global _t
61         assert self._old is not None
62         _t = self._old
63
64 # For Python 2.4:
65 def _with( o , fun , args = () ) :
66     o.__enter__()
67     try :
68         return fun( *args )
69     finally :
70         o.__exit__( None , None , None )
71
72 def withCurrentTransaction( n , fun ) :
73     return _with( CurrentTransaction( n ) , fun )
74
75 def withTransaction( fun , uid = g_ALL_USERS , password = None , ttl = unlimitedTtl ) :
76     ttl = ttlToInt( ttl )
77     n = begin( uid , password , ttl )
78     try :
79         _with( CurrentTransaction( n ) , fun , ( Transaction( n ) , ) )
80     finally :
81         # If the transaction still exist, cancel it inconditionnaly.
82         # This assume that the behavior of forget() on a non-existing
83         # transaction is fine.
84         lib.rsbac_list_ta_forget( n , password )
85
86 #--[ Low level ]--------------------------------------------------------------
87
88 def begin( uid = g_ALL_USERS , password = None , ttl = 0 ) :
89     value = headers.rsbac_list_ta_number_t()
90     raiseIfError( lib.rsbac_list_ta_begin( ttl , byref( value ) ,
91                                            uid , password ) )
92     return int( value.value )
93
94 def refresh( transaction , password = None , ttl = 0 ) :
95     raiseIfError( lib.rsbac_list_ta_refresh( ttl , transaction ,
96                                              password ) )
97
98 def commit( transaction , password = None ) :
99     raiseIfError( lib.rsbac_list_ta_commit( transaction , password ) )
100
101 def forget( transaction , password = None ) :
102     raiseIfError( lib.rsbac_list_ta_forget( transaction , password ) )
103
104 #--[ Wrapper ]----------------------------------------------------------------
105
106 class Transaction( object ) :
107     __slots__ = ( 'id' , 'password' )
108     def __init__( self , id , password = None ) :
109         self.id = id
110         self.password = password
111     def __repr__( self ) :
112         return '<Transaction %d>' % ( self.id , )
113     def refresh( self , ttl = unlimitedTtl ) :
114         return refresh( self.id , self.password , ttlToInt( ttl ) )
115     def commit( self ) :
116         return commit( self.id , self.password )
117     def forget( self ) :
118         return forget( self.id , self.password )
119
120 # Local Variables:
121 # indent-tabs-mode: nil
122 # python-indent: 4
123 # End: