how to prevent access to admin urls in Django? - django

Django gives admin url automatically, such as www.example.com/admin.
I do not want any outside visitors to access this url. This should be accessed only with in the host and allowed IP address.
If I try to access to https://instagram.com/admin/ (which is built using Django),it gives 404 page not Found error
How can I achieve the same behavior?
what is the preferred and right way to do it?
I host my webservice inwebfaction and allowing IP address of host means other webfaction account-holders might be able to access the admin URL which I dont want to. Looking for a neat and simple way
Thanks:
PS: I see a similar question posted here but that is with respect to PHP. I am wondering how can I acheive the same using Django?

One common method, which is advocated by Two Scoops of Django, is to change your admin url. Thus, rather than logging into your admin at www.example.com/admin/, you would log in at www.example.com/supers3cret4dm1n/ or something that you've set. This is likely what Instagram has done in your example.
Example code:
urlpatterns = patterns(''
...
url(r'^supers3cret4dm1n/', include(admin.site.urls)), # Change the pattern to whatever you want here
...
)
Note that this doesn't make it accessible from only one IP address, but it does effectively 'hide' your admin login page.
Another tip is to use the django-admin-honeypot package. This sets up a fake admin page at www.example.com/admin while having your real admin page at another site that you've set. Then, django-admin-honeypot will alert you if anyone tries to hack your admin at the fake admin site.
EDIT:
If you're dead-set on restricting by IP address, here's a SO question and answer showing how to do it with nginx. I imagine it'd be similar with others.

simply you can treat the admin path as a secret, so set it as an environment variable in your system and then retrieve it (good approach if your source code is public).
ADMIN_URL_PATH = os.getenv('DJANGO_ADMIN_PATH')
urlpatterns = [
...
path(ADMIN_URL_PATH, admin.site.urls)
...
]

Related

Django CMS how to use different urls for 2 instances of the same apphook

Following the tutorial of the djangocms documentation, I've created an apphook to allow users to ask for registration to a list of newsletters. Clicking on the page menu goes to the url(r'^$', views.index, name='index') of the hooked application. It works fine.
I would like to create a second page for the newsletters administrator that will use another instance of the same application but using the url(r'^manage/$', views.manage, name='manage') when the page is selected. Is it possible? I don't find how to configure that.
Thanks a lot for any suggestion.
For the lack of a better way, I have usually created another App Hook and pointed it to another view - that way you can have every major part of the app catered for. If it's just two different pages, this may be the simplest solution.
In a page's advanced settings is the application instance name which is there to enable the same apphook to be used on multiple pages. Setting that would get you two instances of the same apphook.
Alternatively, and perhaps more appropriately, you could split your URLs into a separate file for management. Then you could have a NewsletterManagementAppHook which points to that new set of URLs, separate from the frontend URLs for users. That way you can setup another apphook on another page.

How are Django page templates assigned to each page?

I couldn't find this info in the Django docs, but I'm sure it is there, I'm just very new and don't know what terms/etc to search on.
How are Django page templates assigned to each page?
I have a login to a Django site, and also SFTP access to the site. I don't think my Django login is a superuser/full-admin though because the interface seems pretty limited compared to other CMS systems. I can edit pages, posts and the media library, but I don't see anything that says how each page is assigned a template.
For example, I have this file /mysite/templates/pages/index.html
I know that template is being used for the home page because it has all of the content that is specific to the home page on it, and changes I make show up on the home page.
I tried copying that file to test.html, but when I browse to test.html in my browser, I get a 404 error (I also get that error if I go to index.html). So there must be something else that maps a template to a page, but I'll be dambed if I can find it. Will I need more access to the admin area, or can I do something with SFTP? I also have SSH access but wasn't able to follow any of the steps online to create a new superuser account for me, for Django.
Edit: Thanks for both answers, after I work through this I'll accept whichever helped the most. I do not have a views.py file, but I think it might be using an extra module for this routing, I have this in my urls.py file:
urlpatterns = patterns("",
("^admin/", include(admin.site.urls)),
url("^$", "mezzanine.pages.views.page", {"slug": "/"}, name="home"),
("^", include("mezzanine.urls")),
)
Is this "mezzanine" something different which changes the answer (location of views.py or list of views)?
url.py is the file that maps the urls to methods that return rendered templates. In essence you define the url and a method and when someone goes to that url, that method gets called which returns a HTTP response with the rendered template. This map is called urlpatterns. In the following example when someone goes to yourwebsite/blog then in the blog apps, view.py, page method is called, which will use a template and render that with specific information.
urlpatterns = patterns('',
url(r'^blog/$', 'blog.views.page'),
url(r'^blog/page(?P<num>\d+)/$', 'blog.views.page'),
)
Have a look at this link.
https://docs.djangoproject.com/en/dev/topics/http/urls/
Django uses urls.py files to map paths to views. This match is resolved using regular expressions. When a match is found, Django executes the associated view (usually inside views.py). The view is in charge to render the template required for the path (by finding it on the server's hard disk and loading it).
All aforementioned means that there's no direct association between a url path (i.e www.example.com/path/to/page) and a file on the server's hard disk (i.e /server/path/to/page). It's all performed dynamically by Django's engine when a request comes in.
If you want to know which view is gonna be generated for a specific path, follow the regexs at urls.py until you find the path you're looking for. Then open the view for that url and see inside which template it is rendering.
Reading doc's URL Dispatcher is a good point to start learning about this.
Hope this helps!

how can i check that a admin user is logged into django website or not into NGINX

I want to see that admin user is logged in or not into nginx.conf file .
I need this for my specific requirement.
My Try :
I tried to fetch COOKIES into nginx.conf file.
but when admin is logged out so cookies are changed so i am not able figure out that if a admin is logged in or not.
As far as I know this is not possible.
Django uses encrypted cookies by default and stores all data in the session table in the DB (also encrypted). You could check if the user has a cookie set in nginx but you won't be able to verify if that cookie value actually means "Admin" or "random other cookie value".
Also unless you're using custom nginx modules to check the contents of the cookie you run the risk of someone managing to trick nginx into thinking the user is an admin when that is not the case.
I'm not sure what the use case is here but you could try doing something with the django middleware or looking for third party plugins instead of using nginx.
If you want to limit file access to a specific file, e.g. admin-only images/javascript/data files or such you could try the HttpAccessKeyModule for Nginx and just generate a custom 'url' for your admin to access them.
You can also try looking into: http://nginx.org/en/docs/http/ngx_http_auth_request_module.html and see about delegating the check to some part of Django which just returns Yes or No to nginx.
There might be another nginx plugin somewhere which you can add/enable for an admin user from within django. But this requires you to think the other way around. With django telling nginx the user is an admin. Instead of nginx finding it out itself.
Hope this helps you in some way.

Rendering an existing site invite only in Django

For a project I'm working on, we're still undecided whether the site will launch on an invite-only basis, or be open to the general public immediately. Notwithstanding the management of invites, how would one go about to render a public site invite-only in Django?
One way I can come up with is adding #login_required to all views, but that seems to be too labour intensive... In other words, is there a way to restrict the use of the site to those who have login credentials in one swoop?
Thanks in advance!
Have you looked at the privatebeta application (PyPI, GitHub)? It seems like that does what you are looking for. Otherwise you can at least have a look at their middleware component to base your code on.
Perhaps you could use signals to catch people that are not logged in:
http://docs.djangoproject.com/en/dev/ref/signals/#django.core.signals.request_started
Or you could fiddle with the urlpatterns somehow, so that the urlpatterns list only contains the required login stuff when you're not logged in. That would work, right?

User permissions Django for serving media

I want to set up a Django server that allows certain users to access certain media. I'm sure this can't be that hard to do and I'm just being a little bit silly.
For example I want USER1 to be able to access JPEG1, JPEG2 and JPEG3 but not JPEG4, and USER2 to be able to access JPEG3 and JPEG 4.
[I know I should be burnt with fire for using Django to serve up media, but that's what I'm doing at the moment, I'll change it over when I start actually running on gas.]
You can send a file using django by returning the file in the request as shown in Vazquez-Abrams link.
However, you would probably do best by using mod_xsendfile in apache (or similar settings in lighttpd) due to efficiency. Django is not as fast at sending it, one way to do so while keeping the option of using the dev server's static function would be http://pypi.python.org/pypi/django-xsendfile/1.0
As to what user should be able to access what jpeg, you will probably have to implement this yourself. A simple way would be to create an Image model with a many-to-many field to users with access and a function to check if the current user is among those users. Something along the line of:
if image.users_with_access.filter(pk=request.user.id).exists():
return HttpResponse(image.get_file())
With lots of other code of course and only as an example. I actually use a modified mod_xsend in my own project for this very purpose.
You just need to frob the response appropriately.
You can put the media in http://foo.com/media/blah.jpg and set up a media/(?P<file>.*) in urls.py to point to a view blahview that checks the user and their permissions within:
from you_shouldve_made_one_anyways import handler404
def blahview(request,*args,**kwargs):
if cannot_use( request.user, kwargs['username'] ): return handler404(request)
...
Though just to be clear, I do not recommend serving media through Django.