Mercurial > p > roundup > code
view doc/xmlrpc.txt @ 6433:c1d3fbcdbfbd
issue2551142 - Import of retired node ... unique constraint failure.
Title: Import of retired node with username after active node fails
with unique constraint failure.
More fixes needed for mysql and postgresql.
mysql: add unique constraint for (keyvalue, __retired__) when
creating class in the database.
On schema change if class is changed, remove the unique
constraint too.
upgrade version of rdbms database from 5 to 6 to add constraint
to all version 5 databases that were created as version 5
and didn't get the unique constraint. Make no changes
on version 5 databases upgraded from version 4, the upgrade
process to 5 added the constraint. Make no changes
to other databases (sqlite, postgres) during upgrade from
version 5 to 6.
postgres: Handle the exception raised on unique constraint violation.
The exception invalidates the database connection so it
can't be used to recover from the exception.
Added two new database methods:
checkpoint_data - performs a db.commit under postgres
does nothing on other backends
restore_connection_on_error - does a db.rollback on
postgres, does nothing on other
backends
with the rollback() done on the connection I can use the
database connection to fixup the import that failed on the
unique constraint. This makes postgres slower but without the
commit after every imported object, the rollback will delete
all the entries done up to this point.
Trying to figure out how to make the caller do_import batch
and recover from this failure is beyond me.
Also dismissed having to process the export csv file before
importing. Pushing that onto a user just seems wrong. Also
since import/export isn't frequently done the lack of
surprise on having a failing import and reduced
load/frustration for the user seems worth it. Also the import
can be run in verbose mode where it prints out a row as it is
processed, so it may take a while, ut the user can get
feedback.
db_test-base.py: add test for upgrade from 5 to 6.
| author | John Rouillard <rouilj@ieee.org> |
|---|---|
| date | Thu, 10 Jun 2021 12:52:05 -0400 |
| parents | 45e8d10a9609 |
| children | 24e2eeb2ed9a |
line wrap: on
line source
.. index:: triple: api; xml; remote procedure call pair: api; xmlrpc ========================= XML-RPC access to Roundup ========================= .. contents:: :local: Introduction ------------ Version 1.4 of Roundup includes an XML-RPC frontend for remote access. The XML-RPC interface allows a limited subset of commands similar to those found in local `roundup-admin` tool. By default XML-RPC is accessible from ``/xmlrpc`` endpoint: http://username:password@localhost:8000/xmlrpc For demo tracker the URL would be: http://localhost:8917/demo/xmlrpc Enabling XML-RPC server ----------------------- There are two ways to run the XML-RPC interface: through roundup itself stand alone roundup-xmlrpc-server through roundup --------------- The XML-RPC service is available from the roundup HTTP server under /xmlrpc. To enable this set ``enable_xmlrpc`` to ``yes`` in the ``[web]`` section of the ``config.ini`` file in your tracker. Each user that needs access must include the "Xmlrpc Access" role. To add this new permission to the "User" role you should change your schema.py to add:: db.security.addPermissionToRole('User', 'Xmlrpc Access') This is usually included near where other permissions like "Web Access" or "Email Access" are assigned. stand alone roundup-xmlrpc-server --------------------------------- Using roundup to access the xmlrpc interface is preferred. Roundup provides better control over who can use the interface. The Roundup XML-RPC standalone server must be started before remote clients can access the tracker via XML-RPC. ``roundup-xmlrpc-server`` is installed in the scripts directory alongside ``roundup-server`` and ``roundup-admin``. When invoked, the location of the tracker instance must be specified. roundup-xmlrpc-server -i ``/path/to/tracker`` The default port is ``8000``. An alternative port can be specified with the ``--port`` switch. security consideration ---------------------- Both the standalone and embedded roundup XML endpoints used the default python XML parser. This parser is know to have security issues. For details see: https://pypi.org/project/defusedxml/. You may wish to use the rest interface which doesn't have the same issues. Patches with tests to roundup to use defusedxml are welcome. Note that the current ``roundup-xmlrpc-server`` implementation does not support SSL. This means that usernames and passwords will be passed in cleartext unless the server is being proxied behind another server (such as Apache or lighttpd) that provide SSL. Client API ---------- The server currently implements seven methods/commands. Each method requires that the user provide a username and password in the HTTP authorization header in order to authenticate the request against the tracker. ======= ==================================================================== Command Description ======= ==================================================================== schema Fetch tracker schema. list arguments: *classname, [property_name]* List all elements of a given ``classname``. If ``property_name`` is specified, that is the property that will be displayed for each element. If ``property_name`` is not specified the default label property will be used. display arguments: *designator, [property_1, ..., property_N]* Display a single item in the tracker as specified by ``designator`` (e.g. issue20 or user5). The default is to display all properties for the item. Alternatively, a list of properties to display can be specified. create arguments: *classname, arg_1 ... arg_N* Create a new instance of ``classname`` with ``arg_1`` through ``arg_N`` as the values of the new instance. The arguments are name=value pairs (e.g. ``status='3'``). set arguments: *designator, arg_1 ... arg_N* Set the values of an existing item in the tracker as specified by ``designator``. The new values are specified in ``arg_1`` through ``arg_N``. The arguments are name=value pairs (e.g. ``status='3'``). lookup arguments: *classname, key_value* looks up the key_value for the given class. The class needs to have a key and the user needs search permission on the key attribute and id for the given classname. filter arguments: *classname, list or None, attributes* ``list`` is a list of ids to filter. It can be set to None to run filter over all values (requires ``allow_none=True`` when instantiating the ServerProxy). The ``attributes`` are given as a dictionary of name value pairs to search for. See also :ref:`query-tracker`. ======= ==================================================================== sample python client ==================== This client will work if you turn off the x-requested-with header and the only CSRF header check you require is the HTTP host header:: >>> import xmlrpclib >>> roundup_server = xmlrpclib.ServerProxy('http://admin:admin@localhost:8917/demo/xmlrpc', allow_none=True) >>> roundup_server.schema() {'user': [['username', '<roundup.hyperdb.String>'], ...], 'issue': [...]} >>> roundup_server.list('user') ['admin', 'anonymous', 'demo'] >>> roundup_server.list('issue', 'id') ['1'] >>> roundup_server.display('issue1') {'assignedto' : None, 'files' : [], 'title' = 'yes, ..... } >>> roundup_server.display('issue1', 'priority', 'status') {'priority' : '1', 'status' : '2'} >>> roundup_server.set('issue1', 'status=3') >>> roundup_server.display('issue1', 'status') {'status' : '3' } >>> roundup_server.create('issue', "title='another bug'", "status=2") '2' >>> roundup_server.filter('user',None,{'username':'adm'}) ['1'] >>> roundup_server.filter('user',['1','2'],{'username':'adm'}) ['1'] >>> roundup_server.filter('user',['2'],{'username':'adm'}) [] >>> roundup_server.filter('user',[],{'username':'adm'}) [] >>> roundup_server.lookup('user','admin') '1' advanced python client adding anti-csrf headers =============================================== The one below adds Referer and X-Requested-With headers so it can pass stronger CSRF detection methods. It also generates a fault message from the server and reports it. Note if you are using http rather than https, replace xmlrpclib.SafeTransport with xmlrpclib.Transport:: try: from xmlrpc import client as xmlrpclib # python 3 except ImportError: import xmlrpclib # python 2 hostname="localhost" path="/demo" user_pw="admin:admin" class SpecialTransport(xmlrpclib.SafeTransport): def send_content(self, connection, request_body): connection.putheader("Referer", "https://%s%s/"%(hostname, path)) connection.putheader("Origin", "https://%s"%hostname) connection.putheader("X-Requested-With", "XMLHttpRequest") connection.putheader("Content-Type", "text/xml") connection.putheader("Content-Length", str(len(request_body))) connection.endheaders() if request_body: connection.send(request_body) roundup_server = xmlrpclib.ServerProxy( 'https://%s@%s%s/xmlrpc'%(user_pw,hostname,path), transport=SpecialTransport(), verbose=False, allow_none=True) print(roundup_server.schema()) print(roundup_server.display('user2', 'username')) print(roundup_server.display('issue1', 'status')) print(roundup_server.filter('user',['1','2','3'],{'username':'demo'})) # this will fail with a fault try: print(roundup_server.filter('usr',['0','2','3'],{'username':'demo'})) except Exception as msg: print(msg) modify this script replacing the hostname, path and user_pw with those for your tracker.
