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
23 class FusionForgeError(Exception):
24 def __init__(self, msg):
25 Exception.__init__(self, msg)
29 return "%s\n" % self.msg
32 class FusionForgeLink():
33 def get_config(self, varname, secname='core'):
34 if secname not in self.cachedconfig:
35 self.cachedconfig[secname] = {}
36 if varname not in self.cachedconfig[secname]:
37 self.cachedconfig[secname][varname] = \
38 subprocess.Popen(["/usr/share/gforge/bin/forge_get_config",
40 stdout=subprocess.PIPE).communicate()[0].rstrip('\n')
41 return self.cachedconfig[secname][varname]
43 def __init__(self, cookies=['session_ser'], autocreate=True):
44 self.cachedconfig = {}
45 self.database_host = self.get_config('database_host')
46 self.database_name = self.get_config('database_name')
47 self.database_user = self.get_config('database_user')
48 self.database_port = self.get_config('database_port')
49 self.database_password = self.get_config('database_password')
50 if (self.database_host != ''):
51 self._conn = psycopg2.connect(database=self.database_name,
52 user=self.database_user,
53 port=self.database_port,
54 password=self.database_password,
55 host=self.database_host)
57 self._conn = psycopg2.connect(database=self.database_name,
58 user=self.database_user,
59 port=self.database_port,
60 password=self.database_password)
62 # We never want to start transactions, all accesses here are read-only
64 self._conn.set_isolation_level \
65 (psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
66 logging.debug ("FusionForgeLink: __init__ done")
71 class FusionForgeSessionAuth(BaseAuth):
72 """ FusionForge session cookie authentication """
74 name = 'fusionforge_session'
75 logout_possible = False
77 def __init__(self, cookies=['session_ser'], autocreate=True):
78 """ @param cookie: Names of the cookies to parse.
80 BaseAuth.__init__(self)
81 self.cookies = cookies
82 self.autocreate = autocreate
84 self.fflink = FusionForgeLink()
85 self.session_key = self.fflink.get_config('session_key')
87 # List super users (Forge admins)
89 conn = self.fflink._conn
91 cur.execute("""SELECT distinct(u.user_name)
96 WHERE u.user_id = pur.user_id
97 AND pur.role_id = pr.role_id
98 AND pr.role_id = prs.role_id
99 AND prs.section_name='forge_admin'
100 AND prs.perm_val = 1""")
103 self.admins = [r[0] for r in cur]
104 logging.debug ("FusionForgeSessionAuth: admins=%s", (self.admins,))
108 cur.execute("""SELECT g.unix_group_name
109 FROM groups g, group_plugin gp, plugins p
110 WHERE g.group_id = gp.group_id
111 AND gp.plugin_id = p.plugin_id
112 AND p.plugin_name = 'moinmoin'""")
115 self.projects = [r[0] for r in cur]
116 logging.debug ("FusionForgeSessionAuth: projects=%s", (self.projects,))
118 def get_moinmoin_acl_string(self, project_name):
119 conn = self.fflink._conn
122 # Check whether this is a public project
123 # anomymous users and registered users that are not part of the project
125 val = cur.execute("""SELECT prs.perm_val
126 FROM pfo_role_setting prs, groups g
128 AND prs.section_name='project_read'
129 AND prs.ref_id = g.group_id
130 AND g.unix_group_name='%s'""" % project_name)
132 is_public = val != None and val[0] != 0
135 rights = [ 'FFSiteAdminsGroup:read,write,delete,revert,admin' ] \
136 + map (lambda (g, right):
137 'FFProject_%s_%sGroup:%s' % (project_name, g, right),
138 { 'Admins': 'read,write,delete,revert,admin',
139 'Writers': 'read,write,delete,revert',
140 'Readers': 'read' }.iteritems ())
143 rights.append ('All:read')
145 rights.append ('All:')
147 logging.debug ("FusionForgeSessionAuth.get_moinmoin_acl_string: %s",
149 return string.join (rights)
151 def get_permission_entries (self, project_name, section, condition, user_name = None):
152 conn = self.fflink._conn
156 ucond = "u.user_name = '%s'" % (user_name)
159 query = """SELECT DISTINCT(u.user_name)
160 FROM users u, pfo_user_role pur, pfo_role pr,
161 pfo_role_setting prs, groups
163 AND u.user_id = pur.user_id
164 AND pur.role_id = pr.role_id
165 AND pr.role_id = prs.role_id
166 AND prs.section_name = '%s'
167 AND groups.unix_group_name = '%s'
169 AND prs.ref_id = groups.group_id""" \
170 % (ucond, section, project_name, condition)
171 logging.debug ("get_perm_entries: " + query)
175 result = [u[0] for u in cur]
176 logging.debug (" -> %s " % (result,))
179 def check_permission (self, project_name, section, condition, user_name):
180 return len(self.get_permission_entries \
181 (project_name, section, condition, user_name)) > 0
183 def request(self, request, user_obj, **kw):
184 cookies = kw.get('cookie')
185 if cookies is None or cookies == {}:
188 for cookiename in cookies:
189 if cookiename not in self.cookies:
192 urllib.unquote(cookies[cookiename]).decode('iso-8859-1')
194 m = re.search('(.*)-\*-(.*)', cookievalue)
197 (sserial, shash) = m.group(1, 2)
199 sdata = base64.b64decode(sserial)
200 if hashlib.md5(sdata + self.session_key).hexdigest() != shash:
203 m = re.search('(.*)-\*-(.*)-\*-(.*)-\*-(.*)', sdata)
206 (user_id, time, ip, user_agent) = m.group(1, 2, 3, 4)
208 conn = self.fflink._conn
210 cur.execute("""SELECT user_name, realname
211 FROM users WHERE user_id=%s""", [user_id])
212 (loginname, realname) = cur.fetchone()
215 # MoinMoin doesn't enforce unicity of realnames
216 u = user.User(request, name=loginname, auth_username=loginname,
217 auth_method=self.name)
219 if u and self.autocreate:
220 u.create_or_update(True)
224 self.auth_user = None