Try ERPNext Try Frappe Cloud Buy Support Partners Foundation

Multi site requests

@rahy I was under impression when you said you are developing custom application. I myself am new to erpnext and learning the customizations. But the idea is the branches will generate or publish messages when someone clicks the button and the custom app will listen/subscribe to these messages and post it to master… Check this article at medium: How to get Realtime Updates in your App from ERPNext via Socket.io and Redis | by Parth Joshi | Medium

But I am afraid these needs some development skills.

I think I generally understand the logic of the article. But I don’t need real-time communication of data. It’s only once get and keep. So I think session and/or cookies would do it. Of course, I might be wrong :slight_smile:

On the other hand, the custom app that act as repository of central data to be used is not really useful (again…I think) because if the custom app is installed in every sites, these custom apps still need to communicate among them. If this custom app is installed in the central site, actually the User doctype has already functioning as such.

The article differs from my scenario in that it explained the access from multi applications (mobile, web, etc) to a single site, while my scenario needs access from multi sites to one central site (all sites are the same frappe/erpnext but having different role - central vs branch).

I’m already able to do this token retrieval from one branch site to the central. And use it for the subsequent requests.
But doing it from many sites would change the token everytime.

Are the sites hosted on different servers? Why do you need different keys for different site, same key can be used by your branch sites, isn’t? May be I am not able to understand your question correctly.

Yes

It is the User secret that need to be regenerated. I don’t need it to be if C can reuse the first generated secret (by A). But after A, when C sends requests, it regenerates the secret (C is different site than A, hence can’t share the secret generated by A previously).
I hope I explain the issue clearly.

Your understanding of the keys concept is not clear. Can you give me example what you are trying to do in your app? What is getting regenerated? Once a key is generated it can be reused again and again by multiple sites.

Are you using token based auth? See this tutorial: [Tutorial] Using cURL for REST and RPC API calls - Integration - Discuss Frappe/ERPNext


You are talking about this key and secret, right?

As you said, the key can be reused. But Authorization token needs key:secret pair.
It is secret that will be regenerated because sites can’t share it among them.

Yes.
This is what I do:

#1 - First login to the branch site:

urllog = 'https://mysite.com/api/method/login'
paramlog = {
    'usr': 'administrator',
    'pwd': 'a1b2c3'
}
rlog = requests.post(url, headers=headers, params=paramlog)
return rlog.cookies

#2 - then get user (e.g Administrator) secret:

urlsec = 'https://mysite.com/api/method/frappe.core.doctype.user.user.generate_keys'
paramsec = {
    'user': 'Administrator'
}
rsec = requests.post(urlsec, headers=headers, params=paramsec, cookies=logcookies)

#3 - then get key:

urlkey = 'https://mysite.com/api/resource/User'
paramkey = {
    'fields': '["name","api_key"]',
    'filters': '[["name", "=", "Administrator"]]'
}		
rkey = requests.get(urlkey, headers=headers, params=paramkey, cookies=logcookies)

#4 - then create token:

json_objsec = json.loads(rsec.text)
api_secret = str(json_objsec['message']['api_secret'])

json_objkey = json.loads(rkey.text)
api_key = str(json_objkey['message']['api_key'])

token = "token "+api_key+":"+api_secret

#5 - then use the token on other api to create the custom doctype.

headers = {
    'Authorization': token
}
...

My question is with #2 which using generate_keys api. So each time this requests is called it creates new secret (as intended as in the API Access section of User doctype).
I can’t use frappe.get_doc('User') with field api_secret because it will return ********

@rahy You don’t need to generate the secret every time. You create it once and keep it in your configuration and reuse the same secret again and again. It is like database username and password, you generate it once and reuse it whenever you want to connect to database.

I hope you understand what I am saying.
It is generally a good practice to create an API user, generate the key and secret for that user then reuse in your API.

In your step, you will do step no. 2 only once to get the secret, store that secret and reuse it again and again, my friend.

Do you mean to store the secret in the branch site (the origin of requests) or the central site (the target site)?

By this I mean from other branch sites.

The central site will have a user, say API User, you will generate a key and secret. Use web UI to generate the secret and key.

On the branch site B, you can keep the secret and key in config file where app can use to connect to central site and do the API call.

similarly same secret is used on site C, use the same key and secret to connect to make the call

This way only one secret is generate at A and used at B and C.

Edit: The site A is central and B and C are branches…just to be clear.

  1. As I mentioned at my first post, I don’t want the user in central to create the key/secret from the web UI. It needs to be created from the branch sites that want to send request to create the ticket in central.
  2. If central user creates key/secret, it needs to share the key/secret to branches (which is not known beforehand which will send ticket).
  3. The branches sites can’t share the central’s secrets because they don’t know each other.

How will a branch connect to central site without known key and secret? It does not work the way you are thinking.

Anybody wants to connect to API from outside should have secret and key predefined.

You will need to create a secret and key at origin for any source to connect to that origin.

Using the generate_keys endpoint to return api_secret.
And then frappe.get_doc('User') to get the api_key.

Easiest approach is to create an API user for each branch at the central site, use the secret and key for each branch separately so whenever a new branch is established you can use this process. This way branches don’t have shared secret, they have their own key to talk to central site. It is more secure.

This is for local site at branch, not the central site. You want to talk to central site from branch, right?

Yes. from branch to central.

You are not able to follow :slight_smile:

What do you mean?