Postgres + Tests + Permissions = Confusion

Hi,

I'm trying PostgreSQL for the first time and writing a Rails app for
the first time in a long time.

I have PostgreSQL installed on my Mac with owner user "postgres". The
password for this user on my Mac is also "postgres".

Working as this postgres user on my Mac, I made a database called
foo_test and granted all permissions to db user "dev" with password
"pass".

When I work on my Rails app I am Mac user "peter". In My rails app
database.yml file I have

test:
  adapter: postgresql
  database: foo_test
  username: dev
  password: pass

When I run "rake" I see

dropdb: database removal failed: ERROR: must be owner of database
foo_test
createdb: database creation failed: ERROR: permission denied to
create database

If I change my database.yml file to the following then all seems to
work well.

test:
  adapter: postgresql
  database: foo_test
  username: postgres
  password: postgres

Who is getting denied dropping db permission? Mac user "peter" or is
it db user "dev"?

Is it normal that the database is completely dropped when starting a
test. I thought it used to be that all the tables were just dropped.
Bad memory? I never had this problem with MySQL.

Is there any way that I can set my test database user/pass to
something other than postgres/postgres. It doesn't seem very portable
if another developer has their PostgreSQL installed under a different
system user/pass combination.

Any enlightenment greatly appreciated!

Thanks,
Peter

Working as this postgres user on my Mac, I made a database called
foo_test and granted all permissions to db user "dev" with password
"pass".

Actually you didn't give them all permissions or it would have worked.
Maybe all the ones you know about, but not all:) The postgresql docs
are actually very good and it would pay to read up on database roles
and privileges so you have the basics.

Who is getting denied dropping db permission? Mac user "peter" or is
it db user "dev"?

user dev, because dev is not the owner and also not given the
superuser role. One of those is required to drop databases.

Is there any way that I can set my test database user/pass to
something other than postgres/postgres. It doesn't seem very portable
if another developer has their PostgreSQL installed under a different
system user/pass combination.

They won't unless they changed the default user, and if they do that
it's on their heads, since it takes a bit of effort with no good
reason that I can think of. It's probably a good idea to create
another user for your databases though. Just create a user and give
them the createdb role. When they create databases they will have
ownership so they can drop them also.

And don't give up on Postgres, you won't ever look back at mysql after
using it a while, and the mailing lists have some very sharp people on
them if you ever need to tune your database or run into problems.
Every time I do work for people using mysql I have to keep my mouth
shut and stop myself from saying 'well if you used postgresql you
could do this..'

Chris

Hi Chris,

Thanks for the info. I'll look into the createdb role.

PostgreSQL users keep saying things about it being better than MySQL
but I don't know what specifically is better for a Rails app. Perhaps
I'll find out.

Peter

One of the biggest pluses is the help that's available for free when
you need to tune your database or find out how to optimize your
queries. The level of clue on the mailing lists is just so much
higher in general. There is a much higher standard for keeping your
data safe imo. Documentation is also very good. Lots of the advanced
stuff you might never need, but when you do it's there and has
probably been there for years.

Chris

...

When I work on my Rails app I am Mac user "peter". In My rails app
database.yml file I have

test:
  adapter: postgresql
  database: foo_test
  username: dev
  password: pass

When I run "rake" I see

dropdb: database removal failed: ERROR: must be owner of database
foo_test
createdb: database creation failed: ERROR: permission denied to
create database

As has been pointed out by snacktime, you didn't grant createdb
privileges to user dev. You can fix that with the following
command while logged in as postgres:

    alter user dev createdb;

Is it normal that the database is completely dropped when starting a
test. I thought it used to be that all the tables were just dropped.
Bad memory? I never had this problem with MySQL.

For Postgres, the test database is dropped and re-created and then
the schema is cloned from the development database.

Is there any way that I can set my test database user/pass to
something other than postgres/postgres. It doesn't seem very portable
if another developer has their PostgreSQL installed under a different
system user/pass combination.

Yes.

Any enlightenment greatly appreciated!

I take a different approach to database users for my Rails apps. I
submitted this to DHH as a patch but he said that it did not fit in
with the way he wanted to handle databases. I only mention this to
let you know that my approach is NOT the standard Rails way.

I have made a few patches to Rails that allow me to have a separate
development database user and an app database user. When running the
tests, Rails uses the development user to clean out the test database
and clone the development structure. The development user is also
used to load the fixtures and clean up after the tests. During the
tests, the app database user is used. I have also modified the start
up code for testing so that the test database is not dropped and
re-created. It is just emptied and then the development database is
cloned into it. I do this because I don't like granting createdb
privileges to database users other that the superuser. When I create
a database, I make the development user be the owner of the database
so it has all the privileges needed to do anything to the database.

My philosophy about database users is that development users get to
create, alter, drop, tables and indexes and columns but the app user
should only be able to create, read, update, and delete data, not
make any structural updates to the database. Actually, I usually
go farther than that and only grant read access to most tables and
only grant insert, update, and delete access as needed. In my unit
tests, I make sure that the app database user can do everything it
needs to do and that it can not do anything I don't want it to do.
For instance, in an e-commerce app, the Rails app should not be able
to update the catalog of products, only browse it. However, the
app does need to be able to create/update orders. Having a restrictive
database user for the Rails app gives me another layer of protection
against abuse of the web site.

Using Postgres makes my changes relatively easy. It is much harder
to get MySQL to cooperate because of the weird way it handles database
permissions.

Kim