def doEdit(self): member = self.session.get('user') try: language = self.db.query(Preferences).filter(and_(Preferences.uidNumber == member.uidNumber, Preferences.key == 'language')).one() language.last_change = datetime.datetime.now() language.value = self.request.params['language'] self.session['language'] = language.value self.session['flash'] = _('Changes saved!') self.session['flash_class'] = 'success' except NoResultFound: pref = Preferences() pref.uidNumber = member.uidNumber pref.last_change = datetime.datetime.now().date() pref.key = 'language' pref.value = self.request.params['language'] self.db.add(pref) self.session['language'] = cherrypy.request.params['language'] self.session['flash'] = _('Changes saved!') self.session['flash_class'] = 'success' except: self.session['flash'] = _('Unknown error, nothing saved') self.session['flash_class'] = 'error' self.db.commit() self.session.save() raise HTTPRedirect('/preferences/edit')
def _sidebar(self): self.sidebar = [] self.sidebar.append({'name': _('Show all members'), 'args': {'controller': 'members', 'action': 'showAllMembers'}}) self.sidebar.append({'name': _('Add member'), 'args': {'controller': 'members', 'action': 'addMember'}}) self.sidebar.append({'name': _('Active members'), 'args': {'controller': 'members', 'action': 'showActiveMembers'}}) self.sidebar.append({'name': _('Former members'), 'args': {'controller': 'members', 'action': 'showFormerMembers'}}) self.sidebar.append({'name': _('Groups'), 'args': {'controller': 'groups', 'action': 'index'}})
def validateMember(self, member_id): try: member = self.mf.getUser(member_id) if member.validate: tm = self.db.query(TmpMember).filter(TmpMember.id == member.uidNumber).first() member.givenName = tm.gn member.sn = tm.sn member.homePostalAddress = tm.homePostalAddress # @FIXME fix this nasty workaround if not tm.phone == '>>REMOVE<<': member.homePhone = tm.phone else: member.homePhone = '' member.mobile = tm.mobile member.mail = tm.mail member.xmppID = tm.xmppID self.mf.saveMember(member) self.db.delete(tm) self.db.commit() self.session['flash'] = _('Changes accepted') self.postValidationMail(member_id, member.mail, validated=True) else: self.session['flash'] = _('Nothing to validate!') except LookupError: self.session['flash'] = _('Member validation failed!') self.session.save() raise HTTPRedirect('/members/showAllMembers')
def validatePayment(self, member_id, idPayment): """ Validate a payment specified by an id """ try: ParamChecker.checkUsername('member_id', param=True) ParamChecker.checkInt('idPayment', param=True) except: raise HTTPRedirect('/payments/index') try: np = self.db.query(Payment).filter(Payment.id == idPayment).one() if np.verified: np.verified = False else: np.verified = True self.request.db.commit() self.session['flash'] = _('Payment validation successfully toggled') self.session['flash_class'] = 'success' except: self.session['flash'] = _('Saving payment failed') self.session['flash_class'] = 'error' self.session.save() raise HTTPRedirect('/payments/listPayments/?member_id={0}'.format(member_id))
def doEditGroup(self, items): if not self.mf.addGroup(items['gid']): msg = _('Failed to add group!') msg_class = 'error' else: try: lgrp_members = self.mf.getGroupMembers(items['gid']) except LookupError: lgrp_members = [] # Adding new members for m in items['users']: if not m in lgrp_members: #print 'adding -> ' + str(m) self.mf.changeUserGroup(m, items['gid'], True) # Removing members for m in lgrp_members: if not m in items['users']: #print 'removing -> ' + str(m) self.mf.changeUserGroup(m, items['gid'], False) # @TODO add group if not exist msg = _('Group saved successfully') msg_class = 'success' return self.index(msg=msg, msg_class=msg_class)
def deleteUser(self, member_id): try: self.mf.deleteUser(member_id) aliases = self.mf.getMaildropList(member_id) errors = '' for dn, attr in aliases.items(): if errors == '': errors = 'Could not auto-delete the following aliases:' m = re.match(r'^mail=([^,]+),', dn) if m: alias = m.group(1) url_ = url(controller='mails', action='editAlias', alias=alias) errors += '\n<br/><a href="{0}" target="_blank">{1}</a>'.format(url_, alias) if not errors == '': if not 'errors' in self.session: self.session['errors'] = [] self.session['errors'].append(literal(errors)) self.session['flash'] = _('User successfully deleted') self.session.save() except LookupError: self.session['flash'] = _('Failed to delete user') self.session.save() # @TODO make much more noise ! raise HTTPRedirect('/members/showAllMembers')
def doEdit(self): m = self.mf.getUser(self.session['username']) if m.validate: # member locked for validation raise HTTPError(403, 'Forbidden') else: changes = False if self.request.params['sn'] != m.sn or\ self.request.params['givenName'] != m.givenName or\ self.request.params['homePostalAddress'] != m.homePostalAddress or\ self.request.params['homePhone'] != m.homePhone or\ self.request.params['mobile'] != m.mobile or\ self.request.params['mail'] != m.mail or\ self.request.params['xmppID'] != m.xmppID: changes = True if changes: tm = TmpMember(m.uidNumber) tm.sn = str(self.request.params['sn'].encode('utf-8')) tm.gn = str(self.request.params['givenName'].encode('utf-8')) tm.homePostalAddress = str(self.request.params['homePostalAddress'].encode('utf-8')) # @TODO make this more consistent if self.request.params.get('homePhone', '') == '' and not m.homePhone == '': tm.phone = '>>REMOVE<<' else: tm.phone = self.request.params['homePhone'] if self.request.params.get('xmppID', '') == '' and not m.xmppID == '': tm.xmppID = 'removed' else: tm.xmppID = self.request.params['xmppID'] tm.mobile = self.request.params['mobile'] tm.mail = self.request.params['mail'] self.db.add(tm) self.db.commit() self.session['flash'] = _('Changes saved!') self.session['flash_class'] = 'success' self.mailValidationRequired() else: self.session['flash'] = _('Nothing to save!') self.session['flash_class'] = 'info' if not self.request.params.get('userPassword', '') == '' and self.request.params['userPassword'] == self.request.params['userPassword2']: m.setPassword(self.request.params['userPassword']) self.mf.saveMember(m, is_admin=False) self.session['secret'] = encodeAES(self.request.params['userPassword']) self.session['flash'] = _('Password updated!') self.session['flash_class'] = 'success' self.session.save() raise HTTPRedirect('/profile/index')
def doEditDomain(self, items): if not self.mf.addDomain(items["domain"]): msg = _("Failed to add domain!") msg_class = "error" else: msg = _("Domain added") msg_class = "success" return self.index(msg=msg, msg_class=msg_class)
def new_f(self, member_id, idPayment, date, status): # @TODO request.params may contain multiple values per key... test & fix if not self.is_admin() and not member_id == self.session.get('username') or (member_id == self.session.get('username') and ParamChecker.checkInt('idPayment', param=True, optional=True)): print 'checkPayment err0r::', str(self.isAdmin()), str(member_id), str(self.session.get('username')), str(ParamChecker.checkInt('idPayment', param=True, optional=True)) raise HTTPError(403, 'Forbidden') else: formok = True errors = [] items = {} d = None try: ParamChecker.checkDate('date', param=True) d = parser.parse(date) d = datetime.date(d.year, d.month, 1) except Exception as e: print e formok = False errors.append(_('Invalid date')) try: ParamChecker.checkInt('status', param=True) items['status'] = int(status) except: formok = False errors.append(_('Invalid payment status')) try: ParamChecker.checkInt('idPayment', param=True) items['idPayment'] = int(idPayment) except: items['idPayment'] = 0 if not d is None and items['idPayment'] == 0: p_count = self.db.query(Payment).filter(Payment.uid == member_id).filter(Payment.date == d).count() if p_count > 0: formok = False errors.append(_('That month is already on records!')) if not formok: self.session['errors'] = errors self.session['reqparams'] = {} # @TODO request.params may contain multiple values per key... test & fix for k in self.request.params.iterkeys(): self.session['reqparams'][k] = self.request.params[k] self.session.save() raise HTTPRedirect('/payments/editPayment/?member_id={0}&idPayment={1}'.format(member_id, items['idPayment'])) else: items['date'] = d return f(self, member_id, items)
def doLogin(self, username=None, password=None): try: ParamChecker.checkUsername('username', param=True) ParamChecker.checkPassword('password', 'password', param=True) except InvalidParameterFormat as ipf: return self.index(_('Invalid data')) try: ldap_connector = LdapConnector(username=username, password=password) except mematool.helpers.exceptions.InvalidCredentials: return self.index(_('Invalid credentials')) except mematool.helpers.exceptions.ServerError: return self.index(_('Server error, please retry later')) old_session_language = self.session.get('language', '') self.session.regenerate() self.session['username'] = username self.session['password'] = encodeAES(password) self.set_ldapcon(ldap_connector.get_connection()) self.session['groups'] = self.mf.getUserGroupList(username) try: user = self.mf.getUser(self.session['username']) except: return self.index(_('Server error, please retry later')) self.session['user'] = user if self.is_admin(): self.session['pendingMemberValidations'] = self.pendingMemberValidations() uidNumber = user.uidNumber language = self.db.query(Preferences).filter(and_(Preferences.uidNumber == uidNumber, Preferences.key == 'language')).one() if language.value in self.languages: self.session['language'] = language.value elif not old_session_language == '': self.session['language'] = old_session_language else: self.session['language'] = self.default_language log.info(username + ' logged in') if user.is_admin(): raise HTTPRedirect('/members/index') else: raise HTTPRedirect('/profile/index')
def edit(self): c = TemplateContext() c.heading = _('Edit preferences') c.formDisabled = '' try: member = self.session.get('user') c.member = member pref = self.db.query(Preferences).filter(Preferences.uidNumber == member.uidNumber).all() c.language = 'en' if len(pref) > 0: for p in pref: if p.key == 'language': c.language = p.value c.languages = Config.get('mematool', 'languages', ['en']) return self.render('preferences/edit.mako', template_context=c) except LookupError: print 'Edit :: No such user !' return 'ERROR 4x0'
def addMember(self): c = TemplateContext() c.heading = _('Add member') c.mode = 'add' c.groups = [] return self.render('/members/editMember.mako', template_context=c)
def edit(self): c = TemplateContext() c.heading = _('Edit profile') c.formDisabled = '' try: member = self.mf.getUser(self.session.get('username')) if member.validate: tm = self.db.query(TmpMember).filter(TmpMember.id == member.uidNumber).first() member.givenName = tm.gn member.sn = tm.sn member.homePostalAddress = tm.homePostalAddress member.homePhone = tm.phone member.mobile = tm.mobile member.mail = tm.mail member.xmppID = tm.xmppID c.formDisabled = 'disabled' c.member = member c.member.avatarUrl = self.avatarUrl(member.uid, size=180) c.groups = member.groups except LookupError: return 'Edit :: No such user !' return self.render('/profile/edit.mako', template_context=c)
def showAllMembers(self, _filter='active'): c = TemplateContext() try: c.heading = _('All members') members = self.mf.getUsers(clear_credentials=True) c.members = [] # make sure to clean out some vars for m in members: if _filter == 'active' and not m.lockedMember: c.members.append(m) elif _filter == 'former' and m.lockedMember: c.members.append(m) elif _filter == 'all': c.members.append(m) return self.render('/members/viewAll.mako', template_context=c) except LookupError as e: import sys, traceback traceback.print_exc(file=sys.stdout) print 'Lookup error!' print e pass except NoResultFound: print 'No such sql user !' return 'ERROR 4x0'
def deleteGroup(self, gid): try: ParamChecker.checkUsername('gid', param=True) except: raise HTTPRedirect('/groups/index') result = self.mf.deleteGroup(request.params['gid']) if result: msg = _('Group successfully deleted') msg_class = 'success' else: msg = _('Failed to delete group!') msg_class = 'error' return self.index(msg=msg, msg_class=msg_class)
def index(self): c = TemplateContext() c.heading = _("Statistics") c.members = len(self.mf.getUserList()) activeMembers = self.mf.getActiveMemberList() c.activeMembers = len(activeMembers) c.formerMembers = c.members - c.activeMembers c.paymentsOk = 0 for uid in activeMembers: last_payment = None try: last_payment = ( self.db.query(Payment) .filter(and_(Payment.uid == uid, Payment.verified == 1)) .order_by(Payment.date.desc()) .limit(1)[0] ) except Exception as e: """ Don't care if there is no payment """ pass if last_payment: d = last_payment.date today = datetime.datetime.now().date() if d.year > today.year or (d.year == today.year and d.month >= today.month): c.paymentsOk += 1 c.paymentsNotOk = c.activeMembers - c.paymentsOk return self.render("/statistics/index.mako", template_context=c)
def unmanageGroup(self, gid): try: ParamChecker.checkUsername('gid', param=True) except: raise HTTPRedirect('/groups/index') result = self.mf.unmanageGroup(gid) if result: msg = _('Group no longer managed') msg_class = 'success' else: msg = _('Failed to remove group from management!') msg_class = 'error' return self.index(msg=msg, msg_class=msg_class)
def editPayment(self, member_id, year=None, month=None, idPayment='0'): """ Add or edit a payment to/of a specific user """ if not self.is_admin() and not member_id == self.session.get('username'): raise HTTPError(403, 'Forbidden') c = TemplateContext() c.member_id = member_id c.status_0 = False c.status_1 = False c.status_2 = False # vary form depending on mode (do that over ajax) if idPayment == '0': c.payment = Payment() action = 'Adding' try: ParamChecker.checkYear('year', param=True) ParamChecker.checkMonth('month', param=True) c.date = str(datetime.date(int(year), int(month), 1)) except: '''Don't care ... just let the user enter a new date''' pass elif not idPayment == '' and IsInt(idPayment) and int(idPayment) > 0: # @fixme convert IsInt to new class action = 'Editing' payment_q = self.db.query(Payment).filter(Payment.id == int(idPayment)) try: payment = payment_q.one() # @TODO allow member editing if not verified??? if payment.verified and not self.is_admin(): raise HTTPError(403, 'Forbidden') c.payment = payment setattr(c, 'status_' + str(payment.status), True) except NoResultFound: print "oops" raise HTTPRedirect('/members/index') else: raise HTTPRedirect('/members/index') c.heading = _('%s payment for user %s') % (action, c.member_id) self.sidebar.append({'name': _('List payments'), 'args': {'controller': 'payments', 'action': 'listPayments', 'params': {'member_id': member_id}}}) return self.render('/payments/editPayment.mako', template_context=c)
def listPayments(self, member_id=None, year=None): """ Show a specific user's payments """ if member_id is None: if not self.is_admin() and not self.is_finance_admin(): raise HTTPError(403, 'Forbidden') else: raise HTTPRedirect('/payments/showOutstanding/?showAll=1') elif not self.is_admin() and not self.is_finance_admin() and not member_id == self.session.get('username'): raise HTTPError(403, 'Forbidden') if not year is None: try: ParamChecker.checkInt('year', param=True, max_len=4) if int(year) > 1970 and int(year) < 2222: year = int(year) else: year = datetime.datetime.now().year except: pass if year is None: try: ParamChecker.checkUsername('member_id', param=True) year = self._getLastPayment(member_id).year except: pass if year is None: year = datetime.datetime.now().year c = TemplateContext() c.heading = _('Payments for the year {0}, user {1}'.format(year, member_id)) c.member_id = member_id ## consider pagination # http://pylonsbook.com/en/1.1/starting-the-simplesite-tutorial.html#using-pagination try: #c.member.leavingDate = date(int(member.leavingDate[:4]),int(member.leavingDate[5:6]),int(member.leavingDate[7:8])) ## ideally, fetch monthly from member and the rest from payment (one to many relation) ## http://www.sqlalchemy.org/docs/05/reference/ext/declarative.html y_start = datetime.date(year, 1, 1) y_end = datetime.date(year, 12, 31) payment_sql = self.db.query(Payment).filter(Payment.uid == member_id).filter(Payment.date.between(y_start, y_end)).order_by(Payment.date.desc()).all() payments = {} c.unverifiedPledges = 0 for p in payment_sql: if p.verified == 0: c.unverifiedPledges += 1 payments[p.date.month] = p c.year = year c.payments = payments except AttributeError, e: return 'This member has made no payments o.O ?!: %s' % e
def savePayment(self, member_id, items): """ Save a new or edited payment """ verified = False if self.is_finance_admin() and ParamChecker.checkInt('verified', param=True, optional=True): verified = True if items['idPayment'] > 0: try: np = self.db.query(Payment).filter(Payment.id == items['idPayment']).one() np.verified = verified except: self.session['flash'] = _('Invalid record') self.session.save() raise HTTPRedirect('/payments/listPayments/?member_id={0}'.format(member_id)) else: np = Payment() np.verified = verified np.status = 0 for key, value in items.iteritems(): setattr(np, key, value) try: np.uid = member_id except: self.session['flash'] = _('Invalid member') self.session.save() raise HTTPRedirect('/payments/listPayments/?member_id={0}'.format(member_id)) # Cleanup session if 'reqparams' in self.session: del(self.session['reqparams']) self.session.save() ########## self.db.add(np) self.db.commit() self.session['flash'] = _('Payment saved successfully.') self.session['flash_class'] = 'success' self.session.save() raise HTTPRedirect('/payments/listPayments/?member_id={0}'.format(member_id))
def new_f(self, gid, users=None): formok = True errors = [] items = {} try: ParamChecker.checkUsername('gid', param=True) except: formok = False errors.append(_('Invalid group ID')) items['users'] = [] if not users is None: try: #ParamChecker.checkString('users', param=True, min_len=-1, max_len=9999, regex=r'([\w]{1,20}\n?)*') for k in users.split('\n'): m = k.replace('\r', '').replace(' ', '') if m == '': continue else: ParamChecker.checkUsername(m, param=False) items['users'].append(m) except InvalidParameterFormat as ipf: formok = False errors.append(_('Invalid user name(s)')) if not formok: self.session['errors'] = errors self.session['reqparams'] = {} # @TODO request.params may contain multiple values per key... test & fix for k in self.request.params.iterkeys(): self.session['reqparams'][k] = cherrypy.request.params[k] self.session.save() raise HTTPRedirect('/groups/editGroup/?gid={0}'.format(gid)) else: items['gid'] = gid return f(self, items)
def bulkAdd(self, member_id): try: ParamChecker.checkUsername('member_id', param=True) except: raise HTTPRedirect('/payments/index') c = TemplateContext() c.member_id = member_id c.heading = _('Add bulk payments') return self.render('/payments/bulkAdd.mako', template_context=c)
def editAlias(self, alias=None, *args, **kwargs): c = TemplateContext() # vary form depending on mode (do that over ajax) if alias is None: action = "Adding" c.mode = "add" domains = self.mf.getDomains() c.select_domains = [] for d in domains: c.select_domains.append([d.dc, d.dc]) elif not alias == "": try: ParamChecker.checkEmail("alias") except: raise HTTPRedirect("/mails/index") action = "Editing" c.alias = alias c.mode = "edit" try: alias = self.mf.getAlias(alias) mail = "" for m in alias.mail: if not mail == "": mail += "\n" if not m == alias.dn_mail: mail += m c.mail = mail maildrop = "" for m in alias.maildrop: if not maildrop == "": maildrop += "\n" if not m == alias.dn_mail and not m in maildrop: maildrop += m c.maildrop = maildrop except LookupError: # @TODO implement better handler msg = _("No such alias!") return self.index(msg=msg) else: raise HTTPRedirect("/mails/index") c.heading = "{0} alias".format(action) return self.render("/mails/editAlias.mako", template_context=c)
def listAliases(self, domain, *args, **kwargs): try: ParamChecker.checkDomain("domain", param=True) except: raise HTTPRedirect("/mails/index") c = TemplateContext() c.heading = _("Aliases for domain: %s") % (domain) c.domain = domain c.aliases = self.mf.getAliases(domain) return self.render("/mails/listAliases.mako", template_context=c)
def editMember(self, member_id): c = TemplateContext() try: c.heading = _('Edit member') c.member = self.mf.getUser(member_id) c.mode = 'edit' return self.render('/members/editMember.mako', template_context=c) except LookupError: print 'No such user !' return 'ERROR 4x0'
def deleteAlias(self, alias, *args, **kwargs): try: ParamChecker.checkEmail('alias', param=True) except: raise HTTPRedirect('/mails/index') try: result = self.mf.deleteAlias(alias) if result: msg = _('Alias successfully deleted') msg_class = 'success' else: msg = _('Failed to delete alias!') msg_class = 'error' except: import sys, traceback traceback.print_exc(file=sys.stdout) msg = _('Failed to delete alias!') msg_class = 'error' return self.index(msg=msg, msg_class=msg_class)
def doBulkAdd(self, member_id, months, verified=None): try: ParamChecker.checkUsername('member_id', param=True) ParamChecker.checkInt('months', param=True, max_len=2) except: raise HTTPRedirect('/payments/index') lastDate = self._getLastPayment(member_id) months = int(months) if self.is_finance_admin(): try: ParamChecker.checkInt('verified', param=True, max_len=1) verified = True except: verified = False try: for i in range(months): p = Payment() p.uid = member_id p.date = lastDate + relativedelta(months=i) p.status = 0 p.verified = verified self.db.add(p) self.db.commit() self.session['flash'] = _('Payments added') self.session['flash_class'] = 'success' except Exception as e: self.session['flash'] = _('Operation failed') self.session['flash_class'] = 'error' self.session.save() raise HTTPRedirect( '/payments/listPayments/?member_id={0}'.format(member_id))
def checkString(fn, param=True, min_len=0, max_len=255, regex=None, optional=False): return ParamChecker._baseCheckString(fn, _('Invalid value'), param=param, min_len=min_len, max_len=max_len, regex=regex, optional=optional)
def rejectValidation(self, member_id): try: member = self.mf.getUser(member_id) if member.validate: tm = self.db.query(TmpMember).filter(TmpMember.id == member.uidNumber).first() mail = tm.mail self.db.delete(tm) self.db.commit() self.session['flash'] = _('Changes rejected') self.postValidationMail(member_id, mail, validated=False) else: self.session['flash'] = _('Nothing to reject!') self.session['flash_class'] = 'error' except LookupError: self.session['flash'] = _('Failed to reject validation!') self.session['flash_class'] = 'error' self.session.save() raise HTTPRedirect('/members/showAllMembers')
def doEditAlias(self, items, *args, **kwargs): try: alias = Alias() alias.dn_mail = items["alias"] alias.mail = items["mail"] alias.maildrop = items["maildrop"] if items["mode"] == "edit": self.mf.updateAlias(alias) else: self.mf.addAlias(alias) self.session["flash"] = _("Alias successfully edited") self.session.save() except Exception as e: import sys, traceback traceback.print_exc(file=sys.stdout) msg = _("Error while editing alias") return self.index(msg=msg) raise HTTPRedirect("/mails/editAlias/?alias={0}".format(alias.dn_mail))
def doBulkAdd(self, member_id, months, verified=None): try: ParamChecker.checkUsername('member_id', param=True) ParamChecker.checkInt('months', param=True, max_len=2) except: raise HTTPRedirect('/payments/index') lastDate = self._getLastPayment(member_id) months = int(months) if self.is_finance_admin(): try: ParamChecker.checkInt('verified', param=True, max_len=1) verified = True except: verified = False try: for i in range(months): p = Payment() p.uid = member_id p.date = lastDate + relativedelta(months=i) p.status = 0 p.verified = verified self.db.add(p) self.db.commit() self.session['flash'] = _('Payments added') self.session['flash_class'] = 'success' except Exception as e: self.session['flash'] = _('Operation failed') self.session['flash_class'] = 'error' self.session.save() raise HTTPRedirect('/payments/listPayments/?member_id={0}'.format(member_id))
def deleteDomain(self, domain): return "HARD disabled ... you do not want to mess with this in production!!!" try: ParamChecker.checkDomain("domain", param=True) except: raise HTTPRedirect("/mails/index") try: result = self.mf.deleteDomain(domain) if result: msg = _("Domain successfully deleted") msg_class = "success" else: msg = _("Failed to delete domain!") msg_class = "error" except: msg = _("Failed to delete domain!") msg_class = "error" self.session.save() return self.index(msg=msg, msg_class=msg_class)
def deleteAlias(self, alias, *args, **kwargs): try: ParamChecker.checkEmail("alias", param=True) except: raise HTTPRedirect("/mails/index") try: result = self.mf.deleteAlias(alias) if result: msg = _("Alias successfully deleted") msg_class = "success" else: msg = _("Failed to delete alias!") msg_class = "error" except: import sys, traceback traceback.print_exc(file=sys.stdout) msg = _("Failed to delete alias!") msg_class = "error" return self.index(msg=msg, msg_class=msg_class)
def rejectValidation(self, member_id): try: member = self.mf.getUser(member_id) if member.validate: tm = self.db.query(TmpMember).filter( TmpMember.id == member.uidNumber).first() mail = tm.mail self.db.delete(tm) self.db.commit() self.session['flash'] = _('Changes rejected') self.postValidationMail(member_id, mail, validated=False) else: self.session['flash'] = _('Nothing to reject!') self.session['flash_class'] = 'error' except LookupError: self.session['flash'] = _('Failed to reject validation!') self.session['flash_class'] = 'error' self.session.save() raise HTTPRedirect('/members/showAllMembers')
def _sidebar(self): self.sidebar = [] self.sidebar.append({ 'name': _('Show all groups'), 'args': { 'controller': 'groups', 'action': 'listGroups' } }) self.sidebar.append({ 'name': _('Add Group'), 'args': { 'controller': 'groups', 'action': 'editGroup' } }) self.sidebar.append({ 'name': _('Members'), 'args': { 'controller': 'members', 'action': 'index' } })
def deleteDomain(self, domain): return 'HARD disabled ... you do not want to mess with this in production!!!' try: ParamChecker.checkDomain('domain', param=True) except: raise HTTPRedirect('/mails/index') try: result = self.mf.deleteDomain(domain) if result: msg = _('Domain successfully deleted') msg_class = 'success' else: msg = _('Failed to delete domain!') msg_class = 'error' except: msg = _('Failed to delete domain!') msg_class = 'error' self.session.save() return self.index(msg=msg, msg_class=msg_class)
def _sidebar(self): self.sidebar = [] self.sidebar.append({ 'name': _('Show all members'), 'args': { 'controller': 'members', 'action': 'showAllMembers' } }) self.sidebar.append({ 'name': _('Add member'), 'args': { 'controller': 'members', 'action': 'addMember' } }) self.sidebar.append({ 'name': _('Active members'), 'args': { 'controller': 'members', 'action': 'showActiveMembers' } }) self.sidebar.append({ 'name': _('Former members'), 'args': { 'controller': 'members', 'action': 'showFormerMembers' } }) self.sidebar.append({ 'name': _('Groups'), 'args': { 'controller': 'groups', 'action': 'index' } })
def editGroup(self, gid=None): c = TemplateContext() # vary form depending on mode (do that over ajax) if gid is None: c.group = Group() action = 'Adding' c.gid = '' else: try: ParamChecker.checkUsername('gid', param=True) except: msg = _('Invalid format!') return self.index(msg=msg) action = 'Editing' c.gid = gid try: c.group = self.mf.getGroup(gid) print 'poll' users = '' for u in c.group.users: if not users == '': users += '\n' users += u c.group.users = users except LookupError: # @TODO implement better handler msg = _('No such group!') return self.index(msg=msg) c.heading = '{0} group'.format(action) return self.render('/groups/editGroup.mako', template_context=c)
def editAvatar(self): c = TemplateContext() c.heading = _('Edit avatar') try: member = self.mf.getUser(self.session['username']) member.avatarUrl = self.avatarUrl(member.uid, size=180) c.member = member return self.render('/profile/editAvatar.mako', template_context=c) except LookupError: print 'Edit :: No such user !' return 'ERROR 4x0'
def checkMode(fn, param=True, values=[], optional=False): error_msg = _('Invalid mode') if param and TypeChecker.isParamSet(fn): fn = request.params[fn] else: raise InvalidParameterFormat(error_msg) found = False for v in values: if fn == v: found = True break if not found: raise InvalidParameterFormat(error_msg) return True
def checkCountryCode(fn, param=True, optional=False): error_msg = _('Invalid country code') ParamChecker._baseCheckString(fn, error_msg, param=param, min_len=2, max_len=2, optional=optional) if fn.lower() in countrycodes.cc: return True elif fn != '': raise InvalidParameterFormat(error_msg) if optional: return False raise InvalidParameterFormat(error_msg)
def showOutstanding(self, showAll=0): """ Show which users still need to pay their membership fees and if a reminder has already been sent """ if showAll == '1': showAll = True else: showAll = False activeMembers = self.mf.getActiveMemberList() # Prepare add payment form c = TemplateContext() c.heading = _('Outstanding payments') c.members = [] c.member_ids = [] for uid in activeMembers: last_payment = None try: last_payment = self.db.query(Payment).filter( and_(Payment.uid == uid, Payment.verified == 1)).order_by( Payment.date.desc()).limit(1)[0] except: ''' Don't care if there is no payment ''' pass m = self.mf.getUser(uid) m.paymentGood = False if last_payment: d = last_payment.date today = datetime.datetime.now().date() if d.year > today.year or (d.year == today.year and d.month >= today.month): m.paymentGood = True if not m.paymentGood or showAll: c.members.append(m) c.member_ids.append(uid) return self.render('/payments/showOutstanding.mako', template_context=c)
def viewDiff(self, member_id): c = TemplateContext() try: member = self.mf.getUser(member_id) if member.validate: c.heading = _('View diff') c.member = member tmpmember = self.db.query(TmpMember).filter( TmpMember.id == member.uidNumber).first() c.tmpmember = tmpmember return self.render('/members/viewDiff.mako', template_context=c) except LookupError: print 'No such user !' return 'ERROR 4x0'
def new_f(self, language): # @TODO request.params may contain multiple values per key... test & fix formok = True errors = [] try: ParamChecker.checkString('language', min_len=2, max_len=2) except InvalidParameterFormat: errors.append(_('Invalid language')) if not formok: self.session['errors'] = errors self.session['reqparams'] = {} # @TODO request.params may contain multiple values per key... test & fix for k in self.request.params.iterkeys(): self.session['reqparams'][k] = self.request.params[k] self.session.save() raise HTTPRedirect('/preferences/edit') return f(self)
def editDomain(self, domain=None): c = TemplateContext() # vary form depending on mode (do that over ajax) if domain is None: action = 'Adding' c.mode = 'add' else: try: ParamChecker.checkDomain('domain') except: return self.index() action = 'Editing' c.mode = 'edit' try: c.domain = self.mf.getDomain(domain) except LookupError: msg = _('No such domain!') return self.index(msg=msg) c.heading = '%s domain' % (action) return self.render('/mails/editDomain.mako', template_context=c)
def check(self): errors = [] checkOK = True try: ParamChecker.checkUsername(self.uid, param=False) except InvalidParameterFormat as ipf: checkOK = False errors.append(_('Invalid username')) try: ParamChecker.checkString(self.sn, min_len=0, max_len=20, param=False) except InvalidParameterFormat as ipf: checkOK = False errors.append(_('Invalid surname')) try: ParamChecker.checkString(self.givenName, min_len=0, max_len=20, param=False) except InvalidParameterFormat as ipf: checkOK = False errors.append(_('Invalid given name')) try: ParamChecker.checkString(self.homePostalAddress, min_len=0, max_len=255, param=False) except InvalidParameterFormat as ipf: checkOK = False errors.append(_('Invalid address')) '''optional''' try: ParamChecker.checkBool(self.isMinor, param=False, optional=True) except InvalidParameterFormat as ipf: checkOK = False errors.append(_('Invalid selection for "is minor"')) '''optional''' try: ParamChecker.checkPhone(self.homePhone, param=False, optional=True) except InvalidParameterFormat as ipf: checkOK = False errors.append(ipf.message) '''optional''' try: ParamChecker.checkPhone(self.mobile, param=False, optional=True) except InvalidParameterFormat as ipf: checkOK = False errors.append(_('Invalid mobile number')) try: ParamChecker.checkEmail(self.mail, param=False) except InvalidParameterFormat as ipf: checkOK = False errors.append(ipf.message) try: ParamChecker.checkString(self.loginShell, min_len=0, max_len=20, regex=regex.loginShell, param=False) except InvalidParameterFormat as ipf: checkOK = False errors.append(_('Invalid login shell')) try: ParamChecker.checkDate(self.arrivalDate, param=False) except InvalidParameterFormat as ipf: checkOK = False errors.append(_('Invalid "member since" date')) '''optional''' try: ParamChecker.checkDate(self.leavingDate, param=False, optional=True) except InvalidParameterFormat as ipf: checkOK = False errors.append(_('Invalid "membership canceled" date')) '''optional''' try: ParamChecker.checkString(self.sshPublicKey, min_len=0, max_len=1200, regex=regex.sshKey, param=False, optional=True) except InvalidParameterFormat as ipf: checkOK = False errors.append(_('Invalid SSH key')) '''optional''' try: ParamChecker.checkPGP(self.pgpKey, param=False, optional=True) except InvalidParameterFormat as ipf: checkOK = False errors.append(ipf.message) '''optional''' try: ParamChecker.checkiButtonUID(self.iButtonUID, param=False, optional=True) except InvalidParameterFormat as ipf: checkOK = False errors.append(ipf.message) try: ParamChecker.checkUsername(self.conventionSigner, param=False) except InvalidParameterFormat as ipf: checkOK = False errors.append(_('Invalid convention signer')) '''optional''' try: ParamChecker.checkEmail(self.xmppID, param=False, optional=True) except InvalidParameterFormat as ipf: checkOK = False errors.append(_('Invalid XMPP/Jabber/GTalk ID')) '''optional''' try: ParamChecker.checkBool(self.spaceKey, param=False, optional=True) except InvalidParameterFormat as ipf: checkOK = False errors.append(_('Invalid Space-Key value')) '''optional''' try: ParamChecker.checkBool(self.npoMember, param=False, optional=True) except InvalidParameterFormat as ipf: checkOK = False errors.append(_('Invalid NPO-Member value')) try: ParamChecker.checkCountryCode(self.nationality, param=False) except InvalidParameterFormat as ipf: checkOK = False errors.append(_('Invalid nationality')) if checkOK: return checkOK raise InvalidParameterFormat(errors)
def doEdit(self): m = self.mf.getUser(self.session['username']) if m.validate: # member locked for validation raise HTTPError(403, 'Forbidden') else: changes = False if self.request.params['sn'] != m.sn or\ self.request.params['givenName'] != m.givenName or\ self.request.params['homePostalAddress'] != m.homePostalAddress or\ self.request.params['homePhone'] != m.homePhone or\ self.request.params['mobile'] != m.mobile or\ self.request.params['mail'] != m.mail or\ self.request.params['xmppID'] != m.xmppID: changes = True if changes: tm = TmpMember(m.uidNumber) tm.sn = str(self.request.params['sn'].encode('utf-8')) tm.gn = str(self.request.params['givenName'].encode('utf-8')) tm.homePostalAddress = str( self.request.params['homePostalAddress'].encode('utf-8')) # @TODO make this more consistent if self.request.params.get('homePhone', '') == '' and not m.homePhone == '': tm.phone = '>>REMOVE<<' else: tm.phone = self.request.params['homePhone'] if self.request.params.get('xmppID', '') == '' and not m.xmppID == '': tm.xmppID = 'removed' else: tm.xmppID = self.request.params['xmppID'] tm.mobile = self.request.params['mobile'] tm.mail = self.request.params['mail'] self.db.add(tm) self.db.commit() self.session['flash'] = _('Changes saved!') self.session['flash_class'] = 'success' self.mailValidationRequired() else: self.session['flash'] = _('Nothing to save!') self.session['flash_class'] = 'info' if not self.request.params.get( 'userPassword', '' ) == '' and self.request.params[ 'userPassword'] == self.request.params['userPassword2']: m.setPassword(self.request.params['userPassword']) self.mf.saveMember(m, is_admin=False) self.session['secret'] = encodeAES( self.request.params['userPassword']) self.session['flash'] = _('Password updated!') self.session['flash_class'] = 'success' self.session.save() raise HTTPRedirect('/profile/index')
def checkPhone(fn, param=True, optional=False): return ParamChecker._baseCheckString(fn, _('Invalid phone number'), param=param, optional=optional, regex=regex.phone)
def checkDate(fn, param=True, optional=False): return ParamChecker._baseCheckString(fn, _('Invalid date'), param=param, optional=optional, regex=regex.date)
def checkPGP(fn, param=True, optional=False): return ParamChecker._baseCheckString(fn, _('Invalid PGP key'), param=param, optional=optional, regex=regex.pgpKey)
def checkBool(fn, param=True, optional=False): return ParamChecker._baseCheckBool(fn, _('Invalid Boolean value'), param=param, optional=optional)
def new_f(self, member_id, idPayment, date, status): # @TODO request.params may contain multiple values per key... test & fix if not self.is_admin() and not member_id == self.session.get( 'username') or (member_id == self.session.get('username') and ParamChecker.checkInt('idPayment', param=True, optional=True)): print 'checkPayment err0r::', str( self.isAdmin()), str(member_id), str( self.session.get('username')), str( ParamChecker.checkInt('idPayment', param=True, optional=True)) raise HTTPError(403, 'Forbidden') else: formok = True errors = [] items = {} d = None try: ParamChecker.checkDate('date', param=True) d = parser.parse(date) d = datetime.date(d.year, d.month, 1) except Exception as e: print e formok = False errors.append(_('Invalid date')) try: ParamChecker.checkInt('status', param=True) items['status'] = int(status) except: formok = False errors.append(_('Invalid payment status')) try: ParamChecker.checkInt('idPayment', param=True) items['idPayment'] = int(idPayment) except: items['idPayment'] = 0 if not d is None and items['idPayment'] == 0: p_count = self.db.query(Payment).filter( Payment.uid == member_id).filter( Payment.date == d).count() if p_count > 0: formok = False errors.append(_('That month is already on records!')) if not formok: self.session['errors'] = errors self.session['reqparams'] = {} # @TODO request.params may contain multiple values per key... test & fix for k in self.request.params.iterkeys(): self.session['reqparams'][k] = self.request.params[k] self.session.save() raise HTTPRedirect( '/payments/editPayment/?member_id={0}&idPayment={1}'. format(member_id, items['idPayment'])) else: items['date'] = d return f(self, member_id, items)
def checkiButtonUID(fn, param=True, optional=False): return ParamChecker._baseCheckString(fn, _('Invalid iButton UID'), param=param, optional=optional, regex=regex.iButtonUID)
def listDomains(self): c = TemplateContext() c.heading = _('Managed domains') c.domains = self.mf.getDomains() return self.render('/mails/listDomains.mako', template_context=c)
def _sidebar(self): self.sidebar = [] self.sidebar.append({'name': _('Show all domains'), 'args': {'controller': 'mails', 'action': 'listDomains'}}) self.sidebar.append({'name': _('Add domain'), 'args': {'controller': 'mails', 'action': 'editDomain'}}) self.sidebar.append({'name': _('Add alias'), 'args': {'controller': 'mails', 'action': 'editAlias'}})
def checkEmail(fn, param=True, optional=False): return ParamChecker._baseCheckString(fn, _('Invalid e-mail address'), param=param, optional=optional, regex=regex.email)
def listGroups(self): c = TemplateContext() c.heading = _('Managed groups') c.groups = self.mf.getManagedGroupList() return self.render('/groups/listGroups.mako', template_context=c)
def listPayments(self, member_id=None, year=None): """ Show a specific user's payments """ if member_id is None: if not self.is_admin() and not self.is_finance_admin(): raise HTTPError(403, 'Forbidden') else: raise HTTPRedirect('/payments/showOutstanding/?showAll=1') elif not self.is_admin() and not self.is_finance_admin( ) and not member_id == self.session.get('username'): raise HTTPError(403, 'Forbidden') if not year is None: try: ParamChecker.checkInt('year', param=True, max_len=4) if int(year) > 1970 and int(year) < 2222: year = int(year) else: year = datetime.datetime.now().year except: pass if year is None: try: ParamChecker.checkUsername('member_id', param=True) year = self._getLastPayment(member_id).year except: pass if year is None: year = datetime.datetime.now().year c = TemplateContext() c.heading = _('Payments for the year {0}, user {1}'.format( year, member_id)) c.member_id = member_id ## consider pagination # http://pylonsbook.com/en/1.1/starting-the-simplesite-tutorial.html#using-pagination try: #c.member.leavingDate = date(int(member.leavingDate[:4]),int(member.leavingDate[5:6]),int(member.leavingDate[7:8])) ## ideally, fetch monthly from member and the rest from payment (one to many relation) ## http://www.sqlalchemy.org/docs/05/reference/ext/declarative.html y_start = datetime.date(year, 1, 1) y_end = datetime.date(year, 12, 31) payment_sql = self.db.query(Payment).filter( Payment.uid == member_id).filter( Payment.date.between(y_start, y_end)).order_by( Payment.date.desc()).all() payments = {} c.unverifiedPledges = 0 for p in payment_sql: if p.verified == 0: c.unverifiedPledges += 1 payments[p.date.month] = p c.year = year c.payments = payments except AttributeError, e: return 'This member has made no payments o.O ?!: %s' % e
def new_f(self, mode, alias, domain, mail=None, maildrop=None): formok = True errors = [] items = {} if not mode in ['add', 'edit']: raise HTTPRedirect('/mails/index') if mode == 'add': try: ParamChecker.checkDomain('domain') except InvalidParameterFormat as ipf: formok = False errors.append(ipf.message) alias += '@' + domain domain = alias.split('@')[1] try: ParamChecker.checkDomain(domain, param=False) except InvalidParameterFormat as ipf: formok = False errors.append(ipf.message) # @TODO improve check try: ParamChecker.checkString('maildrop', min_len=0, max_len=300) except InvalidParameterFormat as ipf: formok = False errors.append(_('Invalid mail destination!')) if mail and not mail == '': for k in mail.split('\n'): m = k.replace('\r', '').replace(' ', '') if m == '': continue try: ParamChecker.checkEmail(m, param=False) except: formok = False break m_domain = m.split('@')[1] if not m_domain == domain: formok = False errors.append(_('All aliases need to be within the same domain!')) break if len(mail) > 300: formok = False if not formok: errors.append(_('Invalid related aliases!')) if not formok: self.session['errors'] = errors self.session['reqparams'] = {} # @TODO request.params may contain multiple values per key... test & fix for k in cherrypy.request.params.iterkeys(): self.session['reqparams'][k] = cherrypy.request.params[k] self.session.save() if mode == 'edit': raise HTTPRedirect('/mails/editAlias/?alias={0}'.format(alias)) else: raise HTTPRedirect('/mails/editAlias') else: items['mode'] = mode items['alias'] = alias items['mail'] = [] items['maildrop'] = [] if mail and len(mail) > 0: for k in mail.split('\n'): m = k.replace('\r', '').replace(' ', '') if m == '': continue items['mail'].append(m) if maildrop and len(maildrop) > 0: for k in maildrop.split('\n'): m = k.replace('\r', '').replace(' ', '') if m == '': continue items['maildrop'].append(m) return f(self, items)