def test_utils(self): self.assertEqual("900150983cd24fb0d6963f7d28e17f72", md5("abc")) self.assertEqual("a9993e364706816aba3e25717850c26c9cd0d89d", sha1("abc")) self.assertEqual("picbed:a:b", rsp("a", "b")) self.assertEqual(parse_valid_comma("a,b, c,"), ["a", "b", "c"]) self.assertEqual(parse_valid_verticaline("a|b| c"), ["a", "b", "c"]) self.assertTrue(is_true(1)) self.assertTrue(is_true("on")) self.assertTrue(is_true("true")) self.assertFalse(is_true(0)) self.assertIsInstance(get_current_timestamp(), int) self.assertTrue(allowed_file("test.PNG")) self.assertTrue(allowed_file(".jpeg")) self.assertFalse(allowed_file("my.psd")) self.assertFalse(allowed_file("ha.gif", ["jpg"])) self.assertFalse(allowed_file("ha.jpeg", ["jpg"])) self.assertFalse(allowed_file("ha.png", ["jpg"])) self.assertTrue(allowed_file("ha.jpg", ["jpg"])) v = "6afa9046a9579cad143a384c1b564b9a250d27d6f6a63f9f20bf3a7594c9e2c6" self.assertEqual(v, hmac_sha256('key', 'text')) self.assertEqual(v, hmac_sha256(b'key', b'text')) self.assertEqual(v, hmac_sha256(u'key', u'text')) self.assertEqual( "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", sha256("abc"))
def before_request(): if g.signin: return token = request.form.get("token") or parseAuthorization() if token: try: oldToken = token if PY2 and isinstance(token, text_type): token = token.encode("utf-8") token = b64decode(token) if not PY2 and not isinstance(token, text_type): token = token.decode("utf-8") rdm, usr, ctime, sig = token.split(".") ctime = int(ctime) assert len(rdm) == 6 except (TypeError, ValueError, AttributeError, Exception): pass else: tk = rsp("tokens") token2usr = g.rc.hget(tk, oldToken) if token2usr and token2usr == usr: ak = rsp("account", usr) userinfo = g.rc.hgetall(ak) if userinfo and isinstance(userinfo, dict): pwd = userinfo.pop("password", None) if hmac_sha256(pwd, usr) == sig: g.signin = True g.userinfo = userinfo
def gen_token(): return b64encode( ("%s.%s.%s.%s" % ( generate_random(), usr, get_current_timestamp(), hmac_sha256(g.rc.hget(ak, "password"), usr) )).encode("utf-8") ).decode("utf-8") Action = request.args.get("Action")
def token(): if request.method == "GET": return abort(404) res = dict(code=1) usr = g.userinfo.username tk = rsp("tokens") ak = rsp("account", usr) #: 生成token gen_token = lambda: b64encode( ("%s.%s.%s.%s" % (generate_random(), usr, get_current_timestamp(), hmac_sha256(g.rc.hget(ak, "password"), usr))).encode( "utf-8")).decode("utf-8") Action = request.args.get("Action") if Action == "create": if g.rc.hget(ak, "token"): res.update(msg="Existing token") else: token = gen_token() try: pipe = g.rc.pipeline() pipe.hset(tk, token, usr) pipe.hset(ak, "token", token) pipe.execute() except RedisError: res.update(msg="Program data storage service error") else: res.update(code=0, token=token) elif Action == "revoke": token = g.rc.hget(ak, "token") if token: try: pipe = g.rc.pipeline() pipe.hdel(tk, token) pipe.hdel(ak, "token") pipe.execute() except RedisError: res.update(msg="Program data storage service error") else: res.update(code=0) else: res.update(msg="No tokens yet") elif Action == "reset": oldToken = g.rc.hget(ak, "token") token = gen_token() try: pipe = g.rc.pipeline() if oldToken: pipe.hdel(tk, oldToken) pipe.hset(tk, token, usr) pipe.hset(ak, "token", token) pipe.execute() except RedisError: res.update(msg="Program data storage service error") else: res.update(code=0, token=token) return res
def gen_token(key): """生成可以用key校验的token""" return b64encode( ("%s.%s.%s.%s" % ( generate_random(), usr, get_current_timestamp(), hmac_sha256(key, usr) )).encode("utf-8") ).decode("utf-8")
def authorized(): """ Client SSO 单点登录、注销入口, 根据`Action`参数判断是`ssoLogin`还是`ssoLogout` """ Action = request.args.get("Action") if Action == "ssoLogin": # 单点登录 ticket = request.args.get("ticket") if request.method == "GET" and ticket and g.signin == False: resp = sso_request("{}/sso/validate".format(sso_server), dict(Action="validate_ticket"), dict(ticket=ticket, app_name=SSO["app_name"], get_userinfo=True, get_userbind=False)) logger.debug("SSO check ticket resp: {}".format(resp)) if resp and isinstance(resp, dict) and "success" in resp and "uid" in resp: if resp["success"] is True: uid = resp["uid"] sid = resp["sid"] expire = int(resp["expire"]) # 获取用户信息,若不需要,可将get_userinfo=True改为False,并注释下两行 g.userinfo = resp["userinfo"].get("data") or dict() set_userinfo(uid, g.userinfo, expire) logger.debug(g.userinfo) # 授权令牌验证通过,设置局部会话,允许登录 sessionId = set_sessionId(uid=uid, seconds=expire, sid=sid) response = make_response(redirect(get_redirect_url("front.index"))) response.set_cookie(key="sessionId", value=sessionId, max_age=expire, httponly=True, secure=False if request.url_root.split("://")[0] == "http" else True) return response elif Action == "ssoLogout": # 单点注销 ReturnUrl = request.args.get("ReturnUrl") or get_referrer_url() or url_for("front.index", _external=True) NextUrl = "{}/signOut?ReturnUrl={}".format(sso_server, ReturnUrl) app_name = request.args.get("app_name") if request.method == "GET" and NextUrl and app_name and g.signin == True and app_name == SSO["app_name"]: response = make_response(redirect(NextUrl)) response.set_cookie(key="sessionId", value="", expires=0) return response elif Action == "ssoConSync": # 数据同步:参数中必须包含大写的hmac_sha256(app_name:app_id:app_secret)的signature值 signature = request.args.get("signature") if request.method == "POST" and signature and signature == hmac_sha256("{}:{}:{}".format(SSO["app_name"], SSO["app_id"], SSO["app_secret"])).upper(): try: data = json.loads(request.form.get("data")) ct = data["CallbackType"] cd = data["CallbackData"] uid = data["uid"] token = data["token"] except Exception,e: logger.warning(e) else: logger.info("ssoConSync with uid: {} -> {}: {}".format(uid, ct, cd)) resp = sso_request("{}/sso/validate".format(sso_server), dict(Action="validate_sync"), dict(token=token, uid=uid)) if resp and isinstance(resp, dict) and resp.get("success") is True: # 之后根据不同类型的ct处理cd logger.debug("ssoConSync is ok") if ct == "user_profile": g.userinfo.update(cd) elif ct == "user_avatar": g.userinfo["avatar"] = cd return jsonify(msg="Synchronization completed", success=set_userinfo(uid, g.userinfo), app_name=SSO["app_name"])
def clientsConSync(self, getUserApp, uid, data): """ 向uid注册的各sid并发同步数据 流程: 1. 根据uid查找注册的sid,根据sid查到注册的clients,并去重 2. 循环clients获取其sso信息组合,多线程并发回调其授权接口 3. client时,根据token请求passport验证,通过后可以根据data中`CallbackType`处理不同类型数据 参数: @param getUserApp func: userapp.UserAppManager.getUserApp @param uid str:用户标识 @param data dict: 回调数据,格式如:dict(CallbackType="user_profile|user_avatar", CallbackData=dict|list|tuple|str) 请求时json序列化传输,获取时使用json.loads(request.form.get("data")) -> 即data """ # 检查参数 if uid and data and isinstance( data, dict) and "CallbackType" in data and "CallbackData" in data: clients = [] for sid in self.ssoGetRegisteredUserSid(uid): clients += self.ssoGetRegisteredClient(sid) clients = list(set(clients)) logger.debug( "callback: user all sid, get clients: {}".format(clients)) if clients and isinstance(clients, list) and len(clients) > 0: # 生成验证token token = gen_token() # 向uid写入本次验证token self.ssoSetUidConSyncToken(uid, token, len(clients) * 10) # 更新传递给客户端的data参数 data.update(uid=uid, token=token) kwargs = [] for clientName in clients: clientData = getUserApp(clientName) if clientData and isinstance(clientData, dict): kwargs.append( dict(url="{}/sso/authorized".format( clientData["app_redirect_url"].strip("/")), params=dict( Action="ssoConSync", signature=hmac_sha256("{}:{}:{}".format( clientData["name"], clientData["app_id"], clientData["app_secret"])).upper()), data=data, num_retries=0)) logger.debug("callback: kwargs: {}".format(kwargs)) if kwargs: try: pool = ThreadPool() resp = pool.map_async(sso_request, kwargs) resp.wait() logger.debug("callback: return: %s" % resp.get()) except Exception, e: logger.error(e, exc_info=True)
def before_request(): if g.signin: return token = request.form.get("token") or parse_authorization() #: 尝试使用LinkToken映射出token LinkToken = request.form.get( "LinkToken", request.args.get("LinkToken") ) or parse_authorization("LinkToken") if not token and LinkToken: try: if PY2 and isinstance(LinkToken, text_type): LinkToken = LinkToken.encode("utf-8") LinkToken = b64decode(LinkToken) if not PY2 and not isinstance(LinkToken, text_type): LinkToken = LinkToken.decode("utf-8") ctime, LinkId, LinkSig = LinkToken.split(":") ctime = int(ctime) if not LinkId or not LinkSig: raise ValueError except (TypeError, ValueError, AttributeError) as e: logger.debug(e, exc_info=True) else: pipe = g.rc.pipeline() pipe.hexists(rsp("linktokens"), LinkId) pipe.hgetall(rsp("linktoken", LinkId)) result = pipe.execute() if result[0] is True and result[1] and isinstance(result[1], dict): #: LinkId有效,但等待校验签名与权限,可以统计请求数据 Ld = result[1] usr = Ld.get("user") secret = Ld.get("LinkSecret") status = int(Ld.get("status", 1)) userinfo = g.rc.hmget( rsp("account", usr), "token", "ucfg_report_linktoken" ) if status == 1 and hmac_sha256(LinkId, secret) == LinkSig: authentication = "ok" #: 权限校验规则 if verify_rule(Ld): authorization = "ok" logger.info("LinkToken ok and permission pass") g.up_album = Ld.get("album") token = userinfo[0] else: authorization = "fail" logger.info("LinkToken ok and permission deny") else: authentication = "fail" authorization = "fail" #: 统计入库 if is_true(userinfo[1]): g.rc.lpush( rsp("report", "linktokens", usr), json.dumps(dict( LinkId=LinkId, user=usr, ctime=get_current_timestamp(), ip=get_ip(), agent=get_ua(), uap=parse_ua(get_ua()), referer=request.headers.get('Referer', ''), origin=get_origin(), ep=request.endpoint, authentication=authentication, authorization=authorization, )) ) if token: try: oldToken = token if PY2 and isinstance(token, text_type): token = token.encode("utf-8") token = b64decode(token) if not PY2 and not isinstance(token, text_type): token = token.decode("utf-8") rdm, usr, ctime, sig = token.split(".") ctime = int(ctime) assert len(rdm) == 6 except (TypeError, ValueError, AttributeError, Exception) as e: logger.debug(e, exc_info=True) else: tk = rsp("tokens") token2usr = g.rc.hget(tk, oldToken) if token2usr and token2usr == usr: ak = rsp("account", usr) userinfo = g.rc.hgetall(ak) userstatus = int(userinfo.get("status", 1)) if userinfo and userstatus != 0: pwd = userinfo.pop("password", None) tkey = userinfo.pop("token_key", None) if hmac_sha256(pwd, usr) == sig or \ (tkey and hmac_sha256(tkey, usr) == sig): g.signin = True g.userinfo = userinfo #: token验证通过,判断是否禁止普通用户登录 if is_true(g.cfg.disable_login) and \ not is_true(userinfo.get("is_admin")): g.signin = False g.userinfo = {}
def authorized(): """ Client SSO 单点登录、注销入口, 根据`Action`参数判断是`ssoLogin`还是`ssoLogout` """ Action = request.args.get("Action") if Action == "ssoLogin": # 单点登录 ticket = request.args.get("ticket") if request.method == "GET" and ticket and g.signin == False: resp = sso_request( "{}/sso/validate".format(sso_server), dict(Action="validate_ticket"), dict(ticket=ticket, app_name=SSO["app_name"], get_userinfo=True, get_userbind=False)) logger.sys.debug("SSO check ticket resp: {}".format(resp)) if resp and isinstance( resp, dict) and "success" in resp and "uid" in resp: if resp["success"] is True: uid = resp["uid"] sid = resp["sid"] expire = int(resp["expire"]) g.userinfo = resp["userinfo"].get("data") or dict() logger.sys.debug(g.userinfo) # 授权令牌验证通过,设置局部会话,允许登录 sessionId = set_sessionId(uid=uid, seconds=expire, sid=sid) response = make_response( redirect(get_redirect_url("front.index"))) response.set_cookie( key="sessionId", value=sessionId, max_age=expire, httponly=True, secure=False if request.url_root.split("://")[0] == "http" else True) return response elif Action == "ssoLogout": # 单点注销 ReturnUrl = request.args.get("ReturnUrl") or get_referrer_url( ) or url_for("front.index", _external=True) NextUrl = "{}/signOut?ReturnUrl={}".format(sso_server, ReturnUrl) app_name = request.args.get("app_name") if request.method == "GET" and NextUrl and app_name and g.signin == True and app_name == SSO[ "app_name"]: response = make_response(redirect(NextUrl)) response.set_cookie(key="sessionId", value="", expires=0) return response elif Action == "ssoConSync": # 数据同步:参数中必须包含大写的hmac_sha256(app_name:app_id:app_secret)的signature值 # 此处可以改为要求登录,passport sessionId可以解析出所需要的sid、uid signature = request.args.get("signature") if request.method == "POST" and signature and signature == hmac_sha256( "{}:{}:{}".format(SSO["app_name"], SSO["app_id"], SSO["app_secret"])).upper(): try: data = json.loads(request.form.get("data")) ct = data["CallbackType"] cd = data["CallbackData"] uid = data["uid"] token = data["token"] except Exception, e: logger.plugin.warning(e) else: logger.plugin.info("ssoConSync with uid: {} -> {}: {}".format( uid, ct, cd)) resp = sso_request("{}/sso/validate".format(sso_server), dict(Action="validate_sync"), dict(token=token, uid=uid)) if resp and isinstance(resp, dict) and resp.get("success") is True: # 之后根据不同类型的ct处理cd logger.plugin.debug("ssoConSync is ok") if ct == "user_profile": # like {u'nick_name': u'.\u5f18\u5f08', u'gender': u'1', u'domain_name': u'taochengwei', u'birthday': u'1995-04-22', u'location': u'\u5317\u4eac \u671d\u9633', u'signature': u'\u5c81\u6708\u5982\u5200\u65a9\u5929\u9a84'} logger.plugin.debug( "sync user_profile before: {}".format(g.userinfo)) g.userinfo.update(cd) logger.plugin.debug( "sync user_profile after: {}".format(g.userinfo)) elif ct == "user_avatar": logger.plugin.debug( "sync user_avatar before: {}".format( g.userinfo["avatar"])) g.userinfo["avatar"] = cd logger.plugin.debug( "sync user_avatar after: {}".format( g.userinfo["avatar"])) return jsonify(msg="Synchronization completed", success=g.api.sso_set_userinfo( uid, g.userinfo), app_name=SSO["app_name"])
def link(): res = dict(code=1, msg=None) ltk = rsp("linktokens") username = g.userinfo.username def check_body(): """校验post、put参数,返回值有效说明校验不通过""" allow_origin = request.form.get("allow_origin") allow_ip = request.form.get("allow_ip") allow_ep = request.form.get("allow_ep") allow_method = request.form.get("allow_method") er = request.form.get("exterior_relation") ir = request.form.get("interior_relation") if allow_origin: origins = parse_valid_comma(allow_origin) if not origins or not isinstance(origins, (tuple, list)): return "Invalid url address" for url in origins: if url and not check_origin(url): return "Invalid url address" if allow_ip: ips = parse_valid_comma(allow_ip) if not ips or not isinstance(ips, (tuple, list)): return "Invalid IP address" for ip in ips: if ip and not check_ip(ip): return "Invalid IP address" if allow_ep: eps = parse_valid_comma(allow_ep) if not eps or not isinstance(eps, (tuple, list)): return "Not found the endpoint" for ep in eps: if ep and ep not in current_app.view_functions.keys(): return "Not found the endpoint" if allow_method: methods = parse_valid_comma(allow_method) if not methods or not isinstance(methods, (tuple, list)): return "Invalid HTTP method" for md in methods: if md and md.upper() not in ["GET", "POST", "PUT", "DELETE"]: return "Invalid HTTP method" if er: if not er_pat.match(er.strip()): return "Invalid exterior_relation" if ir: if not ir_pat.match(ir.strip()): return "Invalid interior_relation" else: try: check_ir(ir) except (ValueError, TypeError): return "Invalid interior_relation" if request.method == "GET": is_mgr = is_true(request.args.get("is_mgr")) linktokens = g.rc.hgetall(ltk) pipe = g.rc.pipeline() for ltid, usr in iteritems(linktokens): if is_mgr and g.is_admin: pipe.hgetall(rsp("linktoken", ltid)) else: if username == usr: pipe.hgetall(rsp("linktoken", ltid)) try: result = pipe.execute() except RedisError: res.update(msg="Program data storage service error") else: res.update(code=0, data=result, count=len(result)) elif request.method == "POST": comment = request.form.get("comment") or "" #: 定义此引用上传图片时默认设置的相册名 album = request.form.get("album") or "" #: 定义以下几个权限之间的允许访问条件,opt and/or/not opt er = request.form.get("exterior_relation", "").strip() #: 定义权限内部允许访问条件 in/not in:opt, ir = request.form.get("interior_relation", "").strip() #: 定义权限项及默认值,检测参数时不包含默认值 allow_origin = request.form.get("allow_origin") or "" allow_ip = request.form.get("allow_ip") or "" allow_ep = request.form.get("allow_ep") or "api.upload" allow_method = request.form.get("allow_method") or "post" #: 判断用户是否有token ak = rsp("account", username) if not g.rc.hget(ak, "token"): res.update(msg="No tokens yet") return res cv = check_body() if cv: res.update(msg=cv) return res if allow_origin: allow_origin = ",".join([ get_origin(url) for url in parse_valid_comma(allow_origin) if url ]) #: 生成一个引用 LinkId = gen_uuid() LinkSecret = generate_password_hash(LinkId) lid = "%s:%s:%s" % (get_current_timestamp(), LinkId, hmac_sha256(LinkId, LinkSecret)) LinkToken = b64encode(lid.encode("utf-8")).decode("utf-8") pipe = g.rc.pipeline() pipe.hset(ltk, LinkId, username) pipe.hmset( rsp("linktoken", LinkId), dict( LinkId=LinkId, LinkSecret=LinkSecret, LinkToken=LinkToken, ctime=get_current_timestamp(), user=username, comment=comment, album=album, status=1, # 状态,1是启用,0是禁用 allow_origin=allow_origin, allow_ip=allow_ip, allow_ep=allow_ep, allow_method=allow_method, exterior_relation=er, interior_relation=ir, )) try: pipe.execute() except RedisError: res.update(msg="Program data storage service error") else: res.update(code=0, LinkToken=LinkToken) elif request.method == "PUT": LinkId = request.form.get("LinkId") Action = request.args.get("Action") key = rsp("linktoken", LinkId) if Action == "disable": try: g.rc.hset(key, "status", 0) except RedisError: res.update(msg="Program data storage service error") else: res.update(code=0) return res elif Action == "enable": try: g.rc.hset(key, "status", 1) except RedisError: res.update(msg="Program data storage service error") else: res.update(code=0) return res if LinkId and g.rc.exists(key): comment = request.form.get("comment") or "" album = request.form.get("album") or "" er = request.form.get("exterior_relation", "").strip() ir = request.form.get("interior_relation", "").strip() allow_origin = request.form.get("allow_origin") or "" allow_ip = request.form.get("allow_ip") or "" allow_ep = request.form.get("allow_ep") or "api.upload" allow_method = request.form.get("allow_method") or "post" cv = check_body() if cv: res.update(msg=cv) return res if allow_origin: allow_origin = ",".join([ get_origin(url) for url in parse_valid_comma(allow_origin) if url ]) pipe = g.rc.pipeline() pipe.hset(ltk, LinkId, username) pipe.hmset( key, dict( mtime=get_current_timestamp(), comment=comment, album=album, allow_origin=allow_origin, allow_ip=allow_ip, allow_ep=allow_ep, allow_method=allow_method, exterior_relation=er, interior_relation=ir, )) try: pipe.execute() except RedisError: res.update(msg="Program data storage service error") else: res.update(code=0) else: res.update(msg="Not found the LinkId") elif request.method == "DELETE": LinkId = request.form.get("LinkId") if LinkId: pipe = g.rc.pipeline() pipe.hdel(ltk, LinkId) pipe.delete(rsp("linktoken", LinkId)) try: pipe.execute() except RedisError: res.update(msg="Program data storage service error") else: res.update(code=0) else: res.update(msg="Parameter error") return res
def test_utils(self): self.assertEqual("900150983cd24fb0d6963f7d28e17f72", md5("abc")) self.assertEqual("a9993e364706816aba3e25717850c26c9cd0d89d", sha1("abc")) self.assertEqual("picbed:a:b", rsp("a", "b")) self.assertEqual(parse_valid_comma("a,b, c,"), ["a", "b", "c"]) self.assertEqual(parse_valid_verticaline("a|b| c"), ["a", "b", "c"]) self.assertTrue(is_true(1)) self.assertTrue(is_true("on")) self.assertTrue(is_true("true")) self.assertFalse(is_true(0)) self.assertIsInstance(get_current_timestamp(), int) self.assertTrue(allowed_file("test.PNG")) self.assertTrue(allowed_file(".jpeg")) self.assertFalse(allowed_file("my.psd")) self.assertFalse(allowed_file("ha.gif", ["jpg"])) self.assertFalse(allowed_file("ha.jpeg", ["jpg"])) self.assertFalse(allowed_file("ha.png", ["jpg"])) self.assertTrue(allowed_file("ha.jpg", ["jpg"])) v = "6afa9046a9579cad143a384c1b564b9a250d27d6f6a63f9f20bf3a7594c9e2c6" self.assertEqual(v, hmac_sha256("key", "text")) self.assertEqual(v, hmac_sha256(b"key", b"text")) self.assertEqual(v, hmac_sha256(u"key", u"text")) self.assertEqual( "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", sha256("abc"), ) #: test format_upload_src baseimg = "img-url" basefmt = {"src": baseimg} self.assertEqual(format_upload_src(123, baseimg), basefmt) self.assertEqual(format_upload_src(None, baseimg), basefmt) self.assertEqual(format_upload_src([0], baseimg), basefmt) self.assertEqual(format_upload_src("", baseimg), basefmt) self.assertEqual(format_upload_src(".", baseimg), basefmt) self.assertEqual(format_upload_src(".1", baseimg), basefmt) self.assertEqual(format_upload_src("1.", baseimg), basefmt) self.assertEqual(format_upload_src(1.1, baseimg), basefmt) self.assertEqual(format_upload_src("1.1", baseimg), {"1": { "1": baseimg }}) self.assertEqual(format_upload_src("u", baseimg), basefmt) self.assertEqual(format_upload_src("im", baseimg), {"im": baseimg}) self.assertEqual(format_upload_src("url", baseimg), {"url": baseimg}) self.assertEqual(format_upload_src("i.am.src", baseimg), basefmt) self.assertEqual(format_upload_src("src.url", baseimg), {"src": { "url": baseimg }}) #: test format_apires self.assertEqual(format_apires({"code": 0}, "success", "bool"), {"success": True}) self.assertEqual(format_apires({"code": 0}, oc="200"), {"code": 200}) self.assertEqual(format_apires({"code": -1}, "status", "bool"), {"status": False}) self.assertEqual( format_apires(dict(code=-1, msg="xxx"), "errno", "200"), { "errno": -1, "msg": "xxx" }, ) self.assertEqual( format_apires(dict(code=-1, msg="xxx"), "errno", "200", "errmsg"), { "errno": -1, "errmsg": "xxx" }, ) self.assertEqual( format_apires(dict(code=0, msg="xxx"), "", "200", "errmsg"), { "code": 200, "errmsg": "xxx" }, ) self.assertEqual(len(generate_random()), 6) self.assertIn("Mozilla/5.0", gen_ua()) # bleach self.assertEqual(bleach_html("<i>abc</i>"), "<i>abc</i>") self.assertEqual( bleach_html("<script>var abc</script>"), "<script>var abc</script>", ) # re self.assertEqual(parse_author_mail("staugur"), ("staugur", None)) self.assertEqual(parse_author_mail("staugur <mail>"), ("staugur", "mail"))
def test_utils(self): self.assertEqual("900150983cd24fb0d6963f7d28e17f72", md5("abc")) self.assertEqual( "a9993e364706816aba3e25717850c26c9cd0d89d", sha1("abc") ) self.assertEqual("picbed:a:b", rsp("a", "b")) self.assertEqual(parse_valid_comma("a,b, c,"), ["a", "b", "c"]) self.assertEqual(parse_valid_verticaline("a|b| c"), ["a", "b", "c"]) self.assertTrue(is_true(1)) self.assertTrue(is_true("on")) self.assertTrue(is_true("true")) self.assertFalse(is_true(0)) self.assertIsInstance(get_current_timestamp(), int) self.assertTrue(allowed_file("test.PNG")) self.assertTrue(allowed_file(".jpeg")) self.assertFalse(allowed_file("my.psd")) self.assertFalse(allowed_file("ha.gif", ["jpg"])) self.assertFalse(allowed_file("ha.jpeg", ["jpg"])) self.assertFalse(allowed_file("ha.png", ["jpg"])) self.assertTrue(allowed_file("ha.jpg", ["jpg"])) v = "6afa9046a9579cad143a384c1b564b9a250d27d6f6a63f9f20bf3a7594c9e2c6" self.assertEqual(v, hmac_sha256('key', 'text')) self.assertEqual(v, hmac_sha256(b'key', b'text')) self.assertEqual(v, hmac_sha256(u'key', u'text')) self.assertEqual( "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", sha256("abc") ) #: test format_upload_src baseimg = 'img-url' basefmt = {'src': baseimg} self.assertEqual(format_upload_src(123, baseimg), basefmt) self.assertEqual(format_upload_src(None, baseimg), basefmt) self.assertEqual(format_upload_src([0], baseimg), basefmt) self.assertEqual(format_upload_src('', baseimg), basefmt) self.assertEqual(format_upload_src('.', baseimg), basefmt) self.assertEqual(format_upload_src('.1', baseimg), basefmt) self.assertEqual(format_upload_src('1.', baseimg), basefmt) self.assertEqual(format_upload_src(1.1, baseimg), basefmt) self.assertEqual( format_upload_src('1.1', baseimg), {'1': {'1': baseimg}} ) self.assertEqual(format_upload_src('u', baseimg), basefmt) self.assertEqual(format_upload_src('im', baseimg), {'im': baseimg}) self.assertEqual(format_upload_src('url', baseimg), {'url': baseimg}) self.assertEqual(format_upload_src('i.am.src', baseimg), basefmt) self.assertEqual( format_upload_src('src.url', baseimg), {'src': {'url': baseimg}} ) #: test format_apires self.assertEqual( format_apires({'code': 0}, "success", "bool"), {'success': True} ) self.assertEqual( format_apires({'code': 0}, oc="200"), {'code': 200} ) self.assertEqual( format_apires({'code': -1}, "status", "bool"), {'status': False} ) self.assertEqual( format_apires(dict(code=-1, msg='xxx'), 'errno', '200'), {'errno': -1, 'msg': 'xxx'} ) self.assertEqual( format_apires(dict(code=-1, msg='xxx'), 'errno', '200', 'errmsg'), {'errno': -1, 'errmsg': 'xxx'} ) self.assertEqual( format_apires(dict(code=0, msg='xxx'), '', '200', 'errmsg'), {'code': 200, 'errmsg': 'xxx'} ) self.assertEqual(len(generate_random()), 6) self.assertIn("Mozilla/5.0", gen_ua())