def test_login_sso(self): o = util.override(DOMAIN=self.domain, GAE_DOMAIN=self.gae_domain, HOSTED_DOMAIN_ENABLED=True, HOSTED_DOMAIN=self.hosted_domain, SUBDOMAINS_ENABLED=True, SSL_LOGIN_ENABLED=True, ) r = self.post_with_host('/login', {'log': 'popular', 'pwd': self.passwords[clean.nick('popular')] }, self.gae_domain, ssl=True ) check_redirect = 'http://%s/login/noreally' % self.domain r = self.assertRedirectsPrefix(r, check_redirect, status_code=302, target_status_code=302) r = self.assertRedirectsPrefix(r, '/user/popular/overview', status_code=302, target_status_code=200) o.reset()
def actor_invite(request, nick, format='html'): nick = clean.nick(nick) view = api.actor_lookup_nick(request.user, nick) if not view: raise exception.UserDoesNotExistError(nick, request.user) if view.nick != request.user.nick: # Bounce the user to their own page (avoids any confusion for the wrong # nick in the url). return http.HttpResponseRedirect( '%s/invite' % request.user.url()) handled = common_views.handle_view_action( request, { 'invite_request_email': request.path, }) if handled: return handled if request.user and request.user.nick == view.nick: whose = 'Your' else: whose = "%s's" % view.display_nick() c = template.RequestContext(request, locals()) if format == 'html': t = loader.get_template('actor/templates/invite.html') return http.HttpResponse(t.render(c))
def test_login(self): log = 'popular' pwd = self.passwords[clean.nick(log)] r = self.client.post('/login', {'log': log, 'pwd': pwd}) r = self.assertRedirectsPrefix(r, '/user/popular/overview') self.assertTemplateUsed(r, 'actor/templates/overview.html') self.assertTemplateUsed(r, 'common/templates/flash.html')
def actor_invite(request, nick, format='html'): nick = clean.nick(nick) view = api.actor_lookup_nick(request.user, nick) if not view: raise exception.UserDoesNotExistError(nick, request.user) if view.nick != request.user.nick: # Bounce the user to their own page (avoids any confusion for the wrong # nick in the url). return http.HttpResponseRedirect('%s/invite' % request.user.url()) handled = common_views.handle_view_action( request, { 'invite_request_email': request.path, }) if handled: return handled if request.user and request.user.nick == view.nick: whose = 'Your' else: whose = "%s's" % view.display_nick() c = template.RequestContext(request, locals()) if format == 'html': t = loader.get_template('actor/templates/invite.html') return http.HttpResponse(t.render(c))
def test_login(self): log = "popular" pwd = self.passwords[clean.nick(log)] r = self.client.post("/login", {"log": log, "pwd": pwd}) r = self.assertRedirectsPrefix(r, "/user/popular/overview") self.assertTemplateUsed(r, "actor/templates/overview.html") self.assertTemplateUsed(r, "common/templates/flash.html")
def test_settings_change_avatar(self): nick = 'obligated' self.login(nick) nick = clean.nick(nick) old_avatar = api.actor_get(api.ROOT, nick).extra.get('icon', 'avatar_default') # TODO(teemu): add more tests for different file types (gif and jpg). # Alternatively, test those against api.avatar_upload. r = self.client.post('/user/obligated/settings/photo', { 'avatar': 'default/animal_9', '_nonce' : util.create_nonce('obligated', 'change_photo'), }) r = self.assertRedirectsPrefix(r, '/user/obligated/settings/photo') new_avatar = api.actor_get(api.ROOT, nick).extra.get('icon', 'avatar_default') self.assertNotEquals(old_avatar, new_avatar) self.assertContains(r, 'Avatar changed') self.assertTemplateUsed(r, 'actor/templates/settings_photo.html') self.assertTemplateUsed(r, 'common/templates/flash.html')
def actor_settings_redirect(request): if not request.user: return http.HttpResponseRedirect('/login?redirect_to=%s' % request.get_full_path()) nick = clean.nick(request.user.nick) view = api.actor_lookup_nick(request.user, nick) return http.HttpResponseRedirect(view.url() + request.get_full_path())
def test_sign_in(self): nick = 'popular' password = self.passwords[clean.nick(nick)] r = self.receive('SIGN IN %s %s' % (nick, password)) self.assertOutboxContains( r, 'Welcome to %s SMS %s' % (settings.SITE_NAME, nick))
def test_login_sso(self): o = util.override( DOMAIN=self.domain, GAE_DOMAIN=self.gae_domain, HOSTED_DOMAIN_ENABLED=True, HOSTED_DOMAIN=self.hosted_domain, SUBDOMAINS_ENABLED=True, SSL_LOGIN_ENABLED=True, ) r = self.post_with_host('/login', { 'log': 'popular', 'pwd': self.passwords[clean.nick('popular')] }, self.gae_domain, ssl=True) check_redirect = 'http://%s/login/noreally' % self.domain r = self.assertRedirectsPrefix(r, check_redirect, status_code=302, target_status_code=302) r = self.assertRedirectsPrefix(r, '/user/popular/overview', status_code=302, target_status_code=200) o.reset()
def actor_settings_redirect(request): if not request.user: return http.HttpResponseRedirect( '/login?redirect_to=%s' % request.get_full_path()) nick = clean.nick(request.user.nick) view = api.actor_lookup_nick(request.user, nick) return http.HttpResponseRedirect(view.url() + request.get_full_path())
def test_login_with_confirmed_email(self): log = 'hotness' pwd = self.passwords[clean.nick(log)] confirmed_email = '*****@*****.**' r = self.client.post('/login', {'log': confirmed_email, 'pwd': pwd}) r = self.assertRedirectsPrefix(r, '/user/hotness/overview') self.assertTemplateUsed(r, 'actor/templates/overview.html') self.assertTemplateUsed(r, 'common/templates/flash.html')
def test_login_with_confirmed_email(self): log = "hotness" pwd = self.passwords[clean.nick(log)] confirmed_email = "*****@*****.**" r = self.client.post("/login", {"log": confirmed_email, "pwd": pwd}) r = self.assertRedirectsPrefix(r, "/user/hotness/overview") self.assertTemplateUsed(r, "actor/templates/overview.html") self.assertTemplateUsed(r, "common/templates/flash.html")
def actor_followers(request, nick=None, format='html'): nick = clean.nick(nick) view = api.actor_lookup_nick(request.user, nick) if not view: raise exception.UserDoesNotExistError(nick, request.user) handled = common_views.handle_view_action( request, { 'actor_add_contact': request.path, 'actor_remove_contact': request.path, }) if handled: return handled per_page = CONTACTS_PER_PAGE offset, prev = util.page_offset_nick(request) follower_nicks = api.actor_get_followers(request.user, view.nick, limit=(per_page + 1), offset=offset) actor_nicks = follower_nicks actors = api.actor_get_actors(request.user, actor_nicks) # clear deleted actors actors = dict([(k, v) for k, v in actors.iteritems() if v]) per_page = per_page - (len(follower_nicks) - len(actors)) # TODO(termie): incorporate this into paging so we only fetch the range # on this page # add some extra info so we can let the user do contextual actions # on these homeboys if request.user and request.user.nick == view.nick: for actor in actors: if api.actor_is_contact(request.user, view.nick, actor): actors[actor].my_contact = True whose = 'Your' else: whose = "%s's" % view.display_nick() # here comes lots of munging data into shape actor_tiles = [actors[x] for x in follower_nicks if x in actors] actor_tiles_count = view.extra.get('follower_count', 0) actor_tiles, actor_tiles_more = util.page_actors(request, actor_tiles, per_page) area = 'people' c = template.RequestContext(request, locals()) # TODO: Other output formats. if format == 'html': t = loader.get_template('actor/templates/followers.html') return http.HttpResponse(t.render(c))
def test_login_deleted(self): log = "popular" pwd = self.passwords[clean.nick(log)] r = self.client.post("/login", {"log": log, "pwd": pwd}) r = self.assertRedirectsPrefix(r, "/user/popular/overview") self.assertTemplateUsed(r, "actor/templates/overview.html") self.assertTemplateUsed(r, "common/templates/flash.html") api.actor_remove(api.ROOT, "popular") r = self.client.post("/login", {"log": log, "pwd": pwd}) self.assert_error_contains(r, "Invalid username") self.assertTemplateUsed(r, "login/templates/login.html")
def test_login_deleted(self): log = 'popular' pwd = self.passwords[clean.nick(log)] r = self.client.post('/login', {'log': log, 'pwd': pwd}) r = self.assertRedirectsPrefix(r, '/user/popular/overview') self.assertTemplateUsed(r, 'actor/templates/overview.html') self.assertTemplateUsed(r, 'common/templates/flash.html') api.actor_remove(api.ROOT, 'popular') r = self.client.post('/login', {'log': log, 'pwd': pwd}) self.assert_error_contains(r, 'Invalid username') self.assertTemplateUsed(r, 'login/templates/login.html')
def actor_remove_contact(self, from_jid, nick): jid_ref = api.actor_lookup_im(api.ROOT, from_jid.base()) if not jid_ref: raise exception.ValidationError( "You must be signed in to post, please SIGN IN") nick = clean.nick(nick) try: api.actor_remove_contact(jid_ref, jid_ref.nick, nick) self.send_message((from_jid, ), "%s stopped following %s" % (jid_ref.nick, nick)) except: self.send_message((from_jid, ), "Leave FAILED: %s" % nick)
def actor_add_contact(self, sender, nick): sender_ref = api.actor_lookup_mobile(api.ROOT, sender) if not sender_ref: raise exception.ValidationError(HELP_SIGN_IN) clean_nick = clean.nick(nick) try: api.actor_add_contact(sender_ref, sender_ref.nick, clean_nick) self.send_message((sender,), "%s followed %s" % (sender_ref.display_nick(), nick)) except: self.send_message((sender,), "Failed to follow %s" % nick)
def actor_remove_contact(self, sender, nick): sender_ref = api.actor_lookup_mobile(api.ROOT, sender) if not sender_ref: raise exception.ValidationError(HELP_SIGN_IN) clean_nick = clean.nick(nick) try: api.actor_remove_contact(sender_ref, sender_ref.nick, clean_nick) self.send_message( (sender, ), "%s stopped following %s" % (sender_ref.dispaly_nick(), nick)) except: self.send_message((sender, ), "Failed to stop following %s" % nick)
def actor_remove_contact(self, from_jid, nick): jid_ref = api.actor_lookup_im(api.ROOT, from_jid.base()) if not jid_ref: raise exception.ValidationError( "You must be signed in to post, please SIGN IN") nick = clean.nick(nick) try: api.actor_remove_contact(jid_ref, jid_ref.nick, nick) self.send_message((from_jid,), "%s stopped following %s" % (jid_ref.nick, nick)) except: self.send_message((from_jid,), "Leave FAILED: %s" % nick)
def test_login_user_cleanup(self): log = "broken" pwd = self.passwords[clean.nick(log)] actor_ref_pre = api.actor_get(api.ROOT, log) self.assert_(not actor_ref_pre.normalized_nick) self.assertRaises(exception.ApiException, api.stream_get_presence, api.ROOT, log) self.assertRaises(exception.ApiException, api.stream_get_comment, api.ROOT, log) r = self.client.post("/login", {"log": log, "pwd": pwd}) r = self.assertRedirectsPrefix(r, "/user/broken/overview") actor_ref_post = api.actor_get(api.ROOT, log) self.assert_(actor_ref_post.normalized_nick) self.assert_(api.stream_get_presence(api.ROOT, log)) self.assert_(api.stream_get_comment(api.ROOT, log))
def reponse_if_exists(id, service=None): if service is None: view = api.actor_lookup_email(api.ROOT, id) else: eprofile = api.get_external_profile(service, id) if eprofile is not None: nick = clean.nick(eprofile.nick) view = api.actor_lookup_nick(api.ROOT, nick) else: return None if view: response = http.HttpResponseRedirect(view.url("/overview")) response = user.set_user_cookie(response, view) return response return None
def create_nonce(user, action, offset=0): if not user: nick = "" else: try: nick = user.nick except AttributeError: if settings.MANAGE_PY: # extra case to make testing easier nick = clean.nick(user) else: raise i = math.ceil(time.time() / 43200) i += offset nonce = hash_generic(str(i) + action + nick) return nonce[-12:-2]
def test_login_user_cleanup(self): log = 'broken' pwd = self.passwords[clean.nick(log)] actor_ref_pre = api.actor_get(api.ROOT, log) self.assert_(not actor_ref_pre.normalized_nick) self.assertRaises(exception.ApiException, api.stream_get_presence, api.ROOT, log) self.assertRaises(exception.ApiException, api.stream_get_comment, api.ROOT, log) r = self.client.post('/login', {'log': log, 'pwd': pwd}) r = self.assertRedirectsPrefix(r, '/user/broken/overview') actor_ref_post = api.actor_get(api.ROOT, log) self.assert_(actor_ref_post.normalized_nick) self.assert_(api.stream_get_presence(api.ROOT, log)) self.assert_(api.stream_get_comment(api.ROOT, log))
def add_comment(self, sender, nick, message): sender_ref = api.actor_lookup_mobile(api.ROOT, sender) if not sender_ref: raise exception.ValidationError(HELP_SIGN_IN) logging.debug("comment: %s %s %s", nick, sender_ref.nick, message) nick = clean.nick(nick) stream_entry = api.reply_get_cache(sender=nick, target=sender_ref.nick, service='sms') if not stream_entry: # Well, or memcache timed it out... Or we crashed... Or... Or... raise exception.ValidationError( 'The message to which you tried to respond doesn\'t exist') api.entry_add_comment(sender_ref, entry=stream_entry.keyname(), content=message, nick=sender_ref.nick, stream=stream_entry.stream)
def add_comment(self, from_jid, nick, message): jid_ref = api.actor_lookup_im(api.ROOT, from_jid.base()) if not jid_ref: raise exception.ValidationError( "You must be signed in to post, please SIGN IN") logging.debug("comment: %s %s %s", nick, jid_ref.nick, message) nick = clean.nick(nick) stream_entry = api.reply_get_cache(sender=nick, target=jid_ref.nick, service='im') if not stream_entry: # Well, or memcache timed it out... Or we crashed... Or... Or... raise exception.ValidationError( 'The message to which you tried to respond doesn\'t exist') api.entry_add_comment(jid_ref, entry=stream_entry.keyname(), content=message, nick=jid_ref.nick, stream=stream_entry.stream)
def test_photo_upload(self): nick = 'popular' nick = clean.nick(nick) old_avatar = api.actor_get(api.ROOT, nick).extra.get('icon', 'avatar_default') self.login(nick) f = open('testdata/test_avatar.jpg') r = self.client.post( '/welcome/1', { 'imgfile': f, '_nonce': util.create_nonce('popular', 'change_photo'), }) r = self.assertRedirectsPrefix(r, '/welcome/1?') new_avatar = api.actor_get(api.ROOT, nick).extra.get('icon', 'avatar_default') self.assertNotEquals(old_avatar, new_avatar) self.assertContains(r, 'Avatar uploaded') self.assertTemplateUsed(r, 'join/templates/welcome_photo.html') self.assertTemplateUsed(r, 'common/templates/flash.html')
def test_settings_upload_avatar(self): nick = 'obligated' self.login(nick) nick = clean.nick(nick) old_contact_avatars = api.actor_get_contacts_avatars_since( api.ROOT, nick) contacts = api.actor_get_contacts(api.ROOT, nick) self.assertEquals(len(old_contact_avatars), len(contacts) + 1) old_avatar = api.actor_get(api.ROOT, nick).extra.get('icon', 'avatar_default') start_time = api.utcnow() no_contact_avatars = api.actor_get_contacts_avatars_since( api.ROOT, nick, since_time=start_time) self.assertEquals(len(no_contact_avatars), 0) # TODO(teemu): add more tests for different file types (gif and jpg). # Alternatively, test those against api.avatar_upload. f = open('testdata/test_avatar.jpg') r = self.client.post( '/user/obligated/settings/photo', { 'imgfile': f, '_nonce': util.create_nonce('obligated', 'change_photo'), }) r = self.assertRedirectsPrefix(r, '/user/obligated/settings/photo') actor_ref = api.actor_get(api.ROOT, nick) new_avatar = actor_ref.extra.get('icon', 'avatar_default') self.assertNotEquals(old_avatar, new_avatar) self.assertTrue(actor_ref.avatar_updated_at >= start_time) new_contact_avatars = api.actor_get_contacts_avatars_since( api.ROOT, nick, since_time=start_time) self.assertEquals(len(new_contact_avatars), 1) self.assertEquals(new_contact_avatars.pop().nick, nick) self.assertContains(r, 'Avatar uploaded') self.assertTemplateUsed(r, 'actor/templates/settings_photo.html') self.assertTemplateUsed(r, 'common/templates/flash.html')
def test_settings_upload_avatar(self): nick = 'obligated' self.login(nick) nick = clean.nick(nick) old_contact_avatars = api.actor_get_contacts_avatars_since(api.ROOT, nick) contacts = api.actor_get_contacts(api.ROOT, nick) self.assertEquals(len(old_contact_avatars), len(contacts) + 1) old_avatar = api.actor_get(api.ROOT, nick).extra.get('icon', 'avatar_default') start_time = api.utcnow() no_contact_avatars = api.actor_get_contacts_avatars_since(api.ROOT, nick, since_time=start_time) self.assertEquals(len(no_contact_avatars), 0) # TODO(teemu): add more tests for different file types (gif and jpg). # Alternatively, test those against api.avatar_upload. f = open('testdata/test_avatar.jpg') r = self.client.post('/user/obligated/settings/photo', { 'imgfile': f, '_nonce' : util.create_nonce('obligated', 'change_photo'), }) r = self.assertRedirectsPrefix(r, '/user/obligated/settings/photo') actor_ref = api.actor_get(api.ROOT, nick) new_avatar = actor_ref.extra.get('icon', 'avatar_default') self.assertNotEquals(old_avatar, new_avatar) self.assertTrue(actor_ref.avatar_updated_at >= start_time) new_contact_avatars = api.actor_get_contacts_avatars_since(api.ROOT, nick, since_time=start_time) self.assertEquals(len(new_contact_avatars), 1) self.assertEquals(new_contact_avatars.pop().nick, nick) self.assertContains(r, 'Avatar uploaded') self.assertTemplateUsed(r, 'actor/templates/settings_photo.html') self.assertTemplateUsed(r, 'common/templates/flash.html')
def test_photo_upload(self): nick = 'popular' nick = clean.nick(nick) old_avatar = api.actor_get(api.ROOT, nick).extra.get('icon', 'avatar_default') self.login(nick) f = open('testdata/test_avatar.jpg') r = self.client.post('/welcome/1', { 'imgfile': f, '_nonce' : util.create_nonce('popular', 'change_photo'), }) r = self.assertRedirectsPrefix(r, '/welcome/1?') new_avatar = api.actor_get(api.ROOT, nick).extra.get('icon', 'avatar_default') self.assertNotEquals(old_avatar, new_avatar) self.assertContains(r, 'Avatar uploaded') self.assertTemplateUsed(r, 'join/templates/welcome_photo.html') self.assertTemplateUsed(r, 'common/templates/flash.html')
def test_settings_change_avatar(self): nick = 'obligated' self.login(nick) nick = clean.nick(nick) old_avatar = api.actor_get(api.ROOT, nick).extra.get('icon', 'avatar_default') # TODO(teemu): add more tests for different file types (gif and jpg). # Alternatively, test those against api.avatar_upload. r = self.client.post( '/user/obligated/settings/photo', { 'avatar': 'default/animal_9', '_nonce': util.create_nonce('obligated', 'change_photo'), }) r = self.assertRedirectsPrefix(r, '/user/obligated/settings/photo') new_avatar = api.actor_get(api.ROOT, nick).extra.get('icon', 'avatar_default') self.assertNotEquals(old_avatar, new_avatar) self.assertContains(r, 'Avatar changed') self.assertTemplateUsed(r, 'actor/templates/settings_photo.html') self.assertTemplateUsed(r, 'common/templates/flash.html')
def actor_overview(request, nick, format='html'): nick = clean.nick(nick) view = api.actor_lookup_nick(request.user, nick) if not view: raise exception.UserDoesNotExistError(nick, request.user) if not request.user or view.nick != request.user.nick: # Instead of displaying the overview, redirect to the public-facing page return http.HttpResponseRedirect(view.url()) handled = common_views.handle_view_action( request, { 'entry_remove': request.path, 'entry_remove_comment': request.path, 'entry_mark_as_spam': request.path, 'presence_set': request.path, 'settings_hide_comments': request.path, 'post': request.path, }) if handled: return handled per_page = ENTRIES_PER_PAGE offset, prev = util.page_offset(request) inbox = api.inbox_get_actor_overview(request.user, view.nick, limit=(per_page + 1), offset=offset) # START inbox generation chaos # TODO(termie): refacccttttooorrrrr entries = api.entry_get_entries(request.user, inbox) if view.extra.get('comments_hide', 0): # TODO(tyler): This is certainly not the most eloquent way to filter # through entries to remove comments. entries = [x for x in entries if not x.stream.endswith('comments')] per_page = per_page - (len(inbox) - len(entries)) entries, more = util.page_entries(request, entries, per_page) stream_keys = [e.stream for e in entries] actor_streams = api.stream_get_actor(request.user, view.nick) stream_keys += [s.key().name() for s in actor_streams] streams = api.stream_get_streams(request.user, stream_keys) contact_nicks = api.actor_get_contacts(request.user, view.nick, limit=CONTACTS_PER_PAGE) actor_nicks = (contact_nicks + [view.nick] + [s.owner for s in streams.values()] + [e.owner for e in entries] + [e.actor for e in entries]) actors = api.actor_get_actors(request.user, actor_nicks) # here comes lots of munging data into shape # clear deleted contacts contacts = [actors[x] for x in contact_nicks if actors[x]] streams = display.prep_stream_dict(streams, actors) entries = display.prep_entry_list(entries, streams, actors) # END inbox generation chaos # Check for unconfirmed emails unconfirmeds = api.activation_get_actor_email(request.user, view.nick) if unconfirmeds: unconfirmed_email = unconfirmeds[0].content # If not logged in, cannot write is_owner = False try: is_owner = view.nick == request.user.nick except: pass presence = api.presence_get(request.user, view.nick) # for sidebar streams view_streams = dict([(x.key().name(), streams[x.key().name()]) for x in actor_streams]) # for sidebar_contacts contacts_count = view.extra.get('contact_count', 0) contacts_more = contacts_count > CONTACTS_PER_PAGE # Config for the template green_top = True sidebar_green_top = True selectable_icons = display.SELECTABLE_ICONS area = 'home' # TODO(tyler/termie): This conflicts with the global settings import. # Also, this seems fishy. Do none of the settings.* items work in templates? import settings c = template.RequestContext(request, locals()) if format == 'html': t = loader.get_template('actor/templates/overview.html') return http.HttpResponse(t.render(c)) elif format == 'json': t = loader.get_template('actor/templates/overview.json') r = util.HttpJsonResponse(t.render(c), request) return r elif format == 'atom': t = loader.get_template('actor/templates/overview.atom') r = util.HttpAtomResponse(t.render(c), request) return r elif format == 'rss': t = loader.get_template('actor/templates/overview.rss') r = util.HttpRssResponse(t.render(c), request) return r
def actor_overview(request, nick, format='html'): nick = clean.nick(nick) view = api.actor_lookup_nick(request.user, nick) if not view: raise exception.UserDoesNotExistError(nick, request.user) if not request.user or view.nick != request.user.nick: # Instead of displaying the overview, redirect to the public-facing page return http.HttpResponseRedirect(view.url()) handled = common_views.handle_view_action( request, { 'entry_remove': request.path, 'entry_remove_comment': request.path, 'entry_mark_as_spam': request.path, 'presence_set': request.path, 'settings_hide_comments': request.path, 'post': request.path, }) if handled: return handled per_page = ENTRIES_PER_PAGE offset, prev = util.page_offset(request) inbox = api.inbox_get_actor_overview(request.user, view.nick, limit=(per_page + 1), offset=offset) actor_streams = api.stream_get_actor(request.user, view.nick) entries, more = _get_inbox_entries(request, inbox, view.extra.get('comments_hide', 0)) contacts, channels, streams, entries = _assemble_inbox_data( request, entries, actor_streams, view) # Check for unconfirmed emails unconfirmeds = api.activation_get_actor_email(request.user, view.nick) if unconfirmeds: unconfirmed_email = unconfirmeds[0].content # If not logged in, cannot write is_owner = False try: is_owner = view.nick == request.user.nick except: pass presence = api.presence_get(request.user, view.nick) # for sidebar streams view_streams = _get_sidebar_streams(actor_streams, streams) # for sidebar_contacts contacts_count = view.extra.get('contact_count', 0) contacts_more = contacts_count > CONTACTS_PER_PAGE # for sidebar channels channels_count = view.extra.get('channel_count', 0) channels_more = channels_count > CHANNELS_PER_PAGE # Config for the template green_top = True sidebar_green_top = True selectable_icons = display.SELECTABLE_ICONS area = 'home' # TODO(tyler/termie): This conflicts with the global settings import. # Also, this seems fishy. Do none of the settings.* items work in templates? import settings c = template.RequestContext(request, locals()) if format == 'html': t = loader.get_template('actor/templates/overview.html') return http.HttpResponse(t.render(c)) elif format == 'json': t = loader.get_template('actor/templates/overview.json') return util.HttpJsonResponse(t.render(c), request) elif format == 'atom': t = loader.get_template('actor/templates/overview.atom') return util.HttpAtomResponse(t.render(c), request) elif format == 'rss': t = loader.get_template('actor/templates/overview.rss') return util.HttpRssResponse(t.render(c), request)
def actor_settings(request, nick, page='index'): """ just a static page that links to the rest""" nick = clean.nick(nick) view = api.actor_lookup_nick(api.ROOT, nick) if not api.actor_owns_actor(request.user, view): raise exception.ApiOwnerRequired( 'Operation not allowed: %s does not own %s' % (request.user and request.user.nick or '(nobody)', view.nick)) handled = common_views.handle_view_action( request, { 'activation_activate_mobile': view.url('/settings/mobile'), 'activation_request_email': view.url('/settings/email'), 'activation_request_mobile': view.url('/settings/mobile'), 'settings_change_notify': view.url('/settings/notifications'), 'settings_change_privacy': request.path, 'settings_update_account': view.url('/settings/profile'), 'actor_remove': '/logout', #'oauth_remove_consumer': request.path, #'oauth_remove_access_token': request.path } ) if handled: return handled # TODO(tyler/termie): This conflicts with the global settings import. # Also, this seems fishy. Do none of the settings.* items work in templates? import settings # TODO(tyler): Merge this into handle_view_action, if possible if 'password' in request.POST: try: validate.nonce(request, 'change_password') password = request.POST.get('password', '') confirm = request.POST.get('confirm', '') validate.password_and_confirm(password, confirm, field = 'password') api.settings_change_password(request.user, view.nick, password) response = util.RedirectFlash(view.url() + '/settings/password', 'Password updated') request.user.password = util.hash_password(request.user.nick, password) # TODO(mikie): change when cookie-auth is changed user.set_user_cookie(response, request.user) return response except: exception.handle_exception(request) if page == 'feeds': try: if not settings.FEEDS_ENABLED: raise exception.DisabledFeatureError('Feeds are currently disabled') except: exception.handle_exception(request) if page == 'photo': redirect_to = view.url() + '/settings/photo' handled = common_views.common_photo_upload(request, redirect_to) if handled: return handled area = 'settings' full_page = page.capitalize() if page == 'mobile': full_page = 'Mobile Number' mobile = api.mobile_get_actor(request.user, view.nick) sms_notify = view.extra.get('sms_notify', False) elif page == 'im': full_page = 'IM Address' im_address = api.im_get_actor(request.user, view.nick) im_notify = view.extra.get('im_notify', False) elif page == 'index': email = api.email_get_actor(request.user, view.nick) email_notify = view.extra.get('email_notify', False) im_address = api.im_get_actor(request.user, view.nick) im_notify = view.extra.get('im_notify', False) elif page == 'feeds': full_page = 'Web Feeds' elif page == 'email': full_page = 'Email Address' email_notify = view.extra.get('email_notify', False) # check if we already have an email email = api.email_get_actor(request.user, view.nick) # otherwise look for an unconfirmed one if not email: unconfirmeds = api.activation_get_actor_email(api.ROOT, view.nick) if unconfirmeds: unconfirmed_email = unconfirmeds[0].content elif page == 'design': handled = common_views.common_design_update(request, view.nick) if handled: return handled full_page = 'Look and Feel' elif page == 'notifications': email = api.email_get_actor(request.user, view.nick) email_notify = view.extra.get('email_notify', False) im_address = api.im_get_actor(request.user, view.nick) im_notify = view.extra.get('im_notify', False) mobile = api.mobile_get_actor(request.user, request.user.nick) sms_notify = view.extra.get('sms_notify', False) sms_confirm = sms_notify and not view.extra.get('sms_confirmed', False) # TODO(termie): remove this once we can actually receive sms sms_confirm = False elif page == 'profile': # check if we already have an email email = api.email_get_actor(request.user, view.nick) # otherwise look for an unconfirmed one if not email: unconfirmeds = api.activation_get_actor_email(api.ROOT, view.nick) if unconfirmeds: unconfirmed_email = unconfirmeds[0].content elif page == 'photo': avatars = display.DEFAULT_AVATARS small_photos = api.image_get_all_keys(request.user, view.nick, size='f') # TODO(tyler): Fix this avatar nonsense! own_photos = [{ 'path' : small_photo.key().name(), 'name' : small_photo.key().name()[len('image/'):-len('_f.jpg')], } for small_photo in small_photos ] elif page == 'privacy': PRIVACY_PUBLIC = api.PRIVACY_PUBLIC PRIVACY_CONTACTS = api.PRIVACY_CONTACTS elif page == 'jsbadge': full_page = 'Javascript Badges' elif page == 'badge': badges = [{'id': 'badge-stream', 'width': '200', 'height': '300', 'src': '/themes/%s/badge.swf' % settings.DEFAULT_THEME, 'title': 'Stream', }, {'id': 'badge-map', 'width': '200', 'height': '255', 'src': '/themes/%s/badge-map.swf' % settings.DEFAULT_THEME, 'title': 'Map', }, {'id': 'badge-simple', 'width': '200', 'height': '200', 'src': '/themes/%s/badge-simple.swf' % settings.DEFAULT_THEME, 'title': 'Simple', }, ] elif page in ['password', 'delete']: # Catch for remaining pages before we generate a 404. pass else: return common_views.common_404(request) # rendering c = template.RequestContext(request, locals()) t = loader.get_template('actor/templates/settings_%s.html' % page) return http.HttpResponse(t.render(c))
def actor_history(request, nick=None, format='html'): nick = clean.nick(nick) view = api.actor_lookup_nick(request.user, nick) if not view: raise exception.UserDoesNotExistError(nick, request.user) called_subscribe, sub_ref = common_views.call_api_from_request( request, 'subscription_request') if called_subscribe: if sub_ref.state == 'subscribed': message = 'Subscribed.' else: message = 'Subscription requested.' return util.RedirectFlash(view.url(), message) handled = common_views.handle_view_action( request, { 'entry_remove': request.path, 'entry_remove_comment': request.path, 'entry_mark_as_spam': request.path, 'subscription_remove': view.url(), 'actor_add_contact': request.path, 'actor_remove_contact': request.path, 'post': request.path, 'presence_set': request.path, }) if handled: return handled privacy = 'public' if request.user: if view.nick == request.user.nick: privacy = 'private' # ROOT because we care whether or not request.user is a contact of # the view user's, not whether the request.user can see the contacts elif api.actor_has_contact(api.ROOT, view.nick, request.user.nick): privacy = 'contacts' # we're going to hide a bunch of stuff if this user is private and we # aren't allowed to see user_is_private = False if view.privacy < models.PRIVACY_PUBLIC and privacy == 'public': user_is_private = True per_page = ENTRIES_PER_PAGE offset, prev = util.page_offset(request) if privacy == 'public': if user_is_private: inbox = [] else: inbox = api.inbox_get_actor_public(request.user, view.nick, limit=(per_page + 1), offset=offset) elif privacy == 'contacts': inbox = api.inbox_get_actor_contacts(request.user, view.nick, limit=(per_page + 1), offset=offset) elif privacy == 'private': inbox = api.inbox_get_actor_private(request.user, view.nick, limit=(per_page + 1), offset=offset) # START inbox generation chaos # TODO(termie): refacccttttooorrrrr entries = api.entry_get_entries(request.user, inbox) per_page = per_page - (len(inbox) - len(entries)) entries, more = util.page_entries(request, entries, per_page) stream_keys = [e.stream for e in entries] try: actor_streams = api.stream_get_actor(request.user, view.nick) except exception.ApiException: actor_streams = [] stream_keys += [s.key().name() for s in actor_streams] streams = api.stream_get_streams(request.user, stream_keys) try: contact_nicks = api.actor_get_contacts(request.user, view.nick, limit=CONTACTS_PER_PAGE) except exception.ApiException: contact_nicks = [] actor_nicks = (contact_nicks + [view.nick] + [s.owner for s in streams.values()] + [e.owner for e in entries] + [e.actor for e in entries]) actors = api.actor_get_actors(request.user, actor_nicks) # here comes lots of munging data into shape contacts = [actors[x] for x in contact_nicks if actors[x]] streams = display.prep_stream_dict(streams, actors) entries = display.prep_entry_list(entries, streams, actors) # END inbox generation chaos # If not logged in, cannot write is_owner = request.user and view.nick == request.user.nick try: presence = api.presence_get(request.user, view.nick) presence_stream = api.stream_get_presence(request.user, view.nick) last_entry = api.entry_get_last(request.user, presence_stream.keyname()) view.last_entry = last_entry except exception.ApiException: pass # for add/remove contact if request.user: user_is_contact = api.actor_has_contact(request.user, request.user.nick, view.nick) view.my_contact = user_is_contact else: user_is_contact = False # for sidebar streams view_streams = dict([(x.key().name(), streams[x.key().name()]) for x in actor_streams]) if request.user: # un/subscribe buttons are possible only, when logged in # TODO(termie): what if there are quite a lot of streams? for stream in view_streams.values(): stream.subscribed = api.subscription_exists( request.user, stream.key().name(), 'inbox/%s/overview' % request.user.nick) # for sidebar_contacts contacts_count = view.extra.get('contact_count', 0) contacts_more = contacts_count > CONTACTS_PER_PAGE # Config for the template green_top = True sidebar_green_top = True selectable_icons = display.SELECTABLE_ICONS area = 'user' c = template.RequestContext(request, locals()) if format == 'html': t = loader.get_template('actor/templates/history.html') return http.HttpResponse(t.render(c)) elif format == 'json': t = loader.get_template('actor/templates/history.json') r = util.HttpJsonResponse(t.render(c), request) return r elif format == 'atom': t = loader.get_template('actor/templates/history.atom') r = util.HttpAtomResponse(t.render(c), request) return r elif format == 'rss': t = loader.get_template('actor/templates/history.rss') r = util.HttpRssResponse(t.render(c), request) return r
def actor_contacts(request, nick=None, format='html'): nick = clean.nick(nick) view = api.actor_lookup_nick(request.user, nick) if not view: raise exception.UserDoesNotExistError(nick, request.user) handled = common_views.handle_view_action( request, { 'actor_add_contact': request.path, 'actor_remove_contact': request.path, }) if handled: return handled per_page = CONTACTS_PER_PAGE offset, prev = util.page_offset_nick(request) contact_nicks = api.actor_get_contacts(request.user, view.nick, limit=(per_page + 1), offset=offset) actor_nicks = contact_nicks actors = api.actor_get_actors(request.user, actor_nicks) # clear deleted actors actors = dict([(k, v) for k, v in actors.iteritems() if v]) per_page = per_page - (len(contact_nicks) - len(actors)) # TODO(termie): incorporate this into paging so we only fetch the range # on this page # add some extra info so we can let the user do contextual actions # on these homeboys if request.user and request.user.nick == view.nick: # looking at self, find out who of these people follow me so # I can highlight them for actor in actors: if api.actor_is_follower(request.user, view.nick, actor): actors[actor].my_follower = True actors[actor].my_contact = True actors[actor].rel = 'contact' whose = 'Your' elif request.user: my_contacts_nicks = api.actor_get_contacts(request.user, request.user.nick) for f in my_contacts_nicks: try: actors[f].my_contact = True except: pass for x in actors: actors[x].rel = 'contact' whose = "%s's" % view.display_nick() # here comes lots of munging data into shape actor_tiles = [actors[x] for x in contact_nicks if x in actors] actor_tiles_count = view.extra.get('contact_count', 0) actor_tiles, actor_tiles_more = util.page_actors(request, actor_tiles, per_page) area = 'people' c = template.RequestContext(request, locals()) if format == 'html': t = loader.get_template('actor/templates/contacts.html') return http.HttpResponse(t.render(c)) elif format == 'json': t = loader.get_template('actor/templates/contacts.json') r = http.HttpResponse(t.render(c)) r['Content-type'] = 'text/javascript' return r
def sign_in(self, nick, sender=None): password = self.passwords[clean.nick(nick)] r = self.receive('SIGN IN %s %s' % (nick, password), sender=sender) return r
def login(self, nick, password=None): if not password: password = self.passwords[clean.nick(nick)] r = self.client.post('/login', {'log': nick, 'pwd': password}) return
def actor_item(request, nick=None, item=None, format='html'): # The nick passed in the url looks ugly with the escaped @ in it and is # generally just shorter if we only use the lead part of the nick # however the entire system expects full nicks so we should expand this # as soon as possible nick = clean.nick(nick) # Most pages have the concept of a viewer and an actor being viewed, # in all cases the viewer is `request.user` and the actor being viewed # should be named `view` view = api.actor_lookup_nick(request.user, nick) if not view: raise exception.UserDoesNotExistError(nick, request.user) # With very few exceptions, whenever we are referring to a an # instance that is an entity from the datastore we append `_ref` # to the variable name to distinguish it from the variable that # is simply a string identifier. # In the code below `stream_ref` and `entry_ref` are both entity # references, while `entry` is simply the string key_name of an entry stream_ref = api.stream_get_presence(request.user, view.nick) if not stream_ref: raise http.Http404() if item == 'last': entry_ref = api.entry_get_last(request.user, stream_ref.keyname()) return http.HttpResponseRedirect(entry_ref.url()) else: entry = '%s/%s' % (stream_ref.key().name(), item) entry_ref = api.entry_get_safe(request.user, entry) # Most api calls will return None if the entity being looked up does # not exist so we usually want to verify the return values if not entry_ref: raise http.Http404() # When handling user actions the following pattern more or less applies # if 'parameter_unique_to_action' in request.(POST|GET|REQUEST): # try: # validate.nonce(request, 'nonce_action') # validate.anything_else_that_is_related_to_ui_rather_than_call() # # local_variable = request.(POST|GET|REQUEST).get('request_arg') # # or # params = util.query_dict_to_keywords(request.(POST|GET|REQUEST)) # # # Our goal is to have most of the logic for any action translate # # directly into an api call on behalf of the requesting user # # such that the api call is responsible for validating all input # # and raising any applicable errors # result = api.some_api_method(request.user, # method_variable=local_variable, # ...) # # or # result = api.some_api_method(request.user, **params) # # # All actions should issue a redirect with a success message # return util.RedirectFlash('some_url', 'some success message') # except: # exception.handle_exception(request) # # When an exception occurs we expect the rest of the page to be able # to be processed normally as if no action had been taken, the error # handling section of the template should display the errors caught # by the exception.handle_exception() call handled = common_views.handle_view_action( request, {'entry_add_comment': entry_ref.url(request=request), 'entry_remove': view.url(request=request), 'entry_remove_comment': entry_ref.url(request=request), 'entry_mark_as_spam': entry_ref.url(request=request) } ) if handled: return handled comments = api.entry_get_comments(request.user, entry_ref.key().name()) # To minimize the number of lookups to the datastore once we know # all the data we will be displaying on a page we attempt to make # a list of all the actors associated with that data so that we can # fetch them all at once actor_nicks = [entry_ref.owner, entry_ref.actor] + [c.actor for c in comments] actors = api.actor_get_actors(request.user, actor_nicks) # Creates a copy of actors with lowercase keys (Django #6904: template filter # dictsort sorts case sensitive), excluding the currently logged in user. participants = {} for k, v in actors.iteritems(): if (v and not (hasattr(request.user, 'nick') and request.user.nick == v.nick)): participants[k.lower()] = v # Due to restrictions on Django's templating language most of the time # we will have to take an additional step of preparing all of our data # for display, this usually translates to attaching references to # actor or stream entities. # Functions that handle this preparation should be added to the # common.display module entry = display.prep_entry(entry_ref, {stream_ref.key().name(): stream_ref}, actors) comments = display.prep_comment_list(comments, actors) # Additionally, to minimize more logic in the templates some variables # can be defined to configure the output, these are usually template specific # though some are common variables for anything that inherits from the # base templates green_top = True sidebar_green_top = True # The quickest way to make sure we are getting all of the things we care # about passed to the template without the temptation of making last minute # changes is just to pass `locals()` to the template context c = template.RequestContext(request, locals()) # Ideally this is all that should be necessary to add additional output # formats, in practice it is yet to be seen whether additional data # preparation will be necessary before outputting in JSON or ATOM formats if format == 'html': # We always use the full path to the template to prevent naming conflicts # and difficult searches. t = loader.get_template('actor/templates/item.html') return http.HttpResponse(t.render(c)) elif format == 'json': t = loader.get_template('actor/templates/item.json') return util.HttpJsonResponse(t.render(c), request)
def test_sign_in(self): nick = 'popular' password = self.passwords[clean.nick(nick)] r = self.receive('SIGN IN %s %s' % (nick, password)) self.assertOutboxContains(r, 'Welcome to %s SMS %s' % (util.get_metadata('SITE_NAME'), nick))
def login(self, nick, password=None): if not password: password = self.passwords[clean.nick(nick)] r = self.client.post("/login", {"log": nick, "pwd": password}) return
def actor_item(request, nick=None, item=None, format='html'): # The nick passed in the url looks ugly with the escaped @ in it and is # generally just shorter if we only use the lead part of the nick # however the entire system expects full nicks so we should expand this # as soon as possible nick = clean.nick(nick) # Most pages have the concept of a viewer and an actor being viewed, # in all cases the viewer is `request.user` and the actor being viewed # should be named `view` view = api.actor_lookup_nick(request.user, nick) if not view: raise exception.UserDoesNotExistError(nick, request.user) # With very few exceptions, whenever we are referring to a an # instance that is an entity from the datastore we append `_ref` # to the variable name to distinguish it from the variable that # is simply a string identifier. # In the code below `stream_ref` and `entry_ref` are both entity # references, while `entry` is simply the string key_name of an entry stream_ref = api.stream_get_presence(request.user, view.nick) if not stream_ref: raise http.Http404() if item == 'last': entry_ref = api.entry_get_last(request.user, stream_ref.keyname()) return http.HttpResponseRedirect(entry_ref.url()) else: entry = '%s/%s' % (stream_ref.key().name(), item) entry_ref = api.entry_get_safe(request.user, entry) # Most api calls will return None if the entity being looked up does # not exist so we usually want to verify the return values if not entry_ref: raise http.Http404() # When handling user actions the following pattern more or less applies # if 'parameter_unique_to_action' in request.(POST|GET|REQUEST): # try: # validate.nonce(request, 'nonce_action') # validate.anything_else_that_is_related_to_ui_rather_than_call() # # local_variable = request.(POST|GET|REQUEST).get('request_arg') # # or # params = util.query_dict_to_keywords(request.(POST|GET|REQUEST)) # # # Our goal is to have most of the logic for any action translate # # directly into an api call on behalf of the requesting user # # such that the api call is responsible for validating all input # # and raising any applicable errors # result = api.some_api_method(request.user, # method_variable=local_variable, # ...) # # or # result = api.some_api_method(request.user, **params) # # # All actions should issue a redirect with a success message # return util.RedirectFlash('some_url', 'some success message') # except: # exception.handle_exception(request) # # When an exception occurs we expect the rest of the page to be able # to be processed normally as if no action had been taken, the error # handling section of the template should display the errors caught # by the exception.handle_exception() call handled = common_views.handle_view_action( request, { 'entry_add_comment': entry_ref.url(request=request), 'entry_remove': view.url(request=request), 'entry_remove_comment': entry_ref.url(request=request), 'entry_mark_as_spam': entry_ref.url(request=request) }) if handled: return handled comments = api.entry_get_comments(request.user, entry_ref.key().name()) # To minimize the number of lookups to the datastore once we know # all the data we will be displaying on a page we attempt to make # a list of all the actors associated with that data so that we can # fetch them all at once actor_nicks = [entry_ref.owner, entry_ref.actor ] + [c.actor for c in comments] actors = api.actor_get_actors(request.user, actor_nicks) # Creates a copy of actors with lowercase keys (Django #6904: template filter # dictsort sorts case sensitive), excluding the currently logged in user. participants = {} for k, v in actors.iteritems(): if (v and not (hasattr(request.user, 'nick') and request.user.nick == v.nick)): participants[k.lower()] = v # Due to restrictions on Django's templating language most of the time # we will have to take an additional step of preparing all of our data # for display, this usually translates to attaching references to # actor or stream entities. # Functions that handle this preparation should be added to the # common.display module entry = display.prep_entry(entry_ref, {stream_ref.key().name(): stream_ref}, actors) comments = display.prep_comment_list(comments, actors) # Additionally, to minimize more logic in the templates some variables # can be defined to configure the output, these are usually template specific # though some are common variables for anything that inherits from the # base templates green_top = True sidebar_green_top = True # The quickest way to make sure we are getting all of the things we care # about passed to the template without the temptation of making last minute # changes is just to pass `locals()` to the template context c = template.RequestContext(request, locals()) # Ideally this is all that should be necessary to add additional output # formats, in practice it is yet to be seen whether additional data # preparation will be necessary before outputting in JSON or ATOM formats if format == 'html': # We always use the full path to the template to prevent naming conflicts # and difficult searches. t = loader.get_template('actor/templates/item.html') return http.HttpResponse(t.render(c)) elif format == 'json': t = loader.get_template('actor/templates/item.json') return util.HttpJsonResponse(t.render(c), request)
def actor_history(request, nick=None, format='html'): nick = clean.nick(nick) view = api.actor_lookup_nick(request.user, nick) if not view: raise exception.UserDoesNotExistError(nick, request.user) called_subscribe, sub_ref = common_views.call_api_from_request( request, 'subscription_request') if called_subscribe: if sub_ref.state == 'subscribed': message = 'Subscribed.' else: message = 'Subscription requested.' return util.RedirectFlash(view.url(), message) handled = common_views.handle_view_action( request, { 'entry_remove': request.path, 'entry_remove_comment': request.path, 'entry_mark_as_spam': request.path, 'subscription_remove': view.url(), 'actor_add_contact': request.path, 'actor_remove_contact': request.path, 'post': request.path, 'presence_set': request.path, }) if handled: return handled privacy = 'public' if request.user: if view.nick == request.user.nick: privacy = 'private' # ROOT because we care whether or not request.user is a contact of # the view user's, not whether the request.user can see the contacts elif api.actor_has_contact(api.ROOT, view.nick, request.user.nick): privacy = 'contacts' # we're going to hide a bunch of stuff if this user is private and we # aren't allowed to see user_is_private = False if view.privacy < models.PRIVACY_PUBLIC and privacy == 'public': user_is_private = True per_page = ENTRIES_PER_PAGE offset, prev = util.page_offset(request) if privacy == 'public': if user_is_private: inbox = [] else: inbox = api.inbox_get_actor_public(request.user, view.nick, limit=(per_page + 1), offset=offset) elif privacy == 'contacts': inbox = api.inbox_get_actor_contacts(request.user, view.nick, limit=(per_page + 1), offset=offset) elif privacy == 'private': inbox = api.inbox_get_actor_private(request.user, view.nick, limit=(per_page + 1), offset=offset) actor_streams = api.stream_get_actor_safe(request.user, view.nick) entries, more = _get_inbox_entries(request, inbox) contacts, channels, streams, entries = _assemble_inbox_data( request, entries, actor_streams, view) # If not logged in, cannot write is_owner = request.user and view.nick == request.user.nick try: presence = api.presence_get(request.user, view.nick) presence_stream = api.stream_get_presence(request.user, view.nick) last_entry = api.entry_get_last(request.user, presence_stream.keyname()) view.last_entry = last_entry except exception.ApiException: pass # for add/remove contact if request.user: user_is_contact = api.actor_has_contact(request.user, request.user.nick, view.nick) view.my_contact = user_is_contact else: user_is_contact = False # for sidebar streams view_streams = _get_sidebar_streams(actor_streams, streams, request.user) # for sidebar_contacts contacts_count = view.extra.get('contact_count', 0) contacts_more = contacts_count > CONTACTS_PER_PAGE # for sidebar channels channels_count = view.extra.get('channel_count', 0) channels_more = channels_count > CHANNELS_PER_PAGE # Config for the template green_top = True sidebar_green_top = True selectable_icons = display.SELECTABLE_ICONS area = 'user' c = template.RequestContext(request, locals()) if format == 'html': t = loader.get_template('actor/templates/history.html') return http.HttpResponse(t.render(c)) elif format == 'json': t = loader.get_template('actor/templates/history.json') return util.HttpJsonResponse(t.render(c), request) elif format == 'atom': t = loader.get_template('actor/templates/history.atom') return util.HttpAtomResponse(t.render(c), request) elif format == 'rss': t = loader.get_template('actor/templates/history.rss') return util.HttpRssResponse(t.render(c), request)
def actor_settings(request, nick, page='index'): """ just a static page that links to the rest""" nick = clean.nick(nick) view = api.actor_lookup_nick(api.ROOT, nick) if not api.actor_owns_actor(request.user, view): raise exception.ApiOwnerRequired( 'Operation not allowed: %s does not own %s' % (request.user and request.user.nick or '(nobody)', view.nick)) handled = common_views.handle_view_action( request, { 'activation_activate_mobile': view.url('/settings/mobile'), 'activation_request_email': view.url('/settings/email'), 'activation_request_mobile': view.url('/settings/mobile'), 'settings_change_notify': view.url('/settings/notifications'), 'settings_change_privacy': request.path, 'settings_update_account': view.url('/settings/profile'), 'actor_remove': '/logout', #'oauth_remove_consumer': request.path, #'oauth_remove_access_token': request.path }) if handled: return handled # TODO(tyler/termie): This conflicts with the global settings import. # Also, this seems fishy. Do none of the settings.* items work in templates? import settings # TODO(tyler): Merge this into handle_view_action, if possible if 'password' in request.POST: try: validate.nonce(request, 'change_password') password = request.POST.get('password', '') confirm = request.POST.get('confirm', '') validate.password_and_confirm(password, confirm, field='password') api.settings_change_password(request.user, view.nick, password) response = util.RedirectFlash(view.url() + '/settings/password', 'Password updated') request.user.password = util.hash_password(request.user.nick, password) # TODO(mikie): change when cookie-auth is changed user.set_user_cookie(response, request.user) return response except: exception.handle_exception(request) if page == 'feeds': try: if not settings.FEEDS_ENABLED: raise exception.DisabledFeatureError( 'Feeds are currently disabled') except: exception.handle_exception(request) if page == 'photo': redirect_to = view.url() + '/settings/photo' handled = common_views.common_photo_upload(request, redirect_to) if handled: return handled area = 'settings' full_page = page.capitalize() if page == 'mobile': full_page = 'Mobile Number' mobile = api.mobile_get_actor(request.user, view.nick) sms_notify = view.extra.get('sms_notify', False) elif page == 'im': full_page = 'IM Address' im_address = api.im_get_actor(request.user, view.nick) im_notify = view.extra.get('im_notify', False) elif page == 'index': email = api.email_get_actor(request.user, view.nick) email_notify = view.extra.get('email_notify', False) im_address = api.im_get_actor(request.user, view.nick) im_notify = view.extra.get('im_notify', False) elif page == 'feeds': full_page = 'Web Feeds' elif page == 'email': full_page = 'Email Address' email_notify = view.extra.get('email_notify', False) # check if we already have an email email = api.email_get_actor(request.user, view.nick) # otherwise look for an unconfirmed one if not email: unconfirmeds = api.activation_get_actor_email(api.ROOT, view.nick) if unconfirmeds: unconfirmed_email = unconfirmeds[0].content elif page == 'design': handled = common_views.common_design_update(request, view.nick) if handled: return handled full_page = 'Look and Feel' elif page == 'notifications': email = api.email_get_actor(request.user, view.nick) email_notify = view.extra.get('email_notify', False) im_address = api.im_get_actor(request.user, view.nick) im_notify = view.extra.get('im_notify', False) mobile = api.mobile_get_actor(request.user, request.user.nick) sms_notify = view.extra.get('sms_notify', False) sms_confirm = sms_notify and not view.extra.get('sms_confirmed', False) # TODO(termie): remove this once we can actually receive sms sms_confirm = False elif page == 'profile': # check if we already have an email email = api.email_get_actor(request.user, view.nick) # otherwise look for an unconfirmed one if not email: unconfirmeds = api.activation_get_actor_email(api.ROOT, view.nick) if unconfirmeds: unconfirmed_email = unconfirmeds[0].content elif page == 'photo': avatars = display.DEFAULT_AVATARS small_photos = api.image_get_all_keys(request.user, view.nick, size='f') # TODO(tyler): Fix this avatar nonsense! own_photos = [{ 'path': small_photo.key().name(), 'name': small_photo.key().name()[len('image/'):-len('_f.jpg')], } for small_photo in small_photos] elif page == 'privacy': PRIVACY_PUBLIC = api.PRIVACY_PUBLIC PRIVACY_CONTACTS = api.PRIVACY_CONTACTS elif page in ['password', 'delete']: # Catch for remaining pages before we generate a 404. pass else: return common_views.common_404(request) # rendering c = template.RequestContext(request, locals()) t = loader.get_template('actor/templates/settings_%s.html' % page) return http.HttpResponse(t.render(c))
def sign_in(self, from_jid, nick, password=None): if not password: password = self.passwords[clean.nick(nick)] message = 'SIGN IN %s %s' % (nick, password) return self.send(from_jid, message)
def actor_history(request, nick=None, format='html'): nick = clean.nick(nick) view = api.actor_lookup_nick(request.user, nick) if not view: raise exception.UserDoesNotExistError(nick, request.user) called_subscribe, sub_ref = common_views.call_api_from_request( request, 'subscription_request') if called_subscribe: if sub_ref.state == 'subscribed': message = 'Subscribed.' else: message = 'Subscription requested.' return util.RedirectFlash(view.url(), message) handled = common_views.handle_view_action( request, { 'entry_remove': request.path, 'entry_remove_comment': request.path, 'entry_mark_as_spam': request.path, 'subscription_remove': view.url(), 'actor_add_contact': request.path, 'actor_remove_contact': request.path, 'post': request.path, 'presence_set': request.path, } ) if handled: return handled privacy = 'public' if request.user: if view.nick == request.user.nick: privacy = 'private' # ROOT because we care whether or not request.user is a contact of # the view user's, not whether the request.user can see the contacts elif api.actor_has_contact(api.ROOT, view.nick, request.user.nick): privacy = 'contacts' # we're going to hide a bunch of stuff if this user is private and we # aren't allowed to see user_is_private = False if view.privacy < models.PRIVACY_PUBLIC and privacy == 'public': user_is_private = True per_page = ENTRIES_PER_PAGE offset, prev = util.page_offset(request) if privacy == 'public': if user_is_private: inbox = [] else: inbox = api.inbox_get_actor_public(request.user, view.nick, limit=(per_page + 1), offset=offset) elif privacy == 'contacts': inbox = api.inbox_get_actor_contacts(request.user, view.nick, limit=(per_page + 1), offset=offset) elif privacy == 'private': inbox = api.inbox_get_actor_private(request.user, view.nick, limit=(per_page + 1), offset=offset) actor_streams = api.stream_get_actor_safe(request.user, view.nick) entries, more = _get_inbox_entries(request, inbox) contacts, channels, streams, entries = _assemble_inbox_data(request, entries, actor_streams, view) # If not logged in, cannot write is_owner = request.user and view.nick == request.user.nick try: presence = api.presence_get(request.user, view.nick) presence_stream = api.stream_get_presence(request.user, view.nick) last_entry = api.entry_get_last(request.user, presence_stream.keyname()) view.last_entry = last_entry except exception.ApiException: pass # for add/remove contact if request.user: user_is_contact = api.actor_has_contact(request.user, request.user.nick, view.nick) view.my_contact = user_is_contact else: user_is_contact = False # for sidebar streams view_streams = _get_sidebar_streams(actor_streams, streams, request.user) # for sidebar_contacts contacts_count = view.extra.get('contact_count', 0) contacts_more = contacts_count > CONTACTS_PER_PAGE # for sidebar channels channels_count = view.extra.get('channel_count', 0) channels_more = channels_count > CHANNELS_PER_PAGE # Config for the template green_top = True sidebar_green_top = True selectable_icons = display.SELECTABLE_ICONS area = 'user' c = template.RequestContext(request, locals()) if format == 'html': t = loader.get_template('actor/templates/history.html') return http.HttpResponse(t.render(c)) elif format == 'json': t = loader.get_template('actor/templates/history.json') return util.HttpJsonResponse(t.render(c), request) elif format == 'atom': t = loader.get_template('actor/templates/history.atom') return util.HttpAtomResponse(t.render(c), request) elif format == 'rss': t = loader.get_template('actor/templates/history.rss') return util.HttpRssResponse(t.render(c), request)
def actor_overview(request, nick, format='html'): nick = clean.nick(nick) view = api.actor_lookup_nick(request.user, nick) if not view: raise exception.UserDoesNotExistError(nick, request.user) if not request.user or view.nick != request.user.nick: # Instead of displaying the overview, redirect to the public-facing page return http.HttpResponseRedirect(view.url()) handled = common_views.handle_view_action( request, { 'entry_remove': request.path, 'entry_remove_comment': request.path, 'entry_mark_as_spam': request.path, 'presence_set': request.path, 'settings_hide_comments': request.path, 'post': request.path, } ) if handled: return handled per_page = ENTRIES_PER_PAGE offset, prev = util.page_offset(request) inbox = api.inbox_get_actor_overview(request.user, view.nick, limit=(per_page + 1), offset=offset) actor_streams = api.stream_get_actor(request.user, view.nick) entries, more = _get_inbox_entries(request, inbox, view.extra.get('comments_hide', 0)) contacts, channels, streams, entries = _assemble_inbox_data(request, entries, actor_streams, view) # Check for unconfirmed emails unconfirmeds = api.activation_get_actor_email(request.user, view.nick) if unconfirmeds: unconfirmed_email = unconfirmeds[0].content # If not logged in, cannot write is_owner = False try: is_owner = view.nick == request.user.nick except: pass presence = api.presence_get(request.user, view.nick) # for sidebar streams view_streams = _get_sidebar_streams(actor_streams, streams) # for sidebar_contacts contacts_count = view.extra.get('contact_count', 0) contacts_more = contacts_count > CONTACTS_PER_PAGE # for sidebar channels channels_count = view.extra.get('channel_count', 0) channels_more = channels_count > CHANNELS_PER_PAGE # Config for the template green_top = True sidebar_green_top = True selectable_icons = display.SELECTABLE_ICONS area = 'home' # TODO(tyler/termie): This conflicts with the global settings import. # Also, this seems fishy. Do none of the settings.* items work in templates? import settings c = template.RequestContext(request, locals()) if format == 'html': t = loader.get_template('actor/templates/overview.html') return http.HttpResponse(t.render(c)) elif format == 'json': t = loader.get_template('actor/templates/overview.json') return util.HttpJsonResponse(t.render(c), request) elif format == 'atom': t = loader.get_template('actor/templates/overview.atom') return util.HttpAtomResponse(t.render(c), request) elif format == 'rss': t = loader.get_template('actor/templates/overview.rss') return util.HttpRssResponse(t.render(c), request)