views:

75

answers:

3

My clients use one of the following when they sign up for my application:

  1. Foo API (requires a "auth_key", "password", "email")
  2. Acme API (requires a "secure_code", "username", "password")
  3. Bar API (requires a "xyz_code", "pass_key")

(fake names, and about 15 more omitted for simplicity)

I would prefer not to have 10-15 tables in my database just for the different API integration options I offer (particularly when they're all for the same thing and they just choose 1 from the whole list).

My solution was this:

Make a api_configuration table with a column called api_name which holds a code for a specific API (e.g. "foo_api")

Make a table called credentials_attribute with a foreign key back to api_configuration, a column called name, and a column called value.

Then I build a UI for choosing an API. If they choose Acme API, it'll ask for a "secure_code", "username", and "password", and create a row in credentials_attribute for each of the name/value pairs.

On my ORM model for api_configuration I can make a method for looking up credentials_attribute values based on the current api_name.

Does this solution feel right, or is there another way you would do it, if you had to model a solution for this problem? Please explain your rationale as well (ie, better for performance, etc)

A: 

If I understand you correctly, all these properties in the different APIs are conceptually tuples of the same 3 thing, under different names, right?

Your description is from the DB point of view - I will describe what I would do on the domain side (which may be directly mappable to your schema).

I would create a single class, e.g. UserLogin, with the 3 properties mentioned above (e.g. authenticationCode, userId, password), and a mapping of API names/codes to GUI property names. When the user selects the preferred API, I can display fields with the appropriate names on the GUI, and fill the values to the corresponding properties of UserLogin. If needed, UserLogin can also store the preferred login API for that user. This way UserLogin is mapped to a single table on the DB side. I may use another table to configure the property names for each known API.

Péter Török
@Péter - no to the first question, I edited my question to be more explicit about the varying nature of each API's authentication parameters. Some have 2, 3, and one even has 4.
orokusaki
Péter Török
@Péter - -I'm just curious what the reasoning is behind recommending that. I can think of a few reasons, but I want to hear yours.
orokusaki
@orokusaki, I prefer working with objects of real classes instead of collections of name-value pairs, whenever I can. I am a lazy OO programmer, that's all :-)
Péter Török
+1  A: 

I would probably prefer to do this with a single table itself

Have a single UserAuthentication table with columns like IdentificationKey, AuthenticationCriteria1, AuthenticationCriteria2 and so on...

Number of AuthenticationCriteriaX columns = maximum number of criteria that any API will have. I am assuming it will be something reasonable like maybe 5 at the most but anything upto 15-20 is actually still is a pretty small table.

UserAuthentication table also has a api_key column which is a foreign key from an MASTER_API table which is the list of all supported API's

As for the UI part of the problem, i.e what label to show the user for any field from the UserAuthentication table, i think that is just a UI concern and as such you should just have the mapping specific to each api somewhere in your UI layer. The api_key column can be used for the translation as needed. The DB does not necessarily need to know those details, IMO.

InSane
@InSane - Why do you recommend this flattened design over another? I'm trying to understand the different rationales that DBAs and software architects use when deciding these things.
orokusaki
I agree with @InSane - i'd rather have one table. Having 15 tables with the same end result is silly. Is it more flexible? Yes. But sometimes you need to weigh up flexibility with overengineering. You could always store the "main stuff" (those three fields) in a single table for all API's, then have a FK to a "meta-data-type" table, which can have extra stuff.
RPM1984
@orokusaki - my rationale for preferring a single table is because logically - to me atleast - what you have is data used to do the same thing. - so having separate tables for it or even having a horizontal table is just unnecessarily complicating it. This kind of design allows me to just get one record for a user and gives all this authentication criteria to me in one go. Even from a growth perspective, if u make IdentificationKey + api_key as a combined key, you even easily tackle your future issue of supporting multiple api's for the same user as well.
InSane
@orokusaki - To summarize, the implementation is just simpler this way. Having multiple tables / horizontal table doesnt seem to provide any additional benefit over his approach so its doesnt seeem to be worth the additional effort
InSane
Yep. I Agree 100%.
RPM1984
+1  A: 

If I understand the case correctly, it looks like yet another case of the gen-spec design pattern. Look up "generalization specialization relational modeling".

Tutorials on object modeling usually cover gen-spec, but tutorials on relational modeling often do not. But it's well understood, and there are some excellent articles on the web.

Walter Mitty