示例#1
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
    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()
    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()
 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
示例#5
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
示例#6
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()
示例#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)
 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
示例#9
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'])
                )
示例#10
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
示例#11
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
示例#12
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)
示例#13
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
示例#14
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
示例#15
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)
    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
示例#17
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()
示例#18
0
 def _get_thing(self):
     if self._thing is None:
         self._thing = Thing.objects.get(pathid=Thing.hash(self.fullpath))
     return self._thing
示例#19
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())
示例#20
0
 def get_subject_pathid(self):
     return Thing.hash(self.kwargs["thing"])
    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()
    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()