Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:11.4:Update
cobbler
cobbler_csrf_fix.diff
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File cobbler_csrf_fix.diff of Package cobbler
diff --git a/web/settings.py b/web/settings.py index a8db1fd..79794f4 100644 --- a/web/settings.py +++ b/web/settings.py @@ -31,8 +31,7 @@ MEDIA_ROOT = '' MEDIA_URL = '' ADMIN_MEDIA_PREFIX = '/media/' -# FIXME: ??? -SECRET_KEY = 'w&x*74x-b=ycigsdya03699o!9kt4(z4wyx-us9q=--&7clv4=' +SECRET_KEY = '' # code config @@ -42,6 +41,7 @@ TEMPLATE_LOADERS = ( ) MIDDLEWARE_CLASSES = ( 'django.middleware.common.CommonMiddleware', + 'django.contrib.csrf.middleware.CsrfMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', ) diff --git a/web/cobbler_web/templates/generic_edit.tmpl b/web/cobbler_web/templates/generic_edit.tmpl index 49a1530..93f330d 100644 --- a/web/cobbler_web/templates/generic_edit.tmpl +++ b/web/cobbler_web/templates/generic_edit.tmpl @@ -404,6 +404,7 @@ $(document).ready(function() <h1>{% ifequal editmode 'edit' %}Editing{% else %}Adding{% endifequal %} a {{ what|capfirst }}{%ifequal editmode 'edit' %}: {{ name }}{% endifequal %}</h1> <hr /> <form method="post" action="/cobbler_web/{{ what }}/save"> + {% csrf_token %} <input type="hidden" name="editmode" value="{{ editmode }}" /> <input type="hidden" name="subobject" value="{{ subobject }}" /> <ol> diff --git a/web/cobbler_web/templates/generic_list.tmpl b/web/cobbler_web/templates/generic_list.tmpl index 4736255..99a0d5b 100644 --- a/web/cobbler_web/templates/generic_list.tmpl +++ b/web/cobbler_web/templates/generic_list.tmpl @@ -126,6 +126,7 @@ function action_multi(otype) { </ul> <form name="myform" method="post" action="/cobbler_web/{{ what }}/action"> + {% csrf_token %} <table id="listitems" cellspacing="0"> <thead> <tr> diff --git a/web/cobbler_web/templates/import.tmpl b/web/cobbler_web/templates/import.tmpl index da59d8d..4e1298b 100644 --- a/web/cobbler_web/templates/import.tmpl +++ b/web/cobbler_web/templates/import.tmpl @@ -3,6 +3,7 @@ <h1>DVD Importer</h1> <hr /> <form method="post" action="/cobbler_web/import/run"> + {% csrf_token %} <div class="sectionbody"> <ul> <li class="editrow"> diff --git a/web/cobbler_web/templates/ksfile_edit.tmpl b/web/cobbler_web/templates/ksfile_edit.tmpl index 40393dc..63cd3d8 100644 --- a/web/cobbler_web/templates/ksfile_edit.tmpl +++ b/web/cobbler_web/templates/ksfile_edit.tmpl @@ -17,6 +17,7 @@ <h1>{% ifequal editmode 'edit' %}Editing{% else %}Adding{% endifequal %} a Kickstart Template</h1> <hr /> <form id="ksform" method="post" action="/cobbler_web/ksfile/save"> + {% csrf_token %} <ol> <li> <label for="ksdata">{% if ksfile_name %}Editing: {{ ksfile_name }}{% else %}Filename:{% endif %}</label> diff --git a/web/cobbler_web/templates/login.tmpl b/web/cobbler_web/templates/login.tmpl index 0475957..3872d49 100644 --- a/web/cobbler_web/templates/login.tmpl +++ b/web/cobbler_web/templates/login.tmpl @@ -12,6 +12,7 @@ <p class="error">Sorry, that's not a valid username or password</p> {% endif %} <form action="/cobbler_web/do_login" method="post"> + {% csrf_token %} {% if next %}<input type="hidden" name="next" value="{{ next|escape }}" />{% endif %} <div id="username"> <label for="username">Username: </label> diff --git a/web/cobbler_web/templates/snippet_edit.tmpl b/web/cobbler_web/templates/snippet_edit.tmpl index 7f8a7d6..9e36948 100644 --- a/web/cobbler_web/templates/snippet_edit.tmpl +++ b/web/cobbler_web/templates/snippet_edit.tmpl @@ -14,6 +14,7 @@ if you need to resolve this. <h1>{% ifequal editmode 'edit' %}Editing{% else %}Adding{% endifequal %} a Snippet</h1> <hr /> <form id="snippetform" method="post" action="/cobbler_web/snippet/save"> + {% csrf_token %} <ol> <li> <label for="snippetdata">{% if snippet_name %}Snippet: {{ snippet_name }}{% else %}Filename:{% endif %}</label> diff --git a/web/cobbler_web/views.py b/web/cobbler_web/views.py index 43bc070..01e1230 100644 --- a/web/cobbler_web/views.py +++ b/web/cobbler_web/views.py @@ -5,6 +5,25 @@ from django.http import HttpResponse from django.http import HttpResponseRedirect from django.shortcuts import render_to_response +try: + from django.views.decorators.csrf import csrf_protect +except: + # Old Django, fudge the @csrf_protect decorator to be a pass-through + # that does nothing. Django decorator shell based on this page: + # http://passingcuriosity.com/2009/writing-view-decorators-for-django/ + def csrf_protect(f): + def _dec(view_func): + def _view(request,*args,**kwargs): + return view_func(request,*args,**kwargs) + _view.__name__ = view_func.__name__ + _view.__dict__ = view_func.__dict__ + _view.__doc__ = view_func.__doc__ + return _view + if f is None: + return _dec + else: + return _dec(f) + import xmlrpclib import time import simplejson @@ -37,7 +56,7 @@ def index(request): if not test_user_authenticated(request): return login(request,next="/cobbler_web") t = get_template('index.tmpl') - html = t.render(Context({ + html = t.render(RequestContext(request,{ 'version' : remote.version(request.session['token']), 'username': username, })) @@ -51,7 +70,7 @@ def task_created(request): """ if not test_user_authenticated(request): return login(request, next="/cobbler_web/task_created") t = get_template("task_created.tmpl") - html = t.render(Context({ + html = t.render(RequestContext(request,{ 'version' : remote.version(request.session['token']), 'username' : username })) @@ -69,7 +88,7 @@ def error_page(request,message): t = get_template('error_page.tmpl') message = message.replace("<Fault 1: \"<class 'cobbler.cexceptions.CX'>:'","Remote exception: ") message = message.replace("'\">","") - html = t.render(Context({ + html = t.render(RequestContext(request,{ 'version' : remote.version(request.session['token']), 'message' : message, 'username': username @@ -545,7 +564,7 @@ def generic_domulti(request, what, multi_mode=None, multi_arg=None): def import_prompt(request): if not test_user_authenticated(request): return login(request, next="/cobbler_web/import/prompt") t = get_template('import.tmpl') - html = t.render(Context({ + html = t.render(RequestContext(request,{ 'version' : remote.version(request.session['token']), 'username' : username, })) @@ -560,7 +579,7 @@ def check(request): if not test_user_authenticated(request): return login(request, next="/cobbler_web/check") results = remote.check(request.session['token']) t = get_template('check.tmpl') - html = t.render(Context({ + html = t.render(RequestContext(request,{ 'version': remote.version(request.session['token']), 'username' : username, 'results' : results @@ -606,7 +625,7 @@ def ksfile_list(request, page=None): ksfile_list.append((ksfile,ksfile,None)) t = get_template('ksfile_list.tmpl') - html = t.render(Context({ + html = t.render(RequestContext(request,{ 'what':'ksfile', 'ksfiles': ksfile_list, 'version': remote.version(request.session['token']), @@ -617,7 +636,7 @@ def ksfile_list(request, page=None): # ====================================================================== - +@csrf_protect def ksfile_edit(request, ksfile_name=None, editmode='edit'): """ This is the page where a kickstart file is edited. @@ -635,7 +654,7 @@ def ksfile_edit(request, ksfile_name=None, editmode='edit'): ksdata = remote.read_or_write_kickstart_template(ksfile_name, True, "", request.session['token']) t = get_template('ksfile_edit.tmpl') - html = t.render(Context({ + html = t.render(RequestContext(request,{ 'ksfile_name' : ksfile_name, 'deleteable' : deleteable, 'ksdata' : ksdata, @@ -648,6 +667,7 @@ def ksfile_edit(request, ksfile_name=None, editmode='edit'): # ====================================================================== +@csrf_protect def ksfile_save(request): """ This page processes and saves edits to a kickstart file. @@ -691,7 +711,7 @@ def snippet_list(request, page=None): snippet_list.append((snippet,snippet,None)) t = get_template('snippet_list.tmpl') - html = t.render(Context({ + html = t.render(RequestContext(request,{ 'what' : 'snippet', 'snippets' : snippet_list, 'version' : remote.version(request.session['token']), @@ -701,6 +721,7 @@ def snippet_list(request, page=None): # ====================================================================== +@csrf_protect def snippet_edit(request, snippet_name=None, editmode='edit'): """ This page edits a specific snippet. @@ -718,7 +739,7 @@ def snippet_edit(request, snippet_name=None, editmode='edit'): snippetdata = remote.read_or_write_snippet(snippet_name, True, "", request.session['token']) t = get_template('snippet_edit.tmpl') - html = t.render(Context({ + html = t.render(RequestContext(request,{ 'snippet_name' : snippet_name, 'deleteable' : deleteable, 'snippetdata' : snippetdata, @@ -731,6 +752,7 @@ def snippet_edit(request, snippet_name=None, editmode='edit'): # ====================================================================== +@csrf_protect def snippet_save(request): """ This snippet saves a snippet once edited. @@ -774,7 +796,7 @@ def settings(request): results.append([k,settings[k]]) t = get_template('settings.tmpl') - html = t.render(Context({ + html = t.render(RequestContext(request,{ 'settings' : results, 'version' : remote.version(request.session['token']), 'username' : username, @@ -800,7 +822,7 @@ def events(request): events2.sort(sorter) t = get_template('events.tmpl') - html = t.render(Context({ + html = t.render(RequestContext(request,{ 'results' : events2, 'version' : remote.version(request.session['token']), 'username' : username @@ -834,7 +856,7 @@ def eventlog(request, event=0): 'version' : remote.version(request.session['token']), 'username' : username } - html = t.render(Context(vars)) + html = t.render(RequestContext(request,vars)) return HttpResponse(html) # ====================================================================== @@ -912,6 +934,7 @@ def __names_from_dicts(loh,optional=True): # ====================================================================== +@csrf_protect def generic_edit(request, what=None, obj_name=None, editmode="new"): """ @@ -980,7 +1003,7 @@ def generic_edit(request, what=None, obj_name=None, editmode="new"): t = get_template('generic_edit.tmpl') inames = interfaces.keys() inames.sort() - html = t.render(Context({ + html = t.render(RequestContext(request,{ 'what' : what, 'fields' : fields, 'subobject' : child, @@ -998,6 +1021,7 @@ def generic_edit(request, what=None, obj_name=None, editmode="new"): # ====================================================================== +@csrf_protect def generic_save(request,what): """ @@ -1146,9 +1170,11 @@ def test_user_authenticated(request): pass return False +@csrf_protect def login(request, next=None): - return render_to_response('login.tmpl', {'next':next}) + return render_to_response('login.tmpl', RequestContext(request,{'next':next})) +@csrf_protect def do_login(request): global remote global username @@ -1178,6 +1204,7 @@ def do_login(request): else: return login(request,nextsite) +@csrf_protect def do_logout(request): request.session['username'] = "" request.session['token'] = "" diff --git a/web/settings.py b/web/settings.py index 79794f4..3541c8e 100644 --- a/web/settings.py +++ b/web/settings.py @@ -1,4 +1,5 @@ # Django settings for cobbler-web project. +import django DEBUG = True TEMPLATE_DEBUG = DEBUG @@ -39,12 +40,25 @@ TEMPLATE_LOADERS = ( 'django.template.loaders.filesystem.load_template_source', 'django.template.loaders.app_directories.load_template_source', ) -MIDDLEWARE_CLASSES = ( - 'django.middleware.common.CommonMiddleware', - 'django.contrib.csrf.middleware.CsrfMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', -) + +if django.VERSION[0] == 1 and django.VERSION[1] < 2: + # Legacy django had a different CSRF method, which also had + # different middleware. We check the vesion here so we bring in + # the correct one. + MIDDLEWARE_CLASSES = ( + 'django.middleware.common.CommonMiddleware', + 'django.contrib.csrf.middleware.CsrfMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + ) +else: + MIDDLEWARE_CLASSES = ( + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + ) + ROOT_URLCONF = 'urls' TEMPLATE_DIRS = ( commit 18eb1c06779b37d89dfb2962a08236dd1bab24a6 Author: James Cammarata <jimi@sngx.net> Date: Fri Nov 4 02:33:38 2011 -0500 Additional CSRF work. All URLs that modify state are now required to be POSTs only. diff --git a/web/cobbler_web/templates/filter.tmpl b/web/cobbler_web/templates/filter.tmpl index 9e9c9dc..76a230e 100644 --- a/web/cobbler_web/templates/filter.tmpl +++ b/web/cobbler_web/templates/filter.tmpl @@ -1,5 +1,6 @@ {% if pageinfo %} <script type="text/javascript"> +// these functions depend on the "action" form defined in generic_list function add_filter() { field_name = document.getElementById("filter_field"); field_value = document.getElementById("filter_value"); @@ -8,9 +9,14 @@ function add_filter() { } else if (field_value.value == "") { alert("You must select a filter value."); } else { - location = '/cobbler_web/{{ what }}/modifylist/addfilter/'+field_name.value+':'+field_value.value; + document.forms["action"].action = '/cobbler_web/{{ what }}/modifylist/addfilter/'+field_name.value+':'+field_value.value; + document.forms["action"].submit(); } } +function del_filter(filter) { + document.forms["action"].action = '/cobbler_web/{{ what }}/modifylist/removefilter/' + filter + document.forms["action"].submit(); +} </script> <ul id="filter-adder"> <li> @@ -151,7 +157,7 @@ function add_filter() { {% if filters %} <ul id="filter-remover"> {% for key,value in filters.items %} - <li><a href="/cobbler_web/{{ what }}/modifylist/removefilter/{{ key }}" title="remove">✖</a> {{ key }} = {{ value }}</li> + <li><a href="javascript:del_filter('{{ key }}');" title="remove">✖</a> {{ key }} = {{ value }}</li> {% endfor %} </ul> {% endif %} diff --git a/web/cobbler_web/templates/generic_list.tmpl b/web/cobbler_web/templates/generic_list.tmpl index 99a0d5b..7f40afc 100644 --- a/web/cobbler_web/templates/generic_list.tmpl +++ b/web/cobbler_web/templates/generic_list.tmpl @@ -2,6 +2,7 @@ {% load site %} {% block content %} +<form id="action" method="POST" action="">{% csrf_token %}</form> <script type="text/javascript"> function items_check_all(){ var checkall = document.getElementById("itemsall").checked @@ -31,18 +32,21 @@ function items_checked_values() { function obj_rename(old) { var newname = window.prompt("Change {{ what }} name to?",old); if (newname != null) { - window.location = "/cobbler_web/{{ what }}/rename/" + old + "/" + newname; + document.forms["action"].action = "/cobbler_web/{{ what }}/rename/" + old + "/" + newname; + document.forms["action"].submit(); } } function obj_copy(old) { var newname = window.prompt("Name for the new {{ what }}?",old); if (newname != null) { - window.location = "/cobbler_web/{{ what }}/copy/" + old + "/" + newname; + document.forms["action"].action = "/cobbler_web/{{ what }}/copy/" + old + "/" + newname; + document.forms["action"].submit(); } } function obj_delete(old) { if (confirm("Delete {{ what }} (" + old + ") and all child objects?")) { - window.location = "/cobbler_web/{{ what }}/delete/" + old; + document.forms["action"].action = "/cobbler_web/{{ what }}/delete/" + old; + document.forms["action"].submit(); } } @@ -53,6 +57,11 @@ function action(otype) { document.location = "/cobbler_web/" + what + "/" + action } +function action_sort(value) { + document.forms["action"].action = '/cobbler_web/{{ what }}/modifylist/sort/' + value; + document.forms["action"].submit(); +} + function action_multi(otype) { var values = items_checked_values() if (values == "") { @@ -135,7 +144,7 @@ function action_multi(otype) { </th> {% for value in columns %} <th> - <a href="/cobbler_web/{{ what }}/modifylist/sort/{{ value.0 }}">{{ value.0|title }}</a> + <a href="javascript:action_sort('{{ value.0 }}');">{{ value.0|title }}</a> {% ifequal value.1 "asc" %} ↓ {% endifequal %} diff --git a/web/cobbler_web/templates/master.tmpl b/web/cobbler_web/templates/master.tmpl index c83ecf2..44ecb98 100644 --- a/web/cobbler_web/templates/master.tmpl +++ b/web/cobbler_web/templates/master.tmpl @@ -14,9 +14,16 @@ <div id="container"> <div id='user'> <input type="hidden" name="username" id="username" value="{{ username }}" /> - Logged in: <b>{{ username }}</b> <a class="action" href="/cobbler_web/logout">Logout</a> + Logged in: <b>{{ username }}</b> <a class="action" href="javascript:menuaction('/cobbler_web/logout');">Logout</a> </div> <div id="menubar"> + <form id="menuaction" method="POST" action="">{% csrf_token %}</form> + <script type="text/javascript"> + function menuaction(action) { + document.forms["menuaction"].action = action + document.forms["menuaction"].submit(); + } + </script> <h1>Configuration</h1> <ul> <li><a href="/cobbler_web/distro/list" class="edit">Distros</a></li> @@ -36,11 +43,11 @@ <h1>Actions</h1> <ul> <li><a href="/cobbler_web/import/prompt">Import DVD</a></li> - <li><a href="/cobbler_web/sync">Sync</a> ☼</li> - <li><a href="/cobbler_web/reposync">Reposync</a> ☼ </li> - <li><a href="/cobbler_web/hardlink">Hardlink</a> ☼ </li> - <!-- <li><a href="/cobbler_web/replicate">Replicate</a> ☼ </li> --> - <li><a href="/cobbler_web/buildiso">Build ISO</a> ☼ </li> + <li><a href="javascript:menuaction('/cobbler_web/sync');">Sync</a> ☼</li> + <li><a href="javascript:menuaction('/cobbler_web/reposync');"">Reposync</a> ☼ </li> + <li><a href="javascript:menuaction('/cobbler_web/hardlink');"">Hardlink</a> ☼ </li> + <!-- <li><a href="javascript:menuaction('/cobbler_web/replicate');"">Replicate</a> ☼ </li> --> + <li><a href="javascript:menuaction('/cobbler_web/buildiso');">Build ISO</a> ☼ </li> </ul> <h1>Cobbler</h1> <ul> diff --git a/web/cobbler_web/templates/paginate.tmpl b/web/cobbler_web/templates/paginate.tmpl index b8d1870..79d198c 100644 --- a/web/cobbler_web/templates/paginate.tmpl +++ b/web/cobbler_web/templates/paginate.tmpl @@ -1,20 +1,32 @@ {% if pageinfo %} +<script type="text/javascript"> +// All of these functions depend on the form "action" defined in generic_list +function change_limit(value) { + document.forms["action"].action = '/cobbler_web/{{ what }}/modifylist/limit/' + value + document.forms["action"].submit(); +} +function change_page(value) { + document.forms["action"].action = '/cobbler_web/{{ what }}/modifylist/page/' + value + document.forms["action"].submit(); +} +</script> + <li class="paginate"><label for="limit">Items/page:</label> - <select name="limit" id="limit" onchange="javascript:location='/cobbler_web/{{ what }}/modifylist/limit/'+this.value"> + <select name="limit" id="limit" onchange="javascript:change_limit(this.value)"> {% for p in pageinfo.items_per_page_list %} <option value="{{ p }}"{% ifequal pageinfo.items_per_page p %} selected="selected"{% endifequal %}>{{ p }}</option> {% endfor %} </select> {% ifnotequal pageinfo.prev_page "~" %} - <a href="/cobbler_web/{{ what }}/modifylist/page/{{ pageinfo.prev_page }}"><span class="lpointers">⇐</span></a> + <a href="javascript:change_page('{{ pageinfo.prev_page }}')"><span class="lpointers">⇐</span></a> {% else %} <span class="lpointers">⇐</span> {% endifnotequal %} - <select name="page" id="page" onchange="javascript:location='/cobbler_web/{{ what }}/modifylist/page/'+this.value"> + <select name="page" id="page" onchange="javascript:change_page(this.value)"> {% for p in pageinfo.pages %}<option value="{{ p }}"{% ifequal pageinfo.page p %} selected="selected"{% endifequal %}>Page {{ p }}</option>{% endfor %} </select> {% ifnotequal pageinfo.next_page "~" %} - <a href="/cobbler_web/{{ what }}/modifylist/page/{{ pageinfo.next_page }}"><span class="rpointers">⇒</span></a> + <a href="javascript:change_page('{{ pageinfo.next_page }}')"><span class="rpointers">⇒</span></a> {% else %} <span class="rpointers">⇒</span> {% endifnotequal %} diff --git a/web/cobbler_web/views.py b/web/cobbler_web/views.py index d2f3efe..00abb6a 100644 --- a/web/cobbler_web/views.py +++ b/web/cobbler_web/views.py @@ -4,6 +4,7 @@ from django.template import RequestContext from django.http import HttpResponse from django.http import HttpResponseRedirect from django.shortcuts import render_to_response +from django.views.decorators.http import require_POST try: from django.views.decorators.csrf import csrf_protect @@ -366,7 +367,8 @@ def genlist(request, what, page=None): })) return HttpResponse(html) - +@require_POST +@csrf_protect def modify_list(request, what, pref, value=None): """ This function is used in the generic list view @@ -433,6 +435,8 @@ def modify_list(request, what, pref, value=None): # ====================================================================== +@require_POST +@csrf_protect def generic_rename(request, what, obj_name=None, obj_newname=None): """ @@ -453,6 +457,8 @@ def generic_rename(request, what, obj_name=None, obj_newname=None): # ====================================================================== +@require_POST +@csrf_protect def generic_copy(request, what, obj_name=None, obj_newname=None): """ Copies an object. @@ -472,6 +478,8 @@ def generic_copy(request, what, obj_name=None, obj_newname=None): # ====================================================================== +@require_POST +@csrf_protect def generic_delete(request, what, obj_name=None): """ Deletes an object. @@ -491,6 +499,8 @@ def generic_delete(request, what, obj_name=None): # ====================================================================== +@require_POST +@csrf_protect def generic_domulti(request, what, multi_mode=None, multi_arg=None): """ @@ -588,6 +598,8 @@ def check(request): # ====================================================================== +@require_POST +@csrf_protect def buildiso(request): if not test_user_authenticated(request): return login(request, next="/cobbler_web/buildiso") remote.background_buildiso({},request.session['token']) @@ -595,6 +607,8 @@ def buildiso(request): # ====================================================================== +@require_POST +@csrf_protect def import_run(request): if not test_user_authenticated(request): return login(request, next="/cobbler_web/import/prompt") options = { @@ -667,6 +681,7 @@ def ksfile_edit(request, ksfile_name=None, editmode='edit'): # ====================================================================== +@require_POST @csrf_protect def ksfile_save(request): """ @@ -752,6 +767,7 @@ def snippet_edit(request, snippet_name=None, editmode='edit'): # ====================================================================== +@require_POST @csrf_protect def snippet_save(request): """ @@ -872,6 +888,8 @@ def random_mac(request, virttype="xenpv"): # ====================================================================== +@require_POST +@csrf_protect def sync(request): """ Runs 'cobbler sync' from the API when the user presses the sync button. @@ -882,6 +900,8 @@ def sync(request): # ====================================================================== +@require_POST +@csrf_protect def reposync(request): """ Syncs all repos that are configured to be synced. @@ -892,6 +912,8 @@ def reposync(request): # ====================================================================== +@require_POST +@csrf_protect def hardlink(request): """ Hardlinks files between repos and install trees to save space. @@ -902,6 +924,8 @@ def hardlink(request): # ====================================================================== +@require_POST +@csrf_protect def replicate(request): """ Replicate configuration from the central cobbler server, configured @@ -1022,6 +1046,7 @@ def generic_edit(request, what=None, obj_name=None, editmode="new"): # ====================================================================== +@require_POST @csrf_protect def generic_save(request,what): @@ -1175,6 +1200,7 @@ def test_user_authenticated(request): def login(request, next=None): return render_to_response('login.tmpl', RequestContext(request,{'next':next})) +@require_POST @csrf_protect def do_login(request): global remote @@ -1205,6 +1231,7 @@ def do_login(request): else: return login(request,nextsite) +@require_POST @csrf_protect def do_logout(request): request.session['username'] = ""
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor