def rename_resource(request): """Rename a file or folder """ post = json.loads(request.body.decode()) path = post.get('path') target = post.get('target') if not path: return HttpResponseBadRequest(missing_parameter('path')) if not target: return HttpResponseBadRequest(missing_parameter('target')) path = join_fb_root(path) name = os.path.basename(path) new_path = os.path.join(os.path.dirname(path), target) try: if any(c in target for c in settings.FILEBROWSER_DISALLOWED_CHAR): msg = "Can't rename '{0}' to '{1}': name should not contain any of {2}." \ .format(name, target, settings.FILEBROWSER_DISALLOWED_CHAR) return HttpResponseBadRequest(msg) if os.path.exists(new_path): msg = "Can't rename '{0}' to '{1}': this name is already used.".format(name, target) return HttpResponseBadRequest(msg) os.rename(path, new_path) return JsonResponse( {'path': rm_fb_root(new_path), 'status': 200}) except Exception as e: # pragma: no cover msg = "Impossible to rename '{0}' to '{1}': {2}".format(name, target, htmlprint.code( str(type(e)) + ' - ' + str(e))) if settings.DEBUG: msg += ("DEBUG set to True: " + htmlprint.html_exc()) return HttpResponseNotFound(msg)
def search_in_files(request): # TODO ADD TEST path = request.GET.get('path') if not path: return HttpResponseBadRequest(missing_parameter('path')) query = request.GET.get('query') if not query: return HttpResponseBadRequest(missing_parameter('query')) cwd = os.getcwd() try: if (not path.startswith(HOME_DIR) and not path.startswith(LIB_DIR)): return HttpResponseBadRequest('cannot search outside of root directories') path = join_fb_root(path) if not os.path.isdir(path): return HttpResponseBadRequest('path should point to a directory') os.chdir(path) p = subprocess.Popen("grep -nr '{0}' .".format(query), stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) out, err = p.communicate() finally: os.chdir(cwd) ret, out, err = p.returncode, out.decode().strip("\n"), err.decode() if not ret: return HttpResponse(out) else: # pragma: no cover return HttpResponseNotFound(htmlprint.code(out + err))
def commit(request): """ Execute an add and commit of the targeted entry with the informations of POST. """ post = json.loads(request.body.decode()) path = post.get('path') if not path: return HttpResponseBadRequest(missing_parameter('path')) commit = post.get('commit') if not commit: return HttpResponseBadRequest(missing_parameter('commit')) user = request.user if not user.email: return HttpResponseBadRequest("User must have an email") if user.first_name and user.last_name: name = user.get_full_name() else: name = user.get_username() ret, out, err = gitcmd.commit(join_fb_root(path), commit, name=name, mail=request.user.email) if not ret: return HttpResponse(htmlprint.code(out + err)) else: # pragma: no cover return HttpResponseNotFound(htmlprint.code(err + out))
def upload_resource(request): # TODO ADD TEST """ Allow the user to upload a file in the filebrowser """ if request.method != 'POST': return HttpResponseNotAllowed(['POST']) f = request.FILES.get('file') if not f: return HttpResponseBadRequest(missing_parameter('file')) path = request.POST.get('path') if not path: return HttpResponseBadRequest(missing_parameter('path')) name = f.name try: path = os.path.join(join_fb_root(path), name) if os.path.exists(path): return HttpResponseBadRequest("This file's name is already used : " + name) else: with open(path, 'wb+') as dest: for chunk in f.chunks(): dest.write(chunk) return HttpResponse() except Exception as e: # pragma: no cover msg = "Impossible to upload '" + path + "' : " + htmlprint.code( str(type(e)) + ' - ' + str(e)) if settings.DEBUG: messages.error(request, "DEBUG set to True: " + htmlprint.html_exc()) return HttpResponseNotFound(msg)
def reload_pltp(request): """Reload a given activity with the targeted PLTP.""" post = json.loads(request.body.decode()) path = post.get('path') if not path: return HttpResponseBadRequest(missing_parameter('path')) activity_id = post.get('activity_id') if not activity_id: return HttpResponseBadRequest(missing_parameter('activity_id')) activity = Activity.objects.get(id=activity_id) if not activity.is_teacher(request.user): return HttpResponse("Vous n'avez pas le droit de recharger cette activité") return reload_activity(path, activity)
def create_resource(request): """Create a new file or folder """ post = json.loads(request.body.decode()) path = post.get('path') if not path: return HttpResponseBadRequest(missing_parameter('path')) path = join_fb_root(path) name = os.path.basename(path) try: if any(c in name for c in settings.FILEBROWSER_DISALLOWED_CHAR): msg = "Can't create '%s': name should not contain any of %s." return HttpResponseBadRequest(msg % (name, str(settings.FILEBROWSER_DISALLOWED_CHAR))) if os.path.exists(path): return HttpResponseBadRequest("Can't create '%s': this name is already used." % name) if post.get('type', '') == 'file': with open(path, "w") as f: print(post.get('content', ''), file=f) return JsonResponse({'path': rm_fb_root(path)}) else: os.mkdir(path) return JsonResponse({'path': rm_fb_root(path)}) except Exception as e: # pragma: no cover msg = "Impossible to create '{0}' : {1}".format(name, htmlprint.code( str(type(e)) + ' - ' + str(e))) messages.error(request, msg) if settings.DEBUG: msg += ("DEBUG set to True: " + htmlprint.html_exc()) return HttpResponseNotFound(msg)
def delete_resource(request): """Delete a file or folder """ post = json.loads(request.body.decode()) path = post.get('path') if not path: return HttpResponseBadRequest(missing_parameter('path')) if is_root(path): return HttpResponseBadRequest('cannot delete a root folder') try: path = join_fb_root(path) shutil.rmtree( path, ignore_errors=True) if os.path.isdir(path) else os.remove(path) if not path.startswith("lib/"): add_commit_path(request, path, action="deleted") return JsonResponse({'success': True}) except Exception as e: # pragma: no cover path = path.replace(settings.FILEBROWSER_ROOT, '') error = htmlprint.code(str(e).replace(settings.FILEBROWSER_ROOT, '')) msg = "Impossible to delete '%s' : %s" % (path, error) if settings.DEBUG: msg += ("DEBUG: " + htmlprint.html_exc()) return HttpResponseNotFound(msg)
def compile_pl(request): """ Used by the PL editor to compile a PL""" post = json.loads(request.body.decode()) path = post.get('path') if not path: return HttpResponseBadRequest(missing_parameter('path')) path_components = path.split('/') directory = path_components[0] response = {'compiled': True} try: path = join_fb_root(path) with open(path, 'r') as f: content = f.read() shutil.copyfile(path, path + ".bk") with open(path, 'w+') as f: # Writting editor content into the file print(content, file=f) directory = Directory.objects.get(name=directory) relative = os.path.join(*(path_components[1:])) pl, warnings = load_file(directory, relative) if not pl: response['compiled'] = False else: response['json'] = pl.json response['warnings'] = warnings except Exception: # pragma: no cover response['compiled'] = False finally: shutil.move(path + ".bk", path) return HttpResponse( json.dumps(response), content_type='application/json', status=200 )
def test_pl(request): path = request.GET.get('path') if not path: return HttpResponseBadRequest(missing_parameter('path')) try: path_components = path.split('/') directory = Directory.objects.get(name=path_components[0]) relative = os.path.join(*(path_components[1:])) pl, warnings = load_file(directory, relative) if not pl: return HttpResponseBadRequest(warnings.replace(settings.FILEBROWSER_ROOT, "")) pl.save() exercise = SessionTest.objects.create(pl=pl, user=request.user) preview = exercise.get_exercise(request) return render(request, 'filebrowser/test.html', { 'preview': preview, 'id': pl.id, }) except Exception as e: # pragma: no cover msg = ("Impossible to test '" + os.path.basename(path) + "' : " + htmlprint.code( str(type(e)) + ' - ' + str(e))) return HttpResponseBadRequest(msg.replace(settings.FILEBROWSER_ROOT, ""))
def test_show_no_path(self): response = self.c.get(reverse('git:show'), { 'name': 'git_show', }, content_type='application/json') self.assertContains(response, missing_parameter('path'), status_code=400)
def test_clone_no_url(self): response = self.c.post(reverse('git:clone'), { 'path': 'Yggdrasil/folder1', }, content_type='application/json') self.assertContains(response, missing_parameter('url'), status_code=400)
def test_commit_without_message(self): response = self.c.post(reverse("git:commit"), { 'path': 'Yggdrasil/folder1/TPE/', }, content_type='application/json') self.assertContains(response, missing_parameter('commit'), status_code=400)
def test_update_no_path(self): response = self.c.post(reverse("filebrowser:option"), { 'name': 'update_resource', }, content_type='application/json') self.assertContains(response, missing_parameter('path'), status_code=400)
def test_load_pltp_no_path(self): response = self.c.get(reverse("filebrowser:option"), { 'name': 'load_pltp', }, content_type='application/json') self.assertContains(response, missing_parameter('path'), status_code=400)
def test_rename_resource_missing_target(self): response = self.c.post(reverse("filebrowser:option"), { 'name': 'rename_resource', 'path': '100/TPE/function001.pl', }, content_type='application/json') self.assertContains(response, missing_parameter('target'), status_code=400)
def test_status_no_path(self): with open(join(FAKE_FB_ROOT, 'Yggdrasil/folder1/TPE/function001.pl'), 'w+') as f: print("abcdefghijklmnopqrstuvwxyz", file=f) response = self.c.get(reverse("git:status"), content_type='application/json') self.assertContains(response, missing_parameter('path'), status_code=400)
def test_move_resource_no_dst(self): response = self.c.post(reverse("filebrowser:option"), { 'name': 'move_resource', 'path': 'Yggdrasil/TPE/function001.pl', }, content_type='application/json') self.assertContains(response, missing_parameter('dst'), status_code=400)
def test_reload_no_activity_id(self): response = self.c.post(reverse("filebrowser:option"), { 'name': 'reload_pltp', 'path': 'Yggdrasil/working.pltp', }, content_type='application/json') self.assertContains(response, missing_parameter('activity_id'), status_code=400)
def move_resource(request): """ Move post.get('path'] to POST['dst').""" post = json.loads(request.body.decode()) src = post.get('path') if not src: return HttpResponseBadRequest(missing_parameter('path')) dst = post.get('dst') if not dst: return HttpResponseBadRequest(missing_parameter('dst')) try: src_path = join_fb_root(src) dst_path = join_fb_root(dst) if src == dst: return HttpResponseNotFound("Can't move a directory inside itself") elif not os.path.isdir(dst_path): return HttpResponseNotFound('"{0}" is not a directory'.format(dst)) elif dst_path.startswith(src_path): return HttpResponseNotFound("Can't move {0} inside {1}".format( src, dst)) else: destination = os.path.join(dst_path, os.path.basename(src)) if os.path.exists(destination): return HttpResponseNotFound( "{0} already exists inside {1}".format( os.path.basename(src), dst)) else: if post.get('copy'): if os.path.isdir(src_path): shutil.copytree(src_path, destination) else: shutil.copyfile(src_path, destination) else: os.rename(src_path, destination) return JsonResponse( {'path': os.path.join(dst, os.path.basename(src))}) except Exception as e: # pragma: no cover msg = "Impossible to copy '" + os.path.basename( src) + "' : " + htmlprint.code(str(type(e)) + ' - ' + str(e)) return HttpResponseNotFound(msg)
def add(request): """ Execute a git add on the targeted entry.""" path = request.GET.get('path') if not path: return HttpResponseBadRequest(missing_parameter('path')) ret, out, err = gitcmd.add(join_fb_root(path)) if not ret: return HttpResponse("Entry successfully added to the index.") else: # pragma: no cover return HttpResponseNotFound( "Nothing to add." if not err else htmlprint.code(err + out))
def test_commit_no_path(self): with open(join(FAKE_FB_ROOT, 'Yggdrasil/folder1/TPE/function001.pl'), 'w') as f: print("test", file=f) response = self.c.post(reverse("git:commit"), { 'commit': 'mycommit', }, content_type='application/json') self.assertContains(response, missing_parameter('path'), status_code=400)
def test_push_no_path(self): open(join(FAKE_FB_ROOT, 'Yggdrasil/folder1/TPE/function001.pl'), 'w+').close() response = self.c.post(reverse("git:push"), { 'username': '', 'password': '', }, content_type='application/json') self.assertContains(response, missing_parameter('path'), status_code=400)
def status(request): """ Execute a git status on the targeted entry.""" path = request.GET.get('path') if not path: return HttpResponseBadRequest(missing_parameter('path')) ret, out, err = gitcmd.status(join_fb_root(path)) if not ret: return HttpResponse(htmlprint.code(out + err)) else: # pragma: no cover return HttpResponseNotFound(htmlprint.code(out + err))
def resolve_path(request): # TODO ADD TEST path = request.GET.get('path') if not path: return HttpResponseBadRequest(missing_parameter('path')) target = request.GET.get('target') if not target: return HttpResponseBadRequest(missing_parameter('target')) try: path_components = path.split('/') directory = Directory.objects.get(name=path_components[0]) current = path_components[1] if len(path_components) == 2 else \ os.path.join(*path_components[1:-1]) directory, path = get_location(directory, target, current=current) return HttpResponse(os.path.join(directory, path)) except Exception as e: msg = "Impossible to resolve the path '" + request.GET.get( 'target') + "' : " + htmlprint.code(str(type(e)) + ' - ' + str(e)) if settings.DEBUG: messages.error(request, "DEBUG set to True: " + htmlprint.html_exc()) return HttpResponseNotFound(msg)
def option(request): opt = request.GET.get('name') if request.method == 'POST': post = json.loads(request.body.decode()) opt = post.get('name') if not opt: return HttpResponseBadRequest(missing_parameter('name')) try: return globals()[opt](request) except Exception as e: return HttpResponseBadRequest("Cannot use option %s: %s" % (opt, str(e)))
def checkout(request): """ Execute a checkout of the targeted entry with the informations of POST. """ path = request.GET.get('path') if not path: return HttpResponseBadRequest(missing_parameter('path')) ret, out, err = gitcmd.checkout(join_fb_root(path)) if not ret: return HttpResponse("Entry successfully checked out.") else: # pragma: no cover return HttpResponseNotFound( "Nothing to checked out." if not err else htmlprint.code(err + out))
def show(request): """ Execute a git show on the targeted entry.""" path = request.GET.get('path') if not path: return HttpResponseBadRequest(missing_parameter('path')) try: ret, out, err = gitcmd.show_last_revision(join_fb_root(path)) if not ret: return HttpResponse(out) else: # pragma: no cover return HttpResponseNotFound(htmlprint.code(out + err)) except Exception as e: # pragma: no cover error = htmlprint.code(str(type(e)) + ' - ' + str(e)) return HttpResponseNotFound(error)
def update_resource(request): """ View used to update a resource (file). """ post = json.loads(request.body.decode()) path = post.get("path") if path is None: return HttpResponseBadRequest(missing_parameter('path')) try: with open(join_fb_root(path), 'w') as f: print(post.get('content', ''), file=f) if not path.startswith("lib/"): add_commit_path(request, path, action="modified") return JsonResponse({'success': True}) except Exception as e: # pragma: no cover return HttpResponseNotFound(str(e))
def push(request): """ Execute a git push on the targeted entry with the informations of POST.""" post = json.loads(request.body.decode()) username = post.get('username', None) password = post.get('password', None) path = post.get('path', None) if not path: return HttpResponseBadRequest(missing_parameter('path')) ret, out, err = gitcmd.push(join_fb_root(path), username=username, password=password) if not ret: return HttpResponse(htmlprint.code(out + err)) else: # pragma: no cover return HttpResponseNotFound(htmlprint.code(err + out))
def get_resource(request): """Return the content of <path>.""" path = request.GET.get('path') if not path: return HttpResponseBadRequest(missing_parameter('path')) try: path = join_fb_root(path) return JsonResponse({ 'content': get_content(path), 'meta': get_meta(path) }) except Exception as e: # pragma: no cover msg = f"Impossible to open '{rm_fb_root(path)}' : {htmlprint.code(str(e))}" if settings.DEBUG: messages.error(request, "DEBUG set to True: " + htmlprint.html_exc()) msg += f"{request} : DEBUG set to True: {htmlprint.html_exc()}" return HttpResponseNotFound(msg)