The password-generating program that I created, Oplop, has now hit version 0.3. The biggest change since the last version is that the whole idea of having various restriction filters placed on your eventual password is now gone. From practical experience it turned out that most sites are happy with what Oplop generates, otherwise sometimes there is demand for making sure there is a digit.
So now a digit is always included in any generated password. Simplifies the UI immensely. Now all one needs to do is input a label and a password to get their generated label password back; no more checkboxes!
And thanks to the power of App Engine, Oplop is online. I kept needing passwords at work and since I have not gotten around to writing an iPhone or Nokia S60 app, I decided I needed something. Well, since I am interning with the App Engine team and I already had Oplop implemented in Python, I figured I would just do an App engine application where I skip using Django and just do a bare-metal web app.
Now as of right now the online solution is not ideal. While I use HTTPS for everything to prevent online snooping, there is no protection from someone peering over your shoulder to notice the password that is shown on the screen. Besides, if I didn't have JavaScript so much or had my housemate mention he has had issues at his work with differing MD5 implementations, I could have a JS version that does everything client-side.
But I would like to harness the ability to store info on a per-user level for this web app. The thing holding me up is deciding how much to store. If I store labels along with any caveats for the label password for that label, then I don't have to think about having that stuff written down anywhere. Plus I could have completion suggestions for someone who is logged in. And if there is a way for someone to be logged into their Google account from an application then the label completion could extend to even application implementations of Oplop.
The security implication, though, is that if someone gets a hold of someone's label list, will that provide too much information? Chances are you could figure out where someone had an account from the label name (e.g. it's obvious what account the "amazon.com" label is for), but the labels are worthless without the master password. But if you got a hold of the master password, your accounts could all be compromised (still requires knowing the username for each account).
If I store just a list of sites where one has labels along with any password caveats for the site, then I could have a bookmarklet that tells you what the caveat is. You then still have to remember your label for the site, but at least that bit of information would not be available to anyone who manages to get a hold of your account information. But it does guarantee people will know where you have an account.
Storing both the label and corresponding site for the label gives you the perks of both, but with the combined drawbacks. I have not decided if any of these potential security issues are worth the benefits they bring at the moment.
A place for me to babble on about Python development, Python itself, and coding in general. The title is inspired by some knights who enjoy a good shrubbery.
Showing posts with label app engine. Show all posts
Showing posts with label app engine. Show all posts
2008-11-08
2008-10-15
More fiddling with Django and Google App Engine
After having done a static page with some jQuery for my home page, and then a very simple web app to manage the list of TV shows I watch (so I know how far behind I am in watching them), I figured the next web app should be slightly more complicated.
So I tackled lists in a generic fashion. I don't know where I get it, but I tend to make lists of stuff. Nothing significant, mind you, but I do have several lists that I am constantly updating in my head on various topics, such as stuff I want to do in Vancouver before I graduate and leave and what I would do if I was given $20,000,000.
And so I tried to come up with a generic web app for unsorted and definition lists. Now when I have done my web apps I have tried to stick to the DRY principle as much as possible. This meant that I only needed to define a single list model as no matter what kind of list you had, a list is a list at its most basic level. But what type of list does control what information you want per entry of that list. That means two models for list entries. That's slightly tricky since list entries need a reference to the list they are a part of, and thus leads to two different reference sets under Google App Engine's datastore model.
So I did what any programmer would do in this situation and I abstracted with a dash of information upfront. When a list is created, I specify what kind of list it is since that does not fluctuate. Based on that information, various methods defined on the list model pull list entries from the proper reference set (e.g. if a list is defined to be a unordered list it has the items() method return from the unordereditem_set attribute on the list model). And I continued to abstract everything I needed on the list model to the point that I use the list model to get the list entry class that is appropriate. I basically work blindly in the code as to what list entry model is being used.
The other thing I did was define only a single management view for lists and list entries. This means that all creation and editing of lists goes to a single view (same goes for list entries). This allowed me to control more based on URLs than I do from my TV series web app. It does lead to more branching within the single management view, but it keeps things simpler for me as any commonality is easily handled. Besides, I prefer to have a single method that handles a single class of issues based on its arguments more than defining a bunch of custom methods.
And Django deserves credit for letting the views be simplified like this. Being able to generate the form to use is generic enough that I was able to use my abstraction setup for the list types to not have to care what model form I was using; I just used ``list.item_class().form`` and just didn't care.
And the last improvment I did was memcache the hell out of my entire site. I defined a subclass of the Client class provided by App Engine. It allows me to take my old memoize decorator and have it generate the key to use automatically based on the function being decorated and a common prefix. I even went as far as to provide a key argument that is a callable that can return parts to use in the key so that it can be dynamic based on the arguments to the decorated function (which is apparently a complaint someone had with my simple decorator I posted at the App Engine cookbook site). Although, in hindsight, it might be simpler and be a stronger common-case to do it based on the URL instead (sans GET arguments) for the common case instead of the view function's name. Then using Django's reverse() would be all that is needed to figure out what to delete from the memcache. Ugh, why didn't I think of this simplification last night?
When I add or edit something now I just delete the proper entry in the memcache. And if someone is logged in as an admin then no caching is used since admin-specific stuff is put in the HTML.
Once again, I am a happy camper when it comes to App Engine and Django. And once the Django helper for App Engine releases a 1.0 version and I can run that and Django from a zip file, I will a REALLY happy camper. I think the only thing really missing that I wish I had was a slug property for models so that I didn't have to specify them myself by hand. That, and a method I knew I could override that was always called upon commitment to the datastore.
So I tackled lists in a generic fashion. I don't know where I get it, but I tend to make lists of stuff. Nothing significant, mind you, but I do have several lists that I am constantly updating in my head on various topics, such as stuff I want to do in Vancouver before I graduate and leave and what I would do if I was given $20,000,000.
And so I tried to come up with a generic web app for unsorted and definition lists. Now when I have done my web apps I have tried to stick to the DRY principle as much as possible. This meant that I only needed to define a single list model as no matter what kind of list you had, a list is a list at its most basic level. But what type of list does control what information you want per entry of that list. That means two models for list entries. That's slightly tricky since list entries need a reference to the list they are a part of, and thus leads to two different reference sets under Google App Engine's datastore model.
So I did what any programmer would do in this situation and I abstracted with a dash of information upfront. When a list is created, I specify what kind of list it is since that does not fluctuate. Based on that information, various methods defined on the list model pull list entries from the proper reference set (e.g. if a list is defined to be a unordered list it has the items() method return from the unordereditem_set attribute on the list model). And I continued to abstract everything I needed on the list model to the point that I use the list model to get the list entry class that is appropriate. I basically work blindly in the code as to what list entry model is being used.
The other thing I did was define only a single management view for lists and list entries. This means that all creation and editing of lists goes to a single view (same goes for list entries). This allowed me to control more based on URLs than I do from my TV series web app. It does lead to more branching within the single management view, but it keeps things simpler for me as any commonality is easily handled. Besides, I prefer to have a single method that handles a single class of issues based on its arguments more than defining a bunch of custom methods.
And Django deserves credit for letting the views be simplified like this. Being able to generate the form to use is generic enough that I was able to use my abstraction setup for the list types to not have to care what model form I was using; I just used ``list.item_class().form`` and just didn't care.
And the last improvment I did was memcache the hell out of my entire site. I defined a subclass of the Client class provided by App Engine. It allows me to take my old memoize decorator and have it generate the key to use automatically based on the function being decorated and a common prefix. I even went as far as to provide a key argument that is a callable that can return parts to use in the key so that it can be dynamic based on the arguments to the decorated function (which is apparently a complaint someone had with my simple decorator I posted at the App Engine cookbook site). Although, in hindsight, it might be simpler and be a stronger common-case to do it based on the URL instead (sans GET arguments) for the common case instead of the view function's name. Then using Django's reverse() would be all that is needed to figure out what to delete from the memcache. Ugh, why didn't I think of this simplification last night?
When I add or edit something now I just delete the proper entry in the memcache. And if someone is logged in as an admin then no caching is used since admin-specific stuff is put in the HTML.
Once again, I am a happy camper when it comes to App Engine and Django. And once the Django helper for App Engine releases a 1.0 version and I can run that and Django from a zip file, I will a REALLY happy camper. I think the only thing really missing that I wish I had was a slug property for models so that I didn't have to specify them myself by hand. That, and a method I knew I could override that was always called upon commitment to the datastore.
2008-09-20
Initial impressions of Google App Engine
Now that I have a *really* basic web app up for myself, I figured I would give my initial impressions of GAE.
So deploying on GAE is dead-simple. It is rather nice how easy it is to launch the development server locally, poke around, and then deploy to a live site. And all without having to make sure your web server stays up. And having Django included is handy as it lets you get up and going rather quickly. And using the Google App Engine Helper for Django really makes getting up and going really easy. And the library has been good along with its docs. And the articles have been handy. And with the docs easy to download and the GoogleAppEngineLauncher on OS X, the whole experience has been smooth and professional.
But then you run into the problem of the Google App Engine Helper for Django being developed outside of GAE itself (at least using the packaged version available for download). For instance, right now I can't run ``python manage.py test`` as the newest version of GAE verifies that environment variables are set up as expected. Unfortunately, if you use Django's test client, it skips setting that up and thus the tests error out in GAE itself. So as of right now I can't run my unit tests. Not a big deal as I do interactive testing by hand to make sure stuff works, but I am still a big enough fan of unit testing that I would like an automated way to make sure any site-wide changes I make don't break a single page without having to check manually and going through localhost. Hopefully this will be rectified once the Helper releases a new version that support Django 1.0 and I can then just move over to Django 1.0 for everything (I might not wait and run out of svn if it takes too long for the Helper to get an official release or use something like Twill to do automated tests for actual pages).
And I wish there were more unit test helpers in the GAE library. For instance, there is no programmatic way to log in. Yes, the dev server gives you a fake page to use that you can use, but I want a way to do it from code so I could log in through my unit tests.
Overall I am still very happy. Short of the testing issues everything has gone very smoothly. Considering GAE is a preview release and all the Django stuff is pre-1.0 I have faith the kinks I have run up against will get ironed out now that Django 1.0 is out and everyone has a stable target to aim for. And I probably should just bit the bullet and learn Twill or Selenium for page verification testing (I prefer the former since I have no issue emailing TIP or Titus for help =).
So deploying on GAE is dead-simple. It is rather nice how easy it is to launch the development server locally, poke around, and then deploy to a live site. And all without having to make sure your web server stays up. And having Django included is handy as it lets you get up and going rather quickly. And using the Google App Engine Helper for Django really makes getting up and going really easy. And the library has been good along with its docs. And the articles have been handy. And with the docs easy to download and the GoogleAppEngineLauncher on OS X, the whole experience has been smooth and professional.
But then you run into the problem of the Google App Engine Helper for Django being developed outside of GAE itself (at least using the packaged version available for download). For instance, right now I can't run ``python manage.py test`` as the newest version of GAE verifies that environment variables are set up as expected. Unfortunately, if you use Django's test client, it skips setting that up and thus the tests error out in GAE itself. So as of right now I can't run my unit tests. Not a big deal as I do interactive testing by hand to make sure stuff works, but I am still a big enough fan of unit testing that I would like an automated way to make sure any site-wide changes I make don't break a single page without having to check manually and going through localhost. Hopefully this will be rectified once the Helper releases a new version that support Django 1.0 and I can then just move over to Django 1.0 for everything (I might not wait and run out of svn if it takes too long for the Helper to get an official release or use something like Twill to do automated tests for actual pages).
And I wish there were more unit test helpers in the GAE library. For instance, there is no programmatic way to log in. Yes, the dev server gives you a fake page to use that you can use, but I want a way to do it from code so I could log in through my unit tests.
Overall I am still very happy. Short of the testing issues everything has gone very smoothly. Considering GAE is a preview release and all the Django stuff is pre-1.0 I have faith the kinks I have run up against will get ironed out now that Django 1.0 is out and everyone has a stable target to aim for. And I probably should just bit the bullet and learn Twill or Selenium for page verification testing (I prefer the former since I have no issue emailing TIP or Titus for help =).
2008-09-17
The memcache API in GAE is neat
With my web site being my first real web site in several years (last one used PHP to generate static HTML and I devised my own way of not hard-coding URLs), I finally learning about some stuff that I am sure people have been using for a while, such as memcached.
Google App Engine provides an API that is apparently similar to the one provided by memcached. They have aptly enough named the module memcache. I decided to use it where I could so as to learn about it (my web site doesn't get enough traffic to really warrant bothering with memcache).
Once I realized the best way to use the memcache is to factor out the part of a view that generates consistent content (e.g. what objects to view, but not necessarily an entire page if it has dynamic stuff that really needs to be generated every time accurately), I threw together a memcache decorator that handles checking the memcache and either returning what is there or calling the content creating function and then setting what it returns in the memcache. I also set the time to 1 second if I am debugging so as to not constantly hit the memcache when I am making changes quickly to the code.
Google App Engine provides an API that is apparently similar to the one provided by memcached. They have aptly enough named the module memcache. I decided to use it where I could so as to learn about it (my web site doesn't get enough traffic to really warrant bothering with memcache).
Once I realized the best way to use the memcache is to factor out the part of a view that generates consistent content (e.g. what objects to view, but not necessarily an entire page if it has dynamic stuff that really needs to be generated every time accurately), I threw together a memcache decorator that handles checking the memcache and either returning what is there or calling the content creating function and then setting what it returns in the memcache. I also set the time to 1 second if I am debugging so as to not constantly hit the memcache when I am making changes quickly to the code.
2008-09-14
First dynamic section to my web site is up
I finally got around to constructing the first dynamic part of my web site: a system for me to record what television shows I have watched from their pilot episode. While not designed to be a web app used by the world, I am able to add end edit any series listed. And the list that is there is not exhaustive; it's mostly so I know what shows I am behind in watching.
I started with this app because it was simple. The data schema has no relations so I didn't have to worry about doing any many-to-one relations (but another app I have planned will). Probably the trickiest part was setting a 'sort_on' field for TV titles that start with an article ('A', 'An', and 'The'). I wanted that to be based on the specified title for the series, so I overloaded the __init__() method for the model and set it manually. With a subsequent super() call the model class doesn't know that a required value was computed on the fly.
I did go back on forth on whether to use None values for season/episode to represent that I have watched an entire series, but decided against it. I figured it was better to be able to require a value for those attributes and just have an explicit 'completed' boolean attribute.
And I am not happy with how I am currently handling my templates. I am having a tough time deciding how much should be passed into a template through a view, what should be set through a block in a template, and what should just be a a global variable/filter. A good example of this stuff from Google App Engine's Users API. There are functions to specify login and logout URLs along with functions that return what user is logged in and whether they are an admin.
Right now I explicitly set 'user_is_admin' for my templates through the view to decide if a page should display admin-specific info (e.g. edit links by the names of the TV series). But since what user is logged in and whether they are an admin is a project-side thing I feel like writing a Django context processor to handle this. I could then provide a filter that generated login/logout URLs with default to the current URL (although that would probably require a RequestContext to work). Basically I am still feeling around to find out what the right abstraction level is for templates.
I started with this app because it was simple. The data schema has no relations so I didn't have to worry about doing any many-to-one relations (but another app I have planned will). Probably the trickiest part was setting a 'sort_on' field for TV titles that start with an article ('A', 'An', and 'The'). I wanted that to be based on the specified title for the series, so I overloaded the __init__() method for the model and set it manually. With a subsequent super() call the model class doesn't know that a required value was computed on the fly.
I did go back on forth on whether to use None values for season/episode to represent that I have watched an entire series, but decided against it. I figured it was better to be able to require a value for those attributes and just have an explicit 'completed' boolean attribute.
And I am not happy with how I am currently handling my templates. I am having a tough time deciding how much should be passed into a template through a view, what should be set through a block in a template, and what should just be a a global variable/filter. A good example of this stuff from Google App Engine's Users API. There are functions to specify login and logout URLs along with functions that return what user is logged in and whether they are an admin.
Right now I explicitly set 'user_is_admin' for my templates through the view to decide if a page should display admin-specific info (e.g. edit links by the names of the TV series). But since what user is logged in and whether they are an admin is a project-side thing I feel like writing a Django context processor to handle this. I could then provide a filter that generated login/logout URLs with default to the current URL (although that would probably require a RequestContext to work). Basically I am still feeling around to find out what the right abstraction level is for templates.
2008-09-07
Baby steps with Google App Engine
You know that mythical personal web site I have been talking about for months? Well, today I finally started work on actually implementing www.DrBrett.ca (warning: it's ugly until I get around to doing some CSS for it). I figured I might as well blog about how this entire process goes to help others out and to keep track of stuff.
First of all, I am deploying on Google App Engine under Django. I using GAE as I am not a sysadmin and I do not want to have to worry about keeping my web server up any more. There is also the side benefit of preparing me for my internship with the team come November (I don't know what I am working on so don't bother asking or making requests for features). I am using Django because I love the community that has built up around the project. Plus the team leads are all really nice fellows.
Because I am using Django under GAE, I watched Guido's Google I/O talk on Django and GAE. That made me realize I really wanted to use the GAE Helper for Django. Knowing all of this I downloaded the OS X SDK, the docs, the GAE Helper for Django, and got to it.
The GAE Helper for Django makes starting a Django project REALLY simple. Because the Helper doesn't support Django 1.0 from the download and I am starting out small, I just used the version of Django included with GAE. I then went about to creating a dumb little app that does nothing more than directly return a rendered template for my index.html so that I can play with the site look to start.
I also registered my domain with Google Apps. That allowed me to deploy my app on my domain. The only drawback is that GAE doesn't support a naked domain (e.g., drbrett.ca), so I had to explicitly set my site to www.drbrett.ca. Not a huge deal, but still, it would be nice to be able to forward from the naked domain to www.drbrett.ca (my DNS host service doesn't seem to have the support itself).
At the moment I have nothing more than a Django site with a single app that does nothing more than
At this point my plan is to use the site for content that I want to have written down somewhere and that I don't have any problems sharing publicly. I don't expect the site to be of any huge interest to most folks, but I am looking forward to learning how to do a proper web app.
Next step, figuring out how to do unit tests before I move on to something that is in any way complicated.
First of all, I am deploying on Google App Engine under Django. I using GAE as I am not a sysadmin and I do not want to have to worry about keeping my web server up any more. There is also the side benefit of preparing me for my internship with the team come November (I don't know what I am working on so don't bother asking or making requests for features). I am using Django because I love the community that has built up around the project. Plus the team leads are all really nice fellows.
Because I am using Django under GAE, I watched Guido's Google I/O talk on Django and GAE. That made me realize I really wanted to use the GAE Helper for Django. Knowing all of this I downloaded the OS X SDK, the docs, the GAE Helper for Django, and got to it.
The GAE Helper for Django makes starting a Django project REALLY simple. Because the Helper doesn't support Django 1.0 from the download and I am starting out small, I just used the version of Django included with GAE. I then went about to creating a dumb little app that does nothing more than directly return a rendered template for my index.html so that I can play with the site look to start.
I also registered my domain with Google Apps. That allowed me to deploy my app on my domain. The only drawback is that GAE doesn't support a naked domain (e.g., drbrett.ca), so I had to explicitly set my site to www.drbrett.ca. Not a huge deal, but still, it would be nice to be able to forward from the naked domain to www.drbrett.ca (my DNS host service doesn't seem to have the support itself).
At the moment I have nothing more than a Django site with a single app that does nothing more than
return render_to_response("home.html") for my index page, that's HTML 4.01 Strict compatible and is under revision control with Hg. But it still feels good to have the darn thing moving forward.At this point my plan is to use the site for content that I want to have written down somewhere and that I don't have any problems sharing publicly. I don't expect the site to be of any huge interest to most folks, but I am looking forward to learning how to do a proper web app.
Next step, figuring out how to do unit tests before I move on to something that is in any way complicated.
Subscribe to:
Posts (Atom)