コード例 #1
0
    def create_module(self, path, name, shortname):
        """
        Creates a module in the database. Will not create Things above
        module level, and will fail if the path is not unique.
        """

        # find the parent (remove end slash)
        try:
            parent = self.thing_list.get(pathid=Thing.hash(path[:-1]))
        except Thing.DoesNotExist:
            self.logger.log(
                'failed',
                'module',
                'Could not find path {0}'.format(path[:-1])
            )
            return
        except Thing.MultipleObjectsReturned:
            self.logger.log(
                'failed',
                'module',
                'Path {0} was not unique'.format(path[:-1])
            )
            return

        db_module = Thing(
            fullname=name,
            type='module',
            parent=parent,
            name=shortname
        )

        self.logger.log('insert', 'module', name)
        db_module.save()

        return db_module
コード例 #2
0
    def get(self, request, thing, depth="0"):
        if not request.user.has_perm(
                Thing.PERM_READ, ThingSubject(fullpath=thing, depth=depth)):
            return HttpResponseForbidden("Denied")
        hashid = Thing.hash(thing)
        try:
            if depth == "0":
                thing = Thing.objects.get(pathid=hashid)
                typeofthing = thing.type
                if typeofthing is None:
                    typeofthing = "default"
                context = {"thing": thing}
                try:
                    return render(request,
                                  "student/things/thing-%s.html" % typeofthing,
                                  context)
                except:
                    return render(request, "student/things/thing-default.html",
                                  context)
            else:
                depth = int(depth)
                if depth > 10 or depth < 0:
                    return HttpResponseBadRequest(
                        "Sorry no more than 10 levels allowed")
                things = Thing.objects.filter(
                    Thing.treequery([thing],
                                    max_depth=depth)).order_by("fullname")
                return render(request, "student/list-of-things.html",
                              {"things": things})

        except Thing.DoesNotExist:
            return HttpResponseNotFound()
コード例 #3
0
    def test_xml_import_permission(self):
        logger = APILogger()

        # read the file
        file_full_path = os.path.join(xml_path, 'test_add.xml')
        with open(file_full_path) as opened_file:
            content = opened_file.read()

        # process the XML
        processor = processors.XMLImportProcessor(logger=logger)
        modules = processor.process(content)

        importer = importers.APIImporter(self.user, logger=logger)

        # try importing before the part is made
        for module in modules:
            importer.add_module_data(module)

        if logger.was_success():
            self.fail("Imported to non-existent part")
        logger.clear()


        # make the part now
        self.part = Thing(
            fullname='test',
            type='part',
            parent=self.tripos,
            name='test'
        )
        self.part.save()


        # try importing with no permission
        for module in modules:
            importer.add_module_data(module)

        if logger.was_success():
            self.fail("Imported without permission")
        else:
            if logger.failed:
                self.fail("Failed to import data")
        logger.clear()


        # now give permissions and try again
        tag = ThingTag(
            thing=self.userthing,
            targetthing=self.part,
            annotation="admin"
        )
        tag.save()

        for module in modules:
            importer.add_module_data(module)

        if not logger.was_success():
            self.fail("Import failed "+logger.summary())
コード例 #4
0
    def get(self, request):
        site_url = get_site_url_from_request(request)
        grouped_subjects = Subjects.group_for_part_drill_down(
            Subjects.all_subjects())
        # Get the cambridge year data for the acadamic year set in the settings.
        acadamic_year = AcademicYear.for_year(settings.DEFAULT_ACADEMIC_YEAR)
        context = {
            "subjects": Subjects.to_json(grouped_subjects),
            "site_url": site_url,
            "terms": acadamic_year.get_terms_json(),
            "calendar_start": acadamic_year.start_boundary.isoformat(),
            "calendar_end": acadamic_year.end_boundary.isoformat()
        }
        if request.user.is_authenticated():
            # create a url with a hmac in it if the thing is a user. If not just a simple url will do.
            thing = Thing.get_or_create_user_thing(request.user)
            context["user_thing"] = thing

            thingsubject = ThingSubject(thing=thing)
            hmac = thingsubject.create_hmac()
            context["ics_feed_url"] = reverse("export ics hmac",
                                              kwargs={
                                                  "thing": thing.fullpath,
                                                  "hmac": hmac
                                              })
        else:
            context["ics_feed_url"] = None
        try:
            context['raven_url'] = settings.RAVEN_URL
        except:
            pass

        return render(request, "student/base.html", context)
コード例 #5
0
    def get(self, request, thing, depth="0"):
        if not request.user.has_perm(
                Thing.PERM_READ, ThingSubject(fullpath=thing, depth=depth)):
            return HttpResponseForbidden("Denied")
        hashid = Thing.hash(thing)
        try:
            thing = Thing.objects.get(pathid=hashid)
            # create a url with a hmac in it if the thing is a user. If not just a simple url will do.
            thingsubject = ThingSubject(thing=thing)
            if thingsubject.is_user():
                hmac = thingsubject.create_hmac()
                ics_feed_url = reverse("export ics hmac",
                                       kwargs={
                                           "thing": thing.fullpath,
                                           "hmac": hmac
                                       })
            else:
                ics_feed_url = reverse("export ics",
                                       kwargs={"thing": thing.fullpath})

            context = {
                "thing": Thing.objects.get(pathid=hashid),
                "ics_feed_url": ics_feed_url
            }
            return render(request, "calendar.html", context)
        except Thing.DoesNotExist:
            return HttpResponseNotFound()
コード例 #6
0
 def get_user_thing(self, request, thing):
     if (request.user.is_authenticated()
             and self.get_user_permission(request, thing)):
         return Thing.objects.get(pathid=Thing.hash(thing))
     elif thing == self.public_user_path:
         return None
     raise PermissionDenied
コード例 #7
0
    def post(self, request, thing):
        user = ThingSubject(fullpath=thing)

        # Check if the user is logged in
        if request.user.is_anonymous():
            return HttpResponseForbidden("Not logged in")
        elif not request.user.has_perm(Thing.PERM_LINK, user):
            return HttpResponseForbidden("Not your calendar")

        hashid = Thing.hash(thing)

        # Check if the thing exists
        try:
            thing = Thing.objects.get(pathid=hashid)
        except Thing.DoesNotExist:
            return HttpResponseNotFound()

        site_url = get_site_url_from_request(request)
        new_hmac = user.create_hmac(True)
        new_feed_path = reverse("export ics hmac",
                                kwargs={
                                    "thing": thing,
                                    "hmac": new_hmac
                                })

        return HttpResponse(site_url + new_feed_path)
コード例 #8
0
    def _get_subject_perms(self, user_obj, obj):
        if obj.hmac is not None:
            # A hmac can only ever grant read
            if obj.is_hmac_valid():
                return self.JUST_READ
            return set()

        if "user/%s" % user_obj.username == obj.path:
            return self.ALL

        try:
            # Get the thing associated with this user
            userthing = Thing.objects.get(pathid=Thing.hash("user/%s" %
                                                            user_obj.username))
            # Check if this event is associated with an admin annotation via eventtag or eventsourcetag
            t = obj.thing
            if t is not None:
                Thing.objects.get(id=t.id,
                                  relatedthing__thing=userthing,
                                  eventtag__annotation="admin")
                return self.ALL
        except Thing.DoesNotExist:
            # One or more of the things we were looking for doesn't exist, therefore therefore there is only read.
            pass

        # If we got this far, and this is a user Thing then read should be denied
        if obj.is_user():
            return set()
        # could do something more sophisticated here, but just at the moment there is no need.
        return self.JUST_READ
コード例 #9
0
    def get(self, request, thing, hmac=None):
        if not request.user.has_perm(Thing.PERM_READ, ThingSubject(fullpath=thing, hmac=hmac)):
            return HttpResponseForbidden("Denied")
        hashid = Thing.hash(thing)
        outputformat = request.path.split(".")[-1]
        try:
            thing = Thing.objects.get(pathid=hashid)
            if outputformat in settings.EVENT_EXPORTERS:
                exporter_class = settings.EVENT_EXPORTERS[outputformat]
                exporter = newinstance(exporter_class)
                if exporter is not None:
                    depth = self.get_depth()
                    print "Depth: {}".format(depth)
                    events = (thing.get_events(depth=depth)
                        # The series is referenced from event in order to use
                        # the series title in the output, so it helps to
                        # prefetch the series to avoid len(events) queries
                        # when iterating over events.
                        .prefetch_related("source"))
                    return exporter.export(events, feed_name=self._path_to_filename(thing.fullpath))
                return HttpResponseBadRequest("Sorry, Format not recognized, can't load class %s " % exporter_class )
            return HttpResponseBadRequest("Sorry, Format not recognized")

        except Thing.DoesNotExist:
            return HttpResponseNotFound()
コード例 #10
0
 def __get_thing(self):
     try:
         path = self.get_thing_fullpath()
         return Thing.objects.get(pathid=Thing.hash(path))
     except Thing.DoesNotExist:
         # Raise permission denied instead of 404 when a Thing does
         # not exist to avoid leaking presence of a user...
         raise PermissionDenied
コード例 #11
0
    def process_module_dict(self, module):
        """
        Processes a ModuleData dict and updates the database
        """

        path = module['path']
        try:
            db_module = self.thing_list.get(
                pathid=Thing.hash(path+module['shortname'])
            )
        except Thing.DoesNotExist:
            db_module = None

        is_deleting_module = module.is_being_deleted()

        if db_module is None:
            if is_deleting_module:
                # wanted to delete it, doesn't exist, nothing to do
                return
            db_module = self.create_module(
                path,
                module['name'],
                module['shortname']
            )
            if db_module is None:
                # something went wrong creating the module (no need to report
                # it as the logger should already contain the details)
                return

        # check if we want to delete it
        if is_deleting_module:
            self.delete_module(db_module)
            return

        # create a list of child sources
        module_sources = []
        matching_source_tags = self.event_source_list.filter(
            thing=db_module,
            annotation='home'
        )

        for tag in matching_source_tags:
            # check it was imported via the api
            if 'importid' in tag.eventsource.metadata:
                module_sources.append(
                    (tag.eventsource, tag.eventsource.metadata['importid'])
                )

        for source in module['seriesList']:
            db_source = self.process_source_dict(
                module_sources, db_module, source
            )
            if db_source is not None:
                module_sources.append(
                    (db_source, db_source.metadata['importid'])
                )
コード例 #12
0
    def _get_subject_perms(self, user_obj, obj):
        try:
            # Is there anything associated with the user
            userthing = Thing.objects.get(pathid=Thing.hash("user/%s" %
                                                            user_obj.username))
            if ThingTag.objects.filter(thing=userthing,
                                       annotation="admin").count() > 0:
                return self.ALL
        except Thing.DoesNotExist:
            pass

        return self.JUST_READ
コード例 #13
0
 def create_salt(self, update=False):
     '''
     Create or update salt in the Thing metadata.
     Separated from create_hmac so that user salts may be regenerated independently. 
     '''
     t = self._get_thing()
     metadata = t.metadata
     if update or 'salt' not in metadata:
         metadata['salt'] = Thing.hash(now().isoformat())
         t.save()
         return True
     return False
コード例 #14
0
def userHasAccess(user, path):
    # can this user admin the Thing with that full path
    # this is set in the users page up to the level before module

    path = re.sub('/$', '', path)  # remove end slash

    try:
        thing = Thing.objects.get(pathid=Thing.hash(path))
    except Thing.DoesNotExist:
        return False
    except Thing.MultipleObjectsReturned:
        return False

    return thing.can_be_edited_by(user.username)
コード例 #15
0
    def _get_subject_perms(self, user_obj, obj):
        try:
            # Get the thing associated with this user
            userthing = Thing.objects.get(pathid=Thing.hash("user/%s" %
                                                            user_obj.username))
            # Check if this eventsource is associated with an admin annotation via  eventsourcetag
            es = obj.event_source
            if es is not None:
                EventSource.objects.get(id=es.id,
                                        eventsourcetag__thing=userthing,
                                        eventsourcetag__annotation="admin")
                return self.ALL
        except Thing.DoesNotExist:
            pass
        except EventSource.DoesNotExist:
            pass

        return self.JUST_READ
コード例 #16
0
    def _get_subject_perms(self, user_obj, obj):
        # This is a little more complex, we need to find out if the users Thing is associated with
        # the event.
        try:
            # Get the thing associated with this user
            userthing = Thing.objects.get(pathid=Thing.hash("user/%s" %
                                                            user_obj.username))
            # Check if this event is associated with an admin annotation via eventtag or eventsourcetag
            e = obj.event
            if e is not None:
                Event.objects.filter(id=e.id).get(
                    models.Q(eventtag__thing=userthing,
                             eventtag__annotation="admin")
                    | models.Q(source__eventsourcetag__thing=userthing,
                               source__eventsourcetag__annotation="admin"))
                return self.ALL
        except Thing.DoesNotExist:
            pass
        except Event.DoesNotExist:
            pass

        return self.JUST_READ
コード例 #17
0
    def add_module_data(self, module):
        """
        Adds the data in module to the database. Performs
        a check to ensure that user has the appropriate permission.
        Will not create Things above the module level.
        """
        try:
            module.is_valid()
        except DataValidationException as err:
            self.logger.log(
                'failed',
                'module',
                'Module data not valid {0}'.format(err)
            )
            return

        path = module['path']

        # find the parent of the module
        try:
            parent_thing = self.thing_list.get(pathid=Thing.hash(path[:-1]))
        except Thing.DoesNotExist:
            self.logger.log(
                'failed',
                'module',
                'The path {0} does not exist'.format(path[:-1])
            )
            return

        # check for permission
        if not parent_thing.can_be_edited_by(self.user.username):
            self.logger.log(
                'denied',
                'module',
                'You do not have permission to modify {0}'.format(path[:-1])
            )
            return

        self.process_module_dict(module)
コード例 #18
0
    def get(self, request, thing):
        if not request.user.has_perm(Thing.PERM_READ,
                                     ThingSubject(fullpath=thing)):
            return HttpResponseForbidden("Denied")
        hashid = Thing.hash(thing)
        try:
            thing = Thing.objects.get(pathid=hashid)
            typeofthing = thing.type
            if typeofthing is None:
                typeofthing = "default"
            context = {"thing": thing, "events": thing.get_events()}
            try:
                return render(
                    request,
                    "student/things/thing-events-%s.html" % typeofthing,
                    context)
            except:
                return render(request,
                              "student/things/thing-events-default.html",
                              context)

        except Thing.DoesNotExist:
            return HttpResponseNotFound()
    def get_uncategorised_module_for_thing(self, orm, parent_thing):
        fullpath = "{}/{}".format(parent_thing.fullpath, "uncategorised")
        pathid = RealThing.hash(fullpath)

        assert pathid
        assert "/" in fullpath
        assert fullpath.endswith("uncategorised")
        assert parent_thing.pk is not None

        thing, created = orm.Thing.objects.get_or_create(pathid=pathid,
                                                         defaults={
                                                             "parent":
                                                             parent_thing,
                                                             "fullpath":
                                                             fullpath,
                                                             "name":
                                                             "uncategorised",
                                                             "fullname":
                                                             "Uncategorised",
                                                             "type": "module"
                                                         })

        return thing
コード例 #20
0
 def set_metadata(self, crsid, metadata):
     fake_user = FakeUser(username=crsid)
     user_thing = Thing.get_or_create_user_thing(fake_user)
     user_thing.metadata["studentinfo"] = metadata
     user_thing.save()
コード例 #21
0
 def get_subject_pathid(self):
     return Thing.hash(self.kwargs["thing"])
コード例 #22
0
 def _get_thing(self):
     if self._thing is None:
         self._thing = Thing.objects.get(pathid=Thing.hash(self.fullpath))
     return self._thing
コード例 #23
0
    def load_calendar_data(self,
                           nameFilter,
                           caldir,
                           listOnly,
                           eventSourceLevel="file"):
        # Scan the eventdata subdir
        # For each json file found parse and load
        """
        {
    "name": "Systems Biology",
    "vhash": "0f5a767acaf26ba26dfb8bcc40bea479",
    "organiser": "Example organiser",
    "groups": [
        {
            "term": "Michaelmas",
            "code": "Mi1-8 Th 10",
            "name": "Lecture",
            "elements": [
                {
                    "what": "Systems Biology",
                    "code": " x8",
                    "who": "Example person",
                    "when": " x8",
                    "merge": 0,
                    "eid": "Ee8143b54e72ed0ea44ea140fb3ef7eb4",
                    "where": "Example location"
                }
            ]
        },
        ...........
    ],
    "where": "Example location",
    "id": "T0001000012012002",
    "metadata": {
        "notes": "",
        "course-description": ""
    }
}


{
    "years": [
        {
            "triposes": [
                {
                    "parts": [
                        {
                            "name": "Architecture Tripos Part IA",
                            "id": "T0014001202012"
                        },
                        ....
                    ],
                    "name": "Architecture & History of Art"
                },
        """

        caldir = os.path.abspath(caldir)
        topF = open("%s/top.json" % caldir)
        top = json.loads(topF.read())
        topF.close()

        detail_files = []
        detailMatch = re.compile("details_T\d*.json$")
        files = os.listdir(caldir)
        for fileName in files:
            if detailMatch.match(fileName) is not None:
                detail_files.append(fileName)
        total_events = 0
        for year in top["years"]:
            log.info("Processing Year %s " % year['name'])
            start_year = int(re.match("(\d{4})", year['name']).group(1))
            for tripos in year['triposes']:
                if not 'parts' in tripos or \
                        len(tripos['parts']) == 0 or \
                        'id' not in tripos['parts'][0]:
                    log.info("Skipping Invalid Tripos %s " % tripos)
                    continue
                if listOnly:
                    log.info("Processing Tripos %s" % (tripos['name']))

                triposId = self._parseId(tripos['parts'][0]['id'])
                if triposId is None:
                    continue

                partsProcessed = 0
                for p in tripos['parts']:
                    n = 0

                    nameParts = self._parsePartName(p["name"])
                    triposId = self._parseId(p['id'])
                    if nameParts is None:
                        nameParts = {"name": p["name"]}
                        log.error("Failed to parse name  %s " % p["name"])
                    '''

                    if 'level' in nameParts:
                        partId = "%s::%s" % (nameParts['name'], nameParts['level'])
                    else:
                        partId = "%s::" % (nameParts['name'])
                    if nameFilter is not None and partId.lower() not in nameFilter:
                        if listOnly:
                            log.info("Skipping Part triposId %s  Part %s " % (triposCode, partId))
                        continue
                    '''
                    log.info("Processing Part triposId %s  Part %s " %
                             (p["name"], nameParts))
                    if listOnly:
                        continue

                    partsProcessed = partsProcessed + 1

                    dre = re.compile("details_%s\d*.json$" % p['id'])
                    # log.info("Scanning with pattern %s " % dre.pattern)

                    for dfn in detail_files:
                        if not dre.match(dfn):
                            continue
                        detailFileName = "%s/%s" % (caldir, dfn)
                        # log.info("Found %s " % detailFileName)
                        detailF = open(detailFileName)
                        detail = json.loads(detailF.read())
                        detailF.close()

                        groupTitle = "Unknown"
                        level = "0"
                        if "name" in detail:
                            groupTitle = detail['name']
                        elif "subject" in nameParts:
                            groupTitle = nameParts['subject']
                        elif "name" in nameParts:
                            level = nameParts['name']
                            groupTitle = nameParts['name']

                        name = nameParts['name']
                        level = self._get_level(nameParts)
                        module = self._get_module(detail)

                        u = []
                        for x in [
                                self._tripos_for_url(name), level,
                                self._for_url(module)
                        ]:
                            if x is not None:
                                u.append(x)
                        thingpath = "tripos/%s" % ("/".join(u))

                        types = []
                        if self._tripos_for_url(name) is not None:
                            types.append("tripos")
                        if level is not None:
                            types.append("level")
                        if module is not None:
                            types.append("module")

                        thing = Thing.create_path(thingpath, {
                            "fullname":
                            detail['name'][:(MAX_NAME_LENGTH - 1)]
                        }, types)
                        if eventSourceLevel == "file":
                            source = self.loadEventSource(
                                groupTitle[:(MAX_NAME_LENGTH - 1)],
                                dfn[:(MAX_URL_LENGTH - 1)])
                            EventSourceTag.objects.get_or_create(
                                thing=thing, eventsource=source)

                        # Todo: create an Thing here to associate with the source departments/department/subject/name

                        if "groups" in detail:
                            events = []
                            n = 0
                            sources = 0
                            for g in detail['groups']:
                                if eventSourceLevel == "group":
                                    source = self.loadEventSource(
                                        ("%s %s" %
                                         (groupTitle, n))[:(MAX_NAME_LENGTH -
                                                            1)],
                                        ("%s:%s" % (dfn, n))[:(MAX_URL_LENGTH -
                                                               1)])
                                    EventSourceTag.objects.get_or_create(
                                        thing=thing, eventsource=source)
                                    sources = sources + 1
                                group_template = g.get('code') or ""
                                for e in g['elements']:
                                    location = e.get('where') or g.get(
                                        'location') or "Unknown"
                                    title = e.get(
                                        'what') or groupTitle or 'Unnamed'
                                    date_time_pattern = g.get('when') or ""
                                    if eventSourceLevel == "element":
                                        source = self.loadEventSource(
                                            ("%s %s" % (groupTitle, title))[:(
                                                MAX_NAME_LENGTH - 1)],
                                            ("%s:%s:%s" % (dfn, n, title))[:(
                                                MAX_URL_LENGTH - 1)])
                                        EventSourceTag.objects.get_or_create(
                                            thing=thing, eventsource=source)
                                        sources = sources + 1
                                    events.extend(
                                        generate(source, title, location,
                                                 date_time_pattern,
                                                 group_template, start_year))
                            self.bulk_create(events)
                            total_events = total_events + len(events)
                            log.info(
                                "%s (%s) added %s events in %s series" %
                                (thingpath, types[-1], len(events), sources))

            log.info("Created %s events " % total_events)
コード例 #24
0
    def setUp(self):
        # make a user
        self.user = User(
            username='******',
            password='******',
            email='email'
        )
        self.user.save()

        allusers = Thing(
            fullname='All Users',
            type='user',
            name='user'
        )
        allusers.save()

        self.userthing = Thing(
            name='testuser',
            type='user',
            parent=allusers,
            fullname='A Users Calendar'
        )

        self.userthing.save()

        # make tripos/api/test
        alltripos = Thing(
            fullname='All Tripos',
            type='tripos',
            name='tripos'
        )
        alltripos.save()
        self.tripos = Thing(
            fullname='api',
            type='tripos',
            parent=alltripos,
            name='api'
        )
        self.tripos.save()
コード例 #25
0
class TestImport(TestCase):
    def setUp(self):
        # make a user
        self.user = User(
            username='******',
            password='******',
            email='email'
        )
        self.user.save()

        allusers = Thing(
            fullname='All Users',
            type='user',
            name='user'
        )
        allusers.save()

        self.userthing = Thing(
            name='testuser',
            type='user',
            parent=allusers,
            fullname='A Users Calendar'
        )

        self.userthing.save()

        # make tripos/api/test
        alltripos = Thing(
            fullname='All Tripos',
            type='tripos',
            name='tripos'
        )
        alltripos.save()
        self.tripos = Thing(
            fullname='api',
            type='tripos',
            parent=alltripos,
            name='api'
        )
        self.tripos.save()

        # don't make the part yet
        # don't give permissions yet

    def tearDown(self):
        pass

    def test_xml_import_permission(self):
        logger = APILogger()

        # read the file
        file_full_path = os.path.join(xml_path, 'test_add.xml')
        with open(file_full_path) as opened_file:
            content = opened_file.read()

        # process the XML
        processor = processors.XMLImportProcessor(logger=logger)
        modules = processor.process(content)

        importer = importers.APIImporter(self.user, logger=logger)

        # try importing before the part is made
        for module in modules:
            importer.add_module_data(module)

        if logger.was_success():
            self.fail("Imported to non-existent part")
        logger.clear()


        # make the part now
        self.part = Thing(
            fullname='test',
            type='part',
            parent=self.tripos,
            name='test'
        )
        self.part.save()


        # try importing with no permission
        for module in modules:
            importer.add_module_data(module)

        if logger.was_success():
            self.fail("Imported without permission")
        else:
            if logger.failed:
                self.fail("Failed to import data")
        logger.clear()


        # now give permissions and try again
        tag = ThingTag(
            thing=self.userthing,
            targetthing=self.part,
            annotation="admin"
        )
        tag.save()

        for module in modules:
            importer.add_module_data(module)

        if not logger.was_success():
            self.fail("Import failed "+logger.summary())
コード例 #26
0
 def get_user_pathid(self):
     user_thing_path = self.get_user_thing_path()
     if user_thing_path is None:
         return None
     return Thing.hash(self.get_user_thing_path())
コード例 #27
0
    def get(self, request, thing):
        if not request.user.has_perm(
                Thing.PERM_READ, ThingSubject(fullpath=thing, fulldepth=True)):
            return HttpResponseForbidden("Denied")
        try:
            thing = Thing.objects.get(pathid=Thing.hash(thing))
            relatedthings = frozenset()
            relatedsources = frozenset()

            related_path = request.GET[ChildrenView.QUERY_RELATED]
            if related_path:
                # Get the things linked to the thing supplied by EventTag or EventSourceTag
                # eventtag__event__eventtag__thing__in looks for things linked to the same event
                # eventsourcetag__eventsource__eventsourcetag__thing for things linked to the same eventsource
                related_children_q = Thing.treequery([related_path])
                related = Thing.objects.filter(related_children_q)

                contains_event_in_related = models.Q(
                    eventtag__event__eventtag__thing__in=related,
                    eventtag__event__current=True)
                contains_eventseries_in_related = models.Q(
                    eventsourcetag__eventsource__eventsourcetag__thing__in=
                    related,
                    eventsourcetag__eventsource__current=True)

                relatedthings = frozenset(
                    Thing.objects.filter(
                        contains_event_in_related
                        | contains_eventseries_in_related).values_list(
                            "fullpath", flat=True))

                # get all the sources that the target has related
                relatedsources = frozenset(
                    EventSource.objects.filter(
                        eventsourcetag__thing__in=related,
                        current=True).values_list("id", flat=True))

            raw_modules = Thing.objects.filter(
                parent__pathid=thing.pathid).prefetch_related(
                    "eventsourcetag_set__eventsource",
                    "thing_set__eventsourcetag_set__eventsource")

            modules = []
            for raw_module in raw_modules:
                module = {
                    "id": raw_module.id,
                    "title": raw_module.fullname,
                    "fullpath": raw_module.fullpath,
                    "in_calendar": raw_module.fullpath in relatedthings
                }

                series = []
                for eventsourcetag in raw_module.eventsourcetag_set.all():
                    raw_series = eventsourcetag.eventsource
                    single_series = {
                        "id": raw_series.id,
                        "title": raw_series.title,
                        "date_pattern":
                        raw_series.metadata.get("datePattern", ""),
                        "location": raw_series.metadata.get("location", ""),
                        "people": raw_series.metadata.get("people", []),
                        "in_calendar": raw_series.id in relatedsources
                    }
                    series.append(single_series)

                module["series"] = sorted_naturally(series,
                                                    key=itemgetter("title"))
                modules.append(module)

            raw_links = ThingTag.objects.filter(annotation="link", thing=thing)
            links = []

            for raw_link in raw_links:
                target = raw_link.targetthing
                if target.type == "part":
                    name = target.parent.fullname + ", " + target.fullname
                else:
                    name = target.fullname + " " + "(" + target.parent.parent.fullname + "), " + target.parent.fullname
                link = {"fullpath": target.fullpath, "name": name}

                links.append(link)

            context = {
                "modules": sorted_naturally(modules, key=itemgetter("title")),
                "links": sorted_naturally(links, key=itemgetter("name"))
            }
            return render(request, "student/modules-list/base.html", context)
        except Thing.DoesNotExist:
            return HttpResponseNotFound()
コード例 #28
0
    def post(self, request, thing):
        # Check if the user is logged in
        if request.user.is_anonymous():
            return HttpResponseForbidden("Not logged in")
        elif not request.user.has_perm(Thing.PERM_LINK,
                                       ThingSubject(fullpath=thing)):
            return HttpResponseForbidden("Not your calendar")

        hashid = Thing.hash(thing)
        try:
            try:
                thing = Thing.objects.get(pathid=hashid)
            except Thing.DoesNotExist:
                path = "user/%s" % request.user.username
                if thing == path:
                    thing = Thing.get_or_create_user_thing(request.user)

            # Delete associations first
            elist = self._expand(request.POST.getlist("esd"))
            if len(elist) > 0:
                EventSourceTag.objects.filter(
                    thing=thing,
                    eventsource__in=EventSource.objects.filter(
                        id__in=elist)).delete()
            elist = self._expand(request.POST.getlist("ed"))
            if len(elist) > 0:
                EventTag.objects.filter(
                    thing=thing,
                    event__in=Event.objects.filter(id__in=elist)).delete()

            # If there is a list of things to delete, this is a little more complicated.
            tlist = self._expand(request.POST.getlist("td"))
            if len(tlist) > 0:
                # remove all EventTags and EventSourceTags that link this thing to Events or EventSource linked to by any child
                # The following query gets the decendents of all the things listed
                decendents = Thing.objects.filter(Thing.treequery(tlist))
                # Then get the Events associated with all the decendents of all the things
                decendent_events = Event.objects.filter(
                    eventtag__thing__in=decendents)
                # And delete all events tags on this thing, that match those events.
                EventTag.objects.filter(thing=thing,
                                        event__in=decendent_events).delete()
                # get all eventsources that are associated with the list of decendent things
                decendent_eventsource = EventSource.objects.filter(
                    eventsourcetag__thing__in=decendents)
                EventSourceTag.objects.filter(
                    thing=thing,
                    eventsource__in=decendent_eventsource).delete()

            # Add associations
            elist = self._expand(request.POST.getlist("es"))
            if len(elist) > 0:
                # Delete then bulk add, note that no hooks on bulk add
                EventSourceTag.objects.filter(
                    thing=thing,
                    eventsource__in=EventSource.objects.filter(
                        id__in=elist)).delete()
                items = []
                for es in EventSource.objects.filter(id__in=elist,
                                                     current=True):
                    eventsourcetag = EventSourceTag(thing=thing,
                                                    eventsource=es)
                    eventsourcetag.on_pre_save()
                    items.append(eventsourcetag)
                EventSourceTag.objects.bulk_create(items)

            elist = self._expand(request.POST.getlist("e"))
            if len(elist) > 0:
                # Delete then bulk add, note that no hooks on bulk add
                EventTag.objects.filter(
                    thing=thing,
                    event__in=Event.objects.filter(id__in=elist)).delete()
                items = []
                for e in Event.objects.filter(id__id=elist, current=True):
                    eventtag = EventTag(thing=thing, event=e)
                    eventtag.on_pre_save()
                    items.append(eventtag)
                EventTag.objects.bulk_create(items)

            tlist = self._expand(request.POST.getlist("t"))
            if len(tlist) > 0:
                # remove all EventTags and EventSourceTags that link this thing to Events or EventSource linked to by any child
                # The following query gets the decendents of all the things listed
                decendents = Thing.objects.filter(Thing.treequery(tlist))
                # Then get the Events associated with all the decendents of all the things
                decendent_events = Event.objects.filter(
                    eventtag__thing__in=decendents)
                # And delete all events tags on this thing, that match those events.
                EventTag.objects.filter(thing=thing,
                                        event__in=decendent_events).delete()
                # get all eventsources that are associated with the list of decendent things
                decendent_eventsource = EventSource.objects.filter(
                    eventsourcetag__thing__in=decendents)
                EventSourceTag.objects.filter(
                    thing=thing,
                    eventsource__in=decendent_eventsource).delete()

                # Having deleted, we need to add, first the events bulk creating EventTags
                items = []
                for e in decendent_events.filter(current=True):
                    eventtag = EventTag(thing=thing, event=e)
                    eventtag.on_pre_save()
                    items.append(eventtag)
                EventTag.objects.bulk_create(items)

                # Next the Event Sources bulk creating EventSourceTags
                items = []
                for es in decendent_eventsource.filter(current=True):
                    eventtag = EventSourceTag(thing=thing, eventsource=es)
                    eventtag.on_pre_save()
                    items.append(eventtag)
                EventSourceTag.objects.bulk_create(items)

            return HttpResponse("ok")

        except Thing.DoesNotExist:
            return HttpResponseNotFound()