--- user_service/user_service.inc	5 Sep 2009 13:57:59 -0000	1.1.2.8.2.1
+++ user_service/user_service.inc	2 Nov 2009 00:16:36 -0000
@@ -1,5 +1,6 @@
 <?php
 // $Id: user_service.inc,v 1.1.2.8.2.1 2009/09/05 13:57:59 marcingy Exp $
+
 /**
  * @author Services Dev Team
  * @file
@@ -7,19 +8,22 @@
  */
 
 /**
- * Delete an user.
+ * Delete an user, move all content authored content to anonymous
  *
  * @param $uid
  *   Number. The user ID.
+ * @return
+ *   Bool. True on success.
  */
 function user_service_delete($uid) {
   $account = user_load($uid);
   if (empty($account)) {
     return services_error(t('There is no user with such ID.'), 404);
   }
-  user_delete($account, $uid);
 
-  // Everything went right.
+  // Remove account and process cancel method. Using this function to allow
+  // deletion out of a 'progressive' batch.
+  _user_cancel((array)$account, $account, 'user_cancel_reassign');
   return TRUE;
 }
 
@@ -31,8 +35,14 @@
  */
 function user_service_delete_access($uid) {
   global $user;
-  return (($user->uid == $uid && user_access('delete own user')) ||
-    ($user->uid != $uid && user_access('delete any user')));
+
+  // @TODO: remove this false authorization
+  return TRUE;
+
+  if ( user_access('delete any user') || ($user->uid == $uid && user_access('delete own user')) ) {
+    return TRUE;
+  }
+  return FALSE;
 }
 
 /**
@@ -40,6 +50,8 @@
  *
  * @param $uid
  *   Number. The user ID.
+ * @return
+ *   Object. Loaded user object
  */
 function user_service_get($uid) {
   $account = user_load($uid);
@@ -47,7 +59,7 @@
     return services_error(t('There is no user with such ID.'), 404);
   }
 
-  // Everything went right.
+  // Return user Object
   return $account;
 }
 
@@ -59,7 +71,14 @@
  */
 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')));
+
+  // @TODO: remove this false authorization
+  return TRUE;
+
+  if (user_access('get any user data') || ($user->uid == $uid && user_access('get own user data'))) {
+    return TRUE;
+  }
+  return FALSE;
 }
 
 /**
@@ -78,25 +97,33 @@
     return services_error(t('Already logged in as !user.', array('!user' => $user->name)), 406);
   }
 
-  $user = user_authenticate(array('name' => $username, 'pass' => $password));
-
-  if ($user->uid) {
+  $uid = _user_service_user_authenticate($username, $password);
+  if ($uid) {
     // Regenerate the session ID to prevent against session fixation attacks.
-    sess_regenerate();
+    session_regenerate_id();
+
+    $user = user_load($uid);
     module_invoke_all('user', 'login', NULL, $user);
 
     $return = new stdClass();
     $return->sessid = session_id();
     $return->user = $user;
-
     return $return;
   }
-  session_destroy();
+
   return services_error(t('Wrong username or password.'), 401);
 }
 
+/*
+ * Wrapper for user authentication. Check credentials (not altering session id
+ * or other information in current session.
+ */
+function _user_service_user_authenticate($name, $pass) {
+  return user_authenticate($name, $pass);
+}
+
 /**
- * Logout user
+ * Logout current user
  */
 function user_service_logout() {
   global $user;
@@ -114,7 +141,6 @@
 
   // Load the anonymous user
   $user = drupal_anonymous_user();
-
   return TRUE;
 }
 
@@ -122,17 +148,18 @@
  * Save user details.
  *
  * @param $user_data
- *   Object. The user object with all user data.
+ *   Array. The user object with all user data.
+ * @return
+ *   Interger. User id of updated or created user
  */
 function user_service_save($account) {
   // if uid is present then update, otherwise insert
-  $update = user_load($account['uid']);	
-  $account = isset($update->uid) ? user_save($update,$account) : user_save('', $account);  
+  $update = (!isset($account['is_new']) && isset($account['uid']) && ($account['uid'] > 0)) ? user_load($account['uid']) : drupal_anonymous_user();
+  $account = user_save($update, $account);
   if (!$account) {
     return services_error(t('Error on saving the user.'), 500);
   }
 
-  // Everything went right.
   // Return the user ID
   return $account->uid;
 }
@@ -145,7 +172,11 @@
  */
 function user_service_save_access($account) {
   global $user;
-  return ((empty($account['uid']) && user_access('create new users')) ||
-    ($user->uid == $account['uid'] && user_access('update own user data')) ||
-    ($user->uid !=  $account['uid'] && user_access('update any user data')));
+
+  // @TODO: remove this false authorization
+  return TRUE;
+  if ( (($account['uid'] == 0) && user_access('create new users')) || (($account['uid'] > 0) && user_access('update any user data')) || ($user->uid == $account['uid'] && user_access('update own user data')) ) {
+    return TRUE;
+  }
+  return FALSE;
 }
--- user_service/user_service.info	10 Jan 2008 00:35:53 -0000	1.5
+++ user_service/user_service.info	31 Oct 2009 23:13:50 -0000
@@ -3,5 +3,7 @@
 description = Provides a user service.
 package = Services - services
 dependencies[] = services
-dependencies[] = user
-core = 6.x
\ No newline at end of file
+files[] = user_service.inc
+files[] = user_service.module
+files[] = user_service.test
+core = 7.x
\ No newline at end of file
--- user_service/user_service.module	15 Oct 2009 03:54:06 -0000	1.3.2.16.2.1
+++ user_service/user_service.module	2 Nov 2009 00:14:51 -0000
@@ -1,5 +1,6 @@
 <?php
 // $Id: user_service.module,v 1.3.2.16.2.1 2009/10/15 03:54:06 marcingy Exp $
+
 /**
  * @author Services Dev Team
  * @file
@@ -7,31 +8,55 @@
  */
 
 /**
- * Implementation of hook_help().
+ * Implements hook_help().
  */
 function user_service_help($path, $arg) {
   switch ($path) {
     case 'admin/help#services_user':
-      return '<p>'. t('Provides user methods to services applications. Requires services.module.') .'</p>';
+      return '<p>' . t('Provides user methods to services applications. Requires services.module.') . '</p>';
     case 'admin/modules#description':
       return t('Provides user methods to services applications. Requires services.module.');
   }
 }
 
 /**
- * Implementation of hook_perm().
+ * Implements hook_permission().
  */
-function user_service_perm() {
+function user_service_permission() {
   return array(
-    'get any user data', 'get own user data',
-    'update any user data', 'update own user data',
-    'create new users',
-    'delete any user', 'delete own user',
+    'get any user data' =>  array(
+      'title' => t('Get any user data'),
+      'description' => t('Read information from any user account.'),
+    ),
+    'get own user data' =>  array(
+      'title' => t('Get own user data'),
+      'description' => t('Read information from own user account.'),
+    ),
+    'update any user data' =>  array(
+      'title' => t('Administer permissions'),
+      'description' => t('Update information of any user account.'),
+    ),
+    'update own user data' =>  array(
+      'title' => t('Update own user data'),
+      'description' => t('Update information of own user account.'),
+    ),
+    'create new users' =>  array(
+      'title' => t('Create new users'),
+      'description' => t('create new user accounts.'),
+    ),
+    'delete any user' =>  array(
+      'title' => t('Delete any user'),
+      'description' => t('Delete any user account.'),
+    ),
+    'delete own user' =>  array(
+      'title' => t('Delete own user'),
+      'description' => t('Delete own user account.'),
+    ),
   );
 }
 
 /**
- * Implementation of hook_service().
+ * Implements hook_service().
  */
 function user_service_service() {
   return array(
--- user_service/user_service.test
+++ user_service/user_service.test
@@ -0,0 +1,132 @@
+<?php
+// $Id$
+
+/**
+ * @author Services Dev Team
+ * @file
+ *  Test user services implementation.
+ */
+
+class UserServicesAPITestCase extends DrupalWebTestCase {
+
+  public static function getInfo() {
+    return array(
+      'name' => 'User services',
+      'description' => 'Test user services implementation.',
+      'group' => 'Services - Services',
+    );
+  }
+
+  protected $account;
+
+  /*
+   * Enable the module and configure the basics for the test.
+   */
+  function setUp() {
+    global $user;
+
+    parent::setUp('services', 'services_keyauth', 'user_service');
+    module_load_include('inc', 'user_service');
+
+    $this->account = $user;
+  }
+
+  /*
+   * Test user_service_delete implementation.
+   */
+  function testUserServiceDelete() {
+    $user1 = $this->drupalCreateUser();
+
+    // Verify that user exist
+    $result = user_service_get($user1->uid);
+    $this->assertEqual($user1->name, $result->name, t('user successfully read.'));
+
+    // Try to delete a non-existant user
+    $result = user_service_delete( ($user1->uid + 1) );
+    $this->assertEqual(t('There is no user with such ID.'), $result, t('user_service_delete fail successfully verified.'));
+
+    // Check current uid, user_service_delete could destroy our session
+    global $user;
+    $this->assertNotEqual($user->uid, $user1->uid, t('user_service_delete can not destroy current session.'));
+
+    // Verify that user is deleted.
+    $result = user_service_delete($user1->uid);
+    $this->assertEqual(1, $result, t('user_service_delete operation succeed.'));
+    // Check using database, forcing reset of cached users.
+    $result = user_load($user1->uid, TRUE);
+    $this->assertTrue(!isset($result->uid), t('user_service_delete successfully verified.'));
+  }
+  
+  /*
+   * Test user_service_get implementation.
+   */
+  function testUserServiceGet() {
+    $user1 = $this->drupalCreateUser();
+
+    // Verify that user exist
+    $result = user_service_get($user1->uid);
+    $this->assertEqual($user1->name, $result->name, t('user_service_get success load successfully verified.'));
+
+    // Verify that user doesn't exist
+    $user1->uid += 1;
+    $result = user_service_get($user1->uid);
+    $this->assertEqual(t('There is no user with such ID.'), $result, t('user_service_load fail load successfully verified.'));
+  }
+  
+  /*
+   * Test user_service_save implementation.
+   */
+  function testUserServiceSave() {
+    $user1 = $this->drupalCreateUser();
+    $user1->mail = 'testing@' . $this->randomName() . ".com";
+
+    // Verify that user is updated
+    $uid = user_service_save((array)$user1);
+    $this->assertTrue($uid, t('User successfully updated.'));
+    $result = user_service_get($uid);
+    $this->assertEqual($user1->mail, $result->mail, t('user_service_save update successfully verified.'));
+
+    // Verify that new user is created
+    $user1->mail = 'testing@' . $this->randomName() . ".com";
+    $user1->name = $this->randomName();
+    $user1->uid = NULL;
+    $uid = user_service_save((array)$user1);
+    $this->assertTrue($uid, t('User successfully created.'));
+    $result = user_service_get($uid);
+    $this->assertEqual($user1->mail, $result->mail, t('user_service_save create successfully verified.'));
+
+    // Verify user save/update error, providing an incomplete user object
+    // Due to PDO exceptions, I'll leave this commented for now, core is not
+    // handling this exception and stops the whole test.
+    //$user1->name = '';
+    //$result = user_service_save((array)$user1);
+    //$this->assertEqual(t('Error on saving the user.'), $result, t('user_service_load fail load successfully verified.'));
+  }
+  
+  /*
+   * Test user_service_login implementation.
+   */
+  function testUserServiceLogin() {
+    global $user;
+    $result = user_service_login($this->randomName(), $this->randomName());
+    $this->assertEqual(t('Already logged in as !user.', array('!user' => $user->name)), $result, t('user_service_login fail logged in successfully verified.'));
+
+    // Create a new user
+    $user1 = $this->drupalCreateUser();
+
+    $user->uid = 0;
+    // Verify invalid login
+    $result = user_service_login($user1->name, $this->randomName());
+    $this->assertEqual(t('Wrong username or password.'), $result, t('user_service_login invalid login successfully verified.'));
+    $user->uid = $this->account->uid;
+
+    // Verify valid login, using the wrapped function
+    $result = _user_service_user_authenticate($user1->name, $user1->pass_raw);
+    $this->assertEqual($user1->uid, $result, t('user_service_login valid login successfully verified.'));
+
+    // Verify invalid login, using the wrapped function
+    $result = _user_service_user_authenticate($user1->name, $this->randomName());
+    $this->assertTrue(empty($result), t('user_service_login invalid login successfully verified.'));
+  }
+
+}


