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)
61 logging.debug ("FusionForgeLink: __init__ done")
66 class FusionForgeSessionAuth(BaseAuth):
67 """ FusionForge session cookie authentication """
69 name = 'fusionforge_session'
70 logout_possible = False
72 def __init__(self, cookies=['session_ser'], autocreate=True):
73 """ @param cookie: Names of the cookies to parse.
75 BaseAuth.__init__(self)
76 self.cookies = cookies
77 self.autocreate = autocreate
79 self.fflink = FusionForgeLink()
80 self.session_key = self.fflink.get_config('session_key')
82 # List super users (Forge admins)
84 conn = self.fflink._conn
86 cur.execute("""SELECT distinct(u.user_name)
91 WHERE u.user_id = pur.user_id
92 AND pur.role_id = pr.role_id
93 AND pr.role_id = prs.role_id
94 AND prs.section_name='forge_admin'
95 AND prs.perm_val = 1""")
98 self.admins = [r[0] for r in cur]
99 logging.debug ("FusionForgeSessionAuth: admins=%s", (self.admins,))
103 cur.execute("""SELECT g.unix_group_name
104 FROM groups g, group_plugin gp, plugins p
105 WHERE g.group_id = gp.group_id
106 AND gp.plugin_id = p.plugin_id
107 AND p.plugin_name = 'moinmoin'""")
110 self.projects = [r[0] for r in cur]
111 logging.debug ("FusionForgeSessionAuth: projects=%s", (self.projects,))
113 def get_moinmoin_acl_string(self, project_name):
114 conn = self.fflink._conn
117 # Check whether this is a public project
118 # anomymous users and registered users that are not part of the project
120 val = cur.execute("""SELECT is_public
122 WHERE unix_group_name='%s'""" % project_name)
124 is_public = val != None and val[0] != 0
127 rights = [ 'FFSiteAdminsGroup:read,write,delete,revert,admin' ] \
128 + map (lambda (g, right):
129 'FFProject_%s_%sGroup:%s' % (project_name, g, right),
130 { 'Admins': 'read,write,delete,revert,admin',
131 'Writers': 'read,write,delete,revert',
132 'Readers': 'read' }.iteritems ())
135 rights.append ('All:read')
137 rights.append ('All:')
139 logging.debug ("FusionForgeSessionAuth.get_moinmoin_acl_string: %s",
141 return string.join (rights)
143 def get_permission_entries (self, project_name, section, condition, user_name = None):
144 conn = self.fflink._conn
148 ucond = "u.user_name = '%s'" % (user_name)
151 query = """SELECT DISTINCT(u.user_name)
152 FROM users u, pfo_user_role pur, pfo_role pr,
153 pfo_role_setting prs, groups
155 AND u.user_id = pur.user_id
156 AND pur.role_id = pr.role_id
157 AND pr.role_id = prs.role_id
158 AND prs.section_name = '%s'
159 AND groups.unix_group_name = '%s'
161 AND pr.home_group_id = groups.group_id""" \
162 % (ucond, section, project_name, condition)
163 logging.debug ("get_perm_entries: " + query)
167 result = [u[0] for u in cur]
168 logging.debug (" -> %s " % (result,))
171 def check_permission (self, project_name, section, condition, user_name):
172 return len(self.get_permission_entries \
173 (project_name, section, condition, user_name)) > 0
175 def request(self, request, user_obj, **kw):
176 cookies = kw.get('cookie')
177 if cookies is None or cookies == {}:
180 for cookiename in cookies:
181 if cookiename not in self.cookies:
184 urllib.unquote(cookies[cookiename]).decode('iso-8859-1')
186 m = re.search('(.*)-\*-(.*)', cookievalue)
189 (sserial, shash) = m.group(1, 2)
191 sdata = base64.b64decode(sserial)
192 if hashlib.md5(sdata + self.session_key).hexdigest() != shash:
195 m = re.search('(.*)-\*-(.*)-\*-(.*)-\*-(.*)', sdata)
198 (user_id, time, ip, user_agent) = m.group(1, 2, 3, 4)
200 conn = self.fflink._conn
202 cur.execute("""SELECT user_name, realname
203 FROM users WHERE user_id=%s""", [user_id])
204 (loginname, realname) = cur.fetchone()
207 # MoinMoin doesn't enforce unicity of realnames
208 u = user.User(request, name=loginname, auth_username=loginname,
209 auth_method=self.name)
211 if u and self.autocreate:
212 u.create_or_update(True)
216 self.auth_user = None