예제 #1
0
파일: views.py 프로젝트: doubleC2/ios_ci
def __list_all_devices(_config: IosAccountHelper):
    ret = _config.post(
        "获取所有的列表",
        "https://developer.apple.com/services-account/QH65B2/account/ios/device/listDevices.action?teamId=",
        data={
            "includeRemovedDevices": True,
            "includeAvailability": True,
            "pageNumber": 1,
            "pageSize": 100,
            "sort": "status%3dasc",
            "teamId": _config.team_id,
        },
        log=False)
    for device in ret["devices"]:  # type: Dict
        _reg_device(
            device["deviceId"], device["deviceNumber"],
            device.get("model", device.get("deviceClass", "#UNKNOWN#")),
            device.get("serialNumber", "#UNKNOWN#"))
    # 更新一下info
    devices = list(map(lambda x: x["deviceNumber"], ret["devices"]))
    if json_str(devices) != _config.info.devices:
        Log("更新设备列表[%s]数量[%s]=>[%s]" %
            (_config.account, _config.info.devices_num, len(devices)))
        _config.info.devices = json_str(devices)
        _config.info.devices_num = len(devices)
        _config.info.save()
예제 #2
0
파일: views.py 프로젝트: Maroc-OS/ios_ci
def __profile_detail(_config: IosAccountHelper, _profile: IosProfileInfo):
    ret = _config.post(
        "获取profile详情",
        "https://developer.apple.com/services-account/QH65B2/account/ios/profile/getProvisioningProfile.action?teamId=",
        data={
            "includeInactiveProfiles": True,
            "provisioningProfileId": _profile.profile_id,
            "teamId": _config.team_id,
        },
    )
    profile = ret["provisioningProfile"]
    devices = list(map(lambda x: x["deviceNumber"], profile["devices"]))
    devices_str = json_str(devices)
    if _profile.devices != devices_str:
        _profile.devices = devices_str
        _profile.devices_num = len(devices)
        __download_profile(_config, _profile)
        Log("更新profile[%s]" % _profile.sid)
        _profile.save()
    certs = []
    for each in profile["certificates"]:
        certs.append(each["certificateId"])
    if _profile.certs != json_str(certs):
        _profile.certs = json_str(certs)
        _profile.save()
예제 #3
0
 def process_exception(self, request: HttpRequest, e: Exception):
     Trace("执行[%s][%s]出错" % (request.path, json_str(getattr(request, "_orig_params", {}))[:1000]), e)
     msg = str(e) if isinstance(e, AssertionError) else "服务器出错"
     if len(msg) > 1000:
         msg = msg[:996] + " ..."
     return HttpResponse(json_str({
         "ret": -1,
         "error": msg,
     }), content_type="application/json", status=500)
예제 #4
0
 def __save_cookie(self, cookie: Dict):
     _orig = self.info.cookie
     _new = json_str(cookie)
     if _orig == _new:
         return
     self.info.cookie = _new
     self.info.save()
예제 #5
0
def mongo_pack_set(key: str, value: dict, model: str, size=1 * 1000 * 1000):
    """
    大于16M的插入
    以多个对象存在
    """
    db = mongo(model)
    v = json_str(value)
    if len(v) < size:
        return mongo_set(key, value, model)
    # 需要切一下
    Assert("__pack__" not in value, "数据内不能有 __pack__ 字段")
    Assert("__no__" not in value, "数据内不能有 __no__ 字段")
    Assert("__value__" not in value, "数据内不能有 __value__ 字段")
    Assert("__length__" not in value, "数据内不能有 __length__ 字段")

    pack_length = int(ceil(len(v) / size))
    new_value = list(
        map(
            lambda x: {
                "__pack__": True,
                "__no__": v,
                "__length__": pack_length,
                "__value__": v[x * size:(x + 1) * size],
            }, range(0, pack_length)))

    if mongo(model).find_one({
            "_id": "%s_%s" % (model, key)
    }, ["__pack__", "__length__"]).get("__length__", 0) > pack_length:
        # 删除旧的部分
        mongo_pack_pop(key, model)

    mongo_set(key, new_value[0], model)
    for each in new_value[1:]:
        mongo_set(key, each, model)
    return True
예제 #6
0
파일: views.py 프로젝트: doubleC2/ios_ci
def _reg_cert(_config: IosAccountInfo, cert_req_id, name, cert_id, sn,
              type_str, expire):
    sid = "%s:%s" % (_config.account, name)
    orig = str_json(
        db_model.get("IosCertInfo:%s:%s" % (_config.account, name)) or '{}')
    obj = {
        "name": name,
        "app": _config.account,
        "cert_req_id": cert_req_id,
        "cert_id": cert_id,
        "sn": sn,
        "type_str": type_str,
        "expire": expire,
        "expire_str": date_time_str(expire),
    }
    if orig == obj:
        return cert_req_id
    db_model.set("IosCertInfo:%s:%s" % (_config.account, name),
                 json_str(obj),
                 ex=(expire - now()) // 1000)
    _info = IosCertInfo()
    _info.sid = sid
    _info.app = _config.account
    _info.cert_req_id = cert_req_id
    _info.cert_id = cert_id
    _info.sn = sn
    _info.type_str = type_str
    _info.name = name
    _info.create = now()
    _info.expire = datetime.datetime.utcfromtimestamp(expire // 1000)
    _info.save()
    Log("注册新的证书[%s][%s]" % (name, cert_req_id))
    return cert_req_id
예제 #7
0
파일: views.py 프로젝트: doubleC2/ios_ci
def __add_task(_user: UserInfo):
    _account = IosAccountInfo.objects.filter(
        account=_user.account).first()  # type:IosAccountInfo
    _project = IosProjectInfo.objects.filter(
        project=_user.project).first()  # type:IosProjectInfo
    _profile = IosProfileInfo.objects.filter(
        sid="%s:%s" %
        (_user.account, _user.project)).first()  # type:IosProfileInfo
    Assert(_profile, "[%s][%s]证书无效" % (_project.project, _account.account))
    Log("[%s]发布任务[%s]" % (_user.project, _user.account))
    db_session.publish(
        "task:package",
        json_str({
            "cert":
            "iPhone Developer: zhangming luo",
            "cert_p12":
            "",
            "mp_url":
            entry("/apple/download_mp?uuid=%s" % _user.uuid),
            "mp_md5":
            md5bytes(base64decode(_profile.profile)),
            "project":
            _project.project,
            "ipa_url":
            _asset_url("%s/orig.ipa" % _user.project),
            "ipa_md5":
            _project.md5sum,
            "ipa_new":
            "%s_%s.ipa" % (_account.team_id, _account.devices_num),
            "upload_url":
            entry("/apple/upload_ipa?project=%s&account=%s" %
                  (_user.project, _user.account)),
            "ts":
            now(),
        }))
예제 #8
0
def publish_security_code(account: str, code: str, ts: int):
    db_session.publish(
        "account:security:code",
        json_str({
            "account": account,
            "code": code,
            "ts": ts,
        }))
예제 #9
0
파일: views.py 프로젝트: doubleC2/ios_ci
def login_by_fastlane(_req: HttpRequest, cmd: str = "", account: str = ""):
    """
    通过命令获取会话
    fastlane spaceauth -u [email protected]
    ex.
    export FASTLANE_SESSION='---\n- !ruby/object:HTTP::Cookie\n  name: myacinfo\n  value: DAWTKNV2e32a0823580640561dc9dfd382265048c32c2aa5b04485930b2ada1d1c7eba28dee6c6065c749f708f2a429f8f9f2d0f2f7d2ad629652ca5bc3383c0772d51c6ca34a2f7b09141f7b19c358c2b25d0738079ab1e48a06610228a574342c84ef13349ede1a012c25155e265a17989a3b09631dd953954505153fb7ef71aecfe303530cb684c89e8402cb82d8d4d93c3fc3c1209e334f65f71c7ae0cfdf0349ec757abcb104a591f5bea25ac0f1207004c19645b80ed82fb5cd0d3a740224b2f3aef9e91b049bb63a94ae3c76d027411f077069865209d733617a7a84f54cf7e9488e9b4f0a918d29f184f5ec76d95b5f55def61682f70b7f10fc12dc43d6e380213dd1f702a4f3ccab3ad438cd0f6a87c295e028a12ec410aa3fa689210d040377995914d4d3718b90f85ad5452d5db47ef9ae11c6b3216cf8ab61025adc203b0bf072ce832240c384d83f0f4aaf477a3c7313de4c20c5e32c530ff1ad76aebcd8538ac485a9a46941dfa94ee2f3fb40e38666533326562333665333834343461323366383636666563303166613533303330656361323836MVRYV2\n  domain: apple.com\n  for_domain: true\n  path: "/"\n  secure: true\n  httponly: true\n  expires: \n  max_age: \n  created_at: 2019-03-15 11:55:51.031441000 +08:00\n  accessed_at: 2019-03-15 11:55:51.041509000 +08:00\n- !ruby/object:HTTP::Cookie\n  name: dqsid\n  value: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJzZnp2ZGFldGJPeWpXaTc1LVpTRmNBIn0.IEYqXF-pxIYdIwP2rdNRNhoxdCzJgGxt4olTZa2fXo8\n  domain: olympus.itunes.apple.com\n  for_domain: false\n  path: "/"\n  secure: true\n  httponly: true\n  expires: \n  max_age: 1800\n  created_at: &1 2019-03-15 11:55:52.798977000 +08:00\n  accessed_at: *1\n
    curl localhost:8000/apple/login_by_fastlane --data $FASTLANE_SESSION
    """
    if not cmd:
        cmd = _req.body.decode("utf-8")
    Assert(len(cmd), "命令行不对")
    cmd = cmd.replace("\\n", "")
    cookie = dict(re.compile(r"name:\s+(\S+)\s+value:\s+(\S+)").findall(cmd))
    if not account:
        rsp = requests.post(
            "https://developer.apple.com/services-account/QH65B2/account/getUserProfile",
            headers={"cookie": to_form_url(cookie, split=';')})
        if rsp.status_code != 200:
            return {
                "succ": False,
                "reason": "无效的fastlane export",
            }
        data = rsp.json()
        account = data["userProfile"]["email"]

    if account:
        _info = IosAccountInfo.objects.filter(
            account=account).first()  # type:IosAccountInfo
        if not _info:
            _info = IosAccountInfo()
            _info.account = account
            _info.save()
        _info.cookie = json_str(cookie)
        _info.headers = json_str({})
        _info.save()
        Log("通过fastlane登录[%s]" % account)
        return {
            "succ": True,
            "msg": "登录[%s]成功" % account,
        }
    else:
        return {
            "succ": False,
            "msg": "请求不具备提取登录信息",
        }
예제 #10
0
파일: views.py 프로젝트: Maroc-OS/ios_ci
def _reg_device(account: str, device_id: str, udid: str, model: str,
                sn: str) -> str:
    # 需要缓存
    _info = IosDeviceInfo()
    _info.sid = "%s:%s" % (account, udid)
    _info.account = account
    _info.udid = udid
    _info.device_id = device_id
    _info.model = model
    _info.sn = sn
    _info.create = now()
    _info.save()
    Log("注册新的设备[%s][%s][%s]" % (udid, device_id, sn))
    _account = IosAccountInfo.objects.get(account=account)
    device_map = str_json(_account.devices)
    device_map[udid] = device_id
    if json_str(device_map) != _account.devices:
        _account.devices = json_str(device_map)
        _account.devices_num = len(device_map)
        _account.save()
    return udid
예제 #11
0
파일: views.py 프로젝트: doubleC2/ios_ci
def _get_app(_config: IosAccountHelper, project: str) -> IosAppInfo:
    app = IosAppInfo.objects.filter(
        sid="%s:%s" % (_config.account, project), ).first()  # type: IosAppInfo
    if not app:
        _project = IosProjectInfo.objects.filter(
            project=project).first()  # type: IosProjectInfo
        _identifier = "%s.%s" % (_project.bundle_prefix, GetRandomName())
        _config.post(
            "验证一个app",
            "https://developer.apple.com/services-account/QH65B2/account/ios/identifiers/validateAppId.action?teamId=",
            data={
                "teamId": _config.team_id,
                "appIdName": "ci%s" % project,
                "appIdentifierString": _identifier,
                "type": "explicit",
                "explicitIdentifier": _identifier,
            },
        )
        _config.post(
            "注册一个app",
            "https://developer.apple.com/services-account/v1/bundleIds",
            data=json_str({
                "data": {
                    "type": "bundleIds",
                    "attributes": {
                        "name": "ci%s" % project,
                        "identifier": _identifier,
                        "platform": "IOS",
                        "seedId": _config.team_id,
                        "teamId": _config.team_id,
                    },
                    "relationships": {
                        "bundleIdCapabilities": {
                            "data":
                            tran(get_capability,
                                 str_json(_project.capability)),
                        },
                    },
                },
            }),
            ex_headers={
                "content-type": "application/vnd.api+json",
            },
            csrf=True,
            json_api=False,
            status=201,
        )
        __list_all_app(_config, project)
        app = IosAppInfo.objects.filter(
            sid="%s:%s" %
            (_config.account, project), ).first()  # type: IosAppInfo
    return Assert(app, "账号[%s]缺少app[%s]" % (_config.account, project))
예제 #12
0
파일: views.py 프로젝트: doubleC2/ios_ci
def _newbee(_project: IosProjectInfo):
    # 默认一天的时效
    for _ in range(100):
        import uuid
        _uuid = uuid.uuid4()
        if db_session.set("uuid:%s" % _uuid,
                          json_str({
                              "project": _project.project,
                          }),
                          ex=3600 * 24,
                          nx=True):
            return str(_uuid)
    raise Fail("生成失败")
예제 #13
0
def _wait_code(info: IosAccountInfo,
               session: requests.Session,
               ts,
               save_now=False):
    """
    等待二次提交的需要
    """
    Log("等待[%s]二次验证" % info.account)
    # last = info.security_code
    expire = now() + 1200 * 1000
    while now() < expire:
        gevent.sleep(1)
        for data in message_from_topic(__pub, is_json=True, limit=1):
            if data.get("ts") > ts:
                if data.get("code") and data.get("account") in {
                        info.account, "*"
                }:
                    rsp = session.post(
                        "https://idmsa.apple.com/appleauth/auth/verify/phone/securitycode",
                        json={
                            "securityCode": {
                                "code": str(data.get("code")),
                            },
                            "phoneNumber": {
                                "id": 1,
                            },
                            "mode": "sms",
                        })
                    # Log("[%s] %s" % (rsp.status_code, rsp.json()))
                    # rsp = session.post("https://idmsa.apple.com/appleauth/auth/verify/trusteddevice/securitycode", json={
                    #     "securityCode": {"code": data["code"]},
                    # })
                    if rsp.status_code != 200:
                        Log("账号[%s]验证校验码[%s]失败[%s]" %
                            (info.account, data.get("code"), rsp.status_code))
                    # if rsp.status_code != 204:
                    #     Log("账号[%s]验证校验码[%s]失败[%s]" % (info.account, data.get("code"), rsp.status_code))
                    #     continue
                    rsp = session.get(
                        "https://idmsa.apple.com/appleauth/auth/2sv/trust")
                    if rsp.status_code == 204:
                        session.cookies.update(
                            {"__expire": str(now() + 6 * 3600 * 1000)})
                        if save_now:
                            info.cookie = json_str(session.cookies)
                            info.save()
                        Log("账号[%s]登录成功" % info.account)
                        return session
    raise Fail("登录二次验证超时")
예제 #14
0
def to_response(ret: any, req: HttpRequest = None) -> HttpResponse:
    if isinstance(ret, HttpResponse):
        return ret
    if isinstance(ret, Mapping):
        pass
    elif callable(ret) and hasattr(ret, "_is_action"):
        assert req is not None
        depth = getattr(req, "_depth", 0) + 1
        assert depth < 10
        setattr(req, "_depth", depth)
        return to_response(ret(req))
    else:
        ret = {"msg": ret}
    rsp = HttpResponse(json_str({
        "ret": 0,
        "result": ret
    },
                                cls=DjangoExJSONEncoder),
                       content_type="application/json")
    rsp["Access-Control-Allow-Origin"] = "*"
    rsp["Access-Control-Allow-Methods"] = "GET, POST, OPTIONS"
    return rsp
예제 #15
0
def resign_ipa(self: Task, uuid: str, cert: str, cert_url: str, cert_md5: str,
               mp_url, mp_md5, project, ipa_url, ipa_md5, ipa_new, upload_url,
               process_url: str):
    worker = self.request.hostname
    Log("[%s]启动Celery任务[%s][%s][%s]" %
        (worker, uuid, self.request.retries, json_str(self.request.kwargs)))
    base = tempfile.gettempdir()
    _update_state(process_url, worker, "ready")
    # 确认ipa
    with Block("cert部分"):
        if cert in _certs:
            Log("钥匙串中已经拥有证书[%s]" % cert)
        else:
            _refresh_certs()
        if cert in _certs:
            Log("钥匙串中已经拥有证书[%s]" % cert)
        else:
            _update_state(process_url, worker, "prepare_cert")
            Log("下载证书p12[%s]" % cert)
            file_cert = os.path.join(base, "cert.p12")
            assert call(["wget", cert_url, "-O", file_cert, "-o",
                         "/dev/null"]) == 0, "下载[%s]失败了" % cert_url
            assert md5bytes(
                read_binary_file(file_cert)) == cert_md5, "下载[%s]失败" % cert_url
            Log("导入证书p12[%s]" % cert)
            assert call([SECURITY_BIN, "import", file_cert, "-P",
                         "q1w2e3r4"]), "导入证书[%s]失败" % cert
    with Block("mobileprovision部分"):
        file_mp = os.path.join(base, "package.mobileprovision")
        if os.path.isfile(file_mp) and md5bytes(
                read_binary_file(file_mp)) == mp_md5:
            Log("采用本地的mobileprovision文件")
        else:
            _update_state(process_url, worker, "prepare_mp")
            Log("下载mobileprovision文件")
            os.makedirs(os.path.join("package", project), exist_ok=True)
            assert call(["wget", mp_url, "-O", file_mp, "-o",
                         "/dev/null"]) == 0, "下载[%s]失败了" % mp_url
            assert md5bytes(
                read_binary_file(file_mp)) == mp_md5, "下载[%s]失败" % mp_url
    with Block("ipa部分"):
        file_ipa = os.path.join("package", project, "orig.ipa")
        if os.path.isfile(file_ipa) and md5bytes(
                read_binary_file(file_ipa)) == ipa_md5:
            Log("采用本地的ipa文件")
        else:
            _update_state(process_url, worker, "prepare_ipa")
            Log("下载ipa文件[%s]" % ipa_url)
            os.makedirs(os.path.join("package", project), exist_ok=True)
            assert call(["wget", ipa_url, "-O", file_ipa, "-o",
                         "/dev/null"]) == 0, "下载[%s]失败了" % ipa_url
            assert md5bytes(
                read_binary_file(file_ipa)) == ipa_md5, "下载[%s]失败了" % ipa_url

    with Block("打包"):
        Log("开始打包[%s]" % project)
        file_new = os.path.join("package", project, ipa_new)
        _update_state(process_url, worker, "resign")
        # noinspection PyBroadException
        try:
            _package(file_ipa, file_mp, cert, file_new)
        except Exception:
            _update_state(process_url, worker, "fail")

    with Block("上传"):
        _update_state(process_url, worker, "upload_ipa")
        Log("上传ipa[%s][%s]" % (project, upload_url))
        rsp = requests.post(upload_url,
                            files={
                                "worker": worker,
                                "file": read_binary_file(file_new),
                            })
        assert rsp.status_code == 200
        assert rsp.json()["ret"] == 0
    Log("任务完成")
    _update_state(process_url, worker, "succ", fail=True)
    return {
        "succ": True,
        "uuid": uuid,
    }
예제 #16
0
파일: views.py 프로젝트: doubleC2/ios_ci
def __add_device(account: IosAccountInfo, udid: str, project: str) -> bool:
    title = "设备%s" % udid
    _config = IosAccountHelper(account)
    try:
        _device = IosDeviceInfo.objects.filter(
            udid=udid).first()  # type:Optional[IosDeviceInfo]
        if not _device:
            # 先注册设备
            ret = _config.post(
                "验证设备udid",
                "https://developer.apple.com/services-account/QH65B2/account/ios/device/validateDevices.action?teamId=",
                {
                    "deviceNames": title,
                    "deviceNumbers": udid,
                    "register": "single",
                    "teamId": _config.team_id,
                },
                cache=True)

            Assert(
                len(ret["failedDevices"]) == 0,
                "验证udid请求失败[%s][%s]" % (udid, ret["validationMessages"]))
            __list_all_devices(_config)
            ret = _config.post(
                "添加设备",
                "https://developer.apple.com/services-account/QH65B2/account/ios/device/addDevices.action?teamId=%s"
                % _config.team_id, {
                    "deviceClasses": "iphone",
                    "deviceNames": title,
                    "deviceNumbers": udid,
                    "register": "single",
                    "teamId": _config.team_id,
                },
                csrf=True)
            Assert(ret["resultCode"] == 0, "添加udid请求失败[%s]" % udid)
            Assert(not ret["validationMessages"], "添加udid请求失败[%s]" % udid)
            Assert(ret["devices"], "添加udid请求失败[%s]" % udid)
            device = ret["devices"][0]  # type: Dict
            _reg_device(device["deviceId"], device["deviceNumber"],
                        device["model"], device["serialNumber"])

        with Block("更新"):
            ret, _info = __list_all_profile(_config, project)
            if not _info:
                _info = IosProfileInfo()
                _info.sid = "%s:%s" % (_config.account, project)
                _info.app = _config.account
                _info.devices = "[]"
                _info.devices_num = 0
                _info.project = project

            devices = str_json(_info.devices)  # type: List[str]

            if udid in devices:
                pass
            else:
                devices.append(udid)
                with Block("默认全开当期的设备"):
                    # noinspection PyTypeChecker
                    devices = list(
                        set(devices + str_json(_config.info.devices)))
                _cert = _get_cert(_config.info)
                _app = _get_app(_config, project)
                found = False
                for each in ret["provisioningProfiles"]:  # type: Dict
                    if each["name"] != "专用 %s" % project:
                        continue
                    # todo: 过期更新
                    ret = _config.post(
                        "更新ProvisioningProfile",
                        "https://developer.apple.com/services-account/QH65B2/account/ios/profile/regenProvisioningProfile.action?teamId=",
                        data={
                            "provisioningProfileId":
                            each["provisioningProfileId"],
                            "distributionType":
                            "limited",
                            "subPlatform":
                            "",
                            "returnFullObjects":
                            False,
                            "provisioningProfileName":
                            each["name"],
                            "appIdId":
                            _app.app_id_id,
                            "certificateIds":
                            _cert.cert_req_id,
                            "deviceIds":
                            ",".join(_get_device_id(devices).values()),
                        },
                        csrf=True)
                    Assert(ret["resultCode"] == 0)
                    _info.devices = json_str(devices)
                    _info.profile_id = each["provisioningProfileId"]
                    # noinspection PyTypeChecker
                    _info.profile = ret["provisioningProfile"][
                        "encodedProfile"]
                    _info.expire = _to_dt(
                        ret["provisioningProfile"]["dateExpire"])
                    _info.save()
                    found = True
                    Log("更新证书[%s]添加设备[%s][%s]成功" %
                        (project, udid, len(devices)))
                    break
                if not found:
                    ret = _config.post(
                        "创建ProvisioningProfile",
                        "https://developer.apple.com/services-account/QH65B2/account/ios/profile/createProvisioningProfile.action?teamId=",
                        data={
                            "subPlatform": "",
                            "certificateIds": _cert.cert_req_id,
                            "deviceIds":
                            ",".join(_get_device_id(devices).values()),
                            "template": "",
                            "returnFullObjects": False,
                            "distributionTypeLabel": "distributionTypeLabel",
                            "distributionType": "limited",
                            "appIdId": _app.app_id_id,
                            "appIdName": _app.name,
                            "appIdPrefix": _app.prefix,
                            "appIdIdentifier": _app.identifier,
                            "provisioningProfileName": "专用 %s" % project,
                        },
                        csrf=True)
                    Assert(ret["resultCode"] == 0)
                    # noinspection PyTypeChecker
                    _info.profile_id = ret["provisioningProfile"][
                        "provisioningProfileId"]
                    # noinspection PyTypeChecker
                    _info.profile = ret["provisioningProfile"][
                        "encodedProfile"]
                    _info.expire = _to_dt(
                        ret["provisioningProfile"]["dateExpire"])
                    _info.save()
                    Log("添加证书[%s]添加设备[%s][%s]成功" %
                        (project, udid, len(devices)))
    except Exception as e:
        Trace("添加设备出错了[%s]" % e, e)
        return False
    return True
예제 #17
0
    def __login(self):
        if self.csrf_ts > now():
            return
        with Block("账号登录"):
            ret = requests.post(
                "https://developer.apple.com/services-account/QH65B2/account/getTeams",
                json={
                    "includeInMigrationTeams": 1,
                },
                headers={
                    'cookie': to_form_url(self.cookie, split=';'),
                },
                timeout=3,
                verify=False).json() if not self.team_id else {}
            if ret.get("resultCode") == 0:
                self.teams = list(map(lambda x: x["teamId"], ret["teams"]))
                self.info.team_id = self.team_id = self.teams[0]
                self.info.teams = json_str(self.teams)
                self.info.save()
            else:
                # 重新登录
                self.session = requests.session()
                self.session.headers["User-Agent"] = "Spaceship 2.117.1"

                rsp = self.session.get(
                    "https://olympus.itunes.apple.com/v1/app/config?hostname=itunesconnect.apple.com"
                ).json()
                self.session.headers["X-Apple-Widget-Key"] = rsp[
                    "authServiceKey"]
                # self.session.headers["X-Apple-Widget-Key"] = "16452abf721961a1728885bef033f28e"
                self.session.headers["Accept"] = "application/json"
                rsp = self.session.post(
                    "https://idmsa.apple.com/appleauth/auth/signin",
                    json={
                        "accountName": self.account,
                        "password": self.password,
                        "rememberMe": True,
                    },
                    timeout=3)
                self.session.headers["x-apple-id-session-id"] = rsp.headers[
                    "x-apple-id-session-id"]
                self.session.headers["scnt"] = rsp.headers["scnt"]
                if rsp.status_code == 409:
                    # 二次验证
                    # noinspection PyUnusedLocal
                    rsp = self.session.post(
                        "https://idmsa.apple.com/appleauth/auth")
                    # Log("===> https://idmsa.apple.com/appleauth/auth [%s] %s" % (rsp.status_code, rsp.json()))

                    # 切手机验证码
                    rsp = self.session.put(
                        "https://idmsa.apple.com/appleauth/auth/verify/phone",
                        json={
                            "phoneNumber": {
                                "id": 1
                            },
                            "mode": "sms",
                        })
                    Assert(rsp.status_code == 200, "[%s]短信发送失败" % self.account)
                    # Log("===> https://idmsa.apple.com/appleauth/auth/verify/phone [%s] %s" % (rsp.status_code, rsp.json()))
                    _wait_code(self.info, self.session, now())

                self.cookie.update(self.session.cookies)
                self.__expire = now() + 3600 * 1000
        if not self.team_id:
            ret = requests.post(
                "https://developer.apple.com/services-account/QH65B2/account/getTeams",
                json={
                    "includeInMigrationTeams": 1,
                },
                headers={
                    'cookie': to_form_url(self.cookie, split=';'),
                },
                timeout=3,
                verify=False).json()
            if ret["resultCode"] == 0:
                self.teams = list(map(lambda x: x["teamId"], ret["teams"]))
                self.info.team_id = self.team_id = self.teams[0]
                self.info.teams = json_str(self.teams)
                self.info.save()
            else:
                Log("[%s]获取team失败登出了" % self.account)
                self.__logout()
        Log("apple账号[%s:%s]登录完成了" % (self.account, self.team_id))
예제 #18
0
파일: views.py 프로젝트: doubleC2/ios_ci
def login_by_curl(_req: HttpRequest, cmd: str = "", account: str = ""):
    """
    通过拦截网页的curl 请求
    https://developer.apple.com/account/getUserProfile
    ex.
    curl 'https://developer.apple.com/services-account/QH65B2/account/getUserProfile' -H 'origin: https://developer.apple.com' -H 'accept-encoding: gzip, deflate, br' -H 'accept-language: zh-CN,zh;q=0.9' -H 'csrf: cf0796aee015fe0f03e7ccc656ba4b898b696cc1072027988d89b1f6e607fd67' -H 'cookie: geo=SG; ccl=SR+vWVA/vYTrzR1LkZE2tw==; s_fid=56EE3E795513A2B4-16F81B5466B36881; s_cc=true; s_vi=[CS]v1|2E425B0B852E2C90-40002C5160000006[CE]; dslang=CN-ZH; site=CHN; s_pathLength=developer%3D2%2C; acn01=v+zxzKnMyleYWzjWuNuW1Y9+kAJBxfozY2UAH0paNQB+FA==; myacinfo=DAWTKNV2a5c238e8d27e8ed221c8978cfb02ea94b22777f25ffec5abb1a855da8debe4f59d60b506eae457dec4670d5ca9663ed72c3d1976a9f87c53653fae7c63699abe64991180d7c107c50ce88be233047fc96de200c3f23947bfbf2e064c7b9a7652002d285127345fe15adf53bab3d347704cbc0a8b856338680722e5d0387a5eb763d258cf19b79318be28c4abd01e27029d2ef26a1bd0dff61d141380a1b496b92825575735d0be3dd02a934db2d788c9d6532b6a36bc69d244cc9b4873cef8f4a3a90695f172f6f521330f67f20791fd7d62dfc9d6de43899ec26a8485191d62e2c5139f81fca2388d57374ff31f9f689ad373508bcd74975ddd3d3b7875fe3235323962636433633833653433363562313034383164333833643736393763303538353038396439MVRYV2; DSESSIONID=1c3smahkpfbkp7k3fju30279uoba8p8480gs5ajjgsbbvn8lubqt; s_sq=%5B%5BB%5D%5D' -H 'user-locale: en_US' -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 Safari/537.36 QQBrowser/4.5.122.400' -H 'content-type: application/json' -H 'accept: application/json' -H 'cache-control: max-age=0, no-cache, no-store, must-revalidate, proxy-revalidate' -H 'authority: developer.apple.com' -H 'referer: https://developer.apple.com/account/' -H 'csrf_ts: 1552204197631' --data-binary '{}' --compressed
    """

    if not cmd:
        cmd = _req.body.decode("utf-8")
    Assert(len(cmd) and cmd.startswith("curl"), "命令行不对")
    parsed_context = curl_parse_context(cmd)
    params = {
        "data":
        parsed_context.data,
        "headers":
        dict(
            filter(lambda x: not x[0].startswith(":"),
                   parsed_context.headers.items())),
        "cookies":
        parsed_context.cookies,
    }
    if parsed_context.method == 'get':
        rsp = requests.get(
            parsed_context.url,
            **params,
        )
    else:
        rsp = requests.post(
            parsed_context.url,
            **params,
        )
    if rsp.status_code != 200:
        return {
            "succ": False,
            "reason": "无效的curl",
        }
    if parsed_context.url != "https://developer.apple.com/services-account/QH65B2/account/getUserProfile":
        data = rsp.json()
        account = data["userProfile"]["email"]
    else:
        rsp = requests.post(
            "https://developer.apple.com/services-account/QH65B2/account/getUserProfile",
            headers={
                "cookie": parsed_context.cookies,
            })
        data = rsp.json()
        account = data["userProfile"]["email"]

    if account:
        _info = IosAccountInfo.objects.filter(
            account=account).first()  # type:IosAccountInfo
        if not _info:
            _info = IosAccountInfo()
            _info.account = account
            _info.save()
        _info.cookie = json_str(parsed_context.cookies)
        _info.headers = json_str(parsed_context.headers)
        _info.save()
        Log("通过curl登录[%s]" % account)
        return {
            "succ": True,
            "msg": "登录[%s]成功" % account,
        }
    else:
        return {
            "succ": False,
            "msg": "请求不具备提取登录信息",
        }
예제 #19
0
 def wrapper(self, request, *args, **kwargs):
     return HttpResponse(json_str(self.func(request)))