1 # -*- coding: iso-8859-1 -*-
3 MoinMoin - FusionForge session cookie authentication
5 @copyright: 2005 MoinMoin:AlexanderSchremmer (Thanks to Spreadshirt)
6 @copyright: 2011 Roland Mas
7 @license: GNU GPL, see COPYING for details.
19 from MoinMoin import user
20 from MoinMoin.auth import _PHPsessionParser, BaseAuth
22 perm_name = "plugin_moinmoin_access"
23 perm_map = { "Admins": 3,
27 class FusionForgeError(Exception):
28 def __init__(self, msg):
29 Exception.__init__(self, msg)
33 return "%s\n" % self.msg
36 class FusionForgeLink():
37 def get_config(self, varname, secname='core'):
38 if secname not in self.cachedconfig:
39 self.cachedconfig[secname] = {}
40 if varname not in self.cachedconfig[secname]:
41 self.cachedconfig[secname][varname] = \
42 subprocess.Popen(["@BINARY_PATH@/forge_get_config",
44 stdout=subprocess.PIPE).communicate()[0].rstrip('\n')
45 return self.cachedconfig[secname][varname]
47 def __init__(self, cookies=['session_ser'], autocreate=True):
48 self.cachedconfig = {}
49 self.database_host = self.get_config('database_host')
50 self.database_name = self.get_config('database_name')
51 self.database_user = self.get_config('database_user')
52 self.database_port = self.get_config('database_port')
53 self.database_password = self.get_config('database_password')
54 if (self.database_host != ''):
55 self._conn = psycopg2.connect(database=self.database_name,
56 user=self.database_user,
57 port=self.database_port,
58 password=self.database_password,
59 host=self.database_host)
61 self._conn = psycopg2.connect(database=self.database_name,
62 user=self.database_user,
63 port=self.database_port,
64 password=self.database_password)
66 # We never want to start transactions, all accesses here are read-only
68 self._conn.set_isolation_level \
69 (psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
70 logging.debug ("FusionForgeLink: __init__ done")
75 class FusionForgeSessionAuth(BaseAuth):
76 """ FusionForge session cookie authentication """
78 name = 'fusionforge_session'
79 logout_possible = False
81 def __init__(self, cookies=['session_ser'], autocreate=True):
82 """ @param cookie: Names of the cookies to parse.
84 BaseAuth.__init__(self)
85 self.cookies = cookies
86 self.autocreate = autocreate
88 self.fflink = FusionForgeLink()
89 self.session_key = self.fflink.get_config('session_key')
91 # List super users (Forge admins)
93 conn = self.fflink._conn
95 cur.execute("""SELECT distinct(u.user_name)
100 WHERE u.user_id = pur.user_id
101 AND pur.role_id = pr.role_id
102 AND pr.role_id = prs.role_id
103 AND prs.section_name='forge_admin'
104 AND prs.perm_val = 1""")
107 self.admins = [r[0] for r in cur]
108 logging.debug ("FusionForgeSessionAuth: admins=%s", (self.admins,))
112 cur.execute("""SELECT g.unix_group_name
113 FROM groups g, group_plugin gp, plugins p
114 WHERE g.group_id = gp.group_id
115 AND gp.plugin_id = p.plugin_id
116 AND p.plugin_name = 'moinmoin'""")
119 self.projects = [r[0] for r in cur]
120 logging.debug ("FusionForgeSessionAuth: projects=%s", (self.projects,))
122 def get_moinmoin_acl_string(self, project_name):
123 conn = self.fflink._conn
126 # Get perm setting for anonymous users
128 query = """SELECT prs.perm_val
129 FROM pfo_role_setting prs, groups
130 WHERE prs.role_id = 1
131 AND prs.section_name = '%s'
132 AND groups.unix_group_name = '%s'
133 AND prs.ref_id = groups.group_id""" \
134 % (perm_name, project_name)
135 val = cur.execute(query)
138 anon_perm = [k for k, v in perm_map.iteritems() if v == val[0]]
140 anon_perm = anon_perm[0]
145 { 'Admins': 'read,write,delete,revert,admin',
146 'Writers': 'read,write,delete,revert',
149 rights = [ 'FFSiteAdminsGroup:read,write,delete,revert,admin' ] \
150 + map (lambda (g, right):
151 'FFProject_%s_%sGroup:%s' % (project_name, g, right),
152 rights_dict.iteritems ())
154 if anon_perm and rights_dict.has_key(anon_perm):
155 rights.append ('All:' + rights_dict[anon_perm])
157 rights.append ('All:')
159 logging.debug ("FusionForgeSessionAuth.get_moinmoin_acl_string: %s",
161 return string.join (rights)
163 def get_permission_entries (self, project_name, perm, user_name = None):
164 conn = self.fflink._conn
168 ucond = "u.user_name = '%s'" % (user_name)
172 # ??? query should also include user if permission is granted to
173 # authenticated non-members.
175 query = """SELECT DISTINCT(u.user_name)
176 FROM users u, pfo_user_role pur, pfo_role pr,
177 pfo_role_setting prs, groups
179 AND ((u.user_id = pur.user_id
180 AND pur.role_id = pr.role_id
181 AND pr.role_id = prs.role_id)
183 AND prs.section_name = '%s'
184 AND groups.unix_group_name = '%s'
185 AND prs.perm_val = %d
186 AND prs.ref_id = groups.group_id""" \
187 % (ucond, perm_name, project_name, perm_map[perm])
188 logging.debug ("get_perm_entries: " + query)
192 result = [u[0] for u in cur]
193 logging.debug (" -> %s " % (result,))
196 def check_permission (self, project_name, perm, user_name):
197 return len(self.get_permission_entries \
198 (project_name, perm, user_name)) > 0
200 def request(self, request, user_obj, **kw):
201 cookies = kw.get('cookie')
202 if cookies is None or cookies == {}:
205 for cookiename in cookies:
206 if cookiename not in self.cookies:
209 urllib.unquote(cookies[cookiename]).decode('iso-8859-1')
211 m = re.search('(.*)-\*-(.*)', cookievalue)
214 (sserial, shash) = m.group(1, 2)
216 sdata = base64.b64decode(sserial)
217 if hashlib.md5(sdata + self.session_key).hexdigest() != shash:
220 m = re.search('(.*)-\*-(.*)-\*-(.*)-\*-(.*)', sdata)
223 (user_id, time, ip, user_agent) = m.group(1, 2, 3, 4)
225 conn = self.fflink._conn
227 cur.execute("""SELECT user_name, realname
228 FROM users WHERE user_id=%s""", [user_id])
229 (loginname, realname) = cur.fetchone()
232 # MoinMoin doesn't enforce unicity of realnames
233 u = user.User(request, name=loginname, auth_username=loginname,
234 auth_method=self.name)
236 if u and self.autocreate:
237 u.create_or_update(True)
241 self.auth_user = None