Hi all. These days I've been working with services module for two sites and I had to do several in-depth research of module functionality. Somethings I did not expect, others I assume, my first touch of real implementations for this module (I've been using 6.x branch) has been a little chaotic. So I guess it is time to help. I did start my own and then I was aware about the existing D7 port. I tried to contact to marcingy yesterday, and finally I decided to help on this approach pushed in somehow by Heyrocker and RobLoach on irc today.
During these real life setups of the module(s), the first thing I missed was information about how to call the services, how to configure permissions, and what services should do. Later on, as I was reding the code I realized several 'issues' that should be addressed IMO, but as I'm not sure/aware of the functionalities in the module (and there is no point nor clue in the issue queue) I'm unable to resolve them myself.
Because of this, I just started to write some simpletest cases to be sure what is expected and what is not, and then I could move forward asking in the issue queue (that was the original plan). Now that a D7 is on the way, I guess it's time to just discuss them, and resolve if required, so I'll share them. We may have an IRC discussion on IRC: Heyrocker and RobLoach will join. I'm sure most of the issues will be addressed in the 6.x-2.x branch. This is the issue list I would like to share (I'm trying to explain as easy as possible):
- Services require authentication 1: This is not well documented (I found related prosa in the issue queue: #465546: Decouple api and user authentication). Currently, when no authentication module is enabled, services will always reply "TRUE", instead of returning an error about authentication, even if servers already have an error callback waiting to do some job.
- Authenticate using session 1: the following module list is required: services, services_keyauth, xxxxx_server, system_service, user_service, just to 'start using services'. I think this is insane, because we have to enable more modules than we require (just to use system.connect and user.login) and we are exposing services we don't want to be there, that need an extra configuration. IMHO,
- Single authentication / Multiple authorization: currently authentication is not managed in the right way I guess.. authorization and authentincation are merged in the keyauth module and access callbacks. Using both session ID and Key authentication makes no sense.. Authorization should be 'yes you are allowed' or 'not, you can't do that' and authentication is 'yes, this is you' or 'no, you are not this'.. session ID is probably the best approach for authentication (identifying the user, and doing the relationship -> user -> role?), and keys seem to be more focused in authorization. Keys could also be linked to user being able to authenticate, but who should be owner of the content created with one session ID, and the KEY of other user?.. We need to be consistent here. Splitting key and session authentications will help, but we should be sure it's done properly.
Being authenticated (user could be identified) we could provide more fined permissions per-service method (API currently supports that).
- Services require authentication 2: if services are controlled using an access callback, then why we can't just provide also anonymous services?
Ok, now move into code..
- function services_method_call(): Currently the module checks if method exist, and all the required arguments are there.. and then checks authentication.. do you see what I mean? should this be changed to first check for authentication, and then do the checks..
- access callbacks: in services_method_call(), there is call to access callbacks based on several factors ('#access arguments', '#access arguments append'). I was unable to find doc for them even if I can figure where does "#access arguments" come and what does it mean, but what about the appended part? In any case, lets see this access callback call:
...
// Just use the arguments array if no access arguments have been specified
$access_arguments = $args;
...
and this is one of the callbacks:
/**
* Check if the user is allowed to get the user data.
*
* @param $uid
* Number. The user ID.
*/
function user_service_get_access($uid) {
global $user;
return (($user->uid == $uid && user_access('get own user data')) || ($user->uid != $uid && user_access('get any user data')));
}
$user->uid will never match an array
- In services.module: there is code relevant to resouces and also an implementation of node_load : services_node_load.. should this one be here?...
Ok, I've some more, but may be discussed later.. this is a good start :)
Just would like to focus in one thing:
- Service names: it is time to make use of the new naming convention while we convert this module to D7: #312308: Method names match Drupal function names and also #199176: Avoid using special chars in services definition (sorry, I had to mention ;) )
I'm now moving all the test cases to D7, boombatower submitted yesterday a patch to easy the tests coding, so we can use our own DrupalServicesTestCase class, focused on services testing.
So, keep this moving ;)
Comments
Comment #1
robloachThese are definitely issues we could address with the Drupal 7 branch of Services. There's a number of features in Drupal 7 that we should investigate when refactoring Services:
Comment #2
robloachGiving this issue a more prominent role.
Comment #3
ilo commentedShould we include something like this also?
- flood_register_event so we can limit the service calls in use with some magic and configuration.
- Should the services_keyauth module be extended, and the key control the allowed number of requests?
- make some magic also in the login to limit the number of attemps available (thinking in login_security module and how to control login attemps using the services module.
Comment #4
ilo commentedIt is 1:48 AM here.. so don't take what I'm saying too seriously..
Instead of using specific AUTHentication modules, why not mimic Drupal's FAPI functionality for services? we may share current service definitions using an _alter invoke to modify the service.. This may allow module attaching to current existing services extending their default definition, and one of those modules could be:
- API key usage: it will include the key argument in each service definition so now this argument is required as first argument. The key will later be validated (as in FAPI) and errors could be managed by each service module.
We are not so far from FAPI in current service definition, and some services are already submitting forms programatically.. so If we get a service definition close to FAPI, we can submit forms using service arguments, or just call custom functions if no form is available. Submitting the login form will take advantage of other login modifiers: alt_name and login_security is an example. The missing part are those _alter and _validate invokes..
Comment #5
ilo commentedRobLoach commented that Blog API implementation could be created as a service module. I talked to cweagans and he told me there are several things we should not ALTER of current implementation (service discovery by blog publishing tools, and others). As a suggestion, we would have an issue for this feature linked also in the blog api module.
One of the main changes that this would require is the usage of anonymous services. Blog APIs (Blogger API (outdated), Blogger Data API, MetaWeblog API, and Movable Type API) don't use any kind of session validation, being key or/and username and password, just arguments of the blog API method call..
examples:
- metaWeblog.getPost (postid, username, password) returns struct
- blogger.getPost (appkey, postid, username, password) returns struct
In fact, to be able to do so, the session (or authentication mechanism) should not be required (at least for these services)
Comment #6
gddSo I believe that we are all best served by getting a stable version of the 2.x branch released and done. Once that is finished we can talk about refactoring and possibly opening a 3.x branch. I'm marking this postponed because I want it open and don't want to lose it, but I'm trying to focus on clearing out the bugs and patches for 6.x-2.x. Rest assured this is not going to be forgotten about.
Comment #7
marcingy commentedClosing as decision has been made re 6.x.3 and 7
Comment #8
gddI am actually going to keep this open because there's a lot of good discussion that could be applied to the new branches, even though they are already somewhat written. I want to take some time and go through and see what we can take from it.
Comment #9
marcingy commentedgot the hey we have a critical ping....
Comment #10
Frando commentedYou should also definitely have a look at http://api.drupal.org/api/function/hook_page_delivery_callback_alter/7. It allows you to completely swap out the output generation function for a page request.
Comment #11
kylebrowning commentedYou know,cause we backport form HEAD :)
Comment #12
gddTrying to clear out the 7.3 issue queue, will move these to 7.4 when it opens
Comment #13
marcingy commentedI am closing this simply because it is so generic and things have changed so much in the 2 years since it was created