def get_task_folder_data(task, user): folder_ids = get_task_folder_ids(task) # unsafe, no permission check! folders = list(Folder.objects.filter(id__in=folder_ids)) folder_data = prepare_folder_menu(folders, user) # safe # For now, folder is not considered to be the owner of the tasks, but only # a collection. Therefore, if the user has no access to any of the # task's folders, he/she might still have the access to the task itself. # True, automatically removing access to the task if the user has no # access to its containers is a really great feature. But, it is # too complicated - advanced permission check should be added to everything # related to the task (e.g. editing, solutions, permissions editing etc.) return folder_data
def inner(request, folder_id=None, *args, **kwargs): if not folder_id: folder = Folder.objects.get(parent_id__isnull=True) else: folder = get_object_or_404(Folder, id=folder_id) # If type is VIEW, wait, do not call expensive .user_has_perm. if permission != VIEW: explicit = folder.user_has_perm(request.user, permission) if not explicit: # Reject immediately, do not waste time return HttpResponseForbidden('No permission for this action!') else: explicit = None data = prepare_folder_menu([folder], request.user) if not data or not data.get('folder_tree', None): # Even if you are not able to see the folder's ancestors, # you may still have explicit permission. # (for example, if you are the author, or the author gave you # the permission to update/view the folder) # Note: This results in a small security problem. The URL, # i.e. path of the folder contains short names of its ancestors. if permission == VIEW: # ok, now check permissions... (can prepare_folder_menu # give me this same information?) explicit = folder.user_has_perm(request.user, permission) if not explicit: return HttpResponseForbidden('No permission for this action!') data['folder'] = folder try: has_subfolders = bool(data['folder_children'][data['folder'].id]) except: has_subfolders = False data['has_subfolders'] = has_subfolders if has_subfolders: data['has_subfolders_strict'] = True else: # TODO: put in prepare_folder_menu? data['has_subfolders_strict'] = \ Folder.objects.filter(parent_id=folder.id).exists() return func(request, folder, data, *args, **kwargs)
def new(request, folder_id=None): # Analogous to task.models.new if folder_id: folder = get_object_or_404(Folder, id=folder_id) edit = True old_parent_id = folder.parent_id else: folder = old_parent_id = None edit = False data = {} initial_parent_id = None if edit: if not folder.editable: return response.FORBIDDEN permissions = folder.get_user_permissions(request.user) if EDIT not in permissions: return response.FORBIDDEN if EDIT_PERMISSIONS in permissions: data['can_edit_permissions'] = True data['content_type'] = ContentType.objects.get_for_model(Folder) data['children'] = children = list(Folder.objects \ .for_user(request.user, VIEW) \ .filter(parent=folder).order_by('parent_index').distinct()) data['has_subfolders_strict'] = Folder.objects \ .filter(parent_id=folder_id).exists() else: referrer = get_referrer_path(request) if referrer and referrer.startswith('/folder/'): try: initial_parent_id = int(referrer[8:referrer.find('/', 8)]) except: pass if request.method == 'POST': folder_form = FolderForm(request.POST, instance=folder, user=request.user) if folder_form.is_valid(): folder = folder_form.save(commit=False) # TODO: Make a util function for creating Folder instances, to be # able to create tests easier. # If user can't edit short name, copy full name. if 'short_name' not in folder_form.fields: folder.short_name = folder.name if not edit: folder.author = request.user else: for x in children: parent_index = request.POST.get('child-{}'.format(x.id)) parent_index = int(parent_index) if parent_index is not None \ and x.parent_index != parent_index: x.parent_index = parent_index x.save() # Update order... children.sort(key=lambda x: x.parent_index) # If editing, refresh immediately before saving. # Do not call folder_form.save_m2m()! folder._no_save = True set_tags(folder, folder_form.cleaned_data['tags']) folder.save() if not edit: # If new, first save folder (and define ID), and then save tags. set_tags(folder, folder_form.cleaned_data['tags']) # Refresh Folder cache. if old_parent_id != folder.parent_id: # The only folders that have to be refreshed are those in # the folder's subtree, together with folder itself. descendant_ids = get_folder_descendant_ids(folder.id) descendant_ids.append(folder.id) # refresh_path_cache also requires ancestors. Following code # works, because you can't move a folder into its child folder. descendant_ids.extend([int(x) for x in folder.parent.cache_ancestor_ids.split(',') if x]) descendant_ids.append(folder.parent_id) refresh_path_cache(Folder.objects.filter(id__in=descendant_ids)) if not edit: return ('/folder/{}/edit/'.format(folder.id), ) # return HttpResponseRedirect(folder.get_absolute_url()) else: folder_form = FolderForm(instance=folder, user=request.user, initial_parent_id=initial_parent_id) # If parent given and acceptable, show menu. (new mode) initial_parent = getattr(folder_form, 'initial_parent', None) if initial_parent: data.update(prepare_folder_menu([initial_parent], request.user)) if edit: data.update(prepare_folder_menu([folder], request.user)) data['folder'] = folder data['form'] = folder_form data['edit'] = edit if request.user.has_perm('folder.advanced_create'): data['advanced_create_permission'] = True return data