11

I'm about to put a beta version of the site I'm working on up on the web. It needs to have a beta code to restrict access. The site is written in django.

I don't want to change the fundamental Auth system to accommodate a beta code, and I don't care particularly that the security of the beta code is iron-clad, just that it's a significant stumbling block.

How should I do this? It's a fairly large project, so adding code to every view is far from ideal.


That solution works well. The Middleware Class I ended up with this this:

from django.http import HttpResponseRedirect

class BetaMiddleware(object):
    """
    Require beta code session key in order to view any page.
    """
    def process_request(self, request):
        if request.path != '/beta/' and not request.session.get('in_beta'):
            return HttpResponseRedirect('%s?next=%s' % ('/beta/', request.path))
tshepang
  • 12,111
  • 21
  • 91
  • 136
defrex
  • 15,735
  • 7
  • 34
  • 45

7 Answers7

21

Start with this Django snippet, but modify it to check request.session['has_beta_access']. If they don't have it, then have it return a redirect to a "enter beta code" page that, when posted to with the right code, sets that session variable to True.

Making it a public beta then just consists of removing that middleware from your MIDDLEWARE_CLASSES setting.

AdamKG
  • 13,678
  • 3
  • 38
  • 46
4

You can probably restrict access to the entire site via apache with htaccess, taking the problem out of the django's project space entirely.

rcreswick
  • 16,483
  • 15
  • 59
  • 70
2

Do what StackOverflow did.

They had a simple email/password form. It had a single hard-coded password (falkensmaze). When the user gets the password right set a cookie. eg. auth=1

Don't worry about it being unsecure. Who care's if someone hacks into the beta?

Apache/htaccess is also a nice and simple solution.

andyuk
  • 38,118
  • 16
  • 52
  • 52
  • This implies that I have to check for the existence of a cookie in every view. I'd rather avoid adding code to every view. Is there a way to check for a cookie globally in django? – defrex Sep 19 '08 at 21:59
  • @defrex yes with a middleware. See AdamKG answer. – imns Dec 29 '12 at 19:58
0

You should be able to add @login_required decorators across the board and be done with it. Unless you have a boat-load of view functions, it shouldn't be too horrible.

S.Lott
  • 384,516
  • 81
  • 508
  • 779
  • The problem with this is that then whoever is trying to get access is taken to the login page, rather then to a page for entering a beta code. The login page has all the menus and ui around it. I'd like to keep that stuff private for now. – defrex Sep 19 '08 at 21:35
  • @defrex, make your own login_required decorator that wraps Django's built-in version. When you go live, just replace it with Django's entirely. – John Millikin Sep 19 '08 at 22:00
0

I'm not sure what version of the Pinax code you're using, but they've built in the ability to close the site off for a private beta so you don't need to do much work yourself.

The link to the specific project template for a private beta site is here: http://github.com/pinax/pinax/tree/3ad73d1ba44f37365333bae17b507668b0eb7e16/pinax/projects/private_beta_project although I think they might have since added that functionality to all the project templates.

John Debs
  • 3,714
  • 2
  • 25
  • 35
  • A really old version of pinax. The question was asked in Sept, 08. It's a good point though, so I removed the reference to pinax out of the question so people don't get misled. – defrex Aug 10 '09 at 18:30
0

Great snippet but it resulted lots of problems for me related OpenId sessions. So I end up relying on Cookies instead of the Session:

class BetaMiddleware(object):
    """
    Require beta code cookie key in order to view any page.
    """
    set_beta = False
    def process_request(self, request):
        referer = request.META.get('HTTP_REFERER', '')

        if request.method == 'GET' and not 'is_in_beta' in request.COOKIES:
            return HttpResponseRedirect('%s?next=%s' % ('/beta/', request.path))

        if request.method == 'POST' and 'pass' in request.POST:
            code = request.POST['pass']

            if code=='beta':
                self.set_beta = True
                return HttpResponseRedirect('%s' % '/')

    def process_response(self, request, response):        

        if self.set_beta is True:
            response.set_cookie('is_in_beta', '1')
        return response

It's not secure but that's enough for me. This also works with just a beta html page.

ercu
  • 2,565
  • 1
  • 16
  • 14
0

use this middleware:

class BetaForm(Form):
    beta_pass = CharField(required=True)

    def clean_beta_pass(self):
        data = self.cleaned_data['beta_pass']
        if data != settings.BETA_PASS:
            raise forms.ValidationError("Invalid Beta pass!")
        return data


class BetaView(FormView):
    form_class = BetaForm
    template_name = "beta.html"

    def form_valid(self, form):
        response = HttpResponseRedirect(self.request.GET.get("next", "/"))
        response.set_cookie(settings.BETA_PASS, '')
        return response


def beta_middleware(get_response):
    def middleware(request):

        if request.path == reverse("beta"):
            return get_response(request)
        else:
            if settings.BETA_PASS in request.COOKIES:
                return get_response(request)
            else:
                return HttpResponseRedirect(
                    '%s?%s' % (reverse("beta"), urlencode({"next": request.get_full_path()})))
    return middleware

this template:

<!doctype html>
<title>Welcome to the beta!</title>
<style>
  body { text-align: center; padding: 150px; }
  h1 { font-size: 50px; }
  body { font: 20px Helvetica, sans-serif; color: #333; }
  article { display: block; text-align: left; width: 650px; margin: 0 auto; }
  a { color: #dc8100; text-decoration: none; }
  a:hover { color: #333; text-decoration: none; }
</style>

<article>

    <h1>>Welcome to the beta lucky user!</h1>
    <div>
        <form method="POST">
            {% csrf_token %}
            {{form}}
            <input type="submit">
        </form>
    </div>
</article>

this settings:

BETA_PASS="beta"

this path:

path("beta",BetaView.as_view(),name="beta"),
user1387219
  • 465
  • 4
  • 18