diff options
| author | xmo-odoo <xmo@odoo.com> | 2017-11-02 19:06:33 +0100 |
|---|---|---|
| committer | rar-odoo <rar@odoo.com> | 2017-11-02 19:06:33 +0100 |
| commit | b62bb5add272098ec816c1fe2cc4201351e1463e (patch) | |
| tree | b9f8881251da22aa35f8e0b6e0503bd3dbf0bdce /doc | |
| parent | 9818f1c535217a2b70cb6f248dcc93fd7055e331 (diff) | |
IAP doc: tutorial (#20317)
* [ADD] doc: iap tutorial
Should be easier to approach than the raw APIDoc.
contains:
- overview of the flow
- tutorial (coalroller) with guidelines
- technical description of objects/helpers
Diffstat (limited to 'doc')
| -rw-r--r-- | doc/_extensions/odoo_ext/translator.py | 4 | ||||
| -rw-r--r-- | doc/howtos/website/course-m2o | 1 | ||||
| -rw-r--r-- | doc/howtos/website/course-product | 7 | ||||
| -rw-r--r-- | doc/webservices/flow.png | bin | 14726 -> 0 bytes | |||
| -rw-r--r-- | doc/webservices/iap.rst | 386 | ||||
| -rw-r--r-- | doc/webservices/iap/01-init | 16 | ||||
| -rw-r--r-- | doc/webservices/iap/02-button | 34 | ||||
| -rw-r--r-- | doc/webservices/iap/03-callback | 40 | ||||
| -rw-r--r-- | doc/webservices/iap/series | 3 | ||||
| -rw-r--r-- | doc/webservices/iap_service/01-init | 16 | ||||
| -rw-r--r-- | doc/webservices/iap_service/02-tnx | 48 | ||||
| -rw-r--r-- | doc/webservices/iap_service/03-template | 56 | ||||
| -rw-r--r-- | doc/webservices/iap_service/series | 3 | ||||
| -rw-r--r-- | doc/webservices/images/button.png | bin | 0 -> 18845 bytes | |||
| -rw-r--r-- | doc/webservices/images/flow.png | bin | 0 -> 10520 bytes | |||
| -rw-r--r-- | doc/webservices/images/no-credit.png | bin | 0 -> 36604 bytes | |||
| -rw-r--r-- | doc/webservices/images/normal.png | bin | 0 -> 38028 bytes | |||
| -rw-r--r-- | doc/webservices/images/players.png | bin | 0 -> 51317 bytes | |||
| -rw-r--r-- | doc/webservices/images/template.png | bin | 0 -> 42268 bytes |
19 files changed, 556 insertions, 58 deletions
diff --git a/doc/_extensions/odoo_ext/translator.py b/doc/_extensions/odoo_ext/translator.py index 1c6d1c86d2e..9b038fd906b 100644 --- a/doc/_extensions/odoo_ext/translator.py +++ b/doc/_extensions/odoo_ext/translator.py @@ -381,6 +381,10 @@ class BootstrapTranslator(nodes.NodeVisitor, object): "Unsupported alignment value \"%s\"" % node['align'], location=doc ) + elif 'align' in node.parent and node.parent['align'] == 'center': + # figure > image + attrs['class'] += ' center-block' + # todo: explicit width/height/scale? self.body.append(self.starttag(node, 'img', **attrs)) def depart_image(self, node): pass diff --git a/doc/howtos/website/course-m2o b/doc/howtos/website/course-m2o index 8daabaedb7d..d70c0f524da 100644 --- a/doc/howtos/website/course-m2o +++ b/doc/howtos/website/course-m2o @@ -22,4 +22,3 @@ diff --git a/academy/security/ir.model.access.csv b/academy/security/ir.model.ac id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_academy_teachers,access_academy_teachers,model_academy_teachers,,1,0,0,0 +access_academy_courses,access_academy_courses,model_academy_courses,,1,0,0,0 -\ No newline at end of file diff --git a/doc/howtos/website/course-product b/doc/howtos/website/course-product index 53aa555be52..252241150ec 100644 --- a/doc/howtos/website/course-product +++ b/doc/howtos/website/course-product @@ -9,7 +9,7 @@ diff --git a/academy/__manifest__.py b/academy/__manifest__.py 'security/ir.model.access.csv', 'templates.xml', 'views.xml', -+ 'data.xml', ++ 'data.xml', ], # only loaded in demonstration mode 'demo': [ @@ -79,11 +79,8 @@ diff --git a/academy/security/ir.model.access.csv b/academy/security/ir.model.ac +++ b/academy/security/ir.model.access.csv @@ -1,3 +1,2 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink --access_academy_teachers,access_academy_teachers,model_academy_teachers,,1,0,0,0 + access_academy_teachers,access_academy_teachers,model_academy_teachers,,1,0,0,0 -access_academy_courses,access_academy_courses,model_academy_courses,,1,0,0,0 -\ No newline at end of file -+access_academy_teachers,access_academy_teachers,model_academy_teachers,,1,0,0,0 -\ No newline at end of file diff --git a/academy/views.xml b/academy/views.xml --- a/academy/views.xml +++ b/academy/views.xml diff --git a/doc/webservices/flow.png b/doc/webservices/flow.png Binary files differdeleted file mode 100644 index df4bf7cfbbb..00000000000 --- a/doc/webservices/flow.png +++ /dev/null diff --git a/doc/webservices/iap.rst b/doc/webservices/iap.rst index 18af76900fb..382fd6da428 100644 --- a/doc/webservices/iap.rst +++ b/doc/webservices/iap.rst @@ -1,10 +1,41 @@ :types: api - -:code-column: - .. _webservices/iap: +.. using sphinx-patchqueue: + * the "queue" directive selects a *series* file which lists the patches in + the patch queue, in order of application (from top to bottom). The + corresponding patch files should be in the same directory. + * the "patch" directive steps to the next patch in the queue, applies it + and reifies its content (depending on the extension's configuration, by + default it shows the changed files post-diff application, slicing to + only display sections affecte by the file) + +.. while it's technically possible to apply and update patches by hand, it's + finnicky work and easy to break. + +.. the easiest way is to install quilt (http://savannah.nongnu.org/projects/quilt), + go to the directory where you want to reify the addon, then create a + "patches" symlink to the patches directory (the iap/ folder next to this + file) or set QUILT_PATCHES to that folder. + +.. at that point you have a "primed" queue with no patch applied, and you can + move within the queue with "quilt push" and "quilt pop". + * "quilt new" creates a new empty patch at the top of the stack + * "quilt add" tells quilt to start tracking the file, quilt add *works per + patch*, it must be called *every time you want to alter a file within a + patch*: quilt is not a full VCS (since it's intended to sit on top of + an existing source) and does not do permanent tracking of files + * "quilt edit" is a shorthand to "quilt add" then open the file in your + editor, I suggest you use that rather than open the edited module + normally, it avoids forgetting to "quilt add" before doing your + modifications (at which point your modifications are untracked, + invisible and depending on your editor may be a PITA to revert & redo) + * "quilt refresh" updates the current patch to include pending changes + +.. see "man quilt" for the rest of the subcommands. FWIW I could not get + "quilt setup" to do anything useful. + ================ In-App Purchases ================ @@ -13,11 +44,12 @@ IAP allow providers of ongoing services through Odoo apps to be compensated for ongoing service use rather than — and possibly instead of — a sole initial purchase. -In that context, Odoo acts mostly as a *broker* between the service user -(client) and the service provider (Odoo App developer): +In that context, Odoo acts mostly as a *broker* between a client and an Odoo +App Developer: * users purchase service tokens from Odoo -* service providers draw tokens from the user's Odoo account +* service providers draw tokens from the user's Odoo account when service + is requested .. attention:: @@ -25,54 +57,262 @@ In that context, Odoo acts mostly as a *broker* between the service user which can be done either via direct JSON-RPC2_ or if you are using Odoo using the convenience helpers it provides. -.. image:: flow.png +Overview +======== + +.. figure:: images/players.png :align: center -.. contents:: - :local: + The Players -JSON-RPC2_ Transaction API -========================== + * The Service Provider is (probably) you the reader, you will be providing + value to the client in the form of a service paid per-use + * The Client installed your Odoo App, and from there will request services + * Odoo brokers crediting, the Client adds credit to their account, and you + can draw credits from there to provide services + * The External Service is an optional player: *you* can either provide a + service directly, or you can delegate the actual service acting as a + bridge/translator between an Odoo system and the actual service -* The IAP transaction API does not require using Odoo when implementing your - server gateway, calls are standard JSON-RPC2_. -* Calls use different *endpoints* but the same *method* on all endpoints - (``call``). -* Exceptions are returned as JSON-RPC2_ errors, the formal exception name is - available on ``data.name`` for programmatic manipulation. +.. note:: in the following explanations we will ignore the External Service, + they're just a detail of the service you provide -.. class:: ServiceKey +.. figure:: images/normal.png + :align: center - Identifier generated for the provider's service. Each key (and service) - matches a token of a fixed value, as generated by the service provide. + A "normal" service flow - Multiple types of tokens correspond to multiple services e.g. SMS and MMS - could either be the same service (with an MMS being "worth" multiple SMS) - or could be separate services at separate price points. + If everything goes well, the normal flow is: - .. danger:: your service key *is a secret*, leaking your service key - allows other application developers to draw credits bought for - your service(s) + 1. the Client requests a service of some sort + 2. the Service Provider asks Odoo if there are enough credits for the + service in the Client's account, and creates a transaction over that + amount + 3. the Service Provider provides the service (either on their own or + calling to External Services) + 4. the Service Provider goes back to Odoo to capture (if the service could + be provided) or cancel (if the service could not be provided) the + transaction created at step 2 + 5. finally the Service Provider notifies the Client that the service has + been rendered, possibly (depending on the service) displaying or + storing its results in the client's system -.. class:: UserToken +.. figure:: images/no-credit.png + :align: center - Identifier for a user account. + Insufficient Credits -.. class:: TransactionToken + If the Client's account lacks credits for the service, however - Transaction identifier, returned by the authorization process and consumed - by either capturing or cancelling the transaction + 1. the Client requests a service as previously + 2. the Service Provider asks Odoo if there are enough credits on the + Client's account and gets a negative reply + 3. this is signaled back to the Client + 4. who is redirected to their Odoo account to credit it and re-try -.. exception:: odoo.addons.iap.models.iap.NoCreditError - Raised during transaction authorization if the credits requested are not - currently available on the account (either not enough credits or too many - pending transactions/existing holds). +Building your service +===================== + +For this example, the service we will provide is ~~mining dogecoins~~ burning +10 seconds of CPU for a credit. For your own services, you could for example: + +* provide an online service yourself (e.g. convert quotations to faxes for + business in Japan) +* provide an *offline* service yourself (e.g. provide accountancy service) +* act as intermediary to an other service provider (e.g. bridge to an MMS + gateway) + +Register the service on Odoo +---------------------------- + +.. queue:: iap_service/series + +.. todo:: complete this part with screenshots + +The first step is to register your service on the IAP endpoint (production +and/or test) before you can actually query user accounts. To create a service, +go to your *Portal Account* on the IAP endpoint (https://iap.odoo.com for +production, http://iap-sandbox.odoo.com for testing, the endpoints are +*independent* and *not synchronized*). + +Log in then go to :menuselection:`My Account --> Your InApp Services`, click +Create and provide the name of your service. + + +The now created service has *two* important fields: + +* :samp:`name` - :class:`ServiceName`: this will identify your service in the + client's :ref:`app <iap-odoo-app>` communicates directly with IAP. +* :samp:`key` - :class:`ServiceKey`: the developer key that identifies you in + IAP (see :ref:`your service <iap-service>`) and allows to draw credits from the client's account. + +.. warning:: + The :class:`ServiceName` is unique and should usually match the name of your + Odoo App. + +.. danger:: + Your :class:`ServiceKey` *is a secret*, leaking your service key + allows other application developers to draw credits bought for + your service(s). + +.. image:: images/service_select.png + :align: center + +.. image:: images/service_create.png + :align: center + +.. image:: images/service_packs.png + :align: center + +You can then create *credit packs* which clients can purchase in order to +use your service. + +.. _iap-odoo-app: + +Odoo App +-------- + +.. queue:: iap/series + +.. todo:: does this actually require apps? + +The second step is to develop an `Odoo App`_ which clients can install in their +Odoo instance and through which they can *request* services you will provide. +Our app will just add a button to the Partners form which lets a user request +burning some CPU time on the server. + +First, we'll create an *odoo module* depending on ``iap``. IAP is a standard +V11 module and the dependency ensures a local account is properly set up and +we will have access to some necessary views and useful helpers + +.. patch:: + +Second, the "local" side of the integration, here we will only be adding an +action button to the partners view, but you can of course provide significant +local value via your application and additional parts via a remote service. + +.. patch:: + +.. image:: images/button.png + :align: center + +We can now implement the action method/callback. This will *call our own +server*. + +There are no requirements when it comes to the server or the communication +protocol between the app and our server, but ``iap`` provides a +:func:`~odoo.addons.iap.jsonrpc` helper to call a JSON-RPC2_ endpoint on an +other Odoo instance and transparently re-raise relevant Odoo exceptions +(:class:`~odoo.addons.iap.models.iap.InsufficientCreditError`, +:class:`odoo.exceptions.AccessError` and :class:`odoo.exceptions.UserError`). + +In that call, we will need to provide: + +* any relevant client parameter (none here) +* the :class:`token <UserToken>` of the current client, this is provided by + the ``iap.account`` model's ``account_token`` field. You can retrieve the + account for your service by calling :samp:`env['iap.account'].get({service_name})` + where :class:`service_name <ServiceName>` is the name of the service registered + on IAP endpoint. + +.. patch:: + +.. note:: + + ``iap`` automatically handles + :class:`~odoo.addons.iap.models.iap.InsufficientCreditError` coming from the action + and prompts the user to add credits to their account. + + :func:`~odoo.addons.iap.jsonrpc` takes care of re-raising + :class:`~odoo.addons.iap.models.iap.InsufficientCreditError` for you. + +.. danger:: + + If you are not using :func:`~odoo.addons.iap.jsonrpc` you *must* be + careful to re-raise + :class:`~odoo.addons.iap.models.iap.InsufficientCreditError` in your handler + otherwise the user will not be prompted to credit their account, and the + next call will fail the same way. + +.. _iap-service: + +Service +------- + +.. queue:: iap_service/series + +Though that is not *required*, since ``iap`` provides both a client helper +for JSON-RPC2_ calls (:func:`~odoo.addons.iap.jsonrpc`) and a service helper +for transactions (:class:`~odoo.addons.iap.models.iap.charge`) we will also be +implementing the service side as an Odoo module: + +.. patch:: + +Since the query from the client comes as JSON-RPC2_ we will need the +corresponding controller which can call :class:`~odoo.addons.iap.models.iap.charge` and +perform the service within: + +.. patch:: + +.. todo:: for the actual IAP will the "portal" page be on odoo.com or iap.odoo.com? + +.. todo:: "My Account" > "Your InApp Services"? + +The :class:`~odoo.addons.iap.models.iap.charge` helper will: + +1. authorize (create) a transaction with the specified number of credits, + if the account does not have enough credits it will raise the relevant + error +2. execute the body of the ``with`` statement +3. if the body of the ``with`` executes succesfully, capture (confirm) the + transaction +4. otherwise if an error is raised from the body of the ``with`` cancel the + transaction (and release the hold on the credits) + +.. danger:: + + By default, :class:`~odoo.addons.iap.models.iap.charge` contacts the *production* + IAP endpoint, https://iap.odoo.com. While developing and testing your + service you may want to point it towards the *development* IAP endpoint + https://iap-sandbox.odoo.com. + + To do so, set the ``iap.endpoint`` config parameter in your service + Odoo: in debug/developer mode, :menuselection:`Setting --> Technical --> + Parameters --> System Parameters`, just define an entry for the key + ``iap.endpoint`` if none already exists). + +The :class:`~odoo.addons.iap.models.iap.charge` helper has two additional optional +parameters we can use to make things clearer to the end-user: + +``description`` + is a message which will be associated with the transaction and will be + displayed in the user's dashboard, it is useful to remind the user why + the charge exists +``credit_template`` + is the name of a :ref:`reference/qweb` template which will be rendered + and shown to the user if their account has less credit available than the + service provider is requesting, its purpose is to tell your users why + they should be interested in your IAP offers + +.. patch:: -.. exception:: odoo.addons.iap.models.iap.BadAuthError - Raised by any operation to which a service token is required, if the - service token is invalid. + +.. TODO:: how do you test your service? + +JSON-RPC2_ Transaction API +========================== + +.. image:: images/flow.png + :align: center + +* The IAP transaction API does not require using Odoo when implementing your + server gateway, calls are standard JSON-RPC2_. +* Calls use different *endpoints* but the same *method* on all endpoints + (``call``). +* Exceptions are returned as JSON-RPC2_ errors, the formal exception name is + available on ``data.name`` for programmatic manipulation. Authorize --------- @@ -94,12 +334,10 @@ Authorize :param str description: optional, helps users identify the reason for charges on their accounts. :returns: :class:`TransactionToken` if the authorization succeeded. - :raises: :class:`~odoo.addons.iap.models.iap.BadAuthError` if the service token is invalid - :raises: :class:`~odoo.addons.iap.models.iap.NoCreditError` if the account does + :raises: :class:`~odoo.exceptions.AccessError` if the service token is invalid + :raises: :class:`~odoo.addons.iap.models.iap.InsufficientCreditError` if the account does :raises: ``TypeError`` if the ``credit`` value is not an integer -.. rst-class:: doc-aside - .. code-block:: python r = requests.post(ODOO + '/iap/1/authorize', json={ @@ -132,9 +370,7 @@ Capture :param TransactionToken token: :param ServiceKey key: - :raises: :class:`~odoo.addons.iap.models.iap.BadAuthError` - -.. rst-class:: doc-aside + :raises: :class:`~odoo.exceptions.AccessError` .. code-block:: python @@ -164,9 +400,7 @@ Cancel :param TransactionToken token: :param ServiceKey key: - :raises: :class:`~odoo.addons.iap.models.iap.BadAuthError` - -.. rst-class:: doc-aside + :raises: :class:`~odoo.exceptions.AccessError` .. code-block:: python @@ -183,6 +417,56 @@ Cancel # handle cancel error # otherwise transaction is cancelled +Types +----- + +Exceptions aside, these are *abstract types* used for clarity, you should not +care how they are implemented + +.. class:: ServiceName + + String identifying your service on https://iap.odoo.com (production) as well + as the account related to your service in the client's database. + +.. class:: ServiceKey + + Identifier generated for the provider's service. Each key (and service) + matches a token of a fixed value, as generated by the service provide. + + Multiple types of tokens correspond to multiple services e.g. SMS and MMS + could either be the same service (with an MMS being "worth" multiple SMS) + or could be separate services at separate price points. + + .. danger:: your service key *is a secret*, leaking your service key + allows other application developers to draw credits bought for + your service(s). + +.. class:: UserToken + + Identifier for a user account. + +.. class:: TransactionToken + + Transaction identifier, returned by the authorization process and consumed + by either capturing or cancelling the transaction + +.. exception:: odoo.addons.iap.models.iap.InsufficientCreditError + + Raised during transaction authorization if the credits requested are not + currently available on the account (either not enough credits or too many + pending transactions/existing holds). + +.. exception:: odoo.exceptions.AccessError + + Raised by: + + * any operation to which a service token is required, if the service token is invalid. + * any failure in an inter-server call. (typically, in :func:`~odoo.addons.iap.jsonrpc`) + +.. exception:: odoo.exceptions.UserError + + Raised by any unexpeted behaviour at the discretion of the App developer (*you*). + Odoo Helpers ============ @@ -192,7 +476,7 @@ module provides a few helpers to make IAP flow even simpler: Charging -------- -.. class:: odoo.addons.iap.models.iap.charge(env, key, account_token, credit[, description]) +.. class:: odoo.addons.iap.models.iap.charge(env, key, account_token, credit[, description, credit_template]) A *context manager* for authorizing and automatically capturing or cancelling transactions for use in the backend/proxy. @@ -211,8 +495,6 @@ Charging :param int credit: :param str description: -.. rst-class:: doc-aside - .. code-block:: python @route('/deathstar/superlaser', type='json') @@ -231,5 +513,5 @@ Charging ('name', '=', 'Alderaan'), ]).unlink() - .. _JSON-RPC2: http://www.jsonrpc.org/specification +.. _Odoo App: https://www.odoo.com/apps diff --git a/doc/webservices/iap/01-init b/doc/webservices/iap/01-init new file mode 100644 index 00000000000..243dd911e97 --- /dev/null +++ b/doc/webservices/iap/01-init @@ -0,0 +1,16 @@ +Index: coalroller/coalroller/__manifest__.py +=================================================================== +--- /dev/null ++++ coalroller/coalroller/__manifest__.py +@@ -0,0 +1,5 @@ ++{ ++ 'name': "Coal Roller", ++ 'category': 'Tools', ++ 'depends': ['iap'], ++} +Index: coalroller/coalroller/__init__.py +=================================================================== +--- /dev/null ++++ coalroller/coalroller/__init__.py +@@ -0,0 +1 @@ ++# -*- coding: utf-8 -*- diff --git a/doc/webservices/iap/02-button b/doc/webservices/iap/02-button new file mode 100644 index 00000000000..c5e73606e85 --- /dev/null +++ b/doc/webservices/iap/02-button @@ -0,0 +1,34 @@ +Index: coalroller/coalroller/__manifest__.py +=================================================================== +--- coalroller.orig/coalroller/__manifest__.py ++++ coalroller/coalroller/__manifest__.py +@@ -2,4 +2,7 @@ + 'name': "Coal Roller", + 'category': 'Tools', + 'depends': ['iap'], ++ 'data': [ ++ 'views/views.xml', ++ ], + } +Index: coalroller/coalroller/views/views.xml +=================================================================== +--- /dev/null ++++ coalroller/coalroller/views/views.xml +@@ -0,0 +1,17 @@ ++<odoo> ++ <record model="ir.ui.view" id="partner_form_coalroll"> ++ <field name="name">partner.form.coalroll</field> ++ <field name="model">res.partner</field> ++ <field name="inherit_id" ref="base.view_partner_form" /> ++ <field name="arch" type="xml"> ++ <xpath expr="//div[@name='button_box']"> ++ <button type="object" name="action_partner_coalroll" ++ class="oe_stat_button" icon="fa-gears"> ++ <div class="o_form_field o_stat_info"> ++ <span class="o_stat_text">Roll Coal</span> ++ </div> ++ </button> ++ </xpath> ++ </field> ++ </record> ++</odoo> diff --git a/doc/webservices/iap/03-callback b/doc/webservices/iap/03-callback new file mode 100644 index 00000000000..675f117da42 --- /dev/null +++ b/doc/webservices/iap/03-callback @@ -0,0 +1,40 @@ +Index: coalroller/coalroller/__init__.py +=================================================================== +--- coalroller.orig/coalroller/__init__.py ++++ coalroller/coalroller/__init__.py +@@ -1 +1,2 @@ + # -*- coding: utf-8 -*- ++from . import models +Index: coalroller/coalroller/models/__init__.py +=================================================================== +--- /dev/null ++++ coalroller/coalroller/models/__init__.py +@@ -0,0 +1 @@ ++from . import res_partner +Index: coalroller/coalroller/models/res_partner.py +=================================================================== +--- /dev/null ++++ coalroller/coalroller/models/res_partner.py +@@ -0,0 +1,22 @@ ++# -*- coding: utf-8 -*- ++from odoo import api, models ++from odoo.addons.iap import jsonrpc, InsufficientCreditError ++ ++# whichever URL you deploy the service at, here we will run the remote ++# service in a local Odoo bound to the port 8070 ++DEFAULT_ENDPOINT = 'http://localhost:8070' ++class Partner(models.Model): ++ _inherit = 'res.partner' ++ @api.multi ++ def action_partner_coalroll(self): ++ # fetch the user's token for our service ++ user_token = self.env['iap.account'].get('coalroller') ++ params = { ++ # we don't have any parameter to provide ++ 'account_token': user_token.account_token ++ } ++ # ir.config_parameter allows locally overriding the endpoint ++ # for testing & al ++ endpoint = self.env['ir.config_parameter'].sudo().get_param('coalroller.endpoint', DEFAULT_ENDPOINT) ++ jsonrpc(endpoint + '/roll', params=params) ++ return True diff --git a/doc/webservices/iap/series b/doc/webservices/iap/series new file mode 100644 index 00000000000..d44682b30f0 --- /dev/null +++ b/doc/webservices/iap/series @@ -0,0 +1,3 @@ +01-init +02-button +03-callback diff --git a/doc/webservices/iap_service/01-init b/doc/webservices/iap_service/01-init new file mode 100644 index 00000000000..0ffc92159ad --- /dev/null +++ b/doc/webservices/iap_service/01-init @@ -0,0 +1,16 @@ +Index: coalroller_service/coalroller_service/__init__.py +=================================================================== +--- /dev/null ++++ coalroller_service/coalroller_service/__init__.py +@@ -0,0 +1 @@ ++# -*- encoding: utf-8 -*- +Index: coalroller_service/coalroller_service/__manifest__.py +=================================================================== +--- /dev/null ++++ coalroller_service/coalroller_service/__manifest__.py +@@ -0,0 +1,5 @@ ++{ ++ 'name': "Coal Roller Service", ++ 'category': 'Tools', ++ 'depends': ['iap'], ++} diff --git a/doc/webservices/iap_service/02-tnx b/doc/webservices/iap_service/02-tnx new file mode 100644 index 00000000000..68cfbdc82e3 --- /dev/null +++ b/doc/webservices/iap_service/02-tnx @@ -0,0 +1,48 @@ +Index: coalroller_service/coalroller_service/controllers/main.py +=================================================================== +--- /dev/null ++++ coalroller_service/coalroller_service/controllers/main.py +@@ -0,0 +1,29 @@ ++import time ++ ++from passlib import pwd, hash ++ ++from odoo import http ++from odoo.addons.iap import charge ++ ++class CoalBurnerController(http.Controller): ++ @http.route('/roll', type='json', auth='none', csrf='false') ++ def roll(self, account_token): ++ # the service key *is a secret*, it should not be committed in ++ # the source ++ service_key = self.env['ir.config_parameter'].sudo().get_param('coalroller.service_key') ++ ++ # we charge 1 credit for 10 seconds of CPU ++ cost = 1 ++ # TODO: allow the user to specify how many (tens of seconds) of CPU they want to use ++ with charge(http.request.env, service_key, account_token, cost): ++ ++ # 10 seconds of CPU per credit ++ end = time.time() + (10 * cost) ++ while time.time() < end: ++ # we will use CPU doing useful things: generating and ++ # hashing passphrases ++ p = pwd.genphrase() ++ h = hash.pbkdf2_sha512.hash(p) ++ # here we don't have anything useful to the client, an error ++ # will be raised & transmitted in case of issue, if no error ++ # is raised we did the job +Index: coalroller_service/coalroller_service/controllers/__init__.py +=================================================================== +--- /dev/null ++++ coalroller_service/coalroller_service/controllers/__init__.py +@@ -0,0 +1,2 @@ ++# -*- encoding: utf-8 -*- ++from . import main +Index: coalroller_service/coalroller_service/__init__.py +=================================================================== +--- coalroller_service.orig/coalroller_service/__init__.py ++++ coalroller_service/coalroller_service/__init__.py +@@ -1 +1,2 @@ + # -*- encoding: utf-8 -*- ++from . import controllers diff --git a/doc/webservices/iap_service/03-template b/doc/webservices/iap_service/03-template new file mode 100644 index 00000000000..6517181ce29 --- /dev/null +++ b/doc/webservices/iap_service/03-template @@ -0,0 +1,56 @@ +Index: coalroller_service/coalroller_service/controllers/main.py +=================================================================== +--- coalroller_service.orig/coalroller_service/controllers/main.py ++++ coalroller_service/coalroller_service/controllers/main.py +@@ -10,12 +10,14 @@ class CoalBurnerController(http.Controll + def roll(self, account_token): + # the service key *is a secret*, it should not be committed in + # the source +- service_key = self.env['ir.config_parameter'].sudo().get_param('coalroller.service_key') ++ service_key = http.request.env['ir.config_parameter'].sudo().get_param('coalroller.service_key') + + # we charge 1 credit for 10 seconds of CPU + cost = 1 + # TODO: allow the user to specify how many (tens of seconds) of CPU they want to use +- with charge(http.request.env, service_key, account_token, cost): ++ with charge(http.request.env, service_key, account_token, cost, ++ description="We're just obeying orders", ++ credit_template='coalroller_service.no_credit'): + + # 10 seconds of CPU per credit + end = time.time() + (10 * cost) +Index: coalroller_service/coalroller_service/views/no-credit.xml +=================================================================== +--- /dev/null ++++ coalroller_service/coalroller_service/views/no-credit.xml +@@ -0,0 +1,18 @@ ++<odoo> ++ <template id="no_credit" name="No credit warning"> ++ <div> ++ <div class="container-fluid"> ++ <div class="row"> ++ <div class="col-sm-7 col-md-offset-1 mt32 mb32"> ++ <h2>Consume electricity doing nothing useful!</h2> ++ <ul> ++ <li>Heat our state of the art data center for no reason</li> ++ <li>Use multiple watts for only 0.1€</li> ++ <li>Roll coal without going outside</li> ++ </ul> ++ </div> ++ </div> ++ </div> ++ </div> ++ </template> ++</odoo> +Index: coalroller_service/coalroller_service/__manifest__.py +=================================================================== +--- coalroller_service.orig/coalroller_service/__manifest__.py ++++ coalroller_service/coalroller_service/__manifest__.py +@@ -2,4 +2,7 @@ + 'name': "Coal Roller Service", + 'category': 'Tools', + 'depends': ['iap'], ++ 'data': [ ++ 'views/no-credit.xml', ++ ], + } diff --git a/doc/webservices/iap_service/series b/doc/webservices/iap_service/series new file mode 100644 index 00000000000..68544a42924 --- /dev/null +++ b/doc/webservices/iap_service/series @@ -0,0 +1,3 @@ +01-init +02-tnx +03-template diff --git a/doc/webservices/images/button.png b/doc/webservices/images/button.png Binary files differnew file mode 100644 index 00000000000..689abececd6 --- /dev/null +++ b/doc/webservices/images/button.png diff --git a/doc/webservices/images/flow.png b/doc/webservices/images/flow.png Binary files differnew file mode 100644 index 00000000000..a3edab03573 --- /dev/null +++ b/doc/webservices/images/flow.png diff --git a/doc/webservices/images/no-credit.png b/doc/webservices/images/no-credit.png Binary files differnew file mode 100644 index 00000000000..5b5763bd183 --- /dev/null +++ b/doc/webservices/images/no-credit.png diff --git a/doc/webservices/images/normal.png b/doc/webservices/images/normal.png Binary files differnew file mode 100644 index 00000000000..2e9cbcfc50f --- /dev/null +++ b/doc/webservices/images/normal.png diff --git a/doc/webservices/images/players.png b/doc/webservices/images/players.png Binary files differnew file mode 100644 index 00000000000..291466c4976 --- /dev/null +++ b/doc/webservices/images/players.png diff --git a/doc/webservices/images/template.png b/doc/webservices/images/template.png Binary files differnew file mode 100644 index 00000000000..6f989273f10 --- /dev/null +++ b/doc/webservices/images/template.png |
