changeset 1592:8628c8706bf8 beta

[API] Update doc
author Nicolas VINOT <aeris@imirhil.fr>
date Sat, 22 Oct 2011 23:18:03 +0200
parents 0b63a0d2cede (current diff) 8e77c75bd65a (diff)
children 92a4f7c496a5
files docs/api/api.rst rhodecode/model/db.py
diffstat 14 files changed, 350 insertions(+), 84 deletions(-) [+]
line wrap: on
line diff
--- a/development.ini	Wed Oct 19 01:47:56 2011 +0200
+++ b/development.ini	Sat Oct 22 23:18:03 2011 +0200
@@ -24,6 +24,8 @@
 #smtp_port = 
 #smtp_use_tls = false
 #smtp_use_ssl = true
+# Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.)
+#smtp_auth = 
 
 [server:main]
 ##nr of threads to spawn
--- a/docs/api/api.rst	Wed Oct 19 01:47:56 2011 +0200
+++ b/docs/api/api.rst	Sat Oct 22 23:18:03 2011 +0200
@@ -7,7 +7,7 @@
 
 Starting from RhodeCode version 1.2 a simple API was implemented.
 There's a single schema for calling all api methods. API is implemented
-with JSON protocol both ways. An url to send API request in RhodeCode is 
+with JSON protocol both ways. An url to send API request in RhodeCode is
 <your_server>/_admin/api
 
 
@@ -22,90 +22,341 @@
 Example call for autopulling remotes repos using curl::
     curl https://server.com/_admin/api -X POST -H 'content-type:text/plain' --data-binary '{"api_key":"xe7cdb2v278e4evbdf5vs04v832v0efvcbcve4a3","method":"pull","args":{"repo":"CPython"}}'
 
-Simply provide 
+Simply provide
  - *api_key* for access and permission validation.
  - *method* is name of method to call
  - *args* is an key:value list of arguments to pass to method
-    
+
 .. note::
-    
-    api_key can be found in your user account page    
-    
-    
+
+    api_key can be found in your user account page
+
+
 RhodeCode API will return always a JSON formatted answer::
-    
+
     {
-        "result": "<result>", 
+        "result": "<result>",
         "error": null
     }
 
 All responses from API will be `HTTP/1.0 200 OK`, if there's an error while
-calling api *error* key from response will contain failure description 
+calling api *error* key from response will contain failure description
 and result will be null.
 
 API METHODS
 +++++++++++
 
-    
+
 pull
 ----
 
-Pulls given repo from remote location. Can be used to automatically keep 
-remote repos up to date. This command can be executed only using api_key 
-belonging to user with admin rights
-
-INPUT::
-
-    api_key:"<api_key>"
-    method: "pull"
-    args: {"repo":<repo_name>}
-
-OUTPUT::
-
-    result:"Pulled from <repo_name>"
-    error:null
-
-    
-create_user
------------
-
-Creates new user in RhodeCode. This command can be executed only using api_key 
+Pulls given repo from remote location. Can be used to automatically keep
+remote repos up to date. This command can be executed only using api_key
 belonging to user with admin rights
 
 INPUT::
 
-    api_key:"<api_key>"
-    method: "create_user"
-    args: {"username": "<username>", 
-           "password": "<password>", 
-           "active":   "<bool>", 
-           "admin":    "<bool>", 
-           "name":     "<firstname>", 
-           "lastname": "<lastname>", 
-           "email":    "<useremail>"}
+    api_key : "<api_key>"
+    method :  "pull"
+    args :    {
+                "repo" : "<repo_name>"
+              }
+
+OUTPUT::
+
+    result : "Pulled from <repo_name>"
+    error :  null
+
+
+get_users
+---------
+
+Lists all existing users. This command can be executed only using api_key
+belonging to user with admin rights.
+
+INPUT::
+
+    api_key : "<api_key>"
+    method :  "get_users"
+    args :    { }
+
+OUTPUT::
+
+    result: [
+              {
+                "id" :       "<id>",
+                "username" : "<username>",
+                "firstname": "<firstname>",
+                "lastname" : "<lastname>",
+                "email" :    "<email>",
+                "active" :   "<bool>",
+                "admin" :    "<bool>",
+                "ldap" :     "<ldap_dn>"
+              },
+    	      …
+            ]
+    error:  null
+
+create_user
+-----------
+
+Creates new user in RhodeCode. This command can be executed only using api_key
+belonging to user with admin rights.
+
+INPUT::
+
+    api_key : "<api_key>"
+    method :  "create_user"
+    args :    {
+                "username" :  "<username>",
+                "password" :  "<password>",
+                "firstname" : "<firstname>",
+                "lastname" :  "<lastname>",
+                "email" :     "<useremail>"
+                "active" :    "<bool> = True",
+                "admin" :     "<bool> = False",
+                "ldap_dn" :   "<ldap_dn> = None"
+              }
 
 OUTPUT::
 
-    result:{"id": <newuserid>,
-            "msg":"created new user <username>"}
-    error:null
-    
-    
+    result: {
+              "msg" : "created new user <username>"
+            }
+    error:  null
+
+get_users_groups
+----------------
+
+Lists all existing users groups. This command can be executed only using api_key
+belonging to user with admin rights.
+
+INPUT::
+
+    api_key : "<api_key>"
+    method :  "get_users_groups"
+    args :    { }
+
+OUTPUT::
+
+    result : [
+               {
+                 "id" :       "<id>",
+                 "name" :     "<name>",
+                 "active":    "<bool>",
+                 "members" :  [
+	    	                    {
+	    	                      "id" :       "<userid>",
+	                              "username" : "<username>",
+	                              "firstname": "<firstname>",
+	                              "lastname" : "<lastname>",
+	                              "email" :    "<email>",
+	                              "active" :   "<bool>",
+	                              "admin" :    "<bool>",
+	                              "ldap" :     "<ldap_dn>"
+	                            },
+	    	                    …
+	                          ]
+	            }
+              ]
+    error : null
+
+get_users_group
+---------------
+
+Gets an existing users group. This command can be executed only using api_key
+belonging to user with admin rights.
+
+INPUT::
+
+    api_key : "<api_key>"
+    method :  "get_users_group"
+    args :    {
+                "group_name" : "<name>"
+              }
+
+OUTPUT::
+
+    result : None if group not exist
+             {
+               "id" :       "<id>",
+               "name" :     "<name>",
+               "active":    "<bool>",
+               "members" :  [
+	    	                  { "id" :       "<userid>",
+	                            "username" : "<username>",
+	                            "firstname": "<firstname>",
+	                            "lastname" : "<lastname>",
+	                            "email" :    "<email>",
+	                            "active" :   "<bool>",
+	                            "admin" :    "<bool>",
+	                            "ldap" :     "<ldap_dn>"
+	                          },
+	    	                  …
+	                        ]
+             }
+    error : null
+
 create_users_group
 ------------------
 
-creates new users group. This command can be executed only using api_key 
+Creates new users group. This command can be executed only using api_key
 belonging to user with admin rights
 
 INPUT::
 
-    api_key:"<api_key>"
-    method: "create_user"
-    args: {"name":  "<groupname>", 
-           "active":"<bool>"}
+    api_key : "<api_key>"
+    method :  "create_users_group"
+    args:     {
+                "name":  "<name>",
+                "active":"<bool> = True"
+              }
+
+OUTPUT::
+
+    result: {
+              "id":  "<newusersgroupid>",
+              "msg": "created new users group <name>"
+            }
+    error:  null
+
+add_user_to_users_groups
+------------------------
+
+Adds a user to a users group. This command can be executed only using api_key
+belonging to user with admin rights
+
+INPUT::
+
+    api_key : "<api_key>"
+    method :  "add_user_users_group"
+    args:     {
+                "group_name" :  "<groupname>",
+                "user_name" :   "<username>"
+              }
+
+OUTPUT::
+
+    result: {
+              "id":  "<newusersgroupmemberid>",
+              "msg": "created new users group member"
+            }
+    error:  null
+
+get_repos
+---------
+
+Lists all existing repositories. This command can be executed only using api_key
+belonging to user with admin rights
+
+INPUT::
+
+    api_key : "<api_key>"
+    method :  "get_repos"
+    args:     { }
 
 OUTPUT::
 
-    result:{"id": <newusersgroupid>,
-            "msg":"created new users group <groupname>"}
-    error:null    
+    result: [
+              {
+                "id" :          "<id>",
+                "name" :        "<name>"
+                "type" :        "<type>",
+                "description" : "<description>"
+              },
+              …
+            ]
+    error:  null
+
+get_repo
+--------
+
+Gets an existing repository. This command can be executed only using api_key
+belonging to user with admin rights
+
+INPUT::
+
+    api_key : "<api_key>"
+    method :  "get_repo"
+    args:     {
+                "name" : "<name>"
+              }
+
+OUTPUT::
+
+    result: None if repository not exist
+            {
+                "id" :          "<id>",
+                "name" :        "<name>"
+                "type" :        "<type>",
+                "description" : "<description>",
+                "members" :     [
+                                  { "id" :         "<userid>",
+	                                "username" :   "<username>",
+	                                "firstname":   "<firstname>",
+	                                "lastname" :   "<lastname>",
+	                                "email" :      "<email>",
+	                                "active" :     "<bool>",
+	                                "admin" :      "<bool>",
+	                                "ldap" :       "<ldap_dn>",
+	                                "permission" : "repository_(read|write|admin)"
+	                              },
+                                  …
+                                  {
+                                    "id" :       "<usersgroupid>",
+                                    "name" :     "<usersgroupname>",
+                                    "active":    "<bool>",
+                                    "permission" : "repository_(read|write|admin)"
+                                  },
+                                  …
+                                ]
+            }
+    error:  null
+
+create_repo
+-----------
+
+Creates a repository. This command can be executed only using api_key
+belonging to user with admin rights.
+If repository name contains "/", all needed repository groups will be created.
+For example "foo/bar/baz" will create groups "foo", "bar" (with "foo" as parent),
+and create "baz" repository with "bar" as group.
+
+INPUT::
+
+    api_key : "<api_key>"
+    method :  "create_repo"
+    args:     {
+                "name" :        "<name>",
+                "owner_name" :  "<ownername>",
+                "description" : "<description> = ''",
+                "repo_type" :   "<type> = 'hg'",
+                "private" :     "<bool> = False"
+              }
+
+OUTPUT::
+
+    result: None
+    error:  null
+
+add_user_to_repo
+----------------
+
+Add a user to a repository. This command can be executed only using api_key
+belonging to user with admin rights.
+If "perm" is None, user will be removed from the repository.
+
+INPUT::
+
+    api_key : "<api_key>"
+    method :  "add_user_to_repo"
+    args:     {
+                "repo_name" :  "<reponame>",
+                "user_name" :  "<username>",
+                "perm" :       "(None|repository_(read|write|admin))",
+              }
+
+OUTPUT::
+
+    result: None
+    error:  null
--- a/production.ini	Wed Oct 19 01:47:56 2011 +0200
+++ b/production.ini	Sat Oct 22 23:18:03 2011 +0200
@@ -24,6 +24,8 @@
 #smtp_port = 
 #smtp_use_tls = false
 #smtp_use_ssl = true
+# Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.)
+#smtp_auth = 
 
 [server:main]
 ##nr of threads to spawn
--- a/rhodecode/config/deployment.ini_tmpl	Wed Oct 19 01:47:56 2011 +0200
+++ b/rhodecode/config/deployment.ini_tmpl	Sat Oct 22 23:18:03 2011 +0200
@@ -24,6 +24,8 @@
 #smtp_port = 
 #smtp_use_tls = false
 #smtp_use_ssl = true
+# Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.)
+#smtp_auth = 
 
 [server:main]
 ##nr of threads to spawn
@@ -146,7 +148,7 @@
 # SQLITE [default]
 sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db
  
-# POSTGRES
+# POSTGRESQL
 # sqlalchemy.db1.url = postgresql://user:pass@localhost/rhodecode
 
 # MySQL
--- a/rhodecode/lib/__init__.py	Wed Oct 19 01:47:56 2011 +0200
+++ b/rhodecode/lib/__init__.py	Sat Oct 22 23:18:03 2011 +0200
@@ -394,13 +394,12 @@
     try:
         from vcs import get_repo
         from vcs.utils.helpers import get_scm
-        from vcs.exceptions import RepositoryError, VCSError
         repopath = os.path.join(os.path.dirname(__file__), '..', '..')
         scm = get_scm(repopath)[0]
         repo = get_repo(path=repopath, alias=scm)
         tip = repo.get_changeset()
         return (tip.revision, tip.short_id)
-    except (ImportError, RepositoryError, VCSError), err:
+    except Exception, err:
         if not quiet:
             print ("Cannot retrieve rhodecode's revision. Original error "
                    "was: %s" % err)
--- a/rhodecode/lib/auth_ldap.py	Wed Oct 19 01:47:56 2011 +0200
+++ b/rhodecode/lib/auth_ldap.py	Sat Oct 22 23:18:03 2011 +0200
@@ -53,8 +53,10 @@
         if self.TLS_KIND == 'LDAPS':
             port = port or 689
             ldap_server_type = ldap_server_type + 's'
-
-        self.TLS_REQCERT = ldap.__dict__['OPT_X_TLS_' + tls_reqcert]
+        
+        OPT_X_TLS_DEMAND = 2
+        self.TLS_REQCERT = getattr(ldap, 'OPT_X_TLS_%s' % tls_reqcert, 
+                                   OPT_X_TLS_DEMAND)
         self.LDAP_SERVER_ADDRESS = server
         self.LDAP_SERVER_PORT = port
 
@@ -63,12 +65,12 @@
         self.LDAP_BIND_PASS = bind_pass
 
         self.LDAP_SERVER = "%s://%s:%s" % (ldap_server_type,
-                                               self.LDAP_SERVER_ADDRESS,
-                                               self.LDAP_SERVER_PORT)
+                                           self.LDAP_SERVER_ADDRESS,
+                                           self.LDAP_SERVER_PORT)
 
         self.BASE_DN = base_dn
         self.LDAP_FILTER = ldap_filter
-        self.SEARCH_SCOPE = ldap.__dict__['SCOPE_' + search_scope]
+        self.SEARCH_SCOPE = getattr(ldap, 'SCOPE_%s' % search_scope)
         self.attr_login = attr_login
 
     def authenticate_ldap(self, username, password):
@@ -88,7 +90,9 @@
         if "," in username:
             raise LdapUsernameError("invalid character in username: ,")
         try:
-            ldap.set_option(ldap.OPT_X_TLS_CACERTDIR, '/etc/openldap/cacerts')
+            if hasattr(ldap,'OPT_X_TLS_CACERTDIR'):
+                ldap.set_option(ldap.OPT_X_TLS_CACERTDIR, 
+                                '/etc/openldap/cacerts')
             ldap.set_option(ldap.OPT_REFERRALS, ldap.OPT_OFF)
             ldap.set_option(ldap.OPT_RESTART, ldap.OPT_ON)
             ldap.set_option(ldap.OPT_TIMEOUT, 20)
--- a/rhodecode/lib/celerylib/tasks.py	Wed Oct 19 01:47:56 2011 +0200
+++ b/rhodecode/lib/celerylib/tasks.py	Sat Oct 22 23:18:03 2011 +0200
@@ -356,9 +356,10 @@
     tls = str2bool(email_config.get('smtp_use_tls'))
     ssl = str2bool(email_config.get('smtp_use_ssl'))
     debug = str2bool(config.get('debug'))
+    smtp_auth = email_config.get('smtp_auth')
 
     try:
-        m = SmtpMailer(mail_from, user, passwd, mail_server,
+        m = SmtpMailer(mail_from, user, passwd, mail_server,smtp_auth,
                        mail_port, ssl, tls, debug=debug)
         m.send(recipients, subject, body)
     except:
--- a/rhodecode/lib/smtp_mailer.py	Wed Oct 19 01:47:56 2011 +0200
+++ b/rhodecode/lib/smtp_mailer.py	Sat Oct 22 23:18:03 2011 +0200
@@ -39,7 +39,7 @@
 class SmtpMailer(object):
     """SMTP mailer class
 
-    mailer = SmtpMailer(mail_from, user, passwd, mail_server,
+    mailer = SmtpMailer(mail_from, user, passwd, mail_server, smtp_auth
                         mail_port, ssl, tls)
     mailer.send(recipients, subject, body, attachment_files)
 
@@ -49,8 +49,8 @@
 
     """
 
-    def __init__(self, mail_from, user, passwd, mail_server,
-                    mail_port=None, ssl=False, tls=False, debug=False):
+    def __init__(self, mail_from, user, passwd, mail_server, smtp_auth=None,
+                 mail_port=None, ssl=False, tls=False, debug=False):
 
         self.mail_from = mail_from
         self.mail_server = mail_server
@@ -60,6 +60,7 @@
         self.ssl = ssl
         self.tls = tls
         self.debug = debug
+        self.auth = smtp_auth
 
     def send(self, recipients=[], subject='', body='', attachment_files=None):
 
@@ -78,9 +79,11 @@
             smtp_serv.set_debuglevel(1)
 
         smtp_serv.ehlo()
+        if self.auth:
+            smtp_serv.esmtp_features["auth"] = self.auth
 
-        #if server requires authorization you must provide login and password
-        #but only if we have them
+        # if server requires authorization you must provide login and password
+        # but only if we have them
         if self.user and self.passwd:
             smtp_serv.login(self.user, self.passwd)
 
@@ -156,6 +159,7 @@
         if isinstance(msg_file, str):
             return open(msg_file, "rb").read()
         else:
-            #just for safe seek to 0
+            # just for safe seek to 0
             msg_file.seek(0)
             return msg_file.read()
+
--- a/rhodecode/model/db.py	Wed Oct 19 01:47:56 2011 +0200
+++ b/rhodecode/model/db.py	Sat Oct 22 23:18:03 2011 +0200
@@ -425,7 +425,8 @@
                     Session.flush()
                     members_list = []
                     if v:
-                        for u_id in set( list( v ) ):
+                        v = [v] if isinstance(v, basestring) else v
+                        for u_id in set(v):
                             member = UsersGroupMember( users_group_id, u_id )
                             members_list.append( member )
                     setattr( users_group, 'members', members_list )
--- a/rhodecode/templates/admin/repos_groups/repos_groups_add.html	Wed Oct 19 01:47:56 2011 +0200
+++ b/rhodecode/templates/admin/repos_groups/repos_groups_add.html	Sat Oct 22 23:18:03 2011 +0200
@@ -29,7 +29,7 @@
         <div class="fields">
              <div class="field">
                 <div class="label">
-                    <label for="users_group_name">${_('Group name')}:</label>
+                    <label for="group_name">${_('Group name')}:</label>
                 </div>
                 <div class="input">
                     ${h.text('group_name',class_='medium')}
@@ -38,7 +38,7 @@
              
             <div class="field">
                 <div class="label label-textarea">
-                    <label for="description">${_('Description')}:</label>
+                    <label for="group_description">${_('Description')}:</label>
                 </div>
                 <div class="textarea text-area editor">
                     ${h.textarea('group_description',cols=23,rows=5,class_="medium")}
@@ -47,7 +47,7 @@
              
              <div class="field">
                  <div class="label">
-                     <label for="repo_group">${_('Group parent')}:</label>
+                     <label for="group_parent_id">${_('Group parent')}:</label>
                  </div>
                  <div class="input">
                      ${h.select('group_parent_id','',c.repo_groups,class_="medium")}
--- a/rhodecode/templates/admin/repos_groups/repos_groups_edit.html	Wed Oct 19 01:47:56 2011 +0200
+++ b/rhodecode/templates/admin/repos_groups/repos_groups_edit.html	Sat Oct 22 23:18:03 2011 +0200
@@ -29,7 +29,7 @@
         <div class="fields">
              <div class="field">
                 <div class="label">
-                    <label for="users_group_name">${_('Group name')}:</label>
+                    <label for="group_name">${_('Group name')}:</label>
                 </div>
                 <div class="input">
                     ${h.text('group_name',class_='medium')}
@@ -38,7 +38,7 @@
              
 	        <div class="field">
 	            <div class="label label-textarea">
-	                <label for="description">${_('Description')}:</label>
+	                <label for="group_description">${_('Description')}:</label>
 	            </div>
 	            <div class="textarea text-area editor">
 	                ${h.textarea('group_description',cols=23,rows=5,class_="medium")}
@@ -47,7 +47,7 @@
              
 	         <div class="field">
 	             <div class="label">
-	                 <label for="repo_group">${_('Group parent')}:</label>
+	                 <label for="group_parent_id">${_('Group parent')}:</label>
 	             </div>
 	             <div class="input">
 	                 ${h.select('group_parent_id','',c.repo_groups,class_="medium")}
--- a/rhodecode/templates/admin/settings/settings.html	Wed Oct 19 01:47:56 2011 +0200
+++ b/rhodecode/templates/admin/settings/settings.html	Sat Oct 22 23:18:03 2011 +0200
@@ -34,7 +34,7 @@
 		        <div class="checkboxes">
 		            <div class="checkbox">
 		                ${h.checkbox('destroy',True)}
-		                <label for="checkbox-1">
+		                <label for="destroy">
 		                <span class="tooltip" title="${h.tooltip(_('In case a repository was deleted from filesystem and there are leftovers in the database check this option to scan obsolete data in database and remove it.'))}">
 		                ${_('destroy old data')}</span> </label>
 		            </div>
@@ -56,12 +56,12 @@
         <div class="fields">
             <div class="field">
                 <div class="label label-checkbox">
-                    <label for="destroy">${_('index build option')}:</label>
+                    <label>${_('index build option')}:</label>
                 </div>
                 <div class="checkboxes">
                     <div class="checkbox">
                         ${h.checkbox('full_index',True)}
-                        <label for="checkbox-1">${_('build from scratch')}</label>
+                        <label for="full_index">${_('build from scratch')}</label>
                     </div>
                 </div>
             </div>
@@ -100,7 +100,7 @@
             
             <div class="field">
                 <div class="label">
-                    <label for="ga_code">${_('GA code')}:</label>
+                    <label for="rhodecode_ga_code">${_('GA code')}:</label>
                 </div>
                 <div class="input">
                     ${h.text('rhodecode_ga_code',size=30)}
@@ -124,7 +124,7 @@
              
              <div class="field">
                 <div class="label label-checkbox">
-                    <label for="web_push_ssl">${_('Web')}:</label>
+                    <label>${_('Web')}:</label>
                 </div>
                 <div class="checkboxes">
 					<div class="checkbox">
@@ -136,7 +136,7 @@
 
              <div class="field">
                 <div class="label label-checkbox">
-                    <label for="web_push_ssl">${_('Hooks')}:</label>
+                    <label>${_('Hooks')}:</label>
                 </div>
                 <div class="input">
                     ${h.link_to(_('advanced setup'),url('admin_edit_setting',setting_id='hooks'))}
--- a/rhodecode/templates/admin/users/user_edit.html	Wed Oct 19 01:47:56 2011 +0200
+++ b/rhodecode/templates/admin/users/user_edit.html	Sat Oct 22 23:18:03 2011 +0200
@@ -132,7 +132,7 @@
         <div class="fields">
              <div class="field">
                 <div class="label label-checkbox">
-                    <label for="">${_('Create repositories')}:</label>
+                    <label for="create_repo_perm">${_('Create repositories')}:</label>
                 </div>
                 <div class="checkboxes">
                     ${h.checkbox('create_repo_perm',value=True)}
--- a/rhodecode/templates/admin/users_groups/users_group_edit.html	Wed Oct 19 01:47:56 2011 +0200
+++ b/rhodecode/templates/admin/users_groups/users_group_edit.html	Sat Oct 22 23:18:03 2011 +0200
@@ -253,7 +253,7 @@
         <div class="fields">
              <div class="field">
                 <div class="label label-checkbox">
-                    <label for="">${_('Create repositories')}:</label>
+                    <label for="create_repo_perm">${_('Create repositories')}:</label>
                 </div>
                 <div class="checkboxes">
                     ${h.checkbox('create_repo_perm',value=True)}