def GET(self, world, prop):
        
        cur_world = world_exists(world)
        cur_prop = property_exists(prop)

        a = cur_world.get_access_string(self.page_user)
        menu = self.get_or_put_menu(cur_world, a)
        menu['properties'][0][2] = "active"

        param = web.input()
        if hasattr(param, 'r'): # In read-only mode
            section = render().section_property_read(cur_prop)
            return render().admin(cur_world, section, menu, "%s's %s on Palimpsest" % (cur_world.title, cur_prop.name))

        self.redirect_if_not_edit(cur_world, cur_prop)

        if cur_prop.valid_values == "|text|" or cur_prop.valid_values == "|num|":
            valid_vals = cur_prop.valid_values
        else:
            valid_vals = 0

        f = self.properties_form()
        f.fill(**{'name':cur_prop.name,'valid_values':valid_vals,'fixed_values':cur_prop.valid_values,'sorter':cur_prop.sorter,'info':cur_prop.info,'discrete':cur_prop.discrete})
        edit_form = CombinedForm([f], **self.formargs)
        del_form = CombinedForm([self.delete_form()], **self.formargs)

        section = render().section_property(edit_form, del_form, True)
        return render().admin(cur_world, section, menu, "%s's %s on Palimpsest" % (cur_world.title, cur_prop.name), pre=["/js/showhide_form_fields.js"])
 def POST(self):
     d = web.input()
     if d.reload:
         w = world_exists(d.world)
         a = w.get_access_string(self.page_user)
         self.set_menu(w, a)
     return web.seeother(d.refer)
    def POST(self, worldkey, savekey):
        world = world_exists(worldkey)
        save = save_exists(savekey)
        self.redirect_if_not_exists(world, "/yours/saves")
        self.redirect_if_not_exists(save, "/yours/saves")
        #self.can_access_world(world)
        self.can_edit_save(save)
        if not world.publish:
            raise web.notfound()

        i = web.input()
        key = int(i.key)

        room_ftr = Room.get_by_id_async(key)
        save_ftr = SavePath.get_by_id_async(int(savekey))
        room = room_ftr.get_result()
        thesave = save_ftr.get_result()
        new_texts = thesave.texts
        new_texts.append(room.key)
        thesave.texts = new_texts
        new_save_ftr = thesave.put_async()
        json = self.js_make_room_json(room)
        new_save_ftr.get_result()

        return json
Beispiel #4
0
    def POST(self, worldkey):
        world = world_exists(worldkey)
        self.can_access_world(world)

        i = web.input()

        trimmed = i.savename.strip()
        if trimmed == "" or trimmed is None:
            if hasattr(i, 'saveandgo'):
                return web.seeother("%s/go" % worldkey)
            elif hasattr(i, 'sofago'):
                return web.seeother("%s/go?s=1" % worldkey)
            else:
                return web.seeother("%s" % worldkey)

        savename = make_save_name(i.savename, self.page_user)
        new_save = SavePath(name=savename,
                            user=self.page_user.key,
                            publish=False)
        save_ftr = new_save.put_async()
        s = save_ftr.get_result()

        if hasattr(i, 'saveandgo'):
            return web.seeother("%s/save/%s" % (worldkey, s.integer_id()))
        elif hasattr(i, 'sofago'):
            return web.seeother("/%s/save/%s?s=1" % (worldkey, s.integer_id()))
    def GET(self, world, text):
        cur_world = world_exists(world)
        cur_text = text_exists(text)

        access = cur_world.get_access_string(self.page_user)
        world_menu = self.get_or_put_menu(cur_world, access)
        world_menu['texts'][0][2] = "active"

        param = web.input()
        if hasattr(param, 'r'): # In read-only mode
            world_properties = cur_world.get_properties_allowed(self.page_user).get_result()
            try:
                js = self.js_add_properties(world_properties, cur_world)
                properties_available = True
            except IndexError:
                properties_available = False
            property_values = cur_text.get_allowed_property_values(self.page_user).get_result()
            js += self.js_one_room_on_map(cur_text)
            section = render().section_texts_read(cur_text, cur_world.is_open, properties_available, property_values)
            return render().admin(cur_world, section, world_menu, "%s on Palimpsest" % cur_text.name, pre = ['http://maps.google.com/maps/api/js?sensor=false'], js=js, post=['/js/viewroomcoords.js', '/js/add_text_properties.js'])

        self.redirect_if_not_edit(cur_world, cur_text)

        form = self.text_form()
        form.fill(**{'name':cur_text.name, 'short_desc':cur_text.short_desc, 'long_desc':cur_text.long_desc})
        return self.reset_text_page(cur_world, form, access, world_menu, cur_text)
Beispiel #6
0
 def POST(self):
     d = web.input()
     if d.reload:
         w = world_exists(d.world)
         a = w.get_access_string(self.page_user)
         self.set_menu(w, a)
     return web.seeother(d.refer)
    def GET(self, worldkey, save):
        world = world_exists(worldkey)
        save = save_exists(save)
        self.redirect_if_not_exists(world, "/yours/saves")
        self.redirect_if_not_exists(save, "/yours/saves")
        #self.can_access_world(world)
        self.can_edit_save(save)
        if not world.publish:
            raise web.notfound()

        sofaUrl = "/%s/save/%s?s=1" % (world.key.id(), save.key.id())

        param = web.input()
        if hasattr(param, 's'): # In sofa mode
            post = ['/js/maps.google.polygon.containsLatLng.js', '/js/page_scroll.js', '/js/text_queue.js', '/js/room_expand.js','/js/sofa_location.js', '/js/toggle_info.js']
        else:
            post = ['/js/maps.google.polygon.containsLatLng.js', '/js/page_scroll.js', '/js/text_queue.js', '/js/room_expand.js','/js/get_location.js', '/js/toggle_info.js']
        
        js = self.js_coords_list(world, "/%s/save/%s" % (world.key.id(), save.key.id()), sofaUrl)

        return render().go(title="%s on Palimpsest" % world.title
                        ,navleft=[('Back to %s' % world.title,'/%s' % world.key.id())]
                        ,pre=['http://maps.google.com/maps/api/js?sensor=false', '/js/set_page_height.js']
                        ,js=js
                        ,post=post
                    )
Beispiel #8
0
    def POST(self, worldkey, savekey):
        world = world_exists(worldkey)
        save = save_exists(savekey)
        self.redirect_if_not_exists(world, "/yours/saves")
        self.redirect_if_not_exists(save, "/yours/saves")
        #self.can_access_world(world)
        self.can_edit_save(save)
        if not world.publish:
            raise web.notfound()

        i = web.input()
        key = int(i.key)

        room_ftr = Room.get_by_id_async(key)
        save_ftr = SavePath.get_by_id_async(int(savekey))
        room = room_ftr.get_result()
        thesave = save_ftr.get_result()
        new_texts = thesave.texts
        new_texts.append(room.key)
        thesave.texts = new_texts
        new_save_ftr = thesave.put_async()
        json = self.js_make_room_json(room)
        new_save_ftr.get_result()

        return json
Beispiel #9
0
    def POST(self, world):
        cur_world = world_exists(world)
        self.redirect_if_not_create(cur_world)

        f = self.properties_form()
        form = CombinedForm([f], **self.formargs)

        if not f.validates():
            access = cur_world.get_access_string(self.page_user)
            world_menu = self.get_or_put_menu(cur_world, access)
            section = render().section_properties(form)
            return render().admin(
                cur_world,
                section,
                world_menu,
                title="Add a new property to %s on Palimpsest" %
                cur_world.title,
                pre=["/js/showhide_form_fields.js"])
        else:

            access = cur_world.get_access_string(self.page_user)

            try:
                if int(f.d.valid_values) == 0:
                    valid_values = f.d.fixed_values
                else:
                    valid_values = f.d.valid_values
            except ValueError:
                valid_values = f.d.valid_values

            if f.d.discrete == "True":
                discrete = True
            else:
                discrete = False

            if cur_world.is_mod(self.page_user):
                visible = True
                """ Flush menus and available properties for everyone so they get reset"""
                # TODO: Fix this
                memcache.delete("%s-admin" % cur_world.key.id())
                memcache.delete("%s-closed" % cur_world.key.id())
            else:
                visible = False

            new_property = Property(name=f.d.name,
                                    sorter=f.d.sorter,
                                    info=f.d.info,
                                    discrete=discrete,
                                    valid_values=valid_values,
                                    world=cur_world.key,
                                    added_by=self.page_user.key,
                                    visible=visible,
                                    rejected=False)
            new_property.put()

            self.set_menu(cur_world, access)
            memcache.delete("_properties-%s-global" % cur_world.key.id())

            return web.seeother('/%s/property/%s' %
                                (cur_world.key.id(), new_property.key.id()))
    def POST(self, world):

        cur_world = world_exists(world)
        self.redirect_if_not_admin(cur_world)

        o = cur_world.is_open

        world_menu = self.get_or_put_menu(cur_world, "admin")

        f = self.world_form()
        form = CombinedForm([f], **self.formargs)

        if not f.validates():
            section = render().section_world(form)
            return render().admin(cur_world, section, world_menu, "%s on Palimpsest" % cur_world.title)
        else:
            edit_world = World.get_by_id(world)
            edit_world.title=f.d.title
            edit_world.blurb=f.d.blurb
            edit_world.publish=f.d.publish
            edit_world.void_text=f.d.void_text
            edit_world.is_open=f.d.is_open
            edit_world.put()

            if o != edit_world.is_open:
                # update menu
                world_menu = self.replace_or_put_and_get_menu(edit_world, "admin")
            
            section = render().section_world(form)
            return render().admin(edit_world, section, world_menu, "%s on Palimpsest" % cur_world.title)
    def POST(self, world, prop):
        cur_world = world_exists(world)
        cur_prop = property_exists(prop)
        self.redirect_if_not_edit(cur_world, cur_prop)

        a = cur_world.get_access_string(self.page_user)

        post = web.input()
        if hasattr(post, 'delete'):
            
            PropertyValue.delete_all_for_property(cur_prop)
            cur_prop.key.delete()

            """ Flush menus and available properties for everyone so they get reset"""
            # TODO: Fix cache flushing for everyone else
            memcache.delete("_properties-%s-global" % cur_world.key.id())
            if a == "admin":
                memcache.delete("%s-closed" % cur_world.key.id())
            elif a == "closed":
                memcache.delete("%s-admin" % cur_world.key.id())
            self.replace_or_put_menu(cur_world, a)

            raise web.seeother("/%s/property" % cur_world.key.id())

        f = self.properties_form()
        if not f.validates():
            menu = self.get_or_put_menu(cur_world, a)
            edit_form = CombinedForm([f], **self.formargs)
            section = render().section_property(edit_form)
            return render().admin(cur_world, section, menu, "%s's %s on Palimpsest" % (cur_world.title, cur_prop.name), pre=["/js/showhide_form_fields.js"])
        else:

            try:
                if int(f.d.valid_values) == 0:
                    valid_values = f.d.fixed_values
                else:
                    valid_values = f.d.valid_values
            except ValueError:
                valid_values = f.d.valid_values

            if f.d.discrete == "True":
                discrete = True
            else:
                discrete = False

            to_edit = cur_prop
            to_edit.name=f.d.name
            to_edit.sorter=f.d.sorter
            to_edit.info=f.d.info
            to_edit.discrete=discrete
            to_edit.valid_values=valid_values
            to_edit.last_modified_by=self.page_user.key

            to_edit.put()

        return web.seeother("/%s/property/%s" % (cur_world.key.id(), cur_prop.key.id()))
Beispiel #12
0
    def POST(self, worldkey):
        world = world_exists(worldkey)
        self.redirect_if_not_exists("/")
        self.can_access_world(world)

        i = web.input()
        key = int(i.key)
        room = Room.get_by_id(key)

        return self.js_make_room_json(room)
    def POST(self, worldkey):
        world = world_exists(worldkey)
        self.redirect_if_not_exists("/")
        self.can_access_world(world)

        i = web.input()
        key = int(i.key)
        room = Room.get_by_id(key)

        return self.js_make_room_json(room)
Beispiel #14
0
    def POST(self, world):
        cur_world = world_exists(world)
        self.redirect_if_not_create(cur_world)

        i = web.input(long=[], lat=[], prop_name=[], prop_val=[])
        coord = []
        new = []
        access = cur_world.get_access_string(self.page_user)
        form = self.text_form()

        if not form.validates():
            world_menu = self.get_or_put_menu(cur_world, access)
            return self.reset_text_page(cur_world, form, access, world_menu)
        else:

            if cur_world.is_mod(self.page_user):
                visible = True
                """ Flush menus for everyone so they get reset"""
                mrpc = memcache.create_rpc()
                m = flush_caches("", cur_world, mrpc)
                try:
                    m.get_result()
                except AssertionError:  # There were no caches to flush - is this even the problem?
                    pass
            else:
                visible = False

            new_text = Room(world=cur_world.key,
                            name=form.d.name,
                            short_desc=form.d.short_desc,
                            long_desc=form.d.long_desc,
                            added_by=self.page_user.key,
                            latitudes=i.lat,
                            longitudes=i.long,
                            visible=visible,
                            rejected=False)
            new_text.put()

            for index, name in enumerate(i.prop_name):
                p = Property.get_by_id(int(name))
                new.append(PropertyValue())
                new[index].value = i.prop_val[index]
                new[index].of_property = p.key
                new[index].room = new_text.key
                new[index].added_by = self.page_user.key
                new[index].visible = visible

            valftrs = ndb.put_multi_async(new)
            self.set_menu(cur_world, access)

            for ftr in valftrs:
                ftr.get_result()

            return web.seeother('/%s/text/%s' %
                                (cur_world.key.id(), new_text.key.id()))
    def POST(self, world):
        cur_world = world_exists(world)
        self.redirect_if_not_create(cur_world)

        i = web.input(long=[], lat=[], prop_name=[], prop_val=[])
        coord = []
        new = []
        access = cur_world.get_access_string(self.page_user)
        form = self.text_form()

        if not form.validates():
            world_menu = self.get_or_put_menu(cur_world, access)
            return self.reset_text_page(cur_world, form, access, world_menu)
        else:

            if cur_world.is_mod(self.page_user):
                visible = True
                """ Flush menus for everyone so they get reset"""
                mrpc = memcache.create_rpc()
                m = flush_caches("", cur_world, mrpc)
                try:
                    m.get_result()
                except AssertionError: # There were no caches to flush - is this even the problem?
                    pass
            else:
                visible = False

            new_text = Room(world = cur_world.key,
                            name=form.d.name,
                            short_desc=form.d.short_desc,
                            long_desc=form.d.long_desc,
                            added_by=self.page_user.key,
                            latitudes=i.lat,
                            longitudes=i.long,
                            visible=visible,
                            rejected=False
                        )
            new_text.put()

            for index, name in enumerate(i.prop_name):
                p = Property.get_by_id(int(name))
                new.append(PropertyValue())
                new[index].value = i.prop_val[index]
                new[index].of_property = p.key
                new[index].room = new_text.key
                new[index].added_by = self.page_user.key
                new[index].visible = visible

            valftrs = ndb.put_multi_async(new)
            self.set_menu(cur_world, access)

            for ftr in valftrs:
                ftr.get_result()

            return web.seeother('/%s/text/%s' % (cur_world.key.id(), new_text.key.id()))
    def POST(self, world):
        cur_world = world_exists(world)
        self.redirect_if_not_create(cur_world)

        f = self.properties_form()
        form = CombinedForm([f], **self.formargs)

        if not f.validates():
            access = cur_world.get_access_string(self.page_user)
            world_menu = self.get_or_put_menu(cur_world, access)
            section = render().section_properties(form)
            return render().admin(cur_world, section, world_menu, title="Add a new property to %s on Palimpsest" % cur_world.title, pre=["/js/showhide_form_fields.js"])
        else:

            access = cur_world.get_access_string(self.page_user)

            try:
                if int(f.d.valid_values) == 0:
                    valid_values = f.d.fixed_values
                else:
                    valid_values = f.d.valid_values
            except ValueError:
                valid_values = f.d.valid_values

            if f.d.discrete == "True":
                discrete = True
            else:
                discrete = False

            if cur_world.is_mod(self.page_user):
                visible = True
                """ Flush menus and available properties for everyone so they get reset"""
                # TODO: Fix this
                memcache.delete("%s-admin" % cur_world.key.id())
                memcache.delete("%s-closed" % cur_world.key.id())
            else:
                visible = False

            new_property = Property(name=f.d.name,
                                    sorter=f.d.sorter,
                                    info=f.d.info,
                                    discrete=discrete,
                                    valid_values=valid_values,
                                    world=cur_world.key,
                                    added_by=self.page_user.key,
                                    visible=visible,
                                    rejected=False
                )
            new_property.put()

            self.set_menu(cur_world, access)
            memcache.delete("_properties-%s-global" % cur_world.key.id())

            return web.seeother('/%s/property/%s' % (cur_world.key.id(), new_property.key.id()))
    def GET(self, world):
        cur_world = world_exists(world)
        self.redirect_if_not_create(cur_world)

        access = cur_world.get_access_string(self.page_user)
        world_menu = self.get_or_put_menu(cur_world, access)
        world_menu['texts'][0][2] = "active"

        logging.warning(access)

        form = self.text_form()
        return self.reset_text_page(cur_world, form, access, world_menu)
Beispiel #18
0
    def GET(self, world):
        cur_world = world_exists(world)
        self.redirect_if_not_create(cur_world)

        access = cur_world.get_access_string(self.page_user)
        world_menu = self.get_or_put_menu(cur_world, access)
        world_menu['texts'][0][2] = "active"

        logging.warning(access)

        form = self.text_form()
        return self.reset_text_page(cur_world, form, access, world_menu)
    def GET(self, worldkey):
        world = world_exists(worldkey)
        #self.can_access_world(world)
        self.redirect_if_not_exists(world, "/yours/new")
        try:
            if not world.publish:
                raise web.notfound()
        except AttributeError:
            web.seeother("/yours/new")

        js = self.js_all_rooms_on_map(world)

        return render().cover(world, pre=['http://maps.google.com/maps/api/js?sensor=false'], js=js, post=['/js/all_rooms_on_map.js'])
    def GET(self, world):

        cur_world = world_exists(world)
        self.redirect_if_not_admin(cur_world)

        world_menu = self.get_or_put_menu(cur_world, "admin")

        f = self.world_form()
        form = CombinedForm([f], **self.formargs)
        f.fill(**{'title':cur_world.title,'blurb':cur_world.blurb,'publish':cur_world.publish,'is_open':cur_world.is_open,'void_text':cur_world.void_text})

        section = render().section_world(form)

        return render().admin(cur_world, section, world_menu, "%s on Palimpsest" % cur_world.title)
    def GET(self, world):
        cur_world = world_exists(world)
        self.redirect_if_not_create(cur_world)

        access = cur_world.get_access_string(self.page_user)
        world_menu = self.get_or_put_menu(cur_world, access)
        world_menu['properties'][0][2] = "active"

        logging.warning(access)

        f = self.properties_form()
        form = CombinedForm([f], **self.formargs)
        section = render().section_property(form)
        return render().admin(cur_world, section, world_menu, title="Add a new property to %s on Palimpsest" % cur_world.title, pre=["/js/showhide_form_fields.js"])
    def GET(self, world):
        cur_world = world_exists(world)
        self.redirect_if_not_admin(cur_world)

        mods_ftr = cur_world.get_moderators()

        access = cur_world.get_access_string(self.page_user)
        world_menu = self.get_or_put_menu(cur_world, access)
        world_menu['contributors'][0][2] = "active"

        f = self.moderator_form()
        form = CombinedForm([f], **self.formargs)
        cur_mods = mods_ftr.get_result()
        section = render().section_moderators(form, cur_mods)
        return render().admin(cur_world, section, world_menu, title="Moderators of %s on Palimpsest" % cur_world.title, post=self.epost)
    def GET(self, world, auth_key):
        cur_world = world_exists(world)
        try:
            user_pending = ndb.Key(urlsafe=auth_key).get()
            pending_mods = user_pending.get_pending_mods().get_result()

            for m in pending_mods:
                m.user_pending = None
                m.user = get_current_user().key
                m.put()
            user_pending.key.delete()

        except:
            return web.seeother("/")

        return web.seeother("/%s/texts" % world)
Beispiel #24
0
    def GET(self, world, auth_key):
        cur_world = world_exists(world)
        try:
            user_pending = ndb.Key(urlsafe=auth_key).get()
            pending_mods = user_pending.get_pending_mods().get_result()

            for m in pending_mods:
                m.user_pending = None
                m.user = get_current_user().key
                m.put()
            user_pending.key.delete()

        except:
            return web.seeother("/")

        return web.seeother("/%s/texts" % world)
Beispiel #25
0
    def GET(self, worldkey):
        world = world_exists(worldkey)
        #self.can_access_world(world)
        self.redirect_if_not_exists(world, "/yours/new")
        try:
            if not world.publish:
                raise web.notfound()
        except AttributeError:
            web.seeother("/yours/new")

        js = self.js_all_rooms_on_map(world)

        return render().cover(
            world,
            pre=['http://maps.google.com/maps/api/js?sensor=false'],
            js=js,
            post=['/js/all_rooms_on_map.js'])
Beispiel #26
0
    def GET(self, world):
        cur_world = world_exists(world)
        self.redirect_if_not_create(cur_world)

        access = cur_world.get_access_string(self.page_user)
        world_menu = self.get_or_put_menu(cur_world, access)
        world_menu['properties'][0][2] = "active"

        logging.warning(access)

        f = self.properties_form()
        form = CombinedForm([f], **self.formargs)
        section = render().section_property(form)
        return render().admin(cur_world,
                              section,
                              world_menu,
                              title="Add a new property to %s on Palimpsest" %
                              cur_world.title,
                              pre=["/js/showhide_form_fields.js"])
Beispiel #27
0
    def GET(self, world):
        cur_world = world_exists(world)
        self.redirect_if_not_admin(cur_world)

        mods_ftr = cur_world.get_moderators()

        access = cur_world.get_access_string(self.page_user)
        world_menu = self.get_or_put_menu(cur_world, access)
        world_menu['contributors'][0][2] = "active"

        f = self.moderator_form()
        form = CombinedForm([f], **self.formargs)
        cur_mods = mods_ftr.get_result()
        section = render().section_moderators(form, cur_mods)
        return render().admin(cur_world,
                              section,
                              world_menu,
                              title="Moderators of %s on Palimpsest" %
                              cur_world.title,
                              post=self.epost)
Beispiel #28
0
    def GET(self, worldkey, save):
        world = world_exists(worldkey)
        save = save_exists(save)
        self.redirect_if_not_exists(world, "/yours/saves")
        self.redirect_if_not_exists(save, "/yours/saves")
        #self.can_access_world(world)
        self.can_edit_save(save)
        if not world.publish:
            raise web.notfound()

        sofaUrl = "/%s/save/%s?s=1" % (world.key.id(), save.key.id())

        param = web.input()
        if hasattr(param, 's'):  # In sofa mode
            post = [
                '/js/maps.google.polygon.containsLatLng.js',
                '/js/page_scroll.js', '/js/text_queue.js',
                '/js/room_expand.js', '/js/sofa_location.js',
                '/js/toggle_info.js'
            ]
        else:
            post = [
                '/js/maps.google.polygon.containsLatLng.js',
                '/js/page_scroll.js', '/js/text_queue.js',
                '/js/room_expand.js', '/js/get_location.js',
                '/js/toggle_info.js'
            ]

        js = self.js_coords_list(
            world, "/%s/save/%s" % (world.key.id(), save.key.id()), sofaUrl)

        return render().go(
            title="%s on Palimpsest" % world.title,
            navleft=[('Back to %s' % world.title, '/%s' % world.key.id())],
            pre=[
                'http://maps.google.com/maps/api/js?sensor=false',
                '/js/set_page_height.js'
            ],
            js=js,
            post=post)
    def POST(self, worldkey):
        world = world_exists(worldkey)
        self.can_access_world(world)

        i = web.input()

        trimmed = i.savename.strip()
        if trimmed == "" or trimmed is None:
            if hasattr(i, 'saveandgo'):
                return web.seeother("%s/go" % worldkey)
            elif hasattr(i, 'sofago'):
                return web.seeother("%s/go?s=1" % worldkey)
            else:
                return web.seeother("%s" % worldkey)

        savename = make_save_name(i.savename, self.page_user)
        new_save = SavePath(name=savename, user=self.page_user.key, publish=False)
        save_ftr = new_save.put_async()
        s = save_ftr.get_result()

        if hasattr(i, 'saveandgo'):
            return web.seeother("%s/save/%s" % (worldkey, s.integer_id()))
        elif hasattr(i, 'sofago'):
            return web.seeother("/%s/save/%s?s=1" % (worldkey, s.integer_id()))
Beispiel #30
0
    def POST(self, world):
        cur_world = world_exists(world)
        self.redirect_if_not_admin(cur_world)

        param = web.input()
        if hasattr(param, 'mod'):
            # Access rights form submitted
            edit_mod = ndb.Key("Moderator", int(param.userid)).get()
            if int(param.action) == 1:
                edit_mod.admin = True
            if int(param.action) == 2:
                edit_mod.admin = False
            if int(param.action) == 0:
                try:
                    edit_mod.user_pending.delete()
                except AttributeError:
                    # (no pending user)
                    pass
                edit_mod.key.delete()
            else:
                edit_mod.put()
            raise web.seeother("/%s/mods" % world)

        f = self.moderator_form()
        form = CombinedForm([f], **self.formargs)
        if not f.validates():
            mods_ftr = cur_world.get_moderators()

            access = cur_world.get_access_string(self.page_user)
            world_menu = self.get_or_put_menu(cur_world, access)
            world_menu['contributors'][0][2] = "active"

            f = self.moderator_form()
            form = CombinedForm([f], **self.formargs)
            cur_mods = mods_ftr.get_result()
            section = render().section_moderators(form, cur_mods)
            return render().admin(cur_world,
                                  section,
                                  world_menu,
                                  title="Moderators of %s on Palimpsest" %
                                  cur_world.title,
                                  post=self.epost)

        else:

            try_user = users.User(f.d.add_contrib)
            user_result = get_google_user_key(try_user).get_result()
            if len(user_result) > 0 and user_result[0] is not None:
                user = user_exists_bykey(user_result[0])
                m = Moderator(world=cur_world.key, user=user.key, admin=False)
                msg = """You've been added as a contributor to %s.
This means you can add texts and properties which are published straight away.  You can also approve or reject publicly submitted texts and properties.
Try it out: %s/%s/texts""" % (cur_world.title, web.ctx.host,
                              cur_world.key.id())
            else:
                email = str(f.d.add_contrib).lower()
                # TODO: Check UserPending doesn't already exist with that email
                u_p = UserPending(email=email)
                u_p.put()
                m = Moderator(world=cur_world.key,
                              user_pending=u_p.key,
                              admin=False)
                msg = """You've been added as a contributor to %s.
This means you can add texts which bypass the moderation stage, and are published straight away.
Try it out: %s/%s/auth/%s""" % (cur_world.title, web.ctx.host,
                                cur_world.key.id(), str(u_p.key.id()))

            m.put()

            to_addr = f.d.add_contrib
            if not mail.is_email_valid(to_addr):
                return "Could not send: invalid email. Press back and try again."

            message = mail.EmailMessage()
            message.sender = get_current_user().user.email()
            message.to = to_addr
            message.subject = "Palimpsest: You have been added as a moderator of %s!" % cur_world.title
            message.body = msg

            message.send()

        return web.seeother('/%s/mods' % cur_world.key.id())
    def POST(self, world):
        cur_world = world_exists(world)
        self.redirect_if_not_admin(cur_world)

        param = web.input()
        if hasattr(param, 'mod'):
            # Access rights form submitted
            edit_mod = ndb.Key("Moderator", int(param.userid)).get()
            if int(param.action) == 1:
                edit_mod.admin = True
            if int(param.action) == 2:
                edit_mod.admin = False
            if int(param.action) == 0:
                try:
                    edit_mod.user_pending.delete()
                except AttributeError:
                    # (no pending user)
                    pass
                edit_mod.key.delete()
            else:
                edit_mod.put()
            raise web.seeother("/%s/mods" % world)

        f = self.moderator_form()
        form = CombinedForm([f], **self.formargs)
        if not f.validates():
            mods_ftr = cur_world.get_moderators()

            access = cur_world.get_access_string(self.page_user)
            world_menu = self.get_or_put_menu(cur_world, access)
            world_menu['contributors'][0][2] = "active"

            f = self.moderator_form()
            form = CombinedForm([f], **self.formargs)
            cur_mods = mods_ftr.get_result()
            section = render().section_moderators(form, cur_mods)
            return render().admin(cur_world, section, world_menu, title="Moderators of %s on Palimpsest" % cur_world.title, post=self.epost)
        
        else:

            try_user = users.User(f.d.add_contrib)
            user_result = get_google_user_key(try_user).get_result()
            if len(user_result) > 0 and user_result[0] is not None:
                user = user_exists_bykey(user_result[0])
                m = Moderator(world=cur_world.key, user=user.key, admin=False)
                msg = """You've been added as a contributor to %s.
This means you can add texts and properties which are published straight away.  You can also approve or reject publicly submitted texts and properties.
Try it out: %s/%s/texts""" % (cur_world.title, web.ctx.host, cur_world.key.id())
            else:
                email = str(f.d.add_contrib).lower()
                # TODO: Check UserPending doesn't already exist with that email
                u_p = UserPending(email=email)
                u_p.put()
                m = Moderator(world=cur_world.key, user_pending=u_p.key, admin=False)
                msg = """You've been added as a contributor to %s.
This means you can add texts which bypass the moderation stage, and are published straight away.
Try it out: %s/%s/auth/%s""" % (cur_world.title, web.ctx.host, cur_world.key.id(), str(u_p.key.id()))
            
            m.put()
            
            to_addr = f.d.add_contrib
            if not mail.is_email_valid(to_addr):
                return "Could not send: invalid email. Press back and try again."

            message = mail.EmailMessage()
            message.sender = get_current_user().user.email()
            message.to = to_addr
            message.subject = "Palimpsest: You have been added as a moderator of %s!" % cur_world.title
            message.body = msg

            message.send()

        return web.seeother('/%s/mods' % cur_world.key.id())
    def POST(self, world, text):
        cur_world = world_exists(world)
        cur_text = text_exists(text)
        self.redirect_if_not_edit(cur_world, cur_text)

        a = cur_world.get_access_string(self.page_user)

        post = web.input()
        if hasattr(post, 'delete'):
            
            PropertyValue.delete_all_for_text(cur_text)
            cur_text.key.delete()

            """ Flush menus for everyone so they get reset"""
            # TODO: Fix cache flushing for everyone else
            self.replace_or_put_menu(cur_world, a)
            if a == "admin":
                memcache.delete("%s-closed" % cur_world.key.id())
            elif a == "closed":
                memcache.delete("%s-admin" % cur_world.key.id())

            raise web.seeother("/%s/text" % cur_world.key.id())

        else:

            i = web.input(long=[], lat=[], prop_name=[], prop_val=[], del_property=[], action_val=[], mod_id=[])
            coord = []
            new = []

            form = self.text_form()
            if not form.validates():
                world_menu = self.get_or_put_menu(cur_world, a)
                return self.reset_text_page(cur_world, form, a, world_menu, cur_text)
        
            else:

                cur_text.world = cur_world.key
                cur_text.name = form.d.name
                cur_text.short_desc = form.d.short_desc
                cur_text.long_desc = form.d.long_desc
                cur_text.last_modified_by = self.page_user.key
                cur_text.latitudes = i.lat
                cur_text.longitudes = i.long

                text_ftr = cur_text.put_async()

                if cur_world.is_mod(self.page_user):
                    visible = True
                    """ Flush menus for everyone so they get reset"""
                    mrpc = memcache.create_rpc()
                    m = flush_caches("", cur_world, mrpc)
                    try:
                        m.get_result()
                    except AssertionError: # There were no caches to flush - this doesn't work
                        pass
                else:
                    visible = False

                for index, name in enumerate(i.prop_name):
                    p = ndb.Key('Property', int(name))
                    new.append(PropertyValue())
                    new[index].value = i.prop_val[index]
                    new[index].of_property = p
                    new[index].room = cur_text.key
                    new[index].added_by = self.page_user.key
                    new[index].visible = visible

                new_values_ftrs = ndb.put_multi_async(new)

                value_keys = []
                for index, p_id in enumerate(i.del_property):
                    value_keys.append(ndb.Key('PropertyValue', int(p_id)))
                ndb.delete_multi(value_keys)

                for ftr in new_values_ftrs:
                    ftr.get_result()

                text_ftr.get_result()

                self.set_menu(cur_world, a)

                return web.seeother("/%s/text/%s" % (cur_world.key.id(), cur_text.key.id()))