1+ #!/usr/bin/python
2+ # -*- coding: utf-8 -*-
3+ __author__ = 'stliu'
4+
5+ import requests
6+ import json
7+ from time import time
8+ from requests .auth import AuthBase
9+ import string
10+ import random
11+
12+ JSON_HEADER = {'content-type' : 'application/json' }
13+ EASEMOB_HOST = "https://a1.easemob.com"
14+
15+ DEBUG = False
16+
17+ def id_generator (size = 6 , chars = string .ascii_uppercase + string .digits ):
18+ """用来随机生成用户名, 仅仅用来测试用的"""
19+ return '' .join (random .choice (chars ) for _ in range (size ))
20+
21+ def parse_appkey (appkey ):
22+ """解析appkey, 从中得到org和app, 注意, appkey的规则是 {org}#{app}"""
23+ return tuple (appkey .split ('#' ))
24+
25+ def post (url , payload , auth = None ):
26+ r = requests .post (url , data = json .dumps (payload ), headers = JSON_HEADER , auth = auth )
27+ return http_result (r )
28+
29+
30+ def get (url , auth = None ):
31+ r = requests .get (url , headers = JSON_HEADER , auth = auth )
32+ return http_result (r )
33+
34+
35+ def delete (url , auth = None ):
36+ r = requests .delete (url , headers = JSON_HEADER , auth = auth )
37+ return http_result (r )
38+
39+
40+ def http_result (r ):
41+ if DEBUG :
42+ error_log = {
43+ "method" : r .request .method ,
44+ "url" : r .request .url ,
45+ "request_header" : dict (r .request .headers ),
46+ "response_header" : dict (r .headers ),
47+ "response" : r .text
48+ }
49+ if r .request .body :
50+ error_log ["payload" ] = r .request .body
51+ print json .dumps (error_log )
52+
53+ if r .status_code == requests .codes .ok :
54+ return True , r .json ()
55+ else :
56+ return False , r .text
57+
58+
59+ class Token :
60+ """表示一个登陆获取到的token对象"""
61+ def __init__ (self , token , exipres_in ):
62+ self .token = token
63+ self .exipres_in = exipres_in + int (time ())
64+
65+ def is_not_valid (self ):
66+ """这个token是否还合法, 或者说, 是否已经失效了, 这里我们只需要
67+ 检查当前的时间, 是否已经比或者这个token的时间过去了exipreis_in秒
68+
69+ 即 current_time_in_seconds < (expires_in + token_acquired_time)
70+ """
71+ return time () > self .exipres_in
72+
73+ class EasemobAuth (AuthBase ):
74+ """环信登陆认证的基类"""
75+
76+ def __call__ (self , r ):
77+ r .headers ['Authorization' ] = 'Bearer ' + self .get_token ()
78+ return r
79+
80+ def get_token (self ):
81+ """在这里我们先检查是否已经获取过token, 并且这个token有没有过期"""
82+ if (self .token is None ) or (self .token .is_not_valid ()):
83+ self .token = self .acquire_token () #refresh the token
84+ return self .token .token
85+
86+ def acquire_token (self ):
87+ """真正的获取token的方法, 返回值是一个我们定义的Token对象
88+ 这个留给子类去实现
89+ """
90+ pass
91+
92+ class AppClientAuth (EasemobAuth ):
93+ """使用app的client_id和client_secret来获取app管理员token"""
94+ def __init__ (self , org , app , client_id , client_secret ):
95+ super (AppClientAuth , self ).__init__ ()
96+ self .client_id = client_id
97+ self .client_secret = client_secret
98+ self .url = EASEMOB_HOST + ("/%s/%s/token" % (org , app ))
99+ self .token = None
100+
101+ def acquire_token (self ):
102+ """
103+ 使用clieng_id / client_secret来获取token, 具体的REST API为
104+
105+ POST /{org}/{app}/token {'grant_type':'client_credentials', 'client_id':'xxxx', 'client_secret':'xxxxx'}
106+ """
107+ payload = {'grant_type' :'client_credentials' , 'client_id' : self .client_id , 'client_secret' : self .client_secret }
108+ success , result = post (self .url , payload )
109+ if success :
110+ return Token (result ['access_token' ], result ['expires_in' ])
111+ else :
112+ # throws exception
113+ pass
114+
115+ class AppAdminAccountAuth (EasemobAuth ):
116+ """使用app的管理员账号和密码来获取token"""
117+ def __init__ (self , org , app , username , password ):
118+ super (AppAdminAccountAuth , self ).__init__ ()
119+ self .username = username
120+ self .password = password
121+ self .url = EASEMOB_HOST + ("/%s/%s/token" % (org , app ))
122+ self .token = None
123+
124+ def acquire_token (self ):
125+ """
126+ 使用 username / password 来获取token, 具体的REST API为
127+
128+ POST /{org}/{app}/token {'grant_type':'password', 'username':'xxxx', 'password':'xxxxx'}
129+
130+ 这里和上面使用client_id不同的是, grant_type的类型是password, 然后还需要提供username和password
131+ """
132+ payload = {'grant_type' :'password' , 'username' : self .username , 'password' : self .password }
133+ success , result = post (self .url , payload )
134+ if success :
135+ return Token (result ['access_token' ], result ['expires_in' ])
136+ else :
137+ # throws exception
138+ pass
139+
140+
141+ class OrgAdminAccountAuth (EasemobAuth ):
142+ """使用org的管理员账号和密码来获取token,
143+ 和上面不同的是, 这里获取的是整个org的管理员账号,
144+ 所以并没有appkey的概念
145+
146+ 并且, 因为没有appkey的概念, 所以, URL也不相同,
147+ 这里使用的URL是 https://a1.easemob.com/management/token
148+
149+ 而app级别的token都是从 https://a1.easemob.com/{org}/{app}/token
150+ 这个URL去获取的
151+ """
152+ def __init__ (self , username , password ):
153+ super (OrgAdminAccountAuth , self ).__init__ ()
154+ self .username = username
155+ self .password = password
156+ self .url = EASEMOB_HOST + "/management/token"
157+ self .token = None
158+
159+ def acquire_token (self ):
160+ """
161+ 使用 username / password 来获取token, 具体的REST API为
162+
163+ POST /management/token {'grant_type':'password', 'username':'xxxx', 'password':'xxxxx'}
164+ """
165+ payload = {'grant_type' :'password' , 'username' : self .username , 'password' : self .password }
166+ success , result = post (self .url , payload )
167+ if success :
168+ return Token (result ['access_token' ], result ['expires_in' ])
169+ else :
170+ # throws exception
171+ pass
172+
173+
174+
175+ def register_new_user (org , app , auth , username , password ):
176+ """注册新的app用户
177+ POST /{org}/{app}/users {"username":"xxxxx", "password":"yyyyy"}
178+ """
179+ payload = {"username" :username , "password" :password }
180+ url = EASEMOB_HOST + ("/%s/%s/users" % (org , app ))
181+ return post (url , payload , auth )
182+
183+ def delete_user (org , app , auth , username ):
184+ """删除app用户
185+ DELETE /{org}/{app}/users/{username}
186+ """
187+ url = EASEMOB_HOST + ("/%s/%s/users/%s" % (org , app , username ))
188+ return post (url , payload , auth )
189+
190+
191+
192+ if __name__ == '__main__' :
193+ #测试数据
194+ f = file ("../info.json" )
195+ s = json .load (f )
196+ appkey = s ['appkey' ]
197+ org , app = parse_appkey (appkey )
198+ org_admin_username = s ['admin' ]['username' ]
199+ org_admin_password = s ['admin' ]['password' ]
200+ client_id = s ['app' ]['credentials' ]['client_id' ]
201+ client_secret = s ['app' ]['credentials' ]['client_secret' ]
202+ app_admin_username = s ['app' ]['admin' ]['username' ]
203+ app_admin_password = s ['app' ]['admin' ]['password' ]
204+ # org_admin的认证方式
205+ org_admin_auth = OrgAdminAccountAuth (org_admin_username ,org_admin_password )
206+ # 获取org管理员的token
207+ print "Get org admin token: " + org_admin_auth .get_token ()
208+ # 获取app管理员的token
209+ app_admin_auth = AppAdminAccountAuth (org , app , app_admin_username , app_admin_password )
210+ print "Get app admin token:" + app_admin_auth .get_token ()
211+ # 通过client id和secret来获取app管理员的token
212+ app_client_auth = AppClientAuth (org , app , client_id , client_secret )
213+ print "Get app admin tokey with client id/secret: " + app_client_auth .get_token ()
214+
215+ print "now let's register some users...."
216+ app_users = []
217+ for i in range (10 ):
218+ username = id_generator ()
219+
220+ password = '123456'
221+ success , result = register_new_user (org , app , app_admin_auth , username , password )
222+ if success :
223+ print "registered new user %s in appkey[%s]" % (username , appkey )
224+ app_users .append (username )
225+ else :
226+ print "failed to register new user %s in appkey[%s]" % (username , appkey )
227+
228+ print "now let's delete users just created, this time we're using app_client_auth"
229+
230+ for username in app_users :
231+ success , result = delete_user (org , app ,app_client_auth , username )
232+ if success :
233+ print "user %s is deleted"
234+ else :
235+ print "failed to delete user %s"
236+
0 commit comments