def render_userbox(self, ctx, data): """Render the box containing the user's login status.""" avatar = maybe_user(ctx) srv = IService(ctx) warn = '' if avatar.anonymous: email = None else: email = avatar.user.email if not email: email = srv.pretendedEmail(avatar.user) warn = T.span( id="activate")[u"Vous devez encore ", T.a(href="/")[u"activer votre compte"]] if email: greetings = T.div( _class="userinfo")[warn, T.span(style="padding-right:3em")[email], T.a(href="/")[u"Réservations"], u' :: ', T.a(href="/logout")[u"Quitter"], ] else: info = login.LoginInfo(warnings=False, force_reconnect=True) greetings = T.div(_class="userinfo")[login.LoginFragment( original=info)] return ctx.tag[T.a(href="/")[T.img(src="/images/mes-souhaits.png", align="left", alt="Mes souhaits", width=203, height=36)], greetings]
def renderHTTP(self, ctx): """Handle HTTP requests.""" srv = IService(ctx) request = IRequest(ctx) current = must_user(ctx) user = srv.validate_challenge( # pylint: disable-msg=E1101 self.challenge, current.session) if user: message(ctx, u'Bienvenue, %s' % (user.email, )) request.redirect("/") request.finish() return '' # Some people simply reuse invitations: don't complain if they # are already connected, just redirect them to the main page. avatar = maybe_user(ctx) if avatar.identified: request.redirect("/") request.finish() return '' # pylint: disable-msg=E1101 self.contentTags = [ T.h1[u"Cette clé n'est pas valable"], T.p[u"Vous pouvez obtenir une nouvelle clé par e-mail.", T.div(_class="editable bl")[T.div(_class="br")[T.div( _class="tl")[T.div(_class="tr")[T.div( _class="edcontent")[login.LoginFragment( original=login.LoginInfo( force_reconnect=True))], ]]]]] ] return BasePage.renderHTTP(self, ctx)
def data_listContent(self, ctx, _): """Return the list's content (ie the items).""" avatar = maybe_user(ctx) editable = manages_list(ctx, avatar, self.list) needs_reservation = not editable or self.list.showres srv = IService(ctx) # pylint: disable-msg=E1101 items = srv.itemsForList(self.list, needs_reservation) # The list admin needs to see all the items, for other users, # discard items reserved by someone else if not editable: # Simple users have the "reserved" tag, but cannot see by # whom if avatar.anonymous: user = None else: user = avatar.user.id items = [ item for item in items if item.res is None or item.res[0] == user ] # discard the info about who reserved for i in items: if i.res: i.res = (i.res[0], i.res[1], None) return items
def render_myLists(self, ctx, data): """Render the 'sender' field.""" selected = {} for l in data['lst']: selected[l.id] = True # pylint: disable-msg=E1101 srv = IService(ctx) user = must_user(ctx).user lsts = srv.getListsOwnedBy(user) lsts += srv.getFriendLists(user) checkbox = [] for lst, _ in lsts: name = lst.name or T.i[u'Liste sans nom'] args = {'type': "checkbox", 'name': "lst", 'value': lst.id} if lst.id in selected: args['checked'] = '1' checkbox.append( T.div(style="margin-left:2em")[T.input(**args)[u'\xa0' + name]]) return ctx.tag[checkbox]
def child_edit(self, ctx): """Handle edit requests.""" if not manages_list(ctx, must_user(ctx), self.list): message(ctx, u"Vous n'avez pas le droit de modifier cet objet.") return url.URL.fromContext(ctx).up() if ctx.arg('cancel'): message(ctx, u'La modification a été annulée.') return url.URL.fromContext(ctx).up() args = process_default(ctx, self.defaultValues) if not (args['title'] or args['description'] or args['url'] or args['score']): return url.URL.fromContext(ctx) try: score = int(args['score']) if score > 3 or score < 1: raise ValueError except ValueError: score = 2 srv = IService(ctx) srv.editItem( self.item, # pylint: disable-msg=E1101 args['title'], args['description'], args['url'], score) message(ctx, u'Votre souhait a bien été modifié.') return url.URL.fromContext(ctx).up()
def render_maybeEdit(self, ctx, _): """Render action buttons if available.""" # pylint: disable-msg=E1101 if manages_list(ctx, must_user(ctx), self.list): srv = IService(ctx) if srv.isReserved(self.item): notify = T.p[T.input( type="checkbox", name="notify", value="1", checked=""), u"\xa0Avertir la personne qui l'a réservé"] else: notify = [] return ctx.tag(_class="editable bl")[T.div(_class="br")[T.div( _class="tl")[T.div(_class="tr")[T.form( name='confirm', action=url.here.child('confirm'), method='POST', _class="edcontent")[ notify, T.input(type='submit', name='confirm', value=u"Confirmer l'effacement"), T.input(type='submit', name='cancel', value=u"Annuler" ), ]]]]] else: return ''
def render_emailValue(self, ctx, _): """Render the 'email' field.""" srv = IService(ctx) user = maybe_user(ctx).user email = srv.pretendedEmail(user) # pylint: disable-msg=E1101 return ctx.tag(value=email)
def childFactory(self, ctx, name): """Handle all the others sub pages (ie, the items).""" srv = IService(ctx) wl = srv.getListItem(self.list, name) # pylint: disable-msg=E1101 if wl: return ListItem(self.list, wl) return None
def maybe_user(ctx): """Return the user's avatar, but don't create a session.""" cookie = session_cookie(ctx) srv = IService(ctx) # pylint: disable-msg=E1101 user = Avatar(srv.getSessionUser(cookie), srv, cookie) if user.session: # extend the cookie _set_cookie(ctx, user.session) return user
def child_confirm(self, ctx): """Handle the confirmation that a list is dropped.""" srv = IService(ctx) avatar = must_user(ctx) srv.remove_from_friend( # pylint: disable-msg=E1101 avatar.user, self.list) message(ctx, u'Vous ne suivez plus cette liste.') return url.URL.fromString("/")
def child_confirm(self, ctx): """Confirm that an item has been donated.""" srv = IService(ctx) avatar = must_user(ctx) if not avatar.identified: message(ctx, u"Vous devez confirmer votre email d'abord.") return url.URL.fromContext(ctx).up().up() srv.donatedItem(avatar.user, self.item) # pylint: disable-msg=E1101 message(ctx, u"Votre modification est enregistrée.") return url.URL.fromContext(ctx).up().up()
def renderHTTP_exception(self, ctx, failure): """Render the error page.""" request = IRequest(ctx) request.setResponseCode(http.INTERNAL_SERVER_ERROR) res = self.renderHTTP(ctx) request.finishRequest(False) log.err(failure) service = IService(ctx) service.build_and_send(service.ADMIN, '[crash report] mes-souhaits.net', str(failure)) return res
def child_giveup(self, ctx): """Handle reservation cancellation requests.""" srv = IService(ctx) user = must_user(ctx).user if ctx.arg('giveup'): srv.giveupItem(user, self.item) # pylint: disable-msg=E1101 message(ctx, u"Votre modification est enregistrée.") request = IRequest(ctx) referer = request.getHeader('referer') if referer: return url.URL.fromString(referer) return url.URL.fromContext(ctx).up()
def data_listResa(self, ctx, _): """Return the user's reservations.""" user = maybe_user(ctx).user srv = IService(ctx) # pylint: disable-msg=E1101 items = [ item for item in srv.getUserReservations(user) if item.res[1] == 'R' ] for i in items: i.res = (i.res[0], i.res[1], None) return items
def child_confirm(self, ctx): """Handle .../confirm.""" if not manages_list(ctx, must_user(ctx), self.list): message(ctx, u"Vous n'avez pas le droit de modifier cet objet.") return url.URL.fromContext(ctx).up().up() if ctx.arg('cancel'): message(ctx, u"L'effacement a été annulé.") return url.URL.fromContext(ctx).up().up() srv = IService(ctx) # pylint: disable-msg=E1101 srv.deleteItem(self.item, ctx.arg('notify')) message(ctx, u'Votre souhait a bien été supprimé.') return url.URL.fromContext(ctx).up().up()
def child_confirm(self, ctx): """Confirm that the list must be destroyed.""" if not owns_list(must_user(ctx), self.list): return url.URL.fromContext(ctx).up() if ctx.arg('cancel'): message(ctx, u"L'opération a été annulée.") return url.URL.fromContext(ctx).up() srv = IService(ctx) srv.destroyList(self.list) # pylint: disable-msg=E1101 message(ctx, u'Votre liste a bien été détruite.') return url.URL.fromString("/")
def beforeRender(self, ctx): """Called before the page is actually rendered.""" # If we are connected, we can put this list in our "friends" list avatar = maybe_user(ctx) if not avatar.identified or owns_list(avatar, self.list): return # pylint: disable-msg=E1101 IService(ctx).addToFriend(avatar.user, self.list)
def render_display_stats(self, ctx, _): """Display the number of watchers for this list.""" srv = IService(ctx) t = ctx.tag r = len(srv.getListReservations( self.list)) # pylint: disable-msg=E1101 if r: if r == 1: txt = 'une réservation' else: txt = '%d réservations' % r # pylint: disable-msg=E1101 t = t[u'Il y a ', T.b[txt], u' sur cette liste.'] return t
def _create_session(ctx): """Create a new session and give it a cookie.""" # pylint: disable-msg=E1101 user, new_cookie = IService(ctx).createSessionUser() log.msg('creating new session %s' % new_cookie) _set_cookie(ctx, new_cookie) return user, new_cookie
def must_user(ctx): """Ensure that the user has a session and return its avatar.""" user = maybe_user(ctx) srv = IService(ctx) if user.user: return user user, cookie = _create_session(ctx) return Avatar(user, srv, cookie)
def _create_list(self, ctx, name, email): """Actually create the new list.""" req = IRequest(ctx) srv = IService(ctx) avatar = must_user(ctx) # pylint: disable-msg=E1101 wl = srv.createList(avatar.user, name, email) if not wl: req.redirect('/') req.finish() return if not avatar.identified: message( ctx, u"Un message de confirmation a été envoyé" u" à l'adresse <%s>." % (email, )) req.redirect('/' + wl.url) req.finish()
def childFactory(self, ctx, name): """Serve specific lists.""" srv = IService(ctx) name = name.decode('utf-8') # pylint: disable-msg=E1101 wl = srv.getListByURL(name) if wl: return List(wl) # Be nice to the user: if he introduced capitals or other # symbols, try with the normalized form too. norm = core.normalize_url(name) if norm != name: wl = srv.getListByURL(norm) if wl: return url.URL.fromContext(ctx).sibling(wl.url) return None
def render_fullList(self, ctx, data): """Render details of a single item.""" tag = ListBase.render_fullList(self, ctx, data) srv = IService(ctx) # pylint: disable-msg=E1101 if srv.isReserved(self.item): msg = u"""Ce souhait est déjà réservé par quelqu'un. Êtes-vous sûr de vouloir le supprimer\xa0?""" else: msg = u"""Vous êtes sur le point d'effacer un souhait. Cette opération est irréversible.""" return T.div[T.table[T.tr[T.td[T.img(src="/images/logo-danger.png", width="35", height="41", style="margin-right: 1em", alt="Attention"), ], T.td(valign="center")[msg]]], tag]
def render_possibleActions(self, ctx, data): """Render the buttons with the possible actions.""" # pylint: disable-msg=E1101 srv = IService(ctx) lst = srv.getListByKey(data.list) action = url.here.child(lst.url).child(data.key) donated = T.a( href=action.child('donated'), style="margin-left:2em")[u"»\xa0Vous avez donné le cadeau\xa0?"] modify = T.form( action=action.child('giveup'), name='giveup', _class='item-op', method='POST')[T.input( type='submit', name='giveup', value=u'Abandonner cette idée'), donated] return ctx.tag[modify]
def child_get(self, ctx): """Handle reservation requests.""" avatar = must_user(ctx) if owns_list(avatar, self.list): message(ctx, u"Vous ne pouvez pas réserver un de vos souhaits.") return url.URL.fromContext(ctx).up() # In any case, the item is reserved. It is up to the user to # possibly confirm his identity. if not avatar.anonymous: srv = IService(ctx) # pylint: disable-msg=E1101 srv.reserveItem(avatar.user, self.item) message(ctx, u'Votre réservation est enregistrée.') return url.URL.fromContext(ctx).up() message( ctx, u'Votre réservation sera effective lorsque ' u'vous vous serez identifié.') # redirect here after authentication referer = url.URL.fromContext(ctx).child('get') return url.URL.fromString('/login').add(name='referer', value=referer)
def login_info_from_context(ctx): """Collect all login info from the context.""" info = LoginInfo() email = ctx.arg('email') if email: info.email = email.decode('utf-8') else: info.email = u'' info.reconnect = ctx.arg('reconnect') == 'true' info.referer = url.URL.fromString( ctx.arg('referer') or IRequest(ctx).getHeader('referer') or '/') if info.reconnect: # pylint: disable-msg=E1101 info.known = IService(ctx).getUserByEmail(info.email) return info
def render_login(self, ctx, data): """Render the whole login box.""" # pylint: disable-msg=E1101 if IRequest(ctx).method == 'POST' and data.is_valid(): # Simply send a challenge to this email address message( ctx, u"""Un message de confirmation a été envoyé """ u"""à l'adresse <%s>.""" % data.email) IService(ctx).pretend_email_address( must_user(ctx).user, data.email) IRequest(ctx).redirect(data.referer) IRequest(ctx).finish() else: return ctx.tag
def child_add(self, ctx): """Handle the .../add page.""" avatar = must_user(ctx) if not manages_list(ctx, avatar, self.list): log.msg('unauthorized access to the list/add method') return url.URL.fromContext(ctx) args = {} for k in self.defaultValues.keys(): v = ctx.arg(k) or '' v = v.strip().decode('utf-8') if not v or \ v == self.defaultValues[k]: args[k] = '' else: args[k] = v if not (args['title'] or args['description'] or args['url']): return url.URL.fromContext(ctx) srv = IService(ctx) srv.addNewItem( self.list, args['title'], # pylint: disable-msg=E1101 args['description'], args['url']) message(ctx, u'Votre souhait a bien été enregistré.') back = ctx.arg('back') if back: back = url.URL.fromString(back) else: back = url.URL.fromContext(ctx) return back
def render_listDesc(self, ctx, _): """Render the list's description.""" avatar = maybe_user(ctx) editable = manages_list(ctx, avatar, self.list) # pylint: disable-msg=E1101 desc = self.list.desc or T.em['(pas de description)'] if editable: invite = url.URL.fromString("/invite") invite = invite.add('lst', str(self.list.id)) srv = IService(ctx) name = self.list.name or 'ma liste' action = """ url=encodeURIComponent(location.href);location.href='%s?url='+url+'&title='+encodeURIComponent(document.title)+'&back='+url """ % (srv.base_url + '/' + self.list.url) action = re.sub('\s+', ' ', action.strip()) desc = [ desc, T.div(_class="listaction")[ u'» ', T.b[T.a(href=invite)[u'Inviter']], ' :: ', T.a(href=url.here.child('edit'))[u'Modifier'], ' :: ', T.a(href=url.here.child('destroy'))[u'Détruire'], ], T.div(_class="listaction")[ T.em[u'Glisse moi dans tes bookmarks\xa0! '], T.a(href='javascript:' + action)[u'» %s' % name]] ] elif avatar.identified: desc = [ desc, T.div(_class="listaction")[ u'» ', T.a(href=url.here.child('unsubscribe'))[u'Ignorer'], ] ] return ctx.tag[desc]
def data_form(self, ctx, _): """Return the options passed in the invitation form.""" req = IRequest(ctx) warn = [] vals = {'msg': ''} srv = IService(ctx) avatar = must_user(ctx) user = avatar.user # pylint: disable-msg=E1101 if req.method == 'POST': if not arg(req, 'send'): req.redirect('/') req.finish() return self._defaults if not avatar.identified: warn.append(u"Vous n'avez pas encore activé votre compte.") vals['sender'] = arg(req, 'sender') if not vals['sender']: warn.append(u"Vous n'avez pas précisé votre nom.") vals['email'] = arg(req, 'email') if not vals['email']: warn.append(u"Vous n'avez pas précisé de destinataire.") vals['body'] = arg(req, 'body') if not vals['body']: warn.append(u"Votre message n'a pas de contenu.") # We simply filter out lists that don't belong to the # user. vals['lst'] = _my_lists(req.args.get('lst', []), srv, user) if not vals['lst']: warn.append(u"Choisissez au moins une liste ci-dessous.") vals['warn'] = warn if not warn: if not srv.inviteFriend(vals['sender'], user, vals['lst'], vals['email'], vals['body']): warn.append(u"L'adresse <%s> n'est pas valide." % (vals['email'], )) else: vals['msg'] = u'Votre invitation a été envoyée à %s' % ( vals['email'], ) # When we have sent properly, forget the previous # emails, so we don't double-send by mistake. vals['email'] = '' else: vals = self._defaults vals['lst'] = _my_lists(req.args.get('lst', []), srv, user) return vals