Initial import
[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
34 # Minimal transaction support. FIXME: Integrate transactions into the
35 # rest of the modules. For example, as a global (g_transaction
36 # imported from a common module) then used everywhere a transaction is
37 # needed. See Python 2.5 'with' statement that could help to run a
38 # transaction and finish it cleanly. (Emulating Common Lisp special
39 # variable.) -> Update: see _t below.
40
41 # The current transaction
42 _t = 0
43
44 # With Python 2.5 or above:
45 #     ...
46 #     with CurrentTransaction( n ) :
47 #         BLOCK
48 #     ...
49 class CurrentTransaction( object ) :
50     def __init__( self , transaction ) :
51         self._t = transaction
52         self._old = None
53     def __enter__( self ) :
54         global _t
55         self._old = _t
56         _t = self._t
57     def __exit__( self , a , b , c ) :
58         global _t
59         assert self._old is not None
60         _t = self._old
61
62 # For Python 2.4:
63 def _with( o , fun , args = () ) :
64     o.__enter__()
65     try :
66         return fun( *args )
67     finally :
68         o.__exit__( None , None , None )
69
70 def withCurrentTransaction( n , fun ) :
71     return _with( CurrentTransaction( n ) , fun )
72
73 def withTransaction( fun , uid = g_ALL_USERS , password = None , ttl = 0 ) :
74     n = begin( uid , password , ttl )
75     try :
76         _with( CurrentTransaction( n ) , fun , ( Transaction( n ) , ) )
77     finally :
78         # If the transaction still exist, cancel it inconditionnaly.
79         lib.rsbac_list_ta_forget( n , password )
80
81 def begin( uid = g_ALL_USERS , password = None , ttl = 0 ) :
82     value = headers.rsbac_list_ta_number_t()
83     raiseIfError( lib.rsbac_list_ta_begin( ttl , byref( value ) ,
84                                            uid , password ) )
85     return int( value.value )
86
87 def refresh( transaction , password = None , ttl = 0 ) :
88     raiseIfError( lib.rsbac_list_ta_refresh( ttl , transaction ,
89                                              password ) )
90
91 def commit( transaction , password = None ) :
92     raiseIfError( lib.rsbac_list_ta_commit( transaction , password ) )
93
94 def forget( transaction , password = None ) :
95     raiseIfError( lib.rsbac_list_ta_forget( transaction , password ) )
96
97 class Transaction( object ) :
98     def __init__( self , id , password = None ) :
99         self.id = id
100         self.password = password
101     def __repr__( self ) :
102         return '<Transaction %d>' % ( self.id , )
103     def refresh( self , ttl = None ) :
104         return refresh( self.id , self.password , ttlToInt( ttl ) )
105     def commit( self ) :
106         return commit( self.id , self.password )
107     def forget( self ) :
108         return forget( self.id , self.password )
109
110 # Local Variables:
111 # indent-tabs-mode: nil
112 # python-indent: 4
113 # End: