Skip to content

Commit 8a5eaea

Browse files
committed
Sync from github
1 parent 85dfb6d commit 8a5eaea

File tree

3 files changed

+177
-0
lines changed

3 files changed

+177
-0
lines changed

config/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
config.json
2+
service-account.json
3+
.idea

config/README.md

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
Firebase Remote Config REST API Python Quickstart
2+
===============================================
3+
4+
The Firebase Remote Config Python quickstart app demonstrates retrieving and
5+
updating the Firebase Remote Config template.
6+
7+
Introduction
8+
------------
9+
10+
This is a simple example of using the Firebase Remote Config REST API to update
11+
the Remote Config template being used by clients apps.
12+
13+
Getting started
14+
---------------
15+
16+
1. [Add Firebase to your Android Project](https://firebase.google.com/docs/android/setup).
17+
2. Create a service account as described in [Adding Firebase to your Server](https://firebase.google.com/docs/admin/setup) and download the JSON file.
18+
- Copy the private key JSON file to this folder and rename it to `service-account.json`.
19+
3. Change the `PROJECT_ID` variable in `configure.py` to your project ID.
20+
21+
Run
22+
---
23+
24+
- From the `config` directory run `python configure.py --action=get` to retrieve the template.
25+
- The returned template is stored in a file named `config.json`.
26+
- Note the Etag printed to the console you will need to use it when publishing template updates.
27+
- Update the template.
28+
- If your template already has parameters, adjust one or more of the values.
29+
- If your template is empty, update it to look like this:
30+
31+
{
32+
"conditions": [
33+
{
34+
"name": "AndroidUsers",
35+
"expression": "device.os == 'android'",
36+
"tagColor": "PURPLE"
37+
},
38+
{
39+
"name": "iOSUsers",
40+
"expression": "device.os == 'ios'",
41+
"tagColor": "GREEN"
42+
}
43+
],
44+
"parameters": {
45+
"welcome_message": {
46+
"defaultValue": {
47+
"value": "Welcome"
48+
},
49+
"conditionalValues": {
50+
"AndroidUsers": {
51+
"value": "Welcome Android User"
52+
},
53+
"iOSUsers": {
54+
"value": "Welcome iOS User"
55+
}
56+
}
57+
}
58+
}
59+
}
60+
61+
- From the `config` directory run `python configure.py --action=publish --etag=<LATEST_ETAG>` to update the template.
62+
- Be sure to set the etag to the one that was last printed in the console.
63+
- Confirm in the console that the template has been updated.
64+
- At this point mobile clients can fetch the updated values.
65+
66+
Best practices
67+
--------------
68+
69+
This section provides some additional information about how the Remote Config
70+
REST API should be used when retrieving and updating templates.
71+
72+
### Etags ###
73+
74+
Eath time the Remote Config template is retrieved an Etag is included. This Etag is a
75+
unique identifier of the current template on the server. When submitting updates
76+
to the template you must include the latest Etag to ensure that your updates are consistent.
77+
78+
In the event that you want to completely overwrite the server's template use
79+
an Etag of "\*". Use this with caution since this operation cannot be undone.
80+
81+
Support
82+
-------
83+
84+
- [Stack Overflow](https://stackoverflow.com/questions/tagged/firebase-cloud-messaging)
85+
- [Firebase Support](https://firebase.google.com/support/)

config/configure.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import argparse
2+
import requests
3+
import io
4+
5+
from oauth2client.service_account import ServiceAccountCredentials
6+
7+
8+
PROJECT_ID = '<PROJECT_ID>'
9+
BASE_URL = 'https://firebaseremoteconfig.googleapis.com'
10+
REMOTE_CONFIG_ENDPOINT = 'v1/projects/' + PROJECT_ID + '/remoteConfig'
11+
REMOTE_CONFIG_URL = BASE_URL + '/' + REMOTE_CONFIG_ENDPOINT
12+
SCOPES = ['https://www.googleapis.com/auth/firebase.remoteconfig']
13+
14+
# [START retrieve_access_token]
15+
def _get_access_token():
16+
"""Retrieve a valid access token that can be used to authorize requests.
17+
18+
:return: Access token.
19+
"""
20+
credentials = ServiceAccountCredentials.from_json_keyfile_name(
21+
'service-account.json', SCOPES)
22+
access_token_info = credentials.get_access_token()
23+
return access_token_info.access_token
24+
# [END retrieve_access_token]
25+
26+
def _get():
27+
"""Retrieve the current Firebase Remote Config template from server.
28+
29+
Retrieve the current Firebase Remote Config template from server and store it
30+
locally.
31+
"""
32+
headers = {
33+
'Authorization': 'Bearer ' + _get_access_token()
34+
}
35+
resp = requests.get(REMOTE_CONFIG_URL, headers=headers)
36+
37+
if resp.status_code == 200:
38+
with io.open('config.json', 'wb') as f:
39+
f.write(resp.text.encode('utf-8'))
40+
41+
print('Retrieved template has been written to config.json')
42+
print('ETag from server: {}'.format(resp.headers['ETag']))
43+
else:
44+
print('Unable to get template')
45+
print(resp.text)
46+
47+
48+
def _publish(etag):
49+
"""Publish local template to Firebase server.
50+
51+
Args:
52+
etag: ETag for safe (avoid race conditions) template updates.
53+
* can be used to force template replacement.
54+
"""
55+
with open('config.json', 'r', encoding='utf-8') as f:
56+
content = f.read()
57+
headers = {
58+
'Authorization': 'Bearer ' + _get_access_token(),
59+
'Content-Type': 'application/json; UTF-8',
60+
'If-Match': etag
61+
}
62+
resp = requests.put(REMOTE_CONFIG_URL, data=content.encode('utf-8'), headers=headers)
63+
if resp.status_code == 200:
64+
print('Template has been published.')
65+
print('ETag from server: {}'.format(resp.headers['ETag']))
66+
else:
67+
print('Unable to publish template.')
68+
print(resp.text)
69+
70+
71+
def main():
72+
parser = argparse.ArgumentParser()
73+
parser.add_argument('--action')
74+
parser.add_argument('--etag')
75+
args = parser.parse_args()
76+
77+
if args.action and args.action == 'get':
78+
_get()
79+
elif args.action and args.action == 'publish' and args.etag:
80+
_publish(args.etag)
81+
else:
82+
print('''Invalid command. Please use one of the following commands:
83+
python configure.py --action=get
84+
python configure.py --action=publish --etag=<LATEST_ETAG>''')
85+
86+
87+
88+
if __name__ == '__main__':
89+
main()

0 commit comments

Comments
 (0)