Mercurial > moin > 1.9
changeset 3142:fe93fb0732a2
merged main
author | Thomas Waldmann <tw AT waldmann-edv DOT de> |
---|---|
date | Wed, 27 Feb 2008 15:41:41 +0100 |
parents | 044856398918 (current diff) 232b1fcfadab (diff) |
children | 16ae95df840a |
files | |
diffstat | 8 files changed, 243 insertions(+), 38 deletions(-) [+] |
line wrap: on
line diff
--- a/MoinMoin/auth/__init__.py Wed Feb 27 15:41:13 2008 +0100 +++ b/MoinMoin/auth/__init__.py Wed Feb 27 15:41:41 2008 +0100 @@ -93,6 +93,11 @@ - 'username': username entry field - 'password': password entry field - 'openid_identifier': OpenID entry field + - 'special_no_input': manual login is required + but no form fields need to be filled in + (for example openid with forced provider) + in this case the theme may provide a short- + cut omitting the login form * logout_possible: boolean indicating whether this auth methods supports logging out * name: name of the auth method, must be the same as given as the @@ -146,8 +151,11 @@ 'login': '1', 'stage': auth_name} fields.update(extra_fields) - qstr = wikiutil.makeQueryString(fields) - return ''.join([request.getBaseURL(), '?', qstr]) + if request.page: + return request.page.url(request, querystr=fields, relative=False) + else: + qstr = wikiutil.makeQueryString(fields) + return ''.join([request.getBaseURL(), '?', qstr]) class LoginReturn(object):
--- a/MoinMoin/auth/openidrp.py Wed Feb 27 15:41:13 2008 +0100 +++ b/MoinMoin/auth/openidrp.py Wed Feb 27 15:41:41 2008 +0100 @@ -17,11 +17,54 @@ from MoinMoin.auth import MultistageFormLogin, MultistageRedirectLogin from MoinMoin.auth import get_multistage_continuation_url + class OpenIDAuth(BaseAuth): login_inputs = ['openid_identifier'] name = 'openid' logout_possible = True + def __init__(self, modify_request=None, + update_user=None, + create_user=None, + forced_service=None): + BaseAuth.__init__(self) + self._modify_request = modify_request or (lambda x: None) + self._update_user = update_user or (lambda i, u: None) + self._create_user = create_user or (lambda i, u: None) + self._forced_service = forced_service + if forced_service: + self.login_inputs = ['special_no_input'] + + def _handle_user_data(self, request, u): + create = not u + if create: + # pass in a created but unsaved user object + u = user.User(request, auth_method=self.name, + auth_username=request.session['openid.id']) + # invalid name + u.name = '' + u = self._create_user(request.session['openid.info'], u) + + if u: + self._update_user(request.session['openid.info'], u) + + # just in case the wiki admin screwed up + if (not user.isValidName(request, u.name) or + (create and user.getUserId(request, u.name))): + return None + + if not hasattr(u, 'openids'): + u.openids = [] + if not request.session['openid.id'] in u.openids: + u.openids.append(request.session['openid.id']) + + u.save() + + del request.session['openid.id'] + del request.session['openid.info'] + + return u + def _get_account_name(self, request, form, msg=None): # now we need to ask the user for a new username # that they want to use on this wiki @@ -96,12 +139,22 @@ elif info.status == consumer.CANCEL: return CancelLogin(_('Verification canceled.')) elif info.status == consumer.SUCCESS: + request.session['openid.id'] = info.identity_url + request.session['openid.info'] = info + # try to find user object uid = user.getUserIdByOpenId(request, info.identity_url) if uid: u = user.User(request, id=uid, auth_method=self.name, auth_username=info.identity_url) + else: + u = None + + # create or update the user according to the registration data + u = self._handle_user_data(request, u) + if u: return ContinueLogin(u) + # if no user found, then we need to ask for a username, # possibly associating an existing account. request.session['openid.id'] = info.identity_url @@ -125,13 +178,10 @@ uid = user.getUserId(request, newname) if not uid: # we can create a new user with this name :) - u = user.User(request, id=uid, auth_method=self.name, + u = user.User(request, auth_method=self.name, auth_username=request.session['openid.id']) u.name = newname - u.openids = [request.session['openid.id']] - u.aliasname = request.session['openid.id'] - del request.session['openid.id'] - u.save() + u = self._handle_user_data(request, u) return ContinueLogin(u) # requested username already exists. if they know the password, # they can associate that account with the openid. @@ -151,13 +201,7 @@ auth_method=self.name, auth_username=request.session['openid.id']) if u.valid: - if not hasattr(u, 'openids'): - u.openids = [] - u.openids.append(request.session['openid.id']) - if not u.aliasname: - u.aliasname = request.session['openid.id'] - u.save() - del request.session['openid.id'] + self._handle_user_data(request, u) return ContinueLogin(u, _('Your account is now associated to your OpenID.')) else: msg = _('The password you entered is not valid.') @@ -197,8 +241,9 @@ return ContinueLogin(user_obj) openid_id = kw.get('openid_identifier') + # nothing entered? continue... - if not openid_id: + if not self._forced_service and not openid_id: return ContinueLogin(user_obj) _ = request.getText @@ -212,7 +257,14 @@ MoinOpenIDStore(request)) try: - oidreq = oidconsumer.begin(openid_id) + fserv = self._forced_service + if fserv: + if isinstance(fserv, str) or isinstance(fserv, unicode): + oidreq = oidconsumer.begin(fserv) + else: + oidreq = oidconsumer.beginWithoutDiscovery(fserv) + else: + oidreq = oidconsumer.begin(openid_id) except HTTPFetchingError: return ContinueLogin(None, _('Failed to resolve OpenID.')) except DiscoveryFailure: @@ -221,6 +273,8 @@ if oidreq is None: return ContinueLogin(None, _('No OpenID.')) + self._modify_request(oidreq) + return_to = get_multistage_continuation_url(request, self.name, {'oidstage': '1'}) trust_root = request.getBaseURL()
--- a/MoinMoin/formatter/text_html.py Wed Feb 27 15:41:13 2008 +0100 +++ b/MoinMoin/formatter/text_html.py Wed Feb 27 15:41:41 2008 +0100 @@ -1241,7 +1241,7 @@ _allowed_table_attrs = { 'table': ['class', 'id', 'style'], 'row': ['class', 'id', 'style'], - '': ['colspan', 'rowspan', 'class', 'id', 'style'], + '': ['colspan', 'rowspan', 'class', 'id', 'style', 'abbr'], } def _checkTableAttr(self, attrs, prefix):
--- a/MoinMoin/theme/__init__.py Wed Feb 27 15:41:13 2008 +0100 +++ b/MoinMoin/theme/__init__.py Wed Feb 27 15:41:41 2008 +0100 @@ -285,9 +285,13 @@ userlinks.append(d['page'].link_to(request, text=_('Logout', formatted=False), querystr={'action': 'logout', 'logout': 'logout'}, id='logout', rel='nofollow')) else: + query = {'action': 'login'} + # special direct-login link if the auth methods want no input + if request.cfg.auth_login_inputs == ['special_no_input']: + query['login'] = '1' if request.cfg.auth_have_login: userlinks.append(d['page'].link_to(request, text=_("Login", formatted=False), - querystr={'action': 'login'}, id='login', rel='nofollow')) + querystr=query, id='login', rel='nofollow')) userlinks = [u'<li>%s</li>' % link for link in userlinks] html = u'<ul id="username">%s</ul>' % ''.join(userlinks)
--- a/MoinMoin/user.py Wed Feb 27 15:41:13 2008 +0100 +++ b/MoinMoin/user.py Wed Feb 27 15:41:41 2008 +0100 @@ -975,7 +975,7 @@ def isSuperUser(self): """ Check if this user is superuser """ request = self._request - if request.cfg.DesktopEdition and request.remote_addr == '127.0.0.1' and request.user.valid: + if request.cfg.DesktopEdition and request.remote_addr == '127.0.0.1' and request.user and request.user.valid: # the DesktopEdition gives any local user superuser powers return True superusers = request.cfg.superuser
--- a/MoinMoin/widget/browser.py Wed Feb 27 15:41:13 2008 +0100 +++ b/MoinMoin/widget/browser.py Wed Feb 27 15:41:41 2008 +0100 @@ -16,10 +16,15 @@ base.Widget.__init__(self, request, **kw) self.data = None self.data_id = 'dbw.' + # prefixed with __ are untranslated and to be used in the JS self._all = _('[all]') + self.__all = '[all]' self._notempty = _('[not empty]') + self.__notempty = '[notempty]' self._empty = _('[empty]') + self.__empty = '[empty]' self._filter = _('filter') + self.__filter = 'filter' def setData(self, dataset): """ Sets the data for the browser (see MoinMoin.util.dataset). @@ -39,7 +44,7 @@ """ return 'name="%s%s"' % (self.data_id, elem) - def _makeoption(self, item, selected): + def _makeoption(self, item, selected, ntitem = None): """ create an option for a <select> form element @param item: string containing the item name to show @param selected: indicates whether the item should be default or not @@ -50,7 +55,9 @@ selected = '' assert(isinstance(item, basestring)) item = wikiutil.escape(item) - return '<option value="%s"%s>%s</option>' % (item, selected, item) + if ntitem is None: + ntitem = item + return '<option value="%s"%s>%s</option>' % (ntitem, selected, item) def _filteroptions(self, idx): """ create options for all elements in the column @@ -58,9 +65,8 @@ """ self.data.reset() row = self.data.next() - # leave the 'empty' slot blank so we avoid adding - # blank items when getting all possibilities - unique = [self._all, '', self._notempty] + # [empty] is a special already + unique = [''] value = None name = '%sfilter%d' % (self.data_id, idx) @@ -75,17 +81,20 @@ row = self.data.next() # fill in the empty field we left blank - unique[1] = self._empty - sortedlist = unique[3:] - sortedlist.sort() - unique = unique[:3] + sortedlist - return '\n'.join([self._makeoption(item, item == value) for item in unique]) + del unique[0] + unique.sort() + result = [self._makeoption(item, item == value) for item in unique] + common = [None, None, None] + common[0] = self._makeoption(self._all, value == self.__all, self.__all) + common[1] = self._makeoption(self._empty, value == self.__empty, self.__empty) + common[2] = self._makeoption(self._notempty, value == self.__notempty, self.__notempty) + return '\n'.join(common + result) def format(self): fmt = self.request.formatter result = [] - result.append(fmt.rawHTML('<form action="%s/%s" method="GET">' % (self.request.getScriptname(), wikiutil.quoteWikinameURL(self.request.page.page_name)))) + result.append(fmt.rawHTML('<form action="%s/%s" method="GET" name="%s">' % (self.request.getScriptname(), wikiutil.quoteWikinameURL(self.request.page.page_name), self.data_id))) result.append(fmt.div(1)) havefilters = False @@ -96,7 +105,7 @@ if havefilters: result.append(fmt.rawHTML('<input type="submit" value="%s" %s>' % (self._filter, self._name('submit')))) - result.append(fmt.table(1)) + result.append(fmt.table(1, id='%stable' % self.data_id)) # add header line result.append(fmt.table_row(1)) @@ -111,8 +120,10 @@ if col.autofilter: result.append(fmt.linebreak(False)) - select = '<select %s>%s</select>' % (self._name('filter%d' % idx), - self._filteroptions(idx)) + select = '<select %s onchange="dbw_update_search(\'%s\');">%s</select>' % ( + self._name('filter%d' % idx), + self.data_id, + self._filteroptions(idx)) result.append(fmt.rawHTML(select)) result.append(fmt.table_cell(0)) @@ -156,10 +167,11 @@ for idx in range(len(row)): if self.data.columns[idx].hidden: continue - result.append(fmt.table_cell(1)) if isinstance(row[idx], tuple): + result.append(fmt.table_cell(1, abbr=unicode(row[idx][1]))) result.append(unicode(row[idx][0])) else: + result.append(fmt.table_cell(1)) result.append(unicode(row[idx])) result.append(fmt.table_cell(0)) result.append(fmt.table_row(0))
--- a/MoinMoin/wikiutil.py Wed Feb 27 15:41:13 2008 +0100 +++ b/MoinMoin/wikiutil.py Wed Feb 27 15:41:41 2008 +0100 @@ -1578,6 +1578,60 @@ return arg +class IEFArgument: + """ + Base class for new argument parsers for + invoke_extension_function. + """ + def __init__(self): + pass + + def parse_argument(self, s): + """ + Parse the argument given in s (a string) and return + the argument for the extension function. + """ + raise NotImplementedError + + def get_default(self): + """ + Return the default for this argument. + """ + raise NotImplementedError + + +class UnitArgument(IEFArgument): + """ + Argument class for invoke_extension_function that forces + having any of the specified units given for a value. + + Note that the default unit is "mm". + + Use, for example, "UnitArgument('7mm', float, ['%', 'mm'])". + """ + def __init__(self, default, argtype, units=['mm']): + """ + Initialise a UnitArgument giving the default, + argument type and the permitted units. + """ + IEFArgument.__init__(self) + self._units = list(units) + self._units.sort(cmp=lambda x, y: len(y) - len(x)) + self._type = argtype + self._default = self.parse_argument(default) + + def parse_argument(self, s): + for unit in self._units: + if s.endswith(unit): + ret = (self._type(s[:len(s) - len(unit)]), unit) + return ret + ## XXX: how can we translate this? + raise ValueError("Invalid unit in value %s" % s) + + def get_default(self): + return self._default + + class required_arg: """ Wrap a type in this class and give it as default argument @@ -1589,7 +1643,8 @@ Initialise a required_arg @param argtype: the type the argument should have """ - if not argtype in (bool, int, long, float, complex, unicode): + if not (argtype in (bool, int, long, float, complex, unicode) or + isinstance(argtype, IEFArgument)): raise TypeError("argtype must be a valid type") self.argtype = argtype @@ -1642,6 +1697,11 @@ return get_float(request, value, name) elif default is complex: return get_complex(request, value, name) + elif isinstance(default, IEFArgument): + # defaults handled later + if value is None: + return None + return default.parse_argument(value) elif isinstance(default, required_arg): return _convert_arg(request, value, default.argtype, name) return value @@ -1736,9 +1796,11 @@ # went wrong (if it does) kwargs[argname] = _convert_arg(request, kwargs[argname], defaults[argname], argname) - if (kwargs[argname] is None - and isinstance(defaults[argname], required_arg)): - raise ValueError(_('Argument "%s" is required') % argname) + if kwargs[argname] is None: + if isinstance(defaults[argname], required_arg): + raise ValueError(_('Argument "%s" is required') % argname) + if isinstance(defaults[argname], IEFArgument): + kwargs[argname] = defaults[argname].get_default() if not argname in argnames: # move argname into _kwargs parameter
--- a/wiki/htdocs/common/js/common.js Wed Feb 27 15:41:13 2008 +0100 +++ b/wiki/htdocs/common/js/common.js Wed Feb 27 15:41:41 2008 +0100 @@ -200,6 +200,9 @@ // Editor stuff show_switch2gui(); + + // data browser widget + dbw_hide_buttons(); } @@ -217,3 +220,65 @@ // Catch before unloading the page window.onbeforeunload = before_unload +function dbw_update_search(dbw_id) +{ + var table = document.getElementById(dbw_id+'table'); + var cell; + var shown; + var i + var cols = table.rows[0].cells.length; + var filter = new Array(); + var dofilter = new Array(); + var form = document.forms[dbw_id+'form']; + + for (i = 0; i < cols; i++) { + dofilter[i] = false; + if (form[dbw_id+'filter'+i]) { + dofilter[i] = true; + filter[i] = form[dbw_id+'filter'+i].value; + if (filter[i] == '[all]') + dofilter[i] = false; + if (filter[i] == '[empty]') + filter[i] = ''; + } + } + + for (i = 1; i < table.rows.length; i++) { + var show = true; + for (col = 0; col < cols; col++) { + if (!dofilter[col]) + continue; + + cell = table.rows[i].cells[col]; + + if (filter[col] == '[notempty]') { + if (cell.abbr == '') { + show = false; + break; + } + } else if (filter[col] != cell.abbr) { + show = false; + break; + } + } + if (show) + table.rows[i].style.display = ''; + else + table.rows[i].style.display = 'none'; + } +} + +function dbw_hide_buttons() { + var form; + var elem; + + for (var fidx = 0; fidx < document.forms.length; fidx++) { + form = document.forms[fidx]; + for (var eidx = 0; eidx < form.elements.length; eidx++) { + elem = form.elements[eidx]; + name = elem.name; + if (name.substr(0,4) == 'dbw.' && name.substr(-7) == '.submit') + elem.style.display = 'none'; + } + } +}